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 21B3EC6FD18 for ; Fri, 31 Mar 2023 09:34:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231421AbjCaJeb convert rfc822-to-8bit (ORCPT ); Fri, 31 Mar 2023 05:34:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41216 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232230AbjCaJeK (ORCPT ); Fri, 31 Mar 2023 05:34:10 -0400 Received: from fd01.gateway.ufhost.com (fd01.gateway.ufhost.com [61.152.239.71]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CEE071EA1A; Fri, 31 Mar 2023 02:33:37 -0700 (PDT) Received: from EXMBX165.cuchost.com (unknown [175.102.18.54]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "EXMBX165", Issuer "EXMBX165" (not verified)) by fd01.gateway.ufhost.com (Postfix) with ESMTP id 550B524DB8C; Fri, 31 Mar 2023 17:33:27 +0800 (CST) Received: from EXMBX168.cuchost.com (172.16.6.78) by EXMBX165.cuchost.com (172.16.6.75) with Microsoft SMTP Server (TLS) id 15.0.1497.42; Fri, 31 Mar 2023 17:33:27 +0800 Received: from [192.168.120.57] (171.223.208.138) by EXMBX168.cuchost.com (172.16.6.78) with Microsoft SMTP Server (TLS) id 15.0.1497.42; Fri, 31 Mar 2023 17:33:26 +0800 Message-ID: Date: Fri, 31 Mar 2023 17:33:26 +0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.9.0 Subject: Re: [PATCH v4 2/4] mmc: starfive: Add sdio/emmc driver support To: Shengyu Qu , , , CC: Rob Herring , Krzysztof Kozlowski , Jaehoon Chung , Ulf Hansson , References: <20230215113249.47727-1-william.qiu@starfivetech.com> <20230215113249.47727-3-william.qiu@starfivetech.com> Content-Language: en-US From: William Qiu In-Reply-To: Content-Type: text/plain; charset="UTF-8" X-Originating-IP: [171.223.208.138] X-ClientProxiedBy: EXCAS061.cuchost.com (172.16.6.21) To EXMBX168.cuchost.com (172.16.6.78) X-YovoleRuleAgent: yovoleflag Content-Transfer-Encoding: 8BIT Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org On 2023/3/29 0:08, Shengyu Qu wrote: > Hello William, > > Sorry for making noise about this, but seems deleted voltage swtich function > > doesn't help about this. But there's still a problem about eMMC speed. Currently > > only about 20MB/s maximum reading speed could be reached when using eMMC > > on VF2, any idea about this? > > Best regards, > > Shengyu > > 在 2023/3/28 0:01, Shengyu Qu 写道: >> Hello William, >> >> I'm digging into downstream mmc driver these days and found a problem >> >> that current version mainline driver doesn't has a voltage switch function for >> >> it. Downstream older version has one but was deleted in this commit [1]. >> >> It was deleted since vf2's SD slot doesn't have 1.8V input but commiter forgot >> >> that vf2's eMMC slot has a proper 1.8V input. >> >> So could you add voltage switch function for mainline? I've met a eMMC speed >> >> problem possibly due to it. >> >> Best regards, >> >> Shengyu >> Hi Shengyu, Sorry for the late reply. First of all, I will consider adding voltage switch function, but the implementation method is to configure the pmic register configuration in dts, and the implementation interface will use the voltage switch function in dw_mmc.c. As for speed, the main reason for the low rate is the clock of JH7110 and the associated IO driving strength, in this limit, the maximum reading speed I tested was about 50Mb/s. I will try to reproduce your problem and try to solve it. Thanks for suggestions. Best regards, William >> [1] https://github.com/starfive-tech/linux/commit/8037d59091d276e74be38e5fafaaebe36eaa77e1 >> >> 在 2023/2/15 19:32, William Qiu 写道: >>> Add sdio/emmc driver support for StarFive JH7110 soc. >>> >>> Tested-by: Conor Dooley >>> Signed-off-by: William Qiu >>> --- >>>   MAINTAINERS                        |   6 + >>>   drivers/mmc/host/Kconfig           |  10 ++ >>>   drivers/mmc/host/Makefile          |   1 + >>>   drivers/mmc/host/dw_mmc-starfive.c | 186 +++++++++++++++++++++++++++++ >>>   4 files changed, 203 insertions(+) >>>   create mode 100644 drivers/mmc/host/dw_mmc-starfive.c >>> >>> diff --git a/MAINTAINERS b/MAINTAINERS >>> index 85e8f83161d7..644ac9479a6e 100644 >>> --- a/MAINTAINERS >>> +++ b/MAINTAINERS >>> @@ -19640,6 +19640,12 @@ F: Documentation/devicetree/bindings/clock/starfive,jh71*.yaml >>>   F:    drivers/clk/starfive/clk-starfive-jh71* >>>   F:    include/dt-bindings/clock/starfive?jh71*.h >>>   +STARFIVE JH7110 MMC/SD/SDIO DRIVER >>> +M:    William Qiu >>> +S:    Supported >>> +F:    Documentation/devicetree/bindings/mmc/starfive* >>> +F:    drivers/mmc/host/dw_mmc-starfive.c >>> + >>>   STARFIVE JH71X0 PINCTRL DRIVERS >>>   M:    Emil Renner Berthing >>>   M:    Jianlong Huang >>> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig >>> index fb1062a6394c..b87262503403 100644 >>> --- a/drivers/mmc/host/Kconfig >>> +++ b/drivers/mmc/host/Kconfig >>> @@ -871,6 +871,16 @@ config MMC_DW_ROCKCHIP >>>         Synopsys DesignWare Memory Card Interface driver. Select this option >>>         for platforms based on RK3066, RK3188 and RK3288 SoC's. >>>   +config MMC_DW_STARFIVE >>> +    tristate "StarFive specific extensions for Synopsys DW Memory Card Interface" >>> +    depends on SOC_STARFIVE >>> +    depends on MMC_DW >>> +    select MMC_DW_PLTFM >>> +    help >>> +      This selects support for StarFive JH7110 SoC specific extensions to the >>> +      Synopsys DesignWare Memory Card Interface driver. Select this option >>> +      for platforms based on StarFive JH7110 SoC. >>> + >>>   config MMC_SH_MMCIF >>>       tristate "SuperH Internal MMCIF support" >>>       depends on SUPERH || ARCH_RENESAS || COMPILE_TEST >>> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile >>> index 4e4ceb32c4b4..32c0e5564b9a 100644 >>> --- a/drivers/mmc/host/Makefile >>> +++ b/drivers/mmc/host/Makefile >>> @@ -56,6 +56,7 @@ obj-$(CONFIG_MMC_DW_HI3798CV200) += dw_mmc-hi3798cv200.o >>>   obj-$(CONFIG_MMC_DW_K3)        += dw_mmc-k3.o >>>   obj-$(CONFIG_MMC_DW_PCI)    += dw_mmc-pci.o >>>   obj-$(CONFIG_MMC_DW_ROCKCHIP)    += dw_mmc-rockchip.o >>> +obj-$(CONFIG_MMC_DW_STARFIVE)    += dw_mmc-starfive.o >>>   obj-$(CONFIG_MMC_SH_MMCIF)    += sh_mmcif.o >>>   obj-$(CONFIG_MMC_JZ4740)    += jz4740_mmc.o >>>   obj-$(CONFIG_MMC_VUB300)    += vub300.o >>> diff --git a/drivers/mmc/host/dw_mmc-starfive.c b/drivers/mmc/host/dw_mmc-starfive.c >>> new file mode 100644 >>> index 000000000000..40f5969b07a6 >>> --- /dev/null >>> +++ b/drivers/mmc/host/dw_mmc-starfive.c >>> @@ -0,0 +1,186 @@ >>> +// SPDX-License-Identifier: GPL-2.0 >>> +/* >>> + * StarFive Designware Mobile Storage Host Controller Driver >>> + * >>> + * Copyright (c) 2022 StarFive Technology Co., Ltd. >>> + */ >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include "dw_mmc.h" >>> +#include "dw_mmc-pltfm.h" >>> + >>> +#define ALL_INT_CLR        0x1ffff >>> +#define MAX_DELAY_CHAIN        32 >>> + >>> +struct starfive_priv { >>> +    struct device *dev; >>> +    struct regmap *reg_syscon; >>> +    u32 syscon_offset; >>> +    u32 syscon_shift; >>> +    u32 syscon_mask; >>> +}; >>> + >>> +static void dw_mci_starfive_set_ios(struct dw_mci *host, struct mmc_ios *ios) >>> +{ >>> +    int ret; >>> +    unsigned int clock; >>> + >>> +    if (ios->timing == MMC_TIMING_MMC_DDR52 || ios->timing == MMC_TIMING_UHS_DDR50) { >>> +        clock = (ios->clock > 50000000 && ios->clock <= 52000000) ? 100000000 : ios->clock; >>> +        ret = clk_set_rate(host->ciu_clk, clock); >>> +        if (ret) >>> +            dev_dbg(host->dev, "Use an external frequency divider %uHz\n", ios->clock); >>> +        host->bus_hz = clk_get_rate(host->ciu_clk); >>> +    } else { >>> +        dev_dbg(host->dev, "Using the internal divider\n"); >>> +    } >>> +} >>> + >>> +static int dw_mci_starfive_execute_tuning(struct dw_mci_slot *slot, >>> +                         u32 opcode) >>> +{ >>> +    static const int grade  = MAX_DELAY_CHAIN; >>> +    struct dw_mci *host = slot->host; >>> +    struct starfive_priv *priv = host->priv; >>> +    int rise_point = -1, fall_point = -1; >>> +    int err, prev_err; >>> +    int i; >>> +    bool found = 0; >>> +    u32 regval; >>> + >>> +    /* >>> +     * Use grade as the max delay chain, and use the rise_point and >>> +     * fall_point to ensure the best sampling point of a data input >>> +     * signals. >>> +     */ >>> +    for (i = 0; i < grade; i++) { >>> +        regval = i << priv->syscon_shift; >>> +        err = regmap_update_bits(priv->reg_syscon, priv->syscon_offset, >>> +                        priv->syscon_mask, regval); >>> +        if (err) >>> +            return err; >>> +        mci_writel(host, RINTSTS, ALL_INT_CLR); >>> + >>> +        err = mmc_send_tuning(slot->mmc, opcode, NULL); >>> +        if (!err) >>> +            found = 1; >>> + >>> +        if (i > 0) { >>> +            if (err && !prev_err) >>> +                fall_point = i - 1; >>> +            if (!err && prev_err) >>> +                rise_point = i; >>> +        } >>> + >>> +        if (rise_point != -1 && fall_point != -1) >>> +            goto tuning_out; >>> + >>> +        prev_err = err; >>> +        err = 0; >>> +    } >>> + >>> +tuning_out: >>> +    if (found) { >>> +        if (rise_point == -1) >>> +            rise_point = 0; >>> +        if (fall_point == -1) >>> +            fall_point = grade - 1; >>> +        if (fall_point < rise_point) { >>> +            if ((rise_point + fall_point) > >>> +                (grade - 1)) >>> +                i = fall_point / 2; >>> +            else >>> +                i = (rise_point + grade - 1) / 2; >>> +        } else { >>> +            i = (rise_point + fall_point) / 2; >>> +        } >>> + >>> +        regval = i << priv->syscon_shift; >>> +        err = regmap_update_bits(priv->reg_syscon, priv->syscon_offset, >>> +                        priv->syscon_mask, regval); >>> +        if (err) >>> +            return err; >>> +        mci_writel(host, RINTSTS, ALL_INT_CLR); >>> + >>> +        dev_info(host->dev, "Found valid delay chain! use it [delay=%d]\n", i); >>> +    } else { >>> +        dev_err(host->dev, "No valid delay chain! use default\n"); >>> +        err = -EINVAL; >>> +    } >>> + >>> +    mci_writel(host, RINTSTS, ALL_INT_CLR); >>> +    return err; >>> +} >>> + >>> +static int dw_mci_starfive_parse_dt(struct dw_mci *host) >>> +{ >>> +    struct of_phandle_args args; >>> +    struct starfive_priv *priv; >>> +    int ret; >>> + >>> +    priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); >>> +    if (!priv) >>> +        return -ENOMEM; >>> + >>> +    ret = of_parse_phandle_with_fixed_args(host->dev->of_node, >>> +                        "starfive,sysreg", 3, 0, &args); >>> +    if (ret) { >>> +        dev_err(host->dev, "Failed to parse starfive,sysreg\n"); >>> +        return -EINVAL; >>> +    } >>> + >>> +    priv->reg_syscon = syscon_node_to_regmap(args.np); >>> +    of_node_put(args.np); >>> +    if (IS_ERR(priv->reg_syscon)) >>> +        return PTR_ERR(priv->reg_syscon); >>> + >>> +    priv->syscon_offset = args.args[0]; >>> +    priv->syscon_shift  = args.args[1]; >>> +    priv->syscon_mask   = args.args[2]; >>> + >>> +    host->priv = priv; >>> + >>> +    return 0; >>> +} >>> + >>> +static const struct dw_mci_drv_data starfive_data = { >>> +    .common_caps        = MMC_CAP_CMD23, >>> +    .set_ios        = dw_mci_starfive_set_ios, >>> +    .parse_dt        = dw_mci_starfive_parse_dt, >>> +    .execute_tuning        = dw_mci_starfive_execute_tuning, >>> +}; >>> + >>> +static const struct of_device_id dw_mci_starfive_match[] = { >>> +    { .compatible = "starfive,jh7110-mmc", >>> +        .data = &starfive_data }, >>> +    {}, >>> +}; >>> +MODULE_DEVICE_TABLE(of, dw_mci_starfive_match); >>> + >>> +static int dw_mci_starfive_probe(struct platform_device *pdev) >>> +{ >>> +    return dw_mci_pltfm_register(pdev, &starfive_data); >>> +} >>> + >>> +static struct platform_driver dw_mci_starfive_driver = { >>> +    .probe = dw_mci_starfive_probe, >>> +    .remove = dw_mci_pltfm_remove, >>> +    .driver = { >>> +        .name = "dwmmc_starfive", >>> +        .probe_type = PROBE_PREFER_ASYNCHRONOUS, >>> +        .of_match_table = dw_mci_starfive_match, >>> +    }, >>> +}; >>> +module_platform_driver(dw_mci_starfive_driver); >>> + >>> +MODULE_DESCRIPTION("StarFive JH7110 Specific DW-MSHC Driver Extension"); >>> +MODULE_LICENSE("GPL"); >>> +MODULE_ALIAS("platform:dwmmc_starfive"); 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 3D90BC77B60 for ; Fri, 31 Mar 2023 09:34:40 +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-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:From:References:CC:To: Subject:MIME-Version:Date:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=lo8NEdjniPRAOnrXmOhfWQ8x4yoTHFxDjbz/EpFXwng=; b=KKrkHyHoLe1Tfw 1FntEqwWX81Gnq4oChLsKGmorJ0U9G2/E7eh8Y3/broqg9AN9p82Skd02t0F6qG6zoSnLSHKq9/Jm +D5kYLLrs7Cb3YKc7avY/B7AFinrpAy9+V5gDQQ8qqUXrHM0UsGPV9+OWhzDZlXbLmBMkDLarOWfQ wkm7o611faX1UOdITkY/K4MQYzI9y0RU+ZLQmg97oIRN23B8KghJRY9CT7M27HoPYHX1uNT73jllA W8BdBCZBVfD/QOERGNKCd/1+uFnHV0sR4xk+KXlrZv2GfdkaqIcx5Uca6KNTxiaPKbQmCkZfNtthl ejC5KQc7diHMTVt43myQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1piB9U-006hXd-06; Fri, 31 Mar 2023 09:34:32 +0000 Received: from fd01.gateway.ufhost.com ([61.152.239.71]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1piB9O-006hMq-0E for linux-riscv@lists.infradead.org; Fri, 31 Mar 2023 09:34:29 +0000 Received: from EXMBX165.cuchost.com (unknown [175.102.18.54]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "EXMBX165", Issuer "EXMBX165" (not verified)) by fd01.gateway.ufhost.com (Postfix) with ESMTP id 550B524DB8C; Fri, 31 Mar 2023 17:33:27 +0800 (CST) Received: from EXMBX168.cuchost.com (172.16.6.78) by EXMBX165.cuchost.com (172.16.6.75) with Microsoft SMTP Server (TLS) id 15.0.1497.42; Fri, 31 Mar 2023 17:33:27 +0800 Received: from [192.168.120.57] (171.223.208.138) by EXMBX168.cuchost.com (172.16.6.78) with Microsoft SMTP Server (TLS) id 15.0.1497.42; Fri, 31 Mar 2023 17:33:26 +0800 Message-ID: Date: Fri, 31 Mar 2023 17:33:26 +0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.9.0 Subject: Re: [PATCH v4 2/4] mmc: starfive: Add sdio/emmc driver support To: Shengyu Qu , , , CC: Rob Herring , Krzysztof Kozlowski , Jaehoon Chung , Ulf Hansson , References: <20230215113249.47727-1-william.qiu@starfivetech.com> <20230215113249.47727-3-william.qiu@starfivetech.com> Content-Language: en-US From: William Qiu In-Reply-To: X-Originating-IP: [171.223.208.138] X-ClientProxiedBy: EXCAS061.cuchost.com (172.16.6.21) To EXMBX168.cuchost.com (172.16.6.78) X-YovoleRuleAgent: yovoleflag X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230331_023426_589840_0068E259 X-CRM114-Status: GOOD ( 21.92 ) X-BeenThere: linux-riscv@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-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org CgpPbiAyMDIzLzMvMjkgMDowOCwgU2hlbmd5dSBRdSB3cm90ZToKPiBIZWxsbyBXaWxsaWFtLAo+ IAo+IFNvcnJ5IGZvciBtYWtpbmcgbm9pc2UgYWJvdXQgdGhpcywgYnV0IHNlZW1zIGRlbGV0ZWQg dm9sdGFnZSBzd3RpY2ggZnVuY3Rpb24KPiAKPiBkb2Vzbid0IGhlbHAgYWJvdXQgdGhpcy4gQnV0 IHRoZXJlJ3Mgc3RpbGwgYSBwcm9ibGVtIGFib3V0IGVNTUMgc3BlZWQuIEN1cnJlbnRseQo+IAo+ IG9ubHkgYWJvdXQgMjBNQi9zIG1heGltdW0gcmVhZGluZyBzcGVlZCBjb3VsZCBiZSByZWFjaGVk IHdoZW4gdXNpbmcgZU1NQwo+IAo+IG9uIFZGMiwgYW55IGlkZWEgYWJvdXQgdGhpcz8KPiAKPiBC ZXN0IHJlZ2FyZHMsCj4gCj4gU2hlbmd5dQo+IAo+IOWcqCAyMDIzLzMvMjggMDowMSwgU2hlbmd5 dSBRdSDlhpnpgZM6Cj4+IEhlbGxvIFdpbGxpYW0sCj4+Cj4+IEknbSBkaWdnaW5nIGludG8gZG93 bnN0cmVhbSBtbWMgZHJpdmVyIHRoZXNlIGRheXMgYW5kIGZvdW5kIGEgcHJvYmxlbQo+Pgo+PiB0 aGF0IGN1cnJlbnQgdmVyc2lvbiBtYWlubGluZSBkcml2ZXIgZG9lc24ndCBoYXMgYSB2b2x0YWdl IHN3aXRjaCBmdW5jdGlvbiBmb3IKPj4KPj4gaXQuIERvd25zdHJlYW0gb2xkZXIgdmVyc2lvbiBo YXMgb25lIGJ1dCB3YXMgZGVsZXRlZCBpbiB0aGlzIGNvbW1pdCBbMV0uCj4+Cj4+IEl0IHdhcyBk ZWxldGVkIHNpbmNlIHZmMidzIFNEIHNsb3QgZG9lc24ndCBoYXZlIDEuOFYgaW5wdXQgYnV0IGNv bW1pdGVyIGZvcmdvdAo+Pgo+PiB0aGF0IHZmMidzIGVNTUMgc2xvdCBoYXMgYSBwcm9wZXIgMS44 ViBpbnB1dC4KPj4KPj4gU28gY291bGQgeW91IGFkZCB2b2x0YWdlIHN3aXRjaCBmdW5jdGlvbiBm b3IgbWFpbmxpbmU/IEkndmUgbWV0IGEgZU1NQyBzcGVlZAo+Pgo+PiBwcm9ibGVtIHBvc3NpYmx5 IGR1ZSB0byBpdC4KPj4KPj4gQmVzdCByZWdhcmRzLAo+Pgo+PiBTaGVuZ3l1Cj4+CgpIaSBTaGVu Z3l1LAoKU29ycnkgZm9yIHRoZSBsYXRlIHJlcGx5LgoKRmlyc3Qgb2YgYWxsLCBJIHdpbGwgY29u c2lkZXIgYWRkaW5nIHZvbHRhZ2Ugc3dpdGNoIGZ1bmN0aW9uLCBidXQgdGhlIGltcGxlbWVudGF0 aW9uCm1ldGhvZCBpcyB0byBjb25maWd1cmUgdGhlIHBtaWMgcmVnaXN0ZXIgY29uZmlndXJhdGlv biBpbiBkdHMsIGFuZCB0aGUgaW1wbGVtZW50YXRpb24KaW50ZXJmYWNlIHdpbGwgdXNlIHRoZSB2 b2x0YWdlIHN3aXRjaCBmdW5jdGlvbiBpbiBkd19tbWMuYy4KCkFzIGZvciBzcGVlZCwgdGhlIG1h aW4gcmVhc29uIGZvciB0aGUgbG93IHJhdGUgaXMgdGhlIGNsb2NrIG9mIEpINzExMCBhbmQgdGhl CmFzc29jaWF0ZWQgSU8gZHJpdmluZyBzdHJlbmd0aCwgaW4gdGhpcyBsaW1pdCwgdGhlIG1heGlt dW0gcmVhZGluZyBzcGVlZCBJIHRlc3RlZCB3YXMKYWJvdXQgNTBNYi9zLgoKSSB3aWxsIHRyeSB0 byByZXByb2R1Y2UgeW91ciBwcm9ibGVtIGFuZCB0cnkgdG8gc29sdmUgaXQuIFRoYW5rcyBmb3Ig c3VnZ2VzdGlvbnMuCgpCZXN0IHJlZ2FyZHMsCldpbGxpYW0KCj4+IFsxXSBodHRwczovL2dpdGh1 Yi5jb20vc3RhcmZpdmUtdGVjaC9saW51eC9jb21taXQvODAzN2Q1OTA5MWQyNzZlNzRiZTM4ZTVm YWZhYWViZTM2ZWFhNzdlMQo+Pgo+PiDlnKggMjAyMy8yLzE1IDE5OjMyLCBXaWxsaWFtIFFpdSDl hpnpgZM6Cj4+PiBBZGQgc2Rpby9lbW1jIGRyaXZlciBzdXBwb3J0IGZvciBTdGFyRml2ZSBKSDcx MTAgc29jLgo+Pj4KPj4+IFRlc3RlZC1ieTogQ29ub3IgRG9vbGV5IDxjb25vci5kb29sZXlAbWlj cm9jaGlwLmNvbT4KPj4+IFNpZ25lZC1vZmYtYnk6IFdpbGxpYW0gUWl1IDx3aWxsaWFtLnFpdUBz dGFyZml2ZXRlY2guY29tPgo+Pj4gLS0tCj4+PiDCoCBNQUlOVEFJTkVSU8KgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgfMKgwqAgNiArCj4+PiDCoCBkcml2ZXJz L21tYy9ob3N0L0tjb25maWfCoMKgwqDCoMKgwqDCoMKgwqDCoCB8wqAgMTAgKysKPj4+IMKgIGRy aXZlcnMvbW1jL2hvc3QvTWFrZWZpbGXCoMKgwqDCoMKgwqDCoMKgwqAgfMKgwqAgMSArCj4+PiDC oCBkcml2ZXJzL21tYy9ob3N0L2R3X21tYy1zdGFyZml2ZS5jIHwgMTg2ICsrKysrKysrKysrKysr KysrKysrKysrKysrKysrCj4+PiDCoCA0IGZpbGVzIGNoYW5nZWQsIDIwMyBpbnNlcnRpb25zKCsp Cj4+PiDCoCBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9tbWMvaG9zdC9kd19tbWMtc3RhcmZp dmUuYwo+Pj4KPj4+IGRpZmYgLS1naXQgYS9NQUlOVEFJTkVSUyBiL01BSU5UQUlORVJTCj4+PiBp bmRleCA4NWU4ZjgzMTYxZDcuLjY0NGFjOTQ3OWE2ZSAxMDA2NDQKPj4+IC0tLSBhL01BSU5UQUlO RVJTCj4+PiArKysgYi9NQUlOVEFJTkVSUwo+Pj4gQEAgLTE5NjQwLDYgKzE5NjQwLDEyIEBAIEY6 IERvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9jbG9jay9zdGFyZml2ZSxqaDcxKi55 YW1sCj4+PiDCoCBGOsKgwqDCoCBkcml2ZXJzL2Nsay9zdGFyZml2ZS9jbGstc3RhcmZpdmUtamg3 MSoKPj4+IMKgIEY6wqDCoMKgIGluY2x1ZGUvZHQtYmluZGluZ3MvY2xvY2svc3RhcmZpdmU/amg3 MSouaAo+Pj4gwqAgK1NUQVJGSVZFIEpINzExMCBNTUMvU0QvU0RJTyBEUklWRVIKPj4+ICtNOsKg wqDCoCBXaWxsaWFtIFFpdSA8d2lsbGlhbS5xaXVAc3RhcmZpdmV0ZWNoLmNvbT4KPj4+ICtTOsKg wqDCoCBTdXBwb3J0ZWQKPj4+ICtGOsKgwqDCoCBEb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmlu ZGluZ3MvbW1jL3N0YXJmaXZlKgo+Pj4gK0Y6wqDCoMKgIGRyaXZlcnMvbW1jL2hvc3QvZHdfbW1j LXN0YXJmaXZlLmMKPj4+ICsKPj4+IMKgIFNUQVJGSVZFIEpINzFYMCBQSU5DVFJMIERSSVZFUlMK Pj4+IMKgIE06wqDCoMKgIEVtaWwgUmVubmVyIEJlcnRoaW5nIDxrZXJuZWxAZXNtaWwuZGs+Cj4+ PiDCoCBNOsKgwqDCoCBKaWFubG9uZyBIdWFuZyA8amlhbmxvbmcuaHVhbmdAc3RhcmZpdmV0ZWNo LmNvbT4KPj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL21tYy9ob3N0L0tjb25maWcgYi9kcml2ZXJz L21tYy9ob3N0L0tjb25maWcKPj4+IGluZGV4IGZiMTA2MmE2Mzk0Yy4uYjg3MjYyNTAzNDAzIDEw MDY0NAo+Pj4gLS0tIGEvZHJpdmVycy9tbWMvaG9zdC9LY29uZmlnCj4+PiArKysgYi9kcml2ZXJz L21tYy9ob3N0L0tjb25maWcKPj4+IEBAIC04NzEsNiArODcxLDE2IEBAIGNvbmZpZyBNTUNfRFdf Uk9DS0NISVAKPj4+IMKgwqDCoMKgwqDCoMKgIFN5bm9wc3lzIERlc2lnbldhcmUgTWVtb3J5IENh cmQgSW50ZXJmYWNlIGRyaXZlci4gU2VsZWN0IHRoaXMgb3B0aW9uCj4+PiDCoMKgwqDCoMKgwqDC oCBmb3IgcGxhdGZvcm1zIGJhc2VkIG9uIFJLMzA2NiwgUkszMTg4IGFuZCBSSzMyODggU29DJ3Mu Cj4+PiDCoCArY29uZmlnIE1NQ19EV19TVEFSRklWRQo+Pj4gK8KgwqDCoCB0cmlzdGF0ZSAiU3Rh ckZpdmUgc3BlY2lmaWMgZXh0ZW5zaW9ucyBmb3IgU3lub3BzeXMgRFcgTWVtb3J5IENhcmQgSW50 ZXJmYWNlIgo+Pj4gK8KgwqDCoCBkZXBlbmRzIG9uIFNPQ19TVEFSRklWRQo+Pj4gK8KgwqDCoCBk ZXBlbmRzIG9uIE1NQ19EVwo+Pj4gK8KgwqDCoCBzZWxlY3QgTU1DX0RXX1BMVEZNCj4+PiArwqDC oMKgIGhlbHAKPj4+ICvCoMKgwqDCoMKgIFRoaXMgc2VsZWN0cyBzdXBwb3J0IGZvciBTdGFyRml2 ZSBKSDcxMTAgU29DIHNwZWNpZmljIGV4dGVuc2lvbnMgdG8gdGhlCj4+PiArwqDCoMKgwqDCoCBT eW5vcHN5cyBEZXNpZ25XYXJlIE1lbW9yeSBDYXJkIEludGVyZmFjZSBkcml2ZXIuIFNlbGVjdCB0 aGlzIG9wdGlvbgo+Pj4gK8KgwqDCoMKgwqAgZm9yIHBsYXRmb3JtcyBiYXNlZCBvbiBTdGFyRml2 ZSBKSDcxMTAgU29DLgo+Pj4gKwo+Pj4gwqAgY29uZmlnIE1NQ19TSF9NTUNJRgo+Pj4gwqDCoMKg wqDCoCB0cmlzdGF0ZSAiU3VwZXJIIEludGVybmFsIE1NQ0lGIHN1cHBvcnQiCj4+PiDCoMKgwqDC oMKgIGRlcGVuZHMgb24gU1VQRVJIIHx8IEFSQ0hfUkVORVNBUyB8fCBDT01QSUxFX1RFU1QKPj4+ IGRpZmYgLS1naXQgYS9kcml2ZXJzL21tYy9ob3N0L01ha2VmaWxlIGIvZHJpdmVycy9tbWMvaG9z dC9NYWtlZmlsZQo+Pj4gaW5kZXggNGU0Y2ViMzJjNGI0Li4zMmMwZTU1NjRiOWEgMTAwNjQ0Cj4+ PiAtLS0gYS9kcml2ZXJzL21tYy9ob3N0L01ha2VmaWxlCj4+PiArKysgYi9kcml2ZXJzL21tYy9o b3N0L01ha2VmaWxlCj4+PiBAQCAtNTYsNiArNTYsNyBAQCBvYmotJChDT05GSUdfTU1DX0RXX0hJ Mzc5OENWMjAwKSArPSBkd19tbWMtaGkzNzk4Y3YyMDAubwo+Pj4gwqAgb2JqLSQoQ09ORklHX01N Q19EV19LMynCoMKgwqDCoMKgwqDCoCArPSBkd19tbWMtazMubwo+Pj4gwqAgb2JqLSQoQ09ORklH X01NQ19EV19QQ0kpwqDCoMKgICs9IGR3X21tYy1wY2kubwo+Pj4gwqAgb2JqLSQoQ09ORklHX01N Q19EV19ST0NLQ0hJUCnCoMKgwqAgKz0gZHdfbW1jLXJvY2tjaGlwLm8KPj4+ICtvYmotJChDT05G SUdfTU1DX0RXX1NUQVJGSVZFKcKgwqDCoCArPSBkd19tbWMtc3RhcmZpdmUubwo+Pj4gwqAgb2Jq LSQoQ09ORklHX01NQ19TSF9NTUNJRinCoMKgwqAgKz0gc2hfbW1jaWYubwo+Pj4gwqAgb2JqLSQo Q09ORklHX01NQ19KWjQ3NDApwqDCoMKgICs9IGp6NDc0MF9tbWMubwo+Pj4gwqAgb2JqLSQoQ09O RklHX01NQ19WVUIzMDApwqDCoMKgICs9IHZ1YjMwMC5vCj4+PiBkaWZmIC0tZ2l0IGEvZHJpdmVy cy9tbWMvaG9zdC9kd19tbWMtc3RhcmZpdmUuYyBiL2RyaXZlcnMvbW1jL2hvc3QvZHdfbW1jLXN0 YXJmaXZlLmMKPj4+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4+PiBpbmRleCAwMDAwMDAwMDAwMDAu LjQwZjU5NjliMDdhNgo+Pj4gLS0tIC9kZXYvbnVsbAo+Pj4gKysrIGIvZHJpdmVycy9tbWMvaG9z dC9kd19tbWMtc3RhcmZpdmUuYwo+Pj4gQEAgLTAsMCArMSwxODYgQEAKPj4+ICsvLyBTUERYLUxp Y2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAo+Pj4gKy8qCj4+PiArICogU3RhckZpdmUgRGVzaWdu d2FyZSBNb2JpbGUgU3RvcmFnZSBIb3N0IENvbnRyb2xsZXIgRHJpdmVyCj4+PiArICoKPj4+ICsg KiBDb3B5cmlnaHQgKGMpIDIwMjIgU3RhckZpdmUgVGVjaG5vbG9neSBDby4sIEx0ZC4KPj4+ICsg Ki8KPj4+ICsKPj4+ICsjaW5jbHVkZSA8bGludXgvY2xrLmg+Cj4+PiArI2luY2x1ZGUgPGxpbnV4 L2RlbGF5Lmg+Cj4+PiArI2luY2x1ZGUgPGxpbnV4L21mZC9zeXNjb24uaD4KPj4+ICsjaW5jbHVk ZSA8bGludXgvbW1jL2hvc3QuaD4KPj4+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+Cj4+PiAr I2luY2x1ZGUgPGxpbnV4L29mX2FkZHJlc3MuaD4KPj4+ICsjaW5jbHVkZSA8bGludXgvcGxhdGZv cm1fZGV2aWNlLmg+Cj4+PiArI2luY2x1ZGUgPGxpbnV4L3JlZ21hcC5oPgo+Pj4gKwo+Pj4gKyNp bmNsdWRlICJkd19tbWMuaCIKPj4+ICsjaW5jbHVkZSAiZHdfbW1jLXBsdGZtLmgiCj4+PiArCj4+ PiArI2RlZmluZSBBTExfSU5UX0NMUsKgwqDCoMKgwqDCoMKgIDB4MWZmZmYKPj4+ICsjZGVmaW5l IE1BWF9ERUxBWV9DSEFJTsKgwqDCoMKgwqDCoMKgIDMyCj4+PiArCj4+PiArc3RydWN0IHN0YXJm aXZlX3ByaXYgewo+Pj4gK8KgwqDCoCBzdHJ1Y3QgZGV2aWNlICpkZXY7Cj4+PiArwqDCoMKgIHN0 cnVjdCByZWdtYXAgKnJlZ19zeXNjb247Cj4+PiArwqDCoMKgIHUzMiBzeXNjb25fb2Zmc2V0Owo+ Pj4gK8KgwqDCoCB1MzIgc3lzY29uX3NoaWZ0Owo+Pj4gK8KgwqDCoCB1MzIgc3lzY29uX21hc2s7 Cj4+PiArfTsKPj4+ICsKPj4+ICtzdGF0aWMgdm9pZCBkd19tY2lfc3RhcmZpdmVfc2V0X2lvcyhz dHJ1Y3QgZHdfbWNpICpob3N0LCBzdHJ1Y3QgbW1jX2lvcyAqaW9zKQo+Pj4gK3sKPj4+ICvCoMKg wqAgaW50IHJldDsKPj4+ICvCoMKgwqAgdW5zaWduZWQgaW50IGNsb2NrOwo+Pj4gKwo+Pj4gK8Kg wqDCoCBpZiAoaW9zLT50aW1pbmcgPT0gTU1DX1RJTUlOR19NTUNfRERSNTIgfHwgaW9zLT50aW1p bmcgPT0gTU1DX1RJTUlOR19VSFNfRERSNTApIHsKPj4+ICvCoMKgwqDCoMKgwqDCoCBjbG9jayA9 IChpb3MtPmNsb2NrID4gNTAwMDAwMDAgJiYgaW9zLT5jbG9jayA8PSA1MjAwMDAwMCkgPyAxMDAw MDAwMDAgOiBpb3MtPmNsb2NrOwo+Pj4gK8KgwqDCoMKgwqDCoMKgIHJldCA9IGNsa19zZXRfcmF0 ZShob3N0LT5jaXVfY2xrLCBjbG9jayk7Cj4+PiArwqDCoMKgwqDCoMKgwqAgaWYgKHJldCkKPj4+ ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGRldl9kYmcoaG9zdC0+ZGV2LCAiVXNlIGFuIGV4dGVy bmFsIGZyZXF1ZW5jeSBkaXZpZGVyICV1SHpcbiIsIGlvcy0+Y2xvY2spOwo+Pj4gK8KgwqDCoMKg wqDCoMKgIGhvc3QtPmJ1c19oeiA9IGNsa19nZXRfcmF0ZShob3N0LT5jaXVfY2xrKTsKPj4+ICvC oMKgwqAgfSBlbHNlIHsKPj4+ICvCoMKgwqDCoMKgwqDCoCBkZXZfZGJnKGhvc3QtPmRldiwgIlVz aW5nIHRoZSBpbnRlcm5hbCBkaXZpZGVyXG4iKTsKPj4+ICvCoMKgwqAgfQo+Pj4gK30KPj4+ICsK Pj4+ICtzdGF0aWMgaW50IGR3X21jaV9zdGFyZml2ZV9leGVjdXRlX3R1bmluZyhzdHJ1Y3QgZHdf bWNpX3Nsb3QgKnNsb3QsCj4+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgIHUzMiBvcGNvZGUpCj4+PiArewo+Pj4gK8KgwqDCoCBzdGF0aWMgY29uc3Qg aW50IGdyYWRlwqAgPSBNQVhfREVMQVlfQ0hBSU47Cj4+PiArwqDCoMKgIHN0cnVjdCBkd19tY2kg Kmhvc3QgPSBzbG90LT5ob3N0Owo+Pj4gK8KgwqDCoCBzdHJ1Y3Qgc3RhcmZpdmVfcHJpdiAqcHJp diA9IGhvc3QtPnByaXY7Cj4+PiArwqDCoMKgIGludCByaXNlX3BvaW50ID0gLTEsIGZhbGxfcG9p bnQgPSAtMTsKPj4+ICvCoMKgwqAgaW50IGVyciwgcHJldl9lcnI7Cj4+PiArwqDCoMKgIGludCBp Owo+Pj4gK8KgwqDCoCBib29sIGZvdW5kID0gMDsKPj4+ICvCoMKgwqAgdTMyIHJlZ3ZhbDsKPj4+ ICsKPj4+ICvCoMKgwqAgLyoKPj4+ICvCoMKgwqDCoCAqIFVzZSBncmFkZSBhcyB0aGUgbWF4IGRl bGF5IGNoYWluLCBhbmQgdXNlIHRoZSByaXNlX3BvaW50IGFuZAo+Pj4gK8KgwqDCoMKgICogZmFs bF9wb2ludCB0byBlbnN1cmUgdGhlIGJlc3Qgc2FtcGxpbmcgcG9pbnQgb2YgYSBkYXRhIGlucHV0 Cj4+PiArwqDCoMKgwqAgKiBzaWduYWxzLgo+Pj4gK8KgwqDCoMKgICovCj4+PiArwqDCoMKgIGZv ciAoaSA9IDA7IGkgPCBncmFkZTsgaSsrKSB7Cj4+PiArwqDCoMKgwqDCoMKgwqAgcmVndmFsID0g aSA8PCBwcml2LT5zeXNjb25fc2hpZnQ7Cj4+PiArwqDCoMKgwqDCoMKgwqAgZXJyID0gcmVnbWFw X3VwZGF0ZV9iaXRzKHByaXYtPnJlZ19zeXNjb24sIHByaXYtPnN5c2Nvbl9vZmZzZXQsCj4+PiAr wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBwcml2LT5zeXNj b25fbWFzaywgcmVndmFsKTsKPj4+ICvCoMKgwqDCoMKgwqDCoCBpZiAoZXJyKQo+Pj4gK8KgwqDC oMKgwqDCoMKgwqDCoMKgwqAgcmV0dXJuIGVycjsKPj4+ICvCoMKgwqDCoMKgwqDCoCBtY2lfd3Jp dGVsKGhvc3QsIFJJTlRTVFMsIEFMTF9JTlRfQ0xSKTsKPj4+ICsKPj4+ICvCoMKgwqDCoMKgwqDC oCBlcnIgPSBtbWNfc2VuZF90dW5pbmcoc2xvdC0+bW1jLCBvcGNvZGUsIE5VTEwpOwo+Pj4gK8Kg wqDCoMKgwqDCoMKgIGlmICghZXJyKQo+Pj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgZm91bmQg PSAxOwo+Pj4gKwo+Pj4gK8KgwqDCoMKgwqDCoMKgIGlmIChpID4gMCkgewo+Pj4gK8KgwqDCoMKg wqDCoMKgwqDCoMKgwqAgaWYgKGVyciAmJiAhcHJldl9lcnIpCj4+PiArwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgIGZhbGxfcG9pbnQgPSBpIC0gMTsKPj4+ICvCoMKgwqDCoMKgwqDCoMKg wqDCoMKgIGlmICghZXJyICYmIHByZXZfZXJyKQo+Pj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoCByaXNlX3BvaW50ID0gaTsKPj4+ICvCoMKgwqDCoMKgwqDCoCB9Cj4+PiArCj4+PiAr wqDCoMKgwqDCoMKgwqAgaWYgKHJpc2VfcG9pbnQgIT0gLTEgJiYgZmFsbF9wb2ludCAhPSAtMSkK Pj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGdvdG8gdHVuaW5nX291dDsKPj4+ICsKPj4+ICvC oMKgwqDCoMKgwqDCoCBwcmV2X2VyciA9IGVycjsKPj4+ICvCoMKgwqDCoMKgwqDCoCBlcnIgPSAw Owo+Pj4gK8KgwqDCoCB9Cj4+PiArCj4+PiArdHVuaW5nX291dDoKPj4+ICvCoMKgwqAgaWYgKGZv dW5kKSB7Cj4+PiArwqDCoMKgwqDCoMKgwqAgaWYgKHJpc2VfcG9pbnQgPT0gLTEpCj4+PiArwqDC oMKgwqDCoMKgwqDCoMKgwqDCoCByaXNlX3BvaW50ID0gMDsKPj4+ICvCoMKgwqDCoMKgwqDCoCBp ZiAoZmFsbF9wb2ludCA9PSAtMSkKPj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGZhbGxfcG9p bnQgPSBncmFkZSAtIDE7Cj4+PiArwqDCoMKgwqDCoMKgwqAgaWYgKGZhbGxfcG9pbnQgPCByaXNl X3BvaW50KSB7Cj4+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBpZiAoKHJpc2VfcG9pbnQgKyBm YWxsX3BvaW50KSA+Cj4+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIChncmFkZSAt IDEpKQo+Pj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBpID0gZmFsbF9wb2ludCAv IDI7Cj4+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBlbHNlCj4+PiArwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgIGkgPSAocmlzZV9wb2ludCArIGdyYWRlIC0gMSkgLyAyOwo+Pj4gK8Kg wqDCoMKgwqDCoMKgIH0gZWxzZSB7Cj4+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBpID0gKHJp c2VfcG9pbnQgKyBmYWxsX3BvaW50KSAvIDI7Cj4+PiArwqDCoMKgwqDCoMKgwqAgfQo+Pj4gKwo+ Pj4gK8KgwqDCoMKgwqDCoMKgIHJlZ3ZhbCA9IGkgPDwgcHJpdi0+c3lzY29uX3NoaWZ0Owo+Pj4g K8KgwqDCoMKgwqDCoMKgIGVyciA9IHJlZ21hcF91cGRhdGVfYml0cyhwcml2LT5yZWdfc3lzY29u LCBwcml2LT5zeXNjb25fb2Zmc2V0LAo+Pj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqAgcHJpdi0+c3lzY29uX21hc2ssIHJlZ3ZhbCk7Cj4+PiArwqDCoMKg wqDCoMKgwqAgaWYgKGVycikKPj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHJldHVybiBlcnI7 Cj4+PiArwqDCoMKgwqDCoMKgwqAgbWNpX3dyaXRlbChob3N0LCBSSU5UU1RTLCBBTExfSU5UX0NM Uik7Cj4+PiArCj4+PiArwqDCoMKgwqDCoMKgwqAgZGV2X2luZm8oaG9zdC0+ZGV2LCAiRm91bmQg dmFsaWQgZGVsYXkgY2hhaW4hIHVzZSBpdCBbZGVsYXk9JWRdXG4iLCBpKTsKPj4+ICvCoMKgwqAg fSBlbHNlIHsKPj4+ICvCoMKgwqDCoMKgwqDCoCBkZXZfZXJyKGhvc3QtPmRldiwgIk5vIHZhbGlk IGRlbGF5IGNoYWluISB1c2UgZGVmYXVsdFxuIik7Cj4+PiArwqDCoMKgwqDCoMKgwqAgZXJyID0g LUVJTlZBTDsKPj4+ICvCoMKgwqAgfQo+Pj4gKwo+Pj4gK8KgwqDCoCBtY2lfd3JpdGVsKGhvc3Qs IFJJTlRTVFMsIEFMTF9JTlRfQ0xSKTsKPj4+ICvCoMKgwqAgcmV0dXJuIGVycjsKPj4+ICt9Cj4+ PiArCj4+PiArc3RhdGljIGludCBkd19tY2lfc3RhcmZpdmVfcGFyc2VfZHQoc3RydWN0IGR3X21j aSAqaG9zdCkKPj4+ICt7Cj4+PiArwqDCoMKgIHN0cnVjdCBvZl9waGFuZGxlX2FyZ3MgYXJnczsK Pj4+ICvCoMKgwqAgc3RydWN0IHN0YXJmaXZlX3ByaXYgKnByaXY7Cj4+PiArwqDCoMKgIGludCBy ZXQ7Cj4+PiArCj4+PiArwqDCoMKgIHByaXYgPSBkZXZtX2t6YWxsb2MoaG9zdC0+ZGV2LCBzaXpl b2YoKnByaXYpLCBHRlBfS0VSTkVMKTsKPj4+ICvCoMKgwqAgaWYgKCFwcml2KQo+Pj4gK8KgwqDC oMKgwqDCoMKgIHJldHVybiAtRU5PTUVNOwo+Pj4gKwo+Pj4gK8KgwqDCoCByZXQgPSBvZl9wYXJz ZV9waGFuZGxlX3dpdGhfZml4ZWRfYXJncyhob3N0LT5kZXYtPm9mX25vZGUsCj4+PiArwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAic3RhcmZpdmUsc3lzcmVn IiwgMywgMCwgJmFyZ3MpOwo+Pj4gK8KgwqDCoCBpZiAocmV0KSB7Cj4+PiArwqDCoMKgwqDCoMKg wqAgZGV2X2Vycihob3N0LT5kZXYsICJGYWlsZWQgdG8gcGFyc2Ugc3RhcmZpdmUsc3lzcmVnXG4i KTsKPj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gLUVJTlZBTDsKPj4+ICvCoMKgwqAgfQo+Pj4g Kwo+Pj4gK8KgwqDCoCBwcml2LT5yZWdfc3lzY29uID0gc3lzY29uX25vZGVfdG9fcmVnbWFwKGFy Z3MubnApOwo+Pj4gK8KgwqDCoCBvZl9ub2RlX3B1dChhcmdzLm5wKTsKPj4+ICvCoMKgwqAgaWYg KElTX0VSUihwcml2LT5yZWdfc3lzY29uKSkKPj4+ICvCoMKgwqDCoMKgwqDCoCByZXR1cm4gUFRS X0VSUihwcml2LT5yZWdfc3lzY29uKTsKPj4+ICsKPj4+ICvCoMKgwqAgcHJpdi0+c3lzY29uX29m ZnNldCA9IGFyZ3MuYXJnc1swXTsKPj4+ICvCoMKgwqAgcHJpdi0+c3lzY29uX3NoaWZ0wqAgPSBh cmdzLmFyZ3NbMV07Cj4+PiArwqDCoMKgIHByaXYtPnN5c2Nvbl9tYXNrwqDCoCA9IGFyZ3MuYXJn c1syXTsKPj4+ICsKPj4+ICvCoMKgwqAgaG9zdC0+cHJpdiA9IHByaXY7Cj4+PiArCj4+PiArwqDC oMKgIHJldHVybiAwOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGR3X21j aV9kcnZfZGF0YSBzdGFyZml2ZV9kYXRhID0gewo+Pj4gK8KgwqDCoCAuY29tbW9uX2NhcHPCoMKg wqDCoMKgwqDCoCA9IE1NQ19DQVBfQ01EMjMsCj4+PiArwqDCoMKgIC5zZXRfaW9zwqDCoMKgwqDC oMKgwqAgPSBkd19tY2lfc3RhcmZpdmVfc2V0X2lvcywKPj4+ICvCoMKgwqAgLnBhcnNlX2R0wqDC oMKgwqDCoMKgwqAgPSBkd19tY2lfc3RhcmZpdmVfcGFyc2VfZHQsCj4+PiArwqDCoMKgIC5leGVj dXRlX3R1bmluZ8KgwqDCoMKgwqDCoMKgID0gZHdfbWNpX3N0YXJmaXZlX2V4ZWN1dGVfdHVuaW5n LAo+Pj4gK307Cj4+PiArCj4+PiArc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgZHdf bWNpX3N0YXJmaXZlX21hdGNoW10gPSB7Cj4+PiArwqDCoMKgIHsgLmNvbXBhdGlibGUgPSAic3Rh cmZpdmUsamg3MTEwLW1tYyIsCj4+PiArwqDCoMKgwqDCoMKgwqAgLmRhdGEgPSAmc3RhcmZpdmVf ZGF0YSB9LAo+Pj4gK8KgwqDCoCB7fSwKPj4+ICt9Owo+Pj4gK01PRFVMRV9ERVZJQ0VfVEFCTEUo b2YsIGR3X21jaV9zdGFyZml2ZV9tYXRjaCk7Cj4+PiArCj4+PiArc3RhdGljIGludCBkd19tY2lf c3RhcmZpdmVfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKPj4+ICt7Cj4+PiAr wqDCoMKgIHJldHVybiBkd19tY2lfcGx0Zm1fcmVnaXN0ZXIocGRldiwgJnN0YXJmaXZlX2RhdGEp Owo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBkd19tY2lf c3RhcmZpdmVfZHJpdmVyID0gewo+Pj4gK8KgwqDCoCAucHJvYmUgPSBkd19tY2lfc3RhcmZpdmVf cHJvYmUsCj4+PiArwqDCoMKgIC5yZW1vdmUgPSBkd19tY2lfcGx0Zm1fcmVtb3ZlLAo+Pj4gK8Kg wqDCoCAuZHJpdmVyID0gewo+Pj4gK8KgwqDCoMKgwqDCoMKgIC5uYW1lID0gImR3bW1jX3N0YXJm aXZlIiwKPj4+ICvCoMKgwqDCoMKgwqDCoCAucHJvYmVfdHlwZSA9IFBST0JFX1BSRUZFUl9BU1lO Q0hST05PVVMsCj4+PiArwqDCoMKgwqDCoMKgwqAgLm9mX21hdGNoX3RhYmxlID0gZHdfbWNpX3N0 YXJmaXZlX21hdGNoLAo+Pj4gK8KgwqDCoCB9LAo+Pj4gK307Cj4+PiArbW9kdWxlX3BsYXRmb3Jt X2RyaXZlcihkd19tY2lfc3RhcmZpdmVfZHJpdmVyKTsKPj4+ICsKPj4+ICtNT0RVTEVfREVTQ1JJ UFRJT04oIlN0YXJGaXZlIEpINzExMCBTcGVjaWZpYyBEVy1NU0hDIERyaXZlciBFeHRlbnNpb24i KTsKPj4+ICtNT0RVTEVfTElDRU5TRSgiR1BMIik7Cj4+PiArTU9EVUxFX0FMSUFTKCJwbGF0Zm9y bTpkd21tY19zdGFyZml2ZSIpOwoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX18KbGludXgtcmlzY3YgbWFpbGluZyBsaXN0CmxpbnV4LXJpc2N2QGxpc3RzLmlu ZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9s aW51eC1yaXNjdgo=