From mboxrd@z Thu Jan 1 00:00:00 1970 From: miquel.raynal@bootlin.com (Miquel Raynal) Date: Fri, 29 Jun 2018 14:41:46 +0200 Subject: [PATCH v3 10/17] irqchip/irq-mvebu-sei: add new driver for Marvell SEI In-Reply-To: <24fc35a0-20c5-69fd-b098-422c5b539bd4@arm.com> References: <20180622151432.1566-1-miquel.raynal@bootlin.com> <20180622151432.1566-11-miquel.raynal@bootlin.com> <24fc35a0-20c5-69fd-b098-422c5b539bd4@arm.com> Message-ID: <20180629144146.50bd2d82@xps13> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Hi Marc, Marc Zyngier wrote on Thu, 28 Jun 2018 15:54:30 +0100: > On 22/06/18 16:14, Miquel Raynal wrote: > > This is a cascaded interrupt controller in the AP806 GIC that collapses > > SEIs (System Error Interrupt) coming from the AP and the CPs (through > > the ICU). > > > > The SEI handles up to 64 interrupts. The first 21 interrupts are wired > > from the AP. The next 43 interrupts are from the CPs and are triggered > > through MSI messages. To handle this complexity, the driver has to > > declare to the upper layer: one IRQ domain for the wired interrupts, > > one IRQ domain for the MSIs; and acts as a MSI controller ('parent') > > by declaring an MSI domain. > > > > Suggested-by: Haim Boot > > Signed-off-by: Miquel Raynal > > --- > > drivers/irqchip/Kconfig | 3 + > > drivers/irqchip/Makefile | 1 + > > drivers/irqchip/irq-mvebu-sei.c | 444 ++++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 448 insertions(+) > > create mode 100644 drivers/irqchip/irq-mvebu-sei.c > > > > diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig > > index e9233db16e03..922e2a919cf3 100644 > > --- a/drivers/irqchip/Kconfig > > +++ b/drivers/irqchip/Kconfig > > @@ -310,6 +310,9 @@ config MVEBU_ODMI > > config MVEBU_PIC > > bool > > > > +config MVEBU_SEI > > + bool > > + > > config LS_SCFG_MSI > > def_bool y if SOC_LS1021A || ARCH_LAYERSCAPE > > depends on PCI && PCI_MSI > > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile > > index 15f268f646bf..69d2ccb454ef 100644 > > --- a/drivers/irqchip/Makefile > > +++ b/drivers/irqchip/Makefile > > @@ -76,6 +76,7 @@ obj-$(CONFIG_MVEBU_GICP) += irq-mvebu-gicp.o > > obj-$(CONFIG_MVEBU_ICU) += irq-mvebu-icu.o > > obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o > > obj-$(CONFIG_MVEBU_PIC) += irq-mvebu-pic.o > > +obj-$(CONFIG_MVEBU_SEI) += irq-mvebu-sei.o > > obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o > > obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o > > obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o > > diff --git a/drivers/irqchip/irq-mvebu-sei.c b/drivers/irqchip/irq-mvebu-sei.c > > new file mode 100644 > > index 000000000000..4a62cd2385d7 > > --- /dev/null > > +++ b/drivers/irqchip/irq-mvebu-sei.c > > @@ -0,0 +1,444 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +#define pr_fmt(fmt) "mvebu-sei: " fmt > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > + > > +/* Cause register */ > > +#define GICP_SECR(idx) (0x0 + ((idx) * 0x4)) > > +/* Mask register */ > > +#define GICP_SEMR(idx) (0x20 + ((idx) * 0x4)) > > +#define GICP_SET_SEI_OFFSET 0x30 > > + > > +#define SEI_IRQ_COUNT_PER_REG 32 > > +#define SEI_IRQ_REG_COUNT 2 > > +#define SEI_IRQ_COUNT (SEI_IRQ_COUNT_PER_REG * SEI_IRQ_REG_COUNT) > > +#define SEI_IRQ_REG_IDX(irq_id) ((irq_id) / SEI_IRQ_COUNT_PER_REG) > > +#define SEI_IRQ_REG_BIT(irq_id) ((irq_id) % SEI_IRQ_COUNT_PER_REG) > > + > > +struct mvebu_sei_interrupt_range { > > + u32 first; > > + u32 number; > > nit: number is a bit vague. consider using size (or anything similar). Ack. > > > +}; > > + > > +struct mvebu_sei { > > + struct device *dev; > > + void __iomem *base; > > + struct resource *res; > > + struct irq_domain *ap_domain; > > + struct irq_domain *cp_domain; > > + struct mvebu_sei_interrupt_range ap_interrupts; > > + struct mvebu_sei_interrupt_range cp_interrupts; > > + /* Lock on MSI allocations/releases */ > > + struct mutex cp_msi_lock; > > + DECLARE_BITMAP(cp_msi_bitmap, SEI_IRQ_COUNT); > > +}; > > + > > +static int mvebu_sei_domain_to_sei_irq(struct mvebu_sei *sei, > > + struct irq_domain *domain, > > + irq_hw_number_t hwirq) > > +{ > > + if (domain == sei->ap_domain) > > + return sei->ap_interrupts.first + hwirq; > > + else > > + return sei->cp_interrupts.first + hwirq; > > +} > > + > > +static void mvebu_sei_reset(struct mvebu_sei *sei) > > +{ > > + u32 reg_idx; > > + > > + /* Clear IRQ cause registers */ > > + for (reg_idx = 0; reg_idx < SEI_IRQ_REG_COUNT; reg_idx++) > > + writel(0xFFFFFFFF, sei->base + GICP_SECR(reg_idx)); > > +} > > + > > +static void mvebu_sei_mask_irq(struct irq_data *d) > > +{ > > + struct mvebu_sei *sei = irq_data_get_irq_chip_data(d); > > + u32 sei_irq = mvebu_sei_domain_to_sei_irq(sei, d->domain, d->hwirq); > > + u32 reg_idx = SEI_IRQ_REG_IDX(sei_irq); > > + u32 reg; > > + > > + /* 1 disables the interrupt */ > > + reg = readl(sei->base + GICP_SEMR(reg_idx)); > > + reg |= BIT(SEI_IRQ_REG_BIT(sei_irq)); > > + writel(reg, sei->base + GICP_SEMR(reg_idx)); > > Consider using _relaxed accessors, unless this relies on ordering with > other memory accesses (I really don't think it does). I don't think it does neither, I just forgot about the _relaxed variants. I will update for all register reads/writes. > > > +} > > + > > +static void mvebu_sei_unmask_irq(struct irq_data *d) > > +{ > > + struct mvebu_sei *sei = irq_data_get_irq_chip_data(d); > > + u32 sei_irq = mvebu_sei_domain_to_sei_irq(sei, d->domain, d->hwirq); > > + u32 reg_idx = SEI_IRQ_REG_IDX(sei_irq); > > + u32 reg; > > + > > + /* 0 enables the interrupt */ > > + reg = readl(sei->base + GICP_SEMR(reg_idx)); > > + reg &= ~BIT(SEI_IRQ_REG_BIT(sei_irq)); > > + writel(reg, sei->base + GICP_SEMR(reg_idx)); > > +} > > + > > +static void mvebu_sei_compose_msi_msg(struct irq_data *data, > > + struct msi_msg *msg) > > +{ > > + struct mvebu_sei *sei = data->chip_data; > > + phys_addr_t set = sei->res->start + GICP_SET_SEI_OFFSET; > > + > > + msg->data = mvebu_sei_domain_to_sei_irq(sei, data->domain, data->hwirq); > > + msg->address_lo = lower_32_bits(set); > > + msg->address_hi = upper_32_bits(set); > > +} > > + > > +static int mvebu_sei_ap_set_type(struct irq_data *data, unsigned int type) > > +{ > > + if (!(type & IRQ_TYPE_LEVEL_HIGH)) > > + return -EINVAL; > > + > > + return 0; > > +} > > + > > +static int mvebu_sei_cp_set_type(struct irq_data *data, unsigned int type) > > +{ > > + if (!(type & IRQ_TYPE_EDGE_RISING)) > > + return -EINVAL; > > + > > + return 0; > > +} > > + > > +static struct irq_chip mvebu_sei_ap_wired_irq_chip = { > > + .name = "AP wired SEI", > > + .irq_mask = mvebu_sei_mask_irq, > > + .irq_unmask = mvebu_sei_unmask_irq, > > + .irq_eoi = irq_chip_eoi_parent, > > + .irq_set_affinity = irq_chip_set_affinity_parent, > > + .irq_set_type = mvebu_sei_ap_set_type, > > +}; > > + > > +static struct irq_chip mvebu_sei_cp_msi_irq_chip = { > > + .name = "CP MSI SEI", > > + .irq_mask = mvebu_sei_mask_irq, > > + .irq_unmask = mvebu_sei_unmask_irq, > > + .irq_eoi = irq_chip_eoi_parent, > > + .irq_set_affinity = irq_chip_set_affinity_parent, > > + .irq_set_type = mvebu_sei_cp_set_type, > > + .irq_compose_msi_msg = mvebu_sei_compose_msi_msg, > > +}; > > + > > +static int mvebu_sei_irq_domain_alloc(struct irq_domain *domain, > > + unsigned int virq, unsigned int nr_irqs, > > + void *args) > > +{ > > + struct mvebu_sei *sei = domain->host_data; > > + struct irq_fwspec *fwspec = args; > > + struct irq_chip *irq_chip; > > + int sei_hwirq, hwirq; > > + int ret; > > + > > + /* The software only supports single allocations for now */ > > + if (nr_irqs != 1) > > + return -ENOTSUPP; > > + > > + if (domain == sei->ap_domain) { > > + irq_chip = &mvebu_sei_ap_wired_irq_chip; > > + hwirq = fwspec->param[0]; > > + } else { > > + irq_chip = &mvebu_sei_cp_msi_irq_chip; > > + mutex_lock(&sei->cp_msi_lock); > > + hwirq = bitmap_find_free_region(sei->cp_msi_bitmap, > > + sei->cp_interrupts.number, 0); > > + mutex_unlock(&sei->cp_msi_lock); > > + if (hwirq < 0) > > + return -ENOSPC; > > + } > > + > > + sei_hwirq = mvebu_sei_domain_to_sei_irq(sei, domain, hwirq); > > + > > + fwspec->fwnode = domain->parent->fwnode; > > + fwspec->param_count = 3; > > + fwspec->param[0] = GIC_SPI; > > + fwspec->param[1] = sei_hwirq; > > + fwspec->param[2] = IRQ_TYPE_EDGE_RISING; > > + > > + ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, fwspec); > > + if (ret) > > + goto release_region; > > + > > + ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, irq_chip, sei); > > + if (ret) > > + goto free_irq_parents; > > + > > + return 0; > > + > > +free_irq_parents: > > + irq_domain_free_irqs_parent(domain, virq, nr_irqs); > > +release_region: > > + if (domain == sei->cp_domain) { > > + mutex_lock(&sei->cp_msi_lock); > > + bitmap_release_region(sei->cp_msi_bitmap, hwirq, 0); > > + mutex_unlock(&sei->cp_msi_lock); > > + } > > + > > + return ret; > > +} > > + > > +static void mvebu_sei_irq_domain_free(struct irq_domain *domain, > > + unsigned int virq, unsigned int nr_irqs) > > +{ > > + struct mvebu_sei *sei = domain->host_data; > > + struct irq_data *d = irq_domain_get_irq_data(domain, virq); > > + u32 irq_nb = sei->ap_interrupts.number + sei->cp_interrupts.number; > > + > > + if (nr_irqs != 1 || d->hwirq >= irq_nb) { > > + dev_err(sei->dev, "Invalid hwirq %lu\n", d->hwirq); > > + return; > > + } > > + > > + irq_domain_free_irqs_parent(domain, virq, nr_irqs); > > + > > + mutex_lock(&sei->cp_msi_lock); > > + bitmap_release_region(sei->cp_msi_bitmap, d->hwirq, 0); > > + mutex_unlock(&sei->cp_msi_lock); > > +} > > + > > +static int mvebu_sei_ap_match(struct irq_domain *d, struct device_node *node, > > + enum irq_domain_bus_token bus_token) > > +{ > > + struct mvebu_sei *sei = d->host_data; > > If you're dereferencing the domain here... > > > + > > + if (!sei) > > + return 0; > > + > > + if (sei->dev->of_node != node) > > + return 0; > > + > > + if (!d || !sei->ap_domain) > > ... how can it be NULL here? Actually, how can it *ever* be NULL? Over-sanitization indeed. d cannot be NULL. > > Also, it is not clear to me how can sei or sei->ap_domain be NULL. I misread some internal functions of the core and after a second look you are right that there is no possibility for both of them to be NULL. I'll simplify. > > > + return 0; > > + > > + if (d == sei->ap_domain) > > + return 1; > > + > > + return 0; > > +} > > + > > +static const struct irq_domain_ops mvebu_sei_ap_domain_ops = { > > + .match = mvebu_sei_ap_match, > > + .xlate = irq_domain_xlate_onecell, > > + .alloc = mvebu_sei_irq_domain_alloc, > > + .free = mvebu_sei_irq_domain_free, > > +}; > > + > > +static const struct irq_domain_ops mvebu_sei_cp_domain_ops = { > > + .alloc = mvebu_sei_irq_domain_alloc, > > + .free = mvebu_sei_irq_domain_free, > > +}; > > + > > +static struct irq_chip mvebu_sei_msi_irq_chip = { > > + .name = "SEI MSI controller", > > + .irq_set_type = mvebu_sei_cp_set_type, > > +}; > > + > > +static struct msi_domain_ops mvebu_sei_msi_ops = { > > +}; > > + > > +static struct msi_domain_info mvebu_sei_msi_domain_info = { > > + .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS, > > + .ops = &mvebu_sei_msi_ops, > > + .chip = &mvebu_sei_msi_irq_chip, > > +}; > > + > > +static void mvebu_sei_handle_cascade_irq(struct irq_desc *desc) > > +{ > > + struct mvebu_sei *sei = irq_desc_get_handler_data(desc); > > + struct irq_chip *chip = irq_desc_get_chip(desc); > > + unsigned long irqmap, irq_bit; > > + u32 reg_idx, virq, irqn; > > + > > + chained_irq_enter(chip, desc); > > + > > + /* Read both SEI cause registers (64 bits) */ > > + for (reg_idx = 0; reg_idx < SEI_IRQ_REG_COUNT; reg_idx++) { > > + irqmap = readl_relaxed(sei->base + GICP_SECR(reg_idx)); > > I think it'd be a lot clearer if you just read both 32bit registers and > treat the resulting 64bit quantity as a single bitmap, rather than > having this outer loop. True, there is no need for this outer loop once the bitmap is 64-bit wide. > > > + > > + /* Call handler for each set bit */ > > + for_each_set_bit(irq_bit, &irqmap, SEI_IRQ_COUNT_PER_REG) { > > + /* Cause Register gives the SEI number */ > > + irqn = irq_bit + reg_idx * SEI_IRQ_COUNT_PER_REG; > > + /* > > + * Finding Linux mapping (virq) needs the right domain > > + * and the relative hwirq (which start at 0 in both > > + * cases, while irqn is relative to all SEI interrupts). > > + */ > > + if (irqn < sei->ap_interrupts.number) { > > + virq = irq_find_mapping(sei->ap_domain, irqn); > > + } else { > > + irqn -= sei->ap_interrupts.number; > > + virq = irq_find_mapping(sei->cp_domain, irqn); > > + } > > + > > + /* Call IRQ handler */ > > + generic_handle_irq(virq); > > + } > > + > > + /* Clear interrupt indication by writing 1 to it */ > > + writel(irqmap, sei->base + GICP_SECR(reg_idx)); > > write_relaxed. It would probably make sense not to write to that > register if no bits were set to 1 the first place. Will do it. > > > + } > > + > > + chained_irq_exit(chip, desc); > > +} > > + > > +static int mvebu_sei_probe(struct platform_device *pdev) > > +{ > > + struct device_node *node = pdev->dev.of_node, *parent; > > + struct irq_domain *parent_domain, *plat_domain; > > + struct mvebu_sei *sei; > > + const __be32 *property; > > + u32 parent_irq, size; > > + int ret; > > + > > + sei = devm_kzalloc(&pdev->dev, sizeof(*sei), GFP_KERNEL); > > + if (!sei) > > + return -ENOMEM; > > + > > + sei->dev = &pdev->dev; > > + > > + mutex_init(&sei->cp_msi_lock); > > + > > + sei->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > + sei->base = devm_ioremap_resource(sei->dev, sei->res); > > + if (!sei->base) { > > + dev_err(sei->dev, "Failed to remap SEI resource\n"); > > + return -ENODEV; > > + } > > + > > + mvebu_sei_reset(sei); > > + > > + /* > > + * Reserve the single (top-level) parent SPI IRQ from which all the > > + * interrupts handled by this driver will be signaled. > > + */ > > + parent_irq = irq_of_parse_and_map(node, 0); > > + if (parent_irq <= 0) { > > + dev_err(sei->dev, "Failed to retrieve top-level SPI IRQ\n"); > > + return -ENODEV; > > + } > > + > > + irq_set_chained_handler(parent_irq, mvebu_sei_handle_cascade_irq); > > + irq_set_handler_data(parent_irq, sei); > > + > > + /* > > + * SEIs can be triggered from the AP through wired interrupts and from > > + * the CPs through MSIs. > > + */ > > + > > + /* Get a reference to the parent domain to create a hierarchy */ > > + parent = of_irq_find_parent(node); > > + if (!parent) { > > + dev_err(sei->dev, "Failed to find parent IRQ node\n"); > > + ret = -ENODEV; > > + goto dispose_irq; > > + } > > Wouldn't it make sense to check this before having configured things > with a chained handler? i.e. check everything that can be checked, and > once you have everything in order, do the plumbing? Ok > > > + > > + parent_domain = irq_find_host(parent); > > + if (!parent_domain) { > > + dev_err(sei->dev, "Failed to find parent IRQ domain\n"); > > + ret = -ENODEV; > > + goto dispose_irq; > > + } > > + > > + /* > > + * Retrieve the IRQ organization (AP/CP): the index of the first one and > > + * the number of them for each domain. > > + */ > > + property = of_get_property(node, "marvell,sei-ap-ranges", &size); > > + if (!property || (size != (2 * sizeof(u32)))) { > > + dev_err(sei->dev, "Missing 'marvell,sei-ap-ranges' property\n"); > > + ret = -ENODEV; > > + goto dispose_irq; > > + } > > + > > + sei->ap_interrupts.first = be32_to_cpu(property[0]); > > + sei->ap_interrupts.number = be32_to_cpu(property[1]); > > + > > + property = of_get_property(node, "marvell,sei-cp-ranges", &size); > > + if (!property || (size != (2 * sizeof(u32)))) { > > + dev_err(sei->dev, "Missing 'marvell,sei-cp-ranges' property\n"); > > + ret = -ENODEV; > > + goto dispose_irq; > > + } > > + > > + sei->cp_interrupts.first = be32_to_cpu(property[0]); > > + sei->cp_interrupts.number = be32_to_cpu(property[1]); > > + > > + /* Create the 'wired' hierarchy */ > > + sei->ap_domain = irq_domain_create_hierarchy(parent_domain, 0, > > + sei->ap_interrupts.number, > > + of_node_to_fwnode(node), > > + &mvebu_sei_ap_domain_ops, > > + sei); > > + if (!sei->ap_domain) { > > + dev_err(sei->dev, "Failed to create AP IRQ domain\n"); > > + ret = -ENOMEM; > > + goto dispose_irq; > > + } > > + > > + /* Create the 'MSI' hierarchy */ > > + sei->cp_domain = irq_domain_create_hierarchy(parent_domain, 0, > > + sei->cp_interrupts.number, > > + of_node_to_fwnode(node), > > + &mvebu_sei_cp_domain_ops, > > + sei); > > + if (!sei->cp_domain) { > > + pr_err("Failed to create CPs IRQ domain\n"); > > + ret = -ENOMEM; > > + goto remove_ap_domain; > > + } > > + > > + plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node), > > + &mvebu_sei_msi_domain_info, > > + sei->cp_domain); > > + if (!plat_domain) { > > + pr_err("Failed to create CPs MSI domain\n"); > > + ret = -ENOMEM; > > + goto remove_cp_domain; > > + } > > + > > + platform_set_drvdata(pdev, sei); > > + > > + return 0; > > + > > +remove_cp_domain: > > + irq_domain_remove(sei->cp_domain); > > +remove_ap_domain: > > + irq_domain_remove(sei->ap_domain); > > +dispose_irq: > > + irq_dispose_mapping(parent_irq); > > + > > + return ret; > > +} > > + > > +static const struct of_device_id mvebu_sei_of_match[] = { > > + { .compatible = "marvell,armada-8k-sei", }, > > + {}, > > +}; > > + > > +static struct platform_driver mvebu_sei_driver = { > > + .probe = mvebu_sei_probe, > > + .driver = { > > + .name = "mvebu-sei", > > + .of_match_table = mvebu_sei_of_match, > > + }, > > +}; > > +builtin_platform_driver(mvebu_sei_driver); > > > > Thanks, > > M. Thanks, Miqu?l From mboxrd@z Thu Jan 1 00:00:00 1970 From: Miquel Raynal Subject: Re: [PATCH v3 10/17] irqchip/irq-mvebu-sei: add new driver for Marvell SEI Date: Fri, 29 Jun 2018 14:41:46 +0200 Message-ID: <20180629144146.50bd2d82@xps13> References: <20180622151432.1566-1-miquel.raynal@bootlin.com> <20180622151432.1566-11-miquel.raynal@bootlin.com> <24fc35a0-20c5-69fd-b098-422c5b539bd4@arm.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <24fc35a0-20c5-69fd-b098-422c5b539bd4@arm.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org To: Marc Zyngier Cc: Mark Rutland , Andrew Lunn , Jason Cooper , devicetree@vger.kernel.org, Antoine Tenart , Catalin Marinas , Gregory Clement , Haim Boot , Will Deacon , Maxime Chevallier , Nadav Haklai , Rob Herring , Thomas Petazzoni , Thomas Gleixner , Hanna Hawa , linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth List-Id: devicetree@vger.kernel.org SGkgTWFyYywKCk1hcmMgWnluZ2llciA8bWFyYy56eW5naWVyQGFybS5jb20+IHdyb3RlIG9uIFRo dSwgMjggSnVuIDIwMTggMTU6NTQ6MzAKKzAxMDA6Cgo+IE9uIDIyLzA2LzE4IDE2OjE0LCBNaXF1 ZWwgUmF5bmFsIHdyb3RlOgo+ID4gVGhpcyBpcyBhIGNhc2NhZGVkIGludGVycnVwdCBjb250cm9s bGVyIGluIHRoZSBBUDgwNiBHSUMgdGhhdCBjb2xsYXBzZXMKPiA+IFNFSXMgKFN5c3RlbSBFcnJv ciBJbnRlcnJ1cHQpIGNvbWluZyBmcm9tIHRoZSBBUCBhbmQgdGhlIENQcyAodGhyb3VnaAo+ID4g dGhlIElDVSkuCj4gPiAKPiA+IFRoZSBTRUkgaGFuZGxlcyB1cCB0byA2NCBpbnRlcnJ1cHRzLiBU aGUgZmlyc3QgMjEgaW50ZXJydXB0cyBhcmUgd2lyZWQKPiA+IGZyb20gdGhlIEFQLiBUaGUgbmV4 dCA0MyBpbnRlcnJ1cHRzIGFyZSBmcm9tIHRoZSBDUHMgYW5kIGFyZSB0cmlnZ2VyZWQKPiA+IHRo cm91Z2ggTVNJIG1lc3NhZ2VzLiBUbyBoYW5kbGUgdGhpcyBjb21wbGV4aXR5LCB0aGUgZHJpdmVy IGhhcyB0bwo+ID4gZGVjbGFyZSB0byB0aGUgdXBwZXIgbGF5ZXI6IG9uZSBJUlEgZG9tYWluIGZv ciB0aGUgd2lyZWQgaW50ZXJydXB0cywKPiA+IG9uZSBJUlEgZG9tYWluIGZvciB0aGUgTVNJczsg YW5kIGFjdHMgYXMgYSBNU0kgY29udHJvbGxlciAoJ3BhcmVudCcpCj4gPiBieSBkZWNsYXJpbmcg YW4gTVNJIGRvbWFpbi4KPiA+IAo+ID4gU3VnZ2VzdGVkLWJ5OiBIYWltIEJvb3QgPGhheWltQG1h cnZlbGwuY29tPgo+ID4gU2lnbmVkLW9mZi1ieTogTWlxdWVsIFJheW5hbCA8bWlxdWVsLnJheW5h bEBib290bGluLmNvbT4KPiA+IC0tLQo+ID4gIGRyaXZlcnMvaXJxY2hpcC9LY29uZmlnICAgICAg ICAgfCAgIDMgKwo+ID4gIGRyaXZlcnMvaXJxY2hpcC9NYWtlZmlsZSAgICAgICAgfCAgIDEgKwo+ ID4gIGRyaXZlcnMvaXJxY2hpcC9pcnEtbXZlYnUtc2VpLmMgfCA0NDQgKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKwo+ID4gIDMgZmlsZXMgY2hhbmdlZCwgNDQ4IGluc2Vy dGlvbnMoKykKPiA+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9pcnFjaGlwL2lycS1tdmVi dS1zZWkuYwo+ID4gCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9pcnFjaGlwL0tjb25maWcgYi9k cml2ZXJzL2lycWNoaXAvS2NvbmZpZwo+ID4gaW5kZXggZTkyMzNkYjE2ZTAzLi45MjJlMmE5MTlj ZjMgMTAwNjQ0Cj4gPiAtLS0gYS9kcml2ZXJzL2lycWNoaXAvS2NvbmZpZwo+ID4gKysrIGIvZHJp dmVycy9pcnFjaGlwL0tjb25maWcKPiA+IEBAIC0zMTAsNiArMzEwLDkgQEAgY29uZmlnIE1WRUJV X09ETUkKPiA+ICBjb25maWcgTVZFQlVfUElDCj4gPiAgCWJvb2wKPiA+ICAKPiA+ICtjb25maWcg TVZFQlVfU0VJCj4gPiArICAgICAgICBib29sCj4gPiArCj4gPiAgY29uZmlnIExTX1NDRkdfTVNJ Cj4gPiAgCWRlZl9ib29sIHkgaWYgU09DX0xTMTAyMUEgfHwgQVJDSF9MQVlFUlNDQVBFCj4gPiAg CWRlcGVuZHMgb24gUENJICYmIFBDSV9NU0kKPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2lycWNo aXAvTWFrZWZpbGUgYi9kcml2ZXJzL2lycWNoaXAvTWFrZWZpbGUKPiA+IGluZGV4IDE1ZjI2OGY2 NDZiZi4uNjlkMmNjYjQ1NGVmIDEwMDY0NAo+ID4gLS0tIGEvZHJpdmVycy9pcnFjaGlwL01ha2Vm aWxlCj4gPiArKysgYi9kcml2ZXJzL2lycWNoaXAvTWFrZWZpbGUKPiA+IEBAIC03Niw2ICs3Niw3 IEBAIG9iai0kKENPTkZJR19NVkVCVV9HSUNQKQkJKz0gaXJxLW12ZWJ1LWdpY3Aubwo+ID4gIG9i ai0kKENPTkZJR19NVkVCVV9JQ1UpCQkJKz0gaXJxLW12ZWJ1LWljdS5vCj4gPiAgb2JqLSQoQ09O RklHX01WRUJVX09ETUkpCQkrPSBpcnEtbXZlYnUtb2RtaS5vCj4gPiAgb2JqLSQoQ09ORklHX01W RUJVX1BJQykJCQkrPSBpcnEtbXZlYnUtcGljLm8KPiA+ICtvYmotJChDT05GSUdfTVZFQlVfU0VJ KQkJCSs9IGlycS1tdmVidS1zZWkubwo+ID4gIG9iai0kKENPTkZJR19MU19TQ0ZHX01TSSkJCSs9 IGlycS1scy1zY2ZnLW1zaS5vCj4gPiAgb2JqLSQoQ09ORklHX0VaTlBTX0dJQykJCQkrPSBpcnEt ZXpucHMubwo+ID4gIG9iai0kKENPTkZJR19BUkNIX0FTUEVFRCkJCSs9IGlycS1hc3BlZWQtdmlj Lm8gaXJxLWFzcGVlZC1pMmMtaWMubwo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvaXJxY2hpcC9p cnEtbXZlYnUtc2VpLmMgYi9kcml2ZXJzL2lycWNoaXAvaXJxLW12ZWJ1LXNlaS5jCj4gPiBuZXcg ZmlsZSBtb2RlIDEwMDY0NAo+ID4gaW5kZXggMDAwMDAwMDAwMDAwLi40YTYyY2QyMzg1ZDcKPiA+ IC0tLSAvZGV2L251bGwKPiA+ICsrKyBiL2RyaXZlcnMvaXJxY2hpcC9pcnEtbXZlYnUtc2VpLmMK PiA+IEBAIC0wLDAgKzEsNDQ0IEBACj4gPiArLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQ TC0yLjAKPiA+ICsKPiA+ICsjZGVmaW5lIHByX2ZtdChmbXQpICJtdmVidS1zZWk6ICIgZm10Cj4g PiArCj4gPiArI2luY2x1ZGUgPGxpbnV4L2lycS5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9pbnRl cnJ1cHQuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvaXJxY2hpcC9jaGFpbmVkX2lycS5oPgo+ID4g KyNpbmNsdWRlIDxsaW51eC9pcnFkb21haW4uaD4KPiA+ICsjaW5jbHVkZSA8bGludXgva2VybmVs Lmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L29mX2FkZHJlc3MuaD4KPiA+ICsjaW5jbHVkZSA8bGlu dXgvb2ZfaXJxLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L29mX3BsYXRmb3JtLmg+Cj4gPiArI2lu Y2x1ZGUgPGxpbnV4L21zaS5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2Uu aD4KPiA+ICsjaW5jbHVkZSA8bGludXgvaXJxY2hpcC5oPgo+ID4gKwo+ID4gKyNpbmNsdWRlIDxk dC1iaW5kaW5ncy9pbnRlcnJ1cHQtY29udHJvbGxlci9hcm0tZ2ljLmg+Cj4gPiArCj4gPiArLyog Q2F1c2UgcmVnaXN0ZXIgKi8KPiA+ICsjZGVmaW5lIEdJQ1BfU0VDUihpZHgpCQkoMHgwICArICgo aWR4KSAqIDB4NCkpCj4gPiArLyogTWFzayByZWdpc3RlciAqLwo+ID4gKyNkZWZpbmUgR0lDUF9T RU1SKGlkeCkJCSgweDIwICsgKChpZHgpICogMHg0KSkKPiA+ICsjZGVmaW5lIEdJQ1BfU0VUX1NF SV9PRkZTRVQJMHgzMAo+ID4gKwo+ID4gKyNkZWZpbmUgU0VJX0lSUV9DT1VOVF9QRVJfUkVHCTMy Cj4gPiArI2RlZmluZSBTRUlfSVJRX1JFR19DT1VOVAkyCj4gPiArI2RlZmluZSBTRUlfSVJRX0NP VU5UCQkoU0VJX0lSUV9DT1VOVF9QRVJfUkVHICogU0VJX0lSUV9SRUdfQ09VTlQpCj4gPiArI2Rl ZmluZSBTRUlfSVJRX1JFR19JRFgoaXJxX2lkKQkoKGlycV9pZCkgLyBTRUlfSVJRX0NPVU5UX1BF Ul9SRUcpCj4gPiArI2RlZmluZSBTRUlfSVJRX1JFR19CSVQoaXJxX2lkKQkoKGlycV9pZCkgJSBT RUlfSVJRX0NPVU5UX1BFUl9SRUcpCj4gPiArCj4gPiArc3RydWN0IG12ZWJ1X3NlaV9pbnRlcnJ1 cHRfcmFuZ2Ugewo+ID4gKwl1MzIgZmlyc3Q7Cj4gPiArCXUzMiBudW1iZXI7ICAKPiAKPiBuaXQ6 IG51bWJlciBpcyBhIGJpdCB2YWd1ZS4gY29uc2lkZXIgdXNpbmcgc2l6ZSAob3IgYW55dGhpbmcg c2ltaWxhcikuCgpBY2suCgo+IAo+ID4gK307Cj4gPiArCj4gPiArc3RydWN0IG12ZWJ1X3NlaSB7 Cj4gPiArCXN0cnVjdCBkZXZpY2UgKmRldjsKPiA+ICsJdm9pZCBfX2lvbWVtICpiYXNlOwo+ID4g KwlzdHJ1Y3QgcmVzb3VyY2UgKnJlczsKPiA+ICsJc3RydWN0IGlycV9kb21haW4gKmFwX2RvbWFp bjsKPiA+ICsJc3RydWN0IGlycV9kb21haW4gKmNwX2RvbWFpbjsKPiA+ICsJc3RydWN0IG12ZWJ1 X3NlaV9pbnRlcnJ1cHRfcmFuZ2UgYXBfaW50ZXJydXB0czsKPiA+ICsJc3RydWN0IG12ZWJ1X3Nl aV9pbnRlcnJ1cHRfcmFuZ2UgY3BfaW50ZXJydXB0czsKPiA+ICsJLyogTG9jayBvbiBNU0kgYWxs b2NhdGlvbnMvcmVsZWFzZXMgKi8KPiA+ICsJc3RydWN0IG11dGV4IGNwX21zaV9sb2NrOwo+ID4g KwlERUNMQVJFX0JJVE1BUChjcF9tc2lfYml0bWFwLCBTRUlfSVJRX0NPVU5UKTsKPiA+ICt9Owo+ ID4gKwo+ID4gK3N0YXRpYyBpbnQgbXZlYnVfc2VpX2RvbWFpbl90b19zZWlfaXJxKHN0cnVjdCBt dmVidV9zZWkgKnNlaSwKPiA+ICsJCQkJICAgICAgIHN0cnVjdCBpcnFfZG9tYWluICpkb21haW4s Cj4gPiArCQkJCSAgICAgICBpcnFfaHdfbnVtYmVyX3QgaHdpcnEpCj4gPiArewo+ID4gKwlpZiAo ZG9tYWluID09IHNlaS0+YXBfZG9tYWluKQo+ID4gKwkJcmV0dXJuIHNlaS0+YXBfaW50ZXJydXB0 cy5maXJzdCArIGh3aXJxOwo+ID4gKwllbHNlCj4gPiArCQlyZXR1cm4gc2VpLT5jcF9pbnRlcnJ1 cHRzLmZpcnN0ICsgaHdpcnE7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyB2b2lkIG12ZWJ1X3Nl aV9yZXNldChzdHJ1Y3QgbXZlYnVfc2VpICpzZWkpCj4gPiArewo+ID4gKwl1MzIgcmVnX2lkeDsK PiA+ICsKPiA+ICsJLyogQ2xlYXIgSVJRIGNhdXNlIHJlZ2lzdGVycyAqLwo+ID4gKwlmb3IgKHJl Z19pZHggPSAwOyByZWdfaWR4IDwgU0VJX0lSUV9SRUdfQ09VTlQ7IHJlZ19pZHgrKykKPiA+ICsJ CXdyaXRlbCgweEZGRkZGRkZGLCBzZWktPmJhc2UgKyBHSUNQX1NFQ1IocmVnX2lkeCkpOwo+ID4g K30KPiA+ICsKPiA+ICtzdGF0aWMgdm9pZCBtdmVidV9zZWlfbWFza19pcnEoc3RydWN0IGlycV9k YXRhICpkKQo+ID4gK3sKPiA+ICsJc3RydWN0IG12ZWJ1X3NlaSAqc2VpID0gaXJxX2RhdGFfZ2V0 X2lycV9jaGlwX2RhdGEoZCk7Cj4gPiArCXUzMiBzZWlfaXJxID0gbXZlYnVfc2VpX2RvbWFpbl90 b19zZWlfaXJxKHNlaSwgZC0+ZG9tYWluLCBkLT5od2lycSk7Cj4gPiArCXUzMiByZWdfaWR4ID0g U0VJX0lSUV9SRUdfSURYKHNlaV9pcnEpOwo+ID4gKwl1MzIgcmVnOwo+ID4gKwo+ID4gKwkvKiAx IGRpc2FibGVzIHRoZSBpbnRlcnJ1cHQgKi8KPiA+ICsJcmVnID0gcmVhZGwoc2VpLT5iYXNlICsg R0lDUF9TRU1SKHJlZ19pZHgpKTsKPiA+ICsJcmVnIHw9IEJJVChTRUlfSVJRX1JFR19CSVQoc2Vp X2lycSkpOwo+ID4gKwl3cml0ZWwocmVnLCBzZWktPmJhc2UgKyBHSUNQX1NFTVIocmVnX2lkeCkp OyAgCj4gCj4gQ29uc2lkZXIgdXNpbmcgX3JlbGF4ZWQgYWNjZXNzb3JzLCB1bmxlc3MgdGhpcyBy ZWxpZXMgb24gb3JkZXJpbmcgd2l0aAo+IG90aGVyIG1lbW9yeSBhY2Nlc3NlcyAoSSByZWFsbHkg ZG9uJ3QgdGhpbmsgaXQgZG9lcykuCgpJIGRvbid0IHRoaW5rIGl0IGRvZXMgbmVpdGhlciwgSSBq dXN0IGZvcmdvdCBhYm91dCB0aGUgX3JlbGF4ZWQKdmFyaWFudHMuIEkgd2lsbCB1cGRhdGUgZm9y IGFsbCByZWdpc3RlciByZWFkcy93cml0ZXMuCgo+IAo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMg dm9pZCBtdmVidV9zZWlfdW5tYXNrX2lycShzdHJ1Y3QgaXJxX2RhdGEgKmQpCj4gPiArewo+ID4g KwlzdHJ1Y3QgbXZlYnVfc2VpICpzZWkgPSBpcnFfZGF0YV9nZXRfaXJxX2NoaXBfZGF0YShkKTsK PiA+ICsJdTMyIHNlaV9pcnEgPSBtdmVidV9zZWlfZG9tYWluX3RvX3NlaV9pcnEoc2VpLCBkLT5k b21haW4sIGQtPmh3aXJxKTsKPiA+ICsJdTMyIHJlZ19pZHggPSBTRUlfSVJRX1JFR19JRFgoc2Vp X2lycSk7Cj4gPiArCXUzMiByZWc7Cj4gPiArCj4gPiArCS8qIDAgZW5hYmxlcyB0aGUgaW50ZXJy dXB0ICovCj4gPiArCXJlZyA9IHJlYWRsKHNlaS0+YmFzZSArIEdJQ1BfU0VNUihyZWdfaWR4KSk7 Cj4gPiArCXJlZyAmPSB+QklUKFNFSV9JUlFfUkVHX0JJVChzZWlfaXJxKSk7Cj4gPiArCXdyaXRl bChyZWcsIHNlaS0+YmFzZSArIEdJQ1BfU0VNUihyZWdfaWR4KSk7Cj4gPiArfQo+ID4gKwo+ID4g K3N0YXRpYyB2b2lkIG12ZWJ1X3NlaV9jb21wb3NlX21zaV9tc2coc3RydWN0IGlycV9kYXRhICpk YXRhLAo+ID4gKwkJCQkgICAgICBzdHJ1Y3QgbXNpX21zZyAqbXNnKQo+ID4gK3sKPiA+ICsJc3Ry dWN0IG12ZWJ1X3NlaSAqc2VpID0gZGF0YS0+Y2hpcF9kYXRhOwo+ID4gKwlwaHlzX2FkZHJfdCBz ZXQgPSBzZWktPnJlcy0+c3RhcnQgKyBHSUNQX1NFVF9TRUlfT0ZGU0VUOwo+ID4gKwo+ID4gKwlt c2ctPmRhdGEgPSBtdmVidV9zZWlfZG9tYWluX3RvX3NlaV9pcnEoc2VpLCBkYXRhLT5kb21haW4s IGRhdGEtPmh3aXJxKTsKPiA+ICsJbXNnLT5hZGRyZXNzX2xvID0gbG93ZXJfMzJfYml0cyhzZXQp Owo+ID4gKwltc2ctPmFkZHJlc3NfaGkgPSB1cHBlcl8zMl9iaXRzKHNldCk7Cj4gPiArfQo+ID4g Kwo+ID4gK3N0YXRpYyBpbnQgbXZlYnVfc2VpX2FwX3NldF90eXBlKHN0cnVjdCBpcnFfZGF0YSAq ZGF0YSwgdW5zaWduZWQgaW50IHR5cGUpCj4gPiArewo+ID4gKwlpZiAoISh0eXBlICYgSVJRX1RZ UEVfTEVWRUxfSElHSCkpCj4gPiArCQlyZXR1cm4gLUVJTlZBTDsKPiA+ICsKPiA+ICsJcmV0dXJu IDA7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgbXZlYnVfc2VpX2NwX3NldF90eXBlKHN0 cnVjdCBpcnFfZGF0YSAqZGF0YSwgdW5zaWduZWQgaW50IHR5cGUpCj4gPiArewo+ID4gKwlpZiAo ISh0eXBlICYgSVJRX1RZUEVfRURHRV9SSVNJTkcpKQo+ID4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4g PiArCj4gPiArCXJldHVybiAwOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgc3RydWN0IGlycV9j aGlwIG12ZWJ1X3NlaV9hcF93aXJlZF9pcnFfY2hpcCA9IHsKPiA+ICsJLm5hbWUJCQk9ICJBUCB3 aXJlZCBTRUkiLAo+ID4gKwkuaXJxX21hc2sJCT0gbXZlYnVfc2VpX21hc2tfaXJxLAo+ID4gKwku aXJxX3VubWFzawkJPSBtdmVidV9zZWlfdW5tYXNrX2lycSwKPiA+ICsJLmlycV9lb2kJCT0gaXJx X2NoaXBfZW9pX3BhcmVudCwKPiA+ICsJLmlycV9zZXRfYWZmaW5pdHkJPSBpcnFfY2hpcF9zZXRf YWZmaW5pdHlfcGFyZW50LAo+ID4gKwkuaXJxX3NldF90eXBlCQk9IG12ZWJ1X3NlaV9hcF9zZXRf dHlwZSwKPiA+ICt9Owo+ID4gKwo+ID4gK3N0YXRpYyBzdHJ1Y3QgaXJxX2NoaXAgbXZlYnVfc2Vp X2NwX21zaV9pcnFfY2hpcCA9IHsKPiA+ICsJLm5hbWUJCQk9ICJDUCBNU0kgU0VJIiwKPiA+ICsJ LmlycV9tYXNrCQk9IG12ZWJ1X3NlaV9tYXNrX2lycSwKPiA+ICsJLmlycV91bm1hc2sJCT0gbXZl YnVfc2VpX3VubWFza19pcnEsCj4gPiArCS5pcnFfZW9pCQk9IGlycV9jaGlwX2VvaV9wYXJlbnQs Cj4gPiArCS5pcnFfc2V0X2FmZmluaXR5CT0gaXJxX2NoaXBfc2V0X2FmZmluaXR5X3BhcmVudCwK PiA+ICsJLmlycV9zZXRfdHlwZQkJPSBtdmVidV9zZWlfY3Bfc2V0X3R5cGUsCj4gPiArCS5pcnFf Y29tcG9zZV9tc2lfbXNnCT0gbXZlYnVfc2VpX2NvbXBvc2VfbXNpX21zZywKPiA+ICt9Owo+ID4g Kwo+ID4gK3N0YXRpYyBpbnQgbXZlYnVfc2VpX2lycV9kb21haW5fYWxsb2Moc3RydWN0IGlycV9k b21haW4gKmRvbWFpbiwKPiA+ICsJCQkJICAgICAgdW5zaWduZWQgaW50IHZpcnEsIHVuc2lnbmVk IGludCBucl9pcnFzLAo+ID4gKwkJCQkgICAgICB2b2lkICphcmdzKQo+ID4gK3sKPiA+ICsJc3Ry dWN0IG12ZWJ1X3NlaSAqc2VpID0gZG9tYWluLT5ob3N0X2RhdGE7Cj4gPiArCXN0cnVjdCBpcnFf ZndzcGVjICpmd3NwZWMgPSBhcmdzOwo+ID4gKwlzdHJ1Y3QgaXJxX2NoaXAgKmlycV9jaGlwOwo+ ID4gKwlpbnQgc2VpX2h3aXJxLCBod2lycTsKPiA+ICsJaW50IHJldDsKPiA+ICsKPiA+ICsJLyog VGhlIHNvZnR3YXJlIG9ubHkgc3VwcG9ydHMgc2luZ2xlIGFsbG9jYXRpb25zIGZvciBub3cgKi8K PiA+ICsJaWYgKG5yX2lycXMgIT0gMSkKPiA+ICsJCXJldHVybiAtRU5PVFNVUFA7Cj4gPiArCj4g PiArCWlmIChkb21haW4gPT0gc2VpLT5hcF9kb21haW4pIHsKPiA+ICsJCWlycV9jaGlwID0gJm12 ZWJ1X3NlaV9hcF93aXJlZF9pcnFfY2hpcDsKPiA+ICsJCWh3aXJxID0gZndzcGVjLT5wYXJhbVsw XTsKPiA+ICsJfSBlbHNlIHsKPiA+ICsJCWlycV9jaGlwID0gJm12ZWJ1X3NlaV9jcF9tc2lfaXJx X2NoaXA7Cj4gPiArCQltdXRleF9sb2NrKCZzZWktPmNwX21zaV9sb2NrKTsKPiA+ICsJCWh3aXJx ID0gYml0bWFwX2ZpbmRfZnJlZV9yZWdpb24oc2VpLT5jcF9tc2lfYml0bWFwLAo+ID4gKwkJCQkJ CXNlaS0+Y3BfaW50ZXJydXB0cy5udW1iZXIsIDApOwo+ID4gKwkJbXV0ZXhfdW5sb2NrKCZzZWkt PmNwX21zaV9sb2NrKTsKPiA+ICsJCWlmIChod2lycSA8IDApCj4gPiArCQkJcmV0dXJuIC1FTk9T UEM7Cj4gPiArCX0KPiA+ICsKPiA+ICsJc2VpX2h3aXJxID0gbXZlYnVfc2VpX2RvbWFpbl90b19z ZWlfaXJxKHNlaSwgZG9tYWluLCBod2lycSk7Cj4gPiArCj4gPiArCWZ3c3BlYy0+Zndub2RlID0g ZG9tYWluLT5wYXJlbnQtPmZ3bm9kZTsKPiA+ICsJZndzcGVjLT5wYXJhbV9jb3VudCA9IDM7Cj4g PiArCWZ3c3BlYy0+cGFyYW1bMF0gPSBHSUNfU1BJOwo+ID4gKwlmd3NwZWMtPnBhcmFtWzFdID0g c2VpX2h3aXJxOwo+ID4gKwlmd3NwZWMtPnBhcmFtWzJdID0gSVJRX1RZUEVfRURHRV9SSVNJTkc7 Cj4gPiArCj4gPiArCXJldCA9IGlycV9kb21haW5fYWxsb2NfaXJxc19wYXJlbnQoZG9tYWluLCB2 aXJxLCBucl9pcnFzLCBmd3NwZWMpOwo+ID4gKwlpZiAocmV0KQo+ID4gKwkJZ290byByZWxlYXNl X3JlZ2lvbjsKPiA+ICsKPiA+ICsJcmV0ID0gaXJxX2RvbWFpbl9zZXRfaHdpcnFfYW5kX2NoaXAo ZG9tYWluLCB2aXJxLCBod2lycSwgaXJxX2NoaXAsIHNlaSk7Cj4gPiArCWlmIChyZXQpCj4gPiAr CQlnb3RvIGZyZWVfaXJxX3BhcmVudHM7Cj4gPiArCj4gPiArCXJldHVybiAwOwo+ID4gKwo+ID4g K2ZyZWVfaXJxX3BhcmVudHM6Cj4gPiArCWlycV9kb21haW5fZnJlZV9pcnFzX3BhcmVudChkb21h aW4sIHZpcnEsIG5yX2lycXMpOwo+ID4gK3JlbGVhc2VfcmVnaW9uOgo+ID4gKwlpZiAoZG9tYWlu ID09IHNlaS0+Y3BfZG9tYWluKSB7Cj4gPiArCQltdXRleF9sb2NrKCZzZWktPmNwX21zaV9sb2Nr KTsKPiA+ICsJCWJpdG1hcF9yZWxlYXNlX3JlZ2lvbihzZWktPmNwX21zaV9iaXRtYXAsIGh3aXJx LCAwKTsKPiA+ICsJCW11dGV4X3VubG9jaygmc2VpLT5jcF9tc2lfbG9jayk7Cj4gPiArCX0KPiA+ ICsKPiA+ICsJcmV0dXJuIHJldDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIHZvaWQgbXZlYnVf c2VpX2lycV9kb21haW5fZnJlZShzdHJ1Y3QgaXJxX2RvbWFpbiAqZG9tYWluLAo+ID4gKwkJCQkg ICAgICB1bnNpZ25lZCBpbnQgdmlycSwgdW5zaWduZWQgaW50IG5yX2lycXMpCj4gPiArewo+ID4g KwlzdHJ1Y3QgbXZlYnVfc2VpICpzZWkgPSBkb21haW4tPmhvc3RfZGF0YTsKPiA+ICsJc3RydWN0 IGlycV9kYXRhICpkID0gaXJxX2RvbWFpbl9nZXRfaXJxX2RhdGEoZG9tYWluLCB2aXJxKTsKPiA+ ICsJdTMyIGlycV9uYiA9IHNlaS0+YXBfaW50ZXJydXB0cy5udW1iZXIgKyBzZWktPmNwX2ludGVy cnVwdHMubnVtYmVyOwo+ID4gKwo+ID4gKwlpZiAobnJfaXJxcyAhPSAxIHx8IGQtPmh3aXJxID49 IGlycV9uYikgewo+ID4gKwkJZGV2X2VycihzZWktPmRldiwgIkludmFsaWQgaHdpcnEgJWx1XG4i LCBkLT5od2lycSk7Cj4gPiArCQlyZXR1cm47Cj4gPiArCX0KPiA+ICsKPiA+ICsJaXJxX2RvbWFp bl9mcmVlX2lycXNfcGFyZW50KGRvbWFpbiwgdmlycSwgbnJfaXJxcyk7Cj4gPiArCj4gPiArCW11 dGV4X2xvY2soJnNlaS0+Y3BfbXNpX2xvY2spOwo+ID4gKwliaXRtYXBfcmVsZWFzZV9yZWdpb24o c2VpLT5jcF9tc2lfYml0bWFwLCBkLT5od2lycSwgMCk7Cj4gPiArCW11dGV4X3VubG9jaygmc2Vp LT5jcF9tc2lfbG9jayk7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgbXZlYnVfc2VpX2Fw X21hdGNoKHN0cnVjdCBpcnFfZG9tYWluICpkLCBzdHJ1Y3QgZGV2aWNlX25vZGUgKm5vZGUsCj4g PiArCQkJICAgICAgZW51bSBpcnFfZG9tYWluX2J1c190b2tlbiBidXNfdG9rZW4pCj4gPiArewo+ ID4gKwlzdHJ1Y3QgbXZlYnVfc2VpICpzZWkgPSBkLT5ob3N0X2RhdGE7ICAKPiAKPiBJZiB5b3Un cmUgZGVyZWZlcmVuY2luZyB0aGUgZG9tYWluIGhlcmUuLi4KPiAKPiA+ICsKPiA+ICsJaWYgKCFz ZWkpCj4gPiArCQlyZXR1cm4gMDsKPiA+ICsKPiA+ICsJaWYgKHNlaS0+ZGV2LT5vZl9ub2RlICE9 IG5vZGUpCj4gPiArCQlyZXR1cm4gMDsKPiA+ICsKPiA+ICsJaWYgKCFkIHx8ICFzZWktPmFwX2Rv bWFpbikgIAo+IAo+IC4uLiBob3cgY2FuIGl0IGJlIE5VTEwgaGVyZT8gQWN0dWFsbHksIGhvdyBj YW4gaXQgKmV2ZXIqIGJlIE5VTEw/CgpPdmVyLXNhbml0aXphdGlvbiBpbmRlZWQuIGQgY2Fubm90 IGJlIE5VTEwuCgo+IAo+IEFsc28sIGl0IGlzIG5vdCBjbGVhciB0byBtZSBob3cgY2FuIHNlaSBv ciBzZWktPmFwX2RvbWFpbiBiZSBOVUxMLgoKSSBtaXNyZWFkIHNvbWUgaW50ZXJuYWwgZnVuY3Rp b25zIG9mIHRoZSBjb3JlIGFuZCBhZnRlciBhIHNlY29uZCBsb29rCnlvdSBhcmUgcmlnaHQgdGhh dCB0aGVyZSBpcyBubyBwb3NzaWJpbGl0eSBmb3IgYm90aCBvZiB0aGVtIHRvIGJlIE5VTEwuCgpJ J2xsIHNpbXBsaWZ5LgoKPiAKPiA+ICsJCXJldHVybiAwOwo+ID4gKwo+ID4gKwlpZiAoZCA9PSBz ZWktPmFwX2RvbWFpbikKPiA+ICsJCXJldHVybiAxOwo+ID4gKwo+ID4gKwlyZXR1cm4gMDsKPiA+ ICt9Cj4gPiArCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBpcnFfZG9tYWluX29wcyBtdmVidV9z ZWlfYXBfZG9tYWluX29wcyA9IHsKPiA+ICsJLm1hdGNoID0gbXZlYnVfc2VpX2FwX21hdGNoLAo+ ID4gKwkueGxhdGUgPSBpcnFfZG9tYWluX3hsYXRlX29uZWNlbGwsCj4gPiArCS5hbGxvYyA9IG12 ZWJ1X3NlaV9pcnFfZG9tYWluX2FsbG9jLAo+ID4gKwkuZnJlZSA9IG12ZWJ1X3NlaV9pcnFfZG9t YWluX2ZyZWUsCj4gPiArfTsKPiA+ICsKPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGlycV9kb21h aW5fb3BzIG12ZWJ1X3NlaV9jcF9kb21haW5fb3BzID0gewo+ID4gKwkuYWxsb2MgPSBtdmVidV9z ZWlfaXJxX2RvbWFpbl9hbGxvYywKPiA+ICsJLmZyZWUgPSBtdmVidV9zZWlfaXJxX2RvbWFpbl9m cmVlLAo+ID4gK307Cj4gPiArCj4gPiArc3RhdGljIHN0cnVjdCBpcnFfY2hpcCBtdmVidV9zZWlf bXNpX2lycV9jaGlwID0gewo+ID4gKwkubmFtZQkJPSAiU0VJIE1TSSBjb250cm9sbGVyIiwKPiA+ ICsJLmlycV9zZXRfdHlwZQk9IG12ZWJ1X3NlaV9jcF9zZXRfdHlwZSwKPiA+ICt9Owo+ID4gKwo+ ID4gK3N0YXRpYyBzdHJ1Y3QgbXNpX2RvbWFpbl9vcHMgbXZlYnVfc2VpX21zaV9vcHMgPSB7Cj4g PiArfTsKPiA+ICsKPiA+ICtzdGF0aWMgc3RydWN0IG1zaV9kb21haW5faW5mbyBtdmVidV9zZWlf bXNpX2RvbWFpbl9pbmZvID0gewo+ID4gKwkuZmxhZ3MJPSBNU0lfRkxBR19VU0VfREVGX0RPTV9P UFMgfCBNU0lfRkxBR19VU0VfREVGX0NISVBfT1BTLAo+ID4gKwkub3BzCT0gJm12ZWJ1X3NlaV9t c2lfb3BzLAo+ID4gKwkuY2hpcAk9ICZtdmVidV9zZWlfbXNpX2lycV9jaGlwLAo+ID4gK307Cj4g PiArCj4gPiArc3RhdGljIHZvaWQgbXZlYnVfc2VpX2hhbmRsZV9jYXNjYWRlX2lycShzdHJ1Y3Qg aXJxX2Rlc2MgKmRlc2MpCj4gPiArewo+ID4gKwlzdHJ1Y3QgbXZlYnVfc2VpICpzZWkgPSBpcnFf ZGVzY19nZXRfaGFuZGxlcl9kYXRhKGRlc2MpOwo+ID4gKwlzdHJ1Y3QgaXJxX2NoaXAgKmNoaXAg PSBpcnFfZGVzY19nZXRfY2hpcChkZXNjKTsKPiA+ICsJdW5zaWduZWQgbG9uZyBpcnFtYXAsIGly cV9iaXQ7Cj4gPiArCXUzMiByZWdfaWR4LCB2aXJxLCBpcnFuOwo+ID4gKwo+ID4gKwljaGFpbmVk X2lycV9lbnRlcihjaGlwLCBkZXNjKTsKPiA+ICsKPiA+ICsJLyogUmVhZCBib3RoIFNFSSBjYXVz ZSByZWdpc3RlcnMgKDY0IGJpdHMpICovCj4gPiArCWZvciAocmVnX2lkeCA9IDA7IHJlZ19pZHgg PCBTRUlfSVJRX1JFR19DT1VOVDsgcmVnX2lkeCsrKSB7Cj4gPiArCQlpcnFtYXAgPSByZWFkbF9y ZWxheGVkKHNlaS0+YmFzZSArIEdJQ1BfU0VDUihyZWdfaWR4KSk7ICAKPiAKPiBJIHRoaW5rIGl0 J2QgYmUgYSBsb3QgY2xlYXJlciBpZiB5b3UganVzdCByZWFkIGJvdGggMzJiaXQgcmVnaXN0ZXJz IGFuZAo+IHRyZWF0IHRoZSByZXN1bHRpbmcgNjRiaXQgcXVhbnRpdHkgYXMgYSBzaW5nbGUgYml0 bWFwLCByYXRoZXIgdGhhbgo+IGhhdmluZyB0aGlzIG91dGVyIGxvb3AuCgpUcnVlLCB0aGVyZSBp cyBubyBuZWVkIGZvciB0aGlzIG91dGVyIGxvb3Agb25jZSB0aGUgYml0bWFwIGlzIDY0LWJpdAp3 aWRlLgoKPiAKPiA+ICsKPiA+ICsJCS8qIENhbGwgaGFuZGxlciBmb3IgZWFjaCBzZXQgYml0ICov Cj4gPiArCQlmb3JfZWFjaF9zZXRfYml0KGlycV9iaXQsICZpcnFtYXAsIFNFSV9JUlFfQ09VTlRf UEVSX1JFRykgewo+ID4gKwkJCS8qIENhdXNlIFJlZ2lzdGVyIGdpdmVzIHRoZSBTRUkgbnVtYmVy ICovCj4gPiArCQkJaXJxbiA9IGlycV9iaXQgKyByZWdfaWR4ICogU0VJX0lSUV9DT1VOVF9QRVJf UkVHOwo+ID4gKwkJCS8qCj4gPiArCQkJICogRmluZGluZyBMaW51eCBtYXBwaW5nICh2aXJxKSBu ZWVkcyB0aGUgcmlnaHQgZG9tYWluCj4gPiArCQkJICogYW5kIHRoZSByZWxhdGl2ZSBod2lycSAo d2hpY2ggc3RhcnQgYXQgMCBpbiBib3RoCj4gPiArCQkJICogY2FzZXMsIHdoaWxlIGlycW4gaXMg cmVsYXRpdmUgdG8gYWxsIFNFSSBpbnRlcnJ1cHRzKS4KPiA+ICsJCQkgKi8KPiA+ICsJCQlpZiAo aXJxbiA8IHNlaS0+YXBfaW50ZXJydXB0cy5udW1iZXIpIHsKPiA+ICsJCQkJdmlycSA9IGlycV9m aW5kX21hcHBpbmcoc2VpLT5hcF9kb21haW4sIGlycW4pOwo+ID4gKwkJCX0gZWxzZSB7Cj4gPiAr CQkJCWlycW4gLT0gc2VpLT5hcF9pbnRlcnJ1cHRzLm51bWJlcjsKPiA+ICsJCQkJdmlycSA9IGly cV9maW5kX21hcHBpbmcoc2VpLT5jcF9kb21haW4sIGlycW4pOwo+ID4gKwkJCX0KPiA+ICsKPiA+ ICsJCQkvKiBDYWxsIElSUSBoYW5kbGVyICovCj4gPiArCQkJZ2VuZXJpY19oYW5kbGVfaXJxKHZp cnEpOwo+ID4gKwkJfQo+ID4gKwo+ID4gKwkJLyogQ2xlYXIgaW50ZXJydXB0IGluZGljYXRpb24g Ynkgd3JpdGluZyAxIHRvIGl0ICovCj4gPiArCQl3cml0ZWwoaXJxbWFwLCBzZWktPmJhc2UgKyBH SUNQX1NFQ1IocmVnX2lkeCkpOyAgCj4gCj4gd3JpdGVfcmVsYXhlZC4gSXQgd291bGQgcHJvYmFi bHkgbWFrZSBzZW5zZSBub3QgdG8gd3JpdGUgdG8gdGhhdAo+IHJlZ2lzdGVyIGlmIG5vIGJpdHMg d2VyZSBzZXQgdG8gMSB0aGUgZmlyc3QgcGxhY2UuCgpXaWxsIGRvIGl0LgoKPiAKPiA+ICsJfQo+ ID4gKwo+ID4gKwljaGFpbmVkX2lycV9leGl0KGNoaXAsIGRlc2MpOwo+ID4gK30KPiA+ICsKPiA+ ICtzdGF0aWMgaW50IG12ZWJ1X3NlaV9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2 KQo+ID4gK3sKPiA+ICsJc3RydWN0IGRldmljZV9ub2RlICpub2RlID0gcGRldi0+ZGV2Lm9mX25v ZGUsICpwYXJlbnQ7Cj4gPiArCXN0cnVjdCBpcnFfZG9tYWluICpwYXJlbnRfZG9tYWluLCAqcGxh dF9kb21haW47Cj4gPiArCXN0cnVjdCBtdmVidV9zZWkgKnNlaTsKPiA+ICsJY29uc3QgX19iZTMy ICpwcm9wZXJ0eTsKPiA+ICsJdTMyIHBhcmVudF9pcnEsIHNpemU7Cj4gPiArCWludCByZXQ7Cj4g PiArCj4gPiArCXNlaSA9IGRldm1fa3phbGxvYygmcGRldi0+ZGV2LCBzaXplb2YoKnNlaSksIEdG UF9LRVJORUwpOwo+ID4gKwlpZiAoIXNlaSkKPiA+ICsJCXJldHVybiAtRU5PTUVNOwo+ID4gKwo+ ID4gKwlzZWktPmRldiA9ICZwZGV2LT5kZXY7Cj4gPiArCj4gPiArCW11dGV4X2luaXQoJnNlaS0+ Y3BfbXNpX2xvY2spOwo+ID4gKwo+ID4gKwlzZWktPnJlcyA9IHBsYXRmb3JtX2dldF9yZXNvdXJj ZShwZGV2LCBJT1JFU09VUkNFX01FTSwgMCk7Cj4gPiArCXNlaS0+YmFzZSA9IGRldm1faW9yZW1h cF9yZXNvdXJjZShzZWktPmRldiwgc2VpLT5yZXMpOwo+ID4gKwlpZiAoIXNlaS0+YmFzZSkgewo+ ID4gKwkJZGV2X2VycihzZWktPmRldiwgIkZhaWxlZCB0byByZW1hcCBTRUkgcmVzb3VyY2VcbiIp Owo+ID4gKwkJcmV0dXJuIC1FTk9ERVY7Cj4gPiArCX0KPiA+ICsKPiA+ICsJbXZlYnVfc2VpX3Jl c2V0KHNlaSk7Cj4gPiArCj4gPiArCS8qCj4gPiArCSAqIFJlc2VydmUgdGhlIHNpbmdsZSAodG9w LWxldmVsKSBwYXJlbnQgU1BJIElSUSBmcm9tIHdoaWNoIGFsbCB0aGUKPiA+ICsJICogaW50ZXJy dXB0cyBoYW5kbGVkIGJ5IHRoaXMgZHJpdmVyIHdpbGwgYmUgc2lnbmFsZWQuCj4gPiArCSAqLwo+ ID4gKwlwYXJlbnRfaXJxID0gaXJxX29mX3BhcnNlX2FuZF9tYXAobm9kZSwgMCk7Cj4gPiArCWlm IChwYXJlbnRfaXJxIDw9IDApIHsKPiA+ICsJCWRldl9lcnIoc2VpLT5kZXYsICJGYWlsZWQgdG8g cmV0cmlldmUgdG9wLWxldmVsIFNQSSBJUlFcbiIpOwo+ID4gKwkJcmV0dXJuIC1FTk9ERVY7Cj4g PiArCX0KPiA+ICsKPiA+ICsJaXJxX3NldF9jaGFpbmVkX2hhbmRsZXIocGFyZW50X2lycSwgbXZl YnVfc2VpX2hhbmRsZV9jYXNjYWRlX2lycSk7Cj4gPiArCWlycV9zZXRfaGFuZGxlcl9kYXRhKHBh cmVudF9pcnEsIHNlaSk7Cj4gPiArCj4gPiArCS8qCj4gPiArCSAqIFNFSXMgY2FuIGJlIHRyaWdn ZXJlZCBmcm9tIHRoZSBBUCB0aHJvdWdoIHdpcmVkIGludGVycnVwdHMgYW5kIGZyb20KPiA+ICsJ ICogdGhlIENQcyB0aHJvdWdoIE1TSXMuCj4gPiArCSAqLwo+ID4gKwo+ID4gKwkvKiBHZXQgYSBy ZWZlcmVuY2UgdG8gdGhlIHBhcmVudCBkb21haW4gdG8gY3JlYXRlIGEgaGllcmFyY2h5ICovCj4g PiArCXBhcmVudCA9IG9mX2lycV9maW5kX3BhcmVudChub2RlKTsKPiA+ICsJaWYgKCFwYXJlbnQp IHsKPiA+ICsJCWRldl9lcnIoc2VpLT5kZXYsICJGYWlsZWQgdG8gZmluZCBwYXJlbnQgSVJRIG5v ZGVcbiIpOwo+ID4gKwkJcmV0ID0gLUVOT0RFVjsKPiA+ICsJCWdvdG8gZGlzcG9zZV9pcnE7Cj4g PiArCX0gIAo+IAo+IFdvdWxkbid0IGl0IG1ha2Ugc2Vuc2UgdG8gY2hlY2sgdGhpcyBiZWZvcmUg aGF2aW5nIGNvbmZpZ3VyZWQgdGhpbmdzCj4gd2l0aCBhIGNoYWluZWQgaGFuZGxlcj8gaS5lLiBj aGVjayBldmVyeXRoaW5nIHRoYXQgY2FuIGJlIGNoZWNrZWQsIGFuZAo+IG9uY2UgeW91IGhhdmUg ZXZlcnl0aGluZyBpbiBvcmRlciwgZG8gdGhlIHBsdW1iaW5nPwoKT2sKCj4gCj4gPiArCj4gPiAr CXBhcmVudF9kb21haW4gPSBpcnFfZmluZF9ob3N0KHBhcmVudCk7Cj4gPiArCWlmICghcGFyZW50 X2RvbWFpbikgewo+ID4gKwkJZGV2X2VycihzZWktPmRldiwgIkZhaWxlZCB0byBmaW5kIHBhcmVu dCBJUlEgZG9tYWluXG4iKTsKPiA+ICsJCXJldCA9IC1FTk9ERVY7Cj4gPiArCQlnb3RvIGRpc3Bv c2VfaXJxOwo+ID4gKwl9Cj4gPiArCj4gPiArCS8qCj4gPiArCSAqIFJldHJpZXZlIHRoZSBJUlEg b3JnYW5pemF0aW9uIChBUC9DUCk6IHRoZSBpbmRleCBvZiB0aGUgZmlyc3Qgb25lIGFuZAo+ID4g KwkgKiB0aGUgbnVtYmVyIG9mIHRoZW0gZm9yIGVhY2ggZG9tYWluLgo+ID4gKwkgKi8KPiA+ICsJ cHJvcGVydHkgPSBvZl9nZXRfcHJvcGVydHkobm9kZSwgIm1hcnZlbGwsc2VpLWFwLXJhbmdlcyIs ICZzaXplKTsKPiA+ICsJaWYgKCFwcm9wZXJ0eSB8fCAoc2l6ZSAhPSAoMiAqIHNpemVvZih1MzIp KSkpIHsKPiA+ICsJCWRldl9lcnIoc2VpLT5kZXYsICJNaXNzaW5nICdtYXJ2ZWxsLHNlaS1hcC1y YW5nZXMnIHByb3BlcnR5XG4iKTsKPiA+ICsJCXJldCA9IC1FTk9ERVY7Cj4gPiArCQlnb3RvIGRp c3Bvc2VfaXJxOwo+ID4gKwl9Cj4gPiArCj4gPiArCXNlaS0+YXBfaW50ZXJydXB0cy5maXJzdCA9 IGJlMzJfdG9fY3B1KHByb3BlcnR5WzBdKTsKPiA+ICsJc2VpLT5hcF9pbnRlcnJ1cHRzLm51bWJl ciA9IGJlMzJfdG9fY3B1KHByb3BlcnR5WzFdKTsKPiA+ICsKPiA+ICsJcHJvcGVydHkgPSBvZl9n ZXRfcHJvcGVydHkobm9kZSwgIm1hcnZlbGwsc2VpLWNwLXJhbmdlcyIsICZzaXplKTsKPiA+ICsJ aWYgKCFwcm9wZXJ0eSB8fCAoc2l6ZSAhPSAoMiAqIHNpemVvZih1MzIpKSkpIHsKPiA+ICsJCWRl dl9lcnIoc2VpLT5kZXYsICJNaXNzaW5nICdtYXJ2ZWxsLHNlaS1jcC1yYW5nZXMnIHByb3BlcnR5 XG4iKTsKPiA+ICsJCXJldCA9IC1FTk9ERVY7Cj4gPiArCQlnb3RvIGRpc3Bvc2VfaXJxOwo+ID4g Kwl9Cj4gPiArCj4gPiArCXNlaS0+Y3BfaW50ZXJydXB0cy5maXJzdCA9IGJlMzJfdG9fY3B1KHBy b3BlcnR5WzBdKTsKPiA+ICsJc2VpLT5jcF9pbnRlcnJ1cHRzLm51bWJlciA9IGJlMzJfdG9fY3B1 KHByb3BlcnR5WzFdKTsKPiA+ICsKPiA+ICsJLyogQ3JlYXRlIHRoZSAnd2lyZWQnIGhpZXJhcmNo eSAqLwo+ID4gKwlzZWktPmFwX2RvbWFpbiA9IGlycV9kb21haW5fY3JlYXRlX2hpZXJhcmNoeShw YXJlbnRfZG9tYWluLCAwLAo+ID4gKwkJCQkJCSAgICAgc2VpLT5hcF9pbnRlcnJ1cHRzLm51bWJl ciwKPiA+ICsJCQkJCQkgICAgIG9mX25vZGVfdG9fZndub2RlKG5vZGUpLAo+ID4gKwkJCQkJCSAg ICAgJm12ZWJ1X3NlaV9hcF9kb21haW5fb3BzLAo+ID4gKwkJCQkJCSAgICAgc2VpKTsKPiA+ICsJ aWYgKCFzZWktPmFwX2RvbWFpbikgewo+ID4gKwkJZGV2X2VycihzZWktPmRldiwgIkZhaWxlZCB0 byBjcmVhdGUgQVAgSVJRIGRvbWFpblxuIik7Cj4gPiArCQlyZXQgPSAtRU5PTUVNOwo+ID4gKwkJ Z290byBkaXNwb3NlX2lycTsKPiA+ICsJfQo+ID4gKwo+ID4gKwkvKiBDcmVhdGUgdGhlICdNU0kn IGhpZXJhcmNoeSAqLwo+ID4gKwlzZWktPmNwX2RvbWFpbiA9IGlycV9kb21haW5fY3JlYXRlX2hp ZXJhcmNoeShwYXJlbnRfZG9tYWluLCAwLAo+ID4gKwkJCQkJCSAgICAgc2VpLT5jcF9pbnRlcnJ1 cHRzLm51bWJlciwKPiA+ICsJCQkJCQkgICAgIG9mX25vZGVfdG9fZndub2RlKG5vZGUpLAo+ID4g KwkJCQkJCSAgICAgJm12ZWJ1X3NlaV9jcF9kb21haW5fb3BzLAo+ID4gKwkJCQkJCSAgICAgc2Vp KTsKPiA+ICsJaWYgKCFzZWktPmNwX2RvbWFpbikgewo+ID4gKwkJcHJfZXJyKCJGYWlsZWQgdG8g Y3JlYXRlIENQcyBJUlEgZG9tYWluXG4iKTsKPiA+ICsJCXJldCA9IC1FTk9NRU07Cj4gPiArCQln b3RvIHJlbW92ZV9hcF9kb21haW47Cj4gPiArCX0KPiA+ICsKPiA+ICsJcGxhdF9kb21haW4gPSBw bGF0Zm9ybV9tc2lfY3JlYXRlX2lycV9kb21haW4ob2Zfbm9kZV90b19md25vZGUobm9kZSksCj4g PiArCQkJCQkJICAgICAmbXZlYnVfc2VpX21zaV9kb21haW5faW5mbywKPiA+ICsJCQkJCQkgICAg IHNlaS0+Y3BfZG9tYWluKTsKPiA+ICsJaWYgKCFwbGF0X2RvbWFpbikgewo+ID4gKwkJcHJfZXJy KCJGYWlsZWQgdG8gY3JlYXRlIENQcyBNU0kgZG9tYWluXG4iKTsKPiA+ICsJCXJldCA9IC1FTk9N RU07Cj4gPiArCQlnb3RvIHJlbW92ZV9jcF9kb21haW47Cj4gPiArCX0KPiA+ICsKPiA+ICsJcGxh dGZvcm1fc2V0X2RydmRhdGEocGRldiwgc2VpKTsKPiA+ICsKPiA+ICsJcmV0dXJuIDA7Cj4gPiAr Cj4gPiArcmVtb3ZlX2NwX2RvbWFpbjoKPiA+ICsJaXJxX2RvbWFpbl9yZW1vdmUoc2VpLT5jcF9k b21haW4pOwo+ID4gK3JlbW92ZV9hcF9kb21haW46Cj4gPiArCWlycV9kb21haW5fcmVtb3ZlKHNl aS0+YXBfZG9tYWluKTsKPiA+ICtkaXNwb3NlX2lycToKPiA+ICsJaXJxX2Rpc3Bvc2VfbWFwcGlu ZyhwYXJlbnRfaXJxKTsKPiA+ICsKPiA+ICsJcmV0dXJuIHJldDsKPiA+ICt9Cj4gPiArCj4gPiAr c3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgbXZlYnVfc2VpX29mX21hdGNoW10gPSB7 Cj4gPiArCXsgLmNvbXBhdGlibGUgPSAibWFydmVsbCxhcm1hZGEtOGstc2VpIiwgfSwKPiA+ICsJ e30sCj4gPiArfTsKPiA+ICsKPiA+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBtdmVi dV9zZWlfZHJpdmVyID0gewo+ID4gKwkucHJvYmUgID0gbXZlYnVfc2VpX3Byb2JlLAo+ID4gKwku ZHJpdmVyID0gewo+ID4gKwkJLm5hbWUgPSAibXZlYnUtc2VpIiwKPiA+ICsJCS5vZl9tYXRjaF90 YWJsZSA9IG12ZWJ1X3NlaV9vZl9tYXRjaCwKPiA+ICsJfSwKPiA+ICt9Owo+ID4gK2J1aWx0aW5f cGxhdGZvcm1fZHJpdmVyKG12ZWJ1X3NlaV9kcml2ZXIpOwo+ID4gICAKPiAKPiBUaGFua3MsCj4g Cj4gCU0uCgpUaGFua3MsCk1pcXXDqGwKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1r ZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWls bWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK