From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752531AbeENWlN (ORCPT ); Mon, 14 May 2018 18:41:13 -0400 Received: from mail-lf0-f66.google.com ([209.85.215.66]:39646 "EHLO mail-lf0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752446AbeENWkv (ORCPT ); Mon, 14 May 2018 18:40:51 -0400 X-Google-Smtp-Source: AB8JxZqmcMtMvvnCzN9nUcWgSBjeiCpwj6pEFKan6fM8l/XU8KUHRGCTfxET607UXNFt4zjvcN+LxQ== From: Neil Armstrong To: airlied@linux.ie, hans.verkuil@cisco.com, lee.jones@linaro.org, olof@lixom.net, seanpaul@google.com Cc: Neil Armstrong , sadolfsson@google.com, felixe@google.com, bleung@google.com, darekm@google.com, marcheu@chromium.org, fparent@baylibre.com, dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 5/5] media: platform: Add Chrome OS EC CEC driver Date: Tue, 15 May 2018 00:40:39 +0200 Message-Id: <1526337639-3568-6-git-send-email-narmstrong@baylibre.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1526337639-3568-1-git-send-email-narmstrong@baylibre.com> References: <1526337639-3568-1-git-send-email-narmstrong@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The Chrome OS Embedded Controller can expose a CEC bus, this patch add the driver for such feature of the Embedded Controller. This driver is part of the cros-ec MFD and will be add as a sub-device when the feature bit is exposed by the EC. The controller will only handle a single logical address and handles all the messages retries and will only expose Success or Error. When the logical address is invalid, the controller will act as a CEC sniffer and transfer all messages on the bus. Signed-off-by: Neil Armstrong --- drivers/media/platform/Kconfig | 11 + drivers/media/platform/Makefile | 2 + drivers/media/platform/cros-ec/Makefile | 1 + drivers/media/platform/cros-ec/cros-ec-cec.c | 331 +++++++++++++++++++++++++++ 4 files changed, 345 insertions(+) create mode 100644 drivers/media/platform/cros-ec/Makefile create mode 100644 drivers/media/platform/cros-ec/cros-ec-cec.c diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index c7a1cf8..e55a8ed2 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -546,6 +546,17 @@ menuconfig CEC_PLATFORM_DRIVERS if CEC_PLATFORM_DRIVERS +config VIDEO_CROS_EC_CEC + tristate "Chrome OS EC CEC driver" + depends on MFD_CROS_EC || COMPILE_TEST + select CEC_CORE + select CEC_NOTIFIER + ---help--- + If you say yes here you will get support for the + Chrome OS Embedded Controller's CEC. + The CEC bus is present in the HDMI connector and enables communication + between compatible devices. + config VIDEO_MESON_AO_CEC tristate "Amlogic Meson AO CEC driver" depends on ARCH_MESON || COMPILE_TEST diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index 932515d..0e0582e 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -92,3 +92,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss-8x16/ obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/ obj-y += meson/ + +obj-y += cros-ec/ diff --git a/drivers/media/platform/cros-ec/Makefile b/drivers/media/platform/cros-ec/Makefile new file mode 100644 index 0000000..9ce97f9 --- /dev/null +++ b/drivers/media/platform/cros-ec/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_VIDEO_CROS_EC_CEC) += cros-ec-cec.o diff --git a/drivers/media/platform/cros-ec/cros-ec-cec.c b/drivers/media/platform/cros-ec/cros-ec-cec.c new file mode 100644 index 0000000..fea90da --- /dev/null +++ b/drivers/media/platform/cros-ec/cros-ec-cec.c @@ -0,0 +1,331 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * CEC driver for Chrome OS Embedded Controller + * + * Copyright (c) 2018 BayLibre, SAS + * Author: Neil Armstrong + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "cros-ec-cec" + +/** + * struct cros_ec_cec - Driver data for EC CEC + * + * @cros_ec: Pointer to EC device + * @notifier: Notifier info for responding to EC events + * @adap: CEC adapter + * @notify: CEC notifier pointer + * @rc_msg: storage for a received message + */ +struct cros_ec_cec { + struct cros_ec_device *cros_ec; + struct notifier_block notifier; + struct cec_adapter *adap; + struct cec_notifier *notify; + struct cec_msg rx_msg; +}; + +static void handle_cec_message(struct cros_ec_cec *cros_ec_cec) +{ + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; + uint8_t *cec_message = cros_ec->event_data.data.cec_message; + unsigned int len = cros_ec->event_size; + + cros_ec_cec->rx_msg.len = len; + memcpy(cros_ec_cec->rx_msg.msg, cec_message, len); + + cec_received_msg(cros_ec_cec->adap, &cros_ec_cec->rx_msg); +} + +static void handle_cec_event(struct cros_ec_cec *cros_ec_cec) +{ + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; + uint32_t events = cros_ec->event_data.data.cec_events; + + if (events & EC_MKBP_CEC_SEND_OK) + cec_transmit_attempt_done(cros_ec_cec->adap, + CEC_TX_STATUS_OK); + + if (events & EC_MKBP_CEC_SEND_FAILED) + cec_transmit_attempt_done(cros_ec_cec->adap, + CEC_TX_STATUS_ERROR); +} + +static int cros_ec_cec_event(struct notifier_block *nb, + unsigned long queued_during_suspend, void *_notify) +{ + struct cros_ec_cec *cros_ec_cec; + struct cros_ec_device *cros_ec; + + cros_ec_cec = container_of(nb, struct cros_ec_cec, notifier); + cros_ec = cros_ec_cec->cros_ec; + + if (cros_ec->event_data.event_type == EC_MKBP_CEC_EVENT) { + handle_cec_event(cros_ec_cec); + return NOTIFY_OK; + } + + if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_MESSAGE) { + handle_cec_message(cros_ec_cec); + return NOTIFY_OK; + } + + return NOTIFY_DONE; +} + +static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr) +{ + struct cros_ec_cec *cros_ec_cec = adap->priv; + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; + struct { + struct cros_ec_command msg; + struct ec_params_cec_set data; + } __packed msg; + int ret = 0; + + if (logical_addr == CEC_LOG_ADDR_INVALID) + return 0; + + memset(&msg, 0, sizeof(msg)); + msg.msg.command = EC_CMD_CEC_SET; + msg.msg.outsize = sizeof(msg.data); + msg.data.cmd = CEC_CMD_LOGICAL_ADDRESS; + msg.data.address = logical_addr; + + ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); + if (ret < 0) { + dev_err(cros_ec->dev, + "error setting CEC logical address on EC: %d\n", ret); + return ret; + } + + return 0; +} + +static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts, + u32 signal_free_time, struct cec_msg *cec_msg) +{ + struct cros_ec_cec *cros_ec_cec = adap->priv; + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; + struct { + struct cros_ec_command msg; + struct ec_params_cec_write data; + } __packed msg; + int ret = 0; + + if (cec_msg->len > MAX_CEC_MSG_LEN) + return -EINVAL; + + memset(&msg, 0, sizeof(msg)); + msg.msg.command = EC_CMD_CEC_WRITE_MSG; + msg.msg.outsize = cec_msg->len; + memcpy(msg.data.msg, cec_msg->msg, cec_msg->len); + + ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); + if (ret < 0) { + dev_err(cros_ec->dev, + "error writting CEC msg on EC: %d\n", ret); + return ret; + } + + return 0; +} + +static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable) +{ + struct cros_ec_cec *cros_ec_cec = adap->priv; + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; + struct { + struct cros_ec_command msg; + struct ec_params_cec_set data; + } __packed msg; + int ret = 0; + + memset(&msg, 0, sizeof(msg)); + msg.msg.command = EC_CMD_CEC_SET; + msg.msg.outsize = sizeof(msg.data); + msg.data.cmd = CEC_CMD_ENABLE; + msg.data.enable = enable; + + ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); + if (ret < 0) { + dev_err(cros_ec->dev, + "error %sabling CEC on EC: %d\n", + (enable ? "en" : "dis"), ret); + return ret; + } + + return 0; +} + +static const struct cec_adap_ops cros_ec_cec_ops = { + .adap_enable = cros_ec_cec_adap_enable, + .adap_log_addr = cros_ec_cec_set_log_addr, + .adap_transmit = cros_ec_cec_transmit, +}; + +#ifdef CONFIG_PM_SLEEP +static int cros_ec_cec_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev); + + if (device_may_wakeup(dev)) + enable_irq_wake(cros_ec_cec->cros_ec->irq); + + return 0; +} + +static int cros_ec_cec_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev); + + if (device_may_wakeup(dev)) + disable_irq_wake(cros_ec_cec->cros_ec->irq); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops, + cros_ec_cec_suspend, cros_ec_cec_resume); + + +struct cec_dmi_match { + char *sys_vendor; + char *product_name; + char *devname; + char *conn; +}; + +static const struct cec_dmi_match cec_dmi_match_table[] = { + /* Google Fizz */ + { "Google", "Fizz", "0000:00:02.0", "HDMI-A-1" }, +}; + +static int cros_ec_cec_get_notifier(struct cec_notifier **notify) +{ + int i; + + for (i = 0 ; i < ARRAY_SIZE(cec_dmi_match_table) ; ++i) { + const struct cec_dmi_match *m = &cec_dmi_match_table[i]; + + if (dmi_match(DMI_SYS_VENDOR, m->sys_vendor) && + dmi_match(DMI_PRODUCT_NAME, m->product_name)) { + *notify = cec_notifier_get_byname(m->devname, m->conn); + return 0; + } + } + + return -EINVAL; +} + +static int cros_ec_cec_probe(struct platform_device *pdev) +{ + struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent); + struct cros_ec_device *cros_ec = ec_dev->ec_dev; + struct cros_ec_cec *cros_ec_cec; + unsigned int cec_caps = CEC_CAP_DEFAULTS; + int ret; + + cros_ec_cec = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_cec), + GFP_KERNEL); + if (!cros_ec_cec) + return -ENOMEM; + + platform_set_drvdata(pdev, cros_ec_cec); + cros_ec_cec->cros_ec = cros_ec; + + ret = cros_ec_cec_get_notifier(&cros_ec_cec->notify); + if (ret) { + dev_warn(&pdev->dev, "no CEC notifier available\n"); + cec_caps |= CEC_CAP_PHYS_ADDR; + } else if (!cros_ec_cec->notify) { + return -EPROBE_DEFER; + } + + ret = device_init_wakeup(&pdev->dev, 1); + if (ret) { + dev_err(&pdev->dev, "failed to initialize wakeup\n"); + return ret; + } + + cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec, + DRV_NAME, cec_caps, 1); + if (IS_ERR(cros_ec_cec->adap)) + return PTR_ERR(cros_ec_cec->adap); + + cros_ec_cec->adap->owner = THIS_MODULE; + + /* Get CEC events from the EC. */ + cros_ec_cec->notifier.notifier_call = cros_ec_cec_event; + ret = blocking_notifier_chain_register(&cros_ec->event_notifier, + &cros_ec_cec->notifier); + if (ret) { + dev_err(&pdev->dev, "failed to register notifier\n"); + cec_delete_adapter(cros_ec_cec->adap); + return ret; + } + + ret = cec_register_adapter(cros_ec_cec->adap, &pdev->dev); + if (ret < 0) { + cec_delete_adapter(cros_ec_cec->adap); + return ret; + } + + cec_register_cec_notifier(cros_ec_cec->adap, cros_ec_cec->notify); + + return 0; +} + +static int cros_ec_cec_remove(struct platform_device *pdev) +{ + struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + int ret; + + ret = blocking_notifier_chain_unregister( + &cros_ec_cec->cros_ec->event_notifier, + &cros_ec_cec->notifier); + + if (ret) { + dev_err(dev, "failed to unregister notifier\n"); + return ret; + } + + cec_unregister_adapter(cros_ec_cec->adap); + + if (cros_ec_cec->notify) + cec_notifier_put(cros_ec_cec->notify); + + return 0; +} + +static struct platform_driver cros_ec_cec_driver = { + .probe = cros_ec_cec_probe, + .remove = cros_ec_cec_remove, + .driver = { + .name = DRV_NAME, + .pm = &cros_ec_cec_pm_ops, + }, +}; + +module_platform_driver(cros_ec_cec_driver); + +MODULE_DESCRIPTION("CEC driver for Chrome OS ECs"); +MODULE_AUTHOR("Neil Armstrong "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); -- 2.7.4 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Neil Armstrong Subject: [RFC PATCH 5/5] media: platform: Add Chrome OS EC CEC driver Date: Tue, 15 May 2018 00:40:39 +0200 Message-ID: <1526337639-3568-6-git-send-email-narmstrong@baylibre.com> References: <1526337639-3568-1-git-send-email-narmstrong@baylibre.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <1526337639-3568-1-git-send-email-narmstrong@baylibre.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To: airlied@linux.ie, hans.verkuil@cisco.com, lee.jones@linaro.org, olof@lixom.net, seanpaul@google.com Cc: Neil Armstrong , sadolfsson@google.com, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, fparent@baylibre.com, felixe@google.com, bleung@google.com, darekm@google.com, linux-media@vger.kernel.org List-Id: dri-devel@lists.freedesktop.org VGhlIENocm9tZSBPUyBFbWJlZGRlZCBDb250cm9sbGVyIGNhbiBleHBvc2UgYSBDRUMgYnVzLCB0 aGlzIHBhdGNoIGFkZCB0aGUKZHJpdmVyIGZvciBzdWNoIGZlYXR1cmUgb2YgdGhlIEVtYmVkZGVk IENvbnRyb2xsZXIuCgpUaGlzIGRyaXZlciBpcyBwYXJ0IG9mIHRoZSBjcm9zLWVjIE1GRCBhbmQg d2lsbCBiZSBhZGQgYXMgYSBzdWItZGV2aWNlIHdoZW4KdGhlIGZlYXR1cmUgYml0IGlzIGV4cG9z ZWQgYnkgdGhlIEVDLgoKVGhlIGNvbnRyb2xsZXIgd2lsbCBvbmx5IGhhbmRsZSBhIHNpbmdsZSBs b2dpY2FsIGFkZHJlc3MgYW5kIGhhbmRsZXMKYWxsIHRoZSBtZXNzYWdlcyByZXRyaWVzIGFuZCB3 aWxsIG9ubHkgZXhwb3NlIFN1Y2Nlc3Mgb3IgRXJyb3IuCgpXaGVuIHRoZSBsb2dpY2FsIGFkZHJl c3MgaXMgaW52YWxpZCwgdGhlIGNvbnRyb2xsZXIgd2lsbCBhY3QgYXMgYSBDRUMgc25pZmZlcgph bmQgdHJhbnNmZXIgYWxsIG1lc3NhZ2VzIG9uIHRoZSBidXMuCgpTaWduZWQtb2ZmLWJ5OiBOZWls IEFybXN0cm9uZyA8bmFybXN0cm9uZ0BiYXlsaWJyZS5jb20+Ci0tLQogZHJpdmVycy9tZWRpYS9w bGF0Zm9ybS9LY29uZmlnICAgICAgICAgICAgICAgfCAgMTEgKwogZHJpdmVycy9tZWRpYS9wbGF0 Zm9ybS9NYWtlZmlsZSAgICAgICAgICAgICAgfCAgIDIgKwogZHJpdmVycy9tZWRpYS9wbGF0Zm9y bS9jcm9zLWVjL01ha2VmaWxlICAgICAgfCAgIDEgKwogZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9j cm9zLWVjL2Nyb3MtZWMtY2VjLmMgfCAzMzEgKysrKysrKysrKysrKysrKysrKysrKysrKysrCiA0 IGZpbGVzIGNoYW5nZWQsIDM0NSBpbnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJp dmVycy9tZWRpYS9wbGF0Zm9ybS9jcm9zLWVjL01ha2VmaWxlCiBjcmVhdGUgbW9kZSAxMDA2NDQg ZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9jcm9zLWVjL2Nyb3MtZWMtY2VjLmMKCmRpZmYgLS1naXQg YS9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL0tjb25maWcgYi9kcml2ZXJzL21lZGlhL3BsYXRmb3Jt L0tjb25maWcKaW5kZXggYzdhMWNmOC4uZTU1YThlZDIgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvbWVk aWEvcGxhdGZvcm0vS2NvbmZpZworKysgYi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL0tjb25maWcK QEAgLTU0Niw2ICs1NDYsMTcgQEAgbWVudWNvbmZpZyBDRUNfUExBVEZPUk1fRFJJVkVSUwogCiBp ZiBDRUNfUExBVEZPUk1fRFJJVkVSUwogCitjb25maWcgVklERU9fQ1JPU19FQ19DRUMKKwl0cmlz dGF0ZSAiQ2hyb21lIE9TIEVDIENFQyBkcml2ZXIiCisJZGVwZW5kcyBvbiBNRkRfQ1JPU19FQyB8 fCBDT01QSUxFX1RFU1QKKwlzZWxlY3QgQ0VDX0NPUkUKKwlzZWxlY3QgQ0VDX05PVElGSUVSCisJ LS0taGVscC0tLQorCSAgSWYgeW91IHNheSB5ZXMgaGVyZSB5b3Ugd2lsbCBnZXQgc3VwcG9ydCBm b3IgdGhlCisJICBDaHJvbWUgT1MgRW1iZWRkZWQgQ29udHJvbGxlcidzIENFQy4KKwkgIFRoZSBD RUMgYnVzIGlzIHByZXNlbnQgaW4gdGhlIEhETUkgY29ubmVjdG9yIGFuZCBlbmFibGVzIGNvbW11 bmljYXRpb24KKwkgIGJldHdlZW4gY29tcGF0aWJsZSBkZXZpY2VzLgorCiBjb25maWcgVklERU9f TUVTT05fQU9fQ0VDCiAJdHJpc3RhdGUgIkFtbG9naWMgTWVzb24gQU8gQ0VDIGRyaXZlciIKIAlk ZXBlbmRzIG9uIEFSQ0hfTUVTT04gfHwgQ09NUElMRV9URVNUCmRpZmYgLS1naXQgYS9kcml2ZXJz L21lZGlhL3BsYXRmb3JtL01ha2VmaWxlIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9NYWtlZmls ZQppbmRleCA5MzI1MTVkLi4wZTA1ODJlIDEwMDY0NAotLS0gYS9kcml2ZXJzL21lZGlhL3BsYXRm b3JtL01ha2VmaWxlCisrKyBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vTWFrZWZpbGUKQEAgLTky LDMgKzkyLDUgQEAgb2JqLSQoQ09ORklHX1ZJREVPX1FDT01fQ0FNU1MpCQkrPSBxY29tL2NhbXNz LTh4MTYvCiBvYmotJChDT05GSUdfVklERU9fUUNPTV9WRU5VUykJCSs9IHFjb20vdmVudXMvCiAK IG9iai15CQkJCQkrPSBtZXNvbi8KKworb2JqLXkJCQkJCSs9IGNyb3MtZWMvCmRpZmYgLS1naXQg YS9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL2Nyb3MtZWMvTWFrZWZpbGUgYi9kcml2ZXJzL21lZGlh L3BsYXRmb3JtL2Nyb3MtZWMvTWFrZWZpbGUKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAw MDAwMC4uOWNlOTdmOQotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0v Y3Jvcy1lYy9NYWtlZmlsZQpAQCAtMCwwICsxIEBACitvYmotJChDT05GSUdfVklERU9fQ1JPU19F Q19DRUMpICs9IGNyb3MtZWMtY2VjLm8KZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWVkaWEvcGxhdGZv cm0vY3Jvcy1lYy9jcm9zLWVjLWNlYy5jIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9jcm9zLWVj L2Nyb3MtZWMtY2VjLmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uZmVhOTBk YQotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vY3Jvcy1lYy9jcm9z LWVjLWNlYy5jCkBAIC0wLDAgKzEsMzMxIEBACisvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjog R1BMLTIuMCsKKy8qCisgKiBDRUMgZHJpdmVyIGZvciBDaHJvbWUgT1MgRW1iZWRkZWQgQ29udHJv bGxlcgorICoKKyAqIENvcHlyaWdodCAoYykgMjAxOCBCYXlMaWJyZSwgU0FTCisgKiBBdXRob3I6 IE5laWwgQXJtc3Ryb25nIDxuYXJtc3Ryb25nQGJheWxpYnJlLmNvbT4KKyAqLworCisjaW5jbHVk ZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVkZSA8 bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+CisjaW5jbHVkZSA8bGludXgvZG1pLmg+CisjaW5jbHVk ZSA8bGludXgvY2VjLmg+CisjaW5jbHVkZSA8bGludXgvc2xhYi5oPgorI2luY2x1ZGUgPGxpbnV4 L2ludGVycnVwdC5oPgorI2luY2x1ZGUgPG1lZGlhL2NlYy5oPgorI2luY2x1ZGUgPG1lZGlhL2Nl Yy1ub3RpZmllci5oPgorI2luY2x1ZGUgPGxpbnV4L21mZC9jcm9zX2VjLmg+CisjaW5jbHVkZSA8 bGludXgvbWZkL2Nyb3NfZWNfY29tbWFuZHMuaD4KKworI2RlZmluZSBEUlZfTkFNRQkiY3Jvcy1l Yy1jZWMiCisKKy8qKgorICogc3RydWN0IGNyb3NfZWNfY2VjIC0gRHJpdmVyIGRhdGEgZm9yIEVD IENFQworICoKKyAqIEBjcm9zX2VjOiBQb2ludGVyIHRvIEVDIGRldmljZQorICogQG5vdGlmaWVy OiBOb3RpZmllciBpbmZvIGZvciByZXNwb25kaW5nIHRvIEVDIGV2ZW50cworICogQGFkYXA6IENF QyBhZGFwdGVyCisgKiBAbm90aWZ5OiBDRUMgbm90aWZpZXIgcG9pbnRlcgorICogQHJjX21zZzog c3RvcmFnZSBmb3IgYSByZWNlaXZlZCBtZXNzYWdlCisgKi8KK3N0cnVjdCBjcm9zX2VjX2NlYyB7 CisJc3RydWN0IGNyb3NfZWNfZGV2aWNlICpjcm9zX2VjOworCXN0cnVjdCBub3RpZmllcl9ibG9j ayBub3RpZmllcjsKKwlzdHJ1Y3QgY2VjX2FkYXB0ZXIgKmFkYXA7CisJc3RydWN0IGNlY19ub3Rp ZmllciAqbm90aWZ5OworCXN0cnVjdCBjZWNfbXNnIHJ4X21zZzsKK307CisKK3N0YXRpYyB2b2lk IGhhbmRsZV9jZWNfbWVzc2FnZShzdHJ1Y3QgY3Jvc19lY19jZWMgKmNyb3NfZWNfY2VjKQorewor CXN0cnVjdCBjcm9zX2VjX2RldmljZSAqY3Jvc19lYyA9IGNyb3NfZWNfY2VjLT5jcm9zX2VjOwor CXVpbnQ4X3QgKmNlY19tZXNzYWdlID0gY3Jvc19lYy0+ZXZlbnRfZGF0YS5kYXRhLmNlY19tZXNz YWdlOworCXVuc2lnbmVkIGludCBsZW4gPSBjcm9zX2VjLT5ldmVudF9zaXplOworCisJY3Jvc19l Y19jZWMtPnJ4X21zZy5sZW4gPSBsZW47CisJbWVtY3B5KGNyb3NfZWNfY2VjLT5yeF9tc2cubXNn LCBjZWNfbWVzc2FnZSwgbGVuKTsKKworCWNlY19yZWNlaXZlZF9tc2coY3Jvc19lY19jZWMtPmFk YXAsICZjcm9zX2VjX2NlYy0+cnhfbXNnKTsKK30KKworc3RhdGljIHZvaWQgaGFuZGxlX2NlY19l dmVudChzdHJ1Y3QgY3Jvc19lY19jZWMgKmNyb3NfZWNfY2VjKQoreworCXN0cnVjdCBjcm9zX2Vj X2RldmljZSAqY3Jvc19lYyA9IGNyb3NfZWNfY2VjLT5jcm9zX2VjOworCXVpbnQzMl90IGV2ZW50 cyA9IGNyb3NfZWMtPmV2ZW50X2RhdGEuZGF0YS5jZWNfZXZlbnRzOworCisJaWYgKGV2ZW50cyAm IEVDX01LQlBfQ0VDX1NFTkRfT0spCisJCWNlY190cmFuc21pdF9hdHRlbXB0X2RvbmUoY3Jvc19l Y19jZWMtPmFkYXAsCisJCQkJCSAgQ0VDX1RYX1NUQVRVU19PSyk7CisKKwlpZiAoZXZlbnRzICYg RUNfTUtCUF9DRUNfU0VORF9GQUlMRUQpCisJCWNlY190cmFuc21pdF9hdHRlbXB0X2RvbmUoY3Jv c19lY19jZWMtPmFkYXAsCisJCQkJCSAgQ0VDX1RYX1NUQVRVU19FUlJPUik7Cit9CisKK3N0YXRp YyBpbnQgY3Jvc19lY19jZWNfZXZlbnQoc3RydWN0IG5vdGlmaWVyX2Jsb2NrICpuYiwKKwl1bnNp Z25lZCBsb25nIHF1ZXVlZF9kdXJpbmdfc3VzcGVuZCwgdm9pZCAqX25vdGlmeSkKK3sKKwlzdHJ1 Y3QgY3Jvc19lY19jZWMgKmNyb3NfZWNfY2VjOworCXN0cnVjdCBjcm9zX2VjX2RldmljZSAqY3Jv c19lYzsKKworCWNyb3NfZWNfY2VjID0gY29udGFpbmVyX29mKG5iLCBzdHJ1Y3QgY3Jvc19lY19j ZWMsIG5vdGlmaWVyKTsKKwljcm9zX2VjID0gY3Jvc19lY19jZWMtPmNyb3NfZWM7CisKKwlpZiAo Y3Jvc19lYy0+ZXZlbnRfZGF0YS5ldmVudF90eXBlID09IEVDX01LQlBfQ0VDX0VWRU5UKSB7CisJ CWhhbmRsZV9jZWNfZXZlbnQoY3Jvc19lY19jZWMpOworCQlyZXR1cm4gTk9USUZZX09LOworCX0K KworCWlmIChjcm9zX2VjLT5ldmVudF9kYXRhLmV2ZW50X3R5cGUgPT0gRUNfTUtCUF9FVkVOVF9D RUNfTUVTU0FHRSkgeworCQloYW5kbGVfY2VjX21lc3NhZ2UoY3Jvc19lY19jZWMpOworCQlyZXR1 cm4gTk9USUZZX09LOworCX0KKworCXJldHVybiBOT1RJRllfRE9ORTsKK30KKworc3RhdGljIGlu dCBjcm9zX2VjX2NlY19zZXRfbG9nX2FkZHIoc3RydWN0IGNlY19hZGFwdGVyICphZGFwLCB1OCBs b2dpY2FsX2FkZHIpCit7CisJc3RydWN0IGNyb3NfZWNfY2VjICpjcm9zX2VjX2NlYyA9IGFkYXAt PnByaXY7CisJc3RydWN0IGNyb3NfZWNfZGV2aWNlICpjcm9zX2VjID0gY3Jvc19lY19jZWMtPmNy b3NfZWM7CisJc3RydWN0IHsKKwkJc3RydWN0IGNyb3NfZWNfY29tbWFuZCBtc2c7CisJCXN0cnVj dCBlY19wYXJhbXNfY2VjX3NldCBkYXRhOworCX0gX19wYWNrZWQgbXNnOworCWludCByZXQgPSAw OworCisJaWYgKGxvZ2ljYWxfYWRkciA9PSBDRUNfTE9HX0FERFJfSU5WQUxJRCkKKwkJcmV0dXJu IDA7CisKKwltZW1zZXQoJm1zZywgMCwgc2l6ZW9mKG1zZykpOworCW1zZy5tc2cuY29tbWFuZCA9 IEVDX0NNRF9DRUNfU0VUOworCW1zZy5tc2cub3V0c2l6ZSA9IHNpemVvZihtc2cuZGF0YSk7CisJ bXNnLmRhdGEuY21kID0gQ0VDX0NNRF9MT0dJQ0FMX0FERFJFU1M7CisJbXNnLmRhdGEuYWRkcmVz cyA9IGxvZ2ljYWxfYWRkcjsKKworCXJldCA9IGNyb3NfZWNfY21kX3hmZXJfc3RhdHVzKGNyb3Nf ZWMsICZtc2cubXNnKTsKKwlpZiAocmV0IDwgMCkgeworCQlkZXZfZXJyKGNyb3NfZWMtPmRldiwK KwkJCSJlcnJvciBzZXR0aW5nIENFQyBsb2dpY2FsIGFkZHJlc3Mgb24gRUM6ICVkXG4iLCByZXQp OworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IGNyb3Nf ZWNfY2VjX3RyYW5zbWl0KHN0cnVjdCBjZWNfYWRhcHRlciAqYWRhcCwgdTggYXR0ZW1wdHMsCisJ CQkJdTMyIHNpZ25hbF9mcmVlX3RpbWUsIHN0cnVjdCBjZWNfbXNnICpjZWNfbXNnKQoreworCXN0 cnVjdCBjcm9zX2VjX2NlYyAqY3Jvc19lY19jZWMgPSBhZGFwLT5wcml2OworCXN0cnVjdCBjcm9z X2VjX2RldmljZSAqY3Jvc19lYyA9IGNyb3NfZWNfY2VjLT5jcm9zX2VjOworCXN0cnVjdCB7CisJ CXN0cnVjdCBjcm9zX2VjX2NvbW1hbmQgbXNnOworCQlzdHJ1Y3QgZWNfcGFyYW1zX2NlY193cml0 ZSBkYXRhOworCX0gX19wYWNrZWQgbXNnOworCWludCByZXQgPSAwOworCisJaWYgKGNlY19tc2ct PmxlbiA+IE1BWF9DRUNfTVNHX0xFTikKKwkJcmV0dXJuIC1FSU5WQUw7CisKKwltZW1zZXQoJm1z ZywgMCwgc2l6ZW9mKG1zZykpOworCW1zZy5tc2cuY29tbWFuZCA9IEVDX0NNRF9DRUNfV1JJVEVf TVNHOworCW1zZy5tc2cub3V0c2l6ZSA9IGNlY19tc2ctPmxlbjsKKwltZW1jcHkobXNnLmRhdGEu bXNnLCBjZWNfbXNnLT5tc2csIGNlY19tc2ctPmxlbik7CisKKwlyZXQgPSBjcm9zX2VjX2NtZF94 ZmVyX3N0YXR1cyhjcm9zX2VjLCAmbXNnLm1zZyk7CisJaWYgKHJldCA8IDApIHsKKwkJZGV2X2Vy cihjcm9zX2VjLT5kZXYsCisJCQkiZXJyb3Igd3JpdHRpbmcgQ0VDIG1zZyBvbiBFQzogJWRcbiIs IHJldCk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQg Y3Jvc19lY19jZWNfYWRhcF9lbmFibGUoc3RydWN0IGNlY19hZGFwdGVyICphZGFwLCBib29sIGVu YWJsZSkKK3sKKwlzdHJ1Y3QgY3Jvc19lY19jZWMgKmNyb3NfZWNfY2VjID0gYWRhcC0+cHJpdjsK KwlzdHJ1Y3QgY3Jvc19lY19kZXZpY2UgKmNyb3NfZWMgPSBjcm9zX2VjX2NlYy0+Y3Jvc19lYzsK KwlzdHJ1Y3QgeworCQlzdHJ1Y3QgY3Jvc19lY19jb21tYW5kIG1zZzsKKwkJc3RydWN0IGVjX3Bh cmFtc19jZWNfc2V0IGRhdGE7CisJfSBfX3BhY2tlZCBtc2c7CisJaW50IHJldCA9IDA7CisKKwlt ZW1zZXQoJm1zZywgMCwgc2l6ZW9mKG1zZykpOworCW1zZy5tc2cuY29tbWFuZCA9IEVDX0NNRF9D RUNfU0VUOworCW1zZy5tc2cub3V0c2l6ZSA9IHNpemVvZihtc2cuZGF0YSk7CisJbXNnLmRhdGEu Y21kID0gQ0VDX0NNRF9FTkFCTEU7CisJbXNnLmRhdGEuZW5hYmxlID0gZW5hYmxlOworCisJcmV0 ID0gY3Jvc19lY19jbWRfeGZlcl9zdGF0dXMoY3Jvc19lYywgJm1zZy5tc2cpOworCWlmIChyZXQg PCAwKSB7CisJCWRldl9lcnIoY3Jvc19lYy0+ZGV2LAorCQkJImVycm9yICVzYWJsaW5nIENFQyBv biBFQzogJWRcbiIsCisJCQkoZW5hYmxlID8gImVuIiA6ICJkaXMiKSwgcmV0KTsKKwkJcmV0dXJu IHJldDsKKwl9CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGNvbnN0IHN0cnVjdCBjZWNfYWRh cF9vcHMgY3Jvc19lY19jZWNfb3BzID0geworCS5hZGFwX2VuYWJsZSA9IGNyb3NfZWNfY2VjX2Fk YXBfZW5hYmxlLAorCS5hZGFwX2xvZ19hZGRyID0gY3Jvc19lY19jZWNfc2V0X2xvZ19hZGRyLAor CS5hZGFwX3RyYW5zbWl0ID0gY3Jvc19lY19jZWNfdHJhbnNtaXQsCit9OworCisjaWZkZWYgQ09O RklHX1BNX1NMRUVQCitzdGF0aWMgaW50IGNyb3NfZWNfY2VjX3N1c3BlbmQoc3RydWN0IGRldmlj ZSAqZGV2KQoreworCXN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYgPSB0b19wbGF0Zm9ybV9k ZXZpY2UoZGV2KTsKKwlzdHJ1Y3QgY3Jvc19lY19jZWMgKmNyb3NfZWNfY2VjID0gZGV2X2dldF9k cnZkYXRhKCZwZGV2LT5kZXYpOworCisJaWYgKGRldmljZV9tYXlfd2FrZXVwKGRldikpCisJCWVu YWJsZV9pcnFfd2FrZShjcm9zX2VjX2NlYy0+Y3Jvc19lYy0+aXJxKTsKKworCXJldHVybiAwOwor fQorCitzdGF0aWMgaW50IGNyb3NfZWNfY2VjX3Jlc3VtZShzdHJ1Y3QgZGV2aWNlICpkZXYpCit7 CisJc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldiA9IHRvX3BsYXRmb3JtX2RldmljZShkZXYp OworCXN0cnVjdCBjcm9zX2VjX2NlYyAqY3Jvc19lY19jZWMgPSBkZXZfZ2V0X2RydmRhdGEoJnBk ZXYtPmRldik7CisKKwlpZiAoZGV2aWNlX21heV93YWtldXAoZGV2KSkKKwkJZGlzYWJsZV9pcnFf d2FrZShjcm9zX2VjX2NlYy0+Y3Jvc19lYy0+aXJxKTsKKworCXJldHVybiAwOworfQorI2VuZGlm CisKK3N0YXRpYyBTSU1QTEVfREVWX1BNX09QUyhjcm9zX2VjX2NlY19wbV9vcHMsCisJY3Jvc19l Y19jZWNfc3VzcGVuZCwgY3Jvc19lY19jZWNfcmVzdW1lKTsKKworCitzdHJ1Y3QgY2VjX2RtaV9t YXRjaCB7CisJY2hhciAqc3lzX3ZlbmRvcjsKKwljaGFyICpwcm9kdWN0X25hbWU7CisJY2hhciAq ZGV2bmFtZTsKKwljaGFyICpjb25uOworfTsKKworc3RhdGljIGNvbnN0IHN0cnVjdCBjZWNfZG1p X21hdGNoIGNlY19kbWlfbWF0Y2hfdGFibGVbXSA9IHsKKwkvKiBHb29nbGUgRml6eiAqLworCXsg Ikdvb2dsZSIsICJGaXp6IiwgIjAwMDA6MDA6MDIuMCIsICJIRE1JLUEtMSIgfSwKK307CisKK3N0 YXRpYyBpbnQgY3Jvc19lY19jZWNfZ2V0X25vdGlmaWVyKHN0cnVjdCBjZWNfbm90aWZpZXIgKipu b3RpZnkpCit7CisJaW50IGk7CisKKwlmb3IgKGkgPSAwIDsgaSA8IEFSUkFZX1NJWkUoY2VjX2Rt aV9tYXRjaF90YWJsZSkgOyArK2kpIHsKKwkJY29uc3Qgc3RydWN0IGNlY19kbWlfbWF0Y2ggKm0g PSAmY2VjX2RtaV9tYXRjaF90YWJsZVtpXTsKKworCQlpZiAoZG1pX21hdGNoKERNSV9TWVNfVkVO RE9SLCBtLT5zeXNfdmVuZG9yKSAmJgorCQkgICAgZG1pX21hdGNoKERNSV9QUk9EVUNUX05BTUUs IG0tPnByb2R1Y3RfbmFtZSkpIHsKKwkJCSpub3RpZnkgPSBjZWNfbm90aWZpZXJfZ2V0X2J5bmFt ZShtLT5kZXZuYW1lLCBtLT5jb25uKTsKKwkJCXJldHVybiAwOworCQl9CisJfQorCisJcmV0dXJu IC1FSU5WQUw7Cit9CisKK3N0YXRpYyBpbnQgY3Jvc19lY19jZWNfcHJvYmUoc3RydWN0IHBsYXRm b3JtX2RldmljZSAqcGRldikKK3sKKwlzdHJ1Y3QgY3Jvc19lY19kZXYgKmVjX2RldiA9IGRldl9n ZXRfZHJ2ZGF0YShwZGV2LT5kZXYucGFyZW50KTsKKwlzdHJ1Y3QgY3Jvc19lY19kZXZpY2UgKmNy b3NfZWMgPSBlY19kZXYtPmVjX2RldjsKKwlzdHJ1Y3QgY3Jvc19lY19jZWMgKmNyb3NfZWNfY2Vj OworCXVuc2lnbmVkIGludCBjZWNfY2FwcyA9IENFQ19DQVBfREVGQVVMVFM7CisJaW50IHJldDsK KworCWNyb3NfZWNfY2VjID0gZGV2bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZigqY3Jvc19l Y19jZWMpLAorCQkJCSAgIEdGUF9LRVJORUwpOworCWlmICghY3Jvc19lY19jZWMpCisJCXJldHVy biAtRU5PTUVNOworCisJcGxhdGZvcm1fc2V0X2RydmRhdGEocGRldiwgY3Jvc19lY19jZWMpOwor CWNyb3NfZWNfY2VjLT5jcm9zX2VjID0gY3Jvc19lYzsKKworCXJldCA9IGNyb3NfZWNfY2VjX2dl dF9ub3RpZmllcigmY3Jvc19lY19jZWMtPm5vdGlmeSk7CisJaWYgKHJldCkgeworCQlkZXZfd2Fy bigmcGRldi0+ZGV2LCAibm8gQ0VDIG5vdGlmaWVyIGF2YWlsYWJsZVxuIik7CisJCWNlY19jYXBz IHw9IENFQ19DQVBfUEhZU19BRERSOworCX0gZWxzZSBpZiAoIWNyb3NfZWNfY2VjLT5ub3RpZnkp IHsKKwkJcmV0dXJuIC1FUFJPQkVfREVGRVI7CisJfQorCisJcmV0ID0gZGV2aWNlX2luaXRfd2Fr ZXVwKCZwZGV2LT5kZXYsIDEpOworCWlmIChyZXQpIHsKKwkJZGV2X2VycigmcGRldi0+ZGV2LCAi ZmFpbGVkIHRvIGluaXRpYWxpemUgd2FrZXVwXG4iKTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwlj cm9zX2VjX2NlYy0+YWRhcCA9IGNlY19hbGxvY2F0ZV9hZGFwdGVyKCZjcm9zX2VjX2NlY19vcHMs IGNyb3NfZWNfY2VjLAorCQkJCQkJIERSVl9OQU1FLCBjZWNfY2FwcywgMSk7CisJaWYgKElTX0VS Uihjcm9zX2VjX2NlYy0+YWRhcCkpCisJCXJldHVybiBQVFJfRVJSKGNyb3NfZWNfY2VjLT5hZGFw KTsKKworCWNyb3NfZWNfY2VjLT5hZGFwLT5vd25lciA9IFRISVNfTU9EVUxFOworCisJLyogR2V0 IENFQyBldmVudHMgZnJvbSB0aGUgRUMuICovCisJY3Jvc19lY19jZWMtPm5vdGlmaWVyLm5vdGlm aWVyX2NhbGwgPSBjcm9zX2VjX2NlY19ldmVudDsKKwlyZXQgPSBibG9ja2luZ19ub3RpZmllcl9j aGFpbl9yZWdpc3RlcigmY3Jvc19lYy0+ZXZlbnRfbm90aWZpZXIsCisJCQkJCSAgICAgICAmY3Jv c19lY19jZWMtPm5vdGlmaWVyKTsKKwlpZiAocmV0KSB7CisJCWRldl9lcnIoJnBkZXYtPmRldiwg ImZhaWxlZCB0byByZWdpc3RlciBub3RpZmllclxuIik7CisJCWNlY19kZWxldGVfYWRhcHRlcihj cm9zX2VjX2NlYy0+YWRhcCk7CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0ID0gY2VjX3JlZ2lz dGVyX2FkYXB0ZXIoY3Jvc19lY19jZWMtPmFkYXAsICZwZGV2LT5kZXYpOworCWlmIChyZXQgPCAw KSB7CisJCWNlY19kZWxldGVfYWRhcHRlcihjcm9zX2VjX2NlYy0+YWRhcCk7CisJCXJldHVybiBy ZXQ7CisJfQorCisJY2VjX3JlZ2lzdGVyX2NlY19ub3RpZmllcihjcm9zX2VjX2NlYy0+YWRhcCwg Y3Jvc19lY19jZWMtPm5vdGlmeSk7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBjcm9z X2VjX2NlY19yZW1vdmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3sKKwlzdHJ1Y3Qg Y3Jvc19lY19jZWMgKmNyb3NfZWNfY2VjID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7CisJ c3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRldjsKKwlpbnQgcmV0OworCisJcmV0ID0gYmxv Y2tpbmdfbm90aWZpZXJfY2hhaW5fdW5yZWdpc3RlcigKKwkJCSZjcm9zX2VjX2NlYy0+Y3Jvc19l Yy0+ZXZlbnRfbm90aWZpZXIsCisJCQkmY3Jvc19lY19jZWMtPm5vdGlmaWVyKTsKKworCWlmIChy ZXQpIHsKKwkJZGV2X2VycihkZXYsICJmYWlsZWQgdG8gdW5yZWdpc3RlciBub3RpZmllclxuIik7 CisJCXJldHVybiByZXQ7CisJfQorCisJY2VjX3VucmVnaXN0ZXJfYWRhcHRlcihjcm9zX2VjX2Nl Yy0+YWRhcCk7CisKKwlpZiAoY3Jvc19lY19jZWMtPm5vdGlmeSkKKwkJY2VjX25vdGlmaWVyX3B1 dChjcm9zX2VjX2NlYy0+bm90aWZ5KTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgc3RydWN0 IHBsYXRmb3JtX2RyaXZlciBjcm9zX2VjX2NlY19kcml2ZXIgPSB7CisJLnByb2JlID0gY3Jvc19l Y19jZWNfcHJvYmUsCisJLnJlbW92ZSAgPSBjcm9zX2VjX2NlY19yZW1vdmUsCisJLmRyaXZlciA9 IHsKKwkJLm5hbWUgPSBEUlZfTkFNRSwKKwkJLnBtID0gJmNyb3NfZWNfY2VjX3BtX29wcywKKwl9 LAorfTsKKworbW9kdWxlX3BsYXRmb3JtX2RyaXZlcihjcm9zX2VjX2NlY19kcml2ZXIpOworCitN T0RVTEVfREVTQ1JJUFRJT04oIkNFQyBkcml2ZXIgZm9yIENocm9tZSBPUyBFQ3MiKTsKK01PRFVM RV9BVVRIT1IoIk5laWwgQXJtc3Ryb25nIDxuYXJtc3Ryb25nQGJheWxpYnJlLmNvbT4iKTsKK01P RFVMRV9MSUNFTlNFKCJHUEwiKTsKK01PRFVMRV9BTElBUygicGxhdGZvcm06IiBEUlZfTkFNRSk7 Ci0tIAoyLjcuNAoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X18KSW50ZWwtZ2Z4IG1haWxpbmcgbGlzdApJbnRlbC1nZnhAbGlzdHMuZnJlZWRlc2t0b3Aub3Jn Cmh0dHBzOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vaW50ZWwtZ2Z4 Cg==