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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 93F44C43334 for ; Sat, 23 Jul 2022 17:27:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237803AbiGWR1W (ORCPT ); Sat, 23 Jul 2022 13:27:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40058 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230005AbiGWR1U (ORCPT ); Sat, 23 Jul 2022 13:27:20 -0400 Received: from out28-170.mail.aliyun.com (out28-170.mail.aliyun.com [115.124.28.170]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9721218E24; Sat, 23 Jul 2022 10:27:15 -0700 (PDT) X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436282|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.0670894-0.000820908-0.93209;FP=0|0|0|0|0|-1|-1|-1;HT=ay29a033018047194;MF=zhouyanjie@wanyeetech.com;NM=1;PH=DS;RN=23;RT=23;SR=0;TI=SMTPD_---.ObmF7.P_1658597216; Received: from 192.168.10.152(mailfrom:zhouyanjie@wanyeetech.com fp:SMTPD_---.ObmF7.P_1658597216) by smtp.aliyun-inc.com; Sun, 24 Jul 2022 01:26:58 +0800 Subject: Re: [PATCH 3/3] SPI: Ingenic: Add SFC support for Ingenic SoCs. To: Paul Cercueil Cc: tudor.ambarus@microchip.com, p.yadav@ti.com, michael@walle.cc, miquel.raynal@bootlin.com, richard@nod.at, vigneshr@ti.com, broonie@kernel.org, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, linux-mtd@lists.infradead.org, linux-spi@vger.kernel.org, linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, aidanmacdonald.0x0@gmail.com, tmn505@gmail.com, dongsheng.qiu@ingenic.com, aric.pzqi@ingenic.com, rick.tyliu@ingenic.com, jinghui.liu@ingenic.com, sernia.zhou@foxmail.com, reimu@sudomaker.com References: <1658508510-15400-1-git-send-email-zhouyanjie@wanyeetech.com> <1658508510-15400-4-git-send-email-zhouyanjie@wanyeetech.com> From: Zhou Yanjie Message-ID: Date: Sun, 24 Jul 2022 01:26:56 +0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Paul, On 2022/7/23 上午4:03, Paul Cercueil wrote: > Hi Zhou, > > > Le sam., juil. 23 2022 at 00:48:30 +0800, 周琰杰 (Zhou Yanjie) > a écrit : >> Add SFC support for the X1000 SoC, the X1600 SoC, and the X2000 SoC >> from Ingenic. >> >> Signed-off-by: 周琰杰 (Zhou Yanjie) >> --- >>  drivers/spi/Kconfig           |   9 + >>  drivers/spi/Makefile          |   1 + >>  drivers/spi/spi-ingenic-sfc.c | 662 >> ++++++++++++++++++++++++++++++++++++++++++ >>  3 files changed, 672 insertions(+) >>  create mode 100644 drivers/spi/spi-ingenic-sfc.c >> >> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig >> index 3b1044e..1077bd3 100644 >> --- a/drivers/spi/Kconfig >> +++ b/drivers/spi/Kconfig >> @@ -437,6 +437,15 @@ config SPI_INGENIC >>        To compile this driver as a module, choose M here: the module >>        will be called spi-ingenic. >> >> +config SPI_INGENIC_SFC >> +    tristate "Ingenic SoCs SPI Flash Controller" >> +    depends on MACH_INGENIC || COMPILE_TEST >> +    help >> +      This enables support for the Ingenic SoCs SPI flash controller. >> + >> +      To compile this driver as a module, choose M here: the module >> +      will be called ingenic-sfc. >> + >>  config SPI_INTEL >>      tristate >> >> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile >> index 0f44eb6..f3e42c0 100644 >> --- a/drivers/spi/Makefile >> +++ b/drivers/spi/Makefile >> @@ -62,6 +62,7 @@ obj-$(CONFIG_SPI_HISI_SFC_V3XX)        += >> spi-hisi-sfc-v3xx.o >>  obj-$(CONFIG_SPI_IMG_SPFI)        += spi-img-spfi.o >>  obj-$(CONFIG_SPI_IMX)            += spi-imx.o >>  obj-$(CONFIG_SPI_INGENIC)        += spi-ingenic.o >> +obj-$(CONFIG_SPI_INGENIC_SFC)    += spi-ingenic-sfc.o >>  obj-$(CONFIG_SPI_INTEL)            += spi-intel.o >>  obj-$(CONFIG_SPI_INTEL_PCI)        += spi-intel-pci.o >>  obj-$(CONFIG_SPI_INTEL_PLATFORM)    += spi-intel-platform.o >> diff --git a/drivers/spi/spi-ingenic-sfc.c >> b/drivers/spi/spi-ingenic-sfc.c >> new file mode 100644 >> index 00000000..a565546 >> --- /dev/null >> +++ b/drivers/spi/spi-ingenic-sfc.c >> @@ -0,0 +1,662 @@ >> +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > > Dual-license driver? That's not what MODULE_LICENSE() says. > My fault, forgot to modify MODULE_LICENSE(), will fix it in the next version. >> +/* >> + * Ingenic SoCs SPI Flash Controller Driver >> + * Copyright (c) 2022 周琰杰 (Zhou Yanjie) >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +/* SFC register offsets */ >> +#define SFC_REG_GLB                        0x0000 >> +#define SFC_REG_DEV_CONF                0x0004 >> +#define SFC_REG_DEV_STA_EXP                0x0008 >> +#define SFC_REG_DEV_STA_RT                0x000c >> +#define SFC_REG_DEV_STA_MSK                0x0010 >> +#define SFC_REG_TRAN_CONF(n)            (0x0014 + n * 4) >> +#define SFC_REG_TRAN_CFG0(n)            (0x0014 + n * 4) > > You should protect the macro parameter. If you do for instance > SFC_REG_TRAN_CONF(x + 1) it would resolve to (0x0014 + x + 1 * 4) > which is not what you'd want. > Sure, will fix it. > Also - looks like SFC_REG_TRAN_CONF() and SFC_REG_TRAN_CFG0() are the > same thing, that's on purpose? > >> +#define SFC_REG_TRAN_LEN 0x002c >> +#define SFC_REG_DEV_ADDR(n)                (0x0030 + n * 4) >> +#define SFC_REG_DEV_ADDR_PLUS(n)        (0x0048 + n * 4) >> +#define SFC_REG_MEM_ADDR                0x0060 >> +#define SFC_REG_TRIG                    0x0064 >> +#define SFC_REG_SR                        0x0068 >> +#define SFC_REG_SCR                        0x006c >> +#define SFC_REG_INTC                    0x0070 >> +#define SFC_REG_FSM                        0x0074 >> +#define SFC_REG_CGE                        0x0078 >> +#define SFC_REG_TRAN_CFG1(n)            (0x009c + n * 4) >> +#define SFC_REG_DR                        0x1000 >> + >> +/* bits within the GLB register */ >> +#define GLB_TRAN_DIR_MASK                GENMASK(13, 13) >> +#define GLB_TRAN_DIR_WRITE                0x1 >> +#define GLB_TRAN_DIR_READ                0x0 > > When it's a single bit - just use BIT(). Sure. > >> +#define GLB_THRESHOLD_MASK GENMASK(12, 7) >> +#define GLB_OP_MODE_MASK                GENMASK(6, 6) > > Same here, and I see it a few times below as well. > Sure. >> +#define GLB_OP_MODE_DMA                    0x1 >> +#define GLB_OP_MODE_SLAVE                0x0 >> +#define GLB_PHASE_NUM_MASK                GENMASK(5, 3) >> +#define GLB_WP_EN                        BIT(2) >> +#define GLB_BURST_MD_MASK                GENMASK(1, 0) >> +#define GLB_BURST_MD_INCR32                0x3 >> +#define GLB_BURST_MD_INCR16                0x2 >> +#define GLB_BURST_MD_INCR8                0x1 >> +#define GLB_BURST_MD_INCR4                0x0 >> + >> +/* bits within the DEV_CONF register */ >> +#define DEV_CONF_SMP_DELAY_MASK            GENMASK(20, 16) >> +#define DEV_CONF_SMP_DELAY_180DEG        0x4 >> +#define DEV_CONF_SMP_DELAY_HALF_CYCLE    0x1 >> +#define DEV_CONF_CMD_TYPE_MASK            GENMASK(15, 15) >> +#define DEV_CONF_CMD_TYPE_16BIT            0x1 >> +#define DEV_CONF_CMD_TYPE_8BIT            0x0 >> +#define DEV_CONF_STA_TYPE_MASK            GENMASK(14, 13) >> +#define DEV_CONF_THOLD_MASK                GENMASK(12, 11) >> +#define DEV_CONF_TSETUP_MASK            GENMASK(10, 9) >> +#define DEV_CONF_TSH_MASK                GENMASK(8, 5) >> +#define DEV_CONF_CPHA                    BIT(4) >> +#define DEV_CONF_CPOL                    BIT(3) >> +#define DEV_CONF_CE_DL                    BIT(2) >> +#define DEV_CONF_HOLD_DL                BIT(1) >> +#define DEV_CONF_WP_DL                    BIT(0) >> + >> +/* bits within the TRAN_CONF(n) register */ >> +#define TRAN_CONF_TRAN_MODE_MASK        GENMASK(31, 29) >> +#define TRAN_CONF_ADDR_WIDTH_MASK        GENMASK(28, 26) >> +#define TRAN_CONF_POLL_EN                BIT(25) >> +#define TRAN_CONF_CMD_EN                BIT(24) >> +#define TRAN_CONF_PHASE_FORMAT_MASK        GENMASK(23, 23) >> +#define TRAN_CONF_DMY_BITS_MASK            GENMASK(22, 17) >> +#define TRAN_CONF_DATA_EN                BIT(16) >> +#define TRAN_CONF_CMD_MASK                GENMASK(15, 0) >> + >> +/* bits within the TRIG register */ >> +#define TRIG_FLUSH                        BIT(2) >> +#define TRIG_STOP                        BIT(1) >> +#define TRIG_START                        BIT(0) >> + >> +/* bits within the SR register */ >> +#define SR_FIFO_NUM_MASK                GENMASK(22, 16) >> +#define SR_END                            BIT(4) >> +#define SR_TRAN_REQ                        BIT(3) >> +#define SR_RECE_REQ                        BIT(2) >> +#define SR_OVER                            BIT(1) >> +#define SR_UNDER                        BIT(0) >> + >> +/* bits within the SCR register */ >> +#define SCR_CLR_END                        BIT(4) >> +#define SCR_CLR_TREQ                    BIT(3) >> +#define SCR_CLR_RREQ                    BIT(2) >> +#define SCR_CLR_OVER                    BIT(1) >> +#define SCR_CLR_UNDER                    BIT(0) >> + >> +/* bits within the INTC register */ >> +#define INTC_MASK_END                    BIT(4) >> +#define INTC_MASK_TREQ                    BIT(3) >> +#define INTC_MASK_RREQ                    BIT(2) >> +#define INTC_MASK_OVER                    BIT(1) >> +#define INTC_MASK_UNDER                    BIT(0) >> + >> +/* bits within the TRAN_CFG1(n) register */ >> +#define TRAN_CFG1_TRAN_MODE_MASK        GENMASK(7, 4) >> + >> +#define TRAN_MODE_STANDARD                0 >> +#define TRAN_MODE_DUAL_DATA                1 >> +#define TRAN_MODE_DUAL_IO                2 >> +#define TRAN_MODE_DUAL_FULL                3 >> +#define TRAN_MODE_QUAD_DATA                5 >> +#define TRAN_MODE_QUAD_IO                6 >> +#define TRAN_MODE_QUAD_FULL                7 >> +#define TRAN_MODE_OCTAL_DATA            9 >> +#define TRAN_MODE_OCTAL_IO                10 >> +#define TRAN_MODE_OCTAL_FULL            11 >> + >> +#define INGENIC_SFC_FIFO_SIZE            (64 * 4) >> + >> +#define INGENIC_SFC_TRANSFER_TIMEOUT    1000 > > Maybe add the unit name in the macro as well - > INGENIC_SFC_TRANSFER_TIMEOUT_MS. Sure. > >> + >> +enum ingenic_sfc_version { >> +    ID_X1000, >> +    ID_X1600, >> +    ID_X2000, >> +}; >> + >> +struct ingenic_soc_info { >> +    enum ingenic_sfc_version version; >> + >> +    unsigned int max_bus_width; >> + >> +    const u32 tran_mode_mask; >> +}; >> + >> +struct ingenic_sfc { >> +    const struct ingenic_soc_info *soc_info; >> + >> +    void __iomem *base; >> +    struct device *dev; >> +    struct clk *clk; >> +    int irq; >> + >> +    struct completion completion; >> +}; >> + >> +static irqreturn_t ingenic_sfc_irq_handler(int irq, void *data) >> +{ >> +    struct ingenic_sfc *sfc = data; >> + >> +    writel(0x1f, sfc->base + SFC_REG_INTC); >> + >> +    complete(&sfc->completion); >> + >> +    return IRQ_HANDLED; >> +} >> + >> +static int ingenic_sfc_adjust_op_size(struct spi_mem *mem, struct >> spi_mem_op *op) >> +{ >> +    uintptr_t addr = (uintptr_t)op->data.buf.in; >> + >> +    if (op->data.nbytes > INGENIC_SFC_FIFO_SIZE && !IS_ALIGNED(addr, >> 4)) >> +        op->data.nbytes = INGENIC_SFC_FIFO_SIZE; >> + >> +    return 0; >> +} >> + >> +static bool ingenic_sfc_supports_op(struct spi_mem *mem, const >> struct spi_mem_op *op) >> +{ >> +    struct spi_device *spi = mem->spi; >> +    struct ingenic_sfc *sfc = spi_controller_get_devdata(spi->master); >> +    uintptr_t addr = (uintptr_t)op->data.buf.in; >> + >> +    /* The controller only supports Standard SPI mode, Duall mode, >> Quad mode and Octal mode. */ > > Dual* Oops, will fix it. > >> +    if (op->cmd.buswidth > sfc->soc_info->max_bus_width || >> +        op->addr.buswidth > sfc->soc_info->max_bus_width || >> +        op->dummy.buswidth > sfc->soc_info->max_bus_width || >> +        op->data.buswidth > sfc->soc_info->max_bus_width) >> +        return false; >> + >> +    /* Max 32 dummy clock cycles supported */ >> +    if (op->dummy.nbytes && op->dummy.nbytes * 8 / >> op->dummy.buswidth > 32) >> +        return false; >> + >> +    /* Max rx data length, check controller limits and alignment */ >> +    if (op->data.dir == SPI_MEM_DATA_IN && >> +        op->data.nbytes > INGENIC_SFC_FIFO_SIZE && !IS_ALIGNED(addr, >> 4)) > > This does the same check than in ingenic_sfc_adjust_op_size(), maybe > move it to a new inline function? > Sure. >> +        return false; >> + >> +    /* Max 6 bytes address width supported */ >> +    if (op->addr.nbytes > 6) >> +        return false; >> + >> +    return spi_mem_default_supports_op(mem, op); >> +} >> + >> +static void ingenic_sfc_set_transfer_mode(struct ingenic_sfc *sfc, >> const struct spi_mem_op *op) >> +{ >> +    int val; >> + >> +    val = readl(sfc->base + (sfc->soc_info->version >= ID_X1600 ? >> +            SFC_REG_TRAN_CFG1(0) : SFC_REG_TRAN_CONF(0))); > > As Krzysztof said - ugh. > Will fix it. > Also, instead of having a "version" enum in your soc_info, why not > just have a "reg_conf" field that gives you directly the right register? > We still need a version to distinguish the SFC before X1600 SoC and the SFC after X1600 SoC, because in addition to the difference in the cfg register, another difference is that the SFC before X1600 SoC does not support address unaligned RX DMA transfer, while SFC in X1600 and later SoCs can support this feature. > >> +    val &= ~sfc->soc_info->tran_mode_mask; >> +    if (op->cmd.buswidth == 8) >> +        val |= (TRAN_MODE_OCTAL_FULL << >> (ffs(sfc->soc_info->tran_mode_mask) - 1)) & >> +                sfc->soc_info->tran_mode_mask; > > Looks like you're really trying to reinvent the wheel. > > val |= FIELD_PREP(sfc->soc_info->tran_mode_mask, TRAN_MODE_OCTAL_FULL); > > using . > > Also, just define a 'mode' variable and set it in your if/else blocks, > that would look much better. Then you can set val |= FIELD_PREP(..., > mode) at the end. Sure, will change this in the next version. > >> +    else if (op->cmd.buswidth == 4) >> +        val |= (TRAN_MODE_QUAD_FULL << >> (ffs(sfc->soc_info->tran_mode_mask) - 1)) & >> +                sfc->soc_info->tran_mode_mask; >> +    else if (op->cmd.buswidth == 2) >> +        val |= (TRAN_MODE_DUAL_FULL << >> (ffs(sfc->soc_info->tran_mode_mask) - 1)) & >> +                sfc->soc_info->tran_mode_mask; >> +    else if (op->addr.buswidth == 8) >> +        val |= (TRAN_MODE_OCTAL_IO << >> (ffs(sfc->soc_info->tran_mode_mask) - 1)) & >> +                sfc->soc_info->tran_mode_mask; >> +    else if (op->addr.buswidth == 4) >> +        val |= (TRAN_MODE_QUAD_IO << >> (ffs(sfc->soc_info->tran_mode_mask) - 1)) & >> +                sfc->soc_info->tran_mode_mask; >> +    else if (op->addr.buswidth == 2) >> +        val |= (TRAN_MODE_DUAL_IO << >> (ffs(sfc->soc_info->tran_mode_mask) - 1)) & >> +                sfc->soc_info->tran_mode_mask; >> +    else if (op->data.buswidth == 8) >> +        val |= (TRAN_MODE_OCTAL_DATA << >> (ffs(sfc->soc_info->tran_mode_mask) - 1)) & >> +                sfc->soc_info->tran_mode_mask; >> +    else if (op->data.buswidth == 4) >> +        val |= (TRAN_MODE_QUAD_DATA << >> (ffs(sfc->soc_info->tran_mode_mask) - 1)) & >> +                sfc->soc_info->tran_mode_mask; >> +    else if (op->data.buswidth == 2) >> +        val |= (TRAN_MODE_DUAL_DATA << >> (ffs(sfc->soc_info->tran_mode_mask) - 1)) & >> +                sfc->soc_info->tran_mode_mask; >> +    else >> +        val |= (TRAN_MODE_STANDARD << >> (ffs(sfc->soc_info->tran_mode_mask) - 1)) & >> +                sfc->soc_info->tran_mode_mask; >> +    writel(val, sfc->base + (sfc->soc_info->version >= ID_X1600 ? >> +            SFC_REG_TRAN_CFG1(0) : SFC_REG_TRAN_CONF(0))); >> +} >> + >> +/* >> + * We only need PIO mode to handle the SPI_MEM_NO_DATA transfers, >> + * and the unaligned accesses in SPI_MEM_DATA_IN transfers. >> + */ >> +static void ingenic_sfc_read_rxfifo(struct ingenic_sfc *sfc, u8 *to, >> unsigned int len) >> +{ >> +    void __iomem *from; >> + >> +    from = sfc->base + SFC_REG_DR; >> + >> +    for (; len >= 4; len -= 4, to += 4) { >> +        u32 val = __raw_readl(from); >> +        memcpy(to, &val, 4); > > No need to use memcpy for 4 bytes. You can do: put_unaligned(val, (u32 > *)to); > Sure. >> +    } >> + >> +    if (len) { >> +        u32 val = __raw_readl(from); >> +        memcpy(to, &val, len); > > Hmm, I'm not sure that is endian-safe. I would prefer if you copied > byte by byte. > Sure. >> +    } >> +} >> + >> +static int ingenic_sfc_exec_op_pio(struct ingenic_sfc *sfc, const >> struct spi_mem_op *op) >> +{ >> +    int ret, val; >> + >> +    val = readl(sfc->base + SFC_REG_GLB); >> +    u32p_replace_bits(&val, GLB_TRAN_DIR_READ, GLB_TRAN_DIR_MASK); >> +    u32p_replace_bits(&val, GLB_OP_MODE_SLAVE, GLB_OP_MODE_MASK); >> +    writel(val, sfc->base + SFC_REG_GLB); > > By the way, have you considered using regmap? > > It would give you things like regmap_update_bits() for this kind of > things, and regmap_field() to handle your conf register being at a > different address across SoCs. > It seems that the overhead of using regmap will be greater than using readl and writel, the purpose of using readl and writel is to minimize overhead and maximize performance. :) >> + >> +    val = TRAN_CONF_CMD_EN | op->cmd.opcode; >> + >> +    if (op->addr.nbytes > 0) { >> +        val |= FIELD_PREP(TRAN_CONF_ADDR_WIDTH_MASK, op->addr.nbytes); >> + >> +        writel(op->addr.val & 0xffffffff, sfc->base + >> SFC_REG_DEV_ADDR(0)); >> +        writel(op->addr.val >> 32, sfc->base + >> SFC_REG_DEV_ADDR_PLUS(0)); >> +    } >> + >> +    if (op->dummy.nbytes > 0) >> +        val |= FIELD_PREP(TRAN_CONF_DMY_BITS_MASK, >> +                op->dummy.nbytes * 8 / op->dummy.buswidth); >> + >> +    if (op->data.nbytes > 0) >> +        val |= TRAN_CONF_DATA_EN; >> + >> +    writel(val, sfc->base + SFC_REG_TRAN_CONF(0)); >> +    writel(op->data.nbytes, sfc->base + SFC_REG_TRAN_LEN); >> + >> +    ingenic_sfc_set_transfer_mode(sfc, op); >> + >> +    writel(0x1f, sfc->base + SFC_REG_SCR); > > Random 0x1f value here, maybe use a macro? Sure. > >> +    writel(~(INTC_MASK_END | INTC_MASK_RREQ), sfc->base + >> SFC_REG_INTC); >> + >> +    writel(0, sfc->base + SFC_REG_MEM_ADDR); >> + >> +    writel(TRIG_FLUSH, sfc->base + SFC_REG_TRIG); >> +    writel(TRIG_START, sfc->base + SFC_REG_TRIG); >> + >> +    ret = wait_for_completion_timeout(&sfc->completion, >> +            msecs_to_jiffies(INGENIC_SFC_TRANSFER_TIMEOUT)); >> +    if (!ret) { >> +        writel(0x1f, sfc->base + SFC_REG_INTC); >> +        writel(0x1f, sfc->base + SFC_REG_SCR); >> +        dev_err(sfc->dev, "line:%d Timeout for ACK from SFC >> device\n", __LINE__); >> +        return -ETIMEDOUT; >> +    } >> + >> +    ingenic_sfc_read_rxfifo(sfc, op->data.buf.in, op->data.nbytes); >> +    readl_poll_timeout(sfc->base + SFC_REG_SR, val, val & SR_END, >> 10, 0); > > Infinite timeout? Is that very wise? Will fix it in the next version. > >> + >> +    writel(INTC_MASK_END | INTC_MASK_RREQ, sfc->base + SFC_REG_SCR); >> +    writel(TRIG_STOP, sfc->base + SFC_REG_TRIG); >> + >> +    return 0; >> +} >> + >> +static int ingenic_sfc_exec_op_dma(struct ingenic_sfc *sfc, const >> struct spi_mem_op *op) >> +{ >> +    dma_addr_t addr; >> +    int ret, val; >> + >> +    val = readl(sfc->base + SFC_REG_GLB); >> +    u32p_replace_bits(&val, op->data.dir == SPI_MEM_DATA_IN ? >> +            GLB_TRAN_DIR_READ : GLB_TRAN_DIR_WRITE, GLB_TRAN_DIR_MASK); >> +    u32p_replace_bits(&val, GLB_OP_MODE_DMA, GLB_OP_MODE_MASK); >> +    writel(val, sfc->base + SFC_REG_GLB); >> + >> +    val = TRAN_CONF_CMD_EN | op->cmd.opcode; >> + >> +    if (op->addr.nbytes > 0) { >> +        val |= FIELD_PREP(TRAN_CONF_ADDR_WIDTH_MASK, op->addr.nbytes); >> +        writel(op->addr.val & 0xffffffff, sfc->base + >> SFC_REG_DEV_ADDR(0)); >> +        writel(op->addr.val >> 32, sfc->base + >> SFC_REG_DEV_ADDR_PLUS(0)); >> +    } >> + >> +    if (op->dummy.nbytes > 0) >> +        val |= FIELD_PREP(TRAN_CONF_DMY_BITS_MASK, >> +                op->dummy.nbytes * 8 / op->dummy.buswidth); >> + >> +    if (op->data.nbytes > 0) >> +        val |= TRAN_CONF_DATA_EN; > > There's a lot of code duplication here with ingenic_sfc_exec_op_pio(). > A lot can be factorized. Sure, I will try to do it. > >> + >> +    writel(val, sfc->base + SFC_REG_TRAN_CONF(0)); >> +    writel(op->data.nbytes, sfc->base + SFC_REG_TRAN_LEN); >> + >> +    ingenic_sfc_set_transfer_mode(sfc, op); >> + >> +    writel(0x1f, sfc->base + SFC_REG_SCR); >> +    writel(~INTC_MASK_END, sfc->base + SFC_REG_INTC); >> + >> +    switch (op->data.dir) { >> +    case SPI_MEM_DATA_IN: >> +        addr = dma_map_single(sfc->dev, op->data.buf.in, >> op->data.nbytes, DMA_FROM_DEVICE); >> +        if (dma_mapping_error(sfc->dev, addr)) { >> +            dev_err(sfc->dev, "RX DMA memory not mapped\n"); >> +            return -ENOMEM; >> +        } >> + >> +        writel(addr, sfc->base + SFC_REG_MEM_ADDR); >> +        break; >> + >> +    case SPI_MEM_DATA_OUT: >> +        addr = dma_map_single(sfc->dev, (void *)op->data.buf.out, >> +                op->data.nbytes, DMA_TO_DEVICE); >> +        if (dma_mapping_error(sfc->dev, addr)) { >> +            dev_err(sfc->dev, "TX DMA memory not mapped\n"); >> +            return -ENOMEM; >> +        } >> + >> +        writel(addr, sfc->base + SFC_REG_MEM_ADDR); >> +        break; >> + >> +    default: >> +        return -EINVAL; >> +    } >> + >> +    writel(TRIG_START, sfc->base + SFC_REG_TRIG); >> + >> +    ret = wait_for_completion_timeout(&sfc->completion, >> +            msecs_to_jiffies(INGENIC_SFC_TRANSFER_TIMEOUT)); >> +    if (!ret) { >> +        writel(0x1f, sfc->base + SFC_REG_INTC); >> +        writel(0x1f, sfc->base + SFC_REG_SCR); >> +        dev_err(sfc->dev, "line:%d Timeout for ACK from SFC >> device\n", __LINE__); >> +        return -ETIMEDOUT; >> +    } >> + >> +    dma_unmap_single(sfc->dev, addr, op->data.nbytes, >> +            op->data.dir == SPI_MEM_DATA_IN ? DMA_FROM_DEVICE : >> DMA_TO_DEVICE); > > Use a small inline function for that too. My personal rule is that ?: > is fine if the line fits in 80 characters, but if you have to break, > then you really need to move it somewhere else. > Sure. >> + >> +    writel(INTC_MASK_END, sfc->base + SFC_REG_SCR); >> +    writel(TRIG_STOP, sfc->base + SFC_REG_TRIG); >> + >> +    return 0; >> +} >> + >> +static int ingenic_sfc_exec_op(struct spi_mem *mem, const struct >> spi_mem_op *op) >> +{ >> +    struct spi_device *spi = mem->spi; >> +    struct ingenic_sfc *sfc = spi_controller_get_devdata(spi->master); >> +    uintptr_t addr = (uintptr_t)op->data.buf.in; >> + >> +    init_completion(&sfc->completion); >> + >> +    switch (op->data.dir) { >> +    case SPI_MEM_DATA_IN: >> +        if (sfc->soc_info->version >= ID_X1600 || IS_ALIGNED(addr, 4)) >> +            break; >> + >> +        fallthrough; >> + >> +    case SPI_MEM_NO_DATA: >> +        return ingenic_sfc_exec_op_pio(sfc, op); >> + >> +    default: >> +        break; >> +    } >> + >> +    return ingenic_sfc_exec_op_dma(sfc, op); >> +} >> + >> +static int ingenic_sfc_poll_status(struct spi_mem *mem, const struct >> spi_mem_op *op, >> +            u16 mask, u16 match, unsigned long initial_delay_us, >> +            unsigned long polling_delay_us, unsigned long timeout_ms) >> +{ >> +    struct spi_device *spi = mem->spi; >> +    struct ingenic_sfc *sfc = spi_controller_get_devdata(spi->master); >> +    int ret, val; >> + >> +    init_completion(&sfc->completion); >> + >> +    val = readl(sfc->base + SFC_REG_GLB); >> +    u32p_replace_bits(&val, GLB_TRAN_DIR_READ, GLB_TRAN_DIR_MASK); >> +    u32p_replace_bits(&val, GLB_OP_MODE_SLAVE, GLB_OP_MODE_MASK); >> +    writel(val, sfc->base + SFC_REG_GLB); >> + >> +    writel(match, sfc->base + SFC_REG_DEV_STA_EXP); >> +    writel(mask, sfc->base + SFC_REG_DEV_STA_MSK); >> + >> +    val = TRAN_CONF_POLL_EN | TRAN_CONF_CMD_EN | op->cmd.opcode; >> + >> +    if (op->addr.nbytes > 0) { >> +        val |= FIELD_PREP(TRAN_CONF_ADDR_WIDTH_MASK, op->addr.nbytes); >> + >> +        writel(op->addr.val & 0xffffffff, sfc->base + >> SFC_REG_DEV_ADDR(0)); >> +        writel(op->addr.val >> 32, sfc->base + >> SFC_REG_DEV_ADDR_PLUS(0)); >> +    } >> + >> +    if (op->dummy.nbytes > 0) >> +        val |= FIELD_PREP(TRAN_CONF_DMY_BITS_MASK, >> +                op->dummy.nbytes * 8 / op->dummy.buswidth); >> + >> +    if (op->data.nbytes > 0) >> +        val |= TRAN_CONF_DATA_EN; >> + >> +    writel(val, sfc->base + SFC_REG_TRAN_CONF(0)); >> +    writel(op->data.nbytes, sfc->base + SFC_REG_TRAN_LEN); >> + >> +    ingenic_sfc_set_transfer_mode(sfc, op); >> + >> +    writel(0x1f, sfc->base + SFC_REG_SCR); >> +    writel(~INTC_MASK_END, sfc->base + SFC_REG_INTC); >> + >> +    writel(0, sfc->base + SFC_REG_MEM_ADDR); >> + >> +    writel(TRIG_START, sfc->base + SFC_REG_TRIG); >> + >> +    ret = wait_for_completion_timeout(&sfc->completion, >> +            msecs_to_jiffies(INGENIC_SFC_TRANSFER_TIMEOUT)); >> +    if (!ret) { >> +        writel(0x1f, sfc->base + SFC_REG_INTC); >> +        writel(0x1f, sfc->base + SFC_REG_SCR); >> +        dev_err(sfc->dev, "line:%d Timeout for ACK from SFC >> device\n", __LINE__); >> +        return -ETIMEDOUT; >> +    } >> + >> +    writel(SCR_CLR_END, sfc->base + SFC_REG_SCR); >> +    writel(TRIG_STOP, sfc->base + SFC_REG_TRIG); >> + >> +    return 0; >> +} >> + >> +static const struct spi_controller_mem_ops ingenic_sfc_mem_ops = { >> +    .adjust_op_size = ingenic_sfc_adjust_op_size, >> +    .supports_op = ingenic_sfc_supports_op, >> +    .exec_op = ingenic_sfc_exec_op, >> +    .poll_status = ingenic_sfc_poll_status, >> +}; >> + >> +static int ingenic_sfc_setup(struct spi_device *spi) >> +{ >> +    struct ingenic_sfc *sfc = spi_controller_get_devdata(spi->master); >> +    unsigned long rate; >> +    int ret, val; >> + >> +    if (!spi->max_speed_hz) >> +        return -EINVAL; > > Maybe set a sane default? Sure. > >> + >> +    ret = clk_set_rate(sfc->clk, spi->max_speed_hz * 2); >> +    if (ret) >> +        return -EINVAL; >> + >> +    writel(TRIG_STOP, sfc->base + SFC_REG_TRIG); >> +    writel(0, sfc->base + SFC_REG_DEV_CONF); >> +    writel(0, sfc->base + SFC_REG_CGE); >> + >> +    val = readl(sfc->base + SFC_REG_GLB); >> +    u32p_replace_bits(&val, 64 - 1, GLB_THRESHOLD_MASK); >> +    writel(val, sfc->base + SFC_REG_GLB); >> + >> +    val = readl(sfc->base + SFC_REG_DEV_CONF); >> + >> +    /* cpha bit:0 , cpol bit:0 */ >> +    val &= ~(DEV_CONF_CPHA | DEV_CONF_CPOL); >> +    val |= spi->mode & SPI_CPHA ? DEV_CONF_CPHA : 0; >> +    val |= spi->mode & SPI_CPOL ? DEV_CONF_CPOL : 0; >> + >> +    /* ce_dl bit:1, hold bit:1, wp bit:1 */ >> +    val |= (DEV_CONF_CE_DL | DEV_CONF_HOLD_DL | DEV_CONF_WP_DL); >> + >> +    writel(val, sfc->base + SFC_REG_DEV_CONF); >> + >> +    val = readl(sfc->base + SFC_REG_GLB); >> +    u32p_replace_bits(&val, GLB_OP_MODE_SLAVE, GLB_OP_MODE_MASK); >> +    writel(val, sfc->base + SFC_REG_GLB); >> + >> +    rate = clk_get_rate(sfc->clk); > > I'd suggest using clk_round_rate() before clk_set_rate() because then > you know what frequency it's going to be, and you don't have to call > clk_get_rate() afterwards. > Sure, will try. Thanks and best regards! > Cheers, > -Paul > >> +    val = readl(sfc->base + SFC_REG_DEV_CONF); >> +    if (sfc->soc_info->version >= ID_X1600 && rate >= 200000000) >> +        u32p_replace_bits(&val, DEV_CONF_SMP_DELAY_180DEG, >> DEV_CONF_SMP_DELAY_MASK); >> +    else if (sfc->soc_info->version == ID_X1000 && rate >= 100000000) >> +        u32p_replace_bits(&val, DEV_CONF_SMP_DELAY_HALF_CYCLE, >> DEV_CONF_SMP_DELAY_MASK); >> +    writel(val, sfc->base + SFC_REG_DEV_CONF); >> + >> +    return 0; >> +} >> + >> +static int ingenic_sfc_probe(struct platform_device *pdev) >> +{ >> +    struct ingenic_sfc *sfc; >> +    struct spi_controller *ctlr; >> +    int ret; >> + >> +    ctlr = spi_alloc_master(&pdev->dev, sizeof(*sfc)); >> +    if (!ctlr) >> +        return -ENOMEM; >> + >> +    sfc = spi_controller_get_devdata(ctlr); >> + >> +    sfc->soc_info = of_device_get_match_data(&pdev->dev); >> +    if (!sfc->soc_info) { >> +        dev_err(&pdev->dev, "No of match data provided\n"); >> +        ret = -ENODEV; >> +        goto err_put_master; >> +    } >> + >> +    sfc->base = devm_platform_ioremap_resource(pdev, 0); >> +    if (IS_ERR(sfc->base)) { >> +        ret = PTR_ERR(sfc->base); >> +        goto err_put_master; >> +    } >> + >> +    sfc->clk = devm_clk_get(&pdev->dev, "sfc"); >> +    if (IS_ERR(sfc->clk)) { >> +        ret = IS_ERR(sfc->clk); >> +        goto err_put_master; >> +    } >> + >> +    ret = clk_prepare_enable(sfc->clk); >> +    if (ret) >> +        goto err_put_master; >> + >> +    sfc->irq = platform_get_irq(pdev, 0); >> +    if (sfc->irq < 0) { >> +        ret = sfc->irq; >> +        goto err_put_master; >> +    } >> + >> +    sfc->dev = &pdev->dev; >> + >> +    platform_set_drvdata(pdev, sfc); >> + >> +    ret = devm_request_irq(&pdev->dev, sfc->irq, >> ingenic_sfc_irq_handler, 0, >> +            dev_name(&pdev->dev), sfc); >> +    if (ret) { >> +        dev_err(&pdev->dev, "Failed to request irq%d, ret = %d\n", >> sfc->irq, ret); >> +        goto err_put_master; >> +    } >> + >> +    ctlr->bus_num = -1; >> +    ctlr->num_chipselect = 1; >> +    ctlr->mem_ops = &ingenic_sfc_mem_ops; >> +    ctlr->dev.of_node = pdev->dev.of_node; >> +    ctlr->setup = ingenic_sfc_setup; >> +    ctlr->mode_bits = SPI_CPHA | SPI_CPOL | >> +            SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; >> +    if (sfc->soc_info->version >= ID_X2000) >> +        ctlr->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL; >> + >> +    ret = devm_spi_register_controller(&pdev->dev, ctlr); >> +    if (ret) >> +        goto err_put_master; >> + >> +    return 0; >> + >> +err_put_master: >> +    spi_master_put(ctlr); >> + >> +    return ret; >> +} >> + >> +static const struct ingenic_soc_info x1000_soc_info = { >> +    .version = ID_X1000, >> + >> +    .max_bus_width = 4, >> + >> +    .tran_mode_mask = TRAN_CONF_TRAN_MODE_MASK, >> +}; >> + >> +static const struct ingenic_soc_info x1600_soc_info = { >> +    .version = ID_X1600, >> + >> +    .max_bus_width = 4, >> + >> +    .tran_mode_mask = TRAN_CONF_TRAN_MODE_MASK, >> +}; >> + >> +static const struct ingenic_soc_info x2000_soc_info = { >> +    .version = ID_X2000, >> + >> +    .max_bus_width = 8, >> + >> +    .tran_mode_mask = TRAN_CFG1_TRAN_MODE_MASK, >> +}; >> + >> +static const struct of_device_id ingenic_sfc_of_matches[] = { >> +    { .compatible = "ingenic,x1000-sfc", .data = &x1000_soc_info }, >> +    { .compatible = "ingenic,x1600-sfc", .data = &x1600_soc_info }, >> +    { .compatible = "ingenic,x2000-sfc", .data = &x2000_soc_info }, >> +    { /* sentinel */ } >> +}; >> +MODULE_DEVICE_TABLE(of, ingenic_sfc_of_matches); >> + >> +static struct platform_driver ingenic_sfc_driver = { >> +    .driver = { >> +        .name = "ingenic-sfc", >> +        .of_match_table = ingenic_sfc_of_matches, >> +    }, >> +    .probe = ingenic_sfc_probe, >> +}; >> +module_platform_driver(ingenic_sfc_driver); >> + >> +MODULE_LICENSE("GPL"); >> +MODULE_AUTHOR("周琰杰 (Zhou Yanjie) "); >> +MODULE_DESCRIPTION("Ingenic SoCs SPI Flash Controller Driver"); >> -- >> 2.7.4 >> > 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 06C1CC43334 for ; Sat, 23 Jul 2022 17:27:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:Content-Type: Content-Transfer-Encoding:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date:Message-ID:From: References:Cc:To:Subject:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Hkmd2XiM+7k5OLL5hSBkoXNEPxaKYq53SJT/Fn43GCE=; b=qhBnn4GFSEp6+aOuSzI5X1Xq4D G7BgMTxB1NT7NR//FdiixX2elA5C/pUinmT2bGkMkoICUvgvpClqdBn/bD/nlSJiUwv2qZ1Awz1f1 ripCXmzz20X0+tWDjNTBzrUoYqpn3HityKivU7c5gmCuorY8ybmGe3Jq2Dpe4L9JL11E16YkZ4/4U ta6l7eDgwFbK8gfBF9F912Z0c3wvc5jOwstrN0/xiPWtFSaQf7rJaWNvcNS4EW63YMgO/QXQNk2fl 6gIv1g8J+E0dtlEYmYjRA9d80Cj0vvPzJHuxd+k/rcOfGcnjCIWTs52olUoSgcAi5uOUyZcWW/N+0 7QQ3xMSQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oFIuf-005zBI-9K; Sat, 23 Jul 2022 17:27:37 +0000 Received: from out28-173.mail.aliyun.com ([115.124.28.173]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oFIuX-005z2Z-CI for linux-mtd@lists.infradead.org; Sat, 23 Jul 2022 17:27:35 +0000 X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436282|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.0670894-0.000820908-0.93209;FP=0|0|0|0|0|-1|-1|-1;HT=ay29a033018047194;MF=zhouyanjie@wanyeetech.com;NM=1;PH=DS;RN=23;RT=23;SR=0;TI=SMTPD_---.ObmF7.P_1658597216; Received: from 192.168.10.152(mailfrom:zhouyanjie@wanyeetech.com fp:SMTPD_---.ObmF7.P_1658597216) by smtp.aliyun-inc.com; Sun, 24 Jul 2022 01:26:58 +0800 Subject: Re: [PATCH 3/3] SPI: Ingenic: Add SFC support for Ingenic SoCs. To: Paul Cercueil Cc: tudor.ambarus@microchip.com, p.yadav@ti.com, michael@walle.cc, miquel.raynal@bootlin.com, richard@nod.at, vigneshr@ti.com, broonie@kernel.org, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, linux-mtd@lists.infradead.org, linux-spi@vger.kernel.org, linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, aidanmacdonald.0x0@gmail.com, tmn505@gmail.com, dongsheng.qiu@ingenic.com, aric.pzqi@ingenic.com, rick.tyliu@ingenic.com, jinghui.liu@ingenic.com, sernia.zhou@foxmail.com, reimu@sudomaker.com References: <1658508510-15400-1-git-send-email-zhouyanjie@wanyeetech.com> <1658508510-15400-4-git-send-email-zhouyanjie@wanyeetech.com> From: Zhou Yanjie Message-ID: Date: Sun, 24 Jul 2022 01:26:56 +0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220723_102731_487593_D16F33C2 X-CRM114-Status: GOOD ( 35.01 ) X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Sender: "linux-mtd" Errors-To: linux-mtd-bounces+linux-mtd=archiver.kernel.org@lists.infradead.org SGkgUGF1bCwKCk9uIDIwMjIvNy8yMyDkuIrljYg0OjAzLCBQYXVsIENlcmN1ZWlsIHdyb3RlOgo+ IEhpIFpob3UsCj4KPgo+IExlIHNhbS4sIGp1aWwuIDIzIDIwMjIgYXQgMDA6NDg6MzAgKzA4MDAs IOWRqOeQsOadsCAoWmhvdSBZYW5qaWUpIAo+IDx6aG91eWFuamllQHdhbnllZXRlY2guY29tPiBh IMOpY3JpdCA6Cj4+IEFkZCBTRkMgc3VwcG9ydCBmb3IgdGhlIFgxMDAwIFNvQywgdGhlIFgxNjAw IFNvQywgYW5kIHRoZSBYMjAwMCBTb0MKPj4gZnJvbSBJbmdlbmljLgo+Pgo+PiBTaWduZWQtb2Zm LWJ5OiDlkajnkLDmnbAgKFpob3UgWWFuamllKSA8emhvdXlhbmppZUB3YW55ZWV0ZWNoLmNvbT4K Pj4gLS0tCj4+IMKgZHJpdmVycy9zcGkvS2NvbmZpZ8KgwqDCoMKgwqDCoMKgwqDCoMKgIHzCoMKg IDkgKwo+PiDCoGRyaXZlcnMvc3BpL01ha2VmaWxlwqDCoMKgwqDCoMKgwqDCoMKgIHzCoMKgIDEg Kwo+PiDCoGRyaXZlcnMvc3BpL3NwaS1pbmdlbmljLXNmYy5jIHwgNjYyIAo+PiArKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKPj4gwqAzIGZpbGVzIGNoYW5nZWQsIDY3 MiBpbnNlcnRpb25zKCspCj4+IMKgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvc3BpL3NwaS1p bmdlbmljLXNmYy5jCj4+Cj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3NwaS9LY29uZmlnIGIvZHJp dmVycy9zcGkvS2NvbmZpZwo+PiBpbmRleCAzYjEwNDRlLi4xMDc3YmQzIDEwMDY0NAo+PiAtLS0g YS9kcml2ZXJzL3NwaS9LY29uZmlnCj4+ICsrKyBiL2RyaXZlcnMvc3BpL0tjb25maWcKPj4gQEAg LTQzNyw2ICs0MzcsMTUgQEAgY29uZmlnIFNQSV9JTkdFTklDCj4+IMKgwqDCoMKgwqDCoCBUbyBj b21waWxlIHRoaXMgZHJpdmVyIGFzIGEgbW9kdWxlLCBjaG9vc2UgTSBoZXJlOiB0aGUgbW9kdWxl Cj4+IMKgwqDCoMKgwqDCoCB3aWxsIGJlIGNhbGxlZCBzcGktaW5nZW5pYy4KPj4KPj4gK2NvbmZp ZyBTUElfSU5HRU5JQ19TRkMKPj4gK8KgwqDCoCB0cmlzdGF0ZSAiSW5nZW5pYyBTb0NzIFNQSSBG bGFzaCBDb250cm9sbGVyIgo+PiArwqDCoMKgIGRlcGVuZHMgb24gTUFDSF9JTkdFTklDIHx8IENP TVBJTEVfVEVTVAo+PiArwqDCoMKgIGhlbHAKPj4gK8KgwqDCoMKgwqAgVGhpcyBlbmFibGVzIHN1 cHBvcnQgZm9yIHRoZSBJbmdlbmljIFNvQ3MgU1BJIGZsYXNoIGNvbnRyb2xsZXIuCj4+ICsKPj4g K8KgwqDCoMKgwqAgVG8gY29tcGlsZSB0aGlzIGRyaXZlciBhcyBhIG1vZHVsZSwgY2hvb3NlIE0g aGVyZTogdGhlIG1vZHVsZQo+PiArwqDCoMKgwqDCoCB3aWxsIGJlIGNhbGxlZCBpbmdlbmljLXNm Yy4KPj4gKwo+PiDCoGNvbmZpZyBTUElfSU5URUwKPj4gwqDCoMKgwqAgdHJpc3RhdGUKPj4KPj4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvc3BpL01ha2VmaWxlIGIvZHJpdmVycy9zcGkvTWFrZWZpbGUK Pj4gaW5kZXggMGY0NGViNi4uZjNlNDJjMCAxMDA2NDQKPj4gLS0tIGEvZHJpdmVycy9zcGkvTWFr ZWZpbGUKPj4gKysrIGIvZHJpdmVycy9zcGkvTWFrZWZpbGUKPj4gQEAgLTYyLDYgKzYyLDcgQEAg b2JqLSQoQ09ORklHX1NQSV9ISVNJX1NGQ19WM1hYKcKgwqDCoMKgwqDCoMKgICs9IAo+PiBzcGkt aGlzaS1zZmMtdjN4eC5vCj4+IMKgb2JqLSQoQ09ORklHX1NQSV9JTUdfU1BGSSnCoMKgwqDCoMKg wqDCoCArPSBzcGktaW1nLXNwZmkubwo+PiDCoG9iai0kKENPTkZJR19TUElfSU1YKcKgwqDCoMKg wqDCoMKgwqDCoMKgwqAgKz0gc3BpLWlteC5vCj4+IMKgb2JqLSQoQ09ORklHX1NQSV9JTkdFTklD KcKgwqDCoMKgwqDCoMKgICs9IHNwaS1pbmdlbmljLm8KPj4gK29iai0kKENPTkZJR19TUElfSU5H RU5JQ19TRkMpwqDCoMKgICs9IHNwaS1pbmdlbmljLXNmYy5vCj4+IMKgb2JqLSQoQ09ORklHX1NQ SV9JTlRFTCnCoMKgwqDCoMKgwqDCoMKgwqDCoMKgICs9IHNwaS1pbnRlbC5vCj4+IMKgb2JqLSQo Q09ORklHX1NQSV9JTlRFTF9QQ0kpwqDCoMKgwqDCoMKgwqAgKz0gc3BpLWludGVsLXBjaS5vCj4+ IMKgb2JqLSQoQ09ORklHX1NQSV9JTlRFTF9QTEFURk9STSnCoMKgwqAgKz0gc3BpLWludGVsLXBs YXRmb3JtLm8KPj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvc3BpL3NwaS1pbmdlbmljLXNmYy5jIAo+ PiBiL2RyaXZlcnMvc3BpL3NwaS1pbmdlbmljLXNmYy5jCj4+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0 Cj4+IGluZGV4IDAwMDAwMDAwLi5hNTY1NTQ2Cj4+IC0tLSAvZGV2L251bGwKPj4gKysrIGIvZHJp dmVycy9zcGkvc3BpLWluZ2VuaWMtc2ZjLmMKPj4gQEAgLTAsMCArMSw2NjIgQEAKPj4gKy8vIFNQ RFgtTGljZW5zZS1JZGVudGlmaWVyOiAoR1BMLTIuMC1vbmx5IE9SIEJTRC0yLUNsYXVzZSkKPgo+ IER1YWwtbGljZW5zZSBkcml2ZXI/IFRoYXQncyBub3Qgd2hhdCBNT0RVTEVfTElDRU5TRSgpIHNh eXMuCj4KCk15IGZhdWx0LCBmb3Jnb3QgdG8gbW9kaWZ5IE1PRFVMRV9MSUNFTlNFKCksIHdpbGwg Zml4IGl0IGluIHRoZSBuZXh0IAp2ZXJzaW9uLgoKCj4+ICsvKgo+PiArICogSW5nZW5pYyBTb0Nz IFNQSSBGbGFzaCBDb250cm9sbGVyIERyaXZlcgo+PiArICogQ29weXJpZ2h0IChjKSAyMDIyIOWR qOeQsOadsCAoWmhvdSBZYW5qaWUpIDx6aG91eWFuamllQHdhbnllZXRlY2guY29tPgo+PiArICov Cj4+ICsKPj4gKyNpbmNsdWRlIDxsaW51eC9iaXRmaWVsZC5oPgo+PiArI2luY2x1ZGUgPGxpbnV4 L2JpdG9wcy5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2Nsay5oPgo+PiArI2luY2x1ZGUgPGxpbnV4 L2NvbXBsZXRpb24uaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9kbWEtbWFwcGluZy5oPgo+PiArI2lu Y2x1ZGUgPGxpbnV4L2ludGVycnVwdC5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2lvcG9sbC5oPgo+ PiArI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L210ZC9tdGQu aD4KPj4gKyNpbmNsdWRlIDxsaW51eC9vZl9kZXZpY2UuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9w bGF0Zm9ybV9kZXZpY2UuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4+ICsjaW5jbHVk ZSA8bGludXgvc3BpL3NwaS5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L3NwaS9zcGktbWVtLmg+Cj4+ ICsKPj4gKy8qIFNGQyByZWdpc3RlciBvZmZzZXRzICovCj4+ICsjZGVmaW5lIFNGQ19SRUdfR0xC wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAweDAwMDAKPj4g KyNkZWZpbmUgU0ZDX1JFR19ERVZfQ09ORsKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAw eDAwMDQKPj4gKyNkZWZpbmUgU0ZDX1JFR19ERVZfU1RBX0VYUMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoCAweDAwMDgKPj4gKyNkZWZpbmUgU0ZDX1JFR19ERVZfU1RBX1JUwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgIDB4MDAwYwo+PiArI2RlZmluZSBTRkNfUkVHX0RFVl9TVEFf TVNLwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIDB4MDAxMAo+PiArI2RlZmluZSBTRkNf UkVHX1RSQU5fQ09ORihuKcKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgKDB4MDAxNCArIG4gKiA0KQo+ PiArI2RlZmluZSBTRkNfUkVHX1RSQU5fQ0ZHMChuKcKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgKDB4 MDAxNCArIG4gKiA0KQo+Cj4gWW91IHNob3VsZCBwcm90ZWN0IHRoZSBtYWNybyBwYXJhbWV0ZXIu IElmIHlvdSBkbyBmb3IgaW5zdGFuY2UgCj4gU0ZDX1JFR19UUkFOX0NPTkYoeCArIDEpIGl0IHdv dWxkIHJlc29sdmUgdG8gKDB4MDAxNCArIHggKyAxICogNCkgCj4gd2hpY2ggaXMgbm90IHdoYXQg eW91J2Qgd2FudC4KPgoKU3VyZSwgd2lsbCBmaXggaXQuCgoKPiBBbHNvIC0gbG9va3MgbGlrZSBT RkNfUkVHX1RSQU5fQ09ORigpIGFuZCBTRkNfUkVHX1RSQU5fQ0ZHMCgpIGFyZSB0aGUgCj4gc2Ft ZSB0aGluZywgdGhhdCdzIG9uIHB1cnBvc2U/Cj4KPj4gKyNkZWZpbmUgU0ZDX1JFR19UUkFOX0xF TiAweDAwMmMKPj4gKyNkZWZpbmUgU0ZDX1JFR19ERVZfQUREUihuKcKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoCAoMHgwMDMwICsgbiAqIDQpCj4+ICsjZGVmaW5lIFNGQ19SRUdfREVWX0FE RFJfUExVUyhuKcKgwqDCoMKgwqDCoMKgICgweDAwNDggKyBuICogNCkKPj4gKyNkZWZpbmUgU0ZD X1JFR19NRU1fQUREUsKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAweDAwNjAKPj4gKyNk ZWZpbmUgU0ZDX1JFR19UUklHwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAg MHgwMDY0Cj4+ICsjZGVmaW5lIFNGQ19SRUdfU1LCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgIDB4MDA2OAo+PiArI2RlZmluZSBTRkNfUkVHX1NDUsKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgMHgwMDZjCj4+ICsjZGVmaW5l IFNGQ19SRUdfSU5UQ8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIDB4MDA3 MAo+PiArI2RlZmluZSBTRkNfUkVHX0ZTTcKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqAgMHgwMDc0Cj4+ICsjZGVmaW5lIFNGQ19SRUdfQ0dFwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAweDAwNzgKPj4gKyNkZWZpbmUgU0ZD X1JFR19UUkFOX0NGRzEobinCoMKgwqDCoMKgwqDCoMKgwqDCoMKgICgweDAwOWMgKyBuICogNCkK Pj4gKyNkZWZpbmUgU0ZDX1JFR19EUsKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqAgMHgxMDAwCj4+ICsKPj4gKy8qIGJpdHMgd2l0aGluIHRoZSBHTEIgcmVnaXN0 ZXIgKi8KPj4gKyNkZWZpbmUgR0xCX1RSQU5fRElSX01BU0vCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqAgR0VOTUFTSygxMywgMTMpCj4+ICsjZGVmaW5lIEdMQl9UUkFOX0RJUl9XUklURcKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAweDEKPj4gKyNkZWZpbmUgR0xCX1RSQU5fRElS X1JFQUTCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgMHgwCj4KPiBXaGVuIGl0J3MgYSBz aW5nbGUgYml0IC0ganVzdCB1c2UgQklUKCkuCgoKU3VyZS4KCgo+Cj4+ICsjZGVmaW5lIEdMQl9U SFJFU0hPTERfTUFTSyBHRU5NQVNLKDEyLCA3KQo+PiArI2RlZmluZSBHTEJfT1BfTU9ERV9NQVNL wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIEdFTk1BU0soNiwgNikKPgo+IFNhbWUgaGVy ZSwgYW5kIEkgc2VlIGl0IGEgZmV3IHRpbWVzIGJlbG93IGFzIHdlbGwuCj4KClN1cmUuCgoKPj4g KyNkZWZpbmUgR0xCX09QX01PREVfRE1BwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqAgMHgxCj4+ICsjZGVmaW5lIEdMQl9PUF9NT0RFX1NMQVZFwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgIDB4MAo+PiArI2RlZmluZSBHTEJfUEhBU0VfTlVNX01BU0vCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqAgR0VOTUFTSyg1LCAzKQo+PiArI2RlZmluZSBHTEJfV1BfRU7C oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIEJJVCgyKQo+PiAr I2RlZmluZSBHTEJfQlVSU1RfTURfTUFTS8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBH RU5NQVNLKDEsIDApCj4+ICsjZGVmaW5lIEdMQl9CVVJTVF9NRF9JTkNSMzLCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqAgMHgzCj4+ICsjZGVmaW5lIEdMQl9CVVJTVF9NRF9JTkNSMTbCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgMHgyCj4+ICsjZGVmaW5lIEdMQl9CVVJTVF9NRF9J TkNSOMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAweDEKPj4gKyNkZWZpbmUgR0xCX0JV UlNUX01EX0lOQ1I0wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIDB4MAo+PiArCj4+ICsv KiBiaXRzIHdpdGhpbiB0aGUgREVWX0NPTkYgcmVnaXN0ZXIgKi8KPj4gKyNkZWZpbmUgREVWX0NP TkZfU01QX0RFTEFZX01BU0vCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIEdFTk1BU0soMjAsIDE2KQo+ PiArI2RlZmluZSBERVZfQ09ORl9TTVBfREVMQVlfMTgwREVHwqDCoMKgwqDCoMKgwqAgMHg0Cj4+ ICsjZGVmaW5lIERFVl9DT05GX1NNUF9ERUxBWV9IQUxGX0NZQ0xFwqDCoMKgIDB4MQo+PiArI2Rl ZmluZSBERVZfQ09ORl9DTURfVFlQRV9NQVNLwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBHRU5NQVNL KDE1LCAxNSkKPj4gKyNkZWZpbmUgREVWX0NPTkZfQ01EX1RZUEVfMTZCSVTCoMKgwqDCoMKgwqDC oMKgwqDCoMKgIDB4MQo+PiArI2RlZmluZSBERVZfQ09ORl9DTURfVFlQRV84QklUwqDCoMKgwqDC oMKgwqDCoMKgwqDCoCAweDAKPj4gKyNkZWZpbmUgREVWX0NPTkZfU1RBX1RZUEVfTUFTS8KgwqDC oMKgwqDCoMKgwqDCoMKgwqAgR0VOTUFTSygxNCwgMTMpCj4+ICsjZGVmaW5lIERFVl9DT05GX1RI T0xEX01BU0vCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgR0VOTUFTSygxMiwgMTEpCj4+ ICsjZGVmaW5lIERFVl9DT05GX1RTRVRVUF9NQVNLwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBHRU5N QVNLKDEwLCA5KQo+PiArI2RlZmluZSBERVZfQ09ORl9UU0hfTUFTS8KgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoCBHRU5NQVNLKDgsIDUpCj4+ICsjZGVmaW5lIERFVl9DT05GX0NQSEHCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBCSVQoNCkKPj4gKyNkZWZpbmUgREVW X0NPTkZfQ1BPTMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIEJJVCgzKQo+ PiArI2RlZmluZSBERVZfQ09ORl9DRV9ETMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgIEJJVCgyKQo+PiArI2RlZmluZSBERVZfQ09ORl9IT0xEX0RMwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgIEJJVCgxKQo+PiArI2RlZmluZSBERVZfQ09ORl9XUF9ETMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIEJJVCgwKQo+PiArCj4+ICsvKiBiaXRzIHdp dGhpbiB0aGUgVFJBTl9DT05GKG4pIHJlZ2lzdGVyICovCj4+ICsjZGVmaW5lIFRSQU5fQ09ORl9U UkFOX01PREVfTUFTS8KgwqDCoMKgwqDCoMKgIEdFTk1BU0soMzEsIDI5KQo+PiArI2RlZmluZSBU UkFOX0NPTkZfQUREUl9XSURUSF9NQVNLwqDCoMKgwqDCoMKgwqAgR0VOTUFTSygyOCwgMjYpCj4+ ICsjZGVmaW5lIFRSQU5fQ09ORl9QT0xMX0VOwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg IEJJVCgyNSkKPj4gKyNkZWZpbmUgVFJBTl9DT05GX0NNRF9FTsKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoCBCSVQoMjQpCj4+ICsjZGVmaW5lIFRSQU5fQ09ORl9QSEFTRV9GT1JNQVRfTUFT S8KgwqDCoMKgwqDCoMKgIEdFTk1BU0soMjMsIDIzKQo+PiArI2RlZmluZSBUUkFOX0NPTkZfRE1Z X0JJVFNfTUFTS8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgR0VOTUFTSygyMiwgMTcpCj4+ICsjZGVm aW5lIFRSQU5fQ09ORl9EQVRBX0VOwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIEJJVCgx NikKPj4gKyNkZWZpbmUgVFJBTl9DT05GX0NNRF9NQVNLwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgIEdFTk1BU0soMTUsIDApCj4+ICsKPj4gKy8qIGJpdHMgd2l0aGluIHRoZSBUUklHIHJl Z2lzdGVyICovCj4+ICsjZGVmaW5lIFRSSUdfRkxVU0jCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgIEJJVCgyKQo+PiArI2RlZmluZSBUUklHX1NUT1DCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIEJJVCgxKQo+PiArI2RlZmlu ZSBUUklHX1NUQVJUwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oCBCSVQoMCkKPj4gKwo+PiArLyogYml0cyB3aXRoaW4gdGhlIFNSIHJlZ2lzdGVyICovCj4+ICsj ZGVmaW5lIFNSX0ZJRk9fTlVNX01BU0vCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgR0VO TUFTSygyMiwgMTYpCj4+ICsjZGVmaW5lIFNSX0VORMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBCSVQoNCkKPj4gKyNkZWZpbmUgU1JfVFJBTl9S RVHCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIEJJVCgzKQo+ PiArI2RlZmluZSBTUl9SRUNFX1JFUcKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqAgQklUKDIpCj4+ICsjZGVmaW5lIFNSX09WRVLCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgQklUKDEpCj4+ICsjZGVmaW5lIFNS X1VOREVSwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBCSVQo MCkKPj4gKwo+PiArLyogYml0cyB3aXRoaW4gdGhlIFNDUiByZWdpc3RlciAqLwo+PiArI2RlZmlu ZSBTQ1JfQ0xSX0VORMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqAgQklUKDQpCj4+ICsjZGVmaW5lIFNDUl9DTFJfVFJFUcKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgIEJJVCgzKQo+PiArI2RlZmluZSBTQ1JfQ0xSX1JSRVHCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBCSVQoMikKPj4gKyNkZWZpbmUgU0NSX0NMUl9P VkVSwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgQklUKDEpCj4+ICsjZGVm aW5lIFNDUl9DTFJfVU5ERVLCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBC SVQoMCkKPj4gKwo+PiArLyogYml0cyB3aXRoaW4gdGhlIElOVEMgcmVnaXN0ZXIgKi8KPj4gKyNk ZWZpbmUgSU5UQ19NQVNLX0VORMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg IEJJVCg0KQo+PiArI2RlZmluZSBJTlRDX01BU0tfVFJFUcKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgIEJJVCgzKQo+PiArI2RlZmluZSBJTlRDX01BU0tfUlJFUcKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIEJJVCgyKQo+PiArI2RlZmluZSBJTlRDX01B U0tfT1ZFUsKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIEJJVCgxKQo+PiAr I2RlZmluZSBJTlRDX01BU0tfVU5ERVLCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoCBCSVQoMCkKPj4gKwo+PiArLyogYml0cyB3aXRoaW4gdGhlIFRSQU5fQ0ZHMShuKSByZWdp c3RlciAqLwo+PiArI2RlZmluZSBUUkFOX0NGRzFfVFJBTl9NT0RFX01BU0vCoMKgwqDCoMKgwqDC oCBHRU5NQVNLKDcsIDQpCj4+ICsKPj4gKyNkZWZpbmUgVFJBTl9NT0RFX1NUQU5EQVJEwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIDAKPj4gKyNkZWZpbmUgVFJBTl9NT0RFX0RVQUxfREFU QcKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAxCj4+ICsjZGVmaW5lIFRSQU5fTU9ERV9E VUFMX0lPwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIDIKPj4gKyNkZWZpbmUgVFJBTl9N T0RFX0RVQUxfRlVMTMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAzCj4+ICsjZGVmaW5l IFRSQU5fTU9ERV9RVUFEX0RBVEHCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgNQo+PiAr I2RlZmluZSBUUkFOX01PREVfUVVBRF9JT8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCA2 Cj4+ICsjZGVmaW5lIFRSQU5fTU9ERV9RVUFEX0ZVTEzCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqAgNwo+PiArI2RlZmluZSBUUkFOX01PREVfT0NUQUxfREFUQcKgwqDCoMKgwqDCoMKgwqDC oMKgwqAgOQo+PiArI2RlZmluZSBUUkFOX01PREVfT0NUQUxfSU/CoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqAgMTAKPj4gKyNkZWZpbmUgVFJBTl9NT0RFX09DVEFMX0ZVTEzCoMKgwqDCoMKg wqDCoMKgwqDCoMKgIDExCj4+ICsKPj4gKyNkZWZpbmUgSU5HRU5JQ19TRkNfRklGT19TSVpFwqDC oMKgwqDCoMKgwqDCoMKgwqDCoCAoNjQgKiA0KQo+PiArCj4+ICsjZGVmaW5lIElOR0VOSUNfU0ZD X1RSQU5TRkVSX1RJTUVPVVTCoMKgwqAgMTAwMAo+Cj4gTWF5YmUgYWRkIHRoZSB1bml0IG5hbWUg aW4gdGhlIG1hY3JvIGFzIHdlbGwgLSAKPiBJTkdFTklDX1NGQ19UUkFOU0ZFUl9USU1FT1VUX01T LgoKClN1cmUuCgoKPgo+PiArCj4+ICtlbnVtIGluZ2VuaWNfc2ZjX3ZlcnNpb24gewo+PiArwqDC oMKgIElEX1gxMDAwLAo+PiArwqDCoMKgIElEX1gxNjAwLAo+PiArwqDCoMKgIElEX1gyMDAwLAo+ PiArfTsKPj4gKwo+PiArc3RydWN0IGluZ2VuaWNfc29jX2luZm8gewo+PiArwqDCoMKgIGVudW0g aW5nZW5pY19zZmNfdmVyc2lvbiB2ZXJzaW9uOwo+PiArCj4+ICvCoMKgwqAgdW5zaWduZWQgaW50 IG1heF9idXNfd2lkdGg7Cj4+ICsKPj4gK8KgwqDCoCBjb25zdCB1MzIgdHJhbl9tb2RlX21hc2s7 Cj4+ICt9Owo+PiArCj4+ICtzdHJ1Y3QgaW5nZW5pY19zZmMgewo+PiArwqDCoMKgIGNvbnN0IHN0 cnVjdCBpbmdlbmljX3NvY19pbmZvICpzb2NfaW5mbzsKPj4gKwo+PiArwqDCoMKgIHZvaWQgX19p b21lbSAqYmFzZTsKPj4gK8KgwqDCoCBzdHJ1Y3QgZGV2aWNlICpkZXY7Cj4+ICvCoMKgwqAgc3Ry dWN0IGNsayAqY2xrOwo+PiArwqDCoMKgIGludCBpcnE7Cj4+ICsKPj4gK8KgwqDCoCBzdHJ1Y3Qg Y29tcGxldGlvbiBjb21wbGV0aW9uOwo+PiArfTsKPj4gKwo+PiArc3RhdGljIGlycXJldHVybl90 IGluZ2VuaWNfc2ZjX2lycV9oYW5kbGVyKGludCBpcnEsIHZvaWQgKmRhdGEpCj4+ICt7Cj4+ICvC oMKgwqAgc3RydWN0IGluZ2VuaWNfc2ZjICpzZmMgPSBkYXRhOwo+PiArCj4+ICvCoMKgwqAgd3Jp dGVsKDB4MWYsIHNmYy0+YmFzZSArIFNGQ19SRUdfSU5UQyk7Cj4+ICsKPj4gK8KgwqDCoCBjb21w bGV0ZSgmc2ZjLT5jb21wbGV0aW9uKTsKPj4gKwo+PiArwqDCoMKgIHJldHVybiBJUlFfSEFORExF RDsKPj4gK30KPj4gKwo+PiArc3RhdGljIGludCBpbmdlbmljX3NmY19hZGp1c3Rfb3Bfc2l6ZShz dHJ1Y3Qgc3BpX21lbSAqbWVtLCBzdHJ1Y3QgCj4+IHNwaV9tZW1fb3AgKm9wKQo+PiArewo+PiAr wqDCoMKgIHVpbnRwdHJfdCBhZGRyID0gKHVpbnRwdHJfdClvcC0+ZGF0YS5idWYuaW47Cj4+ICsK Pj4gK8KgwqDCoCBpZiAob3AtPmRhdGEubmJ5dGVzID4gSU5HRU5JQ19TRkNfRklGT19TSVpFICYm ICFJU19BTElHTkVEKGFkZHIsIAo+PiA0KSkKPj4gK8KgwqDCoMKgwqDCoMKgIG9wLT5kYXRhLm5i eXRlcyA9IElOR0VOSUNfU0ZDX0ZJRk9fU0laRTsKPj4gKwo+PiArwqDCoMKgIHJldHVybiAwOwo+ PiArfQo+PiArCj4+ICtzdGF0aWMgYm9vbCBpbmdlbmljX3NmY19zdXBwb3J0c19vcChzdHJ1Y3Qg c3BpX21lbSAqbWVtLCBjb25zdCAKPj4gc3RydWN0IHNwaV9tZW1fb3AgKm9wKQo+PiArewo+PiAr wqDCoMKgIHN0cnVjdCBzcGlfZGV2aWNlICpzcGkgPSBtZW0tPnNwaTsKPj4gK8KgwqDCoCBzdHJ1 Y3QgaW5nZW5pY19zZmMgKnNmYyA9IHNwaV9jb250cm9sbGVyX2dldF9kZXZkYXRhKHNwaS0+bWFz dGVyKTsKPj4gK8KgwqDCoCB1aW50cHRyX3QgYWRkciA9ICh1aW50cHRyX3Qpb3AtPmRhdGEuYnVm LmluOwo+PiArCj4+ICvCoMKgwqAgLyogVGhlIGNvbnRyb2xsZXIgb25seSBzdXBwb3J0cyBTdGFu ZGFyZCBTUEkgbW9kZSwgRHVhbGwgbW9kZSwgCj4+IFF1YWQgbW9kZSBhbmQgT2N0YWwgbW9kZS4g Ki8KPgo+IER1YWwqCgoKT29wcywgd2lsbCBmaXggaXQuCgoKPgo+PiArwqDCoMKgIGlmIChvcC0+ Y21kLmJ1c3dpZHRoID4gc2ZjLT5zb2NfaW5mby0+bWF4X2J1c193aWR0aCB8fAo+PiArwqDCoMKg wqDCoMKgwqAgb3AtPmFkZHIuYnVzd2lkdGggPiBzZmMtPnNvY19pbmZvLT5tYXhfYnVzX3dpZHRo IHx8Cj4+ICvCoMKgwqDCoMKgwqDCoCBvcC0+ZHVtbXkuYnVzd2lkdGggPiBzZmMtPnNvY19pbmZv LT5tYXhfYnVzX3dpZHRoIHx8Cj4+ICvCoMKgwqDCoMKgwqDCoCBvcC0+ZGF0YS5idXN3aWR0aCA+ IHNmYy0+c29jX2luZm8tPm1heF9idXNfd2lkdGgpCj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4g ZmFsc2U7Cj4+ICsKPj4gK8KgwqDCoCAvKiBNYXggMzIgZHVtbXkgY2xvY2sgY3ljbGVzIHN1cHBv cnRlZCAqLwo+PiArwqDCoMKgIGlmIChvcC0+ZHVtbXkubmJ5dGVzICYmIG9wLT5kdW1teS5uYnl0 ZXMgKiA4IC8gCj4+IG9wLT5kdW1teS5idXN3aWR0aCA+IDMyKQo+PiArwqDCoMKgwqDCoMKgwqAg cmV0dXJuIGZhbHNlOwo+PiArCj4+ICvCoMKgwqAgLyogTWF4IHJ4IGRhdGEgbGVuZ3RoLCBjaGVj ayBjb250cm9sbGVyIGxpbWl0cyBhbmQgYWxpZ25tZW50ICovCj4+ICvCoMKgwqAgaWYgKG9wLT5k YXRhLmRpciA9PSBTUElfTUVNX0RBVEFfSU4gJiYKPj4gK8KgwqDCoMKgwqDCoMKgIG9wLT5kYXRh Lm5ieXRlcyA+IElOR0VOSUNfU0ZDX0ZJRk9fU0laRSAmJiAhSVNfQUxJR05FRChhZGRyLCAKPj4g NCkpCj4KPiBUaGlzIGRvZXMgdGhlIHNhbWUgY2hlY2sgdGhhbiBpbiBpbmdlbmljX3NmY19hZGp1 c3Rfb3Bfc2l6ZSgpLCBtYXliZSAKPiBtb3ZlIGl0IHRvIGEgbmV3IGlubGluZSBmdW5jdGlvbj8K PgoKU3VyZS4KCgo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIGZhbHNlOwo+PiArCj4+ICvCoMKg wqAgLyogTWF4IDYgYnl0ZXMgYWRkcmVzcyB3aWR0aCBzdXBwb3J0ZWQgKi8KPj4gK8KgwqDCoCBp ZiAob3AtPmFkZHIubmJ5dGVzID4gNikKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiBmYWxzZTsK Pj4gKwo+PiArwqDCoMKgIHJldHVybiBzcGlfbWVtX2RlZmF1bHRfc3VwcG9ydHNfb3AobWVtLCBv cCk7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyB2b2lkIGluZ2VuaWNfc2ZjX3NldF90cmFuc2Zlcl9t b2RlKHN0cnVjdCBpbmdlbmljX3NmYyAqc2ZjLCAKPj4gY29uc3Qgc3RydWN0IHNwaV9tZW1fb3Ag Km9wKQo+PiArewo+PiArwqDCoMKgIGludCB2YWw7Cj4+ICsKPj4gK8KgwqDCoCB2YWwgPSByZWFk bChzZmMtPmJhc2UgKyAoc2ZjLT5zb2NfaW5mby0+dmVyc2lvbiA+PSBJRF9YMTYwMCA/Cj4+ICvC oMKgwqDCoMKgwqDCoMKgwqDCoMKgIFNGQ19SRUdfVFJBTl9DRkcxKDApIDogU0ZDX1JFR19UUkFO X0NPTkYoMCkpKTsKPgo+IEFzIEtyenlzenRvZiBzYWlkIC0gdWdoLgo+CgpXaWxsIGZpeCBpdC4K Cgo+IEFsc28sIGluc3RlYWQgb2YgaGF2aW5nIGEgInZlcnNpb24iIGVudW0gaW4geW91ciBzb2Nf aW5mbywgd2h5IG5vdCAKPiBqdXN0IGhhdmUgYSAicmVnX2NvbmYiIGZpZWxkIHRoYXQgZ2l2ZXMg eW91IGRpcmVjdGx5IHRoZSByaWdodCByZWdpc3Rlcj8KPgoKV2Ugc3RpbGwgbmVlZCBhIHZlcnNp b24gdG8gZGlzdGluZ3Vpc2ggdGhlIFNGQyBiZWZvcmUgWDE2MDAgU29DIGFuZAp0aGUgU0ZDIGFm dGVyIFgxNjAwIFNvQywgYmVjYXVzZSBpbiBhZGRpdGlvbiB0byB0aGUgZGlmZmVyZW5jZSBpbiB0 aGUKY2ZnIHJlZ2lzdGVyLCBhbm90aGVyIGRpZmZlcmVuY2UgaXMgdGhhdCB0aGUgU0ZDIGJlZm9y ZSBYMTYwMCBTb0MgZG9lcwpub3Qgc3VwcG9ydCBhZGRyZXNzIHVuYWxpZ25lZCBSWCBETUEgdHJh bnNmZXIsIHdoaWxlIFNGQyBpbiBYMTYwMCBhbmQKbGF0ZXIgU29DcyBjYW4gc3VwcG9ydCB0aGlz IGZlYXR1cmUuCgoKPgo+PiArwqDCoMKgIHZhbCAmPSB+c2ZjLT5zb2NfaW5mby0+dHJhbl9tb2Rl X21hc2s7Cj4+ICvCoMKgwqAgaWYgKG9wLT5jbWQuYnVzd2lkdGggPT0gOCkKPj4gK8KgwqDCoMKg wqDCoMKgIHZhbCB8PSAoVFJBTl9NT0RFX09DVEFMX0ZVTEwgPDwgCj4+IChmZnMoc2ZjLT5zb2Nf aW5mby0+dHJhbl9tb2RlX21hc2spIC0gMSkpICYKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoCBzZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFzazsKPgo+IExvb2tzIGxpa2UgeW91 J3JlIHJlYWxseSB0cnlpbmcgdG8gcmVpbnZlbnQgdGhlIHdoZWVsLgo+Cj4gdmFsIHw9IEZJRUxE X1BSRVAoc2ZjLT5zb2NfaW5mby0+dHJhbl9tb2RlX21hc2ssIFRSQU5fTU9ERV9PQ1RBTF9GVUxM KTsKPgo+IHVzaW5nIDxsaW51eC9iaXRmaWVsZC5oPi4KPgo+IEFsc28sIGp1c3QgZGVmaW5lIGEg J21vZGUnIHZhcmlhYmxlIGFuZCBzZXQgaXQgaW4geW91ciBpZi9lbHNlIGJsb2NrcywgCj4gdGhh dCB3b3VsZCBsb29rIG11Y2ggYmV0dGVyLiBUaGVuIHlvdSBjYW4gc2V0IHZhbCB8PSBGSUVMRF9Q UkVQKC4uLiwgCj4gbW9kZSkgYXQgdGhlIGVuZC4KCgpTdXJlLCB3aWxsIGNoYW5nZSB0aGlzIGlu IHRoZSBuZXh0IHZlcnNpb24uCgoKPgo+PiArwqDCoMKgIGVsc2UgaWYgKG9wLT5jbWQuYnVzd2lk dGggPT0gNCkKPj4gK8KgwqDCoMKgwqDCoMKgIHZhbCB8PSAoVFJBTl9NT0RFX1FVQURfRlVMTCA8 PCAKPj4gKGZmcyhzZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFzaykgLSAxKSkgJgo+PiArwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHNmYy0+c29jX2luZm8tPnRyYW5fbW9kZV9tYXNr Owo+PiArwqDCoMKgIGVsc2UgaWYgKG9wLT5jbWQuYnVzd2lkdGggPT0gMikKPj4gK8KgwqDCoMKg wqDCoMKgIHZhbCB8PSAoVFJBTl9NT0RFX0RVQUxfRlVMTCA8PCAKPj4gKGZmcyhzZmMtPnNvY19p bmZvLT50cmFuX21vZGVfbWFzaykgLSAxKSkgJgo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgIHNmYy0+c29jX2luZm8tPnRyYW5fbW9kZV9tYXNrOwo+PiArwqDCoMKgIGVsc2UgaWYg KG9wLT5hZGRyLmJ1c3dpZHRoID09IDgpCj4+ICvCoMKgwqDCoMKgwqDCoCB2YWwgfD0gKFRSQU5f TU9ERV9PQ1RBTF9JTyA8PCAKPj4gKGZmcyhzZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFzaykg LSAxKSkgJgo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHNmYy0+c29jX2luZm8t PnRyYW5fbW9kZV9tYXNrOwo+PiArwqDCoMKgIGVsc2UgaWYgKG9wLT5hZGRyLmJ1c3dpZHRoID09 IDQpCj4+ICvCoMKgwqDCoMKgwqDCoCB2YWwgfD0gKFRSQU5fTU9ERV9RVUFEX0lPIDw8IAo+PiAo ZmZzKHNmYy0+c29jX2luZm8tPnRyYW5fbW9kZV9tYXNrKSAtIDEpKSAmCj4+ICvCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqAgc2ZjLT5zb2NfaW5mby0+dHJhbl9tb2RlX21hc2s7Cj4+ICvC oMKgwqAgZWxzZSBpZiAob3AtPmFkZHIuYnVzd2lkdGggPT0gMikKPj4gK8KgwqDCoMKgwqDCoMKg IHZhbCB8PSAoVFJBTl9NT0RFX0RVQUxfSU8gPDwgCj4+IChmZnMoc2ZjLT5zb2NfaW5mby0+dHJh bl9tb2RlX21hc2spIC0gMSkpICYKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBz ZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFzazsKPj4gK8KgwqDCoCBlbHNlIGlmIChvcC0+ZGF0 YS5idXN3aWR0aCA9PSA4KQo+PiArwqDCoMKgwqDCoMKgwqAgdmFsIHw9IChUUkFOX01PREVfT0NU QUxfREFUQSA8PCAKPj4gKGZmcyhzZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFzaykgLSAxKSkg Jgo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHNmYy0+c29jX2luZm8tPnRyYW5f bW9kZV9tYXNrOwo+PiArwqDCoMKgIGVsc2UgaWYgKG9wLT5kYXRhLmJ1c3dpZHRoID09IDQpCj4+ ICvCoMKgwqDCoMKgwqDCoCB2YWwgfD0gKFRSQU5fTU9ERV9RVUFEX0RBVEEgPDwgCj4+IChmZnMo c2ZjLT5zb2NfaW5mby0+dHJhbl9tb2RlX21hc2spIC0gMSkpICYKPj4gK8KgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoCBzZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFzazsKPj4gK8KgwqDC oCBlbHNlIGlmIChvcC0+ZGF0YS5idXN3aWR0aCA9PSAyKQo+PiArwqDCoMKgwqDCoMKgwqAgdmFs IHw9IChUUkFOX01PREVfRFVBTF9EQVRBIDw8IAo+PiAoZmZzKHNmYy0+c29jX2luZm8tPnRyYW5f bW9kZV9tYXNrKSAtIDEpKSAmCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgc2Zj LT5zb2NfaW5mby0+dHJhbl9tb2RlX21hc2s7Cj4+ICvCoMKgwqAgZWxzZQo+PiArwqDCoMKgwqDC oMKgwqAgdmFsIHw9IChUUkFOX01PREVfU1RBTkRBUkQgPDwgCj4+IChmZnMoc2ZjLT5zb2NfaW5m by0+dHJhbl9tb2RlX21hc2spIC0gMSkpICYKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoCBzZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFzazsKPj4gK8KgwqDCoCB3cml0ZWwodmFs LCBzZmMtPmJhc2UgKyAoc2ZjLT5zb2NfaW5mby0+dmVyc2lvbiA+PSBJRF9YMTYwMCA/Cj4+ICvC oMKgwqDCoMKgwqDCoMKgwqDCoMKgIFNGQ19SRUdfVFJBTl9DRkcxKDApIDogU0ZDX1JFR19UUkFO X0NPTkYoMCkpKTsKPj4gK30KPj4gKwo+PiArLyoKPj4gKyAqIFdlIG9ubHkgbmVlZCBQSU8gbW9k ZSB0byBoYW5kbGUgdGhlIFNQSV9NRU1fTk9fREFUQSB0cmFuc2ZlcnMsCj4+ICsgKiBhbmQgdGhl IHVuYWxpZ25lZCBhY2Nlc3NlcyBpbiBTUElfTUVNX0RBVEFfSU4gdHJhbnNmZXJzLgo+PiArICov Cj4+ICtzdGF0aWMgdm9pZCBpbmdlbmljX3NmY19yZWFkX3J4ZmlmbyhzdHJ1Y3QgaW5nZW5pY19z ZmMgKnNmYywgdTggKnRvLCAKPj4gdW5zaWduZWQgaW50IGxlbikKPj4gK3sKPj4gK8KgwqDCoCB2 b2lkIF9faW9tZW0gKmZyb207Cj4+ICsKPj4gK8KgwqDCoCBmcm9tID0gc2ZjLT5iYXNlICsgU0ZD X1JFR19EUjsKPj4gKwo+PiArwqDCoMKgIGZvciAoOyBsZW4gPj0gNDsgbGVuIC09IDQsIHRvICs9 IDQpIHsKPj4gK8KgwqDCoMKgwqDCoMKgIHUzMiB2YWwgPSBfX3Jhd19yZWFkbChmcm9tKTsKPj4g K8KgwqDCoMKgwqDCoMKgIG1lbWNweSh0bywgJnZhbCwgNCk7Cj4KPiBObyBuZWVkIHRvIHVzZSBt ZW1jcHkgZm9yIDQgYnl0ZXMuIFlvdSBjYW4gZG86IHB1dF91bmFsaWduZWQodmFsLCAodTMyIAo+ ICopdG8pOwo+CgpTdXJlLgoKCj4+ICvCoMKgwqAgfQo+PiArCj4+ICvCoMKgwqAgaWYgKGxlbikg ewo+PiArwqDCoMKgwqDCoMKgwqAgdTMyIHZhbCA9IF9fcmF3X3JlYWRsKGZyb20pOwo+PiArwqDC oMKgwqDCoMKgwqAgbWVtY3B5KHRvLCAmdmFsLCBsZW4pOwo+Cj4gSG1tLCBJJ20gbm90IHN1cmUg dGhhdCBpcyBlbmRpYW4tc2FmZS4gSSB3b3VsZCBwcmVmZXIgaWYgeW91IGNvcGllZCAKPiBieXRl IGJ5IGJ5dGUuCj4KClN1cmUuCgoKPj4gK8KgwqDCoCB9Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBp bnQgaW5nZW5pY19zZmNfZXhlY19vcF9waW8oc3RydWN0IGluZ2VuaWNfc2ZjICpzZmMsIGNvbnN0 IAo+PiBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3ApCj4+ICt7Cj4+ICvCoMKgwqAgaW50IHJldCwgdmFs Owo+PiArCj4+ICvCoMKgwqAgdmFsID0gcmVhZGwoc2ZjLT5iYXNlICsgU0ZDX1JFR19HTEIpOwo+ PiArwqDCoMKgIHUzMnBfcmVwbGFjZV9iaXRzKCZ2YWwsIEdMQl9UUkFOX0RJUl9SRUFELCBHTEJf VFJBTl9ESVJfTUFTSyk7Cj4+ICvCoMKgwqAgdTMycF9yZXBsYWNlX2JpdHMoJnZhbCwgR0xCX09Q X01PREVfU0xBVkUsIEdMQl9PUF9NT0RFX01BU0spOwo+PiArwqDCoMKgIHdyaXRlbCh2YWwsIHNm Yy0+YmFzZSArIFNGQ19SRUdfR0xCKTsKPgo+IEJ5IHRoZSB3YXksIGhhdmUgeW91IGNvbnNpZGVy ZWQgdXNpbmcgcmVnbWFwPwo+Cj4gSXQgd291bGQgZ2l2ZSB5b3UgdGhpbmdzIGxpa2UgcmVnbWFw X3VwZGF0ZV9iaXRzKCkgZm9yIHRoaXMga2luZCBvZiAKPiB0aGluZ3MsIGFuZCByZWdtYXBfZmll bGQoKSB0byBoYW5kbGUgeW91ciBjb25mIHJlZ2lzdGVyIGJlaW5nIGF0IGEgCj4gZGlmZmVyZW50 IGFkZHJlc3MgYWNyb3NzIFNvQ3MuCj4KCkl0IHNlZW1zIHRoYXQgdGhlIG92ZXJoZWFkIG9mIHVz aW5nIHJlZ21hcCB3aWxsIGJlIGdyZWF0ZXIgdGhhbiB1c2luZyAKcmVhZGwgYW5kIHdyaXRlbCwK dGhlIHB1cnBvc2Ugb2YgdXNpbmcgcmVhZGwgYW5kIHdyaXRlbCBpcyB0byBtaW5pbWl6ZSBvdmVy aGVhZCBhbmQgCm1heGltaXplIHBlcmZvcm1hbmNlLiA6KQoKCj4+ICsKPj4gK8KgwqDCoCB2YWwg PSBUUkFOX0NPTkZfQ01EX0VOIHwgb3AtPmNtZC5vcGNvZGU7Cj4+ICsKPj4gK8KgwqDCoCBpZiAo b3AtPmFkZHIubmJ5dGVzID4gMCkgewo+PiArwqDCoMKgwqDCoMKgwqAgdmFsIHw9IEZJRUxEX1BS RVAoVFJBTl9DT05GX0FERFJfV0lEVEhfTUFTSywgb3AtPmFkZHIubmJ5dGVzKTsKPj4gKwo+PiAr wqDCoMKgwqDCoMKgwqAgd3JpdGVsKG9wLT5hZGRyLnZhbCAmIDB4ZmZmZmZmZmYsIHNmYy0+YmFz ZSArIAo+PiBTRkNfUkVHX0RFVl9BRERSKDApKTsKPj4gK8KgwqDCoMKgwqDCoMKgIHdyaXRlbChv cC0+YWRkci52YWwgPj4gMzIsIHNmYy0+YmFzZSArIAo+PiBTRkNfUkVHX0RFVl9BRERSX1BMVVMo MCkpOwo+PiArwqDCoMKgIH0KPj4gKwo+PiArwqDCoMKgIGlmIChvcC0+ZHVtbXkubmJ5dGVzID4g MCkKPj4gK8KgwqDCoMKgwqDCoMKgIHZhbCB8PSBGSUVMRF9QUkVQKFRSQU5fQ09ORl9ETVlfQklU U19NQVNLLAo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG9wLT5kdW1teS5uYnl0 ZXMgKiA4IC8gb3AtPmR1bW15LmJ1c3dpZHRoKTsKPj4gKwo+PiArwqDCoMKgIGlmIChvcC0+ZGF0 YS5uYnl0ZXMgPiAwKQo+PiArwqDCoMKgwqDCoMKgwqAgdmFsIHw9IFRSQU5fQ09ORl9EQVRBX0VO Owo+PiArCj4+ICvCoMKgwqAgd3JpdGVsKHZhbCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19UUkFOX0NP TkYoMCkpOwo+PiArwqDCoMKgIHdyaXRlbChvcC0+ZGF0YS5uYnl0ZXMsIHNmYy0+YmFzZSArIFNG Q19SRUdfVFJBTl9MRU4pOwo+PiArCj4+ICvCoMKgwqAgaW5nZW5pY19zZmNfc2V0X3RyYW5zZmVy X21vZGUoc2ZjLCBvcCk7Cj4+ICsKPj4gK8KgwqDCoCB3cml0ZWwoMHgxZiwgc2ZjLT5iYXNlICsg U0ZDX1JFR19TQ1IpOwo+Cj4gUmFuZG9tIDB4MWYgdmFsdWUgaGVyZSwgbWF5YmUgdXNlIGEgbWFj cm8/CgoKU3VyZS4KCgo+Cj4+ICvCoMKgwqAgd3JpdGVsKH4oSU5UQ19NQVNLX0VORCB8IElOVENf TUFTS19SUkVRKSwgc2ZjLT5iYXNlICsgCj4+IFNGQ19SRUdfSU5UQyk7Cj4+ICsKPj4gK8KgwqDC oCB3cml0ZWwoMCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19NRU1fQUREUik7Cj4+ICsKPj4gK8KgwqDC oCB3cml0ZWwoVFJJR19GTFVTSCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19UUklHKTsKPj4gK8KgwqDC oCB3cml0ZWwoVFJJR19TVEFSVCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19UUklHKTsKPj4gKwo+PiAr wqDCoMKgIHJldCA9IHdhaXRfZm9yX2NvbXBsZXRpb25fdGltZW91dCgmc2ZjLT5jb21wbGV0aW9u LAo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBtc2Vjc190b19qaWZmaWVzKElOR0VOSUNfU0ZD X1RSQU5TRkVSX1RJTUVPVVQpKTsKPj4gK8KgwqDCoCBpZiAoIXJldCkgewo+PiArwqDCoMKgwqDC oMKgwqAgd3JpdGVsKDB4MWYsIHNmYy0+YmFzZSArIFNGQ19SRUdfSU5UQyk7Cj4+ICvCoMKgwqDC oMKgwqDCoCB3cml0ZWwoMHgxZiwgc2ZjLT5iYXNlICsgU0ZDX1JFR19TQ1IpOwo+PiArwqDCoMKg wqDCoMKgwqAgZGV2X2VycihzZmMtPmRldiwgImxpbmU6JWQgVGltZW91dCBmb3IgQUNLIGZyb20g U0ZDIAo+PiBkZXZpY2VcbiIsIF9fTElORV9fKTsKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiAt RVRJTUVET1VUOwo+PiArwqDCoMKgIH0KPj4gKwo+PiArwqDCoMKgIGluZ2VuaWNfc2ZjX3JlYWRf cnhmaWZvKHNmYywgb3AtPmRhdGEuYnVmLmluLCBvcC0+ZGF0YS5uYnl0ZXMpOwo+PiArwqDCoMKg IHJlYWRsX3BvbGxfdGltZW91dChzZmMtPmJhc2UgKyBTRkNfUkVHX1NSLCB2YWwsIHZhbCAmIFNS X0VORCwgCj4+IDEwLCAwKTsKPgo+IEluZmluaXRlIHRpbWVvdXQ/IElzIHRoYXQgdmVyeSB3aXNl PwoKCldpbGwgZml4IGl0IGluIHRoZSBuZXh0IHZlcnNpb24uCgoKPgo+PiArCj4+ICvCoMKgwqAg d3JpdGVsKElOVENfTUFTS19FTkQgfCBJTlRDX01BU0tfUlJFUSwgc2ZjLT5iYXNlICsgU0ZDX1JF R19TQ1IpOwo+PiArwqDCoMKgIHdyaXRlbChUUklHX1NUT1AsIHNmYy0+YmFzZSArIFNGQ19SRUdf VFJJRyk7Cj4+ICsKPj4gK8KgwqDCoCByZXR1cm4gMDsKPj4gK30KPj4gKwo+PiArc3RhdGljIGlu dCBpbmdlbmljX3NmY19leGVjX29wX2RtYShzdHJ1Y3QgaW5nZW5pY19zZmMgKnNmYywgY29uc3Qg Cj4+IHN0cnVjdCBzcGlfbWVtX29wICpvcCkKPj4gK3sKPj4gK8KgwqDCoCBkbWFfYWRkcl90IGFk ZHI7Cj4+ICvCoMKgwqAgaW50IHJldCwgdmFsOwo+PiArCj4+ICvCoMKgwqAgdmFsID0gcmVhZGwo c2ZjLT5iYXNlICsgU0ZDX1JFR19HTEIpOwo+PiArwqDCoMKgIHUzMnBfcmVwbGFjZV9iaXRzKCZ2 YWwsIG9wLT5kYXRhLmRpciA9PSBTUElfTUVNX0RBVEFfSU4gPwo+PiArwqDCoMKgwqDCoMKgwqDC oMKgwqDCoCBHTEJfVFJBTl9ESVJfUkVBRCA6IEdMQl9UUkFOX0RJUl9XUklURSwgR0xCX1RSQU5f RElSX01BU0spOwo+PiArwqDCoMKgIHUzMnBfcmVwbGFjZV9iaXRzKCZ2YWwsIEdMQl9PUF9NT0RF X0RNQSwgR0xCX09QX01PREVfTUFTSyk7Cj4+ICvCoMKgwqAgd3JpdGVsKHZhbCwgc2ZjLT5iYXNl ICsgU0ZDX1JFR19HTEIpOwo+PiArCj4+ICvCoMKgwqAgdmFsID0gVFJBTl9DT05GX0NNRF9FTiB8 IG9wLT5jbWQub3Bjb2RlOwo+PiArCj4+ICvCoMKgwqAgaWYgKG9wLT5hZGRyLm5ieXRlcyA+IDAp IHsKPj4gK8KgwqDCoMKgwqDCoMKgIHZhbCB8PSBGSUVMRF9QUkVQKFRSQU5fQ09ORl9BRERSX1dJ RFRIX01BU0ssIG9wLT5hZGRyLm5ieXRlcyk7Cj4+ICvCoMKgwqDCoMKgwqDCoCB3cml0ZWwob3At PmFkZHIudmFsICYgMHhmZmZmZmZmZiwgc2ZjLT5iYXNlICsgCj4+IFNGQ19SRUdfREVWX0FERFIo MCkpOwo+PiArwqDCoMKgwqDCoMKgwqAgd3JpdGVsKG9wLT5hZGRyLnZhbCA+PiAzMiwgc2ZjLT5i YXNlICsgCj4+IFNGQ19SRUdfREVWX0FERFJfUExVUygwKSk7Cj4+ICvCoMKgwqAgfQo+PiArCj4+ ICvCoMKgwqAgaWYgKG9wLT5kdW1teS5uYnl0ZXMgPiAwKQo+PiArwqDCoMKgwqDCoMKgwqAgdmFs IHw9IEZJRUxEX1BSRVAoVFJBTl9DT05GX0RNWV9CSVRTX01BU0ssCj4+ICvCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqAgb3AtPmR1bW15Lm5ieXRlcyAqIDggLyBvcC0+ZHVtbXkuYnVzd2lk dGgpOwo+PiArCj4+ICvCoMKgwqAgaWYgKG9wLT5kYXRhLm5ieXRlcyA+IDApCj4+ICvCoMKgwqDC oMKgwqDCoCB2YWwgfD0gVFJBTl9DT05GX0RBVEFfRU47Cj4KPiBUaGVyZSdzIGEgbG90IG9mIGNv ZGUgZHVwbGljYXRpb24gaGVyZSB3aXRoIGluZ2VuaWNfc2ZjX2V4ZWNfb3BfcGlvKCkuIAo+IEEg bG90IGNhbiBiZSBmYWN0b3JpemVkLgoKClN1cmUsIEkgd2lsbCB0cnkgdG8gZG8gaXQuCgoKPgo+ PiArCj4+ICvCoMKgwqAgd3JpdGVsKHZhbCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19UUkFOX0NPTkYo MCkpOwo+PiArwqDCoMKgIHdyaXRlbChvcC0+ZGF0YS5uYnl0ZXMsIHNmYy0+YmFzZSArIFNGQ19S RUdfVFJBTl9MRU4pOwo+PiArCj4+ICvCoMKgwqAgaW5nZW5pY19zZmNfc2V0X3RyYW5zZmVyX21v ZGUoc2ZjLCBvcCk7Cj4+ICsKPj4gK8KgwqDCoCB3cml0ZWwoMHgxZiwgc2ZjLT5iYXNlICsgU0ZD X1JFR19TQ1IpOwo+PiArwqDCoMKgIHdyaXRlbCh+SU5UQ19NQVNLX0VORCwgc2ZjLT5iYXNlICsg U0ZDX1JFR19JTlRDKTsKPj4gKwo+PiArwqDCoMKgIHN3aXRjaCAob3AtPmRhdGEuZGlyKSB7Cj4+ ICvCoMKgwqAgY2FzZSBTUElfTUVNX0RBVEFfSU46Cj4+ICvCoMKgwqDCoMKgwqDCoCBhZGRyID0g ZG1hX21hcF9zaW5nbGUoc2ZjLT5kZXYsIG9wLT5kYXRhLmJ1Zi5pbiwgCj4+IG9wLT5kYXRhLm5i eXRlcywgRE1BX0ZST01fREVWSUNFKTsKPj4gK8KgwqDCoMKgwqDCoMKgIGlmIChkbWFfbWFwcGlu Z19lcnJvcihzZmMtPmRldiwgYWRkcikpIHsKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgZGV2 X2VycihzZmMtPmRldiwgIlJYIERNQeOAgG1lbW9yeSBub3QgbWFwcGVkXG4iKTsKPj4gK8KgwqDC oMKgwqDCoMKgwqDCoMKgwqAgcmV0dXJuIC1FTk9NRU07Cj4+ICvCoMKgwqDCoMKgwqDCoCB9Cj4+ ICsKPj4gK8KgwqDCoMKgwqDCoMKgIHdyaXRlbChhZGRyLCBzZmMtPmJhc2UgKyBTRkNfUkVHX01F TV9BRERSKTsKPj4gK8KgwqDCoMKgwqDCoMKgIGJyZWFrOwo+PiArCj4+ICvCoMKgwqAgY2FzZSBT UElfTUVNX0RBVEFfT1VUOgo+PiArwqDCoMKgwqDCoMKgwqAgYWRkciA9IGRtYV9tYXBfc2luZ2xl KHNmYy0+ZGV2LCAodm9pZCAqKW9wLT5kYXRhLmJ1Zi5vdXQsCj4+ICvCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqAgb3AtPmRhdGEubmJ5dGVzLCBETUFfVE9fREVWSUNFKTsKPj4gK8KgwqDC oMKgwqDCoMKgIGlmIChkbWFfbWFwcGluZ19lcnJvcihzZmMtPmRldiwgYWRkcikpIHsKPj4gK8Kg wqDCoMKgwqDCoMKgwqDCoMKgwqAgZGV2X2VycihzZmMtPmRldiwgIlRYIERNQeOAgG1lbW9yeSBu b3QgbWFwcGVkXG4iKTsKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgcmV0dXJuIC1FTk9NRU07 Cj4+ICvCoMKgwqDCoMKgwqDCoCB9Cj4+ICsKPj4gK8KgwqDCoMKgwqDCoMKgIHdyaXRlbChhZGRy LCBzZmMtPmJhc2UgKyBTRkNfUkVHX01FTV9BRERSKTsKPj4gK8KgwqDCoMKgwqDCoMKgIGJyZWFr Owo+PiArCj4+ICvCoMKgwqAgZGVmYXVsdDoKPj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybiAtRUlO VkFMOwo+PiArwqDCoMKgIH0KPj4gKwo+PiArwqDCoMKgIHdyaXRlbChUUklHX1NUQVJULCBzZmMt PmJhc2UgKyBTRkNfUkVHX1RSSUcpOwo+PiArCj4+ICvCoMKgwqAgcmV0ID0gd2FpdF9mb3JfY29t cGxldGlvbl90aW1lb3V0KCZzZmMtPmNvbXBsZXRpb24sCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDC oMKgIG1zZWNzX3RvX2ppZmZpZXMoSU5HRU5JQ19TRkNfVFJBTlNGRVJfVElNRU9VVCkpOwo+PiAr wqDCoMKgIGlmICghcmV0KSB7Cj4+ICvCoMKgwqDCoMKgwqDCoCB3cml0ZWwoMHgxZiwgc2ZjLT5i YXNlICsgU0ZDX1JFR19JTlRDKTsKPj4gK8KgwqDCoMKgwqDCoMKgIHdyaXRlbCgweDFmLCBzZmMt PmJhc2UgKyBTRkNfUkVHX1NDUik7Cj4+ICvCoMKgwqDCoMKgwqDCoCBkZXZfZXJyKHNmYy0+ZGV2 LCAibGluZTolZCBUaW1lb3V0IGZvciBBQ0sgZnJvbSBTRkMgCj4+IGRldmljZVxuIiwgX19MSU5F X18pOwo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIC1FVElNRURPVVQ7Cj4+ICvCoMKgwqAgfQo+ PiArCj4+ICvCoMKgwqAgZG1hX3VubWFwX3NpbmdsZShzZmMtPmRldiwgYWRkciwgb3AtPmRhdGEu bmJ5dGVzLAo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBvcC0+ZGF0YS5kaXIgPT0gU1BJX01F TV9EQVRBX0lOID8gRE1BX0ZST01fREVWSUNFIDogCj4+IERNQV9UT19ERVZJQ0UpOwo+Cj4gVXNl IGEgc21hbGwgaW5saW5lIGZ1bmN0aW9uIGZvciB0aGF0IHRvby4gTXkgcGVyc29uYWwgcnVsZSBp cyB0aGF0ID86IAo+IGlzIGZpbmUgaWYgdGhlIGxpbmUgZml0cyBpbiA4MCBjaGFyYWN0ZXJzLCBi dXQgaWYgeW91IGhhdmUgdG8gYnJlYWssIAo+IHRoZW4geW91IHJlYWxseSBuZWVkIHRvIG1vdmUg aXQgc29tZXdoZXJlIGVsc2UuCj4KClN1cmUuCgoKPj4gKwo+PiArwqDCoMKgIHdyaXRlbChJTlRD X01BU0tfRU5ELCBzZmMtPmJhc2UgKyBTRkNfUkVHX1NDUik7Cj4+ICvCoMKgwqAgd3JpdGVsKFRS SUdfU1RPUCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19UUklHKTsKPj4gKwo+PiArwqDCoMKgIHJldHVy biAwOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW50IGluZ2VuaWNfc2ZjX2V4ZWNfb3Aoc3RydWN0 IHNwaV9tZW0gKm1lbSwgY29uc3Qgc3RydWN0IAo+PiBzcGlfbWVtX29wICpvcCkKPj4gK3sKPj4g K8KgwqDCoCBzdHJ1Y3Qgc3BpX2RldmljZSAqc3BpID0gbWVtLT5zcGk7Cj4+ICvCoMKgwqAgc3Ry dWN0IGluZ2VuaWNfc2ZjICpzZmMgPSBzcGlfY29udHJvbGxlcl9nZXRfZGV2ZGF0YShzcGktPm1h c3Rlcik7Cj4+ICvCoMKgwqAgdWludHB0cl90IGFkZHIgPSAodWludHB0cl90KW9wLT5kYXRhLmJ1 Zi5pbjsKPj4gKwo+PiArwqDCoMKgIGluaXRfY29tcGxldGlvbigmc2ZjLT5jb21wbGV0aW9uKTsK Pj4gKwo+PiArwqDCoMKgIHN3aXRjaCAob3AtPmRhdGEuZGlyKSB7Cj4+ICvCoMKgwqAgY2FzZSBT UElfTUVNX0RBVEFfSU46Cj4+ICvCoMKgwqDCoMKgwqDCoCBpZiAoc2ZjLT5zb2NfaW5mby0+dmVy c2lvbiA+PSBJRF9YMTYwMCB8fCBJU19BTElHTkVEKGFkZHIsIDQpKQo+PiArwqDCoMKgwqDCoMKg wqDCoMKgwqDCoCBicmVhazsKPj4gKwo+PiArwqDCoMKgwqDCoMKgwqAgZmFsbHRocm91Z2g7Cj4+ ICsKPj4gK8KgwqDCoCBjYXNlIFNQSV9NRU1fTk9fREFUQToKPj4gK8KgwqDCoMKgwqDCoMKgIHJl dHVybiBpbmdlbmljX3NmY19leGVjX29wX3BpbyhzZmMsIG9wKTsKPj4gKwo+PiArwqDCoMKgIGRl ZmF1bHQ6Cj4+ICvCoMKgwqDCoMKgwqDCoCBicmVhazsKPj4gK8KgwqDCoCB9Cj4+ICsKPj4gK8Kg wqDCoCByZXR1cm4gaW5nZW5pY19zZmNfZXhlY19vcF9kbWEoc2ZjLCBvcCk7Cj4+ICt9Cj4+ICsK Pj4gK3N0YXRpYyBpbnQgaW5nZW5pY19zZmNfcG9sbF9zdGF0dXMoc3RydWN0IHNwaV9tZW0gKm1l bSwgY29uc3Qgc3RydWN0IAo+PiBzcGlfbWVtX29wICpvcCwKPj4gK8KgwqDCoMKgwqDCoMKgwqDC oMKgwqAgdTE2IG1hc2ssIHUxNiBtYXRjaCwgdW5zaWduZWQgbG9uZyBpbml0aWFsX2RlbGF5X3Vz LAo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCB1bnNpZ25lZCBsb25nIHBvbGxpbmdfZGVsYXlf dXMsIHVuc2lnbmVkIGxvbmcgdGltZW91dF9tcykKPj4gK3sKPj4gK8KgwqDCoCBzdHJ1Y3Qgc3Bp X2RldmljZSAqc3BpID0gbWVtLT5zcGk7Cj4+ICvCoMKgwqAgc3RydWN0IGluZ2VuaWNfc2ZjICpz ZmMgPSBzcGlfY29udHJvbGxlcl9nZXRfZGV2ZGF0YShzcGktPm1hc3Rlcik7Cj4+ICvCoMKgwqAg aW50IHJldCwgdmFsOwo+PiArCj4+ICvCoMKgwqAgaW5pdF9jb21wbGV0aW9uKCZzZmMtPmNvbXBs ZXRpb24pOwo+PiArCj4+ICvCoMKgwqAgdmFsID0gcmVhZGwoc2ZjLT5iYXNlICsgU0ZDX1JFR19H TEIpOwo+PiArwqDCoMKgIHUzMnBfcmVwbGFjZV9iaXRzKCZ2YWwsIEdMQl9UUkFOX0RJUl9SRUFE LCBHTEJfVFJBTl9ESVJfTUFTSyk7Cj4+ICvCoMKgwqAgdTMycF9yZXBsYWNlX2JpdHMoJnZhbCwg R0xCX09QX01PREVfU0xBVkUsIEdMQl9PUF9NT0RFX01BU0spOwo+PiArwqDCoMKgIHdyaXRlbCh2 YWwsIHNmYy0+YmFzZSArIFNGQ19SRUdfR0xCKTsKPj4gKwo+PiArwqDCoMKgIHdyaXRlbChtYXRj aCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19ERVZfU1RBX0VYUCk7Cj4+ICvCoMKgwqAgd3JpdGVsKG1h c2ssIHNmYy0+YmFzZSArIFNGQ19SRUdfREVWX1NUQV9NU0spOwo+PiArCj4+ICvCoMKgwqAgdmFs ID0gVFJBTl9DT05GX1BPTExfRU4gfCBUUkFOX0NPTkZfQ01EX0VOIHwgb3AtPmNtZC5vcGNvZGU7 Cj4+ICsKPj4gK8KgwqDCoCBpZiAob3AtPmFkZHIubmJ5dGVzID4gMCkgewo+PiArwqDCoMKgwqDC oMKgwqAgdmFsIHw9IEZJRUxEX1BSRVAoVFJBTl9DT05GX0FERFJfV0lEVEhfTUFTSywgb3AtPmFk ZHIubmJ5dGVzKTsKPj4gKwo+PiArwqDCoMKgwqDCoMKgwqAgd3JpdGVsKG9wLT5hZGRyLnZhbCAm IDB4ZmZmZmZmZmYsIHNmYy0+YmFzZSArIAo+PiBTRkNfUkVHX0RFVl9BRERSKDApKTsKPj4gK8Kg wqDCoMKgwqDCoMKgIHdyaXRlbChvcC0+YWRkci52YWwgPj4gMzIsIHNmYy0+YmFzZSArIAo+PiBT RkNfUkVHX0RFVl9BRERSX1BMVVMoMCkpOwo+PiArwqDCoMKgIH0KPj4gKwo+PiArwqDCoMKgIGlm IChvcC0+ZHVtbXkubmJ5dGVzID4gMCkKPj4gK8KgwqDCoMKgwqDCoMKgIHZhbCB8PSBGSUVMRF9Q UkVQKFRSQU5fQ09ORl9ETVlfQklUU19NQVNLLAo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgIG9wLT5kdW1teS5uYnl0ZXMgKiA4IC8gb3AtPmR1bW15LmJ1c3dpZHRoKTsKPj4gKwo+ PiArwqDCoMKgIGlmIChvcC0+ZGF0YS5uYnl0ZXMgPiAwKQo+PiArwqDCoMKgwqDCoMKgwqAgdmFs IHw9IFRSQU5fQ09ORl9EQVRBX0VOOwo+PiArCj4+ICvCoMKgwqAgd3JpdGVsKHZhbCwgc2ZjLT5i YXNlICsgU0ZDX1JFR19UUkFOX0NPTkYoMCkpOwo+PiArwqDCoMKgIHdyaXRlbChvcC0+ZGF0YS5u Ynl0ZXMsIHNmYy0+YmFzZSArIFNGQ19SRUdfVFJBTl9MRU4pOwo+PiArCj4+ICvCoMKgwqAgaW5n ZW5pY19zZmNfc2V0X3RyYW5zZmVyX21vZGUoc2ZjLCBvcCk7Cj4+ICsKPj4gK8KgwqDCoCB3cml0 ZWwoMHgxZiwgc2ZjLT5iYXNlICsgU0ZDX1JFR19TQ1IpOwo+PiArwqDCoMKgIHdyaXRlbCh+SU5U Q19NQVNLX0VORCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19JTlRDKTsKPj4gKwo+PiArwqDCoMKgIHdy aXRlbCgwLCBzZmMtPmJhc2UgKyBTRkNfUkVHX01FTV9BRERSKTsKPj4gKwo+PiArwqDCoMKgIHdy aXRlbChUUklHX1NUQVJULCBzZmMtPmJhc2UgKyBTRkNfUkVHX1RSSUcpOwo+PiArCj4+ICvCoMKg wqAgcmV0ID0gd2FpdF9mb3JfY29tcGxldGlvbl90aW1lb3V0KCZzZmMtPmNvbXBsZXRpb24sCj4+ ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG1zZWNzX3RvX2ppZmZpZXMoSU5HRU5JQ19TRkNfVFJB TlNGRVJfVElNRU9VVCkpOwo+PiArwqDCoMKgIGlmICghcmV0KSB7Cj4+ICvCoMKgwqDCoMKgwqDC oCB3cml0ZWwoMHgxZiwgc2ZjLT5iYXNlICsgU0ZDX1JFR19JTlRDKTsKPj4gK8KgwqDCoMKgwqDC oMKgIHdyaXRlbCgweDFmLCBzZmMtPmJhc2UgKyBTRkNfUkVHX1NDUik7Cj4+ICvCoMKgwqDCoMKg wqDCoCBkZXZfZXJyKHNmYy0+ZGV2LCAibGluZTolZCBUaW1lb3V0IGZvciBBQ0sgZnJvbSBTRkMg Cj4+IGRldmljZVxuIiwgX19MSU5FX18pOwo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIC1FVElN RURPVVQ7Cj4+ICvCoMKgwqAgfQo+PiArCj4+ICvCoMKgwqAgd3JpdGVsKFNDUl9DTFJfRU5ELCBz ZmMtPmJhc2UgKyBTRkNfUkVHX1NDUik7Cj4+ICvCoMKgwqAgd3JpdGVsKFRSSUdfU1RPUCwgc2Zj LT5iYXNlICsgU0ZDX1JFR19UUklHKTsKPj4gKwo+PiArwqDCoMKgIHJldHVybiAwOwo+PiArfQo+ PiArCj4+ICtzdGF0aWMgY29uc3Qgc3RydWN0IHNwaV9jb250cm9sbGVyX21lbV9vcHMgaW5nZW5p Y19zZmNfbWVtX29wcyA9IHsKPj4gK8KgwqDCoCAuYWRqdXN0X29wX3NpemUgPSBpbmdlbmljX3Nm Y19hZGp1c3Rfb3Bfc2l6ZSwKPj4gK8KgwqDCoCAuc3VwcG9ydHNfb3AgPSBpbmdlbmljX3NmY19z dXBwb3J0c19vcCwKPj4gK8KgwqDCoCAuZXhlY19vcCA9IGluZ2VuaWNfc2ZjX2V4ZWNfb3AsCj4+ ICvCoMKgwqAgLnBvbGxfc3RhdHVzID0gaW5nZW5pY19zZmNfcG9sbF9zdGF0dXMsCj4+ICt9Owo+ PiArCj4+ICtzdGF0aWMgaW50IGluZ2VuaWNfc2ZjX3NldHVwKHN0cnVjdCBzcGlfZGV2aWNlICpz cGkpCj4+ICt7Cj4+ICvCoMKgwqAgc3RydWN0IGluZ2VuaWNfc2ZjICpzZmMgPSBzcGlfY29udHJv bGxlcl9nZXRfZGV2ZGF0YShzcGktPm1hc3Rlcik7Cj4+ICvCoMKgwqAgdW5zaWduZWQgbG9uZyBy YXRlOwo+PiArwqDCoMKgIGludCByZXQsIHZhbDsKPj4gKwo+PiArwqDCoMKgIGlmICghc3BpLT5t YXhfc3BlZWRfaHopCj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gLUVJTlZBTDsKPgo+IE1heWJl IHNldCBhIHNhbmUgZGVmYXVsdD8KCgpTdXJlLgoKCj4KPj4gKwo+PiArwqDCoMKgIHJldCA9IGNs a19zZXRfcmF0ZShzZmMtPmNsaywgc3BpLT5tYXhfc3BlZWRfaHogKiAyKTsKPj4gK8KgwqDCoCBp ZiAocmV0KQo+PiArwqDCoMKgwqDCoMKgwqAgcmV0dXJuIC1FSU5WQUw7Cj4+ICsKPj4gK8KgwqDC oCB3cml0ZWwoVFJJR19TVE9QLCBzZmMtPmJhc2UgKyBTRkNfUkVHX1RSSUcpOwo+PiArwqDCoMKg IHdyaXRlbCgwLCBzZmMtPmJhc2UgKyBTRkNfUkVHX0RFVl9DT05GKTsKPj4gK8KgwqDCoCB3cml0 ZWwoMCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19DR0UpOwo+PiArCj4+ICvCoMKgwqAgdmFsID0gcmVh ZGwoc2ZjLT5iYXNlICsgU0ZDX1JFR19HTEIpOwo+PiArwqDCoMKgIHUzMnBfcmVwbGFjZV9iaXRz KCZ2YWwsIDY0IC0gMSwgR0xCX1RIUkVTSE9MRF9NQVNLKTsKPj4gK8KgwqDCoCB3cml0ZWwodmFs LCBzZmMtPmJhc2UgKyBTRkNfUkVHX0dMQik7Cj4+ICsKPj4gK8KgwqDCoCB2YWwgPSByZWFkbChz ZmMtPmJhc2UgKyBTRkNfUkVHX0RFVl9DT05GKTsKPj4gKwo+PiArwqDCoMKgIC8qIGNwaGEgYml0 OjAgLCBjcG9sIGJpdDowICovCj4+ICvCoMKgwqAgdmFsICY9IH4oREVWX0NPTkZfQ1BIQSB8IERF Vl9DT05GX0NQT0wpOwo+PiArwqDCoMKgIHZhbCB8PSBzcGktPm1vZGUgJiBTUElfQ1BIQSA/IERF Vl9DT05GX0NQSEEgOiAwOwo+PiArwqDCoMKgIHZhbCB8PSBzcGktPm1vZGUgJiBTUElfQ1BPTCA/ IERFVl9DT05GX0NQT0wgOiAwOwo+PiArCj4+ICvCoMKgwqAgLyogY2VfZGwgYml0OjEsIGhvbGQg Yml0OjEsIHdwIGJpdDoxICovCj4+ICvCoMKgwqAgdmFsIHw9IChERVZfQ09ORl9DRV9ETCB8IERF Vl9DT05GX0hPTERfREwgfCBERVZfQ09ORl9XUF9ETCk7Cj4+ICsKPj4gK8KgwqDCoCB3cml0ZWwo dmFsLCBzZmMtPmJhc2UgKyBTRkNfUkVHX0RFVl9DT05GKTsKPj4gKwo+PiArwqDCoMKgIHZhbCA9 IHJlYWRsKHNmYy0+YmFzZSArIFNGQ19SRUdfR0xCKTsKPj4gK8KgwqDCoCB1MzJwX3JlcGxhY2Vf Yml0cygmdmFsLCBHTEJfT1BfTU9ERV9TTEFWRSwgR0xCX09QX01PREVfTUFTSyk7Cj4+ICvCoMKg wqAgd3JpdGVsKHZhbCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19HTEIpOwo+PiArCj4+ICvCoMKgwqAg cmF0ZSA9IGNsa19nZXRfcmF0ZShzZmMtPmNsayk7Cj4KPiBJJ2Qgc3VnZ2VzdCB1c2luZyBjbGtf cm91bmRfcmF0ZSgpIGJlZm9yZSBjbGtfc2V0X3JhdGUoKSBiZWNhdXNlIHRoZW4gCj4geW91IGtu b3cgd2hhdCBmcmVxdWVuY3kgaXQncyBnb2luZyB0byBiZSwgYW5kIHlvdSBkb24ndCBoYXZlIHRv IGNhbGwgCj4gY2xrX2dldF9yYXRlKCkgYWZ0ZXJ3YXJkcy4KPgoKU3VyZSwgd2lsbCB0cnkuCgoK VGhhbmtzIGFuZCBiZXN0IHJlZ2FyZHMhCgoKPiBDaGVlcnMsCj4gLVBhdWwKPgo+PiArwqDCoMKg IHZhbCA9IHJlYWRsKHNmYy0+YmFzZSArIFNGQ19SRUdfREVWX0NPTkYpOwo+PiArwqDCoMKgIGlm IChzZmMtPnNvY19pbmZvLT52ZXJzaW9uID49IElEX1gxNjAwICYmIHJhdGUgPj0gMjAwMDAwMDAw KQo+PiArwqDCoMKgwqDCoMKgwqAgdTMycF9yZXBsYWNlX2JpdHMoJnZhbCwgREVWX0NPTkZfU01Q X0RFTEFZXzE4MERFRywgCj4+IERFVl9DT05GX1NNUF9ERUxBWV9NQVNLKTsKPj4gK8KgwqDCoCBl bHNlIGlmIChzZmMtPnNvY19pbmZvLT52ZXJzaW9uID09IElEX1gxMDAwICYmIHJhdGUgPj0gMTAw MDAwMDAwKQo+PiArwqDCoMKgwqDCoMKgwqAgdTMycF9yZXBsYWNlX2JpdHMoJnZhbCwgREVWX0NP TkZfU01QX0RFTEFZX0hBTEZfQ1lDTEUsIAo+PiBERVZfQ09ORl9TTVBfREVMQVlfTUFTSyk7Cj4+ ICvCoMKgwqAgd3JpdGVsKHZhbCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19ERVZfQ09ORik7Cj4+ICsK Pj4gK8KgwqDCoCByZXR1cm4gMDsKPj4gK30KPj4gKwo+PiArc3RhdGljIGludCBpbmdlbmljX3Nm Y19wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+PiArewo+PiArwqDCoMKgIHN0 cnVjdCBpbmdlbmljX3NmYyAqc2ZjOwo+PiArwqDCoMKgIHN0cnVjdCBzcGlfY29udHJvbGxlciAq Y3RscjsKPj4gK8KgwqDCoCBpbnQgcmV0Owo+PiArCj4+ICvCoMKgwqAgY3RsciA9IHNwaV9hbGxv Y19tYXN0ZXIoJnBkZXYtPmRldiwgc2l6ZW9mKCpzZmMpKTsKPj4gK8KgwqDCoCBpZiAoIWN0bHIp Cj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gLUVOT01FTTsKPj4gKwo+PiArwqDCoMKgIHNmYyA9 IHNwaV9jb250cm9sbGVyX2dldF9kZXZkYXRhKGN0bHIpOwo+PiArCj4+ICvCoMKgwqAgc2ZjLT5z b2NfaW5mbyA9IG9mX2RldmljZV9nZXRfbWF0Y2hfZGF0YSgmcGRldi0+ZGV2KTsKPj4gK8KgwqDC oCBpZiAoIXNmYy0+c29jX2luZm8pIHsKPj4gK8KgwqDCoMKgwqDCoMKgIGRldl9lcnIoJnBkZXYt PmRldiwgIk5vIG9mIG1hdGNoIGRhdGEgcHJvdmlkZWRcbiIpOwo+PiArwqDCoMKgwqDCoMKgwqAg cmV0ID0gLUVOT0RFVjsKPj4gK8KgwqDCoMKgwqDCoMKgIGdvdG8gZXJyX3B1dF9tYXN0ZXI7Cj4+ ICvCoMKgwqAgfQo+PiArCj4+ICvCoMKgwqAgc2ZjLT5iYXNlID0gZGV2bV9wbGF0Zm9ybV9pb3Jl bWFwX3Jlc291cmNlKHBkZXYsIDApOwo+PiArwqDCoMKgIGlmIChJU19FUlIoc2ZjLT5iYXNlKSkg ewo+PiArwqDCoMKgwqDCoMKgwqAgcmV0ID0gUFRSX0VSUihzZmMtPmJhc2UpOwo+PiArwqDCoMKg wqDCoMKgwqAgZ290byBlcnJfcHV0X21hc3RlcjsKPj4gK8KgwqDCoCB9Cj4+ICsKPj4gK8KgwqDC oCBzZmMtPmNsayA9IGRldm1fY2xrX2dldCgmcGRldi0+ZGV2LCAic2ZjIik7Cj4+ICvCoMKgwqAg aWYgKElTX0VSUihzZmMtPmNsaykpIHsKPj4gK8KgwqDCoMKgwqDCoMKgIHJldCA9IElTX0VSUihz ZmMtPmNsayk7Cj4+ICvCoMKgwqDCoMKgwqDCoCBnb3RvIGVycl9wdXRfbWFzdGVyOwo+PiArwqDC oMKgIH0KPj4gKwo+PiArwqDCoMKgIHJldCA9IGNsa19wcmVwYXJlX2VuYWJsZShzZmMtPmNsayk7 Cj4+ICvCoMKgwqAgaWYgKHJldCkKPj4gK8KgwqDCoMKgwqDCoMKgIGdvdG8gZXJyX3B1dF9tYXN0 ZXI7Cj4+ICsKPj4gK8KgwqDCoCBzZmMtPmlycSA9IHBsYXRmb3JtX2dldF9pcnEocGRldiwgMCk7 Cj4+ICvCoMKgwqAgaWYgKHNmYy0+aXJxIDwgMCkgewo+PiArwqDCoMKgwqDCoMKgwqAgcmV0ID0g c2ZjLT5pcnE7Cj4+ICvCoMKgwqDCoMKgwqDCoCBnb3RvIGVycl9wdXRfbWFzdGVyOwo+PiArwqDC oMKgIH0KPj4gKwo+PiArwqDCoMKgIHNmYy0+ZGV2ID0gJnBkZXYtPmRldjsKPj4gKwo+PiArwqDC oMKgIHBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHNmYyk7Cj4+ICsKPj4gK8KgwqDCoCByZXQg PSBkZXZtX3JlcXVlc3RfaXJxKCZwZGV2LT5kZXYsIHNmYy0+aXJxLCAKPj4gaW5nZW5pY19zZmNf aXJxX2hhbmRsZXIsIDAsCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGRldl9uYW1lKCZwZGV2 LT5kZXYpLCBzZmMpOwo+PiArwqDCoMKgIGlmIChyZXQpIHsKPj4gK8KgwqDCoMKgwqDCoMKgIGRl dl9lcnIoJnBkZXYtPmRldiwgIkZhaWxlZCB0byByZXF1ZXN0IGlycSVkLCByZXQgPSAlZFxuIiwg Cj4+IHNmYy0+aXJxLCByZXQpOwo+PiArwqDCoMKgwqDCoMKgwqAgZ290byBlcnJfcHV0X21hc3Rl cjsKPj4gK8KgwqDCoCB9Cj4+ICsKPj4gK8KgwqDCoCBjdGxyLT5idXNfbnVtID0gLTE7Cj4+ICvC oMKgwqAgY3Rsci0+bnVtX2NoaXBzZWxlY3QgPSAxOwo+PiArwqDCoMKgIGN0bHItPm1lbV9vcHMg PSAmaW5nZW5pY19zZmNfbWVtX29wczsKPj4gK8KgwqDCoCBjdGxyLT5kZXYub2Zfbm9kZSA9IHBk ZXYtPmRldi5vZl9ub2RlOwo+PiArwqDCoMKgIGN0bHItPnNldHVwID0gaW5nZW5pY19zZmNfc2V0 dXA7Cj4+ICvCoMKgwqAgY3Rsci0+bW9kZV9iaXRzID0gU1BJX0NQSEEgfCBTUElfQ1BPTCB8Cj4+ ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIFNQSV9SWF9EVUFMIHwgU1BJX1JYX1FVQUQgfCBTUElf VFhfRFVBTCB8IFNQSV9UWF9RVUFEOwo+PiArwqDCoMKgIGlmIChzZmMtPnNvY19pbmZvLT52ZXJz aW9uID49IElEX1gyMDAwKQo+PiArwqDCoMKgwqDCoMKgwqAgY3Rsci0+bW9kZV9iaXRzIHw9IFNQ SV9SWF9PQ1RBTCB8IFNQSV9UWF9PQ1RBTDsKPj4gKwo+PiArwqDCoMKgIHJldCA9IGRldm1fc3Bp X3JlZ2lzdGVyX2NvbnRyb2xsZXIoJnBkZXYtPmRldiwgY3Rscik7Cj4+ICvCoMKgwqAgaWYgKHJl dCkKPj4gK8KgwqDCoMKgwqDCoMKgIGdvdG8gZXJyX3B1dF9tYXN0ZXI7Cj4+ICsKPj4gK8KgwqDC oCByZXR1cm4gMDsKPj4gKwo+PiArZXJyX3B1dF9tYXN0ZXI6Cj4+ICvCoMKgwqAgc3BpX21hc3Rl cl9wdXQoY3Rscik7Cj4+ICsKPj4gK8KgwqDCoCByZXR1cm4gcmV0Owo+PiArfQo+PiArCj4+ICtz dGF0aWMgY29uc3Qgc3RydWN0IGluZ2VuaWNfc29jX2luZm8geDEwMDBfc29jX2luZm8gPSB7Cj4+ ICvCoMKgwqAgLnZlcnNpb24gPSBJRF9YMTAwMCwKPj4gKwo+PiArwqDCoMKgIC5tYXhfYnVzX3dp ZHRoID0gNCwKPj4gKwo+PiArwqDCoMKgIC50cmFuX21vZGVfbWFzayA9IFRSQU5fQ09ORl9UUkFO X01PREVfTUFTSywKPj4gK307Cj4+ICsKPj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgaW5nZW5pY19z b2NfaW5mbyB4MTYwMF9zb2NfaW5mbyA9IHsKPj4gK8KgwqDCoCAudmVyc2lvbiA9IElEX1gxNjAw LAo+PiArCj4+ICvCoMKgwqAgLm1heF9idXNfd2lkdGggPSA0LAo+PiArCj4+ICvCoMKgwqAgLnRy YW5fbW9kZV9tYXNrID0gVFJBTl9DT05GX1RSQU5fTU9ERV9NQVNLLAo+PiArfTsKPj4gKwo+PiAr c3RhdGljIGNvbnN0IHN0cnVjdCBpbmdlbmljX3NvY19pbmZvIHgyMDAwX3NvY19pbmZvID0gewo+ PiArwqDCoMKgIC52ZXJzaW9uID0gSURfWDIwMDAsCj4+ICsKPj4gK8KgwqDCoCAubWF4X2J1c193 aWR0aCA9IDgsCj4+ICsKPj4gK8KgwqDCoCAudHJhbl9tb2RlX21hc2sgPSBUUkFOX0NGRzFfVFJB Tl9NT0RFX01BU0ssCj4+ICt9Owo+PiArCj4+ICtzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2Rldmlj ZV9pZCBpbmdlbmljX3NmY19vZl9tYXRjaGVzW10gPSB7Cj4+ICvCoMKgwqAgeyAuY29tcGF0aWJs ZSA9ICJpbmdlbmljLHgxMDAwLXNmYyIsIC5kYXRhID0gJngxMDAwX3NvY19pbmZvIH0sCj4+ICvC oMKgwqAgeyAuY29tcGF0aWJsZSA9ICJpbmdlbmljLHgxNjAwLXNmYyIsIC5kYXRhID0gJngxNjAw X3NvY19pbmZvIH0sCj4+ICvCoMKgwqAgeyAuY29tcGF0aWJsZSA9ICJpbmdlbmljLHgyMDAwLXNm YyIsIC5kYXRhID0gJngyMDAwX3NvY19pbmZvIH0sCj4+ICvCoMKgwqAgeyAvKiBzZW50aW5lbCAq LyB9Cj4+ICt9Owo+PiArTU9EVUxFX0RFVklDRV9UQUJMRShvZiwgaW5nZW5pY19zZmNfb2ZfbWF0 Y2hlcyk7Cj4+ICsKPj4gK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIGluZ2VuaWNfc2Zj X2RyaXZlciA9IHsKPj4gK8KgwqDCoCAuZHJpdmVyID0gewo+PiArwqDCoMKgwqDCoMKgwqAgLm5h bWUgPSAiaW5nZW5pYy1zZmMiLAo+PiArwqDCoMKgwqDCoMKgwqAgLm9mX21hdGNoX3RhYmxlID0g aW5nZW5pY19zZmNfb2ZfbWF0Y2hlcywKPj4gK8KgwqDCoCB9LAo+PiArwqDCoMKgIC5wcm9iZSA9 IGluZ2VuaWNfc2ZjX3Byb2JlLAo+PiArfTsKPj4gK21vZHVsZV9wbGF0Zm9ybV9kcml2ZXIoaW5n ZW5pY19zZmNfZHJpdmVyKTsKPj4gKwo+PiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo+PiArTU9E VUxFX0FVVEhPUigi5ZGo55Cw5p2wIChaaG91IFlhbmppZSkgPHpob3V5YW5qaWVAd2FueWVldGVj aC5jb20+Iik7Cj4+ICtNT0RVTEVfREVTQ1JJUFRJT04oIkluZ2VuaWMgU29DcyBTUEkgRmxhc2gg Q29udHJvbGxlciBEcml2ZXIiKTsKPj4gLS0gCj4+IDIuNy40Cj4+Cj4KCl9fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpMaW51eCBNVEQgZGlzY3Vz c2lvbiBtYWlsaW5nIGxpc3QKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0 aW5mby9saW51eC1tdGQvCg==