From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id F32C85FEFE for ; Tue, 12 Dec 2023 16:38:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 930CF143D; Tue, 12 Dec 2023 08:39:30 -0800 (PST) Received: from raptor (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 16B2B3F738; Tue, 12 Dec 2023 08:38:38 -0800 (PST) Date: Tue, 12 Dec 2023 16:38:32 +0000 From: Alexandru Elisei To: Rob Herring Cc: catalin.marinas@arm.com, will@kernel.org, oliver.upton@linux.dev, maz@kernel.org, james.morse@arm.com, suzuki.poulose@arm.com, yuzenghui@huawei.com, arnd@arndb.de, akpm@linux-foundation.org, mingo@redhat.com, peterz@infradead.org, juri.lelli@redhat.com, vincent.guittot@linaro.org, dietmar.eggemann@arm.com, rostedt@goodmis.org, bsegall@google.com, mgorman@suse.de, bristot@redhat.com, vschneid@redhat.com, mhiramat@kernel.org, rppt@kernel.org, hughd@google.com, pcc@google.com, steven.price@arm.com, anshuman.khandual@arm.com, vincenzo.frascino@arm.com, david@redhat.com, eugenis@google.com, kcc@google.com, hyesoo.yu@samsung.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, kvmarm@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org Subject: Re: [PATCH RFC v2 11/27] arm64: mte: Reserve tag storage memory Message-ID: References: <20231119165721.9849-1-alexandru.elisei@arm.com> <20231119165721.9849-12-alexandru.elisei@arm.com> Precedence: bulk X-Mailing-List: kvmarm@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: Hi Rob, Thank you so much for the feedback, I'm not very familiar with device tree, and any comments are very useful. On Mon, Dec 11, 2023 at 11:29:40AM -0600, Rob Herring wrote: > On Sun, Nov 19, 2023 at 10:59 AM Alexandru Elisei > wrote: > > > > Allow the kernel to get the size and location of the MTE tag storage > > regions from the DTB. This memory is marked as reserved for now. > > > > The DTB node for the tag storage region is defined as: > > > > tags0: tag-storage@8f8000000 { > > compatible = "arm,mte-tag-storage"; > > reg = <0x08 0xf8000000 0x00 0x4000000>; > > block-size = <0x1000>; > > memory = <&memory0>; // Associated tagged memory node > > }; > > I skimmed thru the discussion some. If this memory range is within > main RAM, then it definitely belongs in /reserved-memory. Ok, will do that. If you don't mind, why do you say that it definitely belongs in reserved-memory? I'm not trying to argue otherwise, I'm curious about the motivation. Tag storage is not DMA and can live anywhere in memory. In arm64_memblock_init(), the kernel first removes the memory that it cannot address from memblock. For example, because it has been compiled with CONFIG_ARM64_VA_BITS_39=y. And then calls early_init_fdt_scan_reserved_mem(). What happens if reserved memory is above what the kernel can address? >From my testing, when the kernel is compiled with 39 bit VA, if I use reserved memory to discover tag storage the lives above the virtua address limit and then I try to use CMA to manage the tag storage memory, I get a kernel panic: [ 0.000000] Reserved memory: created CMA memory pool at 0x0000010000000000, size 64 MiB [ 0.000000] OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool [ 0.000000] OF: reserved mem: 0x0000010000000000..0x0000010003ffffff (65536 KiB) map reusable linux,cma [..] [ 0.806945] Unable to handle kernel paging request at virtual address 00000001fe000000 [ 0.807277] Mem abort info: [ 0.807277] ESR = 0x0000000096000005 [ 0.807693] EC = 0x25: DABT (current EL), IL = 32 bits [ 0.808110] SET = 0, FnV = 0 [ 0.808443] EA = 0, S1PTW = 0 [ 0.808526] FSC = 0x05: level 1 translation fault [ 0.808943] Data abort info: [ 0.808943] ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000 [ 0.809360] CM = 0, WnR = 0, TnD = 0, TagAccess = 0 [ 0.809776] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 [ 0.810221] [00000001fe000000] user address but active_mm is swapper [..] [ 0.820887] Call trace: [ 0.821027] cma_init_reserved_areas+0xc4/0x378 > > You need a binding for this too. By binding you mean having an yaml file in dt-schem [1] describing the tag storage node, right? [1] https://github.com/devicetree-org/dt-schema > > > The tag storage region represents the largest contiguous memory region that > > holds all the tags for the associated contiguous memory region which can be > > tagged. For example, for a 32GB contiguous tagged memory the corresponding > > tag storage region is 1GB of contiguous memory, not two adjacent 512M of > > tag storage memory. > > > > "block-size" represents the minimum multiple of 4K of tag storage where all > > the tags stored in the block correspond to a contiguous memory region. This > > is needed for platforms where the memory controller interleaves tag writes > > to memory. For example, if the memory controller interleaves tag writes for > > 256KB of contiguous memory across 8K of tag storage (2-way interleave), > > then the correct value for "block-size" is 0x2000. This value is a hardware > > property, independent of the selected kernel page size. > > > > Signed-off-by: Alexandru Elisei > > --- > > arch/arm64/Kconfig | 12 ++ > > arch/arm64/include/asm/mte_tag_storage.h | 15 ++ > > arch/arm64/kernel/Makefile | 1 + > > arch/arm64/kernel/mte_tag_storage.c | 256 +++++++++++++++++++++++ > > arch/arm64/kernel/setup.c | 7 + > > 5 files changed, 291 insertions(+) > > create mode 100644 arch/arm64/include/asm/mte_tag_storage.h > > create mode 100644 arch/arm64/kernel/mte_tag_storage.c > > > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig > > index 7b071a00425d..fe8276fdc7a8 100644 > > --- a/arch/arm64/Kconfig > > +++ b/arch/arm64/Kconfig > > @@ -2062,6 +2062,18 @@ config ARM64_MTE > > > > Documentation/arch/arm64/memory-tagging-extension.rst. > > > > +if ARM64_MTE > > +config ARM64_MTE_TAG_STORAGE > > + bool "Dynamic MTE tag storage management" > > + help > > + Adds support for dynamic management of the memory used by the hardware > > + for storing MTE tags. This memory, unlike normal memory, cannot be > > + tagged. When it is used to store tags for another memory location it > > + cannot be used for any type of allocation. > > + > > + If unsure, say N > > +endif # ARM64_MTE > > + > > endmenu # "ARMv8.5 architectural features" > > > > menu "ARMv8.7 architectural features" > > diff --git a/arch/arm64/include/asm/mte_tag_storage.h b/arch/arm64/include/asm/mte_tag_storage.h > > new file mode 100644 > > index 000000000000..8f86c4f9a7c3 > > --- /dev/null > > +++ b/arch/arm64/include/asm/mte_tag_storage.h > > @@ -0,0 +1,15 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/* > > + * Copyright (C) 2023 ARM Ltd. > > + */ > > +#ifndef __ASM_MTE_TAG_STORAGE_H > > +#define __ASM_MTE_TAG_STORAGE_H > > + > > +#ifdef CONFIG_ARM64_MTE_TAG_STORAGE > > +void mte_tag_storage_init(void); > > +#else > > +static inline void mte_tag_storage_init(void) > > +{ > > +} > > +#endif /* CONFIG_ARM64_MTE_TAG_STORAGE */ > > +#endif /* __ASM_MTE_TAG_STORAGE_H */ > > diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile > > index d95b3d6b471a..5f031bf9f8f1 100644 > > --- a/arch/arm64/kernel/Makefile > > +++ b/arch/arm64/kernel/Makefile > > @@ -70,6 +70,7 @@ obj-$(CONFIG_CRASH_CORE) += crash_core.o > > obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o > > obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o > > obj-$(CONFIG_ARM64_MTE) += mte.o > > +obj-$(CONFIG_ARM64_MTE_TAG_STORAGE) += mte_tag_storage.o > > obj-y += vdso-wrap.o > > obj-$(CONFIG_COMPAT_VDSO) += vdso32-wrap.o > > obj-$(CONFIG_UNWIND_PATCH_PAC_INTO_SCS) += patch-scs.o > > diff --git a/arch/arm64/kernel/mte_tag_storage.c b/arch/arm64/kernel/mte_tag_storage.c > > new file mode 100644 > > index 000000000000..fa6267ef8392 > > --- /dev/null > > +++ b/arch/arm64/kernel/mte_tag_storage.c > > @@ -0,0 +1,256 @@ > > +// SPDX-License-Identifier: GPL-2.0-only > > +/* > > + * Support for dynamic tag storage. > > + * > > + * Copyright (C) 2023 ARM Ltd. > > + */ > > + > > +#include > > +#include > > +#include > > You probably don't need this header. If you depend on what it > implicitly includes, then that will now break in linux-next. I'll have a look if I can remove it. Might be an artifact from an earlier version of the patches. > > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > + > > +struct tag_region { > > + struct range mem_range; /* Memory associated with the tag storage, in PFNs. */ > > + struct range tag_range; /* Tag storage memory, in PFNs. */ > > + u32 block_size; /* Tag block size, in pages. */ > > +}; > > + > > +#define MAX_TAG_REGIONS 32 > > + > > +static struct tag_region tag_regions[MAX_TAG_REGIONS]; > > +static int num_tag_regions; > > + > > +static int __init tag_storage_of_flat_get_range(unsigned long node, const __be32 *reg, > > + int reg_len, struct range *range) > > +{ > > + int addr_cells = dt_root_addr_cells; > > + int size_cells = dt_root_size_cells; > > + u64 size; > > + > > + if (reg_len / 4 > addr_cells + size_cells) > > + return -EINVAL; > > + > > + range->start = PHYS_PFN(of_read_number(reg, addr_cells)); > > + size = PHYS_PFN(of_read_number(reg + addr_cells, size_cells)); > > + if (size == 0) { > > + pr_err("Invalid node"); > > + return -EINVAL; > > + } > > + range->end = range->start + size - 1; > > We have a function to read (and translate which you forgot) addresses. > Add what's missing rather than open code your own. I must have missed that there's already a function to read addresses. Would you mind pointing me in the right direction? > > > + > > + return 0; > > +} > > + > > +static int __init tag_storage_of_flat_get_tag_range(unsigned long node, > > + struct range *tag_range) > > +{ > > + const __be32 *reg; > > + int reg_len; > > + > > + reg = of_get_flat_dt_prop(node, "reg", ®_len); > > + if (reg == NULL) { > > + pr_err("Invalid metadata node"); > > + return -EINVAL; > > + } > > + > > + return tag_storage_of_flat_get_range(node, reg, reg_len, tag_range); > > +} > > + > > +static int __init tag_storage_of_flat_get_memory_range(unsigned long node, struct range *mem) > > +{ > > + const __be32 *reg; > > + int reg_len; > > + > > + reg = of_get_flat_dt_prop(node, "linux,usable-memory", ®_len); > > + if (reg == NULL) > > + reg = of_get_flat_dt_prop(node, "reg", ®_len); > > + > > + if (reg == NULL) { > > + pr_err("Invalid memory node"); > > + return -EINVAL; > > + } > > + > > + return tag_storage_of_flat_get_range(node, reg, reg_len, mem); > > +} > > + > > +struct find_memory_node_arg { > > + unsigned long node; > > + u32 phandle; > > +}; > > + > > +static int __init fdt_find_memory_node(unsigned long node, const char *uname, > > + int depth, void *data) > > +{ > > + const char *type = of_get_flat_dt_prop(node, "device_type", NULL); > > + struct find_memory_node_arg *arg = data; > > + > > + if (depth != 1 || !type || strcmp(type, "memory") != 0) > > + return 0; > > + > > + if (of_get_flat_dt_phandle(node) == arg->phandle) { > > + arg->node = node; > > + return 1; > > + } > > + > > + return 0; > > +} > > + > > +static int __init tag_storage_get_memory_node(unsigned long tag_node, unsigned long *mem_node) > > +{ > > + struct find_memory_node_arg arg = { 0 }; > > + const __be32 *memory_prop; > > + u32 mem_phandle; > > + int ret, reg_len; > > + > > + memory_prop = of_get_flat_dt_prop(tag_node, "memory", ®_len); > > + if (!memory_prop) { > > + pr_err("Missing 'memory' property in the tag storage node"); > > + return -EINVAL; > > + } > > + > > + mem_phandle = be32_to_cpup(memory_prop); > > + arg.phandle = mem_phandle; > > + > > + ret = of_scan_flat_dt(fdt_find_memory_node, &arg); > > Do not use of_scan_flat_dt. It is a relic predating libfdt which can > get a node by phandle directly. I used that because that's what drivers/of/fdt.c uses. With reserved memory I shouldn't need it, because struct reserved_mem already includes a phandle. > > > + if (ret != 1) { > > + pr_err("Associated memory node not found"); > > + return -EINVAL; > > + } > > + > > + *mem_node = arg.node; > > + > > + return 0; > > +} > > + > > +static int __init tag_storage_of_flat_read_u32(unsigned long node, const char *propname, > > + u32 *retval) > > If you are going to make a generic function, make it for everyone. Sure. If I still need it, should I put the function in include/linux/of_fdt.h? > > > +{ > > + const __be32 *reg; > > + > > + reg = of_get_flat_dt_prop(node, propname, NULL); > > + if (!reg) > > + return -EINVAL; > > + > > + *retval = be32_to_cpup(reg); > > + return 0; > > +} > > + > > +static u32 __init get_block_size_pages(u32 block_size_bytes) > > +{ > > + u32 a = PAGE_SIZE; > > + u32 b = block_size_bytes; > > + u32 r; > > + > > + /* Find greatest common divisor using the Euclidian algorithm. */ > > + do { > > + r = a % b; > > + a = b; > > + b = r; > > + } while (b != 0); > > + > > + return PHYS_PFN(PAGE_SIZE * block_size_bytes / a); > > +} > > + > > +static int __init fdt_init_tag_storage(unsigned long node, const char *uname, > > + int depth, void *data) > > +{ > > + struct tag_region *region; > > + unsigned long mem_node; > > + struct range *mem_range; > > + struct range *tag_range; > > + u32 block_size_bytes; > > + u32 nid = 0; > > + int ret; > > + > > + if (depth != 1 || !strstr(uname, "tag-storage")) > > + return 0; > > + > > + if (!of_flat_dt_is_compatible(node, "arm,mte-tag-storage")) > > + return 0; > > + > > + if (num_tag_regions == MAX_TAG_REGIONS) { > > + pr_err("Maximum number of tag storage regions exceeded"); > > + return -EINVAL; > > + } > > + > > + region = &tag_regions[num_tag_regions]; > > + mem_range = ®ion->mem_range; > > + tag_range = ®ion->tag_range; > > + > > + ret = tag_storage_of_flat_get_tag_range(node, tag_range); > > + if (ret) { > > + pr_err("Invalid tag storage node"); > > + return ret; > > + } > > + > > + ret = tag_storage_get_memory_node(node, &mem_node); > > + if (ret) > > + return ret; > > + > > + ret = tag_storage_of_flat_get_memory_range(mem_node, mem_range); > > + if (ret) { > > + pr_err("Invalid address for associated data memory node"); > > + return ret; > > + } > > + > > + /* The tag region must exactly match the corresponding memory. */ > > + if (range_len(tag_range) * 32 != range_len(mem_range)) { > > + pr_err("Tag storage region 0x%llx-0x%llx does not cover the memory region 0x%llx-0x%llx", > > + PFN_PHYS(tag_range->start), PFN_PHYS(tag_range->end), > > + PFN_PHYS(mem_range->start), PFN_PHYS(mem_range->end)); > > + return -EINVAL; > > + } > > + > > + ret = tag_storage_of_flat_read_u32(node, "block-size", &block_size_bytes); > > + if (ret || block_size_bytes == 0) { > > + pr_err("Invalid or missing 'block-size' property"); > > + return -EINVAL; > > + } > > + region->block_size = get_block_size_pages(block_size_bytes); > > + if (range_len(tag_range) % region->block_size != 0) { > > + pr_err("Tag storage region size 0x%llx is not a multiple of block size %u", > > + PFN_PHYS(range_len(tag_range)), region->block_size); > > + return -EINVAL; > > + } > > + > > + ret = tag_storage_of_flat_read_u32(mem_node, "numa-node-id", &nid); > > I was going to say we already have a way to associate memory nodes > other nodes using "numa-node-id", so the "memory" phandle property is > somewhat redundant. Maybe the tag node should have a numa-node-id. > With that, it looks like you don't even need to access the /memory > node. Avoiding that would be good for 2 reasons. It avoids parsing > memory nodes twice and it's not the kernel's job to validate the DT. > Really, if you want memory info, you should use memblock to get it > because all the special cases of memory layout are handled. For > example you can have memory nodes with multiple 'reg' entries or > multiple memory nodes or both, and then some of those could be > contiguous. I need to have a memory node associated with the tag storage node because there is a static relationship between a page from "normal" memory and its associated tag storage. If the code doesn't know that the memory region A..B has the corresponding tag storage in the region X..Y, then it doesn't know which tag storage to reserve when a page is allocated as tagged. In the example above, assuming that page P is allocated as tagged, the corresponding tag storage page that needs to be reserved is: tag_storage_pfn = (page_to_pfn(P) - PHYS_PFN(A)) / 32* + PHYS_PFN(X) numa-node-id is not enough for this, because as far I know you can have multiple memory regions withing the same numa node. *32 tagged pages use one tag storage page to store the tags. Thanks, Alex From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6B92EC4332F for ; Tue, 12 Dec 2023 16:39:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:Cc:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=8WuI3ieK4vv4Q/HK63j+NL2EbyrAuHZ28KVgmpON2Og=; b=zT1QYoKCJNB3vq q7pQBaA7ZJo3dyx7jotB/lqotPa6BN//5YUBI3AGEYpscZjEyo/EIAni7xghLpfulOkdApuvuxYRW Q5/UZ316qSUgTsTD1r1hx3adiW4wS7FwvEw1VU3pf6S8pdzmDG+LiReJ3q2boqFHq27UjG//+gkQn F8w88firYF0BmHPyzNbQAnpBSviKAk9UGdo1cSgUmPNns4HnLlFZ1lu3jlGB/XExxSRZbDuZOcx7m HTA/crQo3E/tBunQSKwmVHQvikEIrQ5mjgL02mQTIUJ8XGEMONJiPi+qnE6crQYlRJ23HAZquaIlE XWKCxvjmQbhg2HUiMyww==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD5mV-00CFc2-2Z; Tue, 12 Dec 2023 16:38:51 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rD5mQ-00CFa9-1v for linux-arm-kernel@lists.infradead.org; Tue, 12 Dec 2023 16:38:49 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 930CF143D; Tue, 12 Dec 2023 08:39:30 -0800 (PST) Received: from raptor (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 16B2B3F738; Tue, 12 Dec 2023 08:38:38 -0800 (PST) Date: Tue, 12 Dec 2023 16:38:32 +0000 From: Alexandru Elisei To: Rob Herring Cc: catalin.marinas@arm.com, will@kernel.org, oliver.upton@linux.dev, maz@kernel.org, james.morse@arm.com, suzuki.poulose@arm.com, yuzenghui@huawei.com, arnd@arndb.de, akpm@linux-foundation.org, mingo@redhat.com, peterz@infradead.org, juri.lelli@redhat.com, vincent.guittot@linaro.org, dietmar.eggemann@arm.com, rostedt@goodmis.org, bsegall@google.com, mgorman@suse.de, bristot@redhat.com, vschneid@redhat.com, mhiramat@kernel.org, rppt@kernel.org, hughd@google.com, pcc@google.com, steven.price@arm.com, anshuman.khandual@arm.com, vincenzo.frascino@arm.com, david@redhat.com, eugenis@google.com, kcc@google.com, hyesoo.yu@samsung.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, kvmarm@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org Subject: Re: [PATCH RFC v2 11/27] arm64: mte: Reserve tag storage memory Message-ID: References: <20231119165721.9849-1-alexandru.elisei@arm.com> <20231119165721.9849-12-alexandru.elisei@arm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231212_083846_750458_FAC57977 X-CRM114-Status: GOOD ( 57.21 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org SGkgUm9iLAoKVGhhbmsgeW91IHNvIG11Y2ggZm9yIHRoZSBmZWVkYmFjaywgSSdtIG5vdCB2ZXJ5 IGZhbWlsaWFyIHdpdGggZGV2aWNlIHRyZWUsCmFuZCBhbnkgY29tbWVudHMgYXJlIHZlcnkgdXNl ZnVsLgoKT24gTW9uLCBEZWMgMTEsIDIwMjMgYXQgMTE6Mjk6NDBBTSAtMDYwMCwgUm9iIEhlcnJp bmcgd3JvdGU6Cj4gT24gU3VuLCBOb3YgMTksIDIwMjMgYXQgMTA6NTnigK9BTSBBbGV4YW5kcnUg RWxpc2VpCj4gPGFsZXhhbmRydS5lbGlzZWlAYXJtLmNvbT4gd3JvdGU6Cj4gPgo+ID4gQWxsb3cg dGhlIGtlcm5lbCB0byBnZXQgdGhlIHNpemUgYW5kIGxvY2F0aW9uIG9mIHRoZSBNVEUgdGFnIHN0 b3JhZ2UKPiA+IHJlZ2lvbnMgZnJvbSB0aGUgRFRCLiBUaGlzIG1lbW9yeSBpcyBtYXJrZWQgYXMg cmVzZXJ2ZWQgZm9yIG5vdy4KPiA+Cj4gPiBUaGUgRFRCIG5vZGUgZm9yIHRoZSB0YWcgc3RvcmFn ZSByZWdpb24gaXMgZGVmaW5lZCBhczoKPiA+Cj4gPiAgICAgICAgIHRhZ3MwOiB0YWctc3RvcmFn ZUA4ZjgwMDAwMDAgewo+ID4gICAgICAgICAgICAgICAgIGNvbXBhdGlibGUgPSAiYXJtLG10ZS10 YWctc3RvcmFnZSI7Cj4gPiAgICAgICAgICAgICAgICAgcmVnID0gPDB4MDggMHhmODAwMDAwMCAw eDAwIDB4NDAwMDAwMD47Cj4gPiAgICAgICAgICAgICAgICAgYmxvY2stc2l6ZSA9IDwweDEwMDA+ Owo+ID4gICAgICAgICAgICAgICAgIG1lbW9yeSA9IDwmbWVtb3J5MD47ICAgIC8vIEFzc29jaWF0 ZWQgdGFnZ2VkIG1lbW9yeSBub2RlCj4gPiAgICAgICAgIH07Cj4gCj4gSSBza2ltbWVkIHRocnUg dGhlIGRpc2N1c3Npb24gc29tZS4gSWYgdGhpcyBtZW1vcnkgcmFuZ2UgaXMgd2l0aGluCj4gbWFp biBSQU0sIHRoZW4gaXQgZGVmaW5pdGVseSBiZWxvbmdzIGluIC9yZXNlcnZlZC1tZW1vcnkuCgpP aywgd2lsbCBkbyB0aGF0LgoKSWYgeW91IGRvbid0IG1pbmQsIHdoeSBkbyB5b3Ugc2F5IHRoYXQg aXQgZGVmaW5pdGVseSBiZWxvbmdzIGluCnJlc2VydmVkLW1lbW9yeT8gSSdtIG5vdCB0cnlpbmcg dG8gYXJndWUgb3RoZXJ3aXNlLCBJJ20gY3VyaW91cyBhYm91dCB0aGUKbW90aXZhdGlvbi4KClRh ZyBzdG9yYWdlIGlzIG5vdCBETUEgYW5kIGNhbiBsaXZlIGFueXdoZXJlIGluIG1lbW9yeS4gSW4K YXJtNjRfbWVtYmxvY2tfaW5pdCgpLCB0aGUga2VybmVsIGZpcnN0IHJlbW92ZXMgdGhlIG1lbW9y eSB0aGF0IGl0IGNhbm5vdAphZGRyZXNzIGZyb20gbWVtYmxvY2suIEZvciBleGFtcGxlLCBiZWNh dXNlIGl0IGhhcyBiZWVuIGNvbXBpbGVkIHdpdGgKQ09ORklHX0FSTTY0X1ZBX0JJVFNfMzk9eS4g QW5kIHRoZW4gY2FsbHMKZWFybHlfaW5pdF9mZHRfc2Nhbl9yZXNlcnZlZF9tZW0oKS4KCldoYXQg aGFwcGVucyBpZiByZXNlcnZlZCBtZW1vcnkgaXMgYWJvdmUgd2hhdCB0aGUga2VybmVsIGNhbiBh ZGRyZXNzPwoKRnJvbSBteSB0ZXN0aW5nLCB3aGVuIHRoZSBrZXJuZWwgaXMgY29tcGlsZWQgd2l0 aCAzOSBiaXQgVkEsIGlmIEkgdXNlCnJlc2VydmVkIG1lbW9yeSB0byBkaXNjb3ZlciB0YWcgc3Rv cmFnZSB0aGUgbGl2ZXMgYWJvdmUgdGhlIHZpcnR1YSBhZGRyZXNzCmxpbWl0IGFuZCB0aGVuIEkg dHJ5IHRvIHVzZSBDTUEgdG8gbWFuYWdlIHRoZSB0YWcgc3RvcmFnZSBtZW1vcnksIEkgZ2V0IGEK a2VybmVsIHBhbmljOgoKWyAgICAwLjAwMDAwMF0gUmVzZXJ2ZWQgbWVtb3J5OiBjcmVhdGVkIENN QSBtZW1vcnkgcG9vbCBhdCAweDAwMDAwMTAwMDAwMDAwMDAsIHNpemUgNjQgTWlCClsgICAgMC4w MDAwMDBdIE9GOiByZXNlcnZlZCBtZW06IGluaXRpYWxpemVkIG5vZGUgbGludXgsY21hLCBjb21w YXRpYmxlIGlkIHNoYXJlZC1kbWEtcG9vbApbICAgIDAuMDAwMDAwXSBPRjogcmVzZXJ2ZWQgbWVt OiAweDAwMDAwMTAwMDAwMDAwMDAuLjB4MDAwMDAxMDAwM2ZmZmZmZiAoNjU1MzYgS2lCKSBtYXAg cmV1c2FibGUgbGludXgsY21hClsuLl0KWyAgICAwLjgwNjk0NV0gVW5hYmxlIHRvIGhhbmRsZSBr ZXJuZWwgcGFnaW5nIHJlcXVlc3QgYXQgdmlydHVhbCBhZGRyZXNzIDAwMDAwMDAxZmUwMDAwMDAK WyAgICAwLjgwNzI3N10gTWVtIGFib3J0IGluZm86ClsgICAgMC44MDcyNzddICAgRVNSID0gMHgw MDAwMDAwMDk2MDAwMDA1ClsgICAgMC44MDc2OTNdICAgRUMgPSAweDI1OiBEQUJUIChjdXJyZW50 IEVMKSwgSUwgPSAzMiBiaXRzClsgICAgMC44MDgxMTBdICAgU0VUID0gMCwgRm5WID0gMApbICAg IDAuODA4NDQzXSAgIEVBID0gMCwgUzFQVFcgPSAwClsgICAgMC44MDg1MjZdICAgRlNDID0gMHgw NTogbGV2ZWwgMSB0cmFuc2xhdGlvbiBmYXVsdApbICAgIDAuODA4OTQzXSBEYXRhIGFib3J0IGlu Zm86ClsgICAgMC44MDg5NDNdICAgSVNWID0gMCwgSVNTID0gMHgwMDAwMDAwNSwgSVNTMiA9IDB4 MDAwMDAwMDAKWyAgICAwLjgwOTM2MF0gICBDTSA9IDAsIFduUiA9IDAsIFRuRCA9IDAsIFRhZ0Fj Y2VzcyA9IDAKWyAgICAwLjgwOTc3Nl0gICBHQ1MgPSAwLCBPdmVybGF5ID0gMCwgRGlydHlCaXQg PSAwLCBYcyA9IDAKWyAgICAwLjgxMDIyMV0gWzAwMDAwMDAxZmUwMDAwMDBdIHVzZXIgYWRkcmVz cyBidXQgYWN0aXZlX21tIGlzIHN3YXBwZXIKWy4uXQpbICAgIDAuODIwODg3XSBDYWxsIHRyYWNl OgpbICAgIDAuODIxMDI3XSAgY21hX2luaXRfcmVzZXJ2ZWRfYXJlYXMrMHhjNC8weDM3OAoKPiAK PiBZb3UgbmVlZCBhIGJpbmRpbmcgZm9yIHRoaXMgdG9vLgoKQnkgYmluZGluZyB5b3UgbWVhbiBo YXZpbmcgYW4geWFtbCBmaWxlIGluIGR0LXNjaGVtIFsxXSBkZXNjcmliaW5nIHRoZSB0YWcKc3Rv cmFnZSBub2RlLCByaWdodD8KClsxXSBodHRwczovL2dpdGh1Yi5jb20vZGV2aWNldHJlZS1vcmcv ZHQtc2NoZW1hCgo+IAo+ID4gVGhlIHRhZyBzdG9yYWdlIHJlZ2lvbiByZXByZXNlbnRzIHRoZSBs YXJnZXN0IGNvbnRpZ3VvdXMgbWVtb3J5IHJlZ2lvbiB0aGF0Cj4gPiBob2xkcyBhbGwgdGhlIHRh Z3MgZm9yIHRoZSBhc3NvY2lhdGVkIGNvbnRpZ3VvdXMgbWVtb3J5IHJlZ2lvbiB3aGljaCBjYW4g YmUKPiA+IHRhZ2dlZC4gRm9yIGV4YW1wbGUsIGZvciBhIDMyR0IgY29udGlndW91cyB0YWdnZWQg bWVtb3J5IHRoZSBjb3JyZXNwb25kaW5nCj4gPiB0YWcgc3RvcmFnZSByZWdpb24gaXMgMUdCIG9m IGNvbnRpZ3VvdXMgbWVtb3J5LCBub3QgdHdvIGFkamFjZW50IDUxMk0gb2YKPiA+IHRhZyBzdG9y YWdlIG1lbW9yeS4KPiA+Cj4gPiAiYmxvY2stc2l6ZSIgcmVwcmVzZW50cyB0aGUgbWluaW11bSBt dWx0aXBsZSBvZiA0SyBvZiB0YWcgc3RvcmFnZSB3aGVyZSBhbGwKPiA+IHRoZSB0YWdzIHN0b3Jl ZCBpbiB0aGUgYmxvY2sgY29ycmVzcG9uZCB0byBhIGNvbnRpZ3VvdXMgbWVtb3J5IHJlZ2lvbi4g VGhpcwo+ID4gaXMgbmVlZGVkIGZvciBwbGF0Zm9ybXMgd2hlcmUgdGhlIG1lbW9yeSBjb250cm9s bGVyIGludGVybGVhdmVzIHRhZyB3cml0ZXMKPiA+IHRvIG1lbW9yeS4gRm9yIGV4YW1wbGUsIGlm IHRoZSBtZW1vcnkgY29udHJvbGxlciBpbnRlcmxlYXZlcyB0YWcgd3JpdGVzIGZvcgo+ID4gMjU2 S0Igb2YgY29udGlndW91cyBtZW1vcnkgYWNyb3NzIDhLIG9mIHRhZyBzdG9yYWdlICgyLXdheSBp bnRlcmxlYXZlKSwKPiA+IHRoZW4gdGhlIGNvcnJlY3QgdmFsdWUgZm9yICJibG9jay1zaXplIiBp cyAweDIwMDAuIFRoaXMgdmFsdWUgaXMgYSBoYXJkd2FyZQo+ID4gcHJvcGVydHksIGluZGVwZW5k ZW50IG9mIHRoZSBzZWxlY3RlZCBrZXJuZWwgcGFnZSBzaXplLgo+ID4KPiA+IFNpZ25lZC1vZmYt Ynk6IEFsZXhhbmRydSBFbGlzZWkgPGFsZXhhbmRydS5lbGlzZWlAYXJtLmNvbT4KPiA+IC0tLQo+ ID4gIGFyY2gvYXJtNjQvS2NvbmZpZyAgICAgICAgICAgICAgICAgICAgICAgfCAgMTIgKysKPiA+ ICBhcmNoL2FybTY0L2luY2x1ZGUvYXNtL210ZV90YWdfc3RvcmFnZS5oIHwgIDE1ICsrCj4gPiAg YXJjaC9hcm02NC9rZXJuZWwvTWFrZWZpbGUgICAgICAgICAgICAgICB8ICAgMSArCj4gPiAgYXJj aC9hcm02NC9rZXJuZWwvbXRlX3RhZ19zdG9yYWdlLmMgICAgICB8IDI1NiArKysrKysrKysrKysr KysrKysrKysrKwo+ID4gIGFyY2gvYXJtNjQva2VybmVsL3NldHVwLmMgICAgICAgICAgICAgICAg fCAgIDcgKwo+ID4gIDUgZmlsZXMgY2hhbmdlZCwgMjkxIGluc2VydGlvbnMoKykKPiA+ICBjcmVh dGUgbW9kZSAxMDA2NDQgYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9tdGVfdGFnX3N0b3JhZ2UuaAo+ ID4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBhcmNoL2FybTY0L2tlcm5lbC9tdGVfdGFnX3N0b3JhZ2Uu Ywo+ID4KPiA+IGRpZmYgLS1naXQgYS9hcmNoL2FybTY0L0tjb25maWcgYi9hcmNoL2FybTY0L0tj b25maWcKPiA+IGluZGV4IDdiMDcxYTAwNDI1ZC4uZmU4Mjc2ZmRjN2E4IDEwMDY0NAo+ID4gLS0t IGEvYXJjaC9hcm02NC9LY29uZmlnCj4gPiArKysgYi9hcmNoL2FybTY0L0tjb25maWcKPiA+IEBA IC0yMDYyLDYgKzIwNjIsMTggQEAgY29uZmlnIEFSTTY0X01URQo+ID4KPiA+ICAgICAgICAgICBE b2N1bWVudGF0aW9uL2FyY2gvYXJtNjQvbWVtb3J5LXRhZ2dpbmctZXh0ZW5zaW9uLnJzdC4KPiA+ Cj4gPiAraWYgQVJNNjRfTVRFCj4gPiArY29uZmlnIEFSTTY0X01URV9UQUdfU1RPUkFHRQo+ID4g KyAgICAgICBib29sICJEeW5hbWljIE1URSB0YWcgc3RvcmFnZSBtYW5hZ2VtZW50Igo+ID4gKyAg ICAgICBoZWxwCj4gPiArICAgICAgICAgQWRkcyBzdXBwb3J0IGZvciBkeW5hbWljIG1hbmFnZW1l bnQgb2YgdGhlIG1lbW9yeSB1c2VkIGJ5IHRoZSBoYXJkd2FyZQo+ID4gKyAgICAgICAgIGZvciBz dG9yaW5nIE1URSB0YWdzLiBUaGlzIG1lbW9yeSwgdW5saWtlIG5vcm1hbCBtZW1vcnksIGNhbm5v dCBiZQo+ID4gKyAgICAgICAgIHRhZ2dlZC4gV2hlbiBpdCBpcyB1c2VkIHRvIHN0b3JlIHRhZ3Mg Zm9yIGFub3RoZXIgbWVtb3J5IGxvY2F0aW9uIGl0Cj4gPiArICAgICAgICAgY2Fubm90IGJlIHVz ZWQgZm9yIGFueSB0eXBlIG9mIGFsbG9jYXRpb24uCj4gPiArCj4gPiArICAgICAgICAgSWYgdW5z dXJlLCBzYXkgTgo+ID4gK2VuZGlmICMgQVJNNjRfTVRFCj4gPiArCj4gPiAgZW5kbWVudSAjICJB Uk12OC41IGFyY2hpdGVjdHVyYWwgZmVhdHVyZXMiCj4gPgo+ID4gIG1lbnUgIkFSTXY4LjcgYXJj aGl0ZWN0dXJhbCBmZWF0dXJlcyIKPiA+IGRpZmYgLS1naXQgYS9hcmNoL2FybTY0L2luY2x1ZGUv YXNtL210ZV90YWdfc3RvcmFnZS5oIGIvYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9tdGVfdGFnX3N0 b3JhZ2UuaAo+ID4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiA+IGluZGV4IDAwMDAwMDAwMDAwMC4u OGY4NmM0ZjlhN2MzCj4gPiAtLS0gL2Rldi9udWxsCj4gPiArKysgYi9hcmNoL2FybTY0L2luY2x1 ZGUvYXNtL210ZV90YWdfc3RvcmFnZS5oCj4gPiBAQCAtMCwwICsxLDE1IEBACj4gPiArLyogU1BE WC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAgKi8KPiA+ICsvKgo+ID4gKyAqIENvcHlyaWdo dCAoQykgMjAyMyBBUk0gTHRkLgo+ID4gKyAqLwo+ID4gKyNpZm5kZWYgX19BU01fTVRFX1RBR19T VE9SQUdFX0gKPiA+ICsjZGVmaW5lIF9fQVNNX01URV9UQUdfU1RPUkFHRV9ICj4gPiArCj4gPiAr I2lmZGVmIENPTkZJR19BUk02NF9NVEVfVEFHX1NUT1JBR0UKPiA+ICt2b2lkIG10ZV90YWdfc3Rv cmFnZV9pbml0KHZvaWQpOwo+ID4gKyNlbHNlCj4gPiArc3RhdGljIGlubGluZSB2b2lkIG10ZV90 YWdfc3RvcmFnZV9pbml0KHZvaWQpCj4gPiArewo+ID4gK30KPiA+ICsjZW5kaWYgLyogQ09ORklH X0FSTTY0X01URV9UQUdfU1RPUkFHRSAqLwo+ID4gKyNlbmRpZiAvKiBfX0FTTV9NVEVfVEFHX1NU T1JBR0VfSCAgKi8KPiA+IGRpZmYgLS1naXQgYS9hcmNoL2FybTY0L2tlcm5lbC9NYWtlZmlsZSBi L2FyY2gvYXJtNjQva2VybmVsL01ha2VmaWxlCj4gPiBpbmRleCBkOTViM2Q2YjQ3MWEuLjVmMDMx YmY5ZjhmMSAxMDA2NDQKPiA+IC0tLSBhL2FyY2gvYXJtNjQva2VybmVsL01ha2VmaWxlCj4gPiAr KysgYi9hcmNoL2FybTY0L2tlcm5lbC9NYWtlZmlsZQo+ID4gQEAgLTcwLDYgKzcwLDcgQEAgb2Jq LSQoQ09ORklHX0NSQVNIX0NPUkUpICAgICAgICAgICAgICArPSBjcmFzaF9jb3JlLm8KPiA+ICBv YmotJChDT05GSUdfQVJNX1NERV9JTlRFUkZBQ0UpICAgICAgICAgICAgICAgICs9IHNkZWkubwo+ ID4gIG9iai0kKENPTkZJR19BUk02NF9QVFJfQVVUSCkgICAgICAgICAgICs9IHBvaW50ZXJfYXV0 aC5vCj4gPiAgb2JqLSQoQ09ORklHX0FSTTY0X01URSkgICAgICAgICAgICAgICAgICAgICAgICAr PSBtdGUubwo+ID4gK29iai0kKENPTkZJR19BUk02NF9NVEVfVEFHX1NUT1JBR0UpICAgICs9IG10 ZV90YWdfc3RvcmFnZS5vCj4gPiAgb2JqLXkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgKz0gdmRzby13cmFwLm8KPiA+ICBvYmotJChDT05GSUdfQ09NUEFUX1ZEU08pICAgICAgICAg ICAgICArPSB2ZHNvMzItd3JhcC5vCj4gPiAgb2JqLSQoQ09ORklHX1VOV0lORF9QQVRDSF9QQUNf SU5UT19TQ1MpICAgICAgICArPSBwYXRjaC1zY3Mubwo+ID4gZGlmZiAtLWdpdCBhL2FyY2gvYXJt NjQva2VybmVsL210ZV90YWdfc3RvcmFnZS5jIGIvYXJjaC9hcm02NC9rZXJuZWwvbXRlX3RhZ19z dG9yYWdlLmMKPiA+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gPiBpbmRleCAwMDAwMDAwMDAwMDAu LmZhNjI2N2VmODM5Mgo+ID4gLS0tIC9kZXYvbnVsbAo+ID4gKysrIGIvYXJjaC9hcm02NC9rZXJu ZWwvbXRlX3RhZ19zdG9yYWdlLmMKPiA+IEBAIC0wLDAgKzEsMjU2IEBACj4gPiArLy8gU1BEWC1M aWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAtb25seQo+ID4gKy8qCj4gPiArICogU3VwcG9ydCBm b3IgZHluYW1pYyB0YWcgc3RvcmFnZS4KPiA+ICsgKgo+ID4gKyAqIENvcHlyaWdodCAoQykgMjAy MyBBUk0gTHRkLgo+ID4gKyAqLwo+ID4gKwo+ID4gKyNpbmNsdWRlIDxsaW51eC9tZW1ibG9jay5o Pgo+ID4gKyNpbmNsdWRlIDxsaW51eC9tbS5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9vZl9kZXZp Y2UuaD4KPiAKPiBZb3UgcHJvYmFibHkgZG9uJ3QgbmVlZCB0aGlzIGhlYWRlci4gSWYgeW91IGRl cGVuZCBvbiB3aGF0IGl0Cj4gaW1wbGljaXRseSBpbmNsdWRlcywgdGhlbiB0aGF0IHdpbGwgbm93 IGJyZWFrIGluIGxpbnV4LW5leHQuCgpJJ2xsIGhhdmUgYSBsb29rIGlmIEkgY2FuIHJlbW92ZSBp dC4gTWlnaHQgYmUgYW4gYXJ0aWZhY3QgZnJvbSBhbiBlYXJsaWVyCnZlcnNpb24gb2YgdGhlIHBh dGNoZXMuCgo+IAo+ID4gKyNpbmNsdWRlIDxsaW51eC9vZl9mZHQuaD4KPiA+ICsjaW5jbHVkZSA8 bGludXgvcmFuZ2UuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvc3RyaW5nLmg+Cj4gPiArI2luY2x1 ZGUgPGxpbnV4L3hhcnJheS5oPgo+ID4gKwo+ID4gKyNpbmNsdWRlIDxhc20vbXRlX3RhZ19zdG9y YWdlLmg+Cj4gPiArCj4gPiArc3RydWN0IHRhZ19yZWdpb24gewo+ID4gKyAgICAgICBzdHJ1Y3Qg cmFuZ2UgbWVtX3JhbmdlOyAvKiBNZW1vcnkgYXNzb2NpYXRlZCB3aXRoIHRoZSB0YWcgc3RvcmFn ZSwgaW4gUEZOcy4gKi8KPiA+ICsgICAgICAgc3RydWN0IHJhbmdlIHRhZ19yYW5nZTsgLyogVGFn IHN0b3JhZ2UgbWVtb3J5LCBpbiBQRk5zLiAqLwo+ID4gKyAgICAgICB1MzIgYmxvY2tfc2l6ZTsg ICAgICAgICAvKiBUYWcgYmxvY2sgc2l6ZSwgaW4gcGFnZXMuICovCj4gPiArfTsKPiA+ICsKPiA+ ICsjZGVmaW5lIE1BWF9UQUdfUkVHSU9OUyAgICAgICAgMzIKPiA+ICsKPiA+ICtzdGF0aWMgc3Ry dWN0IHRhZ19yZWdpb24gdGFnX3JlZ2lvbnNbTUFYX1RBR19SRUdJT05TXTsKPiA+ICtzdGF0aWMg aW50IG51bV90YWdfcmVnaW9uczsKPiA+ICsKPiA+ICtzdGF0aWMgaW50IF9faW5pdCB0YWdfc3Rv cmFnZV9vZl9mbGF0X2dldF9yYW5nZSh1bnNpZ25lZCBsb25nIG5vZGUsIGNvbnN0IF9fYmUzMiAq cmVnLAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg aW50IHJlZ19sZW4sIHN0cnVjdCByYW5nZSAqcmFuZ2UpCj4gPiArewo+ID4gKyAgICAgICBpbnQg YWRkcl9jZWxscyA9IGR0X3Jvb3RfYWRkcl9jZWxsczsKPiA+ICsgICAgICAgaW50IHNpemVfY2Vs bHMgPSBkdF9yb290X3NpemVfY2VsbHM7Cj4gPiArICAgICAgIHU2NCBzaXplOwo+ID4gKwo+ID4g KyAgICAgICBpZiAocmVnX2xlbiAvIDQgPiBhZGRyX2NlbGxzICsgc2l6ZV9jZWxscykKPiA+ICsg ICAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPiA+ICsKPiA+ICsgICAgICAgcmFuZ2UtPnN0 YXJ0ID0gUEhZU19QRk4ob2ZfcmVhZF9udW1iZXIocmVnLCBhZGRyX2NlbGxzKSk7Cj4gPiArICAg ICAgIHNpemUgPSBQSFlTX1BGTihvZl9yZWFkX251bWJlcihyZWcgKyBhZGRyX2NlbGxzLCBzaXpl X2NlbGxzKSk7Cj4gPiArICAgICAgIGlmIChzaXplID09IDApIHsKPiA+ICsgICAgICAgICAgICAg ICBwcl9lcnIoIkludmFsaWQgbm9kZSIpOwo+ID4gKyAgICAgICAgICAgICAgIHJldHVybiAtRUlO VkFMOwo+ID4gKyAgICAgICB9Cj4gPiArICAgICAgIHJhbmdlLT5lbmQgPSByYW5nZS0+c3RhcnQg KyBzaXplIC0gMTsKPiAKPiBXZSBoYXZlIGEgZnVuY3Rpb24gdG8gcmVhZCAoYW5kIHRyYW5zbGF0 ZSB3aGljaCB5b3UgZm9yZ290KSBhZGRyZXNzZXMuCj4gQWRkIHdoYXQncyBtaXNzaW5nIHJhdGhl ciB0aGFuIG9wZW4gY29kZSB5b3VyIG93bi4KCkkgbXVzdCBoYXZlIG1pc3NlZCB0aGF0IHRoZXJl J3MgYWxyZWFkeSBhIGZ1bmN0aW9uIHRvIHJlYWQgYWRkcmVzc2VzLiBXb3VsZAp5b3UgbWluZCBw b2ludGluZyBtZSBpbiB0aGUgcmlnaHQgZGlyZWN0aW9uPwoKPiAKPiA+ICsKPiA+ICsgICAgICAg cmV0dXJuIDA7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgX19pbml0IHRhZ19zdG9yYWdl X29mX2ZsYXRfZ2V0X3RhZ19yYW5nZSh1bnNpZ25lZCBsb25nIG5vZGUsCj4gPiArICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IHJhbmdlICp0 YWdfcmFuZ2UpCj4gPiArewo+ID4gKyAgICAgICBjb25zdCBfX2JlMzIgKnJlZzsKPiA+ICsgICAg ICAgaW50IHJlZ19sZW47Cj4gPiArCj4gPiArICAgICAgIHJlZyA9IG9mX2dldF9mbGF0X2R0X3By b3Aobm9kZSwgInJlZyIsICZyZWdfbGVuKTsKPiA+ICsgICAgICAgaWYgKHJlZyA9PSBOVUxMKSB7 Cj4gPiArICAgICAgICAgICAgICAgcHJfZXJyKCJJbnZhbGlkIG1ldGFkYXRhIG5vZGUiKTsKPiA+ ICsgICAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPiA+ICsgICAgICAgfQo+ID4gKwo+ID4g KyAgICAgICByZXR1cm4gdGFnX3N0b3JhZ2Vfb2ZfZmxhdF9nZXRfcmFuZ2Uobm9kZSwgcmVnLCBy ZWdfbGVuLCB0YWdfcmFuZ2UpOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50IF9faW5pdCB0 YWdfc3RvcmFnZV9vZl9mbGF0X2dldF9tZW1vcnlfcmFuZ2UodW5zaWduZWQgbG9uZyBub2RlLCBz dHJ1Y3QgcmFuZ2UgKm1lbSkKPiA+ICt7Cj4gPiArICAgICAgIGNvbnN0IF9fYmUzMiAqcmVnOwo+ ID4gKyAgICAgICBpbnQgcmVnX2xlbjsKPiA+ICsKPiA+ICsgICAgICAgcmVnID0gb2ZfZ2V0X2Zs YXRfZHRfcHJvcChub2RlLCAibGludXgsdXNhYmxlLW1lbW9yeSIsICZyZWdfbGVuKTsKPiA+ICsg ICAgICAgaWYgKHJlZyA9PSBOVUxMKQo+ID4gKyAgICAgICAgICAgICAgIHJlZyA9IG9mX2dldF9m bGF0X2R0X3Byb3Aobm9kZSwgInJlZyIsICZyZWdfbGVuKTsKPiA+ICsKPiA+ICsgICAgICAgaWYg KHJlZyA9PSBOVUxMKSB7Cj4gPiArICAgICAgICAgICAgICAgcHJfZXJyKCJJbnZhbGlkIG1lbW9y eSBub2RlIik7Cj4gPiArICAgICAgICAgICAgICAgcmV0dXJuIC1FSU5WQUw7Cj4gPiArICAgICAg IH0KPiA+ICsKPiA+ICsgICAgICAgcmV0dXJuIHRhZ19zdG9yYWdlX29mX2ZsYXRfZ2V0X3Jhbmdl KG5vZGUsIHJlZywgcmVnX2xlbiwgbWVtKTsKPiA+ICt9Cj4gPiArCj4gPiArc3RydWN0IGZpbmRf bWVtb3J5X25vZGVfYXJnIHsKPiA+ICsgICAgICAgdW5zaWduZWQgbG9uZyBub2RlOwo+ID4gKyAg ICAgICB1MzIgcGhhbmRsZTsKPiA+ICt9Owo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgX19pbml0IGZk dF9maW5kX21lbW9yeV9ub2RlKHVuc2lnbmVkIGxvbmcgbm9kZSwgY29uc3QgY2hhciAqdW5hbWUs Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQgZGVwdGgsIHZv aWQgKmRhdGEpCj4gPiArewo+ID4gKyAgICAgICBjb25zdCBjaGFyICp0eXBlID0gb2ZfZ2V0X2Zs YXRfZHRfcHJvcChub2RlLCAiZGV2aWNlX3R5cGUiLCBOVUxMKTsKPiA+ICsgICAgICAgc3RydWN0 IGZpbmRfbWVtb3J5X25vZGVfYXJnICphcmcgPSBkYXRhOwo+ID4gKwo+ID4gKyAgICAgICBpZiAo ZGVwdGggIT0gMSB8fCAhdHlwZSB8fCBzdHJjbXAodHlwZSwgIm1lbW9yeSIpICE9IDApCj4gPiAr ICAgICAgICAgICAgICAgcmV0dXJuIDA7Cj4gPiArCj4gPiArICAgICAgIGlmIChvZl9nZXRfZmxh dF9kdF9waGFuZGxlKG5vZGUpID09IGFyZy0+cGhhbmRsZSkgewo+ID4gKyAgICAgICAgICAgICAg IGFyZy0+bm9kZSA9IG5vZGU7Cj4gPiArICAgICAgICAgICAgICAgcmV0dXJuIDE7Cj4gPiArICAg ICAgIH0KPiA+ICsKPiA+ICsgICAgICAgcmV0dXJuIDA7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRp YyBpbnQgX19pbml0IHRhZ19zdG9yYWdlX2dldF9tZW1vcnlfbm9kZSh1bnNpZ25lZCBsb25nIHRh Z19ub2RlLCB1bnNpZ25lZCBsb25nICptZW1fbm9kZSkKPiA+ICt7Cj4gPiArICAgICAgIHN0cnVj dCBmaW5kX21lbW9yeV9ub2RlX2FyZyBhcmcgPSB7IDAgfTsKPiA+ICsgICAgICAgY29uc3QgX19i ZTMyICptZW1vcnlfcHJvcDsKPiA+ICsgICAgICAgdTMyIG1lbV9waGFuZGxlOwo+ID4gKyAgICAg ICBpbnQgcmV0LCByZWdfbGVuOwo+ID4gKwo+ID4gKyAgICAgICBtZW1vcnlfcHJvcCA9IG9mX2dl dF9mbGF0X2R0X3Byb3AodGFnX25vZGUsICJtZW1vcnkiLCAmcmVnX2xlbik7Cj4gPiArICAgICAg IGlmICghbWVtb3J5X3Byb3ApIHsKPiA+ICsgICAgICAgICAgICAgICBwcl9lcnIoIk1pc3Npbmcg J21lbW9yeScgcHJvcGVydHkgaW4gdGhlIHRhZyBzdG9yYWdlIG5vZGUiKTsKPiA+ICsgICAgICAg ICAgICAgICByZXR1cm4gLUVJTlZBTDsKPiA+ICsgICAgICAgfQo+ID4gKwo+ID4gKyAgICAgICBt ZW1fcGhhbmRsZSA9IGJlMzJfdG9fY3B1cChtZW1vcnlfcHJvcCk7Cj4gPiArICAgICAgIGFyZy5w aGFuZGxlID0gbWVtX3BoYW5kbGU7Cj4gPiArCj4gPiArICAgICAgIHJldCA9IG9mX3NjYW5fZmxh dF9kdChmZHRfZmluZF9tZW1vcnlfbm9kZSwgJmFyZyk7Cj4gCj4gRG8gbm90IHVzZSBvZl9zY2Fu X2ZsYXRfZHQuIEl0IGlzIGEgcmVsaWMgcHJlZGF0aW5nIGxpYmZkdCB3aGljaCBjYW4KPiBnZXQg YSBub2RlIGJ5IHBoYW5kbGUgZGlyZWN0bHkuCgpJIHVzZWQgdGhhdCBiZWNhdXNlIHRoYXQncyB3 aGF0IGRyaXZlcnMvb2YvZmR0LmMgdXNlcy4gV2l0aCByZXNlcnZlZCBtZW1vcnkKSSBzaG91bGRu J3QgbmVlZCBpdCwgYmVjYXVzZSBzdHJ1Y3QgcmVzZXJ2ZWRfbWVtIGFscmVhZHkgaW5jbHVkZXMg YQpwaGFuZGxlLgoKPiAKPiA+ICsgICAgICAgaWYgKHJldCAhPSAxKSB7Cj4gPiArICAgICAgICAg ICAgICAgcHJfZXJyKCJBc3NvY2lhdGVkIG1lbW9yeSBub2RlIG5vdCBmb3VuZCIpOwo+ID4gKyAg ICAgICAgICAgICAgIHJldHVybiAtRUlOVkFMOwo+ID4gKyAgICAgICB9Cj4gPiArCj4gPiArICAg ICAgICptZW1fbm9kZSA9IGFyZy5ub2RlOwo+ID4gKwo+ID4gKyAgICAgICByZXR1cm4gMDsKPiA+ ICt9Cj4gPiArCj4gPiArc3RhdGljIGludCBfX2luaXQgdGFnX3N0b3JhZ2Vfb2ZfZmxhdF9yZWFk X3UzMih1bnNpZ25lZCBsb25nIG5vZGUsIGNvbnN0IGNoYXIgKnByb3BuYW1lLAo+ID4gKyAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1MzIgKnJldHZhbCkKPiAK PiBJZiB5b3UgYXJlIGdvaW5nIHRvIG1ha2UgYSBnZW5lcmljIGZ1bmN0aW9uLCBtYWtlIGl0IGZv ciBldmVyeW9uZS4KClN1cmUuIElmIEkgc3RpbGwgbmVlZCBpdCwgc2hvdWxkIEkgcHV0IHRoZSBm dW5jdGlvbiBpbgppbmNsdWRlL2xpbnV4L29mX2ZkdC5oPwoKPiAKPiA+ICt7Cj4gPiArICAgICAg IGNvbnN0IF9fYmUzMiAqcmVnOwo+ID4gKwo+ID4gKyAgICAgICByZWcgPSBvZl9nZXRfZmxhdF9k dF9wcm9wKG5vZGUsIHByb3BuYW1lLCBOVUxMKTsKPiA+ICsgICAgICAgaWYgKCFyZWcpCj4gPiAr ICAgICAgICAgICAgICAgcmV0dXJuIC1FSU5WQUw7Cj4gPiArCj4gPiArICAgICAgICpyZXR2YWwg PSBiZTMyX3RvX2NwdXAocmVnKTsKPiA+ICsgICAgICAgcmV0dXJuIDA7Cj4gPiArfQo+ID4gKwo+ ID4gK3N0YXRpYyB1MzIgX19pbml0IGdldF9ibG9ja19zaXplX3BhZ2VzKHUzMiBibG9ja19zaXpl X2J5dGVzKQo+ID4gK3sKPiA+ICsgICAgICAgdTMyIGEgPSBQQUdFX1NJWkU7Cj4gPiArICAgICAg IHUzMiBiID0gYmxvY2tfc2l6ZV9ieXRlczsKPiA+ICsgICAgICAgdTMyIHI7Cj4gPiArCj4gPiAr ICAgICAgIC8qIEZpbmQgZ3JlYXRlc3QgY29tbW9uIGRpdmlzb3IgdXNpbmcgdGhlIEV1Y2xpZGlh biBhbGdvcml0aG0uICovCj4gPiArICAgICAgIGRvIHsKPiA+ICsgICAgICAgICAgICAgICByID0g YSAlIGI7Cj4gPiArICAgICAgICAgICAgICAgYSA9IGI7Cj4gPiArICAgICAgICAgICAgICAgYiA9 IHI7Cj4gPiArICAgICAgIH0gd2hpbGUgKGIgIT0gMCk7Cj4gPiArCj4gPiArICAgICAgIHJldHVy biBQSFlTX1BGTihQQUdFX1NJWkUgKiBibG9ja19zaXplX2J5dGVzIC8gYSk7Cj4gPiArfQo+ID4g Kwo+ID4gK3N0YXRpYyBpbnQgX19pbml0IGZkdF9pbml0X3RhZ19zdG9yYWdlKHVuc2lnbmVkIGxv bmcgbm9kZSwgY29uc3QgY2hhciAqdW5hbWUsCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICBpbnQgZGVwdGgsIHZvaWQgKmRhdGEpCj4gPiArewo+ID4gKyAgICAgICBz dHJ1Y3QgdGFnX3JlZ2lvbiAqcmVnaW9uOwo+ID4gKyAgICAgICB1bnNpZ25lZCBsb25nIG1lbV9u b2RlOwo+ID4gKyAgICAgICBzdHJ1Y3QgcmFuZ2UgKm1lbV9yYW5nZTsKPiA+ICsgICAgICAgc3Ry dWN0IHJhbmdlICp0YWdfcmFuZ2U7Cj4gPiArICAgICAgIHUzMiBibG9ja19zaXplX2J5dGVzOwo+ ID4gKyAgICAgICB1MzIgbmlkID0gMDsKPiA+ICsgICAgICAgaW50IHJldDsKPiA+ICsKPiA+ICsg ICAgICAgaWYgKGRlcHRoICE9IDEgfHwgIXN0cnN0cih1bmFtZSwgInRhZy1zdG9yYWdlIikpCj4g PiArICAgICAgICAgICAgICAgcmV0dXJuIDA7Cj4gPiArCj4gPiArICAgICAgIGlmICghb2ZfZmxh dF9kdF9pc19jb21wYXRpYmxlKG5vZGUsICJhcm0sbXRlLXRhZy1zdG9yYWdlIikpCj4gPiArICAg ICAgICAgICAgICAgcmV0dXJuIDA7Cj4gPiArCj4gPiArICAgICAgIGlmIChudW1fdGFnX3JlZ2lv bnMgPT0gTUFYX1RBR19SRUdJT05TKSB7Cj4gPiArICAgICAgICAgICAgICAgcHJfZXJyKCJNYXhp bXVtIG51bWJlciBvZiB0YWcgc3RvcmFnZSByZWdpb25zIGV4Y2VlZGVkIik7Cj4gPiArICAgICAg ICAgICAgICAgcmV0dXJuIC1FSU5WQUw7Cj4gPiArICAgICAgIH0KPiA+ICsKPiA+ICsgICAgICAg cmVnaW9uID0gJnRhZ19yZWdpb25zW251bV90YWdfcmVnaW9uc107Cj4gPiArICAgICAgIG1lbV9y YW5nZSA9ICZyZWdpb24tPm1lbV9yYW5nZTsKPiA+ICsgICAgICAgdGFnX3JhbmdlID0gJnJlZ2lv bi0+dGFnX3JhbmdlOwo+ID4gKwo+ID4gKyAgICAgICByZXQgPSB0YWdfc3RvcmFnZV9vZl9mbGF0 X2dldF90YWdfcmFuZ2Uobm9kZSwgdGFnX3JhbmdlKTsKPiA+ICsgICAgICAgaWYgKHJldCkgewo+ ID4gKyAgICAgICAgICAgICAgIHByX2VycigiSW52YWxpZCB0YWcgc3RvcmFnZSBub2RlIik7Cj4g PiArICAgICAgICAgICAgICAgcmV0dXJuIHJldDsKPiA+ICsgICAgICAgfQo+ID4gKwo+ID4gKyAg ICAgICByZXQgPSB0YWdfc3RvcmFnZV9nZXRfbWVtb3J5X25vZGUobm9kZSwgJm1lbV9ub2RlKTsK PiA+ICsgICAgICAgaWYgKHJldCkKPiA+ICsgICAgICAgICAgICAgICByZXR1cm4gcmV0Owo+ID4g Kwo+ID4gKyAgICAgICByZXQgPSB0YWdfc3RvcmFnZV9vZl9mbGF0X2dldF9tZW1vcnlfcmFuZ2Uo bWVtX25vZGUsIG1lbV9yYW5nZSk7Cj4gPiArICAgICAgIGlmIChyZXQpIHsKPiA+ICsgICAgICAg ICAgICAgICBwcl9lcnIoIkludmFsaWQgYWRkcmVzcyBmb3IgYXNzb2NpYXRlZCBkYXRhIG1lbW9y eSBub2RlIik7Cj4gPiArICAgICAgICAgICAgICAgcmV0dXJuIHJldDsKPiA+ICsgICAgICAgfQo+ ID4gKwo+ID4gKyAgICAgICAvKiBUaGUgdGFnIHJlZ2lvbiBtdXN0IGV4YWN0bHkgbWF0Y2ggdGhl IGNvcnJlc3BvbmRpbmcgbWVtb3J5LiAqLwo+ID4gKyAgICAgICBpZiAocmFuZ2VfbGVuKHRhZ19y YW5nZSkgKiAzMiAhPSByYW5nZV9sZW4obWVtX3JhbmdlKSkgewo+ID4gKyAgICAgICAgICAgICAg IHByX2VycigiVGFnIHN0b3JhZ2UgcmVnaW9uIDB4JWxseC0weCVsbHggZG9lcyBub3QgY292ZXIg dGhlIG1lbW9yeSByZWdpb24gMHglbGx4LTB4JWxseCIsCj4gPiArICAgICAgICAgICAgICAgICAg ICAgIFBGTl9QSFlTKHRhZ19yYW5nZS0+c3RhcnQpLCBQRk5fUEhZUyh0YWdfcmFuZ2UtPmVuZCks Cj4gPiArICAgICAgICAgICAgICAgICAgICAgIFBGTl9QSFlTKG1lbV9yYW5nZS0+c3RhcnQpLCBQ Rk5fUEhZUyhtZW1fcmFuZ2UtPmVuZCkpOwo+ID4gKyAgICAgICAgICAgICAgIHJldHVybiAtRUlO VkFMOwo+ID4gKyAgICAgICB9Cj4gPiArCj4gPiArICAgICAgIHJldCA9IHRhZ19zdG9yYWdlX29m X2ZsYXRfcmVhZF91MzIobm9kZSwgImJsb2NrLXNpemUiLCAmYmxvY2tfc2l6ZV9ieXRlcyk7Cj4g PiArICAgICAgIGlmIChyZXQgfHwgYmxvY2tfc2l6ZV9ieXRlcyA9PSAwKSB7Cj4gPiArICAgICAg ICAgICAgICAgcHJfZXJyKCJJbnZhbGlkIG9yIG1pc3NpbmcgJ2Jsb2NrLXNpemUnIHByb3BlcnR5 Iik7Cj4gPiArICAgICAgICAgICAgICAgcmV0dXJuIC1FSU5WQUw7Cj4gPiArICAgICAgIH0KPiA+ ICsgICAgICAgcmVnaW9uLT5ibG9ja19zaXplID0gZ2V0X2Jsb2NrX3NpemVfcGFnZXMoYmxvY2tf c2l6ZV9ieXRlcyk7Cj4gPiArICAgICAgIGlmIChyYW5nZV9sZW4odGFnX3JhbmdlKSAlIHJlZ2lv bi0+YmxvY2tfc2l6ZSAhPSAwKSB7Cj4gPiArICAgICAgICAgICAgICAgcHJfZXJyKCJUYWcgc3Rv cmFnZSByZWdpb24gc2l6ZSAweCVsbHggaXMgbm90IGEgbXVsdGlwbGUgb2YgYmxvY2sgc2l6ZSAl dSIsCj4gPiArICAgICAgICAgICAgICAgICAgICAgIFBGTl9QSFlTKHJhbmdlX2xlbih0YWdfcmFu Z2UpKSwgcmVnaW9uLT5ibG9ja19zaXplKTsKPiA+ICsgICAgICAgICAgICAgICByZXR1cm4gLUVJ TlZBTDsKPiA+ICsgICAgICAgfQo+ID4gKwo+ID4gKyAgICAgICByZXQgPSB0YWdfc3RvcmFnZV9v Zl9mbGF0X3JlYWRfdTMyKG1lbV9ub2RlLCAibnVtYS1ub2RlLWlkIiwgJm5pZCk7Cj4gCj4gSSB3 YXMgZ29pbmcgdG8gc2F5IHdlIGFscmVhZHkgaGF2ZSBhIHdheSB0byBhc3NvY2lhdGUgbWVtb3J5 IG5vZGVzCj4gb3RoZXIgbm9kZXMgdXNpbmcgIm51bWEtbm9kZS1pZCIsIHNvIHRoZSAibWVtb3J5 IiBwaGFuZGxlIHByb3BlcnR5IGlzCj4gc29tZXdoYXQgcmVkdW5kYW50LiBNYXliZSB0aGUgdGFn IG5vZGUgc2hvdWxkIGhhdmUgYSBudW1hLW5vZGUtaWQuCj4gV2l0aCB0aGF0LCBpdCBsb29rcyBs aWtlIHlvdSBkb24ndCBldmVuIG5lZWQgdG8gYWNjZXNzIHRoZSAvbWVtb3J5Cj4gbm9kZS4gQXZv aWRpbmcgdGhhdCB3b3VsZCBiZSBnb29kIGZvciAyIHJlYXNvbnMuIEl0IGF2b2lkcyBwYXJzaW5n Cj4gbWVtb3J5IG5vZGVzIHR3aWNlIGFuZCBpdCdzIG5vdCB0aGUga2VybmVsJ3Mgam9iIHRvIHZh bGlkYXRlIHRoZSBEVC4KPiBSZWFsbHksIGlmIHlvdSB3YW50IG1lbW9yeSBpbmZvLCB5b3Ugc2hv dWxkIHVzZSBtZW1ibG9jayB0byBnZXQgaXQKPiBiZWNhdXNlIGFsbCB0aGUgc3BlY2lhbCBjYXNl cyBvZiBtZW1vcnkgbGF5b3V0IGFyZSBoYW5kbGVkLiBGb3IKPiBleGFtcGxlIHlvdSBjYW4gaGF2 ZSBtZW1vcnkgbm9kZXMgd2l0aCBtdWx0aXBsZSAncmVnJyBlbnRyaWVzIG9yCj4gbXVsdGlwbGUg bWVtb3J5IG5vZGVzIG9yIGJvdGgsIGFuZCB0aGVuIHNvbWUgb2YgdGhvc2UgY291bGQgYmUKPiBj b250aWd1b3VzLgoKSSBuZWVkIHRvIGhhdmUgYSBtZW1vcnkgbm9kZSBhc3NvY2lhdGVkIHdpdGgg dGhlIHRhZyBzdG9yYWdlIG5vZGUgYmVjYXVzZQp0aGVyZSBpcyBhIHN0YXRpYyByZWxhdGlvbnNo aXAgYmV0d2VlbiBhIHBhZ2UgZnJvbSAibm9ybWFsIiBtZW1vcnkgYW5kIGl0cwphc3NvY2lhdGVk IHRhZyBzdG9yYWdlLiBJZiB0aGUgY29kZSBkb2Vzbid0IGtub3cgdGhhdCB0aGUgbWVtb3J5IHJl Z2lvbgpBLi5CIGhhcyB0aGUgY29ycmVzcG9uZGluZyB0YWcgc3RvcmFnZSBpbiB0aGUgcmVnaW9u IFguLlksIHRoZW4gaXQgZG9lc24ndAprbm93IHdoaWNoIHRhZyBzdG9yYWdlIHRvIHJlc2VydmUg d2hlbiBhIHBhZ2UgaXMgYWxsb2NhdGVkIGFzIHRhZ2dlZC4KCkluIHRoZSBleGFtcGxlIGFib3Zl LCBhc3N1bWluZyB0aGF0IHBhZ2UgUCBpcyBhbGxvY2F0ZWQgYXMgdGFnZ2VkLCB0aGUKY29ycmVz cG9uZGluZyB0YWcgc3RvcmFnZSBwYWdlIHRoYXQgbmVlZHMgdG8gYmUgcmVzZXJ2ZWQgaXM6Cgp0 YWdfc3RvcmFnZV9wZm4gPSAocGFnZV90b19wZm4oUCkgLSBQSFlTX1BGTihBKSkgLyAzMiogKyBQ SFlTX1BGTihYKQoKbnVtYS1ub2RlLWlkIGlzIG5vdCBlbm91Z2ggZm9yIHRoaXMsIGJlY2F1c2Ug YXMgZmFyIEkga25vdyB5b3UgY2FuIGhhdmUKbXVsdGlwbGUgbWVtb3J5IHJlZ2lvbnMgd2l0aGlu ZyB0aGUgc2FtZSBudW1hIG5vZGUuCgoqMzIgdGFnZ2VkIHBhZ2VzIHVzZSBvbmUgdGFnIHN0b3Jh Z2UgcGFnZSB0byBzdG9yZSB0aGUgdGFncy4KClRoYW5rcywKQWxleAoKCl9fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGlu ZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMu aW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK