From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.3 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS,USER_AGENT_MUTT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E4CC0C2BC61 for ; Mon, 29 Oct 2018 14:30:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9FE2120657 for ; Mon, 29 Oct 2018 14:30:47 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9FE2120657 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726596AbeJ2XTj (ORCPT ); Mon, 29 Oct 2018 19:19:39 -0400 Received: from mga06.intel.com ([134.134.136.31]:3462 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725964AbeJ2XTj (ORCPT ); Mon, 29 Oct 2018 19:19:39 -0400 X-Amp-Result: UNSCANNABLE X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 29 Oct 2018 07:30:45 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,440,1534834800"; d="scan'208";a="103459274" Received: from kuha.fi.intel.com ([10.237.72.189]) by fmsmga001.fm.intel.com with SMTP; 29 Oct 2018 07:30:41 -0700 Received: by kuha.fi.intel.com (sSMTP sendmail emulation); Mon, 29 Oct 2018 16:30:40 +0200 Date: Mon, 29 Oct 2018 16:30:40 +0200 From: Heikki Krogerus To: Yu Chen Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, suzhuangluan@hisilicon.com, kongfei@hisilicon.com, Arnd Bergmann , Greg Kroah-Hartman , John Stultz , Binghui Wang Subject: Re: [PATCH 07/10] hikey960: Support usb functionality of Hikey960 Message-ID: <20181029143040.GB14534@kuha.fi.intel.com> References: <20181027095820.40056-1-chenyu56@huawei.com> <20181027095820.40056-8-chenyu56@huawei.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20181027095820.40056-8-chenyu56@huawei.com> User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, On Sat, Oct 27, 2018 at 05:58:17PM +0800, Yu Chen wrote: > This driver handles usb hub power on and typeC port event of HiKey960 board: > 1)DP&DM switching between usb hub and typeC port base on typeC port > state By "hub" do you mean you have some kind of an integrated USB hub on your SoC? > 2)Control power of usb hub on Hikey960 > 3)Control vbus of typeC port > 4)Handle typeC port event to switch data role Is your role switch a discrete component, or something part of the SoC? > Cc: Arnd Bergmann > Cc: Greg Kroah-Hartman > Cc: John Stultz > Cc: Binghui Wang > Signed-off-by: Yu Chen > --- > drivers/misc/Kconfig | 7 + > drivers/misc/Makefile | 1 + > drivers/misc/hisi_hikey_usb.c | 319 ++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 327 insertions(+) > create mode 100644 drivers/misc/hisi_hikey_usb.c > > diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig > index 3726eacdf65d..8e04fc87b685 100644 > --- a/drivers/misc/Kconfig > +++ b/drivers/misc/Kconfig > @@ -513,6 +513,13 @@ config MISC_RTSX > tristate > default MISC_RTSX_PCI || MISC_RTSX_USB > > +config HISI_HIKEY_USB > + tristate "USB functionality of HiSilicon Hikey Platform" > + depends on GPIOLIB > + default n > + help > + If you say yes here you get support for usb functionality of HiSilicon Hikey Platform. > + > source "drivers/misc/c2port/Kconfig" > source "drivers/misc/eeprom/Kconfig" > source "drivers/misc/cb710/Kconfig" > diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile > index af22bbc3d00c..387dd302815c 100644 > --- a/drivers/misc/Makefile > +++ b/drivers/misc/Makefile > @@ -58,3 +58,4 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o > obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o > obj-$(CONFIG_OCXL) += ocxl/ > obj-$(CONFIG_MISC_RTSX) += cardreader/ > +obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o > diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c > new file mode 100644 > index 000000000000..4965719c99ae > --- /dev/null > +++ b/drivers/misc/hisi_hikey_usb.c > @@ -0,0 +1,319 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * hisi_hikey_usb.c > + * > + * Copyright (c) Hisilicon Tech. Co., Ltd. All rights reserved. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define DEVICE_DRIVER_NAME "hisi_hikey_usb" > + > +#define HUB_VBUS_POWER_ON 1 > +#define HUB_VBUS_POWER_OFF 0 > +#define USB_SWITCH_TO_HUB 1 > +#define USB_SWITCH_TO_TYPEC 0 > + > +#define INVALID_GPIO_VALUE (-1) > + > +struct hisi_hikey_usb { > + int otg_switch_gpio; > + int typec_vbus_gpio; > + int typec_vbus_enable_val; > + int hub_vbus_gpio; I think you should use struct gpio_desc and gpiod_*() API with the gpios. > + struct extcon_dev *edev; > + struct usb_role_switch *role_sw; > +}; > + > +static const unsigned int usb_extcon_cable[] = { > + EXTCON_USB, > + EXTCON_USB_HOST, > + EXTCON_NONE, > +}; > + > +static void hub_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, int value) > +{ > + int gpio = hisi_hikey_usb->hub_vbus_gpio; > + > + if (gpio_is_valid(gpio)) > + gpio_set_value(gpio, value); > +} > + > +static void usb_switch_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, > + int switch_to) > +{ > + int gpio = hisi_hikey_usb->otg_switch_gpio; > + const char *switch_to_str = (switch_to == USB_SWITCH_TO_HUB) ? > + "hub" : "typec"; > + > + if (!gpio_is_valid(gpio)) { > + pr_err("%s: otg_switch_gpio is err\n", __func__); > + return; > + } > + > + if (gpio_get_value(gpio) == switch_to) { > + pr_info("%s: already switch to %s\n", __func__, switch_to_str); That kind of prints are really just noise. > + return; > + } > + > + gpio_direction_output(gpio, switch_to); > + pr_info("%s: switch to %s\n", __func__, switch_to_str); That is also just noise. > +} > + > +static void usb_typec_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, > + int value) > +{ > + int gpio = hisi_hikey_usb->typec_vbus_gpio; > + > + if (!gpio_is_valid(gpio)) { > + pr_err("%s: typec power gpio is err\n", __func__); > + return; > + } > + > + if (gpio_get_value(gpio) == value) { > + pr_info("%s: typec power no change\n", __func__); Ditto. > + return; > + } > + > + gpio_direction_output(gpio, value); > + pr_info("%s: set typec vbus gpio to %d\n", __func__, value); Ditto. > +} > + > +static int extcon_hisi_pd_set_role(struct device *dev, enum usb_role role) > +{ > + struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev); > + > + dev_info(dev, "%s:set usb role to %d\n", __func__, role); > + switch (role) { > + case USB_ROLE_NONE: > + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_HUB); > + usb_typec_power_ctrl(hisi_hikey_usb, > + !hisi_hikey_usb->typec_vbus_enable_val); > + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_ON); > + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, false); > + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST, > + true); > + break; > + case USB_ROLE_HOST: > + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); > + usb_typec_power_ctrl(hisi_hikey_usb, > + hisi_hikey_usb->typec_vbus_enable_val); > + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, false); > + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST, > + true); > + break; > + case USB_ROLE_DEVICE: > + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_OFF); > + usb_typec_power_ctrl(hisi_hikey_usb, > + hisi_hikey_usb->typec_vbus_enable_val); > + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); > + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST, > + false); > + extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, true); > + break; > + } If I understood the above correctly, you are controlling the VBUS based on the data role, right? With USB Type-C connectors the power and data roles are separate, so you should not be doing that. But since you are controlling the VBUS with a single GPIO, wouldn't it be easier to just give the Type-C port controller device that GPIO resources and let the Type-C drivers take care of it? You could add a "set_vbus" callback to struct tcpci_data and take care of the GPIO in tcpci_rt1711h.c, or alternatively, just handle it in tcpci.c. > + return 0; > +} > + > +static enum usb_role extcon_hisi_pd_get_role(struct device *dev) > +{ > + struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev); > + > + return usb_role_switch_get_role(hisi_hikey_usb->role_sw); > +} > + > +static const struct usb_role_switch_desc sw_desc = { > + .set = extcon_hisi_pd_set_role, > + .get = extcon_hisi_pd_get_role, > + .allow_userspace_control = true, > +}; > + > +static int hisi_hikey_usb_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct device_node *root = dev->of_node; > + struct hisi_hikey_usb *hisi_hikey_usb; > + int ret; > + > + hisi_hikey_usb = devm_kzalloc(dev, sizeof(*hisi_hikey_usb), GFP_KERNEL); > + if (!hisi_hikey_usb) > + return -ENOMEM; > + > + dev_set_name(dev, "hisi_hikey_usb"); > + > + hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE; > + hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE; > + hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE; > + > + hisi_hikey_usb->hub_vbus_gpio = of_get_named_gpio(root, > + "hub_vdd33_en_gpio", 0); > + if (!gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) { > + pr_err("%s: hub_vbus_gpio is err\n", __func__); > + return hisi_hikey_usb->hub_vbus_gpio; > + } > + > + ret = gpio_request(hisi_hikey_usb->hub_vbus_gpio, "hub_vbus_int_gpio"); > + if (ret) { > + pr_err("%s: request hub_vbus_gpio err\n", __func__); > + hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE; > + return ret; > + } > + > + ret = gpio_direction_output(hisi_hikey_usb->hub_vbus_gpio, > + HUB_VBUS_POWER_ON); > + if (ret) { > + pr_err("%s: power on hub vbus err\n", __func__); > + goto free_gpio1; > + } > + > + hisi_hikey_usb->typec_vbus_gpio = of_get_named_gpio(root, > + "typc_vbus_int_gpio,typec-gpios", 0); > + if (!gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) { > + pr_err("%s: typec_vbus_gpio is err\n", __func__); > + ret = hisi_hikey_usb->typec_vbus_gpio; > + goto free_gpio1; > + } > + > + ret = gpio_request(hisi_hikey_usb->typec_vbus_gpio, > + "typc_vbus_int_gpio"); > + if (ret) { > + pr_err("%s: request typec_vbus_gpio err\n", __func__); > + hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE; > + goto free_gpio1; > + } > + > + ret = of_property_read_u32(root, "typc_vbus_enable_val", > + &hisi_hikey_usb->typec_vbus_enable_val); > + if (ret) { > + pr_err("%s: typc_vbus_enable_val can't get\n", __func__); > + goto free_gpio2; > + } > + > + hisi_hikey_usb->typec_vbus_enable_val = > + !!hisi_hikey_usb->typec_vbus_enable_val; > + > + ret = gpio_direction_output(hisi_hikey_usb->typec_vbus_gpio, > + hisi_hikey_usb->typec_vbus_enable_val); > + if (ret) { > + pr_err("%s: power on typec vbus err", __func__); > + goto free_gpio2; > + } > + > + if (of_device_is_compatible(root, "hisilicon,hikey960_usb")) { Instead of that kind of checks, isn't it enough to just use optional gpios? > + hisi_hikey_usb->otg_switch_gpio = of_get_named_gpio(root, > + "otg_gpio", 0); > + if (!gpio_is_valid(hisi_hikey_usb->otg_switch_gpio)) { > + pr_info("%s: otg_switch_gpio is err\n", __func__); > + goto free_gpio2; > + } > + > + ret = gpio_request(hisi_hikey_usb->otg_switch_gpio, > + "otg_switch_gpio"); > + if (ret) { > + hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE; > + pr_err("%s: request typec_vbus_gpio err\n", __func__); > + goto free_gpio2; > + } > + } > + > + hisi_hikey_usb->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable); > + if (IS_ERR(hisi_hikey_usb->edev)) { > + dev_err(dev, "failed to allocate extcon device\n"); > + goto free_gpio2; > + } > + > + ret = devm_extcon_dev_register(dev, hisi_hikey_usb->edev); > + if (ret < 0) { > + dev_err(dev, "failed to register extcon device\n"); > + goto free_gpio2; > + } > + extcon_set_state(hisi_hikey_usb->edev, EXTCON_USB_HOST, true); Is the primary purpose for this extcon device to satisfy the DRD code in dwc3 driver? > + hisi_hikey_usb->role_sw = usb_role_switch_register(dev, &sw_desc); > + if (IS_ERR(hisi_hikey_usb->role_sw)) > + goto free_gpio2; It looks a bit clumsy to me to register both the extcon device and the mux device, but I'm guessing you need to get a notification in dwc3 driver when the role changes, right? Perhaps we should simply add notification chain to the role mux structure. That could potentially allow this kind of code to be organized a bit better. > + platform_set_drvdata(pdev, hisi_hikey_usb); > + > + return 0; > + > +free_gpio2: > + if (gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) { > + gpio_free(hisi_hikey_usb->typec_vbus_gpio); > + hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE; > + } > + > +free_gpio1: > + if (gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) { > + gpio_free(hisi_hikey_usb->hub_vbus_gpio); > + hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE; > + } > + > + return ret; > +} > + > +static int hisi_hikey_usb_remove(struct platform_device *pdev) > +{ > + struct hisi_hikey_usb *hisi_hikey_usb = platform_get_drvdata(pdev); > + > + if (gpio_is_valid(hisi_hikey_usb->otg_switch_gpio)) { > + gpio_free(hisi_hikey_usb->otg_switch_gpio); > + hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE; > + } > + > + if (gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) { > + gpio_free(hisi_hikey_usb->typec_vbus_gpio); > + hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE; > + } > + > + if (gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) { > + gpio_free(hisi_hikey_usb->hub_vbus_gpio); > + hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE; > + } > + > + usb_role_switch_unregister(hisi_hikey_usb->role_sw); > + > + return 0; > +} > + > +static const struct of_device_id id_table_hisi_hikey_usb[] = { > + {.compatible = "hisilicon,gpio_hubv1"}, > + {.compatible = "hisilicon,hikey960_usb"}, > + {} > +}; > + > +static struct platform_driver hisi_hikey_usb_driver = { > + .probe = hisi_hikey_usb_probe, > + .remove = hisi_hikey_usb_remove, > + .driver = { > + .name = DEVICE_DRIVER_NAME, > + .of_match_table = of_match_ptr(id_table_hisi_hikey_usb), > + > + }, > +}; > + > +module_platform_driver(hisi_hikey_usb_driver); > + > +MODULE_AUTHOR("Yu Chen "); > +MODULE_DESCRIPTION("Driver Support for USB functionality of Hikey"); > +MODULE_LICENSE("GPL v2"); > -- > 2.15.0-rc2 I think you have too many things integrated into this one driver. IMO it would at least be better to just let the Type-C port driver take care of VBUS like I mentioned above. I'm also wondering if it would make sense to handle the role switch and the "hub" in their own drivers, but I don't know enough about your platform at this point to say for sure. br, -- heikki 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: [07/10] hikey960: Support usb functionality of Hikey960 From: Heikki Krogerus Message-Id: <20181029143040.GB14534@kuha.fi.intel.com> Date: Mon, 29 Oct 2018 16:30:40 +0200 To: Yu Chen Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, suzhuangluan@hisilicon.com, kongfei@hisilicon.com, Arnd Bergmann , Greg Kroah-Hartman , John Stultz , Binghui Wang List-ID: SGksCgpPbiBTYXQsIE9jdCAyNywgMjAxOCBhdCAwNTo1ODoxN1BNICswODAwLCBZdSBDaGVuIHdy b3RlOgo+IFRoaXMgZHJpdmVyIGhhbmRsZXMgdXNiIGh1YiBwb3dlciBvbiBhbmQgdHlwZUMgcG9y dCBldmVudCBvZiBIaUtleTk2MCBib2FyZDoKPiAxKURQJkRNIHN3aXRjaGluZyBiZXR3ZWVuIHVz YiBodWIgYW5kIHR5cGVDIHBvcnQgYmFzZSBvbiB0eXBlQyBwb3J0Cj4gc3RhdGUKCkJ5ICJodWIi IGRvIHlvdSBtZWFuIHlvdSBoYXZlIHNvbWUga2luZCBvZiBhbiBpbnRlZ3JhdGVkIFVTQiBodWIg b24KeW91ciBTb0M/Cgo+IDIpQ29udHJvbCBwb3dlciBvZiB1c2IgaHViIG9uIEhpa2V5OTYwCj4g MylDb250cm9sIHZidXMgb2YgdHlwZUMgcG9ydAo+IDQpSGFuZGxlIHR5cGVDIHBvcnQgZXZlbnQg dG8gc3dpdGNoIGRhdGEgcm9sZQoKSXMgeW91ciByb2xlIHN3aXRjaCBhIGRpc2NyZXRlIGNvbXBv bmVudCwgb3Igc29tZXRoaW5nIHBhcnQgb2YgdGhlIFNvQz8KCj4gQ2M6IEFybmQgQmVyZ21hbm4g PGFybmRAYXJuZGIuZGU+Cj4gQ2M6IEdyZWcgS3JvYWgtSGFydG1hbiA8Z3JlZ2toQGxpbnV4Zm91 bmRhdGlvbi5vcmc+Cj4gQ2M6IEpvaG4gU3R1bHR6IDxqb2huLnN0dWx0ekBsaW5hcm8ub3JnPgo+ IENjOiBCaW5naHVpIFdhbmcgPHdhbmdiaW5naHVpQGhpc2lsaWNvbi5jb20+Cj4gU2lnbmVkLW9m Zi1ieTogWXUgQ2hlbiA8Y2hlbnl1NTZAaHVhd2VpLmNvbT4KPiAtLS0KPiAgZHJpdmVycy9taXNj L0tjb25maWcgICAgICAgICAgfCAgIDcgKwo+ICBkcml2ZXJzL21pc2MvTWFrZWZpbGUgICAgICAg ICB8ICAgMSArCj4gIGRyaXZlcnMvbWlzYy9oaXNpX2hpa2V5X3VzYi5jIHwgMzE5ICsrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwo+ICAzIGZpbGVzIGNoYW5nZWQsIDMy NyBpbnNlcnRpb25zKCspCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21pc2MvaGlzaV9o aWtleV91c2IuYwo+IAo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL21pc2MvS2NvbmZpZyBiL2RyaXZl cnMvbWlzYy9LY29uZmlnCj4gaW5kZXggMzcyNmVhY2RmNjVkLi44ZTA0ZmM4N2I2ODUgMTAwNjQ0 Cj4gLS0tIGEvZHJpdmVycy9taXNjL0tjb25maWcKPiArKysgYi9kcml2ZXJzL21pc2MvS2NvbmZp Zwo+IEBAIC01MTMsNiArNTEzLDEzIEBAIGNvbmZpZyBNSVNDX1JUU1gKPiAgCXRyaXN0YXRlCj4g IAlkZWZhdWx0IE1JU0NfUlRTWF9QQ0kgfHwgTUlTQ19SVFNYX1VTQgo+ICAKPiArY29uZmlnIEhJ U0lfSElLRVlfVVNCCj4gKwl0cmlzdGF0ZSAiVVNCIGZ1bmN0aW9uYWxpdHkgb2YgSGlTaWxpY29u IEhpa2V5IFBsYXRmb3JtIgo+ICsJZGVwZW5kcyBvbiBHUElPTElCCj4gKwlkZWZhdWx0IG4KPiAr CWhlbHAKPiArCSAgSWYgeW91IHNheSB5ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIHVzYiBm dW5jdGlvbmFsaXR5IG9mIEhpU2lsaWNvbiBIaWtleSBQbGF0Zm9ybS4KPiArCj4gIHNvdXJjZSAi ZHJpdmVycy9taXNjL2MycG9ydC9LY29uZmlnIgo+ICBzb3VyY2UgImRyaXZlcnMvbWlzYy9lZXBy b20vS2NvbmZpZyIKPiAgc291cmNlICJkcml2ZXJzL21pc2MvY2I3MTAvS2NvbmZpZyIKPiBkaWZm IC0tZ2l0IGEvZHJpdmVycy9taXNjL01ha2VmaWxlIGIvZHJpdmVycy9taXNjL01ha2VmaWxlCj4g aW5kZXggYWYyMmJiYzNkMDBjLi4zODdkZDMwMjgxNWMgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9t aXNjL01ha2VmaWxlCj4gKysrIGIvZHJpdmVycy9taXNjL01ha2VmaWxlCj4gQEAgLTU4LDMgKzU4 LDQgQEAgb2JqLSQoQ09ORklHX0FTUEVFRF9MUENfU05PT1ApCSs9IGFzcGVlZC1scGMtc25vb3Au bwo+ICBvYmotJChDT05GSUdfUENJX0VORFBPSU5UX1RFU1QpCSs9IHBjaV9lbmRwb2ludF90ZXN0 Lm8KPiAgb2JqLSQoQ09ORklHX09DWEwpCQkrPSBvY3hsLwo+ICBvYmotJChDT05GSUdfTUlTQ19S VFNYKQkJKz0gY2FyZHJlYWRlci8KPiArb2JqLSQoQ09ORklHX0hJU0lfSElLRVlfVVNCKQkrPSBo aXNpX2hpa2V5X3VzYi5vCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWlzYy9oaXNpX2hpa2V5X3Vz Yi5jIGIvZHJpdmVycy9taXNjL2hpc2lfaGlrZXlfdXNiLmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0 NAo+IGluZGV4IDAwMDAwMDAwMDAwMC4uNDk2NTcxOWM5OWFlCj4gLS0tIC9kZXYvbnVsbAo+ICsr KyBiL2RyaXZlcnMvbWlzYy9oaXNpX2hpa2V5X3VzYi5jCj4gQEAgLTAsMCArMSwzMTkgQEAKPiAr Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjArCj4gKy8qCj4gKyAqIGhpc2lfaGlr ZXlfdXNiLmMKPiArICoKPiArICogQ29weXJpZ2h0IChjKSBIaXNpbGljb24gVGVjaC4gQ28uLCBM dGQuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVl IHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5Cj4gKyAqIGl0 IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVi bGlzaGVkIGJ5Cj4gKyAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJz aW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yCj4gKyAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVy IHZlcnNpb24uCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUg aG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAo+ICsgKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFO VFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgo+ICsgKiBNRVJDSEFOVEFC SUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCj4gKyAq IEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCj4gKyAqCj4gKyAq Lwo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgva2Vy bmVsLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9wbGF0 Zm9ybV9kZXZpY2UuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2dwaW8uaD4KPiArI2luY2x1ZGUgPGxp bnV4L29mX2dwaW8uaD4KPiArI2luY2x1ZGUgPGxpbnV4L2V4dGNvbi1wcm92aWRlci5oPgo+ICsj aW5jbHVkZSA8bGludXgvdXNiL3JvbGUuaD4KPiArCj4gKyNkZWZpbmUgREVWSUNFX0RSSVZFUl9O QU1FICJoaXNpX2hpa2V5X3VzYiIKPiArCj4gKyNkZWZpbmUgSFVCX1ZCVVNfUE9XRVJfT04gMQo+ ICsjZGVmaW5lIEhVQl9WQlVTX1BPV0VSX09GRiAwCj4gKyNkZWZpbmUgVVNCX1NXSVRDSF9UT19I VUIgMQo+ICsjZGVmaW5lIFVTQl9TV0lUQ0hfVE9fVFlQRUMgMAo+ICsKPiArI2RlZmluZSBJTlZB TElEX0dQSU9fVkFMVUUgKC0xKQo+ICsKPiArc3RydWN0IGhpc2lfaGlrZXlfdXNiIHsKPiArCWlu dCBvdGdfc3dpdGNoX2dwaW87Cj4gKwlpbnQgdHlwZWNfdmJ1c19ncGlvOwo+ICsJaW50IHR5cGVj X3ZidXNfZW5hYmxlX3ZhbDsKPiArCWludCBodWJfdmJ1c19ncGlvOwoKSSB0aGluayB5b3Ugc2hv dWxkIHVzZSBzdHJ1Y3QgZ3Bpb19kZXNjIGFuZCBncGlvZF8qKCkgQVBJIHdpdGggdGhlCmdwaW9z LgoKPiArCXN0cnVjdCBleHRjb25fZGV2ICplZGV2Owo+ICsJc3RydWN0IHVzYl9yb2xlX3N3aXRj aCAqcm9sZV9zdzsKPiArfTsKPiArCj4gK3N0YXRpYyBjb25zdCB1bnNpZ25lZCBpbnQgdXNiX2V4 dGNvbl9jYWJsZVtdID0gewo+ICsJRVhUQ09OX1VTQiwKPiArCUVYVENPTl9VU0JfSE9TVCwKPiAr CUVYVENPTl9OT05FLAo+ICt9Owo+ICsKPiArc3RhdGljIHZvaWQgaHViX3Bvd2VyX2N0cmwoc3Ry dWN0IGhpc2lfaGlrZXlfdXNiICpoaXNpX2hpa2V5X3VzYiwgaW50IHZhbHVlKQo+ICt7Cj4gKwlp bnQgZ3BpbyA9IGhpc2lfaGlrZXlfdXNiLT5odWJfdmJ1c19ncGlvOwo+ICsKPiArCWlmIChncGlv X2lzX3ZhbGlkKGdwaW8pKQo+ICsJCWdwaW9fc2V0X3ZhbHVlKGdwaW8sIHZhbHVlKTsKPiArfQo+ ICsKPiArc3RhdGljIHZvaWQgdXNiX3N3aXRjaF9jdHJsKHN0cnVjdCBoaXNpX2hpa2V5X3VzYiAq aGlzaV9oaWtleV91c2IsCj4gKwkJaW50IHN3aXRjaF90bykKPiArewo+ICsJaW50IGdwaW8gPSBo aXNpX2hpa2V5X3VzYi0+b3RnX3N3aXRjaF9ncGlvOwo+ICsJY29uc3QgY2hhciAqc3dpdGNoX3Rv X3N0ciA9IChzd2l0Y2hfdG8gPT0gVVNCX1NXSVRDSF9UT19IVUIpID8KPiArCQkiaHViIiA6ICJ0 eXBlYyI7Cj4gKwo+ICsJaWYgKCFncGlvX2lzX3ZhbGlkKGdwaW8pKSB7Cj4gKwkJcHJfZXJyKCIl czogb3RnX3N3aXRjaF9ncGlvIGlzIGVyclxuIiwgX19mdW5jX18pOwo+ICsJCXJldHVybjsKPiAr CX0KPiArCj4gKwlpZiAoZ3Bpb19nZXRfdmFsdWUoZ3BpbykgPT0gc3dpdGNoX3RvKSB7Cj4gKwkJ cHJfaW5mbygiJXM6IGFscmVhZHkgc3dpdGNoIHRvICVzXG4iLCBfX2Z1bmNfXywgc3dpdGNoX3Rv X3N0cik7CgpUaGF0IGtpbmQgb2YgcHJpbnRzIGFyZSByZWFsbHkganVzdCBub2lzZS4KCj4gKwkJ cmV0dXJuOwo+ICsJfQo+ICsKPiArCWdwaW9fZGlyZWN0aW9uX291dHB1dChncGlvLCBzd2l0Y2hf dG8pOwo+ICsJcHJfaW5mbygiJXM6IHN3aXRjaCB0byAlc1xuIiwgX19mdW5jX18sIHN3aXRjaF90 b19zdHIpOwoKVGhhdCBpcyBhbHNvIGp1c3Qgbm9pc2UuCgo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9p ZCB1c2JfdHlwZWNfcG93ZXJfY3RybChzdHJ1Y3QgaGlzaV9oaWtleV91c2IgKmhpc2lfaGlrZXlf dXNiLAo+ICsJCWludCB2YWx1ZSkKPiArewo+ICsJaW50IGdwaW8gPSBoaXNpX2hpa2V5X3VzYi0+ dHlwZWNfdmJ1c19ncGlvOwo+ICsKPiArCWlmICghZ3Bpb19pc192YWxpZChncGlvKSkgewo+ICsJ CXByX2VycigiJXM6IHR5cGVjIHBvd2VyIGdwaW8gaXMgZXJyXG4iLCBfX2Z1bmNfXyk7Cj4gKwkJ cmV0dXJuOwo+ICsJfQo+ICsKPiArCWlmIChncGlvX2dldF92YWx1ZShncGlvKSA9PSB2YWx1ZSkg ewo+ICsJCXByX2luZm8oIiVzOiB0eXBlYyBwb3dlciBubyBjaGFuZ2VcbiIsIF9fZnVuY19fKTsK CkRpdHRvLgoKPiArCQlyZXR1cm47Cj4gKwl9Cj4gKwo+ICsJZ3Bpb19kaXJlY3Rpb25fb3V0cHV0 KGdwaW8sIHZhbHVlKTsKPiArCXByX2luZm8oIiVzOiBzZXQgdHlwZWMgdmJ1cyBncGlvIHRvICVk XG4iLCBfX2Z1bmNfXywgdmFsdWUpOwoKRGl0dG8uCgo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGV4 dGNvbl9oaXNpX3BkX3NldF9yb2xlKHN0cnVjdCBkZXZpY2UgKmRldiwgZW51bSB1c2Jfcm9sZSBy b2xlKQo+ICt7Cj4gKwlzdHJ1Y3QgaGlzaV9oaWtleV91c2IgKmhpc2lfaGlrZXlfdXNiID0gZGV2 X2dldF9kcnZkYXRhKGRldik7Cj4gKwo+ICsJZGV2X2luZm8oZGV2LCAiJXM6c2V0IHVzYiByb2xl IHRvICVkXG4iLCBfX2Z1bmNfXywgcm9sZSk7Cj4gKwlzd2l0Y2ggKHJvbGUpIHsKPiArCWNhc2Ug VVNCX1JPTEVfTk9ORToKPiArCQl1c2Jfc3dpdGNoX2N0cmwoaGlzaV9oaWtleV91c2IsIFVTQl9T V0lUQ0hfVE9fSFVCKTsKPiArCQl1c2JfdHlwZWNfcG93ZXJfY3RybChoaXNpX2hpa2V5X3VzYiwK PiArCQkJCSFoaXNpX2hpa2V5X3VzYi0+dHlwZWNfdmJ1c19lbmFibGVfdmFsKTsKPiArCQlodWJf cG93ZXJfY3RybChoaXNpX2hpa2V5X3VzYiwgSFVCX1ZCVVNfUE9XRVJfT04pOwo+ICsJCWV4dGNv bl9zZXRfc3RhdGVfc3luYyhoaXNpX2hpa2V5X3VzYi0+ZWRldiwgRVhUQ09OX1VTQiwgZmFsc2Up Owo+ICsJCWV4dGNvbl9zZXRfc3RhdGVfc3luYyhoaXNpX2hpa2V5X3VzYi0+ZWRldiwgRVhUQ09O X1VTQl9IT1NULAo+ICsJCQkJdHJ1ZSk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFVTQl9ST0xFX0hP U1Q6Cj4gKwkJdXNiX3N3aXRjaF9jdHJsKGhpc2lfaGlrZXlfdXNiLCBVU0JfU1dJVENIX1RPX1RZ UEVDKTsKPiArCQl1c2JfdHlwZWNfcG93ZXJfY3RybChoaXNpX2hpa2V5X3VzYiwKPiArCQkJCWhp c2lfaGlrZXlfdXNiLT50eXBlY192YnVzX2VuYWJsZV92YWwpOwo+ICsJCWV4dGNvbl9zZXRfc3Rh dGVfc3luYyhoaXNpX2hpa2V5X3VzYi0+ZWRldiwgRVhUQ09OX1VTQiwgZmFsc2UpOwo+ICsJCWV4 dGNvbl9zZXRfc3RhdGVfc3luYyhoaXNpX2hpa2V5X3VzYi0+ZWRldiwgRVhUQ09OX1VTQl9IT1NU LAo+ICsJCQkJdHJ1ZSk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFVTQl9ST0xFX0RFVklDRToKPiAr CQlodWJfcG93ZXJfY3RybChoaXNpX2hpa2V5X3VzYiwgSFVCX1ZCVVNfUE9XRVJfT0ZGKTsKPiAr CQl1c2JfdHlwZWNfcG93ZXJfY3RybChoaXNpX2hpa2V5X3VzYiwKPiArCQkJCWhpc2lfaGlrZXlf dXNiLT50eXBlY192YnVzX2VuYWJsZV92YWwpOwo+ICsJCXVzYl9zd2l0Y2hfY3RybChoaXNpX2hp a2V5X3VzYiwgVVNCX1NXSVRDSF9UT19UWVBFQyk7Cj4gKwkJZXh0Y29uX3NldF9zdGF0ZV9zeW5j KGhpc2lfaGlrZXlfdXNiLT5lZGV2LCBFWFRDT05fVVNCX0hPU1QsCj4gKwkJCQlmYWxzZSk7Cj4g KwkJZXh0Y29uX3NldF9zdGF0ZV9zeW5jKGhpc2lfaGlrZXlfdXNiLT5lZGV2LCBFWFRDT05fVVNC LCB0cnVlKTsKPiArCQlicmVhazsKPiArCX0KCklmIEkgdW5kZXJzdG9vZCB0aGUgYWJvdmUgY29y cmVjdGx5LCB5b3UgYXJlIGNvbnRyb2xsaW5nIHRoZSBWQlVTCmJhc2VkIG9uIHRoZSBkYXRhIHJv bGUsIHJpZ2h0PwoKV2l0aCBVU0IgVHlwZS1DIGNvbm5lY3RvcnMgdGhlIHBvd2VyIGFuZCBkYXRh IHJvbGVzIGFyZSBzZXBhcmF0ZSwgc28KeW91IHNob3VsZCBub3QgYmUgZG9pbmcgdGhhdC4KCkJ1 dCBzaW5jZSB5b3UgYXJlIGNvbnRyb2xsaW5nIHRoZSBWQlVTIHdpdGggYSBzaW5nbGUgR1BJTywg d291bGRuJ3QgaXQKYmUgZWFzaWVyIHRvIGp1c3QgZ2l2ZSB0aGUgVHlwZS1DIHBvcnQgY29udHJv bGxlciBkZXZpY2UgdGhhdCBHUElPCnJlc291cmNlcyBhbmQgbGV0IHRoZSBUeXBlLUMgZHJpdmVy cyB0YWtlIGNhcmUgb2YgaXQ/IFlvdSBjb3VsZCBhZGQgYQoic2V0X3ZidXMiIGNhbGxiYWNrIHRv IHN0cnVjdCB0Y3BjaV9kYXRhIGFuZCB0YWtlIGNhcmUgb2YgdGhlIEdQSU8gaW4KdGNwY2lfcnQx NzExaC5jLCBvciBhbHRlcm5hdGl2ZWx5LCBqdXN0IGhhbmRsZSBpdCBpbiB0Y3BjaS5jLgoKPiAr CXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgZW51bSB1c2Jfcm9sZSBleHRjb25faGlzaV9w ZF9nZXRfcm9sZShzdHJ1Y3QgZGV2aWNlICpkZXYpCj4gK3sKPiArCXN0cnVjdCBoaXNpX2hpa2V5 X3VzYiAqaGlzaV9oaWtleV91c2IgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCj4gKwlyZXR1 cm4gdXNiX3JvbGVfc3dpdGNoX2dldF9yb2xlKGhpc2lfaGlrZXlfdXNiLT5yb2xlX3N3KTsKPiAr fQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCB1c2Jfcm9sZV9zd2l0Y2hfZGVzYyBzd19kZXNj ID0gewo+ICsJLnNldCA9IGV4dGNvbl9oaXNpX3BkX3NldF9yb2xlLAo+ICsJLmdldCA9IGV4dGNv bl9oaXNpX3BkX2dldF9yb2xlLAo+ICsJLmFsbG93X3VzZXJzcGFjZV9jb250cm9sID0gdHJ1ZSwK PiArfTsKPiArCj4gK3N0YXRpYyBpbnQgaGlzaV9oaWtleV91c2JfcHJvYmUoc3RydWN0IHBsYXRm b3JtX2RldmljZSAqcGRldikKPiArewo+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRl djsKPiArCXN0cnVjdCBkZXZpY2Vfbm9kZSAqcm9vdCA9IGRldi0+b2Zfbm9kZTsKPiArCXN0cnVj dCBoaXNpX2hpa2V5X3VzYiAqaGlzaV9oaWtleV91c2I7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWhp c2lfaGlrZXlfdXNiID0gZGV2bV9remFsbG9jKGRldiwgc2l6ZW9mKCpoaXNpX2hpa2V5X3VzYiks IEdGUF9LRVJORUwpOwo+ICsJaWYgKCFoaXNpX2hpa2V5X3VzYikKPiArCQlyZXR1cm4gLUVOT01F TTsKPiArCj4gKwlkZXZfc2V0X25hbWUoZGV2LCAiaGlzaV9oaWtleV91c2IiKTsKPiArCj4gKwlo aXNpX2hpa2V5X3VzYi0+aHViX3ZidXNfZ3BpbyA9IElOVkFMSURfR1BJT19WQUxVRTsKPiArCWhp c2lfaGlrZXlfdXNiLT5vdGdfc3dpdGNoX2dwaW8gPSBJTlZBTElEX0dQSU9fVkFMVUU7Cj4gKwlo aXNpX2hpa2V5X3VzYi0+dHlwZWNfdmJ1c19ncGlvID0gSU5WQUxJRF9HUElPX1ZBTFVFOwo+ICsK PiArCWhpc2lfaGlrZXlfdXNiLT5odWJfdmJ1c19ncGlvID0gb2ZfZ2V0X25hbWVkX2dwaW8ocm9v dCwKPiArCQkJImh1Yl92ZGQzM19lbl9ncGlvIiwgMCk7Cj4gKwlpZiAoIWdwaW9faXNfdmFsaWQo aGlzaV9oaWtleV91c2ItPmh1Yl92YnVzX2dwaW8pKSB7Cj4gKwkJcHJfZXJyKCIlczogaHViX3Zi dXNfZ3BpbyBpcyBlcnJcbiIsIF9fZnVuY19fKTsKPiArCQlyZXR1cm4gaGlzaV9oaWtleV91c2It Pmh1Yl92YnVzX2dwaW87Cj4gKwl9Cj4gKwo+ICsJcmV0ID0gZ3Bpb19yZXF1ZXN0KGhpc2lfaGlr ZXlfdXNiLT5odWJfdmJ1c19ncGlvLCAiaHViX3ZidXNfaW50X2dwaW8iKTsKPiArCWlmIChyZXQp IHsKPiArCQlwcl9lcnIoIiVzOiByZXF1ZXN0IGh1Yl92YnVzX2dwaW8gZXJyXG4iLCBfX2Z1bmNf Xyk7Cj4gKwkJaGlzaV9oaWtleV91c2ItPmh1Yl92YnVzX2dwaW8gPSBJTlZBTElEX0dQSU9fVkFM VUU7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwlyZXQgPSBncGlvX2RpcmVjdGlvbl9v dXRwdXQoaGlzaV9oaWtleV91c2ItPmh1Yl92YnVzX2dwaW8sCj4gKwkJCUhVQl9WQlVTX1BPV0VS X09OKTsKPiArCWlmIChyZXQpIHsKPiArCQlwcl9lcnIoIiVzOiBwb3dlciBvbiBodWIgdmJ1cyBl cnJcbiIsIF9fZnVuY19fKTsKPiArCQlnb3RvIGZyZWVfZ3BpbzE7Cj4gKwl9Cj4gKwo+ICsJaGlz aV9oaWtleV91c2ItPnR5cGVjX3ZidXNfZ3BpbyA9IG9mX2dldF9uYW1lZF9ncGlvKHJvb3QsCj4g KwkJInR5cGNfdmJ1c19pbnRfZ3Bpbyx0eXBlYy1ncGlvcyIsIDApOwo+ICsJaWYgKCFncGlvX2lz X3ZhbGlkKGhpc2lfaGlrZXlfdXNiLT50eXBlY192YnVzX2dwaW8pKSB7Cj4gKwkJcHJfZXJyKCIl czogdHlwZWNfdmJ1c19ncGlvIGlzIGVyclxuIiwgX19mdW5jX18pOwo+ICsJCXJldCA9IGhpc2lf aGlrZXlfdXNiLT50eXBlY192YnVzX2dwaW87Cj4gKwkJZ290byBmcmVlX2dwaW8xOwo+ICsJfQo+ ICsKPiArCXJldCA9IGdwaW9fcmVxdWVzdChoaXNpX2hpa2V5X3VzYi0+dHlwZWNfdmJ1c19ncGlv LAo+ICsJCQkidHlwY192YnVzX2ludF9ncGlvIik7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJcHJfZXJy KCIlczogcmVxdWVzdCB0eXBlY192YnVzX2dwaW8gZXJyXG4iLCBfX2Z1bmNfXyk7Cj4gKwkJaGlz aV9oaWtleV91c2ItPnR5cGVjX3ZidXNfZ3BpbyA9IElOVkFMSURfR1BJT19WQUxVRTsKPiArCQln b3RvIGZyZWVfZ3BpbzE7Cj4gKwl9Cj4gKwo+ICsJcmV0ID0gb2ZfcHJvcGVydHlfcmVhZF91MzIo cm9vdCwgInR5cGNfdmJ1c19lbmFibGVfdmFsIiwKPiArCQkJCSAgICZoaXNpX2hpa2V5X3VzYi0+ dHlwZWNfdmJ1c19lbmFibGVfdmFsKTsKPiArCWlmIChyZXQpIHsKPiArCQlwcl9lcnIoIiVzOiB0 eXBjX3ZidXNfZW5hYmxlX3ZhbCBjYW4ndCBnZXRcbiIsIF9fZnVuY19fKTsKPiArCQlnb3RvIGZy ZWVfZ3BpbzI7Cj4gKwl9Cj4gKwo+ICsJaGlzaV9oaWtleV91c2ItPnR5cGVjX3ZidXNfZW5hYmxl X3ZhbCA9Cj4gKwkJISFoaXNpX2hpa2V5X3VzYi0+dHlwZWNfdmJ1c19lbmFibGVfdmFsOwo+ICsK PiArCXJldCA9IGdwaW9fZGlyZWN0aW9uX291dHB1dChoaXNpX2hpa2V5X3VzYi0+dHlwZWNfdmJ1 c19ncGlvLAo+ICsJCQkJICAgIGhpc2lfaGlrZXlfdXNiLT50eXBlY192YnVzX2VuYWJsZV92YWwp Owo+ICsJaWYgKHJldCkgewo+ICsJCXByX2VycigiJXM6IHBvd2VyIG9uIHR5cGVjIHZidXMgZXJy IiwgX19mdW5jX18pOwo+ICsJCWdvdG8gZnJlZV9ncGlvMjsKPiArCX0KPiArCj4gKwlpZiAob2Zf ZGV2aWNlX2lzX2NvbXBhdGlibGUocm9vdCwgImhpc2lsaWNvbixoaWtleTk2MF91c2IiKSkgewoK SW5zdGVhZCBvZiB0aGF0IGtpbmQgb2YgY2hlY2tzLCBpc24ndCBpdCBlbm91Z2ggdG8ganVzdCB1 c2Ugb3B0aW9uYWwKZ3Bpb3M/Cgo+ICsJCWhpc2lfaGlrZXlfdXNiLT5vdGdfc3dpdGNoX2dwaW8g PSBvZl9nZXRfbmFtZWRfZ3Bpbyhyb290LAo+ICsJCQkJIm90Z19ncGlvIiwgMCk7Cj4gKwkJaWYg KCFncGlvX2lzX3ZhbGlkKGhpc2lfaGlrZXlfdXNiLT5vdGdfc3dpdGNoX2dwaW8pKSB7Cj4gKwkJ CXByX2luZm8oIiVzOiBvdGdfc3dpdGNoX2dwaW8gaXMgZXJyXG4iLCBfX2Z1bmNfXyk7Cj4gKwkJ CWdvdG8gZnJlZV9ncGlvMjsKPiArCQl9Cj4gKwo+ICsJCXJldCA9IGdwaW9fcmVxdWVzdChoaXNp X2hpa2V5X3VzYi0+b3RnX3N3aXRjaF9ncGlvLAo+ICsJCQkJIm90Z19zd2l0Y2hfZ3BpbyIpOwo+ ICsJCWlmIChyZXQpIHsKPiArCQkJaGlzaV9oaWtleV91c2ItPm90Z19zd2l0Y2hfZ3BpbyA9IElO VkFMSURfR1BJT19WQUxVRTsKPiArCQkJcHJfZXJyKCIlczogcmVxdWVzdCB0eXBlY192YnVzX2dw aW8gZXJyXG4iLCBfX2Z1bmNfXyk7Cj4gKwkJCWdvdG8gZnJlZV9ncGlvMjsKPiArCQl9Cj4gKwl9 Cj4gKwo+ICsJaGlzaV9oaWtleV91c2ItPmVkZXYgPSBkZXZtX2V4dGNvbl9kZXZfYWxsb2NhdGUo ZGV2LCB1c2JfZXh0Y29uX2NhYmxlKTsKPiArCWlmIChJU19FUlIoaGlzaV9oaWtleV91c2ItPmVk ZXYpKSB7Cj4gKwkJZGV2X2VycihkZXYsICJmYWlsZWQgdG8gYWxsb2NhdGUgZXh0Y29uIGRldmlj ZVxuIik7Cj4gKwkJZ290byBmcmVlX2dwaW8yOwo+ICsJfQo+ICsKPiArCXJldCA9IGRldm1fZXh0 Y29uX2Rldl9yZWdpc3RlcihkZXYsIGhpc2lfaGlrZXlfdXNiLT5lZGV2KTsKPiArCWlmIChyZXQg PCAwKSB7Cj4gKwkJZGV2X2VycihkZXYsICJmYWlsZWQgdG8gcmVnaXN0ZXIgZXh0Y29uIGRldmlj ZVxuIik7Cj4gKwkJZ290byBmcmVlX2dwaW8yOwo+ICsJfQo+ICsJZXh0Y29uX3NldF9zdGF0ZSho aXNpX2hpa2V5X3VzYi0+ZWRldiwgRVhUQ09OX1VTQl9IT1NULCB0cnVlKTsKCklzIHRoZSBwcmlt YXJ5IHB1cnBvc2UgZm9yIHRoaXMgZXh0Y29uIGRldmljZSB0byBzYXRpc2Z5IHRoZSBEUkQgY29k ZQppbiBkd2MzIGRyaXZlcj8KCj4gKwloaXNpX2hpa2V5X3VzYi0+cm9sZV9zdyA9IHVzYl9yb2xl X3N3aXRjaF9yZWdpc3RlcihkZXYsICZzd19kZXNjKTsKPiArCWlmIChJU19FUlIoaGlzaV9oaWtl eV91c2ItPnJvbGVfc3cpKQo+ICsJCWdvdG8gZnJlZV9ncGlvMjsKCkl0IGxvb2tzIGEgYml0IGNs dW1zeSB0byBtZSB0byByZWdpc3RlciBib3RoIHRoZSBleHRjb24gZGV2aWNlIGFuZCB0aGUKbXV4 IGRldmljZSwgYnV0IEknbSBndWVzc2luZyB5b3UgbmVlZCB0byBnZXQgYSBub3RpZmljYXRpb24g aW4gZHdjMwpkcml2ZXIgd2hlbiB0aGUgcm9sZSBjaGFuZ2VzLCByaWdodD8gUGVyaGFwcyB3ZSBz aG91bGQgc2ltcGx5IGFkZApub3RpZmljYXRpb24gY2hhaW4gdG8gdGhlIHJvbGUgbXV4IHN0cnVj dHVyZS4gVGhhdCBjb3VsZCBwb3RlbnRpYWxseQphbGxvdyB0aGlzIGtpbmQgb2YgY29kZSB0byBi ZSBvcmdhbml6ZWQgYSBiaXQgYmV0dGVyLgoKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYs IGhpc2lfaGlrZXlfdXNiKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArCj4gK2ZyZWVfZ3BpbzI6Cj4g KwlpZiAoZ3Bpb19pc192YWxpZChoaXNpX2hpa2V5X3VzYi0+dHlwZWNfdmJ1c19ncGlvKSkgewo+ ICsJCWdwaW9fZnJlZShoaXNpX2hpa2V5X3VzYi0+dHlwZWNfdmJ1c19ncGlvKTsKPiArCQloaXNp X2hpa2V5X3VzYi0+dHlwZWNfdmJ1c19ncGlvID0gSU5WQUxJRF9HUElPX1ZBTFVFOwo+ICsJfQo+ ICsKPiArZnJlZV9ncGlvMToKPiArCWlmIChncGlvX2lzX3ZhbGlkKGhpc2lfaGlrZXlfdXNiLT5o dWJfdmJ1c19ncGlvKSkgewo+ICsJCWdwaW9fZnJlZShoaXNpX2hpa2V5X3VzYi0+aHViX3ZidXNf Z3Bpbyk7Cj4gKwkJaGlzaV9oaWtleV91c2ItPmh1Yl92YnVzX2dwaW8gPSBJTlZBTElEX0dQSU9f VkFMVUU7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGludCAg aGlzaV9oaWtleV91c2JfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sK PiArCXN0cnVjdCBoaXNpX2hpa2V5X3VzYiAqaGlzaV9oaWtleV91c2IgPSBwbGF0Zm9ybV9nZXRf ZHJ2ZGF0YShwZGV2KTsKPiArCj4gKwlpZiAoZ3Bpb19pc192YWxpZChoaXNpX2hpa2V5X3VzYi0+ b3RnX3N3aXRjaF9ncGlvKSkgewo+ICsJCWdwaW9fZnJlZShoaXNpX2hpa2V5X3VzYi0+b3RnX3N3 aXRjaF9ncGlvKTsKPiArCQloaXNpX2hpa2V5X3VzYi0+b3RnX3N3aXRjaF9ncGlvID0gSU5WQUxJ RF9HUElPX1ZBTFVFOwo+ICsJfQo+ICsKPiArCWlmIChncGlvX2lzX3ZhbGlkKGhpc2lfaGlrZXlf dXNiLT50eXBlY192YnVzX2dwaW8pKSB7Cj4gKwkJZ3Bpb19mcmVlKGhpc2lfaGlrZXlfdXNiLT50 eXBlY192YnVzX2dwaW8pOwo+ICsJCWhpc2lfaGlrZXlfdXNiLT50eXBlY192YnVzX2dwaW8gPSBJ TlZBTElEX0dQSU9fVkFMVUU7Cj4gKwl9Cj4gKwo+ICsJaWYgKGdwaW9faXNfdmFsaWQoaGlzaV9o aWtleV91c2ItPmh1Yl92YnVzX2dwaW8pKSB7Cj4gKwkJZ3Bpb19mcmVlKGhpc2lfaGlrZXlfdXNi LT5odWJfdmJ1c19ncGlvKTsKPiArCQloaXNpX2hpa2V5X3VzYi0+aHViX3ZidXNfZ3BpbyA9IElO VkFMSURfR1BJT19WQUxVRTsKPiArCX0KPiArCj4gKwl1c2Jfcm9sZV9zd2l0Y2hfdW5yZWdpc3Rl cihoaXNpX2hpa2V5X3VzYi0+cm9sZV9zdyk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4g K3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkIGlkX3RhYmxlX2hpc2lfaGlrZXlfdXNi W10gPSB7Cj4gKwl7LmNvbXBhdGlibGUgPSAiaGlzaWxpY29uLGdwaW9faHVidjEifSwKPiArCXsu Y29tcGF0aWJsZSA9ICJoaXNpbGljb24saGlrZXk5NjBfdXNiIn0sCj4gKwl7fQo+ICt9Owo+ICsK PiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgIGhpc2lfaGlrZXlfdXNiX2RyaXZlciA9 IHsKPiArCS5wcm9iZSA9IGhpc2lfaGlrZXlfdXNiX3Byb2JlLAo+ICsJLnJlbW92ZSA9IGhpc2lf aGlrZXlfdXNiX3JlbW92ZSwKPiArCS5kcml2ZXIgPSB7Cj4gKwkJLm5hbWUgPSBERVZJQ0VfRFJJ VkVSX05BTUUsCj4gKwkJLm9mX21hdGNoX3RhYmxlID0gb2ZfbWF0Y2hfcHRyKGlkX3RhYmxlX2hp c2lfaGlrZXlfdXNiKSwKPiArCj4gKwl9LAo+ICt9Owo+ICsKPiArbW9kdWxlX3BsYXRmb3JtX2Ry aXZlcihoaXNpX2hpa2V5X3VzYl9kcml2ZXIpOwo+ICsKPiArTU9EVUxFX0FVVEhPUigiWXUgQ2hl biA8Y2hlbnl1NTZAaHVhd2VpLmNvbT4iKTsKPiArTU9EVUxFX0RFU0NSSVBUSU9OKCJEcml2ZXIg U3VwcG9ydCBmb3IgVVNCIGZ1bmN0aW9uYWxpdHkgb2YgSGlrZXkiKTsKPiArTU9EVUxFX0xJQ0VO U0UoIkdQTCB2MiIpOwo+IC0tIAo+IDIuMTUuMC1yYzIKCkkgdGhpbmsgeW91IGhhdmUgdG9vIG1h bnkgdGhpbmdzIGludGVncmF0ZWQgaW50byB0aGlzIG9uZSBkcml2ZXIuIElNTwppdCB3b3VsZCBh dCBsZWFzdCBiZSBiZXR0ZXIgdG8ganVzdCBsZXQgdGhlIFR5cGUtQyBwb3J0IGRyaXZlciB0YWtl CmNhcmUgb2YgVkJVUyBsaWtlIEkgbWVudGlvbmVkIGFib3ZlLiBJJ20gYWxzbyB3b25kZXJpbmcg aWYgaXQgd291bGQKbWFrZSBzZW5zZSB0byBoYW5kbGUgdGhlIHJvbGUgc3dpdGNoIGFuZCB0aGUg Imh1YiIgaW4gdGhlaXIgb3duCmRyaXZlcnMsIGJ1dCBJIGRvbid0IGtub3cgZW5vdWdoIGFib3V0 IHlvdXIgcGxhdGZvcm0gYXQgdGhpcyBwb2ludCB0bwpzYXkgZm9yIHN1cmUuCgoKYnIsCg==