From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Cyrus-Session-Id: sloti22d1t05-333886-1519830509-2-11434984939246149609 X-Sieve: CMU Sieve 3.0 X-Spam-known-sender: no ("Email failed DMARC policy for domain") X-Spam-score: 0.0 X-Spam-hits: BAYES_00 -1.9, HEADER_FROM_DIFFERENT_DOMAINS 0.249, ME_NOAUTH 0.01, RCVD_IN_DNSWL_HI -5, T_RP_MATCHES_RCVD -0.01, LANGUAGES en, BAYES_USED global, SA_VERSION 3.4.0 X-Spam-source: IP='209.132.180.67', Host='vger.kernel.org', Country='CN', FromHeader='com', MailFrom='org' X-Spam-charsets: X-IgnoreVacation: yes ("Email failed DMARC policy for domain") X-Resolved-to: greg@kroah.com X-Delivered-to: greg@kroah.com X-Mail-from: linux-usb-owner@vger.kernel.org ARC-Seal: i=1; a=rsa-sha256; cv=none; d=messagingengine.com; s=arctest; t=1519830508; b=i9j4wIXNVZGV8DIOLv5iFTAGZeEyBOA5hU8nD0mZW8NmqaC e4DVN/40MKMRvRB10dAAb7NhvO2KYhVDBvWOYBW7AnhljdooPAC756/zNaVHH9Wu jSzKGyYURqBangA+zHsTy+7sDIbau0THCzYMmIOdFA3ZlkHGOX2eK1OwYKLT2ZmS xWDOQKM8QVleVP3XW6pLhD4UmHZlNT9rEtqR4hlWixpK0FKgnacE3yjehHaXn6zt LoKad8AgJi3A67yo9i2hEdPlio8FatAJRdsZlvM+tJGRDEf8XWqfMZP48Y4VOyB6 7LR+TX4U5257/ocM69uD/WdrLeVTj6ekW380M/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=from:to:cc:subject:date:message-id :in-reply-to:references:sender:list-id; s=arctest; t=1519830508; bh=6zwIku9mR7+xog+PCAJwlBSaMZ9BFEe+98neWMKVuFU=; b=IMKQZPCWOpJH cMZvrCsS8tgwhyNhF9AYwHVFaAn1Bva4CRnx0HB1zRA00pQ0LZFShRkS1X3eFAtj a98sS5XAEmJKzTOYh1xMpHOD1TX+m0k69bdPdEA6HDRKLe2BkCu04Z8Yi41xXWjz TTE3gN7sQLUBsj+kfMf4ko8CJNcSkCBm+LgNW4ShIi18xTpkdwy/5/UEa5MvtPju zisyqWtvppk0/s903Cj9YeCxJTZq274ZUSPSWsN5TGM1x9AElioiTg/C9ty1x/in 2b2URxf5G7SyC0xVBwivhwLPRgMGaQ9VvjkMF9Ssq/RtaDaxYIjxWWDkLW/c1uvd 1Cu+qWVKVw== ARC-Authentication-Results: i=1; mx4.messagingengine.com; arc=none (no signatures found); dkim=none (no signatures found); dmarc=fail (p=none,has-list-id=yes,d=none) header.from=redhat.com; iprev=pass policy.iprev=209.132.180.67 (vger.kernel.org); spf=none smtp.mailfrom=linux-usb-owner@vger.kernel.org smtp.helo=vger.kernel.org; x-aligned-from=fail; x-ptr=pass x-ptr-helo=vger.kernel.org x-ptr-lookup=vger.kernel.org; x-return-mx=pass smtp.domain=vger.kernel.org smtp.result=pass smtp_org.domain=kernel.org smtp_org.result=pass smtp_is_org_domain=no header.domain=redhat.com header.result=pass header_is_org_domain=yes Authentication-Results: mx4.messagingengine.com; arc=none (no signatures found); dkim=none (no signatures found); dmarc=fail (p=none,has-list-id=yes,d=none) header.from=redhat.com; iprev=pass policy.iprev=209.132.180.67 (vger.kernel.org); spf=none smtp.mailfrom=linux-usb-owner@vger.kernel.org smtp.helo=vger.kernel.org; x-aligned-from=fail; x-ptr=pass x-ptr-helo=vger.kernel.org x-ptr-lookup=vger.kernel.org; x-return-mx=pass smtp.domain=vger.kernel.org smtp.result=pass smtp_org.domain=kernel.org smtp_org.result=pass smtp_is_org_domain=no header.domain=redhat.com header.result=pass header_is_org_domain=yes Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932538AbeB1PIX (ORCPT ); Wed, 28 Feb 2018 10:08:23 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:58024 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932526AbeB1PIV (ORCPT ); Wed, 28 Feb 2018 10:08:21 -0500 From: Hans de Goede To: Darren Hart , Andy Shevchenko , MyungJoo Ham , Chanwoo Choi , Mathias Nyman , Heikki Krogerus , Greg Kroah-Hartman , Guenter Roeck Cc: Hans de Goede , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Subject: [PATCH v5 12/12] extcon: axp288: Set USB role where necessary Date: Wed, 28 Feb 2018 16:07:49 +0100 Message-Id: <20180228150749.26831-13-hdegoede@redhat.com> In-Reply-To: <20180228150749.26831-1-hdegoede@redhat.com> References: <20180228150749.26831-1-hdegoede@redhat.com> Sender: linux-usb-owner@vger.kernel.org X-Mailing-List: linux-usb@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-Mailing-List: linux-kernel@vger.kernel.org List-ID: The AXP288 BC1.2 charger detection / extcon code may seem like a strange place to add code to control the USB role-switch on devices with an AXP288, but there are 2 reasons to do this inside the axp288 extcon code: 1) On many devices the USB role is controlled by ACPI AML code, but the AML code only switches between the host and none roles, because of Windows not really using device mode. To make device mode work we need to toggle between the none/device roles based on Vbus presence, and the axp288 extcon gets interrupts on Vbus insertion / removal. 2) In order for our BC1.2 charger detection to work properly the role mux must be properly set to device mode before we do the detection. Also note the Kconfig help-text / obsolete depends on USB_PHY which are remnants from older never upstreamed code also controlling the mux from the axp288 extcon code. This commit also adds code to get notifications from the INT3496 extcon device, which is used on some devices to notify the kernel about id-pin changes instead of them being handled through AML code. This fixes: -Device mode not working on most CHT devices with an AXP288 -Host mode not working on devices with an INT3496 ACPI device -Charger-type misdetection (always SDP) on devices with an INT3496 when the USB role (always) gets initialized as host Reviewed-by: Heikki Krogerus Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede --- Changes in v4: -Add Andy's Reviewed-by Changes in v2: -Add depends on X86 to Kconfig (the AXP288 PMIC is only used on X86) -Use new acpi_dev_get_first_match_name() helper to get the INT3496 device-name -Add Heikki's Reviewed-by --- drivers/extcon/Kconfig | 3 +- drivers/extcon/extcon-axp288.c | 177 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 171 insertions(+), 9 deletions(-) diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index a7bca4207f44..de15bf55895b 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -30,7 +30,8 @@ config EXTCON_ARIZONA config EXTCON_AXP288 tristate "X-Power AXP288 EXTCON support" - depends on MFD_AXP20X && USB_PHY + depends on MFD_AXP20X && USB_SUPPORT && X86 + select USB_ROLE_SWITCH help Say Y here to enable support for USB peripheral detection and USB MUX switching by X-Power AXP288 PMIC. diff --git a/drivers/extcon/extcon-axp288.c b/drivers/extcon/extcon-axp288.c index 3ec4c715e240..51e77c7a32c2 100644 --- a/drivers/extcon/extcon-axp288.c +++ b/drivers/extcon/extcon-axp288.c @@ -1,6 +1,7 @@ /* * extcon-axp288.c - X-Power AXP288 PMIC extcon cable detection driver * + * Copyright (c) 2017-2018 Hans de Goede * Copyright (C) 2015 Intel Corporation * Author: Ramakrishna Pallala * @@ -14,6 +15,8 @@ * GNU General Public License for more details. */ +#include +#include #include #include #include @@ -25,6 +28,11 @@ #include #include #include +#include +#include + +#include +#include /* Power source status register */ #define PS_STAT_VBUS_TRIGGER BIT(0) @@ -97,9 +105,19 @@ struct axp288_extcon_info { struct device *dev; struct regmap *regmap; struct regmap_irq_chip_data *regmap_irqc; + struct usb_role_switch *role_sw; + struct work_struct role_work; int irq[EXTCON_IRQ_END]; struct extcon_dev *edev; + struct extcon_dev *id_extcon; + struct notifier_block id_nb; unsigned int previous_cable; + bool vbus_attach; +}; + +static const struct x86_cpu_id cherry_trail_cpu_ids[] = { + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT, X86_FEATURE_ANY }, + {} }; /* Power up/down reason string array */ @@ -137,20 +155,74 @@ static void axp288_extcon_log_rsi(struct axp288_extcon_info *info) regmap_write(info->regmap, AXP288_PS_BOOT_REASON_REG, clear_mask); } -static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info) +/* + * The below code to control the USB role-switch on devices with an AXP288 + * may seem out of place, but there are 2 reasons why this is the best place + * to control the USB role-switch on such devices: + * 1) On many devices the USB role is controlled by AML code, but the AML code + * only switches between the host and none roles, because of Windows not + * really using device mode. To make device mode work we need to toggle + * between the none/device roles based on Vbus presence, and this driver + * gets interrupts on Vbus insertion / removal. + * 2) In order for our BC1.2 charger detection to work properly the role + * mux must be properly set to device mode before we do the detection. + */ + +/* Returns the id-pin value, note pulled low / false == host-mode */ +static bool axp288_get_id_pin(struct axp288_extcon_info *info) { - int ret, stat, cfg, pwr_stat; - u8 chrg_type; - unsigned int cable = info->previous_cable; - bool vbus_attach = false; + enum usb_role role; + + if (info->id_extcon) + return extcon_get_state(info->id_extcon, EXTCON_USB_HOST) <= 0; + + /* We cannot access the id-pin, see what mode the AML code has set */ + role = usb_role_switch_get_role(info->role_sw); + return role != USB_ROLE_HOST; +} + +static void axp288_usb_role_work(struct work_struct *work) +{ + struct axp288_extcon_info *info = + container_of(work, struct axp288_extcon_info, role_work); + enum usb_role role; + bool id_pin; + int ret; + + id_pin = axp288_get_id_pin(info); + if (!id_pin) + role = USB_ROLE_HOST; + else if (info->vbus_attach) + role = USB_ROLE_DEVICE; + else + role = USB_ROLE_NONE; + + ret = usb_role_switch_set_role(info->role_sw, role); + if (ret) + dev_err(info->dev, "failed to set role: %d\n", ret); +} + +static bool axp288_get_vbus_attach(struct axp288_extcon_info *info) +{ + int ret, pwr_stat; ret = regmap_read(info->regmap, AXP288_PS_STAT_REG, &pwr_stat); if (ret < 0) { dev_err(info->dev, "failed to read vbus status\n"); - return ret; + return false; } - vbus_attach = (pwr_stat & PS_STAT_VBUS_VALID); + return !!(pwr_stat & PS_STAT_VBUS_VALID); +} + +static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info) +{ + int ret, stat, cfg; + u8 chrg_type; + unsigned int cable = info->previous_cable; + bool vbus_attach = false; + + vbus_attach = axp288_get_vbus_attach(info); if (!vbus_attach) goto no_vbus; @@ -201,6 +273,12 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info) info->previous_cable = cable; } + if (info->role_sw && info->vbus_attach != vbus_attach) { + info->vbus_attach = vbus_attach; + /* Setting the role can take a while */ + queue_work(system_long_wq, &info->role_work); + } + return 0; dev_det_ret: @@ -210,6 +288,18 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info) return ret; } +static int axp288_extcon_id_evt(struct notifier_block *nb, + unsigned long event, void *param) +{ + struct axp288_extcon_info *info = + container_of(nb, struct axp288_extcon_info, id_nb); + + /* We may not sleep and setting the role can take a while */ + queue_work(system_long_wq, &info->role_work); + + return NOTIFY_OK; +} + static irqreturn_t axp288_extcon_isr(int irq, void *data) { struct axp288_extcon_info *info = data; @@ -231,10 +321,20 @@ static void axp288_extcon_enable(struct axp288_extcon_info *info) BC_GLOBAL_RUN, BC_GLOBAL_RUN); } +static void axp288_put_role_sw(void *data) +{ + struct axp288_extcon_info *info = data; + + cancel_work_sync(&info->role_work); + usb_role_switch_put(info->role_sw); +} + static int axp288_extcon_probe(struct platform_device *pdev) { struct axp288_extcon_info *info; struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + const char *name; int ret, i, pirq; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); @@ -245,9 +345,33 @@ static int axp288_extcon_probe(struct platform_device *pdev) info->regmap = axp20x->regmap; info->regmap_irqc = axp20x->regmap_irqc; info->previous_cable = EXTCON_NONE; + INIT_WORK(&info->role_work, axp288_usb_role_work); + info->id_nb.notifier_call = axp288_extcon_id_evt; platform_set_drvdata(pdev, info); + info->role_sw = usb_role_switch_get(dev); + if (IS_ERR(info->role_sw)) + return PTR_ERR(info->role_sw); + if (info->role_sw) { + ret = devm_add_action_or_reset(dev, axp288_put_role_sw, info); + if (ret) + return ret; + + name = acpi_dev_get_first_match_name("INT3496", NULL, -1); + if (name) { + info->id_extcon = extcon_get_extcon_dev(name); + if (!info->id_extcon) + return -EPROBE_DEFER; + + dev_info(dev, "controlling USB role\n"); + } else { + dev_info(dev, "controlling USB role based on Vbus presence\n"); + } + } + + info->vbus_attach = axp288_get_vbus_attach(info); + axp288_extcon_log_rsi(info); /* Initialize extcon device */ @@ -289,6 +413,19 @@ static int axp288_extcon_probe(struct platform_device *pdev) } } + if (info->id_extcon) { + ret = devm_extcon_register_notifier_all(dev, info->id_extcon, + &info->id_nb); + if (ret) + return ret; + } + + /* Make sure the role-sw is set correctly before doing BC detection */ + if (info->role_sw) { + queue_work(system_long_wq, &info->role_work); + flush_work(&info->role_work); + } + /* Start charger cable type detection */ axp288_extcon_enable(info); @@ -308,8 +445,32 @@ static struct platform_driver axp288_extcon_driver = { .name = "axp288_extcon", }, }; -module_platform_driver(axp288_extcon_driver); + +static struct devcon axp288_extcon_role_sw_conn = { + .endpoint[0] = "axp288_extcon", + .endpoint[1] = "intel_xhci_usb_sw-role-switch", + .id = "usb-role-switch", +}; + +static int __init axp288_extcon_init(void) +{ + if (x86_match_cpu(cherry_trail_cpu_ids)) + add_device_connection(&axp288_extcon_role_sw_conn); + + return platform_driver_register(&axp288_extcon_driver); +} +module_init(axp288_extcon_init); + +static void __exit axp288_extcon_exit(void) +{ + if (x86_match_cpu(cherry_trail_cpu_ids)) + remove_device_connection(&axp288_extcon_role_sw_conn); + + platform_driver_unregister(&axp288_extcon_driver); +} +module_exit(axp288_extcon_exit); MODULE_AUTHOR("Ramakrishna Pallala "); +MODULE_AUTHOR("Hans de Goede "); MODULE_DESCRIPTION("X-Powers AXP288 extcon driver"); MODULE_LICENSE("GPL v2"); -- 2.14.3 From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [v5,12/12] extcon: axp288: Set USB role where necessary From: Hans de Goede Message-Id: <20180228150749.26831-13-hdegoede@redhat.com> Date: Wed, 28 Feb 2018 16:07:49 +0100 To: Darren Hart , Andy Shevchenko , MyungJoo Ham , Chanwoo Choi , Mathias Nyman , Heikki Krogerus , Greg Kroah-Hartman , Guenter Roeck Cc: Hans de Goede , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org List-ID: VGhlIEFYUDI4OCBCQzEuMiBjaGFyZ2VyIGRldGVjdGlvbiAvIGV4dGNvbiBjb2RlIG1heSBzZWVt IGxpa2UgYSBzdHJhbmdlCnBsYWNlIHRvIGFkZCBjb2RlIHRvIGNvbnRyb2wgdGhlIFVTQiByb2xl LXN3aXRjaCBvbiBkZXZpY2VzIHdpdGggYW4gQVhQMjg4LApidXQgdGhlcmUgYXJlIDIgcmVhc29u cyB0byBkbyB0aGlzIGluc2lkZSB0aGUgYXhwMjg4IGV4dGNvbiBjb2RlOgoKMSkgT24gbWFueSBk ZXZpY2VzIHRoZSBVU0Igcm9sZSBpcyBjb250cm9sbGVkIGJ5IEFDUEkgQU1MIGNvZGUsIGJ1dCB0 aGUgQU1MCiAgIGNvZGUgb25seSBzd2l0Y2hlcyBiZXR3ZWVuIHRoZSBob3N0IGFuZCBub25lIHJv bGVzLCBiZWNhdXNlIG9mIFdpbmRvd3MKICAgbm90IHJlYWxseSB1c2luZyBkZXZpY2UgbW9kZS4g VG8gbWFrZSBkZXZpY2UgbW9kZSB3b3JrIHdlIG5lZWQgdG8gdG9nZ2xlCiAgIGJldHdlZW4gdGhl IG5vbmUvZGV2aWNlIHJvbGVzIGJhc2VkIG9uIFZidXMgcHJlc2VuY2UsIGFuZCB0aGUgYXhwMjg4 CiAgIGV4dGNvbiBnZXRzIGludGVycnVwdHMgb24gVmJ1cyBpbnNlcnRpb24gLyByZW1vdmFsLgoK MikgSW4gb3JkZXIgZm9yIG91ciBCQzEuMiBjaGFyZ2VyIGRldGVjdGlvbiB0byB3b3JrIHByb3Bl cmx5IHRoZSByb2xlCiAgIG11eCBtdXN0IGJlIHByb3Blcmx5IHNldCB0byBkZXZpY2UgbW9kZSBi ZWZvcmUgd2UgZG8gdGhlIGRldGVjdGlvbi4KCkFsc28gbm90ZSB0aGUgS2NvbmZpZyBoZWxwLXRl eHQgLyBvYnNvbGV0ZSBkZXBlbmRzIG9uIFVTQl9QSFkgd2hpY2ggYXJlCnJlbW5hbnRzIGZyb20g b2xkZXIgbmV2ZXIgdXBzdHJlYW1lZCBjb2RlIGFsc28gY29udHJvbGxpbmcgdGhlIG11eCBmcm9t CnRoZSBheHAyODggZXh0Y29uIGNvZGUuCgpUaGlzIGNvbW1pdCBhbHNvIGFkZHMgY29kZSB0byBn ZXQgbm90aWZpY2F0aW9ucyBmcm9tIHRoZSBJTlQzNDk2IGV4dGNvbgpkZXZpY2UsIHdoaWNoIGlz IHVzZWQgb24gc29tZSBkZXZpY2VzIHRvIG5vdGlmeSB0aGUga2VybmVsIGFib3V0IGlkLXBpbgpj aGFuZ2VzIGluc3RlYWQgb2YgdGhlbSBiZWluZyBoYW5kbGVkIHRocm91Z2ggQU1MIGNvZGUuCgpU aGlzIGZpeGVzOgotRGV2aWNlIG1vZGUgbm90IHdvcmtpbmcgb24gbW9zdCBDSFQgZGV2aWNlcyB3 aXRoIGFuIEFYUDI4OAotSG9zdCBtb2RlIG5vdCB3b3JraW5nIG9uIGRldmljZXMgd2l0aCBhbiBJ TlQzNDk2IEFDUEkgZGV2aWNlCi1DaGFyZ2VyLXR5cGUgbWlzZGV0ZWN0aW9uIChhbHdheXMgU0RQ KSBvbiBkZXZpY2VzIHdpdGggYW4gSU5UMzQ5NiB3aGVuIHRoZQogVVNCIHJvbGUgKGFsd2F5cykg Z2V0cyBpbml0aWFsaXplZCBhcyBob3N0CgpSZXZpZXdlZC1ieTogSGVpa2tpIEtyb2dlcnVzIDxo ZWlra2kua3JvZ2VydXNAbGludXguaW50ZWwuY29tPgpSZXZpZXdlZC1ieTogQW5keSBTaGV2Y2hl bmtvIDxhbmR5LnNoZXZjaGVua29AZ21haWwuY29tPgpTaWduZWQtb2ZmLWJ5OiBIYW5zIGRlIEdv ZWRlIDxoZGVnb2VkZUByZWRoYXQuY29tPgotLS0KQ2hhbmdlcyBpbiB2NDoKLUFkZCBBbmR5J3Mg UmV2aWV3ZWQtYnkKCkNoYW5nZXMgaW4gdjI6Ci1BZGQgZGVwZW5kcyBvbiBYODYgdG8gS2NvbmZp ZyAodGhlIEFYUDI4OCBQTUlDIGlzIG9ubHkgdXNlZCBvbiBYODYpCi1Vc2UgbmV3IGFjcGlfZGV2 X2dldF9maXJzdF9tYXRjaF9uYW1lKCkgaGVscGVyIHRvIGdldCB0aGUgSU5UMzQ5NiBkZXZpY2Ut bmFtZQotQWRkIEhlaWtraSdzIFJldmlld2VkLWJ5Ci0tLQogZHJpdmVycy9leHRjb24vS2NvbmZp ZyAgICAgICAgIHwgICAzICstCiBkcml2ZXJzL2V4dGNvbi9leHRjb24tYXhwMjg4LmMgfCAxNzcg KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrLS0KIDIgZmlsZXMgY2hhbmdl ZCwgMTcxIGluc2VydGlvbnMoKyksIDkgZGVsZXRpb25zKC0pCgpkaWZmIC0tZ2l0IGEvZHJpdmVy cy9leHRjb24vS2NvbmZpZyBiL2RyaXZlcnMvZXh0Y29uL0tjb25maWcKaW5kZXggYTdiY2E0MjA3 ZjQ0Li5kZTE1YmY1NTg5NWIgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvZXh0Y29uL0tjb25maWcKKysr IGIvZHJpdmVycy9leHRjb24vS2NvbmZpZwpAQCAtMzAsNyArMzAsOCBAQCBjb25maWcgRVhUQ09O X0FSSVpPTkEKIAogY29uZmlnIEVYVENPTl9BWFAyODgKIAl0cmlzdGF0ZSAiWC1Qb3dlciBBWFAy ODggRVhUQ09OIHN1cHBvcnQiCi0JZGVwZW5kcyBvbiBNRkRfQVhQMjBYICYmIFVTQl9QSFkKKwlk ZXBlbmRzIG9uIE1GRF9BWFAyMFggJiYgVVNCX1NVUFBPUlQgJiYgWDg2CisJc2VsZWN0IFVTQl9S T0xFX1NXSVRDSAogCWhlbHAKIAkgIFNheSBZIGhlcmUgdG8gZW5hYmxlIHN1cHBvcnQgZm9yIFVT QiBwZXJpcGhlcmFsIGRldGVjdGlvbgogCSAgYW5kIFVTQiBNVVggc3dpdGNoaW5nIGJ5IFgtUG93 ZXIgQVhQMjg4IFBNSUMuCmRpZmYgLS1naXQgYS9kcml2ZXJzL2V4dGNvbi9leHRjb24tYXhwMjg4 LmMgYi9kcml2ZXJzL2V4dGNvbi9leHRjb24tYXhwMjg4LmMKaW5kZXggM2VjNGM3MTVlMjQwLi41 MWU3N2M3YTMyYzIgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvZXh0Y29uL2V4dGNvbi1heHAyODguYwor KysgYi9kcml2ZXJzL2V4dGNvbi9leHRjb24tYXhwMjg4LmMKQEAgLTEsNiArMSw3IEBACiAvKgog ICogZXh0Y29uLWF4cDI4OC5jIC0gWC1Qb3dlciBBWFAyODggUE1JQyBleHRjb24gY2FibGUgZGV0 ZWN0aW9uIGRyaXZlcgogICoKKyAqIENvcHlyaWdodCAoYykgMjAxNy0yMDE4IEhhbnMgZGUgR29l ZGUgPGhkZWdvZWRlQHJlZGhhdC5jb20+CiAgKiBDb3B5cmlnaHQgKEMpIDIwMTUgSW50ZWwgQ29y cG9yYXRpb24KICAqIEF1dGhvcjogUmFtYWtyaXNobmEgUGFsbGFsYSA8cmFtYWtyaXNobmEucGFs bGFsYUBpbnRlbC5jb20+CiAgKgpAQCAtMTQsNiArMTUsOCBAQAogICogR05VIEdlbmVyYWwgUHVi bGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICAqLwogCisjaW5jbHVkZSA8bGludXgvYWNw aS5oPgorI2luY2x1ZGUgPGxpbnV4L2Nvbm5lY3Rpb24uaD4KICNpbmNsdWRlIDxsaW51eC9tb2R1 bGUuaD4KICNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4KICNpbmNsdWRlIDxsaW51eC9pby5oPgpA QCAtMjUsNiArMjgsMTEgQEAKICNpbmNsdWRlIDxsaW51eC9leHRjb24tcHJvdmlkZXIuaD4KICNp bmNsdWRlIDxsaW51eC9yZWdtYXAuaD4KICNpbmNsdWRlIDxsaW51eC9tZmQvYXhwMjB4Lmg+Cisj aW5jbHVkZSA8bGludXgvdXNiL3JvbGUuaD4KKyNpbmNsdWRlIDxsaW51eC93b3JrcXVldWUuaD4K KworI2luY2x1ZGUgPGFzbS9jcHVfZGV2aWNlX2lkLmg+CisjaW5jbHVkZSA8YXNtL2ludGVsLWZh bWlseS5oPgogCiAvKiBQb3dlciBzb3VyY2Ugc3RhdHVzIHJlZ2lzdGVyICovCiAjZGVmaW5lIFBT X1NUQVRfVkJVU19UUklHR0VSCQlCSVQoMCkKQEAgLTk3LDkgKzEwNSwxOSBAQCBzdHJ1Y3QgYXhw Mjg4X2V4dGNvbl9pbmZvIHsKIAlzdHJ1Y3QgZGV2aWNlICpkZXY7CiAJc3RydWN0IHJlZ21hcCAq cmVnbWFwOwogCXN0cnVjdCByZWdtYXBfaXJxX2NoaXBfZGF0YSAqcmVnbWFwX2lycWM7CisJc3Ry dWN0IHVzYl9yb2xlX3N3aXRjaCAqcm9sZV9zdzsKKwlzdHJ1Y3Qgd29ya19zdHJ1Y3Qgcm9sZV93 b3JrOwogCWludCBpcnFbRVhUQ09OX0lSUV9FTkRdOwogCXN0cnVjdCBleHRjb25fZGV2ICplZGV2 OworCXN0cnVjdCBleHRjb25fZGV2ICppZF9leHRjb247CisJc3RydWN0IG5vdGlmaWVyX2Jsb2Nr IGlkX25iOwogCXVuc2lnbmVkIGludCBwcmV2aW91c19jYWJsZTsKKwlib29sIHZidXNfYXR0YWNo OworfTsKKworc3RhdGljIGNvbnN0IHN0cnVjdCB4ODZfY3B1X2lkIGNoZXJyeV90cmFpbF9jcHVf aWRzW10gPSB7CisJeyBYODZfVkVORE9SX0lOVEVMLCA2LCBJTlRFTF9GQU02X0FUT01fQUlSTU9O VCwgWDg2X0ZFQVRVUkVfQU5ZIH0sCisJe30KIH07CiAKIC8qIFBvd2VyIHVwL2Rvd24gcmVhc29u IHN0cmluZyBhcnJheSAqLwpAQCAtMTM3LDIwICsxNTUsNzQgQEAgc3RhdGljIHZvaWQgYXhwMjg4 X2V4dGNvbl9sb2dfcnNpKHN0cnVjdCBheHAyODhfZXh0Y29uX2luZm8gKmluZm8pCiAJcmVnbWFw X3dyaXRlKGluZm8tPnJlZ21hcCwgQVhQMjg4X1BTX0JPT1RfUkVBU09OX1JFRywgY2xlYXJfbWFz ayk7CiB9CiAKLXN0YXRpYyBpbnQgYXhwMjg4X2hhbmRsZV9jaHJnX2RldF9ldmVudChzdHJ1Y3Qg YXhwMjg4X2V4dGNvbl9pbmZvICppbmZvKQorLyoKKyAqIFRoZSBiZWxvdyBjb2RlIHRvIGNvbnRy b2wgdGhlIFVTQiByb2xlLXN3aXRjaCBvbiBkZXZpY2VzIHdpdGggYW4gQVhQMjg4CisgKiBtYXkg c2VlbSBvdXQgb2YgcGxhY2UsIGJ1dCB0aGVyZSBhcmUgMiByZWFzb25zIHdoeSB0aGlzIGlzIHRo ZSBiZXN0IHBsYWNlCisgKiB0byBjb250cm9sIHRoZSBVU0Igcm9sZS1zd2l0Y2ggb24gc3VjaCBk ZXZpY2VzOgorICogMSkgT24gbWFueSBkZXZpY2VzIHRoZSBVU0Igcm9sZSBpcyBjb250cm9sbGVk IGJ5IEFNTCBjb2RlLCBidXQgdGhlIEFNTCBjb2RlCisgKiAgICBvbmx5IHN3aXRjaGVzIGJldHdl ZW4gdGhlIGhvc3QgYW5kIG5vbmUgcm9sZXMsIGJlY2F1c2Ugb2YgV2luZG93cyBub3QKKyAqICAg IHJlYWxseSB1c2luZyBkZXZpY2UgbW9kZS4gVG8gbWFrZSBkZXZpY2UgbW9kZSB3b3JrIHdlIG5l ZWQgdG8gdG9nZ2xlCisgKiAgICBiZXR3ZWVuIHRoZSBub25lL2RldmljZSByb2xlcyBiYXNlZCBv biBWYnVzIHByZXNlbmNlLCBhbmQgdGhpcyBkcml2ZXIKKyAqICAgIGdldHMgaW50ZXJydXB0cyBv biBWYnVzIGluc2VydGlvbiAvIHJlbW92YWwuCisgKiAyKSBJbiBvcmRlciBmb3Igb3VyIEJDMS4y IGNoYXJnZXIgZGV0ZWN0aW9uIHRvIHdvcmsgcHJvcGVybHkgdGhlIHJvbGUKKyAqICAgIG11eCBt dXN0IGJlIHByb3Blcmx5IHNldCB0byBkZXZpY2UgbW9kZSBiZWZvcmUgd2UgZG8gdGhlIGRldGVj dGlvbi4KKyAqLworCisvKiBSZXR1cm5zIHRoZSBpZC1waW4gdmFsdWUsIG5vdGUgcHVsbGVkIGxv dyAvIGZhbHNlID09IGhvc3QtbW9kZSAqLworc3RhdGljIGJvb2wgYXhwMjg4X2dldF9pZF9waW4o c3RydWN0IGF4cDI4OF9leHRjb25faW5mbyAqaW5mbykKIHsKLQlpbnQgcmV0LCBzdGF0LCBjZmcs IHB3cl9zdGF0OwotCXU4IGNocmdfdHlwZTsKLQl1bnNpZ25lZCBpbnQgY2FibGUgPSBpbmZvLT5w cmV2aW91c19jYWJsZTsKLQlib29sIHZidXNfYXR0YWNoID0gZmFsc2U7CisJZW51bSB1c2Jfcm9s ZSByb2xlOworCisJaWYgKGluZm8tPmlkX2V4dGNvbikKKwkJcmV0dXJuIGV4dGNvbl9nZXRfc3Rh dGUoaW5mby0+aWRfZXh0Y29uLCBFWFRDT05fVVNCX0hPU1QpIDw9IDA7CisKKwkvKiBXZSBjYW5u b3QgYWNjZXNzIHRoZSBpZC1waW4sIHNlZSB3aGF0IG1vZGUgdGhlIEFNTCBjb2RlIGhhcyBzZXQg Ki8KKwlyb2xlID0gdXNiX3JvbGVfc3dpdGNoX2dldF9yb2xlKGluZm8tPnJvbGVfc3cpOworCXJl dHVybiByb2xlICE9IFVTQl9ST0xFX0hPU1Q7Cit9CisKK3N0YXRpYyB2b2lkIGF4cDI4OF91c2Jf cm9sZV93b3JrKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykKK3sKKwlzdHJ1Y3QgYXhwMjg4X2V4 dGNvbl9pbmZvICppbmZvID0KKwkJY29udGFpbmVyX29mKHdvcmssIHN0cnVjdCBheHAyODhfZXh0 Y29uX2luZm8sIHJvbGVfd29yayk7CisJZW51bSB1c2Jfcm9sZSByb2xlOworCWJvb2wgaWRfcGlu OworCWludCByZXQ7CisKKwlpZF9waW4gPSBheHAyODhfZ2V0X2lkX3BpbihpbmZvKTsKKwlpZiAo IWlkX3BpbikKKwkJcm9sZSA9IFVTQl9ST0xFX0hPU1Q7CisJZWxzZSBpZiAoaW5mby0+dmJ1c19h dHRhY2gpCisJCXJvbGUgPSBVU0JfUk9MRV9ERVZJQ0U7CisJZWxzZQorCQlyb2xlID0gVVNCX1JP TEVfTk9ORTsKKworCXJldCA9IHVzYl9yb2xlX3N3aXRjaF9zZXRfcm9sZShpbmZvLT5yb2xlX3N3 LCByb2xlKTsKKwlpZiAocmV0KQorCQlkZXZfZXJyKGluZm8tPmRldiwgImZhaWxlZCB0byBzZXQg cm9sZTogJWRcbiIsIHJldCk7Cit9CisKK3N0YXRpYyBib29sIGF4cDI4OF9nZXRfdmJ1c19hdHRh Y2goc3RydWN0IGF4cDI4OF9leHRjb25faW5mbyAqaW5mbykKK3sKKwlpbnQgcmV0LCBwd3Jfc3Rh dDsKIAogCXJldCA9IHJlZ21hcF9yZWFkKGluZm8tPnJlZ21hcCwgQVhQMjg4X1BTX1NUQVRfUkVH LCAmcHdyX3N0YXQpOwogCWlmIChyZXQgPCAwKSB7CiAJCWRldl9lcnIoaW5mby0+ZGV2LCAiZmFp bGVkIHRvIHJlYWQgdmJ1cyBzdGF0dXNcbiIpOwotCQlyZXR1cm4gcmV0OworCQlyZXR1cm4gZmFs c2U7CiAJfQogCi0JdmJ1c19hdHRhY2ggPSAocHdyX3N0YXQgJiBQU19TVEFUX1ZCVVNfVkFMSUQp OworCXJldHVybiAhIShwd3Jfc3RhdCAmIFBTX1NUQVRfVkJVU19WQUxJRCk7Cit9CisKK3N0YXRp YyBpbnQgYXhwMjg4X2hhbmRsZV9jaHJnX2RldF9ldmVudChzdHJ1Y3QgYXhwMjg4X2V4dGNvbl9p bmZvICppbmZvKQoreworCWludCByZXQsIHN0YXQsIGNmZzsKKwl1OCBjaHJnX3R5cGU7CisJdW5z aWduZWQgaW50IGNhYmxlID0gaW5mby0+cHJldmlvdXNfY2FibGU7CisJYm9vbCB2YnVzX2F0dGFj aCA9IGZhbHNlOworCisJdmJ1c19hdHRhY2ggPSBheHAyODhfZ2V0X3ZidXNfYXR0YWNoKGluZm8p OwogCWlmICghdmJ1c19hdHRhY2gpCiAJCWdvdG8gbm9fdmJ1czsKIApAQCAtMjAxLDYgKzI3Mywx MiBAQCBzdGF0aWMgaW50IGF4cDI4OF9oYW5kbGVfY2hyZ19kZXRfZXZlbnQoc3RydWN0IGF4cDI4 OF9leHRjb25faW5mbyAqaW5mbykKIAkJaW5mby0+cHJldmlvdXNfY2FibGUgPSBjYWJsZTsKIAl9 CiAKKwlpZiAoaW5mby0+cm9sZV9zdyAmJiBpbmZvLT52YnVzX2F0dGFjaCAhPSB2YnVzX2F0dGFj aCkgeworCQlpbmZvLT52YnVzX2F0dGFjaCA9IHZidXNfYXR0YWNoOworCQkvKiBTZXR0aW5nIHRo ZSByb2xlIGNhbiB0YWtlIGEgd2hpbGUgKi8KKwkJcXVldWVfd29yayhzeXN0ZW1fbG9uZ193cSwg JmluZm8tPnJvbGVfd29yayk7CisJfQorCiAJcmV0dXJuIDA7CiAKIGRldl9kZXRfcmV0OgpAQCAt MjEwLDYgKzI4OCwxOCBAQCBzdGF0aWMgaW50IGF4cDI4OF9oYW5kbGVfY2hyZ19kZXRfZXZlbnQo c3RydWN0IGF4cDI4OF9leHRjb25faW5mbyAqaW5mbykKIAlyZXR1cm4gcmV0OwogfQogCitzdGF0 aWMgaW50IGF4cDI4OF9leHRjb25faWRfZXZ0KHN0cnVjdCBub3RpZmllcl9ibG9jayAqbmIsCisJ CQkJdW5zaWduZWQgbG9uZyBldmVudCwgdm9pZCAqcGFyYW0pCit7CisJc3RydWN0IGF4cDI4OF9l eHRjb25faW5mbyAqaW5mbyA9CisJCWNvbnRhaW5lcl9vZihuYiwgc3RydWN0IGF4cDI4OF9leHRj b25faW5mbywgaWRfbmIpOworCisJLyogV2UgbWF5IG5vdCBzbGVlcCBhbmQgc2V0dGluZyB0aGUg cm9sZSBjYW4gdGFrZSBhIHdoaWxlICovCisJcXVldWVfd29yayhzeXN0ZW1fbG9uZ193cSwgJmlu Zm8tPnJvbGVfd29yayk7CisKKwlyZXR1cm4gTk9USUZZX09LOworfQorCiBzdGF0aWMgaXJxcmV0 dXJuX3QgYXhwMjg4X2V4dGNvbl9pc3IoaW50IGlycSwgdm9pZCAqZGF0YSkKIHsKIAlzdHJ1Y3Qg YXhwMjg4X2V4dGNvbl9pbmZvICppbmZvID0gZGF0YTsKQEAgLTIzMSwxMCArMzIxLDIwIEBAIHN0 YXRpYyB2b2lkIGF4cDI4OF9leHRjb25fZW5hYmxlKHN0cnVjdCBheHAyODhfZXh0Y29uX2luZm8g KmluZm8pCiAJCQkJCUJDX0dMT0JBTF9SVU4sIEJDX0dMT0JBTF9SVU4pOwogfQogCitzdGF0aWMg dm9pZCBheHAyODhfcHV0X3JvbGVfc3codm9pZCAqZGF0YSkKK3sKKwlzdHJ1Y3QgYXhwMjg4X2V4 dGNvbl9pbmZvICppbmZvID0gZGF0YTsKKworCWNhbmNlbF93b3JrX3N5bmMoJmluZm8tPnJvbGVf d29yayk7CisJdXNiX3JvbGVfc3dpdGNoX3B1dChpbmZvLT5yb2xlX3N3KTsKK30KKwogc3RhdGlj IGludCBheHAyODhfZXh0Y29uX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCiB7 CiAJc3RydWN0IGF4cDI4OF9leHRjb25faW5mbyAqaW5mbzsKIAlzdHJ1Y3QgYXhwMjB4X2RldiAq YXhwMjB4ID0gZGV2X2dldF9kcnZkYXRhKHBkZXYtPmRldi5wYXJlbnQpOworCXN0cnVjdCBkZXZp Y2UgKmRldiA9ICZwZGV2LT5kZXY7CisJY29uc3QgY2hhciAqbmFtZTsKIAlpbnQgcmV0LCBpLCBw aXJxOwogCiAJaW5mbyA9IGRldm1fa3phbGxvYygmcGRldi0+ZGV2LCBzaXplb2YoKmluZm8pLCBH RlBfS0VSTkVMKTsKQEAgLTI0NSw5ICszNDUsMzMgQEAgc3RhdGljIGludCBheHAyODhfZXh0Y29u X3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCiAJaW5mby0+cmVnbWFwID0gYXhw MjB4LT5yZWdtYXA7CiAJaW5mby0+cmVnbWFwX2lycWMgPSBheHAyMHgtPnJlZ21hcF9pcnFjOwog CWluZm8tPnByZXZpb3VzX2NhYmxlID0gRVhUQ09OX05PTkU7CisJSU5JVF9XT1JLKCZpbmZvLT5y b2xlX3dvcmssIGF4cDI4OF91c2Jfcm9sZV93b3JrKTsKKwlpbmZvLT5pZF9uYi5ub3RpZmllcl9j YWxsID0gYXhwMjg4X2V4dGNvbl9pZF9ldnQ7CiAKIAlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2 LCBpbmZvKTsKIAorCWluZm8tPnJvbGVfc3cgPSB1c2Jfcm9sZV9zd2l0Y2hfZ2V0KGRldik7CisJ aWYgKElTX0VSUihpbmZvLT5yb2xlX3N3KSkKKwkJcmV0dXJuIFBUUl9FUlIoaW5mby0+cm9sZV9z dyk7CisJaWYgKGluZm8tPnJvbGVfc3cpIHsKKwkJcmV0ID0gZGV2bV9hZGRfYWN0aW9uX29yX3Jl c2V0KGRldiwgYXhwMjg4X3B1dF9yb2xlX3N3LCBpbmZvKTsKKwkJaWYgKHJldCkKKwkJCXJldHVy biByZXQ7CisKKwkJbmFtZSA9IGFjcGlfZGV2X2dldF9maXJzdF9tYXRjaF9uYW1lKCJJTlQzNDk2 IiwgTlVMTCwgLTEpOworCQlpZiAobmFtZSkgeworCQkJaW5mby0+aWRfZXh0Y29uID0gZXh0Y29u X2dldF9leHRjb25fZGV2KG5hbWUpOworCQkJaWYgKCFpbmZvLT5pZF9leHRjb24pCisJCQkJcmV0 dXJuIC1FUFJPQkVfREVGRVI7CisKKwkJCWRldl9pbmZvKGRldiwgImNvbnRyb2xsaW5nIFVTQiBy b2xlXG4iKTsKKwkJfSBlbHNlIHsKKwkJCWRldl9pbmZvKGRldiwgImNvbnRyb2xsaW5nIFVTQiBy b2xlIGJhc2VkIG9uIFZidXMgcHJlc2VuY2VcbiIpOworCQl9CisJfQorCisJaW5mby0+dmJ1c19h dHRhY2ggPSBheHAyODhfZ2V0X3ZidXNfYXR0YWNoKGluZm8pOworCiAJYXhwMjg4X2V4dGNvbl9s b2dfcnNpKGluZm8pOwogCiAJLyogSW5pdGlhbGl6ZSBleHRjb24gZGV2aWNlICovCkBAIC0yODks NiArNDEzLDE5IEBAIHN0YXRpYyBpbnQgYXhwMjg4X2V4dGNvbl9wcm9iZShzdHJ1Y3QgcGxhdGZv cm1fZGV2aWNlICpwZGV2KQogCQl9CiAJfQogCisJaWYgKGluZm8tPmlkX2V4dGNvbikgeworCQly ZXQgPSBkZXZtX2V4dGNvbl9yZWdpc3Rlcl9ub3RpZmllcl9hbGwoZGV2LCBpbmZvLT5pZF9leHRj b24sCisJCQkJCQkJJmluZm8tPmlkX25iKTsKKwkJaWYgKHJldCkKKwkJCXJldHVybiByZXQ7CisJ fQorCisJLyogTWFrZSBzdXJlIHRoZSByb2xlLXN3IGlzIHNldCBjb3JyZWN0bHkgYmVmb3JlIGRv aW5nIEJDIGRldGVjdGlvbiAqLworCWlmIChpbmZvLT5yb2xlX3N3KSB7CisJCXF1ZXVlX3dvcmso c3lzdGVtX2xvbmdfd3EsICZpbmZvLT5yb2xlX3dvcmspOworCQlmbHVzaF93b3JrKCZpbmZvLT5y b2xlX3dvcmspOworCX0KKwogCS8qIFN0YXJ0IGNoYXJnZXIgY2FibGUgdHlwZSBkZXRlY3Rpb24g Ki8KIAlheHAyODhfZXh0Y29uX2VuYWJsZShpbmZvKTsKIApAQCAtMzA4LDggKzQ0NSwzMiBAQCBz dGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBheHAyODhfZXh0Y29uX2RyaXZlciA9IHsKIAkJ Lm5hbWUgPSAiYXhwMjg4X2V4dGNvbiIsCiAJfSwKIH07Ci1tb2R1bGVfcGxhdGZvcm1fZHJpdmVy KGF4cDI4OF9leHRjb25fZHJpdmVyKTsKKworc3RhdGljIHN0cnVjdCBkZXZjb24gYXhwMjg4X2V4 dGNvbl9yb2xlX3N3X2Nvbm4gPSB7CisJLmVuZHBvaW50WzBdID0gImF4cDI4OF9leHRjb24iLAor CS5lbmRwb2ludFsxXSA9ICJpbnRlbF94aGNpX3VzYl9zdy1yb2xlLXN3aXRjaCIsCisJLmlkID0g InVzYi1yb2xlLXN3aXRjaCIsCit9OworCitzdGF0aWMgaW50IF9faW5pdCBheHAyODhfZXh0Y29u X2luaXQodm9pZCkKK3sKKwlpZiAoeDg2X21hdGNoX2NwdShjaGVycnlfdHJhaWxfY3B1X2lkcykp CisJCWFkZF9kZXZpY2VfY29ubmVjdGlvbigmYXhwMjg4X2V4dGNvbl9yb2xlX3N3X2Nvbm4pOwor CisJcmV0dXJuIHBsYXRmb3JtX2RyaXZlcl9yZWdpc3RlcigmYXhwMjg4X2V4dGNvbl9kcml2ZXIp OworfQorbW9kdWxlX2luaXQoYXhwMjg4X2V4dGNvbl9pbml0KTsKKworc3RhdGljIHZvaWQgX19l eGl0IGF4cDI4OF9leHRjb25fZXhpdCh2b2lkKQoreworCWlmICh4ODZfbWF0Y2hfY3B1KGNoZXJy eV90cmFpbF9jcHVfaWRzKSkKKwkJcmVtb3ZlX2RldmljZV9jb25uZWN0aW9uKCZheHAyODhfZXh0 Y29uX3JvbGVfc3dfY29ubik7CisKKwlwbGF0Zm9ybV9kcml2ZXJfdW5yZWdpc3RlcigmYXhwMjg4 X2V4dGNvbl9kcml2ZXIpOworfQorbW9kdWxlX2V4aXQoYXhwMjg4X2V4dGNvbl9leGl0KTsKIAog TU9EVUxFX0FVVEhPUigiUmFtYWtyaXNobmEgUGFsbGFsYSA8cmFtYWtyaXNobmEucGFsbGFsYUBp bnRlbC5jb20+Iik7CitNT0RVTEVfQVVUSE9SKCJIYW5zIGRlIEdvZWRlIDxoZGVnb2VkZUByZWRo YXQuY29tPiIpOwogTU9EVUxFX0RFU0NSSVBUSU9OKCJYLVBvd2VycyBBWFAyODggZXh0Y29uIGRy aXZlciIpOwogTU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIpOwo=