From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1032466AbeBOBgv (ORCPT ); Wed, 14 Feb 2018 20:36:51 -0500 Received: from mga11.intel.com ([192.55.52.93]:16655 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1032245AbeBOBgt (ORCPT ); Wed, 14 Feb 2018 20:36:49 -0500 X-Amp-Result: UNKNOWN X-Amp-Original-Verdict: FILE UNKNOWN X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.46,515,1511856000"; d="scan'208";a="17745827" Date: Wed, 14 Feb 2018 17:34:52 -0800 From: Dongwon Kim To: "linux-kernel@vger.kernel.org" Cc: "dri-devel@lists.freedesktop.org" , "xen-devel@lists.xenproject.org" , "Potrola, MateuszX" Subject: Re: [RFC PATCH 01/60] hyper_dmabuf: initial working version of hyper_dmabuf drv Message-ID: <20180215013452.GB8672@downor-Z87X-UD5H> References: <1513711816-2618-1-git-send-email-dongwon.kim@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <1513711816-2618-1-git-send-email-dongwon.kim@intel.com> User-Agent: Mutt/1.5.24 (2015-08-30) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Abandoning this series as a new version was submitted for the review "[RFC PATCH v2 0/9] hyper_dmabuf: Hyper_DMABUF driver" On Tue, Dec 19, 2017 at 11:29:17AM -0800, Kim, Dongwon wrote: > Upload of intial version of hyper_DMABUF driver enabling > DMA_BUF exchange between two different VMs in virtualized > platform based on hypervisor such as KVM or XEN. > > Hyper_DMABUF drv's primary role is to import a DMA_BUF > from originator then re-export it to another Linux VM > so that it can be mapped and accessed by it. > > The functionality of this driver highly depends on > Hypervisor's native page sharing mechanism and inter-VM > communication support. > > This driver has two layers, one is main hyper_DMABUF > framework for scatter-gather list management that handles > actual import and export of DMA_BUF. Lower layer is about > actual memory sharing and communication between two VMs, > which is hypervisor-specific interface. > > This driver is initially designed to enable DMA_BUF > sharing across VMs in Xen environment, so currently working > with Xen only. > > This also adds Kernel configuration for hyper_DMABUF drv > under Device Drivers->Xen driver support->hyper_dmabuf > options. > > To give some brief information about each source file, > > hyper_dmabuf/hyper_dmabuf_conf.h > : configuration info > > hyper_dmabuf/hyper_dmabuf_drv.c > : driver interface and initialization > > hyper_dmabuf/hyper_dmabuf_imp.c > : scatter-gather list generation and management. DMA_BUF > ops for DMA_BUF reconstructed from hyper_DMABUF > > hyper_dmabuf/hyper_dmabuf_ioctl.c > : IOCTLs calls for export/import and comm channel creation > unexport. > > hyper_dmabuf/hyper_dmabuf_list.c > : Database (linked-list) for exported and imported > hyper_DMABUF > > hyper_dmabuf/hyper_dmabuf_msg.c > : creation and management of messages between exporter and > importer > > hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c > : comm ch management and ISRs for incoming messages. > > hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c > : Database (linked-list) for keeping information about > existing comm channels among VMs > > Signed-off-by: Dongwon Kim > Signed-off-by: Mateusz Polrola > --- > drivers/xen/Kconfig | 2 + > drivers/xen/Makefile | 1 + > drivers/xen/hyper_dmabuf/Kconfig | 14 + > drivers/xen/hyper_dmabuf/Makefile | 34 + > drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h | 2 + > drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c | 54 ++ > drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h | 101 +++ > drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c | 852 +++++++++++++++++++++ > drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h | 31 + > drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c | 462 +++++++++++ > drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c | 119 +++ > drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h | 40 + > drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c | 212 +++++ > drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h | 45 ++ > drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h | 16 + > drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h | 70 ++ > .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c | 328 ++++++++ > .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h | 62 ++ > .../hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c | 106 +++ > .../hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h | 35 + > 20 files changed, 2586 insertions(+) > create mode 100644 drivers/xen/hyper_dmabuf/Kconfig > create mode 100644 drivers/xen/hyper_dmabuf/Makefile > create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h > create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c > create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h > create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c > create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h > create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c > create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c > create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h > create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c > create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h > create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h > create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h > create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c > create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h > create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c > create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h > > diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig > index d8dd546..b59b0e3 100644 > --- a/drivers/xen/Kconfig > +++ b/drivers/xen/Kconfig > @@ -321,4 +321,6 @@ config XEN_SYMS > config XEN_HAVE_VPMU > bool > > +source "drivers/xen/hyper_dmabuf/Kconfig" > + > endmenu > diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile > index 451e833..a6e253a 100644 > --- a/drivers/xen/Makefile > +++ b/drivers/xen/Makefile > @@ -4,6 +4,7 @@ obj-$(CONFIG_X86) += fallback.o > obj-y += grant-table.o features.o balloon.o manage.o preempt.o time.o > obj-y += events/ > obj-y += xenbus/ > +obj-y += hyper_dmabuf/ > > nostackp := $(call cc-option, -fno-stack-protector) > CFLAGS_features.o := $(nostackp) > diff --git a/drivers/xen/hyper_dmabuf/Kconfig b/drivers/xen/hyper_dmabuf/Kconfig > new file mode 100644 > index 0000000..75e1f96 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/Kconfig > @@ -0,0 +1,14 @@ > +menu "hyper_dmabuf options" > + > +config HYPER_DMABUF > + tristate "Enables hyper dmabuf driver" > + default y > + > +config HYPER_DMABUF_XEN > + bool "Configure hyper_dmabuf for XEN hypervisor" > + default y > + depends on HYPER_DMABUF > + help > + Configuring hyper_dmabuf driver for XEN hypervisor > + > +endmenu > diff --git a/drivers/xen/hyper_dmabuf/Makefile b/drivers/xen/hyper_dmabuf/Makefile > new file mode 100644 > index 0000000..0be7445 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/Makefile > @@ -0,0 +1,34 @@ > +TARGET_MODULE:=hyper_dmabuf > + > +# If we running by kernel building system > +ifneq ($(KERNELRELEASE),) > + $(TARGET_MODULE)-objs := hyper_dmabuf_drv.o \ > + hyper_dmabuf_ioctl.o \ > + hyper_dmabuf_list.o \ > + hyper_dmabuf_imp.o \ > + hyper_dmabuf_msg.o \ > + xen/hyper_dmabuf_xen_comm.o \ > + xen/hyper_dmabuf_xen_comm_list.o > + > +obj-$(CONFIG_HYPER_DMABUF) := $(TARGET_MODULE).o > + > +# If we are running without kernel build system > +else > +BUILDSYSTEM_DIR?=../../../ > +PWD:=$(shell pwd) > + > +all : > +# run kernel build system to make module > +$(MAKE) -C $(BUILDSYSTEM_DIR) M=$(PWD) modules > + > +clean: > +# run kernel build system to cleanup in current directory > +$(MAKE) -C $(BUILDSYSTEM_DIR) M=$(PWD) clean > + > +load: > + insmod ./$(TARGET_MODULE).ko > + > +unload: > + rmmod ./$(TARGET_MODULE).ko > + > +endif > diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h > new file mode 100644 > index 0000000..3d9b2d6 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h > @@ -0,0 +1,2 @@ > +#define CURRENT_TARGET XEN > +#define INTER_DOMAIN_DMABUF_SYNCHRONIZATION > diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c > new file mode 100644 > index 0000000..0698327 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c > @@ -0,0 +1,54 @@ > +#include /* module_init, module_exit */ > +#include /* version info, MODULE_LICENSE, MODULE_AUTHOR, printk() */ > +#include "hyper_dmabuf_conf.h" > +#include "hyper_dmabuf_list.h" > +#include "xen/hyper_dmabuf_xen_comm_list.h" > + > +MODULE_LICENSE("Dual BSD/GPL"); > +MODULE_AUTHOR("IOTG-PED, INTEL"); > + > +int register_device(void); > +int unregister_device(void); > + > +/*===============================================================================================*/ > +static int hyper_dmabuf_drv_init(void) > +{ > + int ret = 0; > + > + printk( KERN_NOTICE "hyper_dmabuf_starting: Initialization started" ); > + > + ret = register_device(); > + if (ret < 0) { > + return -EINVAL; > + } > + > + printk( KERN_NOTICE "initializing database for imported/exported dmabufs\n"); > + > + ret = hyper_dmabuf_table_init(); > + if (ret < 0) { > + return -EINVAL; > + } > + > + ret = hyper_dmabuf_ring_table_init(); > + if (ret < 0) { > + return -EINVAL; > + } > + > + /* interrupt for comm should be registered here: */ > + return ret; > +} > + > +/*-----------------------------------------------------------------------------------------------*/ > +static void hyper_dmabuf_drv_exit(void) > +{ > + /* hash tables for export/import entries and ring_infos */ > + hyper_dmabuf_table_destroy(); > + hyper_dmabuf_ring_table_init(); > + > + printk( KERN_NOTICE "dma_buf-src_sink model: Exiting" ); > + unregister_device(); > +} > +/*===============================================================================================*/ > + > +module_init(hyper_dmabuf_drv_init); > +module_exit(hyper_dmabuf_drv_exit); > diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h > new file mode 100644 > index 0000000..2dad9a6 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h > @@ -0,0 +1,101 @@ > +#ifndef __LINUX_PUBLIC_HYPER_DMABUF_DRV_H__ > +#define __LINUX_PUBLIC_HYPER_DMABUF_DRV_H__ > + > +typedef int (*hyper_dmabuf_ioctl_t)(void *data); > + > +struct hyper_dmabuf_ioctl_desc { > + unsigned int cmd; > + int flags; > + hyper_dmabuf_ioctl_t func; > + const char *name; > +}; > + > +#define HYPER_DMABUF_IOCTL_DEF(ioctl, _func, _flags) \ > + [_IOC_NR(ioctl)] = { \ > + .cmd = ioctl, \ > + .func = _func, \ > + .flags = _flags, \ > + .name = #ioctl \ > + } > + > +#define IOCTL_HYPER_DMABUF_EXPORTER_RING_SETUP \ > +_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_hyper_dmabuf_exporter_ring_setup)) > +struct ioctl_hyper_dmabuf_exporter_ring_setup { > + /* IN parameters */ > + /* Remote domain id */ > + uint32_t remote_domain; > + grant_ref_t ring_refid; /* assigned by driver, copied to userspace after initialization */ > + uint32_t port; /* assigned by driver, copied to userspace after initialization */ > +}; > + > +#define IOCTL_HYPER_DMABUF_IMPORTER_RING_SETUP \ > +_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_hyper_dmabuf_importer_ring_setup)) > +struct ioctl_hyper_dmabuf_importer_ring_setup { > + /* IN parameters */ > + /* Source domain id */ > + uint32_t source_domain; > + /* Ring shared page refid */ > + grant_ref_t ring_refid; > + /* Port number */ > + uint32_t port; > +}; > + > +#define IOCTL_HYPER_DMABUF_EXPORT_REMOTE \ > +_IOC(_IOC_NONE, 'G', 2, sizeof(struct ioctl_hyper_dmabuf_export_remote)) > +struct ioctl_hyper_dmabuf_export_remote { > + /* IN parameters */ > + /* DMA buf fd to be exported */ > + uint32_t dmabuf_fd; > + /* Domain id to which buffer should be exported */ > + uint32_t remote_domain; > + /* exported dma buf id */ > + uint32_t hyper_dmabuf_id; > + uint32_t private[4]; > +}; > + > +#define IOCTL_HYPER_DMABUF_EXPORT_FD \ > +_IOC(_IOC_NONE, 'G', 3, sizeof(struct ioctl_hyper_dmabuf_export_fd)) > +struct ioctl_hyper_dmabuf_export_fd { > + /* IN parameters */ > + /* hyper dmabuf id to be imported */ > + uint32_t hyper_dmabuf_id; > + /* flags */ > + uint32_t flags; > + /* OUT parameters */ > + /* exported dma buf fd */ > + uint32_t fd; > +}; > + > +#define IOCTL_HYPER_DMABUF_DESTROY \ > +_IOC(_IOC_NONE, 'G', 4, sizeof(struct ioctl_hyper_dmabuf_destroy)) > +struct ioctl_hyper_dmabuf_destroy { > + /* IN parameters */ > + /* hyper dmabuf id to be destroyed */ > + uint32_t hyper_dmabuf_id; > + /* OUT parameters */ > + /* Status of request */ > + uint32_t status; > +}; > + > +#define IOCTL_HYPER_DMABUF_QUERY \ > +_IOC(_IOC_NONE, 'G', 5, sizeof(struct ioctl_hyper_dmabuf_query)) > +struct ioctl_hyper_dmabuf_query { > + /* in parameters */ > + /* hyper dmabuf id to be queried */ > + uint32_t hyper_dmabuf_id; > + /* item to be queried */ > + uint32_t item; > + /* OUT parameters */ > + /* Value of queried item */ > + uint32_t info; > +}; > + > +#define IOCTL_HYPER_DMABUF_REMOTE_EXPORTER_RING_SETUP \ > +_IOC(_IOC_NONE, 'G', 6, sizeof(struct ioctl_hyper_dmabuf_remote_exporter_ring_setup)) > +struct ioctl_hyper_dmabuf_remote_exporter_ring_setup { > + /* in parameters */ > + uint32_t rdomain; /* id of remote domain where exporter's ring need to be setup */ > + uint32_t info; > +}; > + > +#endif //__LINUX_PUBLIC_HYPER_DMABUF_DRV_H__ > diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c > new file mode 100644 > index 0000000..faa5c1b > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c > @@ -0,0 +1,852 @@ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "hyper_dmabuf_struct.h" > +#include "hyper_dmabuf_imp.h" > +#include "xen/hyper_dmabuf_xen_comm.h" > +#include "hyper_dmabuf_msg.h" > + > +#define REFS_PER_PAGE (PAGE_SIZE/sizeof(grant_ref_t)) > + > +/* return total number of pages referecned by a sgt > + * for pre-calculation of # of pages behind a given sgt > + */ > +static int hyper_dmabuf_get_num_pgs(struct sg_table *sgt) > +{ > + struct scatterlist *sgl; > + int length, i; > + /* at least one page */ > + int num_pages = 1; > + > + sgl = sgt->sgl; > + > + length = sgl->length - PAGE_SIZE + sgl->offset; > + num_pages += ((length + PAGE_SIZE - 1)/PAGE_SIZE); /* round-up */ > + > + for (i = 1; i < sgt->nents; i++) { > + sgl = sg_next(sgl); > + num_pages += ((sgl->length + PAGE_SIZE - 1) / PAGE_SIZE); /* round-up */ > + } > + > + return num_pages; > +} > + > +/* extract pages directly from struct sg_table */ > +struct hyper_dmabuf_pages_info *hyper_dmabuf_ext_pgs(struct sg_table *sgt) > +{ > + struct hyper_dmabuf_pages_info *pinfo; > + int i, j; > + int length; > + struct scatterlist *sgl; > + > + pinfo = kmalloc(sizeof(*pinfo), GFP_KERNEL); > + if (pinfo == NULL) > + return NULL; > + > + pinfo->pages = kmalloc(sizeof(struct page *)*hyper_dmabuf_get_num_pgs(sgt), GFP_KERNEL); > + if (pinfo->pages == NULL) > + return NULL; > + > + sgl = sgt->sgl; > + > + pinfo->nents = 1; > + pinfo->frst_ofst = sgl->offset; > + pinfo->pages[0] = sg_page(sgl); > + length = sgl->length - PAGE_SIZE + sgl->offset; > + i=1; > + > + while (length > 0) { > + pinfo->pages[i] = nth_page(sg_page(sgl), i); > + length -= PAGE_SIZE; > + pinfo->nents++; > + i++; > + } > + > + for (j = 1; j < sgt->nents; j++) { > + sgl = sg_next(sgl); > + pinfo->pages[i++] = sg_page(sgl); > + length = sgl->length - PAGE_SIZE; > + pinfo->nents++; > + > + while (length > 0) { > + pinfo->pages[i] = nth_page(sg_page(sgl), i); > + length -= PAGE_SIZE; > + pinfo->nents++; > + i++; > + } > + } > + > + /* > + * lenght at that point will be 0 or negative, > + * so to calculate last page size just add it to PAGE_SIZE > + */ > + pinfo->last_len = PAGE_SIZE + length; > + > + return pinfo; > +} > + > +/* create sg_table with given pages and other parameters */ > +struct sg_table* hyper_dmabuf_create_sgt(struct page **pages, > + int frst_ofst, int last_len, int nents) > +{ > + struct sg_table *sgt; > + struct scatterlist *sgl; > + int i, ret; > + > + sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL); > + if (sgt == NULL) { > + return NULL; > + } > + > + ret = sg_alloc_table(sgt, nents, GFP_KERNEL); > + if (ret) { > + kfree(sgt); > + return NULL; > + } > + > + sgl = sgt->sgl; > + > + sg_set_page(sgl, pages[0], PAGE_SIZE-frst_ofst, frst_ofst); > + > + for (i=1; i + sgl = sg_next(sgl); > + sg_set_page(sgl, pages[i], PAGE_SIZE, 0); > + } > + > + if (i > 1) /* more than one page */ { > + sgl = sg_next(sgl); > + sg_set_page(sgl, pages[i], last_len, 0); > + } > + > + return sgt; > +} > + > +/* > + * Creates 2 level page directory structure for referencing shared pages. > + * Top level page is a single page that contains up to 1024 refids that > + * point to 2nd level pages. > + * Each 2nd level page contains up to 1024 refids that point to shared > + * data pages. > + * There will always be one top level page and number of 2nd level pages > + * depends on number of shared data pages. > + * > + * Top level page 2nd level pages Data pages > + * +-------------------------+ ┌>+--------------------+ ┌--->+------------+ > + * |2nd level page 0 refid |---┘ |Data page 0 refid |-┘ |Data page 0 | > + * |2nd level page 1 refid |---┐ |Data page 1 refid |-┐ +------------+ > + * | ... | | | .... | | > + * |2nd level page 1023 refid|-┐ | |Data page 1023 refid| └--->+------------+ > + * +-------------------------+ | | +--------------------+ |Data page 1 | > + * | | +------------+ > + * | └>+--------------------+ > + * | |Data page 1024 refid| > + * | |Data page 1025 refid| > + * | | ... | > + * | |Data page 2047 refid| > + * | +--------------------+ > + * | > + * | ..... > + * └-->+-----------------------+ > + * |Data page 1047552 refid| > + * |Data page 1047553 refid| > + * | ... | > + * |Data page 1048575 refid|-->+------------------+ > + * +-----------------------+ |Data page 1048575 | > + * +------------------+ > + * > + * Using such 2 level structure it is possible to reference up to 4GB of > + * shared data using single refid pointing to top level page. > + * > + * Returns refid of top level page. > + */ > +grant_ref_t hyper_dmabuf_create_addressing_tables(grant_ref_t *data_refs, int nents, int rdomain, > + struct hyper_dmabuf_shared_pages_info *shared_pages_info) > +{ > + /* > + * Calculate number of pages needed for 2nd level addresing: > + */ > + int n_2nd_level_pages = (nents/REFS_PER_PAGE + ((nents % REFS_PER_PAGE) ? 1: 0));/* rounding */ > + int i; > + unsigned long gref_page_start; > + grant_ref_t *tmp_page; > + grant_ref_t top_level_ref; > + grant_ref_t * addr_refs; > + addr_refs = kcalloc(sizeof(grant_ref_t), n_2nd_level_pages, GFP_KERNEL); > + > + gref_page_start = __get_free_pages(GFP_KERNEL, n_2nd_level_pages); > + tmp_page = (grant_ref_t *)gref_page_start; > + > + /* Store 2nd level pages to be freed later */ > + shared_pages_info->addr_pages = tmp_page; > + > + /*TODO: make sure that allocated memory is filled with 0*/ > + > + /* Share 2nd level addressing pages in readonly mode*/ > + for (i=0; i< n_2nd_level_pages; i++) { > + addr_refs[i] = gnttab_grant_foreign_access(rdomain, virt_to_mfn((unsigned long)tmp_page+i*PAGE_SIZE ), 1); > + } > + > + /* > + * fill second level pages with data refs > + */ > + for (i = 0; i < nents; i++) { > + tmp_page[i] = data_refs[i]; > + } > + > + > + /* allocate top level page */ > + gref_page_start = __get_free_pages(GFP_KERNEL, 1); > + tmp_page = (grant_ref_t *)gref_page_start; > + > + /* Store top level page to be freed later */ > + shared_pages_info->top_level_page = tmp_page; > + > + /* > + * fill top level page with reference numbers of second level pages refs. > + */ > + for (i=0; i< n_2nd_level_pages; i++) { > + tmp_page[i] = addr_refs[i]; > + } > + > + /* Share top level addressing page in readonly mode*/ > + top_level_ref = gnttab_grant_foreign_access(rdomain, virt_to_mfn((unsigned long)tmp_page), 1); > + > + kfree(addr_refs); > + > + return top_level_ref; > +} > + > +/* > + * Maps provided top level ref id and then return array of pages containing data refs. > + */ > +struct page** hyper_dmabuf_get_data_refs(grant_ref_t top_level_ref, int domid, int nents, > + struct hyper_dmabuf_shared_pages_info *shared_pages_info) > +{ > + struct page *top_level_page; > + struct page **level2_pages; > + > + grant_ref_t *top_level_refs; > + > + struct gnttab_map_grant_ref top_level_map_ops; > + struct gnttab_unmap_grant_ref top_level_unmap_ops; > + > + struct gnttab_map_grant_ref *map_ops; > + struct gnttab_unmap_grant_ref *unmap_ops; > + > + unsigned long addr; > + int n_level2_refs = 0; > + int i; > + > + n_level2_refs = (nents / REFS_PER_PAGE) + ((nents % REFS_PER_PAGE) ? 1 : 0); > + > + level2_pages = kcalloc(sizeof(struct page*), n_level2_refs, GFP_KERNEL); > + > + map_ops = kcalloc(sizeof(map_ops[0]), REFS_PER_PAGE, GFP_KERNEL); > + unmap_ops = kcalloc(sizeof(unmap_ops[0]), REFS_PER_PAGE, GFP_KERNEL); > + > + /* Map top level addressing page */ > + if (gnttab_alloc_pages(1, &top_level_page)) { > + printk("Cannot allocate pages\n"); > + return NULL; > + } > + > + addr = (unsigned long)pfn_to_kaddr(page_to_pfn(top_level_page)); > + gnttab_set_map_op(&top_level_map_ops, addr, GNTMAP_host_map | GNTMAP_readonly, top_level_ref, domid); > + gnttab_set_unmap_op(&top_level_unmap_ops, addr, GNTMAP_host_map | GNTMAP_readonly, -1); > + > + if (gnttab_map_refs(&top_level_map_ops, NULL, &top_level_page, 1)) { > + printk("\nxen: dom0: HYPERVISOR map grant ref failed"); > + return NULL; > + } > + > + if (top_level_map_ops.status) { > + printk("\nxen: dom0: HYPERVISOR map grant ref failed status = %d", > + top_level_map_ops.status); > + return NULL; > + } else { > + top_level_unmap_ops.handle = top_level_map_ops.handle; > + } > + > + /* Parse contents of top level addressing page to find how many second level pages is there*/ > + top_level_refs = pfn_to_kaddr(page_to_pfn(top_level_page)); > + > + /* Map all second level pages */ > + if (gnttab_alloc_pages(n_level2_refs, level2_pages)) { > + printk("Cannot allocate pages\n"); > + return NULL; > + } > + > + for (i = 0; i < n_level2_refs; i++) { > + addr = (unsigned long)pfn_to_kaddr(page_to_pfn(level2_pages[i])); > + gnttab_set_map_op(&map_ops[i], addr, GNTMAP_host_map | GNTMAP_readonly, top_level_refs[i], domid); > + gnttab_set_unmap_op(&unmap_ops[i], addr, GNTMAP_host_map | GNTMAP_readonly, -1); > + } > + > + if (gnttab_map_refs(map_ops, NULL, level2_pages, n_level2_refs)) { > + printk("\nxen: dom0: HYPERVISOR map grant ref failed"); > + return NULL; > + } > + > + /* Checks if pages were mapped correctly and at the same time is calculating total number of data refids*/ > + for (i = 0; i < n_level2_refs; i++) { > + if (map_ops[i].status) { > + printk("\nxen: dom0: HYPERVISOR map grant ref failed status = %d", > + map_ops[i].status); > + return NULL; > + } else { > + unmap_ops[i].handle = map_ops[i].handle; > + } > + } > + > + /* Unmap top level page, as it won't be needed any longer */ > + if (gnttab_unmap_refs(&top_level_unmap_ops, NULL, &top_level_page, 1)) { > + printk("\xen: cannot unmap top level page\n"); > + return NULL; > + } > + > + gnttab_free_pages(1, &top_level_page); > + kfree(map_ops); > + shared_pages_info->unmap_ops = unmap_ops; > + > + return level2_pages; > +} > + > + > +/* This collects all reference numbers for 2nd level shared pages and create a table > + * with those in 1st level shared pages then return reference numbers for this top level > + * table. */ > +grant_ref_t hyper_dmabuf_create_gref_table(struct page **pages, int rdomain, int nents, > + struct hyper_dmabuf_shared_pages_info *shared_pages_info) > +{ > + int i = 0; > + grant_ref_t *data_refs; > + grant_ref_t top_level_ref; > + > + /* allocate temp array for refs of shared data pages */ > + data_refs = kcalloc(nents, sizeof(grant_ref_t), GFP_KERNEL); > + > + /* share data pages in rw mode*/ > + for (i=0; i + data_refs[i] = gnttab_grant_foreign_access(rdomain, pfn_to_mfn(page_to_pfn(pages[i])), 0); > + } > + > + /* create additional shared pages with 2 level addressing of data pages */ > + top_level_ref = hyper_dmabuf_create_addressing_tables(data_refs, nents, rdomain, > + shared_pages_info); > + > + /* Store exported pages refid to be unshared later */ > + shared_pages_info->data_refs = data_refs; > + shared_pages_info->top_level_ref = top_level_ref; > + > + return top_level_ref; > +} > + > +int hyper_dmabuf_cleanup_gref_table(struct hyper_dmabuf_sgt_info *sgt_info) { > + uint32_t i = 0; > + struct hyper_dmabuf_shared_pages_info *shared_pages_info = &sgt_info->shared_pages_info; > + > + grant_ref_t *ref = shared_pages_info->top_level_page; > + int n_2nd_level_pages = (sgt_info->sgt->nents/REFS_PER_PAGE + ((sgt_info->sgt->nents % REFS_PER_PAGE) ? 1: 0));/* rounding */ > + > + > + if (shared_pages_info->data_refs == NULL || > + shared_pages_info->addr_pages == NULL || > + shared_pages_info->top_level_page == NULL || > + shared_pages_info->top_level_ref == -1) { > + printk("gref table for hyper_dmabuf already cleaned up\n"); > + return 0; > + } > + > + /* End foreign access for 2nd level addressing pages */ > + while(ref[i] != 0 && i < n_2nd_level_pages) { > + if (gnttab_query_foreign_access(ref[i])) { > + printk("refid not shared !!\n"); > + } > + if (!gnttab_end_foreign_access_ref(ref[i], 1)) { > + printk("refid still in use!!!\n"); > + } > + i++; > + } > + free_pages((unsigned long)shared_pages_info->addr_pages, i); > + > + /* End foreign access for top level addressing page */ > + if (gnttab_query_foreign_access(shared_pages_info->top_level_ref)) { > + printk("refid not shared !!\n"); > + } > + if (!gnttab_end_foreign_access_ref(shared_pages_info->top_level_ref, 1)) { > + printk("refid still in use!!!\n"); > + } > + gnttab_end_foreign_access_ref(shared_pages_info->top_level_ref, 1); > + free_pages((unsigned long)shared_pages_info->top_level_page, 1); > + > + /* End foreign access for data pages, but do not free them */ > + for (i = 0; i < sgt_info->sgt->nents; i++) { > + if (gnttab_query_foreign_access(shared_pages_info->data_refs[i])) { > + printk("refid not shared !!\n"); > + } > + gnttab_end_foreign_access_ref(shared_pages_info->data_refs[i], 0); > + } > + > + kfree(shared_pages_info->data_refs); > + > + shared_pages_info->data_refs = NULL; > + shared_pages_info->addr_pages = NULL; > + shared_pages_info->top_level_page = NULL; > + shared_pages_info->top_level_ref = -1; > + > + return 0; > +} > + > +int hyper_dmabuf_cleanup_imported_pages(struct hyper_dmabuf_imported_sgt_info *sgt_info) { > + struct hyper_dmabuf_shared_pages_info *shared_pages_info = &sgt_info->shared_pages_info; > + > + if(shared_pages_info->unmap_ops == NULL || shared_pages_info->data_pages == NULL) { > + printk("Imported pages already cleaned up or buffer was not imported yet\n"); > + return 0; > + } > + > + if (gnttab_unmap_refs(shared_pages_info->unmap_ops, NULL, shared_pages_info->data_pages, sgt_info->nents) ) { > + printk("Cannot unmap data pages\n"); > + return -EINVAL; > + } > + > + gnttab_free_pages(sgt_info->nents, shared_pages_info->data_pages); > + kfree(shared_pages_info->data_pages); > + kfree(shared_pages_info->unmap_ops); > + shared_pages_info->unmap_ops = NULL; > + shared_pages_info->data_pages = NULL; > + > + return 0; > +} > + > +/* map and construct sg_lists from reference numbers */ > +struct sg_table* hyper_dmabuf_map_pages(grant_ref_t top_level_gref, int frst_ofst, int last_len, int nents, int sdomain, > + struct hyper_dmabuf_shared_pages_info *shared_pages_info) > +{ > + struct sg_table *st; > + struct page **pages; > + struct gnttab_map_grant_ref *ops; > + struct gnttab_unmap_grant_ref *unmap_ops; > + unsigned long addr; > + grant_ref_t *refs; > + int i; > + int n_level2_refs = (nents / REFS_PER_PAGE) + ((nents % REFS_PER_PAGE) ? 1 : 0); > + > + /* Get data refids */ > + struct page** refid_pages = hyper_dmabuf_get_data_refs(top_level_gref, sdomain, nents, > + shared_pages_info); > + > + pages = kcalloc(sizeof(struct page*), nents, GFP_KERNEL); > + if (pages == NULL) { > + return NULL; > + } > + > + /* allocate new pages that are mapped to shared pages via grant-table */ > + if (gnttab_alloc_pages(nents, pages)) { > + printk("Cannot allocate pages\n"); > + return NULL; > + } > + > + ops = (struct gnttab_map_grant_ref *)kcalloc(nents, sizeof(struct gnttab_map_grant_ref), GFP_KERNEL); > + unmap_ops = (struct gnttab_unmap_grant_ref *)kcalloc(nents, sizeof(struct gnttab_unmap_grant_ref), GFP_KERNEL); > + > + for (i=0; i + addr = (unsigned long)pfn_to_kaddr(page_to_pfn(pages[i])); > + refs = pfn_to_kaddr(page_to_pfn(refid_pages[i / REFS_PER_PAGE])); > + gnttab_set_map_op(&ops[i], addr, GNTMAP_host_map | GNTMAP_readonly, refs[i % REFS_PER_PAGE], sdomain); > + gnttab_set_unmap_op(&unmap_ops[i], addr, GNTMAP_host_map | GNTMAP_readonly, -1); > + } > + > + if (gnttab_map_refs(ops, NULL, pages, nents)) { > + printk("\nxen: dom0: HYPERVISOR map grant ref failed\n"); > + return NULL; > + } > + > + for (i=0; i + if (ops[i].status) { > + printk("\nxen: dom0: HYPERVISOR map grant ref failed status = %d\n", > + ops[0].status); > + return NULL; > + } else { > + unmap_ops[i].handle = ops[i].handle; > + } > + } > + > + st = hyper_dmabuf_create_sgt(pages, frst_ofst, last_len, nents); > + > + if (gnttab_unmap_refs(shared_pages_info->unmap_ops, NULL, refid_pages, n_level2_refs) ) { > + printk("Cannot unmap 2nd level refs\n"); > + return NULL; > + } > + > + gnttab_free_pages(n_level2_refs, refid_pages); > + kfree(refid_pages); > + > + kfree(shared_pages_info->unmap_ops); > + shared_pages_info->unmap_ops = unmap_ops; > + shared_pages_info->data_pages = pages; > + kfree(ops); > + > + return st; > +} > + > +inline int hyper_dmabuf_sync_request_and_wait(int id, int ops) > +{ > + struct hyper_dmabuf_ring_rq *req; > + int operands[2]; > + int ret; > + > + operands[0] = id; > + operands[1] = ops; > + > + req = kcalloc(1, sizeof(*req), GFP_KERNEL); > + > + hyper_dmabuf_create_request(req, HYPER_DMABUF_OPS_TO_SOURCE, &operands[0]); > + > + /* send request */ > + ret = hyper_dmabuf_send_request(id, req); > + > + /* TODO: wait until it gets response.. or can we just move on? */ > + > + kfree(req); > + > + return ret; > +} > + > +static int hyper_dmabuf_ops_attach(struct dma_buf* dmabuf, struct device* dev, > + struct dma_buf_attachment *attach) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!attach->dmabuf->priv) > + return -EINVAL; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)attach->dmabuf->priv; > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_ATTACH); > + > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > + > + return ret; > +} > + > +static void hyper_dmabuf_ops_detach(struct dma_buf* dmabuf, struct dma_buf_attachment *attach) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!attach->dmabuf->priv) > + return; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)attach->dmabuf->priv; > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_DETACH); > + > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > +} > + > +static struct sg_table* hyper_dmabuf_ops_map(struct dma_buf_attachment *attachment, > + enum dma_data_direction dir) > +{ > + struct sg_table *st; > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + struct hyper_dmabuf_pages_info *page_info; > + int ret; > + > + if (!attachment->dmabuf->priv) > + return NULL; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)attachment->dmabuf->priv; > + > + /* extract pages from sgt */ > + page_info = hyper_dmabuf_ext_pgs(sgt_info->sgt); > + > + /* create a new sg_table with extracted pages */ > + st = hyper_dmabuf_create_sgt(page_info->pages, page_info->frst_ofst, > + page_info->last_len, page_info->nents); > + if (st == NULL) > + goto err_free_sg; > + > + if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) { > + goto err_free_sg; > + } > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_MAP); > + > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > + > + return st; > + > +err_free_sg: > + sg_free_table(st); > + kfree(st); > + return NULL; > +} > + > +static void hyper_dmabuf_ops_unmap(struct dma_buf_attachment *attachment, > + struct sg_table *sg, > + enum dma_data_direction dir) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!attachment->dmabuf->priv) > + return; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)attachment->dmabuf->priv; > + > + dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir); > + > + sg_free_table(sg); > + kfree(sg); > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_UNMAP); > + > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > +} > + > +static void hyper_dmabuf_ops_release(struct dma_buf *dmabuf) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!dmabuf->priv) > + return; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_RELEASE); > + > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > +} > + > +static int hyper_dmabuf_ops_begin_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction dir) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!dmabuf->priv) > + return -EINVAL; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_BEGIN_CPU_ACCESS); > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > + > + return ret; > +} > + > +static int hyper_dmabuf_ops_end_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction dir) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!dmabuf->priv) > + return -EINVAL; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_END_CPU_ACCESS); > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > + > + return 0; > +} > + > +static void *hyper_dmabuf_ops_kmap_atomic(struct dma_buf *dmabuf, unsigned long pgnum) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!dmabuf->priv) > + return NULL; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_KMAP_ATOMIC); > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > + > + return NULL; /* for now NULL.. need to return the address of mapped region */ > +} > + > +static void hyper_dmabuf_ops_kunmap_atomic(struct dma_buf *dmabuf, unsigned long pgnum, void *vaddr) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!dmabuf->priv) > + return; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_KUNMAP_ATOMIC); > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > +} > + > +static void *hyper_dmabuf_ops_kmap(struct dma_buf *dmabuf, unsigned long pgnum) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!dmabuf->priv) > + return NULL; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_KMAP); > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > + > + return NULL; /* for now NULL.. need to return the address of mapped region */ > +} > + > +static void hyper_dmabuf_ops_kunmap(struct dma_buf *dmabuf, unsigned long pgnum, void *vaddr) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!dmabuf->priv) > + return; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_KUNMAP); > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > +} > + > +static int hyper_dmabuf_ops_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!dmabuf->priv) > + return -EINVAL; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_MMAP); > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > + > + return ret; > +} > + > +static void *hyper_dmabuf_ops_vmap(struct dma_buf *dmabuf) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!dmabuf->priv) > + return NULL; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_VMAP); > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > + > + return NULL; > +} > + > +static void hyper_dmabuf_ops_vunmap(struct dma_buf *dmabuf, void *vaddr) > +{ > + struct hyper_dmabuf_imported_sgt_info *sgt_info; > + int ret; > + > + if (!dmabuf->priv) > + return; > + > + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; > + > + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), > + HYPER_DMABUF_OPS_VUNMAP); > + if (ret < 0) { > + printk("send dmabuf sync request failed\n"); > + } > +} > + > +static const struct dma_buf_ops hyper_dmabuf_ops = { > + .attach = hyper_dmabuf_ops_attach, > + .detach = hyper_dmabuf_ops_detach, > + .map_dma_buf = hyper_dmabuf_ops_map, > + .unmap_dma_buf = hyper_dmabuf_ops_unmap, > + .release = hyper_dmabuf_ops_release, > + .begin_cpu_access = (void*)hyper_dmabuf_ops_begin_cpu_access, > + .end_cpu_access = (void*)hyper_dmabuf_ops_end_cpu_access, > + .map_atomic = hyper_dmabuf_ops_kmap_atomic, > + .unmap_atomic = hyper_dmabuf_ops_kunmap_atomic, > + .map = hyper_dmabuf_ops_kmap, > + .unmap = hyper_dmabuf_ops_kunmap, > + .mmap = hyper_dmabuf_ops_mmap, > + .vmap = hyper_dmabuf_ops_vmap, > + .vunmap = hyper_dmabuf_ops_vunmap, > +}; > + > +/* exporting dmabuf as fd */ > +int hyper_dmabuf_export_fd(struct hyper_dmabuf_imported_sgt_info *dinfo, int flags) > +{ > + int fd; > + > + struct dma_buf* dmabuf; > + > +/* call hyper_dmabuf_export_dmabuf and create and bind a handle for it > + * then release */ > + > + dmabuf = hyper_dmabuf_export_dma_buf(dinfo); > + > + fd = dma_buf_fd(dmabuf, flags); > + > + return fd; > +} > + > +struct dma_buf* hyper_dmabuf_export_dma_buf(struct hyper_dmabuf_imported_sgt_info *dinfo) > +{ > + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); > + > + exp_info.ops = &hyper_dmabuf_ops; > + exp_info.size = dinfo->sgt->nents * PAGE_SIZE; /* multiple of PAGE_SIZE, not considering offset */ > + exp_info.flags = /* not sure about flag */0; > + exp_info.priv = dinfo; > + > + return dma_buf_export(&exp_info); > +}; > diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h > new file mode 100644 > index 0000000..003c158 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h > @@ -0,0 +1,31 @@ > +#ifndef __HYPER_DMABUF_IMP_H__ > +#define __HYPER_DMABUF_IMP_H__ > + > +#include "hyper_dmabuf_struct.h" > + > +/* extract pages directly from struct sg_table */ > +struct hyper_dmabuf_pages_info *hyper_dmabuf_ext_pgs(struct sg_table *sgt); > + > +/* create sg_table with given pages and other parameters */ > +struct sg_table* hyper_dmabuf_create_sgt(struct page **pages, > + int frst_ofst, int last_len, int nents); > + > +grant_ref_t hyper_dmabuf_create_gref_table(struct page **pages, int rdomain, int nents, > + struct hyper_dmabuf_shared_pages_info *shared_pages_info); > + > +int hyper_dmabuf_cleanup_gref_table(struct hyper_dmabuf_sgt_info *sgt_info); > + > +int hyper_dmabuf_cleanup_imported_pages(struct hyper_dmabuf_imported_sgt_info *sgt_info); > + > +/* map first level tables that contains reference numbers for actual shared pages */ > +grant_ref_t *hyper_dmabuf_map_gref_table(grant_ref_t *gref_table, int n_pages_table); > + > +/* map and construct sg_lists from reference numbers */ > +struct sg_table* hyper_dmabuf_map_pages(grant_ref_t gref, int frst_ofst, int last_len, int nents, int sdomain, > + struct hyper_dmabuf_shared_pages_info *shared_pages_info); > + > +int hyper_dmabuf_export_fd(struct hyper_dmabuf_imported_sgt_info *dinfo, int flags); > + > +struct dma_buf* hyper_dmabuf_export_dma_buf(struct hyper_dmabuf_imported_sgt_info *dinfo); > + > +#endif /* __HYPER_DMABUF_IMP_H__ */ > diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c > new file mode 100644 > index 0000000..5e50908 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c > @@ -0,0 +1,462 @@ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "hyper_dmabuf_struct.h" > +#include "hyper_dmabuf_imp.h" > +#include "hyper_dmabuf_list.h" > +#include "hyper_dmabuf_drv.h" > +#include "hyper_dmabuf_query.h" > +#include "xen/hyper_dmabuf_xen_comm.h" > +#include "hyper_dmabuf_msg.h" > + > +struct hyper_dmabuf_private { > + struct device *device; > +} hyper_dmabuf_private; > + > +static uint32_t hyper_dmabuf_id_gen(void) { > + /* TODO: add proper implementation */ > + static uint32_t id = 0; > + static int32_t domid = -1; > + if (domid == -1) { > + domid = hyper_dmabuf_get_domid(); > + } > + return HYPER_DMABUF_ID_IMPORTER(domid, id++); > +} > + > +static int hyper_dmabuf_exporter_ring_setup(void *data) > +{ > + struct ioctl_hyper_dmabuf_exporter_ring_setup *ring_attr; > + int ret = 0; > + > + if (!data) { > + printk("user data is NULL\n"); > + return -1; > + } > + ring_attr = (struct ioctl_hyper_dmabuf_exporter_ring_setup *)data; > + > + ret = hyper_dmabuf_exporter_ringbuf_init(ring_attr->remote_domain, > + &ring_attr->ring_refid, > + &ring_attr->port); > + > + return ret; > +} > + > +static int hyper_dmabuf_importer_ring_setup(void *data) > +{ > + struct ioctl_hyper_dmabuf_importer_ring_setup *setup_imp_ring_attr; > + int ret = 0; > + > + if (!data) { > + printk("user data is NULL\n"); > + return -1; > + } > + > + setup_imp_ring_attr = (struct ioctl_hyper_dmabuf_importer_ring_setup *)data; > + > + /* user need to provide a port number and ref # for the page used as ring buffer */ > + ret = hyper_dmabuf_importer_ringbuf_init(setup_imp_ring_attr->source_domain, > + setup_imp_ring_attr->ring_refid, > + setup_imp_ring_attr->port); > + > + return ret; > +} > + > +static int hyper_dmabuf_export_remote(void *data) > +{ > + struct ioctl_hyper_dmabuf_export_remote *export_remote_attr; > + struct dma_buf *dma_buf; > + struct dma_buf_attachment *attachment; > + struct sg_table *sgt; > + struct hyper_dmabuf_pages_info *page_info; > + struct hyper_dmabuf_sgt_info *sgt_info; > + struct hyper_dmabuf_ring_rq *req; > + int operands[9]; > + int ret = 0; > + > + if (!data) { > + printk("user data is NULL\n"); > + return -1; > + } > + > + export_remote_attr = (struct ioctl_hyper_dmabuf_export_remote *)data; > + > + dma_buf = dma_buf_get(export_remote_attr->dmabuf_fd); > + if (!dma_buf) { > + printk("Cannot get dma buf\n"); > + return -1; > + } > + > + attachment = dma_buf_attach(dma_buf, hyper_dmabuf_private.device); > + if (!attachment) { > + printk("Cannot get attachment\n"); > + return -1; > + } > + > + /* we check if this specific attachment was already exported > + * to the same domain and if yes, it returns hyper_dmabuf_id > + * of pre-exported sgt */ > + ret = hyper_dmabuf_find_id(attachment, export_remote_attr->remote_domain); > + if (ret != -1) { > + dma_buf_detach(dma_buf, attachment); > + dma_buf_put(dma_buf); > + export_remote_attr->hyper_dmabuf_id = ret; > + return 0; > + } > + /* Clear ret, as that will cause whole ioctl to return failure to userspace, which is not true */ > + ret = 0; > + > + sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL); > + > + sgt_info = kmalloc(sizeof(*sgt_info), GFP_KERNEL); > + > + sgt_info->hyper_dmabuf_id = hyper_dmabuf_id_gen(); > + /* TODO: We might need to consider using port number on event channel? */ > + sgt_info->hyper_dmabuf_rdomain = export_remote_attr->remote_domain; > + sgt_info->sgt = sgt; > + sgt_info->attachment = attachment; > + sgt_info->dma_buf = dma_buf; > + > + page_info = hyper_dmabuf_ext_pgs(sgt); > + if (page_info == NULL) > + goto fail_export; > + > + /* now register it to export list */ > + hyper_dmabuf_register_exported(sgt_info); > + > + page_info->hyper_dmabuf_rdomain = sgt_info->hyper_dmabuf_rdomain; > + page_info->hyper_dmabuf_id = sgt_info->hyper_dmabuf_id; /* may not be needed */ > + > + export_remote_attr->hyper_dmabuf_id = sgt_info->hyper_dmabuf_id; > + > + /* now create table of grefs for shared pages and */ > + > + /* now create request for importer via ring */ > + operands[0] = page_info->hyper_dmabuf_id; > + operands[1] = page_info->nents; > + operands[2] = page_info->frst_ofst; > + operands[3] = page_info->last_len; > + operands[4] = hyper_dmabuf_create_gref_table(page_info->pages, export_remote_attr->remote_domain, > + page_info->nents, &sgt_info->shared_pages_info); > + /* driver/application specific private info, max 32 bytes */ > + operands[5] = export_remote_attr->private[0]; > + operands[6] = export_remote_attr->private[1]; > + operands[7] = export_remote_attr->private[2]; > + operands[8] = export_remote_attr->private[3]; > + > + req = kcalloc(1, sizeof(*req), GFP_KERNEL); > + > + /* composing a message to the importer */ > + hyper_dmabuf_create_request(req, HYPER_DMABUF_EXPORT, &operands[0]); > + if(hyper_dmabuf_send_request(export_remote_attr->remote_domain, req)) > + goto fail_send_request; > + > + /* free msg */ > + kfree(req); > + /* free page_info */ > + kfree(page_info); > + > + return ret; > + > +fail_send_request: > + kfree(req); > + hyper_dmabuf_remove_exported(sgt_info->hyper_dmabuf_id); > + > +fail_export: > + dma_buf_unmap_attachment(sgt_info->attachment, sgt_info->sgt, DMA_BIDIRECTIONAL); > + dma_buf_detach(sgt_info->dma_buf, sgt_info->attachment); > + dma_buf_put(sgt_info->dma_buf); > + > + return -EINVAL; > +} > + > +static int hyper_dmabuf_export_fd_ioctl(void *data) > +{ > + struct ioctl_hyper_dmabuf_export_fd *export_fd_attr; > + struct hyper_dmabuf_imported_sgt_info *imported_sgt_info; > + int ret = 0; > + > + if (!data) { > + printk("user data is NULL\n"); > + return -1; > + } > + > + export_fd_attr = (struct ioctl_hyper_dmabuf_export_fd *)data; > + > + /* look for dmabuf for the id */ > + imported_sgt_info = hyper_dmabuf_find_imported(export_fd_attr->hyper_dmabuf_id); > + if (imported_sgt_info == NULL) /* can't find sgt from the table */ > + return -1; > + > + printk("%s Found buffer gref %d off %d last len %d nents %d domain %d\n", __func__, > + imported_sgt_info->gref, imported_sgt_info->frst_ofst, > + imported_sgt_info->last_len, imported_sgt_info->nents, > + HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(imported_sgt_info->hyper_dmabuf_id)); > + > + imported_sgt_info->sgt = hyper_dmabuf_map_pages(imported_sgt_info->gref, > + imported_sgt_info->frst_ofst, > + imported_sgt_info->last_len, > + imported_sgt_info->nents, > + HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(imported_sgt_info->hyper_dmabuf_id), > + &imported_sgt_info->shared_pages_info); > + > + if (!imported_sgt_info->sgt) { > + return -1; > + } > + > + export_fd_attr->fd = hyper_dmabuf_export_fd(imported_sgt_info, export_fd_attr->flags); > + if (export_fd_attr < 0) { > + ret = export_fd_attr->fd; > + } > + > + return ret; > +} > + > +/* removing dmabuf from the database and send int req to the source domain > +* to unmap it. */ > +static int hyper_dmabuf_destroy(void *data) > +{ > + struct ioctl_hyper_dmabuf_destroy *destroy_attr; > + struct hyper_dmabuf_sgt_info *sgt_info; > + struct hyper_dmabuf_ring_rq *req; > + int ret; > + > + if (!data) { > + printk("user data is NULL\n"); > + return -EINVAL; > + } > + > + destroy_attr = (struct ioctl_hyper_dmabuf_destroy *)data; > + > + /* find dmabuf in export list */ > + sgt_info = hyper_dmabuf_find_exported(destroy_attr->hyper_dmabuf_id); > + if (sgt_info == NULL) { /* failed to find corresponding entry in export list */ > + destroy_attr->status = -EINVAL; > + return -EFAULT; > + } > + > + req = kcalloc(1, sizeof(*req), GFP_KERNEL); > + > + hyper_dmabuf_create_request(req, HYPER_DMABUF_DESTROY, &destroy_attr->hyper_dmabuf_id); > + > + /* now send destroy request to remote domain > + * currently assuming there's only one importer exist */ > + ret = hyper_dmabuf_send_request(sgt_info->hyper_dmabuf_rdomain, req); > + if (ret < 0) { > + kfree(req); > + return -EFAULT; > + } > + > + /* free msg */ > + kfree(req); > + destroy_attr->status = ret; > + > + /* Rest of cleanup will follow when importer will free it's buffer, > + * current implementation assumes that there is only one importer > + */ > + > + return ret; > +} > + > +static int hyper_dmabuf_query(void *data) > +{ > + struct ioctl_hyper_dmabuf_query *query_attr; > + struct hyper_dmabuf_sgt_info *sgt_info; > + struct hyper_dmabuf_imported_sgt_info *imported_sgt_info; > + int ret = 0; > + > + if (!data) { > + printk("user data is NULL\n"); > + return -EINVAL; > + } > + > + query_attr = (struct ioctl_hyper_dmabuf_query *)data; > + > + sgt_info = hyper_dmabuf_find_exported(query_attr->hyper_dmabuf_id); > + imported_sgt_info = hyper_dmabuf_find_imported(query_attr->hyper_dmabuf_id); > + > + /* if dmabuf can't be found in both lists, return */ > + if (!(sgt_info && imported_sgt_info)) { > + printk("can't find entry anywhere\n"); > + return -EINVAL; > + } > + > + /* not considering the case where a dmabuf is found on both queues > + * in one domain */ > + switch (query_attr->item) > + { > + case DMABUF_QUERY_TYPE_LIST: > + if (sgt_info) { > + query_attr->info = EXPORTED; > + } else { > + query_attr->info = IMPORTED; > + } > + break; > + > + /* exporting domain of this specific dmabuf*/ > + case DMABUF_QUERY_EXPORTER: > + if (sgt_info) { > + query_attr->info = 0xFFFFFFFF; /* myself */ > + } else { > + query_attr->info = (HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(imported_sgt_info->hyper_dmabuf_id)); > + } > + break; > + > + /* importing domain of this specific dmabuf */ > + case DMABUF_QUERY_IMPORTER: > + if (sgt_info) { > + query_attr->info = sgt_info->hyper_dmabuf_rdomain; > + } else { > +#if 0 /* TODO: a global variable, current_domain does not exist yet*/ > + query_attr->info = current_domain; > +#endif > + } > + break; > + > + /* size of dmabuf in byte */ > + case DMABUF_QUERY_SIZE: > + if (sgt_info) { > +#if 0 /* TODO: hyper_dmabuf_buf_size is not implemented yet */ > + query_attr->info = hyper_dmabuf_buf_size(sgt_info->sgt); > +#endif > + } else { > + query_attr->info = imported_sgt_info->nents * 4096 - > + imported_sgt_info->frst_ofst - 4096 + > + imported_sgt_info->last_len; > + } > + break; > + } > + > + return ret; > +} > + > +static int hyper_dmabuf_remote_exporter_ring_setup(void *data) > +{ > + struct ioctl_hyper_dmabuf_remote_exporter_ring_setup *remote_exporter_ring_setup; > + struct hyper_dmabuf_ring_rq *req; > + > + remote_exporter_ring_setup = (struct ioctl_hyper_dmabuf_remote_exporter_ring_setup *)data; > + > + req = kcalloc(1, sizeof(*req), GFP_KERNEL); > + hyper_dmabuf_create_request(req, HYPER_DMABUF_EXPORTER_RING_SETUP, NULL); > + > + /* requesting remote domain to set-up exporter's ring */ > + if(hyper_dmabuf_send_request(remote_exporter_ring_setup->rdomain, req) < 0) { > + kfree(req); > + return -EINVAL; > + } > + > + kfree(req); > + return 0; > +} > + > +static const struct hyper_dmabuf_ioctl_desc hyper_dmabuf_ioctls[] = { > + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_EXPORTER_RING_SETUP, hyper_dmabuf_exporter_ring_setup, 0), > + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_IMPORTER_RING_SETUP, hyper_dmabuf_importer_ring_setup, 0), > + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_EXPORT_REMOTE, hyper_dmabuf_export_remote, 0), > + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_EXPORT_FD, hyper_dmabuf_export_fd_ioctl, 0), > + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_DESTROY, hyper_dmabuf_destroy, 0), > + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_QUERY, hyper_dmabuf_query, 0), > + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_REMOTE_EXPORTER_RING_SETUP, hyper_dmabuf_remote_exporter_ring_setup, 0), > +}; > + > +static long hyper_dmabuf_ioctl(struct file *filp, > + unsigned int cmd, unsigned long param) > +{ > + const struct hyper_dmabuf_ioctl_desc *ioctl = NULL; > + unsigned int nr = _IOC_NR(cmd); > + int ret = -EINVAL; > + hyper_dmabuf_ioctl_t func; > + char *kdata; > + > + ioctl = &hyper_dmabuf_ioctls[nr]; > + > + func = ioctl->func; > + > + if (unlikely(!func)) { > + printk("no function\n"); > + return -EINVAL; > + } > + > + kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); > + if (!kdata) { > + printk("no memory\n"); > + return -ENOMEM; > + } > + > + if (copy_from_user(kdata, (void __user *)param, _IOC_SIZE(cmd)) != 0) { > + printk("failed to copy from user arguments\n"); > + return -EFAULT; > + } > + > + ret = func(kdata); > + > + if (copy_to_user((void __user *)param, kdata, _IOC_SIZE(cmd)) != 0) { > + printk("failed to copy to user arguments\n"); > + return -EFAULT; > + } > + > + kfree(kdata); > + > + return ret; > +} > + > +struct device_info { > + int curr_domain; > +}; > + > +/*===============================================================================================*/ > +static struct file_operations hyper_dmabuf_driver_fops = > +{ > + .owner = THIS_MODULE, > + .unlocked_ioctl = hyper_dmabuf_ioctl, > +}; > + > +static struct miscdevice hyper_dmabuf_miscdev = { > + .minor = MISC_DYNAMIC_MINOR, > + .name = "xen/hyper_dmabuf", > + .fops = &hyper_dmabuf_driver_fops, > +}; > + > +static const char device_name[] = "hyper_dmabuf"; > + > +/*===============================================================================================*/ > +int register_device(void) > +{ > + int result = 0; > + > + result = misc_register(&hyper_dmabuf_miscdev); > + > + if (result != 0) { > + printk(KERN_WARNING "hyper_dmabuf: driver can't be registered\n"); > + return result; > + } > + > + hyper_dmabuf_private.device = hyper_dmabuf_miscdev.this_device; > + > + /* TODO: Check if there is a different way to initialize dma mask nicely */ > + dma_coerce_mask_and_coherent(hyper_dmabuf_private.device, 0xFFFFFFFF); > + > + /* TODO find a way to provide parameters for below function or move that to ioctl */ > +/* err = bind_interdomain_evtchn_to_irqhandler(rdomain, evtchn, > + src_sink_isr, PORT_NUM, "remote_domain", &info); > + if (err < 0) { > + printk("hyper_dmabuf: can't register interrupt handlers\n"); > + return -EFAULT; > + } > + > + info.irq = err; > +*/ > + return result; > +} > + > +/*-----------------------------------------------------------------------------------------------*/ > +void unregister_device(void) > +{ > + printk( KERN_NOTICE "hyper_dmabuf: unregister_device() is called" ); > + misc_deregister(&hyper_dmabuf_miscdev); > +} > diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c > new file mode 100644 > index 0000000..77a7e65 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c > @@ -0,0 +1,119 @@ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "hyper_dmabuf_list.h" > + > +DECLARE_HASHTABLE(hyper_dmabuf_hash_imported, MAX_ENTRY_IMPORTED); > +DECLARE_HASHTABLE(hyper_dmabuf_hash_exported, MAX_ENTRY_EXPORTED); > + > +int hyper_dmabuf_table_init() > +{ > + hash_init(hyper_dmabuf_hash_imported); > + hash_init(hyper_dmabuf_hash_exported); > + return 0; > +} > + > +int hyper_dmabuf_table_destroy() > +{ > + /* TODO: cleanup hyper_dmabuf_hash_imported and hyper_dmabuf_hash_exported */ > + return 0; > +} > + > +int hyper_dmabuf_register_exported(struct hyper_dmabuf_sgt_info *info) > +{ > + struct hyper_dmabuf_info_entry_exported *info_entry; > + > + info_entry = kmalloc(sizeof(*info_entry), GFP_KERNEL); > + > + info_entry->info = info; > + > + hash_add(hyper_dmabuf_hash_exported, &info_entry->node, > + info_entry->info->hyper_dmabuf_id); > + > + return 0; > +} > + > +int hyper_dmabuf_register_imported(struct hyper_dmabuf_imported_sgt_info* info) > +{ > + struct hyper_dmabuf_info_entry_imported *info_entry; > + > + info_entry = kmalloc(sizeof(*info_entry), GFP_KERNEL); > + > + info_entry->info = info; > + > + hash_add(hyper_dmabuf_hash_imported, &info_entry->node, > + info_entry->info->hyper_dmabuf_id); > + > + return 0; > +} > + > +struct hyper_dmabuf_sgt_info *hyper_dmabuf_find_exported(int id) > +{ > + struct hyper_dmabuf_info_entry_exported *info_entry; > + int bkt; > + > + hash_for_each(hyper_dmabuf_hash_exported, bkt, info_entry, node) > + if(info_entry->info->hyper_dmabuf_id == id) > + return info_entry->info; > + > + return NULL; > +} > + > +/* search for pre-exported sgt and return id of it if it exist */ > +int hyper_dmabuf_find_id(struct dma_buf_attachment *attach, int domid) > +{ > + struct hyper_dmabuf_info_entry_exported *info_entry; > + int bkt; > + > + hash_for_each(hyper_dmabuf_hash_exported, bkt, info_entry, node) > + if(info_entry->info->attachment == attach && > + info_entry->info->hyper_dmabuf_rdomain == domid) > + return info_entry->info->hyper_dmabuf_id; > + > + return -1; > +} > + > +struct hyper_dmabuf_imported_sgt_info *hyper_dmabuf_find_imported(int id) > +{ > + struct hyper_dmabuf_info_entry_imported *info_entry; > + int bkt; > + > + hash_for_each(hyper_dmabuf_hash_imported, bkt, info_entry, node) > + if(info_entry->info->hyper_dmabuf_id == id) > + return info_entry->info; > + > + return NULL; > +} > + > +int hyper_dmabuf_remove_exported(int id) > +{ > + struct hyper_dmabuf_info_entry_exported *info_entry; > + int bkt; > + > + hash_for_each(hyper_dmabuf_hash_exported, bkt, info_entry, node) > + if(info_entry->info->hyper_dmabuf_id == id) { > + hash_del(&info_entry->node); > + return 0; > + } > + > + return -1; > +} > + > +int hyper_dmabuf_remove_imported(int id) > +{ > + struct hyper_dmabuf_info_entry_imported *info_entry; > + int bkt; > + > + hash_for_each(hyper_dmabuf_hash_imported, bkt, info_entry, node) > + if(info_entry->info->hyper_dmabuf_id == id) { > + hash_del(&info_entry->node); > + return 0; > + } > + > + return -1; > +} > diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h > new file mode 100644 > index 0000000..869cd9a > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h > @@ -0,0 +1,40 @@ > +#ifndef __HYPER_DMABUF_LIST_H__ > +#define __HYPER_DMABUF_LIST_H__ > + > +#include "hyper_dmabuf_struct.h" > + > +/* number of bits to be used for exported dmabufs hash table */ > +#define MAX_ENTRY_EXPORTED 7 > +/* number of bits to be used for imported dmabufs hash table */ > +#define MAX_ENTRY_IMPORTED 7 > + > +struct hyper_dmabuf_info_entry_exported { > + struct hyper_dmabuf_sgt_info *info; > + struct hlist_node node; > +}; > + > +struct hyper_dmabuf_info_entry_imported { > + struct hyper_dmabuf_imported_sgt_info *info; > + struct hlist_node node; > +}; > + > +int hyper_dmabuf_table_init(void); > + > +int hyper_dmabuf_table_destroy(void); > + > +int hyper_dmabuf_register_exported(struct hyper_dmabuf_sgt_info *info); > + > +/* search for pre-exported sgt and return id of it if it exist */ > +int hyper_dmabuf_find_id(struct dma_buf_attachment *attach, int domid); > + > +int hyper_dmabuf_register_imported(struct hyper_dmabuf_imported_sgt_info* info); > + > +struct hyper_dmabuf_sgt_info *hyper_dmabuf_find_exported(int id); > + > +struct hyper_dmabuf_imported_sgt_info *hyper_dmabuf_find_imported(int id); > + > +int hyper_dmabuf_remove_exported(int id); > + > +int hyper_dmabuf_remove_imported(int id); > + > +#endif // __HYPER_DMABUF_LIST_H__ > diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c > new file mode 100644 > index 0000000..3237e50 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c > @@ -0,0 +1,212 @@ > +#include > +#include > +#include > +#include > +#include > +#include "hyper_dmabuf_imp.h" > +//#include "hyper_dmabuf_remote_sync.h" > +#include "xen/hyper_dmabuf_xen_comm.h" > +#include "hyper_dmabuf_msg.h" > +#include "hyper_dmabuf_list.h" > + > +void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request, > + enum hyper_dmabuf_command command, int *operands) > +{ > + int i; > + > + request->request_id = hyper_dmabuf_next_req_id_export(); > + request->status = HYPER_DMABUF_REQ_NOT_RESPONDED; > + request->command = command; > + > + switch(command) { > + /* as exporter, commands to importer */ > + case HYPER_DMABUF_EXPORT: > + /* exporting pages for dmabuf */ > + /* command : HYPER_DMABUF_EXPORT, > + * operands0 : hyper_dmabuf_id > + * operands1 : number of pages to be shared > + * operands2 : offset of data in the first page > + * operands3 : length of data in the last page > + * operands4 : top-level reference number for shared pages > + * operands5~8 : Driver-specific private data (e.g. graphic buffer's meta info) > + */ > + for (i=0; i < 8; i++) > + request->operands[i] = operands[i]; > + break; > + > + case HYPER_DMABUF_DESTROY: > + /* destroy sg_list for hyper_dmabuf_id on remote side */ > + /* command : DMABUF_DESTROY, > + * operands0 : hyper_dmabuf_id > + */ > + request->operands[0] = operands[0]; > + break; > + > + case HYPER_DMABUF_OPS_TO_REMOTE: > + /* notifying dmabuf map/unmap to importer (probably not needed) */ > + /* for dmabuf synchronization */ > + break; > + > + /* as importer, command to exporter */ > + case HYPER_DMABUF_OPS_TO_SOURCE: > + /* notifying dmabuf map/unmap to exporter, map will make the driver to do shadow mapping > + * or unmapping for synchronization with original exporter (e.g. i915) */ > + /* command : DMABUF_OPS_TO_SOURCE. > + * operands0 : hyper_dmabuf_id > + * operands1 : map(=1)/unmap(=2)/attach(=3)/detach(=4) > + */ > + for (i=0; i<2; i++) > + request->operands[i] = operands[i]; > + break; > + > + /* requesting the other side to setup another ring channel for reverse direction */ > + case HYPER_DMABUF_EXPORTER_RING_SETUP: > + /* command : HYPER_DMABUF_EXPORTER_RING_SETUP */ > + /* no operands needed */ > + break; > + > + default: > + /* no command found */ > + return; > + } > +} > + > +int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_ring_rq *req) > +{ > + uint32_t i, ret; > + struct hyper_dmabuf_imported_sgt_info *imported_sgt_info; > + struct hyper_dmabuf_sgt_info *sgt_info; > + > + /* make sure req is not NULL (may not be needed) */ > + if (!req) { > + return -EINVAL; > + } > + > + req->status = HYPER_DMABUF_REQ_PROCESSED; > + > + switch (req->command) { > + case HYPER_DMABUF_EXPORT: > + /* exporting pages for dmabuf */ > + /* command : HYPER_DMABUF_EXPORT, > + * operands0 : hyper_dmabuf_id > + * operands1 : number of pages to be shared > + * operands2 : offset of data in the first page > + * operands3 : length of data in the last page > + * operands4 : top-level reference number for shared pages > + * operands5~8 : Driver-specific private data (e.g. graphic buffer's meta info) > + */ > + imported_sgt_info = (struct hyper_dmabuf_imported_sgt_info*)kcalloc(1, sizeof(*imported_sgt_info), GFP_KERNEL); > + imported_sgt_info->hyper_dmabuf_id = req->operands[0]; > + imported_sgt_info->frst_ofst = req->operands[2]; > + imported_sgt_info->last_len = req->operands[3]; > + imported_sgt_info->nents = req->operands[1]; > + imported_sgt_info->gref = req->operands[4]; > + > + printk("DMABUF was exported\n"); > + printk("\thyper_dmabuf_id %d\n", req->operands[0]); > + printk("\tnents %d\n", req->operands[1]); > + printk("\tfirst offset %d\n", req->operands[2]); > + printk("\tlast len %d\n", req->operands[3]); > + printk("\tgrefid %d\n", req->operands[4]); > + > + for (i=0; i<4; i++) > + imported_sgt_info->private[i] = req->operands[5+i]; > + > + hyper_dmabuf_register_imported(imported_sgt_info); > + break; > + > + case HYPER_DMABUF_DESTROY: > + /* destroy sg_list for hyper_dmabuf_id on remote side */ > + /* command : DMABUF_DESTROY, > + * operands0 : hyper_dmabuf_id > + */ > + > + imported_sgt_info = > + hyper_dmabuf_find_imported(req->operands[0]); > + > + if (imported_sgt_info) { > + hyper_dmabuf_cleanup_imported_pages(imported_sgt_info); > + > + hyper_dmabuf_remove_imported(req->operands[0]); > + > + /* TODO: cleanup sgt on importer side etc */ > + } > + > + /* Notify exporter that buffer is freed and it can cleanup it */ > + req->status = HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP; > + req->command = HYPER_DMABUF_DESTROY_FINISH; > + > +#if 0 /* function is not implemented yet */ > + > + ret = hyper_dmabuf_destroy_sgt(req->hyper_dmabuf_id); > +#endif > + break; > + > + case HYPER_DMABUF_DESTROY_FINISH: > + /* destroy sg_list for hyper_dmabuf_id on local side */ > + /* command : DMABUF_DESTROY_FINISH, > + * operands0 : hyper_dmabuf_id > + */ > + > + /* TODO: that should be done on workqueue, when received ack from all importers that buffer is no longer used */ > + sgt_info = > + hyper_dmabuf_find_exported(req->operands[0]); > + > + if (sgt_info) { > + hyper_dmabuf_cleanup_gref_table(sgt_info); > + > + /* unmap dmabuf */ > + dma_buf_unmap_attachment(sgt_info->attachment, sgt_info->sgt, DMA_BIDIRECTIONAL); > + dma_buf_detach(sgt_info->dma_buf, sgt_info->attachment); > + dma_buf_put(sgt_info->dma_buf); > + > + /* TODO: Rest of cleanup, sgt cleanup etc */ > + } > + > + break; > + > + case HYPER_DMABUF_OPS_TO_REMOTE: > + /* notifying dmabuf map/unmap to importer (probably not needed) */ > + /* for dmabuf synchronization */ > + break; > + > + /* as importer, command to exporter */ > + case HYPER_DMABUF_OPS_TO_SOURCE: > + /* notifying dmabuf map/unmap to exporter, map will make the driver to do shadow mapping > + * or unmapping for synchronization with original exporter (e.g. i915) */ > + /* command : DMABUF_OPS_TO_SOURCE. > + * operands0 : hyper_dmabuf_id > + * operands1 : map(=1)/unmap(=2)/attach(=3)/detach(=4) > + */ > + break; > + > + /* requesting the other side to setup another ring channel for reverse direction */ > + case HYPER_DMABUF_EXPORTER_RING_SETUP: > + /* command: HYPER_DMABUF_EXPORTER_RING_SETUP > + * no operands needed */ > + ret = hyper_dmabuf_exporter_ringbuf_init(domid, &req->operands[0], &req->operands[1]); > + if (ret < 0) { > + req->status = HYPER_DMABUF_REQ_ERROR; > + return -EINVAL; > + } > + > + req->status = HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP; > + req->command = HYPER_DMABUF_IMPORTER_RING_SETUP; > + break; > + > + case HYPER_DMABUF_IMPORTER_RING_SETUP: > + /* command: HYPER_DMABUF_IMPORTER_RING_SETUP */ > + /* no operands needed */ > + ret = hyper_dmabuf_importer_ringbuf_init(domid, req->operands[0], req->operands[1]); > + if (ret < 0) > + return -EINVAL; > + > + break; > + > + default: > + /* no matched command, nothing to do.. just return error */ > + return -EINVAL; > + } > + > + return req->command; > +} > diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h > new file mode 100644 > index 0000000..44bfb70 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h > @@ -0,0 +1,45 @@ > +#ifndef __HYPER_DMABUF_MSG_H__ > +#define __HYPER_DMABUF_MSG_H__ > + > +enum hyper_dmabuf_command { > + HYPER_DMABUF_EXPORT = 0x10, > + HYPER_DMABUF_DESTROY, > + HYPER_DMABUF_DESTROY_FINISH, > + HYPER_DMABUF_OPS_TO_REMOTE, > + HYPER_DMABUF_OPS_TO_SOURCE, > + HYPER_DMABUF_EXPORTER_RING_SETUP, /* requesting remote domain to set up exporter's ring */ > + HYPER_DMABUF_IMPORTER_RING_SETUP, /* requesting remote domain to set up importer's ring */ > +}; > + > +enum hyper_dmabuf_ops { > + HYPER_DMABUF_OPS_ATTACH = 0x1000, > + HYPER_DMABUF_OPS_DETACH, > + HYPER_DMABUF_OPS_MAP, > + HYPER_DMABUF_OPS_UNMAP, > + HYPER_DMABUF_OPS_RELEASE, > + HYPER_DMABUF_OPS_BEGIN_CPU_ACCESS, > + HYPER_DMABUF_OPS_END_CPU_ACCESS, > + HYPER_DMABUF_OPS_KMAP_ATOMIC, > + HYPER_DMABUF_OPS_KUNMAP_ATOMIC, > + HYPER_DMABUF_OPS_KMAP, > + HYPER_DMABUF_OPS_KUNMAP, > + HYPER_DMABUF_OPS_MMAP, > + HYPER_DMABUF_OPS_VMAP, > + HYPER_DMABUF_OPS_VUNMAP, > +}; > + > +enum hyper_dmabuf_req_feedback { > + HYPER_DMABUF_REQ_PROCESSED = 0x100, > + HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP, > + HYPER_DMABUF_REQ_ERROR, > + HYPER_DMABUF_REQ_NOT_RESPONDED > +}; > + > +/* create a request packet with given command and operands */ > +void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request, > + enum hyper_dmabuf_command command, int *operands); > + > +/* parse incoming request packet (or response) and take appropriate actions for those */ > +int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_ring_rq *req); > + > +#endif // __HYPER_DMABUF_MSG_H__ > diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h > new file mode 100644 > index 0000000..a577167 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h > @@ -0,0 +1,16 @@ > +#ifndef __HYPER_DMABUF_QUERY_H__ > +#define __HYPER_DMABUF_QUERY_H__ > + > +enum hyper_dmabuf_query { > + DMABUF_QUERY_TYPE_LIST = 0x10, > + DMABUF_QUERY_EXPORTER, > + DMABUF_QUERY_IMPORTER, > + DMABUF_QUERY_SIZE > +}; > + > +enum hyper_dmabuf_status { > + EXPORTED = 0x01, > + IMPORTED > +}; > + > +#endif /* __HYPER_DMABUF_QUERY_H__ */ > diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h > new file mode 100644 > index 0000000..c8a2f4d > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h > @@ -0,0 +1,70 @@ > +#ifndef __HYPER_DMABUF_STRUCT_H__ > +#define __HYPER_DMABUF_STRUCT_H__ > + > +#include > + > +/* Importer combine source domain id with given hyper_dmabuf_id > + * to make it unique in case there are multiple exporters */ > + > +#define HYPER_DMABUF_ID_IMPORTER(sdomain, id) \ > + ((((sdomain) & 0xFF) << 24) | ((id) & 0xFFFFFF)) > + > +#define HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(id) \ > + (((id) >> 24) & 0xFF) > + > +/* each grant_ref_t is 4 bytes, so total 4096 grant_ref_t can be > + * in this block meaning we can share 4KB*4096 = 16MB of buffer > + * (needs to be increased for large buffer use-cases such as 4K > + * frame buffer) */ > +#define MAX_ALLOWED_NUM_PAGES_FOR_GREF_NUM_ARRAYS 4 > + > +struct hyper_dmabuf_shared_pages_info { > + grant_ref_t *data_refs; /* table with shared buffer pages refid */ > + grant_ref_t *addr_pages; /* pages of 2nd level addressing */ > + grant_ref_t *top_level_page; /* page of top level addressing, it contains refids of 2nd level pages */ > + grant_ref_t top_level_ref; /* top level refid */ > + struct gnttab_unmap_grant_ref* unmap_ops; /* unmap ops for mapped pages */ > + struct page **data_pages; /* data pages to be unmapped */ > +}; > + > +/* Exporter builds pages_info before sharing pages */ > +struct hyper_dmabuf_pages_info { > + int hyper_dmabuf_id; /* unique id to reference dmabuf in source domain */ > + int hyper_dmabuf_rdomain; /* currenting considering just one remote domain access it */ > + int frst_ofst; /* offset of data in the first page */ > + int last_len; /* length of data in the last page */ > + int nents; /* # of pages */ > + struct page **pages; /* pages that contains reference numbers of shared pages*/ > +}; > + > +/* Both importer and exporter use this structure to point to sg lists > + * > + * Exporter stores references to sgt in a hash table > + * Exporter keeps these references for synchronization and tracking purposes > + * > + * Importer use this structure exporting to other drivers in the same domain */ > +struct hyper_dmabuf_sgt_info { > + int hyper_dmabuf_id; /* unique id to reference dmabuf in remote domain */ > + int hyper_dmabuf_rdomain; /* domain importing this sgt */ > + struct sg_table *sgt; /* pointer to sgt */ > + struct dma_buf *dma_buf; /* needed to store this for freeing it later */ > + struct dma_buf_attachment *attachment; /* needed to store this for freeing this later */ > + struct hyper_dmabuf_shared_pages_info shared_pages_info; > + int private[4]; /* device specific info (e.g. image's meta info?) */ > +}; > + > +/* Importer store references (before mapping) on shared pages > + * Importer store these references in the table and map it in > + * its own memory map once userspace asks for reference for the buffer */ > +struct hyper_dmabuf_imported_sgt_info { > + int hyper_dmabuf_id; /* unique id to reference dmabuf (HYPER_DMABUF_ID_IMPORTER(source domain id, exporter's hyper_dmabuf_id */ > + int frst_ofst; /* start offset in shared page #1 */ > + int last_len; /* length of data in the last shared page */ > + int nents; /* number of pages to be shared */ > + grant_ref_t gref; /* reference number of top level addressing page of shared pages */ > + struct sg_table *sgt; /* sgt pointer after importing buffer */ > + struct hyper_dmabuf_shared_pages_info shared_pages_info; > + int private[4]; /* device specific info (e.g. image's meta info?) */ > +}; > + > +#endif /* __HYPER_DMABUF_STRUCT_H__ */ > diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c > new file mode 100644 > index 0000000..22f2ef0 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c > @@ -0,0 +1,328 @@ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "hyper_dmabuf_xen_comm.h" > +#include "hyper_dmabuf_xen_comm_list.h" > +#include "../hyper_dmabuf_imp.h" > +#include "../hyper_dmabuf_list.h" > +#include "../hyper_dmabuf_msg.h" > + > +static int export_req_id = 0; > +static int import_req_id = 0; > + > +int32_t hyper_dmabuf_get_domid(void) > +{ > + struct xenbus_transaction xbt; > + int32_t domid; > + > + xenbus_transaction_start(&xbt); > + > + if (!xenbus_scanf(xbt, "domid","", "%d", &domid)) { > + domid = -1; > + } > + xenbus_transaction_end(xbt, 0); > + > + return domid; > +} > + > +int hyper_dmabuf_next_req_id_export(void) > +{ > + export_req_id++; > + return export_req_id; > +} > + > +int hyper_dmabuf_next_req_id_import(void) > +{ > + import_req_id++; > + return import_req_id; > +} > + > +/* For now cache latast rings as global variables TODO: keep them in list*/ > +static irqreturn_t hyper_dmabuf_front_ring_isr(int irq, void *dev_id); > +static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, void *dev_id); > + > +/* exporter needs to generated info for page sharing */ > +int hyper_dmabuf_exporter_ringbuf_init(int rdomain, grant_ref_t *refid, int *port) > +{ > + struct hyper_dmabuf_ring_info_export *ring_info; > + struct hyper_dmabuf_sring *sring; > + struct evtchn_alloc_unbound alloc_unbound; > + struct evtchn_close close; > + > + void *shared_ring; > + int ret; > + > + ring_info = (struct hyper_dmabuf_ring_info_export*) > + kmalloc(sizeof(*ring_info), GFP_KERNEL); > + > + /* from exporter to importer */ > + shared_ring = (void *)__get_free_pages(GFP_KERNEL, 1); > + if (shared_ring == 0) { > + return -EINVAL; > + } > + > + sring = (struct hyper_dmabuf_sring *) shared_ring; > + > + SHARED_RING_INIT(sring); > + > + FRONT_RING_INIT(&(ring_info->ring_front), sring, PAGE_SIZE); > + > + ring_info->gref_ring = gnttab_grant_foreign_access(rdomain, > + virt_to_mfn(shared_ring), 0); > + if (ring_info->gref_ring < 0) { > + return -EINVAL; /* fail to get gref */ > + } > + > + alloc_unbound.dom = DOMID_SELF; > + alloc_unbound.remote_dom = rdomain; > + ret = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &alloc_unbound); > + if (ret != 0) { > + printk("Cannot allocate event channel\n"); > + return -EINVAL; > + } > + > + /* setting up interrupt */ > + ret = bind_evtchn_to_irqhandler(alloc_unbound.port, > + hyper_dmabuf_front_ring_isr, 0, > + NULL, (void*) ring_info); > + > + if (ret < 0) { > + printk("Failed to setup event channel\n"); > + close.port = alloc_unbound.port; > + HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); > + gnttab_end_foreign_access(ring_info->gref_ring, 0, virt_to_mfn(shared_ring)); > + return -EINVAL; > + } > + > + ring_info->rdomain = rdomain; > + ring_info->irq = ret; > + ring_info->port = alloc_unbound.port; > + > + /* store refid and port numbers for userspace's use */ > + *refid = ring_info->gref_ring; > + *port = ring_info->port; > + > + printk("%s: allocated eventchannel gref %d port: %d irq: %d\n", __func__, > + ring_info->gref_ring, > + ring_info->port, > + ring_info->irq); > + > + /* register ring info */ > + ret = hyper_dmabuf_register_exporter_ring(ring_info); > + > + return ret; > +} > + > +/* importer needs to know about shared page and port numbers for ring buffer and event channel */ > +int hyper_dmabuf_importer_ringbuf_init(int sdomain, grant_ref_t gref, int port) > +{ > + struct hyper_dmabuf_ring_info_import *ring_info; > + struct hyper_dmabuf_sring *sring; > + > + struct page *shared_ring; > + > + struct gnttab_map_grant_ref *ops; > + struct gnttab_unmap_grant_ref *unmap_ops; > + int ret; > + > + ring_info = (struct hyper_dmabuf_ring_info_import *) > + kmalloc(sizeof(*ring_info), GFP_KERNEL); > + > + ring_info->sdomain = sdomain; > + ring_info->evtchn = port; > + > + ops = (struct gnttab_map_grant_ref*)kmalloc(sizeof(*ops), GFP_KERNEL); > + unmap_ops = (struct gnttab_unmap_grant_ref*)kmalloc(sizeof(*unmap_ops), GFP_KERNEL); > + > + if (gnttab_alloc_pages(1, &shared_ring)) { > + return -EINVAL; > + } > + > + gnttab_set_map_op(&ops[0], (unsigned long)pfn_to_kaddr(page_to_pfn(shared_ring)), > + GNTMAP_host_map, gref, sdomain); > + > + ret = gnttab_map_refs(ops, NULL, &shared_ring, 1); > + if (ret < 0) { > + printk("Cannot map ring\n"); > + return -EINVAL; > + } > + > + if (ops[0].status) { > + printk("Ring mapping failed\n"); > + return -EINVAL; > + } > + > + sring = (struct hyper_dmabuf_sring*) pfn_to_kaddr(page_to_pfn(shared_ring)); > + > + BACK_RING_INIT(&ring_info->ring_back, sring, PAGE_SIZE); > + > + ret = bind_interdomain_evtchn_to_irqhandler(sdomain, port, hyper_dmabuf_back_ring_isr, 0, > + NULL, (void*)ring_info); > + if (ret < 0) { > + return -EINVAL; > + } > + > + ring_info->irq = ret; > + > + printk("%s: bound to eventchannel port: %d irq: %d\n", __func__, > + port, > + ring_info->irq); > + > + ret = hyper_dmabuf_register_importer_ring(ring_info); > + > + return ret; > +} > + > +int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req) > +{ > + struct hyper_dmabuf_front_ring *ring; > + struct hyper_dmabuf_ring_rq *new_req; > + struct hyper_dmabuf_ring_info_export *ring_info; > + int notify; > + > + /* find a ring info for the channel */ > + ring_info = hyper_dmabuf_find_exporter_ring(domain); > + if (!ring_info) { > + printk("Can't find ring info for the channel\n"); > + return -EINVAL; > + } > + > + ring = &ring_info->ring_front; > + > + if (RING_FULL(ring)) > + return -EBUSY; > + > + new_req = RING_GET_REQUEST(ring, ring->req_prod_pvt); > + if (!new_req) { > + printk("NULL REQUEST\n"); > + return -EIO; > + } > + > + memcpy(new_req, req, sizeof(*new_req)); > + > + ring->req_prod_pvt++; > + > + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(ring, notify); > + if (notify) { > + notify_remote_via_irq(ring_info->irq); > + } > + > + return 0; > +} > + > +/* called by interrupt (WORKQUEUE) */ > +int hyper_dmabuf_send_response(struct hyper_dmabuf_ring_rp* response, int domain) > +{ > + /* as a importer and as a exporter */ > + return 0; > +} > + > +/* ISR for request from exporter (as an importer) */ > +static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, void *dev_id) > +{ > + RING_IDX rc, rp; > + struct hyper_dmabuf_ring_rq request; > + struct hyper_dmabuf_ring_rp response; > + int notify, more_to_do; > + int ret; > +// struct hyper_dmabuf_work *work; > + > + struct hyper_dmabuf_ring_info_import *ring_info = (struct hyper_dmabuf_ring_info_import *)dev_id; > + struct hyper_dmabuf_back_ring *ring; > + > + ring = &ring_info->ring_back; > + > + do { > + rc = ring->req_cons; > + rp = ring->sring->req_prod; > + > + while (rc != rp) { > + if (RING_REQUEST_CONS_OVERFLOW(ring, rc)) > + break; > + > + memcpy(&request, RING_GET_REQUEST(ring, rc), sizeof(request)); > + printk("Got request\n"); > + ring->req_cons = ++rc; > + > + /* TODO: probably using linked list for multiple requests then let > + * a task in a workqueue to process those is better idea becuase > + * we do not want to stay in ISR for long. > + */ > + ret = hyper_dmabuf_msg_parse(ring_info->sdomain, &request); > + > + if (ret > 0) { > + /* build response */ > + memcpy(&response, &request, sizeof(response)); > + > + /* we sent back modified request as a response.. we might just need to have request only..*/ > + memcpy(RING_GET_RESPONSE(ring, ring->rsp_prod_pvt), &response, sizeof(response)); > + ring->rsp_prod_pvt++; > + > + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(ring, notify); > + > + if (notify) { > + printk("Notyfing\n"); > + notify_remote_via_irq(ring_info->irq); > + } > + } > + > + RING_FINAL_CHECK_FOR_REQUESTS(ring, more_to_do); > + printk("Final check for requests %d\n", more_to_do); > + } > + } while (more_to_do); > + > + return IRQ_HANDLED; > +} > + > +/* ISR for responses from importer */ > +static irqreturn_t hyper_dmabuf_front_ring_isr(int irq, void *dev_id) > +{ > + /* front ring only care about response from back */ > + struct hyper_dmabuf_ring_rp *response; > + RING_IDX i, rp; > + int more_to_do, ret; > + > + struct hyper_dmabuf_ring_info_export *ring_info = (struct hyper_dmabuf_ring_info_export *)dev_id; > + struct hyper_dmabuf_front_ring *ring; > + ring = &ring_info->ring_front; > + > + do { > + more_to_do = 0; > + rp = ring->sring->rsp_prod; > + for (i = ring->rsp_cons; i != rp; i++) { > + unsigned long id; > + > + response = RING_GET_RESPONSE(ring, i); > + id = response->response_id; > + > + if (response->status == HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP) { > + /* parsing response */ > + ret = hyper_dmabuf_msg_parse(ring_info->rdomain, (struct hyper_dmabuf_ring_rq*)response); > + > + if (ret < 0) { > + printk("getting error while parsing response\n"); > + } > + } else if (response->status == HYPER_DMABUF_REQ_ERROR) { > + printk("remote domain %d couldn't process request %d\n", ring_info->rdomain, response->command); > + } > + > + } > + > + ring->rsp_cons = i; > + > + if (i != ring->req_prod_pvt) { > + RING_FINAL_CHECK_FOR_RESPONSES(ring, more_to_do); > + printk("more to do %d\n", more_to_do); > + } else { > + ring->sring->rsp_event = i+1; > + } > + } while (more_to_do); > + > + return IRQ_HANDLED; > +} > diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h > new file mode 100644 > index 0000000..2754917 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h > @@ -0,0 +1,62 @@ > +#ifndef __HYPER_DMABUF_XEN_COMM_H__ > +#define __HYPER_DMABUF_XEN_COMM_H__ > + > +#include "xen/interface/io/ring.h" > + > +#define MAX_NUMBER_OF_OPERANDS 9 > + > +struct hyper_dmabuf_ring_rq { > + unsigned int request_id; > + unsigned int status; > + unsigned int command; > + unsigned int operands[MAX_NUMBER_OF_OPERANDS]; > +}; > + > +struct hyper_dmabuf_ring_rp { > + unsigned int response_id; > + unsigned int status; > + unsigned int command; > + unsigned int operands[MAX_NUMBER_OF_OPERANDS]; > +}; > + > +DEFINE_RING_TYPES(hyper_dmabuf, struct hyper_dmabuf_ring_rq, struct hyper_dmabuf_ring_rp); > + > +struct hyper_dmabuf_ring_info_export { > + struct hyper_dmabuf_front_ring ring_front; > + int rdomain; > + int gref_ring; > + int irq; > + int port; > +}; > + > +struct hyper_dmabuf_ring_info_import { > + int sdomain; > + int irq; > + int evtchn; > + struct hyper_dmabuf_back_ring ring_back; > +}; > + > +//struct hyper_dmabuf_work { > +// hyper_dmabuf_ring_rq requrest; > +// struct work_struct msg_parse; > +//}; > + > +int32_t hyper_dmabuf_get_domid(void); > + > +int hyper_dmabuf_next_req_id_export(void); > + > +int hyper_dmabuf_next_req_id_import(void); > + > +/* exporter needs to generated info for page sharing */ > +int hyper_dmabuf_exporter_ringbuf_init(int rdomain, grant_ref_t *gref, int *port); > + > +/* importer needs to know about shared page and port numbers for ring buffer and event channel */ > +int hyper_dmabuf_importer_ringbuf_init(int sdomain, grant_ref_t gref, int port); > + > +/* send request to the remote domain */ > +int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req); > + > +/* called by interrupt (WORKQUEUE) */ > +int hyper_dmabuf_send_response(struct hyper_dmabuf_ring_rp* response, int domain); > + > +#endif // __HYPER_DMABUF_XEN_COMM_H__ > diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c > new file mode 100644 > index 0000000..15c9d29 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c > @@ -0,0 +1,106 @@ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "hyper_dmabuf_xen_comm.h" > +#include "hyper_dmabuf_xen_comm_list.h" > + > +DECLARE_HASHTABLE(hyper_dmabuf_hash_importer_ring, MAX_ENTRY_IMPORT_RING); > +DECLARE_HASHTABLE(hyper_dmabuf_hash_exporter_ring, MAX_ENTRY_EXPORT_RING); > + > +int hyper_dmabuf_ring_table_init() > +{ > + hash_init(hyper_dmabuf_hash_importer_ring); > + hash_init(hyper_dmabuf_hash_exporter_ring); > + return 0; > +} > + > +int hyper_dmabuf_ring_table_destroy() > +{ > + /* TODO: cleanup tables*/ > + return 0; > +} > + > +int hyper_dmabuf_register_exporter_ring(struct hyper_dmabuf_ring_info_export *ring_info) > +{ > + struct hyper_dmabuf_exporter_ring_info *info_entry; > + > + info_entry = kmalloc(sizeof(*info_entry), GFP_KERNEL); > + > + info_entry->info = ring_info; > + > + hash_add(hyper_dmabuf_hash_exporter_ring, &info_entry->node, > + info_entry->info->rdomain); > + > + return 0; > +} > + > +int hyper_dmabuf_register_importer_ring(struct hyper_dmabuf_ring_info_import *ring_info) > +{ > + struct hyper_dmabuf_importer_ring_info *info_entry; > + > + info_entry = kmalloc(sizeof(*info_entry), GFP_KERNEL); > + > + info_entry->info = ring_info; > + > + hash_add(hyper_dmabuf_hash_importer_ring, &info_entry->node, > + info_entry->info->sdomain); > + > + return 0; > +} > + > +struct hyper_dmabuf_ring_info_export *hyper_dmabuf_find_exporter_ring(int domid) > +{ > + struct hyper_dmabuf_exporter_ring_info *info_entry; > + int bkt; > + > + hash_for_each(hyper_dmabuf_hash_exporter_ring, bkt, info_entry, node) > + if(info_entry->info->rdomain == domid) > + return info_entry->info; > + > + return NULL; > +} > + > +struct hyper_dmabuf_ring_info_import *hyper_dmabuf_find_importer_ring(int domid) > +{ > + struct hyper_dmabuf_importer_ring_info *info_entry; > + int bkt; > + > + hash_for_each(hyper_dmabuf_hash_importer_ring, bkt, info_entry, node) > + if(info_entry->info->sdomain == domid) > + return info_entry->info; > + > + return NULL; > +} > + > +int hyper_dmabuf_remove_exporter_ring(int domid) > +{ > + struct hyper_dmabuf_exporter_ring_info *info_entry; > + int bkt; > + > + hash_for_each(hyper_dmabuf_hash_exporter_ring, bkt, info_entry, node) > + if(info_entry->info->rdomain == domid) { > + hash_del(&info_entry->node); > + return 0; > + } > + > + return -1; > +} > + > +int hyper_dmabuf_remove_importer_ring(int domid) > +{ > + struct hyper_dmabuf_importer_ring_info *info_entry; > + int bkt; > + > + hash_for_each(hyper_dmabuf_hash_importer_ring, bkt, info_entry, node) > + if(info_entry->info->sdomain == domid) { > + hash_del(&info_entry->node); > + return 0; > + } > + > + return -1; > +} > diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h > new file mode 100644 > index 0000000..5929f99 > --- /dev/null > +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h > @@ -0,0 +1,35 @@ > +#ifndef __HYPER_DMABUF_XEN_COMM_LIST_H__ > +#define __HYPER_DMABUF_XEN_COMM_LIST_H__ > + > +/* number of bits to be used for exported dmabufs hash table */ > +#define MAX_ENTRY_EXPORT_RING 7 > +/* number of bits to be used for imported dmabufs hash table */ > +#define MAX_ENTRY_IMPORT_RING 7 > + > +struct hyper_dmabuf_exporter_ring_info { > + struct hyper_dmabuf_ring_info_export *info; > + struct hlist_node node; > +}; > + > +struct hyper_dmabuf_importer_ring_info { > + struct hyper_dmabuf_ring_info_import *info; > + struct hlist_node node; > +}; > + > +int hyper_dmabuf_ring_table_init(void); > + > +int hyper_dmabuf_ring_table_destroy(void); > + > +int hyper_dmabuf_register_exporter_ring(struct hyper_dmabuf_ring_info_export *ring_info); > + > +int hyper_dmabuf_register_importer_ring(struct hyper_dmabuf_ring_info_import *ring_info); > + > +struct hyper_dmabuf_ring_info_export *hyper_dmabuf_find_exporter_ring(int domid); > + > +struct hyper_dmabuf_ring_info_import *hyper_dmabuf_find_importer_ring(int domid); > + > +int hyper_dmabuf_remove_exporter_ring(int domid); > + > +int hyper_dmabuf_remove_importer_ring(int domid); > + > +#endif // __HYPER_DMABUF_XEN_COMM_LIST_H__ > -- > 2.7.4 > > From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dongwon Kim Subject: Re: [RFC PATCH 01/60] hyper_dmabuf: initial working version of hyper_dmabuf drv Date: Wed, 14 Feb 2018 17:34:52 -0800 Message-ID: <20180215013452.GB8672@downor-Z87X-UD5H> References: <1513711816-2618-1-git-send-email-dongwon.kim@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1AA176E07F for ; Thu, 15 Feb 2018 01:36:48 +0000 (UTC) Content-Disposition: inline In-Reply-To: <1513711816-2618-1-git-send-email-dongwon.kim@intel.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: "linux-kernel@vger.kernel.org" Cc: "xen-devel@lists.xenproject.org" , "Potrola, MateuszX" , "dri-devel@lists.freedesktop.org" List-Id: dri-devel@lists.freedesktop.org QWJhbmRvbmluZyB0aGlzIHNlcmllcyBhcyBhIG5ldyB2ZXJzaW9uIHdhcyBzdWJtaXR0ZWQgZm9y IHRoZSByZXZpZXcKCiJbUkZDIFBBVENIIHYyIDAvOV0gaHlwZXJfZG1hYnVmOiBIeXBlcl9ETUFC VUYgZHJpdmVyIgoKT24gVHVlLCBEZWMgMTksIDIwMTcgYXQgMTE6Mjk6MTdBTSAtMDgwMCwgS2lt LCBEb25nd29uIHdyb3RlOgo+IFVwbG9hZCBvZiBpbnRpYWwgdmVyc2lvbiBvZiBoeXBlcl9ETUFC VUYgZHJpdmVyIGVuYWJsaW5nCj4gRE1BX0JVRiBleGNoYW5nZSBiZXR3ZWVuIHR3byBkaWZmZXJl bnQgVk1zIGluIHZpcnR1YWxpemVkCj4gcGxhdGZvcm0gYmFzZWQgb24gaHlwZXJ2aXNvciBzdWNo IGFzIEtWTSBvciBYRU4uCj4gCj4gSHlwZXJfRE1BQlVGIGRydidzIHByaW1hcnkgcm9sZSBpcyB0 byBpbXBvcnQgYSBETUFfQlVGCj4gZnJvbSBvcmlnaW5hdG9yIHRoZW4gcmUtZXhwb3J0IGl0IHRv IGFub3RoZXIgTGludXggVk0KPiBzbyB0aGF0IGl0IGNhbiBiZSBtYXBwZWQgYW5kIGFjY2Vzc2Vk IGJ5IGl0Lgo+IAo+IFRoZSBmdW5jdGlvbmFsaXR5IG9mIHRoaXMgZHJpdmVyIGhpZ2hseSBkZXBl bmRzIG9uCj4gSHlwZXJ2aXNvcidzIG5hdGl2ZSBwYWdlIHNoYXJpbmcgbWVjaGFuaXNtIGFuZCBp bnRlci1WTQo+IGNvbW11bmljYXRpb24gc3VwcG9ydC4KPiAKPiBUaGlzIGRyaXZlciBoYXMgdHdv IGxheWVycywgb25lIGlzIG1haW4gaHlwZXJfRE1BQlVGCj4gZnJhbWV3b3JrIGZvciBzY2F0dGVy LWdhdGhlciBsaXN0IG1hbmFnZW1lbnQgdGhhdCBoYW5kbGVzCj4gYWN0dWFsIGltcG9ydCBhbmQg ZXhwb3J0IG9mIERNQV9CVUYuIExvd2VyIGxheWVyIGlzIGFib3V0Cj4gYWN0dWFsIG1lbW9yeSBz aGFyaW5nIGFuZCBjb21tdW5pY2F0aW9uIGJldHdlZW4gdHdvIFZNcywKPiB3aGljaCBpcyBoeXBl cnZpc29yLXNwZWNpZmljIGludGVyZmFjZS4KPiAKPiBUaGlzIGRyaXZlciBpcyBpbml0aWFsbHkg ZGVzaWduZWQgdG8gZW5hYmxlIERNQV9CVUYKPiBzaGFyaW5nIGFjcm9zcyBWTXMgaW4gWGVuIGVu dmlyb25tZW50LCBzbyBjdXJyZW50bHkgd29ya2luZwo+IHdpdGggWGVuIG9ubHkuCj4gCj4gVGhp cyBhbHNvIGFkZHMgS2VybmVsIGNvbmZpZ3VyYXRpb24gZm9yIGh5cGVyX0RNQUJVRiBkcnYKPiB1 bmRlciBEZXZpY2UgRHJpdmVycy0+WGVuIGRyaXZlciBzdXBwb3J0LT5oeXBlcl9kbWFidWYKPiBv cHRpb25zLgo+IAo+IFRvIGdpdmUgc29tZSBicmllZiBpbmZvcm1hdGlvbiBhYm91dCBlYWNoIHNv dXJjZSBmaWxlLAo+IAo+IGh5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfY29uZi5oCj4gOiBjb25m aWd1cmF0aW9uIGluZm8KPiAKPiBoeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2Rydi5jCj4gOiBk cml2ZXIgaW50ZXJmYWNlIGFuZCBpbml0aWFsaXphdGlvbgo+IAo+IGh5cGVyX2RtYWJ1Zi9oeXBl cl9kbWFidWZfaW1wLmMKPiA6IHNjYXR0ZXItZ2F0aGVyIGxpc3QgZ2VuZXJhdGlvbiBhbmQgbWFu YWdlbWVudC4gRE1BX0JVRgo+IG9wcyBmb3IgRE1BX0JVRiByZWNvbnN0cnVjdGVkIGZyb20gaHlw ZXJfRE1BQlVGCj4gCj4gaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9pb2N0bC5jCj4gOiBJT0NU THMgY2FsbHMgZm9yIGV4cG9ydC9pbXBvcnQgYW5kIGNvbW0gY2hhbm5lbCBjcmVhdGlvbgo+IHVu ZXhwb3J0Lgo+IAo+IGh5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfbGlzdC5jCj4gOiBEYXRhYmFz ZSAobGlua2VkLWxpc3QpIGZvciBleHBvcnRlZCBhbmQgaW1wb3J0ZWQKPiBoeXBlcl9ETUFCVUYK PiAKPiBoeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX21zZy5jCj4gOiBjcmVhdGlvbiBhbmQgbWFu YWdlbWVudCBvZiBtZXNzYWdlcyBiZXR3ZWVuIGV4cG9ydGVyIGFuZAo+IGltcG9ydGVyCj4gCj4g aHlwZXJfZG1hYnVmL3hlbi9oeXBlcl9kbWFidWZfeGVuX2NvbW0uYwo+IDogY29tbSBjaCBtYW5h Z2VtZW50IGFuZCBJU1JzIGZvciBpbmNvbWluZyBtZXNzYWdlcy4KPiAKPiBoeXBlcl9kbWFidWYv eGVuL2h5cGVyX2RtYWJ1Zl94ZW5fY29tbV9saXN0LmMKPiA6IERhdGFiYXNlIChsaW5rZWQtbGlz dCkgZm9yIGtlZXBpbmcgaW5mb3JtYXRpb24gYWJvdXQKPiBleGlzdGluZyBjb21tIGNoYW5uZWxz IGFtb25nIFZNcwo+IAo+IFNpZ25lZC1vZmYtYnk6IERvbmd3b24gS2ltIDxkb25nd29uLmtpbUBp bnRlbC5jb20+Cj4gU2lnbmVkLW9mZi1ieTogTWF0ZXVzeiBQb2xyb2xhIDxtYXRldXN6eC5wb3Ry b2xhQGludGVsLmNvbT4KPiAtLS0KPiAgZHJpdmVycy94ZW4vS2NvbmZpZyAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgfCAgIDIgKwo+ICBkcml2ZXJzL3hlbi9NYWtlZmlsZSAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICB8ICAgMSArCj4gIGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1 Zi9LY29uZmlnICAgICAgICAgICAgICAgICAgIHwgIDE0ICsKPiAgZHJpdmVycy94ZW4vaHlwZXJf ZG1hYnVmL01ha2VmaWxlICAgICAgICAgICAgICAgICAgfCAgMzQgKwo+ICBkcml2ZXJzL3hlbi9o eXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2NvbmYuaCAgICAgICB8ICAgMiArCj4gIGRyaXZlcnMv eGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfZHJ2LmMgICAgICAgIHwgIDU0ICsrCj4gIGRy aXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfZHJ2LmggICAgICAgIHwgMTAxICsr Kwo+ICBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2ltcC5jICAgICAgICB8 IDg1MiArKysrKysrKysrKysrKysrKysrKysKPiAgZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5 cGVyX2RtYWJ1Zl9pbXAuaCAgICAgICAgfCAgMzEgKwo+ICBkcml2ZXJzL3hlbi9oeXBlcl9kbWFi dWYvaHlwZXJfZG1hYnVmX2lvY3RsLmMgICAgICB8IDQ2MiArKysrKysrKysrKwo+ICBkcml2ZXJz L3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2xpc3QuYyAgICAgICB8IDExOSArKysKPiAg ZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9saXN0LmggICAgICAgfCAgNDAg Kwo+ICBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX21zZy5jICAgICAgICB8 IDIxMiArKysrKwo+ICBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX21zZy5o ICAgICAgICB8ICA0NSArKwo+ICBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVm X3F1ZXJ5LmggICAgICB8ICAxNiArCj4gIGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9k bWFidWZfc3RydWN0LmggICAgIHwgIDcwICsrCj4gIC4uLi94ZW4vaHlwZXJfZG1hYnVmL3hlbi9o eXBlcl9kbWFidWZfeGVuX2NvbW0uYyAgIHwgMzI4ICsrKysrKysrCj4gIC4uLi94ZW4vaHlwZXJf ZG1hYnVmL3hlbi9oeXBlcl9kbWFidWZfeGVuX2NvbW0uaCAgIHwgIDYyICsrCj4gIC4uLi9oeXBl cl9kbWFidWYveGVuL2h5cGVyX2RtYWJ1Zl94ZW5fY29tbV9saXN0LmMgIHwgMTA2ICsrKwo+ICAu Li4vaHlwZXJfZG1hYnVmL3hlbi9oeXBlcl9kbWFidWZfeGVuX2NvbW1fbGlzdC5oICB8ICAzNSAr Cj4gIDIwIGZpbGVzIGNoYW5nZWQsIDI1ODYgaW5zZXJ0aW9ucygrKQo+ICBjcmVhdGUgbW9kZSAx MDA2NDQgZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL0tjb25maWcKPiAgY3JlYXRlIG1vZGUgMTAw NjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9NYWtlZmlsZQo+ICBjcmVhdGUgbW9kZSAxMDA2 NDQgZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9jb25mLmgKPiAgY3JlYXRl IG1vZGUgMTAwNjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfZHJ2LmMK PiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFi dWZfZHJ2LmgKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9o eXBlcl9kbWFidWZfaW1wLmMKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMveGVuL2h5cGVy X2RtYWJ1Zi9oeXBlcl9kbWFidWZfaW1wLmgKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMv eGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfaW9jdGwuYwo+ICBjcmVhdGUgbW9kZSAxMDA2 NDQgZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9saXN0LmMKPiAgY3JlYXRl IG1vZGUgMTAwNjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfbGlzdC5o Cj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1h YnVmX21zZy5jCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYv aHlwZXJfZG1hYnVmX21zZy5oCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL3hlbi9oeXBl cl9kbWFidWYvaHlwZXJfZG1hYnVmX3F1ZXJ5LmgKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZl cnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfc3RydWN0LmgKPiAgY3JlYXRlIG1vZGUg MTAwNjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21t LmMKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi94ZW4vaHlw ZXJfZG1hYnVmX3hlbl9jb21tLmgKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMveGVuL2h5 cGVyX2RtYWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tX2xpc3QuYwo+ICBjcmVhdGUgbW9k ZSAxMDA2NDQgZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL3hlbi9oeXBlcl9kbWFidWZfeGVuX2Nv bW1fbGlzdC5oCj4gCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMveGVuL0tjb25maWcgYi9kcml2ZXJz L3hlbi9LY29uZmlnCj4gaW5kZXggZDhkZDU0Ni4uYjU5YjBlMyAxMDA2NDQKPiAtLS0gYS9kcml2 ZXJzL3hlbi9LY29uZmlnCj4gKysrIGIvZHJpdmVycy94ZW4vS2NvbmZpZwo+IEBAIC0zMjEsNCAr MzIxLDYgQEAgY29uZmlnIFhFTl9TWU1TCj4gIGNvbmZpZyBYRU5fSEFWRV9WUE1VCj4gICAgICAg ICBib29sCj4gIAo+ICtzb3VyY2UgImRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9LY29uZmlnIgo+ ICsKPiAgZW5kbWVudQo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3hlbi9NYWtlZmlsZSBiL2RyaXZl cnMveGVuL01ha2VmaWxlCj4gaW5kZXggNDUxZTgzMy4uYTZlMjUzYSAxMDA2NDQKPiAtLS0gYS9k cml2ZXJzL3hlbi9NYWtlZmlsZQo+ICsrKyBiL2RyaXZlcnMveGVuL01ha2VmaWxlCj4gQEAgLTQs NiArNCw3IEBAIG9iai0kKENPTkZJR19YODYpCQkJKz0gZmFsbGJhY2subwo+ICBvYmoteQkrPSBn cmFudC10YWJsZS5vIGZlYXR1cmVzLm8gYmFsbG9vbi5vIG1hbmFnZS5vIHByZWVtcHQubyB0aW1l Lm8KPiAgb2JqLXkJKz0gZXZlbnRzLwo+ICBvYmoteQkrPSB4ZW5idXMvCj4gK29iai15CSs9IGh5 cGVyX2RtYWJ1Zi8KPiAgCj4gIG5vc3RhY2twIDo9ICQoY2FsbCBjYy1vcHRpb24sIC1mbm8tc3Rh Y2stcHJvdGVjdG9yKQo+ICBDRkxBR1NfZmVhdHVyZXMubwkJCTo9ICQobm9zdGFja3ApCj4gZGlm ZiAtLWdpdCBhL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9LY29uZmlnIGIvZHJpdmVycy94ZW4v aHlwZXJfZG1hYnVmL0tjb25maWcKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAw MDAuLjc1ZTFmOTYKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy94ZW4vaHlwZXJfZG1h YnVmL0tjb25maWcKPiBAQCAtMCwwICsxLDE0IEBACj4gK21lbnUgImh5cGVyX2RtYWJ1ZiBvcHRp b25zIgo+ICsKPiArY29uZmlnIEhZUEVSX0RNQUJVRgo+ICsJdHJpc3RhdGUgIkVuYWJsZXMgaHlw ZXIgZG1hYnVmIGRyaXZlciIKPiArCWRlZmF1bHQgeQo+ICsKPiArY29uZmlnIEhZUEVSX0RNQUJV Rl9YRU4KPiArCWJvb2wgIkNvbmZpZ3VyZSBoeXBlcl9kbWFidWYgZm9yIFhFTiBoeXBlcnZpc29y Igo+ICsJZGVmYXVsdCB5Cj4gKwlkZXBlbmRzIG9uIEhZUEVSX0RNQUJVRgo+ICsJaGVscAo+ICsJ ICBDb25maWd1cmluZyBoeXBlcl9kbWFidWYgZHJpdmVyIGZvciBYRU4gaHlwZXJ2aXNvcgo+ICsK PiArZW5kbWVudQo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvTWFrZWZp bGUgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvTWFrZWZpbGUKPiBuZXcgZmlsZSBtb2RlIDEw MDY0NAo+IGluZGV4IDAwMDAwMDAuLjBiZTc0NDUKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJp dmVycy94ZW4vaHlwZXJfZG1hYnVmL01ha2VmaWxlCj4gQEAgLTAsMCArMSwzNCBAQAo+ICtUQVJH RVRfTU9EVUxFOj1oeXBlcl9kbWFidWYKPiArCj4gKyMgSWYgd2UgcnVubmluZyBieSBrZXJuZWwg YnVpbGRpbmcgc3lzdGVtCj4gK2lmbmVxICgkKEtFUk5FTFJFTEVBU0UpLCkKPiArCSQoVEFSR0VU X01PRFVMRSktb2JqcyA6PSBoeXBlcl9kbWFidWZfZHJ2Lm8gXAo+ICsgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICBoeXBlcl9kbWFidWZfaW9jdGwubyBcCj4gKyAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIGh5cGVyX2RtYWJ1Zl9saXN0Lm8gXAo+ICsJCQkJIGh5cGVyX2Rt YWJ1Zl9pbXAubyBcCj4gKwkJCQkgaHlwZXJfZG1hYnVmX21zZy5vIFwKPiArCQkJCSB4ZW4vaHlw ZXJfZG1hYnVmX3hlbl9jb21tLm8gXAo+ICsJCQkJIHhlbi9oeXBlcl9kbWFidWZfeGVuX2NvbW1f bGlzdC5vCj4gKwo+ICtvYmotJChDT05GSUdfSFlQRVJfRE1BQlVGKSA6PSAkKFRBUkdFVF9NT0RV TEUpLm8KPiArCj4gKyMgSWYgd2UgYXJlIHJ1bm5pbmcgd2l0aG91dCBrZXJuZWwgYnVpbGQgc3lz dGVtCj4gK2Vsc2UKPiArQlVJTERTWVNURU1fRElSPz0uLi8uLi8uLi8KPiArUFdEOj0kKHNoZWxs IHB3ZCkKPiArCj4gK2FsbCA6Cj4gKyMgcnVuIGtlcm5lbCBidWlsZCBzeXN0ZW0gdG8gbWFrZSBt b2R1bGUKPiArJChNQUtFKSAtQyAkKEJVSUxEU1lTVEVNX0RJUikgTT0kKFBXRCkgbW9kdWxlcwo+ ICsKPiArY2xlYW46Cj4gKyMgcnVuIGtlcm5lbCBidWlsZCBzeXN0ZW0gdG8gY2xlYW51cCBpbiBj dXJyZW50IGRpcmVjdG9yeQo+ICskKE1BS0UpIC1DICQoQlVJTERTWVNURU1fRElSKSBNPSQoUFdE KSBjbGVhbgo+ICsKPiArbG9hZDoKPiArCWluc21vZCAuLyQoVEFSR0VUX01PRFVMRSkua28KPiAr Cj4gK3VubG9hZDoKPiArCXJtbW9kIC4vJChUQVJHRVRfTU9EVUxFKS5rbwo+ICsKPiArZW5kaWYK PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9jb25m LmggYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2NvbmYuaAo+IG5ldyBm aWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uM2Q5YjJkNgo+IC0tLSAvZGV2L251bGwK PiArKysgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2NvbmYuaAo+IEBA IC0wLDAgKzEsMiBAQAo+ICsjZGVmaW5lIENVUlJFTlRfVEFSR0VUIFhFTgo+ICsjZGVmaW5lIElO VEVSX0RPTUFJTl9ETUFCVUZfU1lOQ0hST05JWkFUSU9OCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMv eGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfZHJ2LmMgYi9kcml2ZXJzL3hlbi9oeXBlcl9k bWFidWYvaHlwZXJfZG1hYnVmX2Rydi5jCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAw MDAwMDAwLi4wNjk4MzI3Cj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMveGVuL2h5cGVy X2RtYWJ1Zi9oeXBlcl9kbWFidWZfZHJ2LmMKPiBAQCAtMCwwICsxLDU0IEBACj4gKyNpbmNsdWRl IDxsaW51eC9pbml0Lmg+ICAgICAgIC8qIG1vZHVsZV9pbml0LCBtb2R1bGVfZXhpdCAqLwo+ICsj aW5jbHVkZSA8bGludXgvbW9kdWxlLmg+IC8qIHZlcnNpb24gaW5mbywgTU9EVUxFX0xJQ0VOU0Us IE1PRFVMRV9BVVRIT1IsIHByaW50aygpICovCj4gKyNpbmNsdWRlICJoeXBlcl9kbWFidWZfY29u Zi5oIgo+ICsjaW5jbHVkZSAiaHlwZXJfZG1hYnVmX2xpc3QuaCIKPiArI2luY2x1ZGUgInhlbi9o eXBlcl9kbWFidWZfeGVuX2NvbW1fbGlzdC5oIgo+ICsKPiArTU9EVUxFX0xJQ0VOU0UoIkR1YWwg QlNEL0dQTCIpOwo+ICtNT0RVTEVfQVVUSE9SKCJJT1RHLVBFRCwgSU5URUwiKTsKPiArCj4gK2lu dCByZWdpc3Rlcl9kZXZpY2Uodm9pZCk7Cj4gK2ludCB1bnJlZ2lzdGVyX2RldmljZSh2b2lkKTsK PiArCj4gKy8qPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qLwo+ICtzdGF0 aWMgaW50IGh5cGVyX2RtYWJ1Zl9kcnZfaW5pdCh2b2lkKQo+ICt7Cj4gKwlpbnQgcmV0ID0gMDsK PiArCj4gKwlwcmludGsoIEtFUk5fTk9USUNFICJoeXBlcl9kbWFidWZfc3RhcnRpbmc6IEluaXRp YWxpemF0aW9uIHN0YXJ0ZWQiICk7Cj4gKwo+ICsJcmV0ID0gcmVnaXN0ZXJfZGV2aWNlKCk7Cj4g KwlpZiAocmV0IDwgMCkgewo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXByaW50 ayggS0VSTl9OT1RJQ0UgImluaXRpYWxpemluZyBkYXRhYmFzZSBmb3IgaW1wb3J0ZWQvZXhwb3J0 ZWQgZG1hYnVmc1xuIik7Cj4gKwo+ICsJcmV0ID0gaHlwZXJfZG1hYnVmX3RhYmxlX2luaXQoKTsK PiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJcmV0 ID0gaHlwZXJfZG1hYnVmX3JpbmdfdGFibGVfaW5pdCgpOwo+ICsJaWYgKHJldCA8IDApIHsKPiAr CQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwkvKiBpbnRlcnJ1cHQgZm9yIGNvbW0gc2hv dWxkIGJlIHJlZ2lzdGVyZWQgaGVyZTogKi8KPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gKy8q LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwo+ICtzdGF0aWMgdm9pZCBo eXBlcl9kbWFidWZfZHJ2X2V4aXQodm9pZCkKPiArewo+ICsJLyogaGFzaCB0YWJsZXMgZm9yIGV4 cG9ydC9pbXBvcnQgZW50cmllcyBhbmQgcmluZ19pbmZvcyAqLwo+ICsJaHlwZXJfZG1hYnVmX3Rh YmxlX2Rlc3Ryb3koKTsKPiArCWh5cGVyX2RtYWJ1Zl9yaW5nX3RhYmxlX2luaXQoKTsKPiArCj4g KwlwcmludGsoIEtFUk5fTk9USUNFICJkbWFfYnVmLXNyY19zaW5rIG1vZGVsOiBFeGl0aW5nIiAp Owo+ICsJdW5yZWdpc3Rlcl9kZXZpY2UoKTsKPiArfQo+ICsvKj09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09Ki8KPiArCj4gK21vZHVsZV9pbml0KGh5cGVyX2RtYWJ1Zl9kcnZf aW5pdCk7Cj4gK21vZHVsZV9leGl0KGh5cGVyX2RtYWJ1Zl9kcnZfZXhpdCk7Cj4gZGlmZiAtLWdp dCBhL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfZHJ2LmggYi9kcml2ZXJz L3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2Rydi5oCj4gbmV3IGZpbGUgbW9kZSAxMDA2 NDQKPiBpbmRleCAwMDAwMDAwLi4yZGFkOWE2Cj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZl cnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfZHJ2LmgKPiBAQCAtMCwwICsxLDEwMSBA QAo+ICsjaWZuZGVmIF9fTElOVVhfUFVCTElDX0hZUEVSX0RNQUJVRl9EUlZfSF9fCj4gKyNkZWZp bmUgX19MSU5VWF9QVUJMSUNfSFlQRVJfRE1BQlVGX0RSVl9IX18KPiArCj4gK3R5cGVkZWYgaW50 ICgqaHlwZXJfZG1hYnVmX2lvY3RsX3QpKHZvaWQgKmRhdGEpOwo+ICsKPiArc3RydWN0IGh5cGVy X2RtYWJ1Zl9pb2N0bF9kZXNjIHsKPiArCXVuc2lnbmVkIGludCBjbWQ7Cj4gKwlpbnQgZmxhZ3M7 Cj4gKwloeXBlcl9kbWFidWZfaW9jdGxfdCBmdW5jOwo+ICsJY29uc3QgY2hhciAqbmFtZTsKPiAr fTsKPiArCj4gKyNkZWZpbmUgSFlQRVJfRE1BQlVGX0lPQ1RMX0RFRihpb2N0bCwgX2Z1bmMsIF9m bGFncykgCVwKPiArCVtfSU9DX05SKGlvY3RsKV0gPSB7CQkJCVwKPiArCQkJLmNtZCA9IGlvY3Rs LAkJCVwKPiArCQkJLmZ1bmMgPSBfZnVuYywJCQlcCj4gKwkJCS5mbGFncyA9IF9mbGFncywJCVwK PiArCQkJLm5hbWUgPSAjaW9jdGwJCQlcCj4gKwl9Cj4gKwo+ICsjZGVmaW5lIElPQ1RMX0hZUEVS X0RNQUJVRl9FWFBPUlRFUl9SSU5HX1NFVFVQIFwKPiArX0lPQyhfSU9DX05PTkUsICdHJywgMCwg c2l6ZW9mKHN0cnVjdCBpb2N0bF9oeXBlcl9kbWFidWZfZXhwb3J0ZXJfcmluZ19zZXR1cCkpCj4g K3N0cnVjdCBpb2N0bF9oeXBlcl9kbWFidWZfZXhwb3J0ZXJfcmluZ19zZXR1cCB7Cj4gKwkvKiBJ TiBwYXJhbWV0ZXJzICovCj4gKwkvKiBSZW1vdGUgZG9tYWluIGlkICovCj4gKwl1aW50MzJfdCBy ZW1vdGVfZG9tYWluOwo+ICsJZ3JhbnRfcmVmX3QgcmluZ19yZWZpZDsgLyogYXNzaWduZWQgYnkg ZHJpdmVyLCBjb3BpZWQgdG8gdXNlcnNwYWNlIGFmdGVyIGluaXRpYWxpemF0aW9uICovCj4gKwl1 aW50MzJfdCBwb3J0OyAvKiBhc3NpZ25lZCBieSBkcml2ZXIsIGNvcGllZCB0byB1c2Vyc3BhY2Ug YWZ0ZXIgaW5pdGlhbGl6YXRpb24gKi8KPiArfTsKPiArCj4gKyNkZWZpbmUgSU9DVExfSFlQRVJf RE1BQlVGX0lNUE9SVEVSX1JJTkdfU0VUVVAgXAo+ICtfSU9DKF9JT0NfTk9ORSwgJ0cnLCAxLCBz aXplb2Yoc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9pbXBvcnRlcl9yaW5nX3NldHVwKSkKPiAr c3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9pbXBvcnRlcl9yaW5nX3NldHVwIHsKPiArCS8qIElO IHBhcmFtZXRlcnMgKi8KPiArCS8qIFNvdXJjZSBkb21haW4gaWQgKi8KPiArCXVpbnQzMl90IHNv dXJjZV9kb21haW47Cj4gKwkvKiBSaW5nIHNoYXJlZCBwYWdlIHJlZmlkICovCj4gKwlncmFudF9y ZWZfdCByaW5nX3JlZmlkOwo+ICsJLyogUG9ydCBudW1iZXIgKi8KPiArCXVpbnQzMl90IHBvcnQ7 Cj4gK307Cj4gKwo+ICsjZGVmaW5lIElPQ1RMX0hZUEVSX0RNQUJVRl9FWFBPUlRfUkVNT1RFIFwK PiArX0lPQyhfSU9DX05PTkUsICdHJywgMiwgc2l6ZW9mKHN0cnVjdCBpb2N0bF9oeXBlcl9kbWFi dWZfZXhwb3J0X3JlbW90ZSkpCj4gK3N0cnVjdCBpb2N0bF9oeXBlcl9kbWFidWZfZXhwb3J0X3Jl bW90ZSB7Cj4gKwkvKiBJTiBwYXJhbWV0ZXJzICovCj4gKwkvKiBETUEgYnVmIGZkIHRvIGJlIGV4 cG9ydGVkICovCj4gKwl1aW50MzJfdCBkbWFidWZfZmQ7Cj4gKwkvKiBEb21haW4gaWQgdG8gd2hp Y2ggYnVmZmVyIHNob3VsZCBiZSBleHBvcnRlZCAqLwo+ICsJdWludDMyX3QgcmVtb3RlX2RvbWFp bjsKPiArCS8qIGV4cG9ydGVkIGRtYSBidWYgaWQgKi8KPiArCXVpbnQzMl90IGh5cGVyX2RtYWJ1 Zl9pZDsKPiArCXVpbnQzMl90IHByaXZhdGVbNF07Cj4gK307Cj4gKwo+ICsjZGVmaW5lIElPQ1RM X0hZUEVSX0RNQUJVRl9FWFBPUlRfRkQgXAo+ICtfSU9DKF9JT0NfTk9ORSwgJ0cnLCAzLCBzaXpl b2Yoc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9leHBvcnRfZmQpKQo+ICtzdHJ1Y3QgaW9jdGxf aHlwZXJfZG1hYnVmX2V4cG9ydF9mZCB7Cj4gKwkvKiBJTiBwYXJhbWV0ZXJzICovCj4gKwkvKiBo eXBlciBkbWFidWYgaWQgdG8gYmUgaW1wb3J0ZWQgKi8KPiArCXVpbnQzMl90IGh5cGVyX2RtYWJ1 Zl9pZDsKPiArCS8qIGZsYWdzICovCj4gKwl1aW50MzJfdCBmbGFnczsKPiArCS8qIE9VVCBwYXJh bWV0ZXJzICovCj4gKwkvKiBleHBvcnRlZCBkbWEgYnVmIGZkICovCj4gKwl1aW50MzJfdCBmZDsK PiArfTsKPiArCj4gKyNkZWZpbmUgSU9DVExfSFlQRVJfRE1BQlVGX0RFU1RST1kgXAo+ICtfSU9D KF9JT0NfTk9ORSwgJ0cnLCA0LCBzaXplb2Yoc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9kZXN0 cm95KSkKPiArc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9kZXN0cm95IHsKPiArCS8qIElOIHBh cmFtZXRlcnMgKi8KPiArCS8qIGh5cGVyIGRtYWJ1ZiBpZCB0byBiZSBkZXN0cm95ZWQgKi8KPiAr CXVpbnQzMl90IGh5cGVyX2RtYWJ1Zl9pZDsKPiArCS8qIE9VVCBwYXJhbWV0ZXJzICovCj4gKwkv KiBTdGF0dXMgb2YgcmVxdWVzdCAqLwo+ICsJdWludDMyX3Qgc3RhdHVzOwo+ICt9Owo+ICsKPiAr I2RlZmluZSBJT0NUTF9IWVBFUl9ETUFCVUZfUVVFUlkgXAo+ICtfSU9DKF9JT0NfTk9ORSwgJ0cn LCA1LCBzaXplb2Yoc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9xdWVyeSkpCj4gK3N0cnVjdCBp b2N0bF9oeXBlcl9kbWFidWZfcXVlcnkgewo+ICsJLyogaW4gcGFyYW1ldGVycyAqLwo+ICsJLyog aHlwZXIgZG1hYnVmIGlkIHRvIGJlIHF1ZXJpZWQgKi8KPiArCXVpbnQzMl90IGh5cGVyX2RtYWJ1 Zl9pZDsKPiArCS8qIGl0ZW0gdG8gYmUgcXVlcmllZCAqLwo+ICsJdWludDMyX3QgaXRlbTsKPiAr CS8qIE9VVCBwYXJhbWV0ZXJzICovCj4gKwkvKiBWYWx1ZSBvZiBxdWVyaWVkIGl0ZW0gKi8KPiAr CXVpbnQzMl90IGluZm87Cj4gK307Cj4gKwo+ICsjZGVmaW5lIElPQ1RMX0hZUEVSX0RNQUJVRl9S RU1PVEVfRVhQT1JURVJfUklOR19TRVRVUCBcCj4gK19JT0MoX0lPQ19OT05FLCAnRycsIDYsIHNp emVvZihzdHJ1Y3QgaW9jdGxfaHlwZXJfZG1hYnVmX3JlbW90ZV9leHBvcnRlcl9yaW5nX3NldHVw KSkKPiArc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9yZW1vdGVfZXhwb3J0ZXJfcmluZ19zZXR1 cCB7Cj4gKwkvKiBpbiBwYXJhbWV0ZXJzICovCj4gKwl1aW50MzJfdCByZG9tYWluOyAvKiBpZCBv ZiByZW1vdGUgZG9tYWluIHdoZXJlIGV4cG9ydGVyJ3MgcmluZyBuZWVkIHRvIGJlIHNldHVwICov Cj4gKwl1aW50MzJfdCBpbmZvOwo+ICt9Owo+ICsKPiArI2VuZGlmIC8vX19MSU5VWF9QVUJMSUNf SFlQRVJfRE1BQlVGX0RSVl9IX18KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy94ZW4vaHlwZXJfZG1h YnVmL2h5cGVyX2RtYWJ1Zl9pbXAuYyBiL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9k bWFidWZfaW1wLmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLmZhYTVj MWIKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVy X2RtYWJ1Zl9pbXAuYwo+IEBAIC0wLDAgKzEsODUyIEBACj4gKyNpbmNsdWRlIDxsaW51eC9rZXJu ZWwuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2Vycm5vLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zbGFi Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2RtYS1i dWYuaD4KPiArI2luY2x1ZGUgPHhlbi9ncmFudF90YWJsZS5oPgo+ICsjaW5jbHVkZSA8YXNtL3hl bi9wYWdlLmg+Cj4gKyNpbmNsdWRlICJoeXBlcl9kbWFidWZfc3RydWN0LmgiCj4gKyNpbmNsdWRl ICJoeXBlcl9kbWFidWZfaW1wLmgiCj4gKyNpbmNsdWRlICJ4ZW4vaHlwZXJfZG1hYnVmX3hlbl9j b21tLmgiCj4gKyNpbmNsdWRlICJoeXBlcl9kbWFidWZfbXNnLmgiCj4gKwo+ICsjZGVmaW5lIFJF RlNfUEVSX1BBR0UgKFBBR0VfU0laRS9zaXplb2YoZ3JhbnRfcmVmX3QpKQo+ICsKPiArLyogcmV0 dXJuIHRvdGFsIG51bWJlciBvZiBwYWdlcyByZWZlcmVjbmVkIGJ5IGEgc2d0Cj4gKyAqIGZvciBw cmUtY2FsY3VsYXRpb24gb2YgIyBvZiBwYWdlcyBiZWhpbmQgYSBnaXZlbiBzZ3QKPiArICovCj4g K3N0YXRpYyBpbnQgaHlwZXJfZG1hYnVmX2dldF9udW1fcGdzKHN0cnVjdCBzZ190YWJsZSAqc2d0 KQo+ICt7Cj4gKwlzdHJ1Y3Qgc2NhdHRlcmxpc3QgKnNnbDsKPiArCWludCBsZW5ndGgsIGk7Cj4g KwkvKiBhdCBsZWFzdCBvbmUgcGFnZSAqLwo+ICsJaW50IG51bV9wYWdlcyA9IDE7Cj4gKwo+ICsJ c2dsID0gc2d0LT5zZ2w7Cj4gKwo+ICsJbGVuZ3RoID0gc2dsLT5sZW5ndGggLSBQQUdFX1NJWkUg KyBzZ2wtPm9mZnNldDsKPiArCW51bV9wYWdlcyArPSAoKGxlbmd0aCArIFBBR0VfU0laRSAtIDEp L1BBR0VfU0laRSk7IC8qIHJvdW5kLXVwICovCj4gKwo+ICsJZm9yIChpID0gMTsgaSA8IHNndC0+ bmVudHM7IGkrKykgewo+ICsJCXNnbCA9IHNnX25leHQoc2dsKTsKPiArCQludW1fcGFnZXMgKz0g KChzZ2wtPmxlbmd0aCArIFBBR0VfU0laRSAtIDEpIC8gUEFHRV9TSVpFKTsgLyogcm91bmQtdXAg Ki8KPiArCX0KPiArCj4gKwlyZXR1cm4gbnVtX3BhZ2VzOwo+ICt9Cj4gKwo+ICsvKiBleHRyYWN0 IHBhZ2VzIGRpcmVjdGx5IGZyb20gc3RydWN0IHNnX3RhYmxlICovCj4gK3N0cnVjdCBoeXBlcl9k bWFidWZfcGFnZXNfaW5mbyAqaHlwZXJfZG1hYnVmX2V4dF9wZ3Moc3RydWN0IHNnX3RhYmxlICpz Z3QpCj4gK3sKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZfcGFnZXNfaW5mbyAqcGluZm87Cj4gKwlp bnQgaSwgajsKPiArCWludCBsZW5ndGg7Cj4gKwlzdHJ1Y3Qgc2NhdHRlcmxpc3QgKnNnbDsKPiAr Cj4gKwlwaW5mbyA9IGttYWxsb2Moc2l6ZW9mKCpwaW5mbyksIEdGUF9LRVJORUwpOwo+ICsJaWYg KHBpbmZvID09IE5VTEwpCj4gKwkJcmV0dXJuIE5VTEw7Cj4gKwo+ICsJcGluZm8tPnBhZ2VzID0g a21hbGxvYyhzaXplb2Yoc3RydWN0IHBhZ2UgKikqaHlwZXJfZG1hYnVmX2dldF9udW1fcGdzKHNn dCksIEdGUF9LRVJORUwpOwo+ICsJaWYgKHBpbmZvLT5wYWdlcyA9PSBOVUxMKQo+ICsJCXJldHVy biBOVUxMOwo+ICsKPiArCXNnbCA9IHNndC0+c2dsOwo+ICsKPiArCXBpbmZvLT5uZW50cyA9IDE7 Cj4gKwlwaW5mby0+ZnJzdF9vZnN0ID0gc2dsLT5vZmZzZXQ7Cj4gKwlwaW5mby0+cGFnZXNbMF0g PSBzZ19wYWdlKHNnbCk7Cj4gKwlsZW5ndGggPSBzZ2wtPmxlbmd0aCAtIFBBR0VfU0laRSArIHNn bC0+b2Zmc2V0Owo+ICsJaT0xOwo+ICsKPiArCXdoaWxlIChsZW5ndGggPiAwKSB7Cj4gKwkJcGlu Zm8tPnBhZ2VzW2ldID0gbnRoX3BhZ2Uoc2dfcGFnZShzZ2wpLCBpKTsKPiArCQlsZW5ndGggLT0g UEFHRV9TSVpFOwo+ICsJCXBpbmZvLT5uZW50cysrOwo+ICsJCWkrKzsKPiArCX0KPiArCj4gKwlm b3IgKGogPSAxOyBqIDwgc2d0LT5uZW50czsgaisrKSB7Cj4gKwkJc2dsID0gc2dfbmV4dChzZ2wp Owo+ICsJCXBpbmZvLT5wYWdlc1tpKytdID0gc2dfcGFnZShzZ2wpOwo+ICsJCWxlbmd0aCA9IHNn bC0+bGVuZ3RoIC0gUEFHRV9TSVpFOwo+ICsJCXBpbmZvLT5uZW50cysrOwo+ICsKPiArCQl3aGls ZSAobGVuZ3RoID4gMCkgewo+ICsJCQlwaW5mby0+cGFnZXNbaV0gPSBudGhfcGFnZShzZ19wYWdl KHNnbCksIGkpOwo+ICsJCQlsZW5ndGggLT0gUEFHRV9TSVpFOwo+ICsJCQlwaW5mby0+bmVudHMr KzsKPiArCQkJaSsrOwo+ICsJCX0KPiArCX0KPiArCj4gKwkvKgo+ICsJICogbGVuZ2h0IGF0IHRo YXQgcG9pbnQgd2lsbCBiZSAwIG9yIG5lZ2F0aXZlLAo+ICsJICogc28gdG8gY2FsY3VsYXRlIGxh c3QgcGFnZSBzaXplIGp1c3QgYWRkIGl0IHRvIFBBR0VfU0laRQo+ICsJICovCj4gKwlwaW5mby0+ bGFzdF9sZW4gPSBQQUdFX1NJWkUgKyBsZW5ndGg7Cj4gKwo+ICsJcmV0dXJuIHBpbmZvOwo+ICt9 Cj4gKwo+ICsvKiBjcmVhdGUgc2dfdGFibGUgd2l0aCBnaXZlbiBwYWdlcyBhbmQgb3RoZXIgcGFy YW1ldGVycyAqLwo+ICtzdHJ1Y3Qgc2dfdGFibGUqIGh5cGVyX2RtYWJ1Zl9jcmVhdGVfc2d0KHN0 cnVjdCBwYWdlICoqcGFnZXMsCj4gKwkJCQlpbnQgZnJzdF9vZnN0LCBpbnQgbGFzdF9sZW4sIGlu dCBuZW50cykKPiArewo+ICsJc3RydWN0IHNnX3RhYmxlICpzZ3Q7Cj4gKwlzdHJ1Y3Qgc2NhdHRl cmxpc3QgKnNnbDsKPiArCWludCBpLCByZXQ7Cj4gKwo+ICsJc2d0ID0ga21hbGxvYyhzaXplb2Yo c3RydWN0IHNnX3RhYmxlKSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoc2d0ID09IE5VTEwpIHsKPiAr CQlyZXR1cm4gTlVMTDsKPiArCX0KPiArCj4gKwlyZXQgPSBzZ19hbGxvY190YWJsZShzZ3QsIG5l bnRzLCBHRlBfS0VSTkVMKTsKPiArCWlmIChyZXQpIHsKPiArCQlrZnJlZShzZ3QpOwo+ICsJCXJl dHVybiBOVUxMOwo+ICsJfQo+ICsKPiArCXNnbCA9IHNndC0+c2dsOwo+ICsKPiArCXNnX3NldF9w YWdlKHNnbCwgcGFnZXNbMF0sIFBBR0VfU0laRS1mcnN0X29mc3QsIGZyc3Rfb2ZzdCk7Cj4gKwo+ ICsJZm9yIChpPTE7IGk8bmVudHMtMTsgaSsrKSB7Cj4gKwkJc2dsID0gc2dfbmV4dChzZ2wpOwo+ ICsJCXNnX3NldF9wYWdlKHNnbCwgcGFnZXNbaV0sIFBBR0VfU0laRSwgMCk7Cj4gKwl9Cj4gKwo+ ICsJaWYgKGkgPiAxKSAvKiBtb3JlIHRoYW4gb25lIHBhZ2UgKi8gewo+ICsJCXNnbCA9IHNnX25l eHQoc2dsKTsKPiArCQlzZ19zZXRfcGFnZShzZ2wsIHBhZ2VzW2ldLCBsYXN0X2xlbiwgMCk7Cj4g Kwl9Cj4gKwo+ICsJcmV0dXJuIHNndDsKPiArfQo+ICsKPiArLyoKPiArICogQ3JlYXRlcyAyIGxl dmVsIHBhZ2UgZGlyZWN0b3J5IHN0cnVjdHVyZSBmb3IgcmVmZXJlbmNpbmcgc2hhcmVkIHBhZ2Vz Lgo+ICsgKiBUb3AgbGV2ZWwgcGFnZSBpcyBhIHNpbmdsZSBwYWdlIHRoYXQgY29udGFpbnMgdXAg dG8gMTAyNCByZWZpZHMgdGhhdAo+ICsgKiBwb2ludCB0byAybmQgbGV2ZWwgcGFnZXMuCj4gKyAq IEVhY2ggMm5kIGxldmVsIHBhZ2UgY29udGFpbnMgdXAgdG8gMTAyNCByZWZpZHMgdGhhdCBwb2lu dCB0byBzaGFyZWQKPiArICogZGF0YSBwYWdlcy4KPiArICogVGhlcmUgd2lsbCBhbHdheXMgYmUg b25lIHRvcCBsZXZlbCBwYWdlIGFuZCBudW1iZXIgb2YgMm5kIGxldmVsIHBhZ2VzCj4gKyAqIGRl cGVuZHMgb24gbnVtYmVyIG9mIHNoYXJlZCBkYXRhIHBhZ2VzLgo+ICsgKgo+ICsgKiAgICAgIFRv cCBsZXZlbCBwYWdlICAgICAgICAgICAgICAgIDJuZCBsZXZlbCBwYWdlcyAgICAgICAgICAgIERh dGEgcGFnZXMKPiArICogKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rICAg4pSMPistLS0tLS0t LS0tLS0tLS0tLS0tLSsg4pSMLS0tPistLS0tLS0tLS0tLS0rCj4gKyAqIHwybmQgbGV2ZWwgcGFn ZSAwIHJlZmlkICAgfC0tLeKUmCB8RGF0YSBwYWdlIDAgcmVmaWQgICB8LeKUmCAgICB8RGF0YSBw YWdlIDAgfAo+ICsgKiB8Mm5kIGxldmVsIHBhZ2UgMSByZWZpZCAgIHwtLS3ilJAgfERhdGEgcGFn ZSAxIHJlZmlkICAgfC3ilJAgICAgKy0tLS0tLS0tLS0tLSsKPiArICogfCAgICAgICAgICAgLi4u ICAgICAgICAgICB8ICAgfCB8ICAgICAuLi4uICAgICAgICAgICB8IHwKPiArICogfDJuZCBsZXZl bCBwYWdlIDEwMjMgcmVmaWR8LeKUkCB8IHxEYXRhIHBhZ2UgMTAyMyByZWZpZHwg4pSULS0tPist LS0tLS0tLS0tLS0rCj4gKyAqICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKyB8IHwgKy0tLS0t LS0tLS0tLS0tLS0tLS0tKyAgICAgIHxEYXRhIHBhZ2UgMSB8Cj4gKyAqICAgICAgICAgICAgICAg ICAgICAgICAgICAgICB8IHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICstLS0tLS0tLS0t LS0rCj4gKyAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IOKUlD4rLS0tLS0tLS0tLS0t LS0tLS0tLS0rCj4gKyAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgfERhdGEgcGFn ZSAxMDI0IHJlZmlkfAo+ICsgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIHxEYXRh IHBhZ2UgMTAyNSByZWZpZHwKPiArICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICB8 ICAgICAgIC4uLiAgICAgICAgICB8Cj4gKyAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8 ICAgfERhdGEgcGFnZSAyMDQ3IHJlZmlkfAo+ICsgKiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgfCAgICstLS0tLS0tLS0tLS0tLS0tLS0tLSsKPiArICogICAgICAgICAgICAgICAgICAgICAg ICAgICAgIHwKPiArICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIC4uLi4u Cj4gKyAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilJQtLT4rLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0rCj4gKyAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfERhdGEgcGFn ZSAxMDQ3NTUyIHJlZmlkfAo+ICsgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHxE YXRhIHBhZ2UgMTA0NzU1MyByZWZpZHwKPiArICogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICB8ICAgICAgIC4uLiAgICAgICAgICAgICB8Cj4gKyAqICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgfERhdGEgcGFnZSAxMDQ4NTc1IHJlZmlkfC0tPistLS0tLS0tLS0tLS0tLS0t LS0rCj4gKyAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKy0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tKyAgIHxEYXRhIHBhZ2UgMTA0ODU3NSB8Cj4gKyAqICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICstLS0tLS0tLS0tLS0t LS0tLS0rCj4gKyAqCj4gKyAqIFVzaW5nIHN1Y2ggMiBsZXZlbCBzdHJ1Y3R1cmUgaXQgaXMgcG9z c2libGUgdG8gcmVmZXJlbmNlIHVwIHRvIDRHQiBvZgo+ICsgKiBzaGFyZWQgZGF0YSB1c2luZyBz aW5nbGUgcmVmaWQgcG9pbnRpbmcgdG8gdG9wIGxldmVsIHBhZ2UuCj4gKyAqCj4gKyAqIFJldHVy bnMgcmVmaWQgb2YgdG9wIGxldmVsIHBhZ2UuCj4gKyAqLwo+ICtncmFudF9yZWZfdCBoeXBlcl9k bWFidWZfY3JlYXRlX2FkZHJlc3NpbmdfdGFibGVzKGdyYW50X3JlZl90ICpkYXRhX3JlZnMsIGlu dCBuZW50cywgaW50IHJkb21haW4sCj4gKwkJCQkJCSAgc3RydWN0IGh5cGVyX2RtYWJ1Zl9zaGFy ZWRfcGFnZXNfaW5mbyAqc2hhcmVkX3BhZ2VzX2luZm8pCj4gK3sKPiArCS8qCj4gKwkgKiBDYWxj dWxhdGUgbnVtYmVyIG9mIHBhZ2VzIG5lZWRlZCBmb3IgMm5kIGxldmVsIGFkZHJlc2luZzoKPiAr CSAqLwo+ICsJaW50IG5fMm5kX2xldmVsX3BhZ2VzID0gKG5lbnRzL1JFRlNfUEVSX1BBR0UgKyAo KG5lbnRzICUgUkVGU19QRVJfUEFHRSkgPyAxOiAwKSk7Lyogcm91bmRpbmcgKi8KPiArCWludCBp Owo+ICsJdW5zaWduZWQgbG9uZyBncmVmX3BhZ2Vfc3RhcnQ7Cj4gKwlncmFudF9yZWZfdCAqdG1w X3BhZ2U7Cj4gKwlncmFudF9yZWZfdCB0b3BfbGV2ZWxfcmVmOwo+ICsJZ3JhbnRfcmVmX3QgKiBh ZGRyX3JlZnM7Cj4gKwlhZGRyX3JlZnMgPSBrY2FsbG9jKHNpemVvZihncmFudF9yZWZfdCksIG5f Mm5kX2xldmVsX3BhZ2VzLCBHRlBfS0VSTkVMKTsKPiArCj4gKwlncmVmX3BhZ2Vfc3RhcnQgPSBf X2dldF9mcmVlX3BhZ2VzKEdGUF9LRVJORUwsIG5fMm5kX2xldmVsX3BhZ2VzKTsKPiArCXRtcF9w YWdlID0gKGdyYW50X3JlZl90ICopZ3JlZl9wYWdlX3N0YXJ0Owo+ICsKPiArCS8qIFN0b3JlIDJu ZCBsZXZlbCBwYWdlcyB0byBiZSBmcmVlZCBsYXRlciAqLwo+ICsJc2hhcmVkX3BhZ2VzX2luZm8t PmFkZHJfcGFnZXMgPSB0bXBfcGFnZTsKPiArCj4gKwkvKlRPRE86IG1ha2Ugc3VyZSB0aGF0IGFs bG9jYXRlZCBtZW1vcnkgaXMgZmlsbGVkIHdpdGggMCovCj4gKwo+ICsJLyogU2hhcmUgMm5kIGxl dmVsIGFkZHJlc3NpbmcgcGFnZXMgaW4gcmVhZG9ubHkgbW9kZSovCj4gKwlmb3IgKGk9MDsgaTwg bl8ybmRfbGV2ZWxfcGFnZXM7IGkrKykgewo+ICsJCWFkZHJfcmVmc1tpXSA9IGdudHRhYl9ncmFu dF9mb3JlaWduX2FjY2VzcyhyZG9tYWluLCB2aXJ0X3RvX21mbigodW5zaWduZWQgbG9uZyl0bXBf cGFnZStpKlBBR0VfU0laRSApLCAxKTsKPiArCX0KPiArCj4gKwkvKgo+ICsJICogZmlsbCBzZWNv bmQgbGV2ZWwgcGFnZXMgd2l0aCBkYXRhIHJlZnMKPiArCSAqLwo+ICsJZm9yIChpID0gMDsgaSA8 IG5lbnRzOyBpKyspIHsKPiArCQl0bXBfcGFnZVtpXSA9IGRhdGFfcmVmc1tpXTsKPiArCX0KPiAr Cj4gKwo+ICsJLyogYWxsb2NhdGUgdG9wIGxldmVsIHBhZ2UgKi8KPiArCWdyZWZfcGFnZV9zdGFy dCA9IF9fZ2V0X2ZyZWVfcGFnZXMoR0ZQX0tFUk5FTCwgMSk7Cj4gKwl0bXBfcGFnZSA9IChncmFu dF9yZWZfdCAqKWdyZWZfcGFnZV9zdGFydDsKPiArCj4gKwkvKiBTdG9yZSB0b3AgbGV2ZWwgcGFn ZSB0byBiZSBmcmVlZCBsYXRlciAqLwo+ICsJc2hhcmVkX3BhZ2VzX2luZm8tPnRvcF9sZXZlbF9w YWdlID0gdG1wX3BhZ2U7Cj4gKwo+ICsJLyoKPiArCSAqIGZpbGwgdG9wIGxldmVsIHBhZ2Ugd2l0 aCByZWZlcmVuY2UgbnVtYmVycyBvZiBzZWNvbmQgbGV2ZWwgcGFnZXMgcmVmcy4KPiArCSAqLwo+ ICsJZm9yIChpPTA7IGk8IG5fMm5kX2xldmVsX3BhZ2VzOyBpKyspIHsKPiArCQl0bXBfcGFnZVtp XSA9ICBhZGRyX3JlZnNbaV07Cj4gKwl9Cj4gKwo+ICsJLyogU2hhcmUgdG9wIGxldmVsIGFkZHJl c3NpbmcgcGFnZSBpbiByZWFkb25seSBtb2RlKi8KPiArCXRvcF9sZXZlbF9yZWYgPSBnbnR0YWJf Z3JhbnRfZm9yZWlnbl9hY2Nlc3MocmRvbWFpbiwgdmlydF90b19tZm4oKHVuc2lnbmVkIGxvbmcp dG1wX3BhZ2UpLCAxKTsKPiArCj4gKwlrZnJlZShhZGRyX3JlZnMpOwo+ICsKPiArCXJldHVybiB0 b3BfbGV2ZWxfcmVmOwo+ICt9Cj4gKwo+ICsvKgo+ICsgKiBNYXBzIHByb3ZpZGVkIHRvcCBsZXZl bCByZWYgaWQgYW5kIHRoZW4gcmV0dXJuIGFycmF5IG9mIHBhZ2VzIGNvbnRhaW5pbmcgZGF0YSBy ZWZzLgo+ICsgKi8KPiArc3RydWN0IHBhZ2UqKiBoeXBlcl9kbWFidWZfZ2V0X2RhdGFfcmVmcyhn cmFudF9yZWZfdCB0b3BfbGV2ZWxfcmVmLCBpbnQgZG9taWQsIGludCBuZW50cywKPiArCQkJCQkg c3RydWN0IGh5cGVyX2RtYWJ1Zl9zaGFyZWRfcGFnZXNfaW5mbyAqc2hhcmVkX3BhZ2VzX2luZm8p Cj4gK3sKPiArCXN0cnVjdCBwYWdlICp0b3BfbGV2ZWxfcGFnZTsKPiArCXN0cnVjdCBwYWdlICoq bGV2ZWwyX3BhZ2VzOwo+ICsKPiArCWdyYW50X3JlZl90ICp0b3BfbGV2ZWxfcmVmczsKPiArCj4g KwlzdHJ1Y3QgZ250dGFiX21hcF9ncmFudF9yZWYgdG9wX2xldmVsX21hcF9vcHM7Cj4gKwlzdHJ1 Y3QgZ250dGFiX3VubWFwX2dyYW50X3JlZiB0b3BfbGV2ZWxfdW5tYXBfb3BzOwo+ICsKPiArCXN0 cnVjdCBnbnR0YWJfbWFwX2dyYW50X3JlZiAqbWFwX29wczsKPiArCXN0cnVjdCBnbnR0YWJfdW5t YXBfZ3JhbnRfcmVmICp1bm1hcF9vcHM7Cj4gKwo+ICsJdW5zaWduZWQgbG9uZyBhZGRyOwo+ICsJ aW50IG5fbGV2ZWwyX3JlZnMgPSAwOwo+ICsJaW50IGk7Cj4gKwo+ICsJbl9sZXZlbDJfcmVmcyA9 IChuZW50cyAvIFJFRlNfUEVSX1BBR0UpICsgKChuZW50cyAlIFJFRlNfUEVSX1BBR0UpID8gMSA6 IDApOwo+ICsKPiArCWxldmVsMl9wYWdlcyA9IGtjYWxsb2Moc2l6ZW9mKHN0cnVjdCBwYWdlKiks IG5fbGV2ZWwyX3JlZnMsIEdGUF9LRVJORUwpOwo+ICsKPiArCW1hcF9vcHMgPSBrY2FsbG9jKHNp emVvZihtYXBfb3BzWzBdKSwgUkVGU19QRVJfUEFHRSwgR0ZQX0tFUk5FTCk7Cj4gKwl1bm1hcF9v cHMgPSBrY2FsbG9jKHNpemVvZih1bm1hcF9vcHNbMF0pLCBSRUZTX1BFUl9QQUdFLCBHRlBfS0VS TkVMKTsKPiArCj4gKwkvKiBNYXAgdG9wIGxldmVsIGFkZHJlc3NpbmcgcGFnZSAqLwo+ICsJaWYg KGdudHRhYl9hbGxvY19wYWdlcygxLCAmdG9wX2xldmVsX3BhZ2UpKSB7Cj4gKwkJcHJpbnRrKCJD YW5ub3QgYWxsb2NhdGUgcGFnZXNcbiIpOwo+ICsJCXJldHVybiBOVUxMOwo+ICsJfQo+ICsKPiAr CWFkZHIgPSAodW5zaWduZWQgbG9uZylwZm5fdG9fa2FkZHIocGFnZV90b19wZm4odG9wX2xldmVs X3BhZ2UpKTsKPiArCWdudHRhYl9zZXRfbWFwX29wKCZ0b3BfbGV2ZWxfbWFwX29wcywgYWRkciwg R05UTUFQX2hvc3RfbWFwIHwgR05UTUFQX3JlYWRvbmx5LCB0b3BfbGV2ZWxfcmVmLCBkb21pZCk7 Cj4gKwlnbnR0YWJfc2V0X3VubWFwX29wKCZ0b3BfbGV2ZWxfdW5tYXBfb3BzLCBhZGRyLCBHTlRN QVBfaG9zdF9tYXAgfCBHTlRNQVBfcmVhZG9ubHksIC0xKTsKPiArCj4gKwlpZiAoZ250dGFiX21h cF9yZWZzKCZ0b3BfbGV2ZWxfbWFwX29wcywgTlVMTCwgJnRvcF9sZXZlbF9wYWdlLCAxKSkgewo+ ICsJCXByaW50aygiXG54ZW46IGRvbTA6IEhZUEVSVklTT1IgbWFwIGdyYW50IHJlZiBmYWlsZWQi KTsKPiArCQlyZXR1cm4gTlVMTDsKPiArCX0KPiArCj4gKwlpZiAodG9wX2xldmVsX21hcF9vcHMu c3RhdHVzKSB7Cj4gKwkJcHJpbnRrKCJcbnhlbjogZG9tMDogSFlQRVJWSVNPUiBtYXAgZ3JhbnQg cmVmIGZhaWxlZCBzdGF0dXMgPSAlZCIsCj4gKwkJCQl0b3BfbGV2ZWxfbWFwX29wcy5zdGF0dXMp Owo+ICsJCXJldHVybiBOVUxMOwo+ICsJfSBlbHNlIHsKPiArCQl0b3BfbGV2ZWxfdW5tYXBfb3Bz LmhhbmRsZSA9IHRvcF9sZXZlbF9tYXBfb3BzLmhhbmRsZTsKPiArCX0KPiArCj4gKwkvKiBQYXJz ZSBjb250ZW50cyBvZiB0b3AgbGV2ZWwgYWRkcmVzc2luZyBwYWdlIHRvIGZpbmQgaG93IG1hbnkg c2Vjb25kIGxldmVsIHBhZ2VzIGlzIHRoZXJlKi8KPiArCXRvcF9sZXZlbF9yZWZzID0gcGZuX3Rv X2thZGRyKHBhZ2VfdG9fcGZuKHRvcF9sZXZlbF9wYWdlKSk7Cj4gKwo+ICsJLyogTWFwIGFsbCBz ZWNvbmQgbGV2ZWwgcGFnZXMgKi8KPiArCWlmIChnbnR0YWJfYWxsb2NfcGFnZXMobl9sZXZlbDJf cmVmcywgbGV2ZWwyX3BhZ2VzKSkgewo+ICsJCXByaW50aygiQ2Fubm90IGFsbG9jYXRlIHBhZ2Vz XG4iKTsKPiArCQlyZXR1cm4gTlVMTDsKPiArCX0KPiArCj4gKwlmb3IgKGkgPSAwOyBpIDwgbl9s ZXZlbDJfcmVmczsgaSsrKSB7Cj4gKwkJYWRkciA9ICh1bnNpZ25lZCBsb25nKXBmbl90b19rYWRk cihwYWdlX3RvX3BmbihsZXZlbDJfcGFnZXNbaV0pKTsKPiArCQlnbnR0YWJfc2V0X21hcF9vcCgm bWFwX29wc1tpXSwgYWRkciwgR05UTUFQX2hvc3RfbWFwIHwgR05UTUFQX3JlYWRvbmx5LCB0b3Bf bGV2ZWxfcmVmc1tpXSwgZG9taWQpOwo+ICsJCWdudHRhYl9zZXRfdW5tYXBfb3AoJnVubWFwX29w c1tpXSwgYWRkciwgR05UTUFQX2hvc3RfbWFwIHwgR05UTUFQX3JlYWRvbmx5LCAtMSk7Cj4gKwl9 Cj4gKwo+ICsJaWYgKGdudHRhYl9tYXBfcmVmcyhtYXBfb3BzLCBOVUxMLCBsZXZlbDJfcGFnZXMs IG5fbGV2ZWwyX3JlZnMpKSB7Cj4gKwkJcHJpbnRrKCJcbnhlbjogZG9tMDogSFlQRVJWSVNPUiBt YXAgZ3JhbnQgcmVmIGZhaWxlZCIpOwo+ICsJCXJldHVybiBOVUxMOwo+ICsJfQo+ICsKPiArCS8q IENoZWNrcyBpZiBwYWdlcyB3ZXJlIG1hcHBlZCBjb3JyZWN0bHkgYW5kIGF0IHRoZSBzYW1lIHRp bWUgaXMgY2FsY3VsYXRpbmcgdG90YWwgbnVtYmVyIG9mIGRhdGEgcmVmaWRzKi8KPiArCWZvciAo aSA9IDA7IGkgPCBuX2xldmVsMl9yZWZzOyBpKyspIHsKPiArCQlpZiAobWFwX29wc1tpXS5zdGF0 dXMpIHsKPiArCQkJcHJpbnRrKCJcbnhlbjogZG9tMDogSFlQRVJWSVNPUiBtYXAgZ3JhbnQgcmVm IGZhaWxlZCBzdGF0dXMgPSAlZCIsCj4gKwkJCQkJbWFwX29wc1tpXS5zdGF0dXMpOwo+ICsJCQly ZXR1cm4gTlVMTDsKPiArCQl9IGVsc2Ugewo+ICsJCQl1bm1hcF9vcHNbaV0uaGFuZGxlID0gbWFw X29wc1tpXS5oYW5kbGU7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCS8qIFVubWFwIHRvcCBsZXZlbCBw YWdlLCBhcyBpdCB3b24ndCBiZSBuZWVkZWQgYW55IGxvbmdlciAqLwo+ICsJaWYgKGdudHRhYl91 bm1hcF9yZWZzKCZ0b3BfbGV2ZWxfdW5tYXBfb3BzLCBOVUxMLCAmdG9wX2xldmVsX3BhZ2UsIDEp KSB7Cj4gKwkJcHJpbnRrKCJceGVuOiBjYW5ub3QgdW5tYXAgdG9wIGxldmVsIHBhZ2VcbiIpOwo+ ICsJCXJldHVybiBOVUxMOwo+ICsJfQo+ICsKPiArCWdudHRhYl9mcmVlX3BhZ2VzKDEsICZ0b3Bf bGV2ZWxfcGFnZSk7Cj4gKwlrZnJlZShtYXBfb3BzKTsKPiArCXNoYXJlZF9wYWdlc19pbmZvLT51 bm1hcF9vcHMgPSB1bm1hcF9vcHM7Cj4gKwo+ICsJcmV0dXJuIGxldmVsMl9wYWdlczsKPiArfQo+ ICsKPiArCj4gKy8qIFRoaXMgY29sbGVjdHMgYWxsIHJlZmVyZW5jZSBudW1iZXJzIGZvciAybmQg bGV2ZWwgc2hhcmVkIHBhZ2VzIGFuZCBjcmVhdGUgYSB0YWJsZQo+ICsgKiB3aXRoIHRob3NlIGlu IDFzdCBsZXZlbCBzaGFyZWQgcGFnZXMgdGhlbiByZXR1cm4gcmVmZXJlbmNlIG51bWJlcnMgZm9y IHRoaXMgdG9wIGxldmVsCj4gKyAqIHRhYmxlLiAqLwo+ICtncmFudF9yZWZfdCBoeXBlcl9kbWFi dWZfY3JlYXRlX2dyZWZfdGFibGUoc3RydWN0IHBhZ2UgKipwYWdlcywgaW50IHJkb21haW4sIGlu dCBuZW50cywKPiArCQkJCQkgICBzdHJ1Y3QgaHlwZXJfZG1hYnVmX3NoYXJlZF9wYWdlc19pbmZv ICpzaGFyZWRfcGFnZXNfaW5mbykKPiArewo+ICsJaW50IGkgPSAwOwo+ICsJZ3JhbnRfcmVmX3Qg KmRhdGFfcmVmczsKPiArCWdyYW50X3JlZl90IHRvcF9sZXZlbF9yZWY7Cj4gKwo+ICsJLyogYWxs b2NhdGUgdGVtcCBhcnJheSBmb3IgcmVmcyBvZiBzaGFyZWQgZGF0YSBwYWdlcyAqLwo+ICsJZGF0 YV9yZWZzID0ga2NhbGxvYyhuZW50cywgc2l6ZW9mKGdyYW50X3JlZl90KSwgR0ZQX0tFUk5FTCk7 Cj4gKwo+ICsJLyogc2hhcmUgZGF0YSBwYWdlcyBpbiBydyBtb2RlKi8KPiArCWZvciAoaT0wOyBp PG5lbnRzOyBpKyspIHsKPiArCQlkYXRhX3JlZnNbaV0gPSBnbnR0YWJfZ3JhbnRfZm9yZWlnbl9h Y2Nlc3MocmRvbWFpbiwgcGZuX3RvX21mbihwYWdlX3RvX3BmbihwYWdlc1tpXSkpLCAwKTsKPiAr CX0KPiArCj4gKwkvKiBjcmVhdGUgYWRkaXRpb25hbCBzaGFyZWQgcGFnZXMgd2l0aCAyIGxldmVs IGFkZHJlc3Npbmcgb2YgZGF0YSBwYWdlcyAqLwo+ICsJdG9wX2xldmVsX3JlZiA9IGh5cGVyX2Rt YWJ1Zl9jcmVhdGVfYWRkcmVzc2luZ190YWJsZXMoZGF0YV9yZWZzLCBuZW50cywgcmRvbWFpbiwK PiArCQkJCQkJCSAgICAgIHNoYXJlZF9wYWdlc19pbmZvKTsKPiArCj4gKwkvKiBTdG9yZSBleHBv cnRlZCBwYWdlcyByZWZpZCB0byBiZSB1bnNoYXJlZCBsYXRlciAqLwo+ICsJc2hhcmVkX3BhZ2Vz X2luZm8tPmRhdGFfcmVmcyA9IGRhdGFfcmVmczsKPiArCXNoYXJlZF9wYWdlc19pbmZvLT50b3Bf bGV2ZWxfcmVmID0gdG9wX2xldmVsX3JlZjsKPiArCj4gKwlyZXR1cm4gdG9wX2xldmVsX3JlZjsK PiArfQo+ICsKPiAraW50IGh5cGVyX2RtYWJ1Zl9jbGVhbnVwX2dyZWZfdGFibGUoc3RydWN0IGh5 cGVyX2RtYWJ1Zl9zZ3RfaW5mbyAqc2d0X2luZm8pIHsKPiArCXVpbnQzMl90IGkgPSAwOwo+ICsJ c3RydWN0IGh5cGVyX2RtYWJ1Zl9zaGFyZWRfcGFnZXNfaW5mbyAqc2hhcmVkX3BhZ2VzX2luZm8g PSAmc2d0X2luZm8tPnNoYXJlZF9wYWdlc19pbmZvOwo+ICsKPiArCWdyYW50X3JlZl90ICpyZWYg PSBzaGFyZWRfcGFnZXNfaW5mby0+dG9wX2xldmVsX3BhZ2U7Cj4gKwlpbnQgbl8ybmRfbGV2ZWxf cGFnZXMgPSAoc2d0X2luZm8tPnNndC0+bmVudHMvUkVGU19QRVJfUEFHRSArICgoc2d0X2luZm8t PnNndC0+bmVudHMgJSBSRUZTX1BFUl9QQUdFKSA/IDE6IDApKTsvKiByb3VuZGluZyAqLwo+ICsK PiArCj4gKwlpZiAoc2hhcmVkX3BhZ2VzX2luZm8tPmRhdGFfcmVmcyA9PSBOVUxMIHx8Cj4gKwkg ICAgc2hhcmVkX3BhZ2VzX2luZm8tPmFkZHJfcGFnZXMgPT0gIE5VTEwgfHwKPiArCSAgICBzaGFy ZWRfcGFnZXNfaW5mby0+dG9wX2xldmVsX3BhZ2UgPT0gTlVMTCB8fAo+ICsJICAgIHNoYXJlZF9w YWdlc19pbmZvLT50b3BfbGV2ZWxfcmVmID09IC0xKSB7Cj4gKwkJcHJpbnRrKCJncmVmIHRhYmxl IGZvciBoeXBlcl9kbWFidWYgYWxyZWFkeSBjbGVhbmVkIHVwXG4iKTsKPiArCQlyZXR1cm4gMDsK PiArCX0KPiArCj4gKwkvKiBFbmQgZm9yZWlnbiBhY2Nlc3MgZm9yIDJuZCBsZXZlbCBhZGRyZXNz aW5nIHBhZ2VzICovCj4gKwl3aGlsZShyZWZbaV0gIT0gMCAmJiBpIDwgbl8ybmRfbGV2ZWxfcGFn ZXMpIHsKPiArCQlpZiAoZ250dGFiX3F1ZXJ5X2ZvcmVpZ25fYWNjZXNzKHJlZltpXSkpIHsKPiAr CQkJcHJpbnRrKCJyZWZpZCBub3Qgc2hhcmVkICEhXG4iKTsKPiArCQl9Cj4gKwkJaWYgKCFnbnR0 YWJfZW5kX2ZvcmVpZ25fYWNjZXNzX3JlZihyZWZbaV0sIDEpKSB7Cj4gKwkJCXByaW50aygicmVm aWQgc3RpbGwgaW4gdXNlISEhXG4iKTsKPiArCQl9Cj4gKwkJaSsrOwo+ICsJfQo+ICsJZnJlZV9w YWdlcygodW5zaWduZWQgbG9uZylzaGFyZWRfcGFnZXNfaW5mby0+YWRkcl9wYWdlcywgaSk7Cj4g Kwo+ICsJLyogRW5kIGZvcmVpZ24gYWNjZXNzIGZvciB0b3AgbGV2ZWwgYWRkcmVzc2luZyBwYWdl ICovCj4gKwlpZiAoZ250dGFiX3F1ZXJ5X2ZvcmVpZ25fYWNjZXNzKHNoYXJlZF9wYWdlc19pbmZv LT50b3BfbGV2ZWxfcmVmKSkgewo+ICsJCXByaW50aygicmVmaWQgbm90IHNoYXJlZCAhIVxuIik7 Cj4gKwl9Cj4gKwlpZiAoIWdudHRhYl9lbmRfZm9yZWlnbl9hY2Nlc3NfcmVmKHNoYXJlZF9wYWdl c19pbmZvLT50b3BfbGV2ZWxfcmVmLCAxKSkgewo+ICsJCXByaW50aygicmVmaWQgc3RpbGwgaW4g dXNlISEhXG4iKTsKPiArCX0KPiArCWdudHRhYl9lbmRfZm9yZWlnbl9hY2Nlc3NfcmVmKHNoYXJl ZF9wYWdlc19pbmZvLT50b3BfbGV2ZWxfcmVmLCAxKTsKPiArCWZyZWVfcGFnZXMoKHVuc2lnbmVk IGxvbmcpc2hhcmVkX3BhZ2VzX2luZm8tPnRvcF9sZXZlbF9wYWdlLCAxKTsKPiArCj4gKwkvKiBF bmQgZm9yZWlnbiBhY2Nlc3MgZm9yIGRhdGEgcGFnZXMsIGJ1dCBkbyBub3QgZnJlZSB0aGVtICov Cj4gKwlmb3IgKGkgPSAwOyBpIDwgc2d0X2luZm8tPnNndC0+bmVudHM7IGkrKykgewo+ICsJCWlm IChnbnR0YWJfcXVlcnlfZm9yZWlnbl9hY2Nlc3Moc2hhcmVkX3BhZ2VzX2luZm8tPmRhdGFfcmVm c1tpXSkpIHsKPiArCQkJcHJpbnRrKCJyZWZpZCBub3Qgc2hhcmVkICEhXG4iKTsKPiArCQl9Cj4g KwkJZ250dGFiX2VuZF9mb3JlaWduX2FjY2Vzc19yZWYoc2hhcmVkX3BhZ2VzX2luZm8tPmRhdGFf cmVmc1tpXSwgMCk7Cj4gKwl9Cj4gKwo+ICsJa2ZyZWUoc2hhcmVkX3BhZ2VzX2luZm8tPmRhdGFf cmVmcyk7Cj4gKwo+ICsJc2hhcmVkX3BhZ2VzX2luZm8tPmRhdGFfcmVmcyA9IE5VTEw7Cj4gKwlz aGFyZWRfcGFnZXNfaW5mby0+YWRkcl9wYWdlcyA9IE5VTEw7Cj4gKwlzaGFyZWRfcGFnZXNfaW5m by0+dG9wX2xldmVsX3BhZ2UgPSBOVUxMOwo+ICsJc2hhcmVkX3BhZ2VzX2luZm8tPnRvcF9sZXZl bF9yZWYgPSAtMTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiAraW50IGh5cGVyX2RtYWJ1 Zl9jbGVhbnVwX2ltcG9ydGVkX3BhZ2VzKHN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0 X2luZm8gKnNndF9pbmZvKSB7Cj4gKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3NoYXJlZF9wYWdlc19p bmZvICpzaGFyZWRfcGFnZXNfaW5mbyA9ICZzZ3RfaW5mby0+c2hhcmVkX3BhZ2VzX2luZm87Cj4g Kwo+ICsJaWYoc2hhcmVkX3BhZ2VzX2luZm8tPnVubWFwX29wcyA9PSBOVUxMIHx8IHNoYXJlZF9w YWdlc19pbmZvLT5kYXRhX3BhZ2VzID09IE5VTEwpIHsKPiArCQlwcmludGsoIkltcG9ydGVkIHBh Z2VzIGFscmVhZHkgY2xlYW5lZCB1cCBvciBidWZmZXIgd2FzIG5vdCBpbXBvcnRlZCB5ZXRcbiIp Owo+ICsJCXJldHVybiAwOwo+ICsJfQo+ICsKPiArCWlmIChnbnR0YWJfdW5tYXBfcmVmcyhzaGFy ZWRfcGFnZXNfaW5mby0+dW5tYXBfb3BzLCBOVUxMLCBzaGFyZWRfcGFnZXNfaW5mby0+ZGF0YV9w YWdlcywgc2d0X2luZm8tPm5lbnRzKSApIHsKPiArCQlwcmludGsoIkNhbm5vdCB1bm1hcCBkYXRh IHBhZ2VzXG4iKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlnbnR0YWJfZnJl ZV9wYWdlcyhzZ3RfaW5mby0+bmVudHMsIHNoYXJlZF9wYWdlc19pbmZvLT5kYXRhX3BhZ2VzKTsK PiArCWtmcmVlKHNoYXJlZF9wYWdlc19pbmZvLT5kYXRhX3BhZ2VzKTsKPiArCWtmcmVlKHNoYXJl ZF9wYWdlc19pbmZvLT51bm1hcF9vcHMpOwo+ICsJc2hhcmVkX3BhZ2VzX2luZm8tPnVubWFwX29w cyA9IE5VTEw7Cj4gKwlzaGFyZWRfcGFnZXNfaW5mby0+ZGF0YV9wYWdlcyA9IE5VTEw7Cj4gKwo+ ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gKy8qIG1hcCBhbmQgY29uc3RydWN0IHNnX2xpc3RzIGZy b20gcmVmZXJlbmNlIG51bWJlcnMgKi8KPiArc3RydWN0IHNnX3RhYmxlKiBoeXBlcl9kbWFidWZf bWFwX3BhZ2VzKGdyYW50X3JlZl90IHRvcF9sZXZlbF9ncmVmLCBpbnQgZnJzdF9vZnN0LCBpbnQg bGFzdF9sZW4sIGludCBuZW50cywgaW50IHNkb21haW4sCj4gKwkJCQkJc3RydWN0IGh5cGVyX2Rt YWJ1Zl9zaGFyZWRfcGFnZXNfaW5mbyAqc2hhcmVkX3BhZ2VzX2luZm8pCj4gK3sKPiArCXN0cnVj dCBzZ190YWJsZSAqc3Q7Cj4gKwlzdHJ1Y3QgcGFnZSAqKnBhZ2VzOwo+ICsJc3RydWN0IGdudHRh Yl9tYXBfZ3JhbnRfcmVmICpvcHM7Cj4gKwlzdHJ1Y3QgZ250dGFiX3VubWFwX2dyYW50X3JlZiAq dW5tYXBfb3BzOwo+ICsJdW5zaWduZWQgbG9uZyBhZGRyOwo+ICsJZ3JhbnRfcmVmX3QgKnJlZnM7 Cj4gKwlpbnQgaTsKPiArCWludCBuX2xldmVsMl9yZWZzID0gKG5lbnRzIC8gUkVGU19QRVJfUEFH RSkgKyAoKG5lbnRzICUgUkVGU19QRVJfUEFHRSkgPyAxIDogMCk7Cj4gKwo+ICsJLyogR2V0IGRh dGEgcmVmaWRzICovCj4gKwlzdHJ1Y3QgcGFnZSoqIHJlZmlkX3BhZ2VzID0gaHlwZXJfZG1hYnVm X2dldF9kYXRhX3JlZnModG9wX2xldmVsX2dyZWYsIHNkb21haW4sIG5lbnRzLAo+ICsJCQkJCQkJ ICAgICAgIHNoYXJlZF9wYWdlc19pbmZvKTsKPiArCj4gKwlwYWdlcyA9IGtjYWxsb2Moc2l6ZW9m KHN0cnVjdCBwYWdlKiksIG5lbnRzLCBHRlBfS0VSTkVMKTsKPiArCWlmIChwYWdlcyA9PSBOVUxM KSB7Cj4gKwkJcmV0dXJuIE5VTEw7Cj4gKwl9Cj4gKwo+ICsJLyogYWxsb2NhdGUgbmV3IHBhZ2Vz IHRoYXQgYXJlIG1hcHBlZCB0byBzaGFyZWQgcGFnZXMgdmlhIGdyYW50LXRhYmxlICovCj4gKwlp ZiAoZ250dGFiX2FsbG9jX3BhZ2VzKG5lbnRzLCBwYWdlcykpIHsKPiArCQlwcmludGsoIkNhbm5v dCBhbGxvY2F0ZSBwYWdlc1xuIik7Cj4gKwkJcmV0dXJuIE5VTEw7Cj4gKwl9Cj4gKwo+ICsJb3Bz ID0gKHN0cnVjdCBnbnR0YWJfbWFwX2dyYW50X3JlZiAqKWtjYWxsb2MobmVudHMsIHNpemVvZihz dHJ1Y3QgZ250dGFiX21hcF9ncmFudF9yZWYpLCBHRlBfS0VSTkVMKTsKPiArCXVubWFwX29wcyA9 IChzdHJ1Y3QgZ250dGFiX3VubWFwX2dyYW50X3JlZiAqKWtjYWxsb2MobmVudHMsIHNpemVvZihz dHJ1Y3QgZ250dGFiX3VubWFwX2dyYW50X3JlZiksIEdGUF9LRVJORUwpOwo+ICsKPiArCWZvciAo aT0wOyBpPG5lbnRzOyBpKyspIHsKPiArCQlhZGRyID0gKHVuc2lnbmVkIGxvbmcpcGZuX3RvX2th ZGRyKHBhZ2VfdG9fcGZuKHBhZ2VzW2ldKSk7Cj4gKwkJcmVmcyA9IHBmbl90b19rYWRkcihwYWdl X3RvX3BmbihyZWZpZF9wYWdlc1tpIC8gUkVGU19QRVJfUEFHRV0pKTsKPiArCQlnbnR0YWJfc2V0 X21hcF9vcCgmb3BzW2ldLCBhZGRyLCBHTlRNQVBfaG9zdF9tYXAgfCBHTlRNQVBfcmVhZG9ubHks IHJlZnNbaSAlIFJFRlNfUEVSX1BBR0VdLCBzZG9tYWluKTsKPiArCQlnbnR0YWJfc2V0X3VubWFw X29wKCZ1bm1hcF9vcHNbaV0sIGFkZHIsIEdOVE1BUF9ob3N0X21hcCB8IEdOVE1BUF9yZWFkb25s eSwgLTEpOwo+ICsJfQo+ICsKPiArCWlmIChnbnR0YWJfbWFwX3JlZnMob3BzLCBOVUxMLCBwYWdl cywgbmVudHMpKSB7Cj4gKwkJcHJpbnRrKCJcbnhlbjogZG9tMDogSFlQRVJWSVNPUiBtYXAgZ3Jh bnQgcmVmIGZhaWxlZFxuIik7Cj4gKwkJcmV0dXJuIE5VTEw7Cj4gKwl9Cj4gKwo+ICsJZm9yIChp PTA7IGk8bmVudHM7IGkrKykgewo+ICsJCWlmIChvcHNbaV0uc3RhdHVzKSB7Cj4gKwkJCXByaW50 aygiXG54ZW46IGRvbTA6IEhZUEVSVklTT1IgbWFwIGdyYW50IHJlZiBmYWlsZWQgc3RhdHVzID0g JWRcbiIsCj4gKwkJCQlvcHNbMF0uc3RhdHVzKTsKPiArCQkJcmV0dXJuIE5VTEw7Cj4gKwkJfSBl bHNlIHsKPiArCQkJdW5tYXBfb3BzW2ldLmhhbmRsZSA9IG9wc1tpXS5oYW5kbGU7Cj4gKwkJfQo+ ICsJfQo+ICsKPiArCXN0ID0gaHlwZXJfZG1hYnVmX2NyZWF0ZV9zZ3QocGFnZXMsIGZyc3Rfb2Zz dCwgbGFzdF9sZW4sIG5lbnRzKTsKPiArCj4gKwlpZiAoZ250dGFiX3VubWFwX3JlZnMoc2hhcmVk X3BhZ2VzX2luZm8tPnVubWFwX29wcywgTlVMTCwgcmVmaWRfcGFnZXMsIG5fbGV2ZWwyX3JlZnMp ICkgewo+ICsJCXByaW50aygiQ2Fubm90IHVubWFwIDJuZCBsZXZlbCByZWZzXG4iKTsKPiArCQly ZXR1cm4gTlVMTDsKPiArCX0KPiArCj4gKwlnbnR0YWJfZnJlZV9wYWdlcyhuX2xldmVsMl9yZWZz LCByZWZpZF9wYWdlcyk7Cj4gKwlrZnJlZShyZWZpZF9wYWdlcyk7Cj4gKwo+ICsJa2ZyZWUoc2hh cmVkX3BhZ2VzX2luZm8tPnVubWFwX29wcyk7Cj4gKwlzaGFyZWRfcGFnZXNfaW5mby0+dW5tYXBf b3BzID0gdW5tYXBfb3BzOwo+ICsJc2hhcmVkX3BhZ2VzX2luZm8tPmRhdGFfcGFnZXMgPSBwYWdl czsKPiArCWtmcmVlKG9wcyk7Cj4gKwo+ICsJcmV0dXJuIHN0Owo+ICt9Cj4gKwo+ICtpbmxpbmUg aW50IGh5cGVyX2RtYWJ1Zl9zeW5jX3JlcXVlc3RfYW5kX3dhaXQoaW50IGlkLCBpbnQgb3BzKQo+ ICt7Cj4gKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfcnEgKnJlcTsKPiArCWludCBvcGVyYW5k c1syXTsKPiArCWludCByZXQ7Cj4gKwo+ICsJb3BlcmFuZHNbMF0gPSBpZDsKPiArCW9wZXJhbmRz WzFdID0gb3BzOwo+ICsKPiArCXJlcSA9IGtjYWxsb2MoMSwgc2l6ZW9mKCpyZXEpLCBHRlBfS0VS TkVMKTsKPiArCj4gKwloeXBlcl9kbWFidWZfY3JlYXRlX3JlcXVlc3QocmVxLCBIWVBFUl9ETUFC VUZfT1BTX1RPX1NPVVJDRSwgJm9wZXJhbmRzWzBdKTsKPiArCj4gKwkvKiBzZW5kIHJlcXVlc3Qg Ki8KPiArCXJldCA9IGh5cGVyX2RtYWJ1Zl9zZW5kX3JlcXVlc3QoaWQsIHJlcSk7Cj4gKwo+ICsJ LyogVE9ETzogd2FpdCB1bnRpbCBpdCBnZXRzIHJlc3BvbnNlLi4gb3IgY2FuIHdlIGp1c3QgbW92 ZSBvbj8gKi8KPiArCj4gKwlrZnJlZShyZXEpOwo+ICsKPiArCXJldHVybiByZXQ7Cj4gK30KPiAr Cj4gK3N0YXRpYyBpbnQgaHlwZXJfZG1hYnVmX29wc19hdHRhY2goc3RydWN0IGRtYV9idWYqIGRt YWJ1Ziwgc3RydWN0IGRldmljZSogZGV2LAo+ICsJCQlzdHJ1Y3QgZG1hX2J1Zl9hdHRhY2htZW50 ICphdHRhY2gpCj4gK3sKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8g KnNndF9pbmZvOwo+ICsJaW50IHJldDsKPiArCj4gKwlpZiAoIWF0dGFjaC0+ZG1hYnVmLT5wcml2 KQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXNndF9pbmZvID0gKHN0cnVjdCBoeXBlcl9k bWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKilhdHRhY2gtPmRtYWJ1Zi0+cHJpdjsKPiArCj4gKwly ZXQgPSBoeXBlcl9kbWFidWZfc3luY19yZXF1ZXN0X2FuZF93YWl0KEhZUEVSX0RNQUJVRl9JRF9J TVBPUlRFUl9HRVRfU0RPTUFJTl9JRChzZ3RfaW5mby0+aHlwZXJfZG1hYnVmX2lkKSwKPiArCQkJ CQkJSFlQRVJfRE1BQlVGX09QU19BVFRBQ0gpOwo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJ cHJpbnRrKCJzZW5kIGRtYWJ1ZiBzeW5jIHJlcXVlc3QgZmFpbGVkXG4iKTsKPiArCX0KPiArCj4g KwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBoeXBlcl9kbWFidWZfb3BzX2Rl dGFjaChzdHJ1Y3QgZG1hX2J1ZiogZG1hYnVmLCBzdHJ1Y3QgZG1hX2J1Zl9hdHRhY2htZW50ICph dHRhY2gpCj4gK3sKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKnNn dF9pbmZvOwo+ICsJaW50IHJldDsKPiArCj4gKwlpZiAoIWF0dGFjaC0+ZG1hYnVmLT5wcml2KQo+ ICsJCXJldHVybjsKPiArCj4gKwlzZ3RfaW5mbyA9IChzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9y dGVkX3NndF9pbmZvICopYXR0YWNoLT5kbWFidWYtPnByaXY7Cj4gKwo+ICsJcmV0ID0gaHlwZXJf ZG1hYnVmX3N5bmNfcmVxdWVzdF9hbmRfd2FpdChIWVBFUl9ETUFCVUZfSURfSU1QT1JURVJfR0VU X1NET01BSU5fSUQoc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZCksCj4gKwkJCQkJCUhZUEVSX0RN QUJVRl9PUFNfREVUQUNIKTsKPiArCj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByaW50aygic2Vu ZCBkbWFidWYgc3luYyByZXF1ZXN0IGZhaWxlZFxuIik7Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRp YyBzdHJ1Y3Qgc2dfdGFibGUqIGh5cGVyX2RtYWJ1Zl9vcHNfbWFwKHN0cnVjdCBkbWFfYnVmX2F0 dGFjaG1lbnQgKmF0dGFjaG1lbnQsCj4gKwkJCQkJCWVudW0gZG1hX2RhdGFfZGlyZWN0aW9uIGRp cikKPiArewo+ICsJc3RydWN0IHNnX3RhYmxlICpzdDsKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZf aW1wb3J0ZWRfc2d0X2luZm8gKnNndF9pbmZvOwo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9wYWdl c19pbmZvICpwYWdlX2luZm87Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWlmICghYXR0YWNobWVudC0+ ZG1hYnVmLT5wcml2KQo+ICsJCXJldHVybiBOVUxMOwo+ICsKPiArCXNndF9pbmZvID0gKHN0cnVj dCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKilhdHRhY2htZW50LT5kbWFidWYtPnBy aXY7Cj4gKwo+ICsJLyogZXh0cmFjdCBwYWdlcyBmcm9tIHNndCAqLwo+ICsJcGFnZV9pbmZvID0g aHlwZXJfZG1hYnVmX2V4dF9wZ3Moc2d0X2luZm8tPnNndCk7Cj4gKwo+ICsJLyogY3JlYXRlIGEg bmV3IHNnX3RhYmxlIHdpdGggZXh0cmFjdGVkIHBhZ2VzICovCj4gKwlzdCA9IGh5cGVyX2RtYWJ1 Zl9jcmVhdGVfc2d0KHBhZ2VfaW5mby0+cGFnZXMsIHBhZ2VfaW5mby0+ZnJzdF9vZnN0LAo+ICsJ CQkJcGFnZV9pbmZvLT5sYXN0X2xlbiwgcGFnZV9pbmZvLT5uZW50cyk7Cj4gKwlpZiAoc3QgPT0g TlVMTCkKPiArCQlnb3RvIGVycl9mcmVlX3NnOwo+ICsKPiArICAgICAgICBpZiAoIWRtYV9tYXBf c2coYXR0YWNobWVudC0+ZGV2LCBzdC0+c2dsLCBzdC0+bmVudHMsIGRpcikpIHsKPiArICAgICAg ICAgICAgICAgIGdvdG8gZXJyX2ZyZWVfc2c7Cj4gKyAgICAgICAgfQo+ICsKPiArCXJldCA9IGh5 cGVyX2RtYWJ1Zl9zeW5jX3JlcXVlc3RfYW5kX3dhaXQoSFlQRVJfRE1BQlVGX0lEX0lNUE9SVEVS X0dFVF9TRE9NQUlOX0lEKHNndF9pbmZvLT5oeXBlcl9kbWFidWZfaWQpLAo+ICsJCQkJCQlIWVBF Ul9ETUFCVUZfT1BTX01BUCk7Cj4gKwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlwcmludGsoInNl bmQgZG1hYnVmIHN5bmMgcmVxdWVzdCBmYWlsZWRcbiIpOwo+ICsJfQo+ICsKPiArCXJldHVybiBz dDsKPiArCj4gK2Vycl9mcmVlX3NnOgo+ICsJc2dfZnJlZV90YWJsZShzdCk7Cj4gKwlrZnJlZShz dCk7Cj4gKwlyZXR1cm4gTlVMTDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgaHlwZXJfZG1hYnVm X29wc191bm1hcChzdHJ1Y3QgZG1hX2J1Zl9hdHRhY2htZW50ICphdHRhY2htZW50LAo+ICsJCQkJ CQlzdHJ1Y3Qgc2dfdGFibGUgKnNnLAo+ICsJCQkJCQllbnVtIGRtYV9kYXRhX2RpcmVjdGlvbiBk aXIpCj4gK3sKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKnNndF9p bmZvOwo+ICsJaW50IHJldDsKPiArCj4gKwlpZiAoIWF0dGFjaG1lbnQtPmRtYWJ1Zi0+cHJpdikK PiArCQlyZXR1cm47Cj4gKwo+ICsJc2d0X2luZm8gPSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBv cnRlZF9zZ3RfaW5mbyAqKWF0dGFjaG1lbnQtPmRtYWJ1Zi0+cHJpdjsKPiArCj4gKwlkbWFfdW5t YXBfc2coYXR0YWNobWVudC0+ZGV2LCBzZy0+c2dsLCBzZy0+bmVudHMsIGRpcik7Cj4gKwo+ICsJ c2dfZnJlZV90YWJsZShzZyk7Cj4gKwlrZnJlZShzZyk7Cj4gKwo+ICsJcmV0ID0gaHlwZXJfZG1h YnVmX3N5bmNfcmVxdWVzdF9hbmRfd2FpdChIWVBFUl9ETUFCVUZfSURfSU1QT1JURVJfR0VUX1NE T01BSU5fSUQoc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZCksCj4gKwkJCQkJCUhZUEVSX0RNQUJV Rl9PUFNfVU5NQVApOwo+ICsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJpbnRrKCJzZW5kIGRt YWJ1ZiBzeW5jIHJlcXVlc3QgZmFpbGVkXG4iKTsKPiArCX0KPiArfQo+ICsKPiArc3RhdGljIHZv aWQgaHlwZXJfZG1hYnVmX29wc19yZWxlYXNlKHN0cnVjdCBkbWFfYnVmICpkbWFidWYpCj4gK3sK PiArCXN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKnNndF9pbmZvOwo+ICsJ aW50IHJldDsKPiArCj4gKwlpZiAoIWRtYWJ1Zi0+cHJpdikKPiArCQlyZXR1cm47Cj4gKwo+ICsJ c2d0X2luZm8gPSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqKWRtYWJ1 Zi0+cHJpdjsKPiArCj4gKwlyZXQgPSBoeXBlcl9kbWFidWZfc3luY19yZXF1ZXN0X2FuZF93YWl0 KEhZUEVSX0RNQUJVRl9JRF9JTVBPUlRFUl9HRVRfU0RPTUFJTl9JRChzZ3RfaW5mby0+aHlwZXJf ZG1hYnVmX2lkKSwKPiArCQkJCQkJSFlQRVJfRE1BQlVGX09QU19SRUxFQVNFKTsKPiArCj4gKwlp ZiAocmV0IDwgMCkgewo+ICsJCXByaW50aygic2VuZCBkbWFidWYgc3luYyByZXF1ZXN0IGZhaWxl ZFxuIik7Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgaHlwZXJfZG1hYnVmX29wc19iZWdp bl9jcHVfYWNjZXNzKHN0cnVjdCBkbWFfYnVmICpkbWFidWYsIGVudW0gZG1hX2RhdGFfZGlyZWN0 aW9uIGRpcikKPiArewo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAq c2d0X2luZm87Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWlmICghZG1hYnVmLT5wcml2KQo+ICsJCXJl dHVybiAtRUlOVkFMOwo+ICsKPiArCXNndF9pbmZvID0gKHN0cnVjdCBoeXBlcl9kbWFidWZfaW1w b3J0ZWRfc2d0X2luZm8gKilkbWFidWYtPnByaXY7Cj4gKwo+ICsJcmV0ID0gaHlwZXJfZG1hYnVm X3N5bmNfcmVxdWVzdF9hbmRfd2FpdChIWVBFUl9ETUFCVUZfSURfSU1QT1JURVJfR0VUX1NET01B SU5fSUQoc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZCksCj4gKwkJCQkJCUhZUEVSX0RNQUJVRl9P UFNfQkVHSU5fQ1BVX0FDQ0VTUyk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByaW50aygic2Vu ZCBkbWFidWYgc3luYyByZXF1ZXN0IGZhaWxlZFxuIik7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIHJl dDsKPiArfQo+ICsKPiArc3RhdGljIGludCBoeXBlcl9kbWFidWZfb3BzX2VuZF9jcHVfYWNjZXNz KHN0cnVjdCBkbWFfYnVmICpkbWFidWYsIGVudW0gZG1hX2RhdGFfZGlyZWN0aW9uIGRpcikKPiAr ewo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqc2d0X2luZm87Cj4g KwlpbnQgcmV0Owo+ICsKPiArCWlmICghZG1hYnVmLT5wcml2KQo+ICsJCXJldHVybiAtRUlOVkFM Owo+ICsKPiArCXNndF9pbmZvID0gKHN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2lu Zm8gKilkbWFidWYtPnByaXY7Cj4gKwo+ICsJcmV0ID0gaHlwZXJfZG1hYnVmX3N5bmNfcmVxdWVz dF9hbmRfd2FpdChIWVBFUl9ETUFCVUZfSURfSU1QT1JURVJfR0VUX1NET01BSU5fSUQoc2d0X2lu Zm8tPmh5cGVyX2RtYWJ1Zl9pZCksCj4gKwkJCQkJCUhZUEVSX0RNQUJVRl9PUFNfRU5EX0NQVV9B Q0NFU1MpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlwcmludGsoInNlbmQgZG1hYnVmIHN5bmMg cmVxdWVzdCBmYWlsZWRcbiIpOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtz dGF0aWMgdm9pZCAqaHlwZXJfZG1hYnVmX29wc19rbWFwX2F0b21pYyhzdHJ1Y3QgZG1hX2J1ZiAq ZG1hYnVmLCB1bnNpZ25lZCBsb25nIHBnbnVtKQo+ICt7Cj4gKwlzdHJ1Y3QgaHlwZXJfZG1hYnVm X2ltcG9ydGVkX3NndF9pbmZvICpzZ3RfaW5mbzsKPiArCWludCByZXQ7Cj4gKwo+ICsJaWYgKCFk bWFidWYtPnByaXYpCj4gKwkJcmV0dXJuIE5VTEw7Cj4gKwo+ICsJc2d0X2luZm8gPSAoc3RydWN0 IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqKWRtYWJ1Zi0+cHJpdjsKPiArCj4gKwly ZXQgPSBoeXBlcl9kbWFidWZfc3luY19yZXF1ZXN0X2FuZF93YWl0KEhZUEVSX0RNQUJVRl9JRF9J TVBPUlRFUl9HRVRfU0RPTUFJTl9JRChzZ3RfaW5mby0+aHlwZXJfZG1hYnVmX2lkKSwKPiArCQkJ CQkJSFlQRVJfRE1BQlVGX09QU19LTUFQX0FUT01JQyk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJ CXByaW50aygic2VuZCBkbWFidWYgc3luYyByZXF1ZXN0IGZhaWxlZFxuIik7Cj4gKwl9Cj4gKwo+ ICsJcmV0dXJuIE5VTEw7IC8qIGZvciBub3cgTlVMTC4uIG5lZWQgdG8gcmV0dXJuIHRoZSBhZGRy ZXNzIG9mIG1hcHBlZCByZWdpb24gKi8KPiArfQo+ICsKPiArc3RhdGljIHZvaWQgaHlwZXJfZG1h YnVmX29wc19rdW5tYXBfYXRvbWljKHN0cnVjdCBkbWFfYnVmICpkbWFidWYsIHVuc2lnbmVkIGxv bmcgcGdudW0sIHZvaWQgKnZhZGRyKQo+ICt7Cj4gKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9y dGVkX3NndF9pbmZvICpzZ3RfaW5mbzsKPiArCWludCByZXQ7Cj4gKwo+ICsJaWYgKCFkbWFidWYt PnByaXYpCj4gKwkJcmV0dXJuOwo+ICsKPiArCXNndF9pbmZvID0gKHN0cnVjdCBoeXBlcl9kbWFi dWZfaW1wb3J0ZWRfc2d0X2luZm8gKilkbWFidWYtPnByaXY7Cj4gKwo+ICsJcmV0ID0gaHlwZXJf ZG1hYnVmX3N5bmNfcmVxdWVzdF9hbmRfd2FpdChIWVBFUl9ETUFCVUZfSURfSU1QT1JURVJfR0VU X1NET01BSU5fSUQoc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZCksCj4gKwkJCQkJCUhZUEVSX0RN QUJVRl9PUFNfS1VOTUFQX0FUT01JQyk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByaW50aygi c2VuZCBkbWFidWYgc3luYyByZXF1ZXN0IGZhaWxlZFxuIik7Cj4gKwl9Cj4gK30KPiArCj4gK3N0 YXRpYyB2b2lkICpoeXBlcl9kbWFidWZfb3BzX2ttYXAoc3RydWN0IGRtYV9idWYgKmRtYWJ1Ziwg dW5zaWduZWQgbG9uZyBwZ251bSkKPiArewo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRl ZF9zZ3RfaW5mbyAqc2d0X2luZm87Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWlmICghZG1hYnVmLT5w cml2KQo+ICsJCXJldHVybiBOVUxMOwo+ICsKPiArCXNndF9pbmZvID0gKHN0cnVjdCBoeXBlcl9k bWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKilkbWFidWYtPnByaXY7Cj4gKwo+ICsJcmV0ID0gaHlw ZXJfZG1hYnVmX3N5bmNfcmVxdWVzdF9hbmRfd2FpdChIWVBFUl9ETUFCVUZfSURfSU1QT1JURVJf R0VUX1NET01BSU5fSUQoc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZCksCj4gKwkJCQkJCUhZUEVS X0RNQUJVRl9PUFNfS01BUCk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByaW50aygic2VuZCBk bWFidWYgc3luYyByZXF1ZXN0IGZhaWxlZFxuIik7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIE5VTEw7 IC8qIGZvciBub3cgTlVMTC4uIG5lZWQgdG8gcmV0dXJuIHRoZSBhZGRyZXNzIG9mIG1hcHBlZCBy ZWdpb24gKi8KPiArfQo+ICsKPiArc3RhdGljIHZvaWQgaHlwZXJfZG1hYnVmX29wc19rdW5tYXAo c3RydWN0IGRtYV9idWYgKmRtYWJ1ZiwgdW5zaWduZWQgbG9uZyBwZ251bSwgdm9pZCAqdmFkZHIp Cj4gK3sKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKnNndF9pbmZv Owo+ICsJaW50IHJldDsKPiArCj4gKwlpZiAoIWRtYWJ1Zi0+cHJpdikKPiArCQlyZXR1cm47Cj4g Kwo+ICsJc2d0X2luZm8gPSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAq KWRtYWJ1Zi0+cHJpdjsKPiArCj4gKwlyZXQgPSBoeXBlcl9kbWFidWZfc3luY19yZXF1ZXN0X2Fu ZF93YWl0KEhZUEVSX0RNQUJVRl9JRF9JTVBPUlRFUl9HRVRfU0RPTUFJTl9JRChzZ3RfaW5mby0+ aHlwZXJfZG1hYnVmX2lkKSwKPiArCQkJCQkJSFlQRVJfRE1BQlVGX09QU19LVU5NQVApOwo+ICsJ aWYgKHJldCA8IDApIHsKPiArCQlwcmludGsoInNlbmQgZG1hYnVmIHN5bmMgcmVxdWVzdCBmYWls ZWRcbiIpOwo+ICsJfQo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGh5cGVyX2RtYWJ1Zl9vcHNfbW1h cChzdHJ1Y3QgZG1hX2J1ZiAqZG1hYnVmLCBzdHJ1Y3Qgdm1fYXJlYV9zdHJ1Y3QgKnZtYSkKPiAr ewo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqc2d0X2luZm87Cj4g KwlpbnQgcmV0Owo+ICsKPiArCWlmICghZG1hYnVmLT5wcml2KQo+ICsJCXJldHVybiAtRUlOVkFM Owo+ICsKPiArCXNndF9pbmZvID0gKHN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2lu Zm8gKilkbWFidWYtPnByaXY7Cj4gKwo+ICsJcmV0ID0gaHlwZXJfZG1hYnVmX3N5bmNfcmVxdWVz dF9hbmRfd2FpdChIWVBFUl9ETUFCVUZfSURfSU1QT1JURVJfR0VUX1NET01BSU5fSUQoc2d0X2lu Zm8tPmh5cGVyX2RtYWJ1Zl9pZCksCj4gKwkJCQkJCUhZUEVSX0RNQUJVRl9PUFNfTU1BUCk7Cj4g KwlpZiAocmV0IDwgMCkgewo+ICsJCXByaW50aygic2VuZCBkbWFidWYgc3luYyByZXF1ZXN0IGZh aWxlZFxuIik7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIHZv aWQgKmh5cGVyX2RtYWJ1Zl9vcHNfdm1hcChzdHJ1Y3QgZG1hX2J1ZiAqZG1hYnVmKQo+ICt7Cj4g KwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZvICpzZ3RfaW5mbzsKPiArCWlu dCByZXQ7Cj4gKwo+ICsJaWYgKCFkbWFidWYtPnByaXYpCj4gKwkJcmV0dXJuIE5VTEw7Cj4gKwo+ ICsJc2d0X2luZm8gPSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqKWRt YWJ1Zi0+cHJpdjsKPiArCj4gKwlyZXQgPSBoeXBlcl9kbWFidWZfc3luY19yZXF1ZXN0X2FuZF93 YWl0KEhZUEVSX0RNQUJVRl9JRF9JTVBPUlRFUl9HRVRfU0RPTUFJTl9JRChzZ3RfaW5mby0+aHlw ZXJfZG1hYnVmX2lkKSwKPiArCQkJCQkJSFlQRVJfRE1BQlVGX09QU19WTUFQKTsKPiArCWlmIChy ZXQgPCAwKSB7Cj4gKwkJcHJpbnRrKCJzZW5kIGRtYWJ1ZiBzeW5jIHJlcXVlc3QgZmFpbGVkXG4i KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gTlVMTDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgaHlw ZXJfZG1hYnVmX29wc192dW5tYXAoc3RydWN0IGRtYV9idWYgKmRtYWJ1Ziwgdm9pZCAqdmFkZHIp Cj4gK3sKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKnNndF9pbmZv Owo+ICsJaW50IHJldDsKPiArCj4gKwlpZiAoIWRtYWJ1Zi0+cHJpdikKPiArCQlyZXR1cm47Cj4g Kwo+ICsJc2d0X2luZm8gPSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAq KWRtYWJ1Zi0+cHJpdjsKPiArCj4gKwlyZXQgPSBoeXBlcl9kbWFidWZfc3luY19yZXF1ZXN0X2Fu ZF93YWl0KEhZUEVSX0RNQUJVRl9JRF9JTVBPUlRFUl9HRVRfU0RPTUFJTl9JRChzZ3RfaW5mby0+ aHlwZXJfZG1hYnVmX2lkKSwKPiArCQkJCQkJSFlQRVJfRE1BQlVGX09QU19WVU5NQVApOwo+ICsJ aWYgKHJldCA8IDApIHsKPiArCQlwcmludGsoInNlbmQgZG1hYnVmIHN5bmMgcmVxdWVzdCBmYWls ZWRcbiIpOwo+ICsJfQo+ICt9Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGRtYV9idWZfb3Bz IGh5cGVyX2RtYWJ1Zl9vcHMgPSB7Cj4gKwkJLmF0dGFjaCA9IGh5cGVyX2RtYWJ1Zl9vcHNfYXR0 YWNoLAo+ICsJCS5kZXRhY2ggPSBoeXBlcl9kbWFidWZfb3BzX2RldGFjaCwKPiArCQkubWFwX2Rt YV9idWYgPSBoeXBlcl9kbWFidWZfb3BzX21hcCwKPiArCQkudW5tYXBfZG1hX2J1ZiA9IGh5cGVy X2RtYWJ1Zl9vcHNfdW5tYXAsCj4gKwkJLnJlbGVhc2UgPSBoeXBlcl9kbWFidWZfb3BzX3JlbGVh c2UsCj4gKwkJLmJlZ2luX2NwdV9hY2Nlc3MgPSAodm9pZCopaHlwZXJfZG1hYnVmX29wc19iZWdp bl9jcHVfYWNjZXNzLAo+ICsJCS5lbmRfY3B1X2FjY2VzcyA9ICh2b2lkKiloeXBlcl9kbWFidWZf b3BzX2VuZF9jcHVfYWNjZXNzLAo+ICsJCS5tYXBfYXRvbWljID0gaHlwZXJfZG1hYnVmX29wc19r bWFwX2F0b21pYywKPiArCQkudW5tYXBfYXRvbWljID0gaHlwZXJfZG1hYnVmX29wc19rdW5tYXBf YXRvbWljLAo+ICsJCS5tYXAgPSBoeXBlcl9kbWFidWZfb3BzX2ttYXAsCj4gKwkJLnVubWFwID0g aHlwZXJfZG1hYnVmX29wc19rdW5tYXAsCj4gKwkJLm1tYXAgPSBoeXBlcl9kbWFidWZfb3BzX21t YXAsCj4gKwkJLnZtYXAgPSBoeXBlcl9kbWFidWZfb3BzX3ZtYXAsCj4gKwkJLnZ1bm1hcCA9IGh5 cGVyX2RtYWJ1Zl9vcHNfdnVubWFwLAo+ICt9Owo+ICsKPiArLyogZXhwb3J0aW5nIGRtYWJ1ZiBh cyBmZCAqLwo+ICtpbnQgaHlwZXJfZG1hYnVmX2V4cG9ydF9mZChzdHJ1Y3QgaHlwZXJfZG1hYnVm X2ltcG9ydGVkX3NndF9pbmZvICpkaW5mbywgaW50IGZsYWdzKQo+ICt7Cj4gKwlpbnQgZmQ7Cj4g Kwo+ICsJc3RydWN0IGRtYV9idWYqIGRtYWJ1ZjsKPiArCj4gKy8qIGNhbGwgaHlwZXJfZG1hYnVm X2V4cG9ydF9kbWFidWYgYW5kIGNyZWF0ZSBhbmQgYmluZCBhIGhhbmRsZSBmb3IgaXQKPiArICog dGhlbiByZWxlYXNlICovCj4gKwo+ICsJZG1hYnVmID0gaHlwZXJfZG1hYnVmX2V4cG9ydF9kbWFf YnVmKGRpbmZvKTsKPiArCj4gKwlmZCA9IGRtYV9idWZfZmQoZG1hYnVmLCBmbGFncyk7Cj4gKwo+ ICsJcmV0dXJuIGZkOwo+ICt9Cj4gKwo+ICtzdHJ1Y3QgZG1hX2J1ZiogaHlwZXJfZG1hYnVmX2V4 cG9ydF9kbWFfYnVmKHN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKmRpbmZv KQo+ICt7Cj4gKwlERUZJTkVfRE1BX0JVRl9FWFBPUlRfSU5GTyhleHBfaW5mbyk7Cj4gKwo+ICsJ ZXhwX2luZm8ub3BzID0gJmh5cGVyX2RtYWJ1Zl9vcHM7Cj4gKwlleHBfaW5mby5zaXplID0gZGlu Zm8tPnNndC0+bmVudHMgKiBQQUdFX1NJWkU7IC8qIG11bHRpcGxlIG9mIFBBR0VfU0laRSwgbm90 IGNvbnNpZGVyaW5nIG9mZnNldCAqLwo+ICsJZXhwX2luZm8uZmxhZ3MgPSAvKiBub3Qgc3VyZSBh Ym91dCBmbGFnICovMDsKPiArCWV4cF9pbmZvLnByaXYgPSBkaW5mbzsKPiArCj4gKwlyZXR1cm4g ZG1hX2J1Zl9leHBvcnQoJmV4cF9pbmZvKTsKPiArfTsKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy94 ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9pbXAuaCBiL2RyaXZlcnMveGVuL2h5cGVyX2Rt YWJ1Zi9oeXBlcl9kbWFidWZfaW1wLmgKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAw MDAwMDAuLjAwM2MxNTgKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy94ZW4vaHlwZXJf ZG1hYnVmL2h5cGVyX2RtYWJ1Zl9pbXAuaAo+IEBAIC0wLDAgKzEsMzEgQEAKPiArI2lmbmRlZiBf X0hZUEVSX0RNQUJVRl9JTVBfSF9fCj4gKyNkZWZpbmUgX19IWVBFUl9ETUFCVUZfSU1QX0hfXwo+ ICsKPiArI2luY2x1ZGUgImh5cGVyX2RtYWJ1Zl9zdHJ1Y3QuaCIKPiArCj4gKy8qIGV4dHJhY3Qg cGFnZXMgZGlyZWN0bHkgZnJvbSBzdHJ1Y3Qgc2dfdGFibGUgKi8KPiArc3RydWN0IGh5cGVyX2Rt YWJ1Zl9wYWdlc19pbmZvICpoeXBlcl9kbWFidWZfZXh0X3BncyhzdHJ1Y3Qgc2dfdGFibGUgKnNn dCk7Cj4gKwo+ICsvKiBjcmVhdGUgc2dfdGFibGUgd2l0aCBnaXZlbiBwYWdlcyBhbmQgb3RoZXIg cGFyYW1ldGVycyAqLwo+ICtzdHJ1Y3Qgc2dfdGFibGUqIGh5cGVyX2RtYWJ1Zl9jcmVhdGVfc2d0 KHN0cnVjdCBwYWdlICoqcGFnZXMsCj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg aW50IGZyc3Rfb2ZzdCwgaW50IGxhc3RfbGVuLCBpbnQgbmVudHMpOwo+ICsKPiArZ3JhbnRfcmVm X3QgaHlwZXJfZG1hYnVmX2NyZWF0ZV9ncmVmX3RhYmxlKHN0cnVjdCBwYWdlICoqcGFnZXMsIGlu dCByZG9tYWluLCBpbnQgbmVudHMsCj4gKwkJCQkJICAgc3RydWN0IGh5cGVyX2RtYWJ1Zl9zaGFy ZWRfcGFnZXNfaW5mbyAqc2hhcmVkX3BhZ2VzX2luZm8pOwo+ICsKPiAraW50IGh5cGVyX2RtYWJ1 Zl9jbGVhbnVwX2dyZWZfdGFibGUoc3RydWN0IGh5cGVyX2RtYWJ1Zl9zZ3RfaW5mbyAqc2d0X2lu Zm8pOwo+ICsKPiAraW50IGh5cGVyX2RtYWJ1Zl9jbGVhbnVwX2ltcG9ydGVkX3BhZ2VzKHN0cnVj dCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKnNndF9pbmZvKTsKPiArCj4gKy8qIG1h cCBmaXJzdCBsZXZlbCB0YWJsZXMgdGhhdCBjb250YWlucyByZWZlcmVuY2UgbnVtYmVycyBmb3Ig YWN0dWFsIHNoYXJlZCBwYWdlcyAqLwo+ICtncmFudF9yZWZfdCAqaHlwZXJfZG1hYnVmX21hcF9n cmVmX3RhYmxlKGdyYW50X3JlZl90ICpncmVmX3RhYmxlLCBpbnQgbl9wYWdlc190YWJsZSk7Cj4g Kwo+ICsvKiBtYXAgYW5kIGNvbnN0cnVjdCBzZ19saXN0cyBmcm9tIHJlZmVyZW5jZSBudW1iZXJz ICovCj4gK3N0cnVjdCBzZ190YWJsZSogaHlwZXJfZG1hYnVmX21hcF9wYWdlcyhncmFudF9yZWZf dCBncmVmLCBpbnQgZnJzdF9vZnN0LCBpbnQgbGFzdF9sZW4sIGludCBuZW50cywgaW50IHNkb21h aW4sCj4gKwkJCQkJc3RydWN0IGh5cGVyX2RtYWJ1Zl9zaGFyZWRfcGFnZXNfaW5mbyAqc2hhcmVk X3BhZ2VzX2luZm8pOwo+ICsKPiAraW50IGh5cGVyX2RtYWJ1Zl9leHBvcnRfZmQoc3RydWN0IGh5 cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqZGluZm8sIGludCBmbGFncyk7Cj4gKwo+ICtz dHJ1Y3QgZG1hX2J1ZiogaHlwZXJfZG1hYnVmX2V4cG9ydF9kbWFfYnVmKHN0cnVjdCBoeXBlcl9k bWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKmRpbmZvKTsKPiArCj4gKyNlbmRpZiAvKiBfX0hZUEVS X0RNQUJVRl9JTVBfSF9fICovCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1 Zi9oeXBlcl9kbWFidWZfaW9jdGwuYyBiL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9k bWFidWZfaW9jdGwuYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uNWU1 MDkwOAo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlw ZXJfZG1hYnVmX2lvY3RsLmMKPiBAQCAtMCwwICsxLDQ2MiBAQAo+ICsjaW5jbHVkZSA8bGludXgv a2VybmVsLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9lcnJuby5oPgo+ICsjaW5jbHVkZSA8bGludXgv bW9kdWxlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9t aXNjZGV2aWNlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC91YWNjZXNzLmg+Cj4gKyNpbmNsdWRlIDxs aW51eC9kbWEtYnVmLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9kZWxheS5oPgo+ICsjaW5jbHVkZSAi aHlwZXJfZG1hYnVmX3N0cnVjdC5oIgo+ICsjaW5jbHVkZSAiaHlwZXJfZG1hYnVmX2ltcC5oIgo+ ICsjaW5jbHVkZSAiaHlwZXJfZG1hYnVmX2xpc3QuaCIKPiArI2luY2x1ZGUgImh5cGVyX2RtYWJ1 Zl9kcnYuaCIKPiArI2luY2x1ZGUgImh5cGVyX2RtYWJ1Zl9xdWVyeS5oIgo+ICsjaW5jbHVkZSAi eGVuL2h5cGVyX2RtYWJ1Zl94ZW5fY29tbS5oIgo+ICsjaW5jbHVkZSAiaHlwZXJfZG1hYnVmX21z Zy5oIgo+ICsKPiArc3RydWN0IGh5cGVyX2RtYWJ1Zl9wcml2YXRlIHsKPiArCXN0cnVjdCBkZXZp Y2UgKmRldmljZTsKPiArfSBoeXBlcl9kbWFidWZfcHJpdmF0ZTsKPiArCj4gK3N0YXRpYyB1aW50 MzJfdCBoeXBlcl9kbWFidWZfaWRfZ2VuKHZvaWQpIHsKPiArCS8qIFRPRE86IGFkZCBwcm9wZXIg aW1wbGVtZW50YXRpb24gKi8KPiArCXN0YXRpYyB1aW50MzJfdCBpZCA9IDA7Cj4gKwlzdGF0aWMg aW50MzJfdCBkb21pZCA9IC0xOwo+ICsJaWYgKGRvbWlkID09IC0xKSB7Cj4gKwkJZG9taWQgPSBo eXBlcl9kbWFidWZfZ2V0X2RvbWlkKCk7Cj4gKwl9Cj4gKwlyZXR1cm4gSFlQRVJfRE1BQlVGX0lE X0lNUE9SVEVSKGRvbWlkLCBpZCsrKTsKPiArfQo+ICsKPiArc3RhdGljIGludCBoeXBlcl9kbWFi dWZfZXhwb3J0ZXJfcmluZ19zZXR1cCh2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3QgaW9jdGxf aHlwZXJfZG1hYnVmX2V4cG9ydGVyX3Jpbmdfc2V0dXAgKnJpbmdfYXR0cjsKPiArCWludCByZXQg PSAwOwo+ICsKPiArCWlmICghZGF0YSkgewo+ICsJCXByaW50aygidXNlciBkYXRhIGlzIE5VTExc biIpOwo+ICsJCXJldHVybiAtMTsKPiArCX0KPiArCXJpbmdfYXR0ciA9IChzdHJ1Y3QgaW9jdGxf aHlwZXJfZG1hYnVmX2V4cG9ydGVyX3Jpbmdfc2V0dXAgKilkYXRhOwo+ICsKPiArCXJldCA9IGh5 cGVyX2RtYWJ1Zl9leHBvcnRlcl9yaW5nYnVmX2luaXQocmluZ19hdHRyLT5yZW1vdGVfZG9tYWlu LAo+ICsJCQkJCQkmcmluZ19hdHRyLT5yaW5nX3JlZmlkLAo+ICsJCQkJCQkmcmluZ19hdHRyLT5w b3J0KTsKPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGh5cGVyX2Rt YWJ1Zl9pbXBvcnRlcl9yaW5nX3NldHVwKHZvaWQgKmRhdGEpCj4gK3sKPiArCXN0cnVjdCBpb2N0 bF9oeXBlcl9kbWFidWZfaW1wb3J0ZXJfcmluZ19zZXR1cCAqc2V0dXBfaW1wX3JpbmdfYXR0cjsK PiArCWludCByZXQgPSAwOwo+ICsKPiArCWlmICghZGF0YSkgewo+ICsJCXByaW50aygidXNlciBk YXRhIGlzIE5VTExcbiIpOwo+ICsJCXJldHVybiAtMTsKPiArCX0KPiArCj4gKwlzZXR1cF9pbXBf cmluZ19hdHRyID0gKHN0cnVjdCBpb2N0bF9oeXBlcl9kbWFidWZfaW1wb3J0ZXJfcmluZ19zZXR1 cCAqKWRhdGE7Cj4gKwo+ICsJLyogdXNlciBuZWVkIHRvIHByb3ZpZGUgYSBwb3J0IG51bWJlciBh bmQgcmVmICMgZm9yIHRoZSBwYWdlIHVzZWQgYXMgcmluZyBidWZmZXIgKi8KPiArCXJldCA9IGh5 cGVyX2RtYWJ1Zl9pbXBvcnRlcl9yaW5nYnVmX2luaXQoc2V0dXBfaW1wX3JpbmdfYXR0ci0+c291 cmNlX2RvbWFpbiwKPiArCQkJCQkJIHNldHVwX2ltcF9yaW5nX2F0dHItPnJpbmdfcmVmaWQsCj4g KwkJCQkJCSBzZXR1cF9pbXBfcmluZ19hdHRyLT5wb3J0KTsKPiArCj4gKwlyZXR1cm4gcmV0Owo+ ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGh5cGVyX2RtYWJ1Zl9leHBvcnRfcmVtb3RlKHZvaWQgKmRh dGEpCj4gK3sKPiArCXN0cnVjdCBpb2N0bF9oeXBlcl9kbWFidWZfZXhwb3J0X3JlbW90ZSAqZXhw b3J0X3JlbW90ZV9hdHRyOwo+ICsJc3RydWN0IGRtYV9idWYgKmRtYV9idWY7Cj4gKwlzdHJ1Y3Qg ZG1hX2J1Zl9hdHRhY2htZW50ICphdHRhY2htZW50Owo+ICsJc3RydWN0IHNnX3RhYmxlICpzZ3Q7 Cj4gKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3BhZ2VzX2luZm8gKnBhZ2VfaW5mbzsKPiArCXN0cnVj dCBoeXBlcl9kbWFidWZfc2d0X2luZm8gKnNndF9pbmZvOwo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1 Zl9yaW5nX3JxICpyZXE7Cj4gKwlpbnQgb3BlcmFuZHNbOV07Cj4gKwlpbnQgcmV0ID0gMDsKPiAr Cj4gKwlpZiAoIWRhdGEpIHsKPiArCQlwcmludGsoInVzZXIgZGF0YSBpcyBOVUxMXG4iKTsKPiAr CQlyZXR1cm4gLTE7Cj4gKwl9Cj4gKwo+ICsJZXhwb3J0X3JlbW90ZV9hdHRyID0gKHN0cnVjdCBp b2N0bF9oeXBlcl9kbWFidWZfZXhwb3J0X3JlbW90ZSAqKWRhdGE7Cj4gKwo+ICsJZG1hX2J1ZiA9 IGRtYV9idWZfZ2V0KGV4cG9ydF9yZW1vdGVfYXR0ci0+ZG1hYnVmX2ZkKTsKPiArCWlmICghZG1h X2J1Zikgewo+ICsJCXByaW50aygiQ2Fubm90IGdldCBkbWEgYnVmXG4iKTsKPiArCQlyZXR1cm4g LTE7Cj4gKwl9Cj4gKwo+ICsJYXR0YWNobWVudCA9IGRtYV9idWZfYXR0YWNoKGRtYV9idWYsIGh5 cGVyX2RtYWJ1Zl9wcml2YXRlLmRldmljZSk7Cj4gKwlpZiAoIWF0dGFjaG1lbnQpIHsKPiArCQlw cmludGsoIkNhbm5vdCBnZXQgYXR0YWNobWVudFxuIik7Cj4gKwkJcmV0dXJuIC0xOwo+ICsJfQo+ ICsKPiArCS8qIHdlIGNoZWNrIGlmIHRoaXMgc3BlY2lmaWMgYXR0YWNobWVudCB3YXMgYWxyZWFk eSBleHBvcnRlZAo+ICsJICogdG8gdGhlIHNhbWUgZG9tYWluIGFuZCBpZiB5ZXMsIGl0IHJldHVy bnMgaHlwZXJfZG1hYnVmX2lkCj4gKwkgKiBvZiBwcmUtZXhwb3J0ZWQgc2d0ICovCj4gKwlyZXQg PSBoeXBlcl9kbWFidWZfZmluZF9pZChhdHRhY2htZW50LCBleHBvcnRfcmVtb3RlX2F0dHItPnJl bW90ZV9kb21haW4pOwo+ICsJaWYgKHJldCAhPSAtMSkgewo+ICsJCWRtYV9idWZfZGV0YWNoKGRt YV9idWYsIGF0dGFjaG1lbnQpOwo+ICsJCWRtYV9idWZfcHV0KGRtYV9idWYpOwo+ICsJCWV4cG9y dF9yZW1vdGVfYXR0ci0+aHlwZXJfZG1hYnVmX2lkID0gcmV0Owo+ICsJCXJldHVybiAwOwo+ICsJ fQo+ICsJLyogQ2xlYXIgcmV0LCBhcyB0aGF0IHdpbGwgY2F1c2Ugd2hvbGUgaW9jdGwgdG8gcmV0 dXJuIGZhaWx1cmUgdG8gdXNlcnNwYWNlLCB3aGljaCBpcyBub3QgdHJ1ZSAqLwo+ICsJcmV0ID0g MDsKPiArCj4gKwlzZ3QgPSBkbWFfYnVmX21hcF9hdHRhY2htZW50KGF0dGFjaG1lbnQsIERNQV9C SURJUkVDVElPTkFMKTsKPiArCj4gKwlzZ3RfaW5mbyA9IGttYWxsb2Moc2l6ZW9mKCpzZ3RfaW5m byksIEdGUF9LRVJORUwpOwo+ICsKPiArCXNndF9pbmZvLT5oeXBlcl9kbWFidWZfaWQgPSBoeXBl cl9kbWFidWZfaWRfZ2VuKCk7Cj4gKwkvKiBUT0RPOiBXZSBtaWdodCBuZWVkIHRvIGNvbnNpZGVy IHVzaW5nIHBvcnQgbnVtYmVyIG9uIGV2ZW50IGNoYW5uZWw/ICovCj4gKwlzZ3RfaW5mby0+aHlw ZXJfZG1hYnVmX3Jkb21haW4gPSBleHBvcnRfcmVtb3RlX2F0dHItPnJlbW90ZV9kb21haW47Cj4g KwlzZ3RfaW5mby0+c2d0ID0gc2d0Owo+ICsJc2d0X2luZm8tPmF0dGFjaG1lbnQgPSBhdHRhY2ht ZW50Owo+ICsJc2d0X2luZm8tPmRtYV9idWYgPSBkbWFfYnVmOwo+ICsKPiArCXBhZ2VfaW5mbyA9 IGh5cGVyX2RtYWJ1Zl9leHRfcGdzKHNndCk7Cj4gKwlpZiAocGFnZV9pbmZvID09IE5VTEwpCj4g KwkJZ290byBmYWlsX2V4cG9ydDsKPiArCj4gKwkvKiBub3cgcmVnaXN0ZXIgaXQgdG8gZXhwb3J0 IGxpc3QgKi8KPiArCWh5cGVyX2RtYWJ1Zl9yZWdpc3Rlcl9leHBvcnRlZChzZ3RfaW5mbyk7Cj4g Kwo+ICsJcGFnZV9pbmZvLT5oeXBlcl9kbWFidWZfcmRvbWFpbiA9IHNndF9pbmZvLT5oeXBlcl9k bWFidWZfcmRvbWFpbjsKPiArCXBhZ2VfaW5mby0+aHlwZXJfZG1hYnVmX2lkID0gc2d0X2luZm8t Pmh5cGVyX2RtYWJ1Zl9pZDsgLyogbWF5IG5vdCBiZSBuZWVkZWQgKi8KPiArCj4gKwlleHBvcnRf cmVtb3RlX2F0dHItPmh5cGVyX2RtYWJ1Zl9pZCA9IHNndF9pbmZvLT5oeXBlcl9kbWFidWZfaWQ7 Cj4gKwo+ICsJLyogbm93IGNyZWF0ZSB0YWJsZSBvZiBncmVmcyBmb3Igc2hhcmVkIHBhZ2VzIGFu ZCAqLwo+ICsKPiArCS8qIG5vdyBjcmVhdGUgcmVxdWVzdCBmb3IgaW1wb3J0ZXIgdmlhIHJpbmcg Ki8KPiArCW9wZXJhbmRzWzBdID0gcGFnZV9pbmZvLT5oeXBlcl9kbWFidWZfaWQ7Cj4gKwlvcGVy YW5kc1sxXSA9IHBhZ2VfaW5mby0+bmVudHM7Cj4gKwlvcGVyYW5kc1syXSA9IHBhZ2VfaW5mby0+ ZnJzdF9vZnN0Owo+ICsJb3BlcmFuZHNbM10gPSBwYWdlX2luZm8tPmxhc3RfbGVuOwo+ICsJb3Bl cmFuZHNbNF0gPSBoeXBlcl9kbWFidWZfY3JlYXRlX2dyZWZfdGFibGUocGFnZV9pbmZvLT5wYWdl cywgZXhwb3J0X3JlbW90ZV9hdHRyLT5yZW1vdGVfZG9tYWluLAo+ICsJCQkJCQlwYWdlX2luZm8t Pm5lbnRzLCAmc2d0X2luZm8tPnNoYXJlZF9wYWdlc19pbmZvKTsKPiArCS8qIGRyaXZlci9hcHBs aWNhdGlvbiBzcGVjaWZpYyBwcml2YXRlIGluZm8sIG1heCAzMiBieXRlcyAqLwo+ICsJb3BlcmFu ZHNbNV0gPSBleHBvcnRfcmVtb3RlX2F0dHItPnByaXZhdGVbMF07Cj4gKwlvcGVyYW5kc1s2XSA9 IGV4cG9ydF9yZW1vdGVfYXR0ci0+cHJpdmF0ZVsxXTsKPiArCW9wZXJhbmRzWzddID0gZXhwb3J0 X3JlbW90ZV9hdHRyLT5wcml2YXRlWzJdOwo+ICsJb3BlcmFuZHNbOF0gPSBleHBvcnRfcmVtb3Rl X2F0dHItPnByaXZhdGVbM107Cj4gKwo+ICsJcmVxID0ga2NhbGxvYygxLCBzaXplb2YoKnJlcSks IEdGUF9LRVJORUwpOwo+ICsKPiArCS8qIGNvbXBvc2luZyBhIG1lc3NhZ2UgdG8gdGhlIGltcG9y dGVyICovCj4gKwloeXBlcl9kbWFidWZfY3JlYXRlX3JlcXVlc3QocmVxLCBIWVBFUl9ETUFCVUZf RVhQT1JULCAmb3BlcmFuZHNbMF0pOwo+ICsJaWYoaHlwZXJfZG1hYnVmX3NlbmRfcmVxdWVzdChl eHBvcnRfcmVtb3RlX2F0dHItPnJlbW90ZV9kb21haW4sIHJlcSkpCj4gKwkJZ290byBmYWlsX3Nl bmRfcmVxdWVzdDsKPiArCj4gKwkvKiBmcmVlIG1zZyAqLwo+ICsJa2ZyZWUocmVxKTsKPiArCS8q IGZyZWUgcGFnZV9pbmZvICovCj4gKwlrZnJlZShwYWdlX2luZm8pOwo+ICsKPiArCXJldHVybiBy ZXQ7Cj4gKwo+ICtmYWlsX3NlbmRfcmVxdWVzdDoKPiArCWtmcmVlKHJlcSk7Cj4gKwloeXBlcl9k bWFidWZfcmVtb3ZlX2V4cG9ydGVkKHNndF9pbmZvLT5oeXBlcl9kbWFidWZfaWQpOwo+ICsKPiAr ZmFpbF9leHBvcnQ6Cj4gKwlkbWFfYnVmX3VubWFwX2F0dGFjaG1lbnQoc2d0X2luZm8tPmF0dGFj aG1lbnQsIHNndF9pbmZvLT5zZ3QsIERNQV9CSURJUkVDVElPTkFMKTsKPiArCWRtYV9idWZfZGV0 YWNoKHNndF9pbmZvLT5kbWFfYnVmLCBzZ3RfaW5mby0+YXR0YWNobWVudCk7Cj4gKwlkbWFfYnVm X3B1dChzZ3RfaW5mby0+ZG1hX2J1Zik7Cj4gKwo+ICsJcmV0dXJuIC1FSU5WQUw7Cj4gK30KPiAr Cj4gK3N0YXRpYyBpbnQgaHlwZXJfZG1hYnVmX2V4cG9ydF9mZF9pb2N0bCh2b2lkICpkYXRhKQo+ ICt7Cj4gKwlzdHJ1Y3QgaW9jdGxfaHlwZXJfZG1hYnVmX2V4cG9ydF9mZCAqZXhwb3J0X2ZkX2F0 dHI7Cj4gKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZvICppbXBvcnRlZF9z Z3RfaW5mbzsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCWlmICghZGF0YSkgewo+ICsJCXByaW50 aygidXNlciBkYXRhIGlzIE5VTExcbiIpOwo+ICsJCXJldHVybiAtMTsKPiArCX0KPiArCj4gKwll eHBvcnRfZmRfYXR0ciA9IChzdHJ1Y3QgaW9jdGxfaHlwZXJfZG1hYnVmX2V4cG9ydF9mZCAqKWRh dGE7Cj4gKwo+ICsJLyogbG9vayBmb3IgZG1hYnVmIGZvciB0aGUgaWQgKi8KPiArCWltcG9ydGVk X3NndF9pbmZvID0gaHlwZXJfZG1hYnVmX2ZpbmRfaW1wb3J0ZWQoZXhwb3J0X2ZkX2F0dHItPmh5 cGVyX2RtYWJ1Zl9pZCk7Cj4gKwlpZiAoaW1wb3J0ZWRfc2d0X2luZm8gPT0gTlVMTCkgLyogY2Fu J3QgZmluZCBzZ3QgZnJvbSB0aGUgdGFibGUgKi8KPiArCQlyZXR1cm4gLTE7Cj4gKwo+ICsJcHJp bnRrKCIlcyBGb3VuZCBidWZmZXIgZ3JlZiAlZCAgb2ZmICVkIGxhc3QgbGVuICVkIG5lbnRzICVk IGRvbWFpbiAlZFxuIiwgX19mdW5jX18sCj4gKwkJaW1wb3J0ZWRfc2d0X2luZm8tPmdyZWYsIGlt cG9ydGVkX3NndF9pbmZvLT5mcnN0X29mc3QsCj4gKwkJaW1wb3J0ZWRfc2d0X2luZm8tPmxhc3Rf bGVuLCBpbXBvcnRlZF9zZ3RfaW5mby0+bmVudHMsCj4gKwkJSFlQRVJfRE1BQlVGX0lEX0lNUE9S VEVSX0dFVF9TRE9NQUlOX0lEKGltcG9ydGVkX3NndF9pbmZvLT5oeXBlcl9kbWFidWZfaWQpKTsK PiArCj4gKwlpbXBvcnRlZF9zZ3RfaW5mby0+c2d0ID0gaHlwZXJfZG1hYnVmX21hcF9wYWdlcyhp bXBvcnRlZF9zZ3RfaW5mby0+Z3JlZiwKPiArCQkJCQkJaW1wb3J0ZWRfc2d0X2luZm8tPmZyc3Rf b2ZzdCwKPiArCQkJCQkJaW1wb3J0ZWRfc2d0X2luZm8tPmxhc3RfbGVuLAo+ICsJCQkJCQlpbXBv cnRlZF9zZ3RfaW5mby0+bmVudHMsCj4gKwkJCQkJCUhZUEVSX0RNQUJVRl9JRF9JTVBPUlRFUl9H RVRfU0RPTUFJTl9JRChpbXBvcnRlZF9zZ3RfaW5mby0+aHlwZXJfZG1hYnVmX2lkKSwKPiArCQkJ CQkJJmltcG9ydGVkX3NndF9pbmZvLT5zaGFyZWRfcGFnZXNfaW5mbyk7Cj4gKwo+ICsJaWYgKCFp bXBvcnRlZF9zZ3RfaW5mby0+c2d0KSB7Cj4gKwkJcmV0dXJuIC0xOwo+ICsJfQo+ICsKPiArCWV4 cG9ydF9mZF9hdHRyLT5mZCA9IGh5cGVyX2RtYWJ1Zl9leHBvcnRfZmQoaW1wb3J0ZWRfc2d0X2lu Zm8sIGV4cG9ydF9mZF9hdHRyLT5mbGFncyk7Cj4gKwlpZiAoZXhwb3J0X2ZkX2F0dHIgPCAwKSB7 Cj4gKwkJcmV0ID0gZXhwb3J0X2ZkX2F0dHItPmZkOwo+ICsJfQo+ICsKPiArCXJldHVybiByZXQ7 Cj4gK30KPiArCj4gKy8qIHJlbW92aW5nIGRtYWJ1ZiBmcm9tIHRoZSBkYXRhYmFzZSBhbmQgc2Vu ZCBpbnQgcmVxIHRvIHRoZSBzb3VyY2UgZG9tYWluCj4gKyogdG8gdW5tYXAgaXQuICovCj4gK3N0 YXRpYyBpbnQgaHlwZXJfZG1hYnVmX2Rlc3Ryb3kodm9pZCAqZGF0YSkKPiArewo+ICsJc3RydWN0 IGlvY3RsX2h5cGVyX2RtYWJ1Zl9kZXN0cm95ICpkZXN0cm95X2F0dHI7Cj4gKwlzdHJ1Y3QgaHlw ZXJfZG1hYnVmX3NndF9pbmZvICpzZ3RfaW5mbzsKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZfcmlu Z19ycSAqcmVxOwo+ICsJaW50IHJldDsKPiArCj4gKwlpZiAoIWRhdGEpIHsKPiArCQlwcmludGso InVzZXIgZGF0YSBpcyBOVUxMXG4iKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4g KwlkZXN0cm95X2F0dHIgPSAoc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9kZXN0cm95ICopZGF0 YTsKPiArCj4gKwkvKiBmaW5kIGRtYWJ1ZiBpbiBleHBvcnQgbGlzdCAqLwo+ICsJc2d0X2luZm8g PSBoeXBlcl9kbWFidWZfZmluZF9leHBvcnRlZChkZXN0cm95X2F0dHItPmh5cGVyX2RtYWJ1Zl9p ZCk7Cj4gKwlpZiAoc2d0X2luZm8gPT0gTlVMTCkgeyAvKiBmYWlsZWQgdG8gZmluZCBjb3JyZXNw b25kaW5nIGVudHJ5IGluIGV4cG9ydCBsaXN0ICovCj4gKwkJZGVzdHJveV9hdHRyLT5zdGF0dXMg PSAtRUlOVkFMOwo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsJfQo+ICsKPiArCXJlcSA9IGtjYWxs b2MoMSwgc2l6ZW9mKCpyZXEpLCBHRlBfS0VSTkVMKTsKPiArCj4gKwloeXBlcl9kbWFidWZfY3Jl YXRlX3JlcXVlc3QocmVxLCBIWVBFUl9ETUFCVUZfREVTVFJPWSwgJmRlc3Ryb3lfYXR0ci0+aHlw ZXJfZG1hYnVmX2lkKTsKPiArCj4gKwkvKiBub3cgc2VuZCBkZXN0cm95IHJlcXVlc3QgdG8gcmVt b3RlIGRvbWFpbgo+ICsJICogY3VycmVudGx5IGFzc3VtaW5nIHRoZXJlJ3Mgb25seSBvbmUgaW1w b3J0ZXIgZXhpc3QgKi8KPiArCXJldCA9IGh5cGVyX2RtYWJ1Zl9zZW5kX3JlcXVlc3Qoc2d0X2lu Zm8tPmh5cGVyX2RtYWJ1Zl9yZG9tYWluLCByZXEpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlr ZnJlZShyZXEpOwo+ICsJCXJldHVybiAtRUZBVUxUOwo+ICsJfQo+ICsKPiArCS8qIGZyZWUgbXNn ICovCj4gKwlrZnJlZShyZXEpOwo+ICsJZGVzdHJveV9hdHRyLT5zdGF0dXMgPSByZXQ7Cj4gKwo+ ICsJLyogUmVzdCBvZiBjbGVhbnVwIHdpbGwgZm9sbG93IHdoZW4gaW1wb3J0ZXIgd2lsbCBmcmVl IGl0J3MgYnVmZmVyLAo+ICsJICogY3VycmVudCBpbXBsZW1lbnRhdGlvbiBhc3N1bWVzIHRoYXQg dGhlcmUgaXMgb25seSBvbmUgaW1wb3J0ZXIKPiArICAgICAgICAgKi8KPiArCj4gKwlyZXR1cm4g cmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGh5cGVyX2RtYWJ1Zl9xdWVyeSh2b2lkICpkYXRh KQo+ICt7Cj4gKwlzdHJ1Y3QgaW9jdGxfaHlwZXJfZG1hYnVmX3F1ZXJ5ICpxdWVyeV9hdHRyOwo+ ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9zZ3RfaW5mbyAqc2d0X2luZm87Cj4gKwlzdHJ1Y3QgaHlw ZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZvICppbXBvcnRlZF9zZ3RfaW5mbzsKPiArCWludCBy ZXQgPSAwOwo+ICsKPiArCWlmICghZGF0YSkgewo+ICsJCXByaW50aygidXNlciBkYXRhIGlzIE5V TExcbiIpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXF1ZXJ5X2F0dHIgPSAo c3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9xdWVyeSAqKWRhdGE7Cj4gKwo+ICsJc2d0X2luZm8g PSBoeXBlcl9kbWFidWZfZmluZF9leHBvcnRlZChxdWVyeV9hdHRyLT5oeXBlcl9kbWFidWZfaWQp Owo+ICsJaW1wb3J0ZWRfc2d0X2luZm8gPSBoeXBlcl9kbWFidWZfZmluZF9pbXBvcnRlZChxdWVy eV9hdHRyLT5oeXBlcl9kbWFidWZfaWQpOwo+ICsKPiArCS8qIGlmIGRtYWJ1ZiBjYW4ndCBiZSBm b3VuZCBpbiBib3RoIGxpc3RzLCByZXR1cm4gKi8KPiArCWlmICghKHNndF9pbmZvICYmIGltcG9y dGVkX3NndF9pbmZvKSkgewo+ICsJCXByaW50aygiY2FuJ3QgZmluZCBlbnRyeSBhbnl3aGVyZVxu Iik7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJLyogbm90IGNvbnNpZGVyaW5n IHRoZSBjYXNlIHdoZXJlIGEgZG1hYnVmIGlzIGZvdW5kIG9uIGJvdGggcXVldWVzCj4gKwkgKiBp biBvbmUgZG9tYWluICovCj4gKwlzd2l0Y2ggKHF1ZXJ5X2F0dHItPml0ZW0pCj4gKwl7Cj4gKwkJ Y2FzZSBETUFCVUZfUVVFUllfVFlQRV9MSVNUOgo+ICsJCQlpZiAoc2d0X2luZm8pIHsKPiArCQkJ CXF1ZXJ5X2F0dHItPmluZm8gPSBFWFBPUlRFRDsKPiArCQkJfSBlbHNlIHsKPiArCQkJCXF1ZXJ5 X2F0dHItPmluZm8gPSBJTVBPUlRFRDsKPiArCQkJfQo+ICsJCQlicmVhazsKPiArCj4gKwkJLyog ZXhwb3J0aW5nIGRvbWFpbiBvZiB0aGlzIHNwZWNpZmljIGRtYWJ1ZiovCj4gKwkJY2FzZSBETUFC VUZfUVVFUllfRVhQT1JURVI6Cj4gKwkJCWlmIChzZ3RfaW5mbykgewo+ICsJCQkJcXVlcnlfYXR0 ci0+aW5mbyA9IDB4RkZGRkZGRkY7IC8qIG15c2VsZiAqLwo+ICsJCQl9IGVsc2Ugewo+ICsJCQkJ cXVlcnlfYXR0ci0+aW5mbyA9IChIWVBFUl9ETUFCVUZfSURfSU1QT1JURVJfR0VUX1NET01BSU5f SUQoaW1wb3J0ZWRfc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZCkpOwo+ICsJCQl9Cj4gKwkJCWJy ZWFrOwo+ICsKPiArCQkvKiBpbXBvcnRpbmcgZG9tYWluIG9mIHRoaXMgc3BlY2lmaWMgZG1hYnVm ICovCj4gKwkJY2FzZSBETUFCVUZfUVVFUllfSU1QT1JURVI6Cj4gKwkJCWlmIChzZ3RfaW5mbykg ewo+ICsJCQkJcXVlcnlfYXR0ci0+aW5mbyA9IHNndF9pbmZvLT5oeXBlcl9kbWFidWZfcmRvbWFp bjsKPiArCQkJfSBlbHNlIHsKPiArI2lmIDAgLyogVE9ETzogYSBnbG9iYWwgdmFyaWFibGUsIGN1 cnJlbnRfZG9tYWluIGRvZXMgbm90IGV4aXN0IHlldCovCj4gKwkJCQlxdWVyeV9hdHRyLT5pbmZv ID0gY3VycmVudF9kb21haW47Cj4gKyNlbmRpZgo+ICsJCQl9Cj4gKwkJCWJyZWFrOwo+ICsKPiAr CQkvKiBzaXplIG9mIGRtYWJ1ZiBpbiBieXRlICovCj4gKwkJY2FzZSBETUFCVUZfUVVFUllfU0la RToKPiArCQkJaWYgKHNndF9pbmZvKSB7Cj4gKyNpZiAwIC8qIFRPRE86IGh5cGVyX2RtYWJ1Zl9i dWZfc2l6ZSBpcyBub3QgaW1wbGVtZW50ZWQgeWV0ICovCj4gKwkJCQlxdWVyeV9hdHRyLT5pbmZv ID0gaHlwZXJfZG1hYnVmX2J1Zl9zaXplKHNndF9pbmZvLT5zZ3QpOwo+ICsjZW5kaWYKPiArCQkJ fSBlbHNlIHsKPiArCQkJCXF1ZXJ5X2F0dHItPmluZm8gPSBpbXBvcnRlZF9zZ3RfaW5mby0+bmVu dHMgKiA0MDk2IC0KPiArCQkJCQkJICAgaW1wb3J0ZWRfc2d0X2luZm8tPmZyc3Rfb2ZzdCAtIDQw OTYgKwo+ICsJCQkJCQkgICBpbXBvcnRlZF9zZ3RfaW5mby0+bGFzdF9sZW47Cj4gKwkJCX0KPiAr CQkJYnJlYWs7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGlu dCBoeXBlcl9kbWFidWZfcmVtb3RlX2V4cG9ydGVyX3Jpbmdfc2V0dXAodm9pZCAqZGF0YSkKPiAr ewo+ICsJc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9yZW1vdGVfZXhwb3J0ZXJfcmluZ19zZXR1 cCAqcmVtb3RlX2V4cG9ydGVyX3Jpbmdfc2V0dXA7Cj4gKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3Jp bmdfcnEgKnJlcTsKPiArCj4gKwlyZW1vdGVfZXhwb3J0ZXJfcmluZ19zZXR1cCA9IChzdHJ1Y3Qg aW9jdGxfaHlwZXJfZG1hYnVmX3JlbW90ZV9leHBvcnRlcl9yaW5nX3NldHVwICopZGF0YTsKPiAr Cj4gKwlyZXEgPSBrY2FsbG9jKDEsIHNpemVvZigqcmVxKSwgR0ZQX0tFUk5FTCk7Cj4gKwloeXBl cl9kbWFidWZfY3JlYXRlX3JlcXVlc3QocmVxLCBIWVBFUl9ETUFCVUZfRVhQT1JURVJfUklOR19T RVRVUCwgTlVMTCk7Cj4gKwo+ICsJLyogcmVxdWVzdGluZyByZW1vdGUgZG9tYWluIHRvIHNldC11 cCBleHBvcnRlcidzIHJpbmcgKi8KPiArCWlmKGh5cGVyX2RtYWJ1Zl9zZW5kX3JlcXVlc3QocmVt b3RlX2V4cG9ydGVyX3Jpbmdfc2V0dXAtPnJkb21haW4sIHJlcSkgPCAwKSB7Cj4gKwkJa2ZyZWUo cmVxKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlrZnJlZShyZXEpOwo+ICsJ cmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgaHlwZXJfZG1hYnVmX2lv Y3RsX2Rlc2MgaHlwZXJfZG1hYnVmX2lvY3Rsc1tdID0gewo+ICsJSFlQRVJfRE1BQlVGX0lPQ1RM X0RFRihJT0NUTF9IWVBFUl9ETUFCVUZfRVhQT1JURVJfUklOR19TRVRVUCwgaHlwZXJfZG1hYnVm X2V4cG9ydGVyX3Jpbmdfc2V0dXAsIDApLAo+ICsJSFlQRVJfRE1BQlVGX0lPQ1RMX0RFRihJT0NU TF9IWVBFUl9ETUFCVUZfSU1QT1JURVJfUklOR19TRVRVUCwgaHlwZXJfZG1hYnVmX2ltcG9ydGVy X3Jpbmdfc2V0dXAsIDApLAo+ICsJSFlQRVJfRE1BQlVGX0lPQ1RMX0RFRihJT0NUTF9IWVBFUl9E TUFCVUZfRVhQT1JUX1JFTU9URSwgaHlwZXJfZG1hYnVmX2V4cG9ydF9yZW1vdGUsIDApLAo+ICsJ SFlQRVJfRE1BQlVGX0lPQ1RMX0RFRihJT0NUTF9IWVBFUl9ETUFCVUZfRVhQT1JUX0ZELCBoeXBl cl9kbWFidWZfZXhwb3J0X2ZkX2lvY3RsLCAwKSwKPiArCUhZUEVSX0RNQUJVRl9JT0NUTF9ERUYo SU9DVExfSFlQRVJfRE1BQlVGX0RFU1RST1ksIGh5cGVyX2RtYWJ1Zl9kZXN0cm95LCAwKSwKPiAr CUhZUEVSX0RNQUJVRl9JT0NUTF9ERUYoSU9DVExfSFlQRVJfRE1BQlVGX1FVRVJZLCBoeXBlcl9k bWFidWZfcXVlcnksIDApLAo+ICsJSFlQRVJfRE1BQlVGX0lPQ1RMX0RFRihJT0NUTF9IWVBFUl9E TUFCVUZfUkVNT1RFX0VYUE9SVEVSX1JJTkdfU0VUVVAsIGh5cGVyX2RtYWJ1Zl9yZW1vdGVfZXhw b3J0ZXJfcmluZ19zZXR1cCwgMCksCj4gK307Cj4gKwo+ICtzdGF0aWMgbG9uZyBoeXBlcl9kbWFi dWZfaW9jdGwoc3RydWN0IGZpbGUgKmZpbHAsCj4gKwkJCXVuc2lnbmVkIGludCBjbWQsIHVuc2ln bmVkIGxvbmcgcGFyYW0pCj4gK3sKPiArCWNvbnN0IHN0cnVjdCBoeXBlcl9kbWFidWZfaW9jdGxf ZGVzYyAqaW9jdGwgPSBOVUxMOwo+ICsJdW5zaWduZWQgaW50IG5yID0gX0lPQ19OUihjbWQpOwo+ ICsJaW50IHJldCA9IC1FSU5WQUw7Cj4gKwloeXBlcl9kbWFidWZfaW9jdGxfdCBmdW5jOwo+ICsJ Y2hhciAqa2RhdGE7Cj4gKwo+ICsJaW9jdGwgPSAmaHlwZXJfZG1hYnVmX2lvY3Rsc1tucl07Cj4g Kwo+ICsJZnVuYyA9IGlvY3RsLT5mdW5jOwo+ICsKPiArCWlmICh1bmxpa2VseSghZnVuYykpIHsK PiArCQlwcmludGsoIm5vIGZ1bmN0aW9uXG4iKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0K PiArCj4gKwlrZGF0YSA9IGttYWxsb2MoX0lPQ19TSVpFKGNtZCksIEdGUF9LRVJORUwpOwo+ICsJ aWYgKCFrZGF0YSkgewo+ICsJCXByaW50aygibm8gbWVtb3J5XG4iKTsKPiArCQlyZXR1cm4gLUVO T01FTTsKPiArCX0KPiArCj4gKwlpZiAoY29weV9mcm9tX3VzZXIoa2RhdGEsICh2b2lkIF9fdXNl ciAqKXBhcmFtLCBfSU9DX1NJWkUoY21kKSkgIT0gMCkgewo+ICsJCXByaW50aygiZmFpbGVkIHRv IGNvcHkgZnJvbSB1c2VyIGFyZ3VtZW50c1xuIik7Cj4gKwkJcmV0dXJuIC1FRkFVTFQ7Cj4gKwl9 Cj4gKwo+ICsJcmV0ID0gZnVuYyhrZGF0YSk7Cj4gKwo+ICsJaWYgKGNvcHlfdG9fdXNlcigodm9p ZCBfX3VzZXIgKilwYXJhbSwga2RhdGEsIF9JT0NfU0laRShjbWQpKSAhPSAwKSB7Cj4gKwkJcHJp bnRrKCJmYWlsZWQgdG8gY29weSB0byB1c2VyIGFyZ3VtZW50c1xuIik7Cj4gKwkJcmV0dXJuIC1F RkFVTFQ7Cj4gKwl9Cj4gKwo+ICsJa2ZyZWUoa2RhdGEpOwo+ICsKPiArCXJldHVybiByZXQ7Cj4g K30KPiArCj4gK3N0cnVjdCBkZXZpY2VfaW5mbyB7Cj4gKwlpbnQgY3Vycl9kb21haW47Cj4gK307 Cj4gKwo+ICsvKj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki8KPiArc3Rh dGljIHN0cnVjdCBmaWxlX29wZXJhdGlvbnMgaHlwZXJfZG1hYnVmX2RyaXZlcl9mb3BzID0KPiAr ewo+ICsgICAub3duZXIgPSBUSElTX01PRFVMRSwKPiArICAgLnVubG9ja2VkX2lvY3RsID0gaHlw ZXJfZG1hYnVmX2lvY3RsLAo+ICt9Owo+ICsKPiArc3RhdGljIHN0cnVjdCBtaXNjZGV2aWNlIGh5 cGVyX2RtYWJ1Zl9taXNjZGV2ID0gewo+ICsJLm1pbm9yID0gTUlTQ19EWU5BTUlDX01JTk9SLAo+ ICsJLm5hbWUgPSAieGVuL2h5cGVyX2RtYWJ1ZiIsCj4gKwkuZm9wcyA9ICZoeXBlcl9kbWFidWZf ZHJpdmVyX2ZvcHMsCj4gK307Cj4gKwo+ICtzdGF0aWMgY29uc3QgY2hhciBkZXZpY2VfbmFtZVtd ID0gImh5cGVyX2RtYWJ1ZiI7Cj4gKwo+ICsvKj09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09Ki8KPiAraW50IHJlZ2lzdGVyX2RldmljZSh2b2lkKQo+ICt7Cj4gKwlpbnQgcmVz dWx0ID0gMDsKPiArCj4gKwlyZXN1bHQgPSBtaXNjX3JlZ2lzdGVyKCZoeXBlcl9kbWFidWZfbWlz Y2Rldik7Cj4gKwo+ICsJaWYgKHJlc3VsdCAhPSAwKSB7Cj4gKwkJcHJpbnRrKEtFUk5fV0FSTklO RyAiaHlwZXJfZG1hYnVmOiBkcml2ZXIgY2FuJ3QgYmUgcmVnaXN0ZXJlZFxuIik7Cj4gKwkJcmV0 dXJuIHJlc3VsdDsKPiArCX0KPiArCj4gKwloeXBlcl9kbWFidWZfcHJpdmF0ZS5kZXZpY2UgPSBo eXBlcl9kbWFidWZfbWlzY2Rldi50aGlzX2RldmljZTsKPiArCj4gKwkvKiBUT0RPOiBDaGVjayBp ZiB0aGVyZSBpcyBhIGRpZmZlcmVudCB3YXkgdG8gaW5pdGlhbGl6ZSBkbWEgbWFzayBuaWNlbHkg Ki8KPiArCWRtYV9jb2VyY2VfbWFza19hbmRfY29oZXJlbnQoaHlwZXJfZG1hYnVmX3ByaXZhdGUu ZGV2aWNlLCAweEZGRkZGRkZGKTsKPiArCj4gKwkvKiBUT0RPIGZpbmQgYSB3YXkgdG8gcHJvdmlk ZSBwYXJhbWV0ZXJzIGZvciBiZWxvdyBmdW5jdGlvbiBvciBtb3ZlIHRoYXQgdG8gaW9jdGwgKi8K PiArLyoJZXJyID0gYmluZF9pbnRlcmRvbWFpbl9ldnRjaG5fdG9faXJxaGFuZGxlcihyZG9tYWlu LCBldnRjaG4sCj4gKwkJCQlzcmNfc2lua19pc3IsIFBPUlRfTlVNLCAicmVtb3RlX2RvbWFpbiIs ICZpbmZvKTsKPiArCWlmIChlcnIgPCAwKSB7Cj4gKwkJcHJpbnRrKCJoeXBlcl9kbWFidWY6IGNh bid0IHJlZ2lzdGVyIGludGVycnVwdCBoYW5kbGVyc1xuIik7Cj4gKwkJcmV0dXJuIC1FRkFVTFQ7 Cj4gKwl9Cj4gKwo+ICsJaW5mby5pcnEgPSBlcnI7Cj4gKyovCj4gKwlyZXR1cm4gcmVzdWx0Owo+ ICt9Cj4gKwo+ICsvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KPiAr dm9pZCB1bnJlZ2lzdGVyX2RldmljZSh2b2lkKQo+ICt7Cj4gKwlwcmludGsoIEtFUk5fTk9USUNF ICJoeXBlcl9kbWFidWY6IHVucmVnaXN0ZXJfZGV2aWNlKCkgaXMgY2FsbGVkIiApOwo+ICsJbWlz Y19kZXJlZ2lzdGVyKCZoeXBlcl9kbWFidWZfbWlzY2Rldik7Cj4gK30KPiBkaWZmIC0tZ2l0IGEv ZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9saXN0LmMgYi9kcml2ZXJzL3hl bi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2xpc3QuYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0 Cj4gaW5kZXggMDAwMDAwMC4uNzdhN2U2NQo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJz L3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2xpc3QuYwo+IEBAIC0wLDAgKzEsMTE5IEBA Cj4gKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2Vycm5vLmg+ Cj4gKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4K PiArI2luY2x1ZGUgPGxpbnV4L2NkZXYuaD4KPiArI2luY2x1ZGUgPGFzbS91YWNjZXNzLmg+Cj4g KyNpbmNsdWRlIDxsaW51eC9oYXNodGFibGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2RtYS1idWYu aD4KPiArI2luY2x1ZGUgImh5cGVyX2RtYWJ1Zl9saXN0LmgiCj4gKwo+ICtERUNMQVJFX0hBU0hU QUJMRShoeXBlcl9kbWFidWZfaGFzaF9pbXBvcnRlZCwgTUFYX0VOVFJZX0lNUE9SVEVEKTsKPiAr REVDTEFSRV9IQVNIVEFCTEUoaHlwZXJfZG1hYnVmX2hhc2hfZXhwb3J0ZWQsIE1BWF9FTlRSWV9F WFBPUlRFRCk7Cj4gKwo+ICtpbnQgaHlwZXJfZG1hYnVmX3RhYmxlX2luaXQoKQo+ICt7Cj4gKwlo YXNoX2luaXQoaHlwZXJfZG1hYnVmX2hhc2hfaW1wb3J0ZWQpOwo+ICsJaGFzaF9pbml0KGh5cGVy X2RtYWJ1Zl9oYXNoX2V4cG9ydGVkKTsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtpbnQgaHlw ZXJfZG1hYnVmX3RhYmxlX2Rlc3Ryb3koKQo+ICt7Cj4gKwkvKiBUT0RPOiBjbGVhbnVwIGh5cGVy X2RtYWJ1Zl9oYXNoX2ltcG9ydGVkIGFuZCBoeXBlcl9kbWFidWZfaGFzaF9leHBvcnRlZCAqLwo+ ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK2ludCBoeXBlcl9kbWFidWZfcmVnaXN0ZXJfZXhwb3J0 ZWQoc3RydWN0IGh5cGVyX2RtYWJ1Zl9zZ3RfaW5mbyAqaW5mbykKPiArewo+ICsJc3RydWN0IGh5 cGVyX2RtYWJ1Zl9pbmZvX2VudHJ5X2V4cG9ydGVkICppbmZvX2VudHJ5Owo+ICsKPiArCWluZm9f ZW50cnkgPSBrbWFsbG9jKHNpemVvZigqaW5mb19lbnRyeSksIEdGUF9LRVJORUwpOwo+ICsKPiAr CWluZm9fZW50cnktPmluZm8gPSBpbmZvOwo+ICsKPiArCWhhc2hfYWRkKGh5cGVyX2RtYWJ1Zl9o YXNoX2V4cG9ydGVkLCAmaW5mb19lbnRyeS0+bm9kZSwKPiArCQlpbmZvX2VudHJ5LT5pbmZvLT5o eXBlcl9kbWFidWZfaWQpOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtpbnQgaHlwZXJf ZG1hYnVmX3JlZ2lzdGVyX2ltcG9ydGVkKHN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0 X2luZm8qIGluZm8pCj4gK3sKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZfaW5mb19lbnRyeV9pbXBv cnRlZCAqaW5mb19lbnRyeTsKPiArCj4gKwlpbmZvX2VudHJ5ID0ga21hbGxvYyhzaXplb2YoKmlu Zm9fZW50cnkpLCBHRlBfS0VSTkVMKTsKPiArCj4gKwlpbmZvX2VudHJ5LT5pbmZvID0gaW5mbzsK PiArCj4gKwloYXNoX2FkZChoeXBlcl9kbWFidWZfaGFzaF9pbXBvcnRlZCwgJmluZm9fZW50cnkt Pm5vZGUsCj4gKwkJaW5mb19lbnRyeS0+aW5mby0+aHlwZXJfZG1hYnVmX2lkKTsKPiArCj4gKwly ZXR1cm4gMDsKPiArfQo+ICsKPiArc3RydWN0IGh5cGVyX2RtYWJ1Zl9zZ3RfaW5mbyAqaHlwZXJf ZG1hYnVmX2ZpbmRfZXhwb3J0ZWQoaW50IGlkKQo+ICt7Cj4gKwlzdHJ1Y3QgaHlwZXJfZG1hYnVm X2luZm9fZW50cnlfZXhwb3J0ZWQgKmluZm9fZW50cnk7Cj4gKwlpbnQgYmt0Owo+ICsKPiArCWhh c2hfZm9yX2VhY2goaHlwZXJfZG1hYnVmX2hhc2hfZXhwb3J0ZWQsIGJrdCwgaW5mb19lbnRyeSwg bm9kZSkKPiArCQlpZihpbmZvX2VudHJ5LT5pbmZvLT5oeXBlcl9kbWFidWZfaWQgPT0gaWQpCj4g KwkJCXJldHVybiBpbmZvX2VudHJ5LT5pbmZvOwo+ICsKPiArCXJldHVybiBOVUxMOwo+ICt9Cj4g Kwo+ICsvKiBzZWFyY2ggZm9yIHByZS1leHBvcnRlZCBzZ3QgYW5kIHJldHVybiBpZCBvZiBpdCBp ZiBpdCBleGlzdCAqLwo+ICtpbnQgaHlwZXJfZG1hYnVmX2ZpbmRfaWQoc3RydWN0IGRtYV9idWZf YXR0YWNobWVudCAqYXR0YWNoLCBpbnQgZG9taWQpCj4gK3sKPiArCXN0cnVjdCBoeXBlcl9kbWFi dWZfaW5mb19lbnRyeV9leHBvcnRlZCAqaW5mb19lbnRyeTsKPiArCWludCBia3Q7Cj4gKwo+ICsJ aGFzaF9mb3JfZWFjaChoeXBlcl9kbWFidWZfaGFzaF9leHBvcnRlZCwgYmt0LCBpbmZvX2VudHJ5 LCBub2RlKQo+ICsJCWlmKGluZm9fZW50cnktPmluZm8tPmF0dGFjaG1lbnQgPT0gYXR0YWNoICYm Cj4gKwkJCWluZm9fZW50cnktPmluZm8tPmh5cGVyX2RtYWJ1Zl9yZG9tYWluID09IGRvbWlkKQo+ ICsJCQlyZXR1cm4gaW5mb19lbnRyeS0+aW5mby0+aHlwZXJfZG1hYnVmX2lkOwo+ICsKPiArCXJl dHVybiAtMTsKPiArfQo+ICsKPiArc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5m byAqaHlwZXJfZG1hYnVmX2ZpbmRfaW1wb3J0ZWQoaW50IGlkKQo+ICt7Cj4gKwlzdHJ1Y3QgaHlw ZXJfZG1hYnVmX2luZm9fZW50cnlfaW1wb3J0ZWQgKmluZm9fZW50cnk7Cj4gKwlpbnQgYmt0Owo+ ICsKPiArCWhhc2hfZm9yX2VhY2goaHlwZXJfZG1hYnVmX2hhc2hfaW1wb3J0ZWQsIGJrdCwgaW5m b19lbnRyeSwgbm9kZSkKPiArCQlpZihpbmZvX2VudHJ5LT5pbmZvLT5oeXBlcl9kbWFidWZfaWQg PT0gaWQpCj4gKwkJCXJldHVybiBpbmZvX2VudHJ5LT5pbmZvOwo+ICsKPiArCXJldHVybiBOVUxM Owo+ICt9Cj4gKwo+ICtpbnQgaHlwZXJfZG1hYnVmX3JlbW92ZV9leHBvcnRlZChpbnQgaWQpCj4g K3sKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZfaW5mb19lbnRyeV9leHBvcnRlZCAqaW5mb19lbnRy eTsKPiArCWludCBia3Q7Cj4gKwo+ICsJaGFzaF9mb3JfZWFjaChoeXBlcl9kbWFidWZfaGFzaF9l eHBvcnRlZCwgYmt0LCBpbmZvX2VudHJ5LCBub2RlKQo+ICsJCWlmKGluZm9fZW50cnktPmluZm8t Pmh5cGVyX2RtYWJ1Zl9pZCA9PSBpZCkgewo+ICsJCQloYXNoX2RlbCgmaW5mb19lbnRyeS0+bm9k ZSk7Cj4gKwkJCXJldHVybiAwOwo+ICsJCX0KPiArCj4gKwlyZXR1cm4gLTE7Cj4gK30KPiArCj4g K2ludCBoeXBlcl9kbWFidWZfcmVtb3ZlX2ltcG9ydGVkKGludCBpZCkKPiArewo+ICsJc3RydWN0 IGh5cGVyX2RtYWJ1Zl9pbmZvX2VudHJ5X2ltcG9ydGVkICppbmZvX2VudHJ5Owo+ICsJaW50IGJr dDsKPiArCj4gKwloYXNoX2Zvcl9lYWNoKGh5cGVyX2RtYWJ1Zl9oYXNoX2ltcG9ydGVkLCBia3Qs IGluZm9fZW50cnksIG5vZGUpCj4gKwkJaWYoaW5mb19lbnRyeS0+aW5mby0+aHlwZXJfZG1hYnVm X2lkID09IGlkKSB7Cj4gKwkJCWhhc2hfZGVsKCZpbmZvX2VudHJ5LT5ub2RlKTsKPiArCQkJcmV0 dXJuIDA7Cj4gKwkJfQo+ICsKPiArCXJldHVybiAtMTsKPiArfQo+IGRpZmYgLS1naXQgYS9kcml2 ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2xpc3QuaCBiL2RyaXZlcnMveGVuL2h5 cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfbGlzdC5oCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBp bmRleCAwMDAwMDAwLi44NjljZDlhCj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMveGVu L2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfbGlzdC5oCj4gQEAgLTAsMCArMSw0MCBAQAo+ICsj aWZuZGVmIF9fSFlQRVJfRE1BQlVGX0xJU1RfSF9fCj4gKyNkZWZpbmUgX19IWVBFUl9ETUFCVUZf TElTVF9IX18KPiArCj4gKyNpbmNsdWRlICJoeXBlcl9kbWFidWZfc3RydWN0LmgiCj4gKwo+ICsv KiBudW1iZXIgb2YgYml0cyB0byBiZSB1c2VkIGZvciBleHBvcnRlZCBkbWFidWZzIGhhc2ggdGFi bGUgKi8KPiArI2RlZmluZSBNQVhfRU5UUllfRVhQT1JURUQgNwo+ICsvKiBudW1iZXIgb2YgYml0 cyB0byBiZSB1c2VkIGZvciBpbXBvcnRlZCBkbWFidWZzIGhhc2ggdGFibGUgKi8KPiArI2RlZmlu ZSBNQVhfRU5UUllfSU1QT1JURUQgNwo+ICsKPiArc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbmZvX2Vu dHJ5X2V4cG9ydGVkIHsKPiArICAgICAgICBzdHJ1Y3QgaHlwZXJfZG1hYnVmX3NndF9pbmZvICpp bmZvOwo+ICsgICAgICAgIHN0cnVjdCBobGlzdF9ub2RlIG5vZGU7Cj4gK307Cj4gKwo+ICtzdHJ1 Y3QgaHlwZXJfZG1hYnVmX2luZm9fZW50cnlfaW1wb3J0ZWQgewo+ICsgICAgICAgIHN0cnVjdCBo eXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKmluZm87Cj4gKyAgICAgICAgc3RydWN0IGhs aXN0X25vZGUgbm9kZTsKPiArfTsKPiArCj4gK2ludCBoeXBlcl9kbWFidWZfdGFibGVfaW5pdCh2 b2lkKTsKPiArCj4gK2ludCBoeXBlcl9kbWFidWZfdGFibGVfZGVzdHJveSh2b2lkKTsKPiArCj4g K2ludCBoeXBlcl9kbWFidWZfcmVnaXN0ZXJfZXhwb3J0ZWQoc3RydWN0IGh5cGVyX2RtYWJ1Zl9z Z3RfaW5mbyAqaW5mbyk7Cj4gKwo+ICsvKiBzZWFyY2ggZm9yIHByZS1leHBvcnRlZCBzZ3QgYW5k IHJldHVybiBpZCBvZiBpdCBpZiBpdCBleGlzdCAqLwo+ICtpbnQgaHlwZXJfZG1hYnVmX2ZpbmRf aWQoc3RydWN0IGRtYV9idWZfYXR0YWNobWVudCAqYXR0YWNoLCBpbnQgZG9taWQpOwo+ICsKPiAr aW50IGh5cGVyX2RtYWJ1Zl9yZWdpc3Rlcl9pbXBvcnRlZChzdHJ1Y3QgaHlwZXJfZG1hYnVmX2lt cG9ydGVkX3NndF9pbmZvKiBpbmZvKTsKPiArCj4gK3N0cnVjdCBoeXBlcl9kbWFidWZfc2d0X2lu Zm8gKmh5cGVyX2RtYWJ1Zl9maW5kX2V4cG9ydGVkKGludCBpZCk7Cj4gKwo+ICtzdHJ1Y3QgaHlw ZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZvICpoeXBlcl9kbWFidWZfZmluZF9pbXBvcnRlZChp bnQgaWQpOwo+ICsKPiAraW50IGh5cGVyX2RtYWJ1Zl9yZW1vdmVfZXhwb3J0ZWQoaW50IGlkKTsK PiArCj4gK2ludCBoeXBlcl9kbWFidWZfcmVtb3ZlX2ltcG9ydGVkKGludCBpZCk7Cj4gKwo+ICsj ZW5kaWYgLy8gX19IWVBFUl9ETUFCVUZfTElTVF9IX18KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy94 ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9tc2cuYyBiL2RyaXZlcnMveGVuL2h5cGVyX2Rt YWJ1Zi9oeXBlcl9kbWFidWZfbXNnLmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAw MDAwMDAuLjMyMzdlNTAKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy94ZW4vaHlwZXJf ZG1hYnVmL2h5cGVyX2RtYWJ1Zl9tc2cuYwo+IEBAIC0wLDAgKzEsMjEyIEBACj4gKyNpbmNsdWRl IDxsaW51eC9rZXJuZWwuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2Vycm5vLmg+Cj4gKyNpbmNsdWRl IDxsaW51eC9tb2R1bGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KPiArI2luY2x1ZGUg PGxpbnV4L2RtYS1idWYuaD4KPiArI2luY2x1ZGUgImh5cGVyX2RtYWJ1Zl9pbXAuaCIKPiArLy8j aW5jbHVkZSAiaHlwZXJfZG1hYnVmX3JlbW90ZV9zeW5jLmgiCj4gKyNpbmNsdWRlICJ4ZW4vaHlw ZXJfZG1hYnVmX3hlbl9jb21tLmgiCj4gKyNpbmNsdWRlICJoeXBlcl9kbWFidWZfbXNnLmgiCj4g KyNpbmNsdWRlICJoeXBlcl9kbWFidWZfbGlzdC5oIgo+ICsKPiArdm9pZCBoeXBlcl9kbWFidWZf Y3JlYXRlX3JlcXVlc3Qoc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX3JxICpyZXF1ZXN0LAo+ICsJ CQkJICAgICAgICBlbnVtIGh5cGVyX2RtYWJ1Zl9jb21tYW5kIGNvbW1hbmQsIGludCAqb3BlcmFu ZHMpCj4gK3sKPiArCWludCBpOwo+ICsKPiArCXJlcXVlc3QtPnJlcXVlc3RfaWQgPSBoeXBlcl9k bWFidWZfbmV4dF9yZXFfaWRfZXhwb3J0KCk7Cj4gKwlyZXF1ZXN0LT5zdGF0dXMgPSBIWVBFUl9E TUFCVUZfUkVRX05PVF9SRVNQT05ERUQ7Cj4gKwlyZXF1ZXN0LT5jb21tYW5kID0gY29tbWFuZDsK PiArCj4gKwlzd2l0Y2goY29tbWFuZCkgewo+ICsJLyogYXMgZXhwb3J0ZXIsIGNvbW1hbmRzIHRv IGltcG9ydGVyICovCj4gKwljYXNlIEhZUEVSX0RNQUJVRl9FWFBPUlQ6Cj4gKwkJLyogZXhwb3J0 aW5nIHBhZ2VzIGZvciBkbWFidWYgKi8KPiArCQkvKiBjb21tYW5kIDogSFlQRVJfRE1BQlVGX0VY UE9SVCwKPiArCQkgKiBvcGVyYW5kczAgOiBoeXBlcl9kbWFidWZfaWQKPiArCQkgKiBvcGVyYW5k czEgOiBudW1iZXIgb2YgcGFnZXMgdG8gYmUgc2hhcmVkCj4gKwkJICogb3BlcmFuZHMyIDogb2Zm c2V0IG9mIGRhdGEgaW4gdGhlIGZpcnN0IHBhZ2UKPiArCQkgKiBvcGVyYW5kczMgOiBsZW5ndGgg b2YgZGF0YSBpbiB0aGUgbGFzdCBwYWdlCj4gKwkJICogb3BlcmFuZHM0IDogdG9wLWxldmVsIHJl ZmVyZW5jZSBudW1iZXIgZm9yIHNoYXJlZCBwYWdlcwo+ICsJCSAqIG9wZXJhbmRzNX44IDogRHJp dmVyLXNwZWNpZmljIHByaXZhdGUgZGF0YSAoZS5nLiBncmFwaGljIGJ1ZmZlcidzIG1ldGEgaW5m bykKPiArCQkgKi8KPiArCQlmb3IgKGk9MDsgaSA8IDg7IGkrKykKPiArCQkJcmVxdWVzdC0+b3Bl cmFuZHNbaV0gPSBvcGVyYW5kc1tpXTsKPiArCQlicmVhazsKPiArCj4gKwljYXNlIEhZUEVSX0RN QUJVRl9ERVNUUk9ZOgo+ICsJCS8qIGRlc3Ryb3kgc2dfbGlzdCBmb3IgaHlwZXJfZG1hYnVmX2lk IG9uIHJlbW90ZSBzaWRlICovCj4gKwkJLyogY29tbWFuZCA6IERNQUJVRl9ERVNUUk9ZLAo+ICsJ CSAqIG9wZXJhbmRzMCA6IGh5cGVyX2RtYWJ1Zl9pZAo+ICsJCSAqLwo+ICsJCXJlcXVlc3QtPm9w ZXJhbmRzWzBdID0gb3BlcmFuZHNbMF07Cj4gKwkJYnJlYWs7Cj4gKwo+ICsJY2FzZSBIWVBFUl9E TUFCVUZfT1BTX1RPX1JFTU9URToKPiArCQkvKiBub3RpZnlpbmcgZG1hYnVmIG1hcC91bm1hcCB0 byBpbXBvcnRlciAocHJvYmFibHkgbm90IG5lZWRlZCkgKi8KPiArCQkvKiBmb3IgZG1hYnVmIHN5 bmNocm9uaXphdGlvbiAqLwo+ICsJCWJyZWFrOwo+ICsKPiArCS8qIGFzIGltcG9ydGVyLCBjb21t YW5kIHRvIGV4cG9ydGVyICovCj4gKwljYXNlIEhZUEVSX0RNQUJVRl9PUFNfVE9fU09VUkNFOgo+ ICsJCS8qIG5vdGlmeWluZyBkbWFidWYgbWFwL3VubWFwIHRvIGV4cG9ydGVyLCBtYXAgd2lsbCBt YWtlIHRoZSBkcml2ZXIgdG8gZG8gc2hhZG93IG1hcHBpbmcKPiArCQkqIG9yIHVubWFwcGluZyBm b3Igc3luY2hyb25pemF0aW9uIHdpdGggb3JpZ2luYWwgZXhwb3J0ZXIgKGUuZy4gaTkxNSkgKi8K PiArCQkvKiBjb21tYW5kIDogRE1BQlVGX09QU19UT19TT1VSQ0UuCj4gKwkJICogb3BlcmFuZHMw IDogaHlwZXJfZG1hYnVmX2lkCj4gKwkJICogb3BlcmFuZHMxIDogbWFwKD0xKS91bm1hcCg9Mikv YXR0YWNoKD0zKS9kZXRhY2goPTQpCj4gKwkJICovCj4gKwkJZm9yIChpPTA7IGk8MjsgaSsrKQo+ ICsJCQlyZXF1ZXN0LT5vcGVyYW5kc1tpXSA9IG9wZXJhbmRzW2ldOwo+ICsJCWJyZWFrOwo+ICsK PiArCS8qIHJlcXVlc3RpbmcgdGhlIG90aGVyIHNpZGUgdG8gc2V0dXAgYW5vdGhlciByaW5nIGNo YW5uZWwgZm9yIHJldmVyc2UgZGlyZWN0aW9uICovCj4gKwljYXNlIEhZUEVSX0RNQUJVRl9FWFBP UlRFUl9SSU5HX1NFVFVQOgo+ICsJCS8qIGNvbW1hbmQgOiBIWVBFUl9ETUFCVUZfRVhQT1JURVJf UklOR19TRVRVUCAqLwo+ICsJCS8qIG5vIG9wZXJhbmRzIG5lZWRlZCAqLwo+ICsJCWJyZWFrOwo+ ICsKPiArCWRlZmF1bHQ6Cj4gKwkJLyogbm8gY29tbWFuZCBmb3VuZCAqLwo+ICsJCXJldHVybjsK PiArCX0KPiArfQo+ICsKPiAraW50IGh5cGVyX2RtYWJ1Zl9tc2dfcGFyc2UoaW50IGRvbWlkLCBz dHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfcnEgKnJlcSkKPiArewo+ICsJdWludDMyX3QgaSwgcmV0 Owo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqaW1wb3J0ZWRfc2d0 X2luZm87Cj4gKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3NndF9pbmZvICpzZ3RfaW5mbzsKPiArCj4g KwkvKiBtYWtlIHN1cmUgcmVxIGlzIG5vdCBOVUxMIChtYXkgbm90IGJlIG5lZWRlZCkgKi8KPiAr CWlmICghcmVxKSB7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJcmVxLT5zdGF0 dXMgPSBIWVBFUl9ETUFCVUZfUkVRX1BST0NFU1NFRDsKPiArCj4gKwlzd2l0Y2ggKHJlcS0+Y29t bWFuZCkgewo+ICsJY2FzZSBIWVBFUl9ETUFCVUZfRVhQT1JUOgo+ICsJCS8qIGV4cG9ydGluZyBw YWdlcyBmb3IgZG1hYnVmICovCj4gKwkJLyogY29tbWFuZCA6IEhZUEVSX0RNQUJVRl9FWFBPUlQs Cj4gKwkJICogb3BlcmFuZHMwIDogaHlwZXJfZG1hYnVmX2lkCj4gKwkJICogb3BlcmFuZHMxIDog bnVtYmVyIG9mIHBhZ2VzIHRvIGJlIHNoYXJlZAo+ICsJCSAqIG9wZXJhbmRzMiA6IG9mZnNldCBv ZiBkYXRhIGluIHRoZSBmaXJzdCBwYWdlCj4gKwkJICogb3BlcmFuZHMzIDogbGVuZ3RoIG9mIGRh dGEgaW4gdGhlIGxhc3QgcGFnZQo+ICsJCSAqIG9wZXJhbmRzNCA6IHRvcC1sZXZlbCByZWZlcmVu Y2UgbnVtYmVyIGZvciBzaGFyZWQgcGFnZXMKPiArCQkgKiBvcGVyYW5kczV+OCA6IERyaXZlci1z cGVjaWZpYyBwcml2YXRlIGRhdGEgKGUuZy4gZ3JhcGhpYyBidWZmZXIncyBtZXRhIGluZm8pCj4g KwkJICovCj4gKwkJaW1wb3J0ZWRfc2d0X2luZm8gPSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBv cnRlZF9zZ3RfaW5mbyopa2NhbGxvYygxLCBzaXplb2YoKmltcG9ydGVkX3NndF9pbmZvKSwgR0ZQ X0tFUk5FTCk7Cj4gKwkJaW1wb3J0ZWRfc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZCA9IHJlcS0+ b3BlcmFuZHNbMF07Cj4gKwkJaW1wb3J0ZWRfc2d0X2luZm8tPmZyc3Rfb2ZzdCA9IHJlcS0+b3Bl cmFuZHNbMl07Cj4gKwkJaW1wb3J0ZWRfc2d0X2luZm8tPmxhc3RfbGVuID0gcmVxLT5vcGVyYW5k c1szXTsKPiArCQlpbXBvcnRlZF9zZ3RfaW5mby0+bmVudHMgPSByZXEtPm9wZXJhbmRzWzFdOwo+ ICsJCWltcG9ydGVkX3NndF9pbmZvLT5ncmVmID0gcmVxLT5vcGVyYW5kc1s0XTsKPiArCj4gKwkJ cHJpbnRrKCJETUFCVUYgd2FzIGV4cG9ydGVkXG4iKTsKPiArCQlwcmludGsoIlx0aHlwZXJfZG1h YnVmX2lkICVkXG4iLCByZXEtPm9wZXJhbmRzWzBdKTsKPiArCQlwcmludGsoIlx0bmVudHMgJWRc biIsIHJlcS0+b3BlcmFuZHNbMV0pOwo+ICsJCXByaW50aygiXHRmaXJzdCBvZmZzZXQgJWRcbiIs IHJlcS0+b3BlcmFuZHNbMl0pOwo+ICsJCXByaW50aygiXHRsYXN0IGxlbiAlZFxuIiwgcmVxLT5v cGVyYW5kc1szXSk7Cj4gKwkJcHJpbnRrKCJcdGdyZWZpZCAlZFxuIiwgcmVxLT5vcGVyYW5kc1s0 XSk7Cj4gKwo+ICsJCWZvciAoaT0wOyBpPDQ7IGkrKykKPiArCQkJaW1wb3J0ZWRfc2d0X2luZm8t PnByaXZhdGVbaV0gPSByZXEtPm9wZXJhbmRzWzUraV07Cj4gKwo+ICsJCWh5cGVyX2RtYWJ1Zl9y ZWdpc3Rlcl9pbXBvcnRlZChpbXBvcnRlZF9zZ3RfaW5mbyk7Cj4gKwkJYnJlYWs7Cj4gKwo+ICsJ Y2FzZSBIWVBFUl9ETUFCVUZfREVTVFJPWToKPiArCQkvKiBkZXN0cm95IHNnX2xpc3QgZm9yIGh5 cGVyX2RtYWJ1Zl9pZCBvbiByZW1vdGUgc2lkZSAqLwo+ICsJCS8qIGNvbW1hbmQgOiBETUFCVUZf REVTVFJPWSwKPiArCQkgKiBvcGVyYW5kczAgOiBoeXBlcl9kbWFidWZfaWQKPiArCQkgKi8KPiAr Cj4gKwkJaW1wb3J0ZWRfc2d0X2luZm8gPQo+ICsJCQloeXBlcl9kbWFidWZfZmluZF9pbXBvcnRl ZChyZXEtPm9wZXJhbmRzWzBdKTsKPiArCj4gKwkJaWYgKGltcG9ydGVkX3NndF9pbmZvKSB7Cj4g KwkJCWh5cGVyX2RtYWJ1Zl9jbGVhbnVwX2ltcG9ydGVkX3BhZ2VzKGltcG9ydGVkX3NndF9pbmZv KTsKPiArCj4gKwkJCWh5cGVyX2RtYWJ1Zl9yZW1vdmVfaW1wb3J0ZWQocmVxLT5vcGVyYW5kc1sw XSk7Cj4gKwo+ICsJCQkvKiBUT0RPOiBjbGVhbnVwIHNndCBvbiBpbXBvcnRlciBzaWRlIGV0YyAq Lwo+ICsJCX0KPiArCj4gKwkJLyogTm90aWZ5IGV4cG9ydGVyIHRoYXQgYnVmZmVyIGlzIGZyZWVk IGFuZCBpdCBjYW4gY2xlYW51cCBpdCAqLwo+ICsJCXJlcS0+c3RhdHVzID0gSFlQRVJfRE1BQlVG X1JFUV9ORUVEU19GT0xMT1dfVVA7Cj4gKwkJcmVxLT5jb21tYW5kID0gSFlQRVJfRE1BQlVGX0RF U1RST1lfRklOSVNIOwo+ICsKPiArI2lmIDAgLyogZnVuY3Rpb24gaXMgbm90IGltcGxlbWVudGVk IHlldCAqLwo+ICsKPiArCQlyZXQgPSBoeXBlcl9kbWFidWZfZGVzdHJveV9zZ3QocmVxLT5oeXBl cl9kbWFidWZfaWQpOwo+ICsjZW5kaWYKPiArCQlicmVhazsKPiArCj4gKwljYXNlIEhZUEVSX0RN QUJVRl9ERVNUUk9ZX0ZJTklTSDoKPiArCQkvKiBkZXN0cm95IHNnX2xpc3QgZm9yIGh5cGVyX2Rt YWJ1Zl9pZCBvbiBsb2NhbCBzaWRlICovCj4gKwkJLyogY29tbWFuZCA6IERNQUJVRl9ERVNUUk9Z X0ZJTklTSCwKPiArCQkgKiBvcGVyYW5kczAgOiBoeXBlcl9kbWFidWZfaWQKPiArCQkgKi8KPiAr Cj4gKwkJLyogVE9ETzogdGhhdCBzaG91bGQgYmUgZG9uZSBvbiB3b3JrcXVldWUsIHdoZW4gcmVj ZWl2ZWQgYWNrIGZyb20gYWxsIGltcG9ydGVycyB0aGF0IGJ1ZmZlciBpcyBubyBsb25nZXIgdXNl ZCAqLwo+ICsJCXNndF9pbmZvID0KPiArCQkJaHlwZXJfZG1hYnVmX2ZpbmRfZXhwb3J0ZWQocmVx LT5vcGVyYW5kc1swXSk7Cj4gKwo+ICsJCWlmIChzZ3RfaW5mbykgewo+ICsJCQloeXBlcl9kbWFi dWZfY2xlYW51cF9ncmVmX3RhYmxlKHNndF9pbmZvKTsKPiArCj4gKwkJCS8qIHVubWFwIGRtYWJ1 ZiAqLwo+ICsJCQlkbWFfYnVmX3VubWFwX2F0dGFjaG1lbnQoc2d0X2luZm8tPmF0dGFjaG1lbnQs IHNndF9pbmZvLT5zZ3QsIERNQV9CSURJUkVDVElPTkFMKTsKPiArCQkJZG1hX2J1Zl9kZXRhY2go c2d0X2luZm8tPmRtYV9idWYsIHNndF9pbmZvLT5hdHRhY2htZW50KTsKPiArCQkJZG1hX2J1Zl9w dXQoc2d0X2luZm8tPmRtYV9idWYpOwo+ICsKPiArCQkJLyogVE9ETzogUmVzdCBvZiBjbGVhbnVw LCBzZ3QgY2xlYW51cCBldGMgKi8KPiArCQl9Cj4gKwo+ICsJCWJyZWFrOwo+ICsKPiArCWNhc2Ug SFlQRVJfRE1BQlVGX09QU19UT19SRU1PVEU6Cj4gKwkJLyogbm90aWZ5aW5nIGRtYWJ1ZiBtYXAv dW5tYXAgdG8gaW1wb3J0ZXIgKHByb2JhYmx5IG5vdCBuZWVkZWQpICovCj4gKwkJLyogZm9yIGRt YWJ1ZiBzeW5jaHJvbml6YXRpb24gKi8KPiArCQlicmVhazsKPiArCj4gKwkvKiBhcyBpbXBvcnRl ciwgY29tbWFuZCB0byBleHBvcnRlciAqLwo+ICsJY2FzZSBIWVBFUl9ETUFCVUZfT1BTX1RPX1NP VVJDRToKPiArCQkvKiBub3RpZnlpbmcgZG1hYnVmIG1hcC91bm1hcCB0byBleHBvcnRlciwgbWFw IHdpbGwgbWFrZSB0aGUgZHJpdmVyIHRvIGRvIHNoYWRvdyBtYXBwaW5nCj4gKwkJKiBvciB1bm1h cHBpbmcgZm9yIHN5bmNocm9uaXphdGlvbiB3aXRoIG9yaWdpbmFsIGV4cG9ydGVyIChlLmcuIGk5 MTUpICovCj4gKwkJLyogY29tbWFuZCA6IERNQUJVRl9PUFNfVE9fU09VUkNFLgo+ICsJCSAqIG9w ZXJhbmRzMCA6IGh5cGVyX2RtYWJ1Zl9pZAo+ICsJCSAqIG9wZXJhbmRzMSA6IG1hcCg9MSkvdW5t YXAoPTIpL2F0dGFjaCg9MykvZGV0YWNoKD00KQo+ICsJCSAqLwo+ICsJCWJyZWFrOwo+ICsKPiAr CS8qIHJlcXVlc3RpbmcgdGhlIG90aGVyIHNpZGUgdG8gc2V0dXAgYW5vdGhlciByaW5nIGNoYW5u ZWwgZm9yIHJldmVyc2UgZGlyZWN0aW9uICovCj4gKwljYXNlIEhZUEVSX0RNQUJVRl9FWFBPUlRF Ul9SSU5HX1NFVFVQOgo+ICsJCS8qIGNvbW1hbmQ6IEhZUEVSX0RNQUJVRl9FWFBPUlRFUl9SSU5H X1NFVFVQCj4gKwkJICogbm8gb3BlcmFuZHMgbmVlZGVkICovCj4gKwkJcmV0ID0gaHlwZXJfZG1h YnVmX2V4cG9ydGVyX3JpbmdidWZfaW5pdChkb21pZCwgJnJlcS0+b3BlcmFuZHNbMF0sICZyZXEt Pm9wZXJhbmRzWzFdKTsKPiArCQlpZiAocmV0IDwgMCkgewo+ICsJCQlyZXEtPnN0YXR1cyA9IEhZ UEVSX0RNQUJVRl9SRVFfRVJST1I7Cj4gKwkJCXJldHVybiAtRUlOVkFMOwo+ICsJCX0KPiArCj4g KwkJcmVxLT5zdGF0dXMgPSBIWVBFUl9ETUFCVUZfUkVRX05FRURTX0ZPTExPV19VUDsKPiArCQly ZXEtPmNvbW1hbmQgPSBIWVBFUl9ETUFCVUZfSU1QT1JURVJfUklOR19TRVRVUDsKPiArCQlicmVh azsKPiArCj4gKwljYXNlIEhZUEVSX0RNQUJVRl9JTVBPUlRFUl9SSU5HX1NFVFVQOgo+ICsJCS8q IGNvbW1hbmQ6IEhZUEVSX0RNQUJVRl9JTVBPUlRFUl9SSU5HX1NFVFVQICovCj4gKwkJLyogbm8g b3BlcmFuZHMgbmVlZGVkICovCj4gKwkJcmV0ID0gaHlwZXJfZG1hYnVmX2ltcG9ydGVyX3Jpbmdi dWZfaW5pdChkb21pZCwgcmVxLT5vcGVyYW5kc1swXSwgcmVxLT5vcGVyYW5kc1sxXSk7Cj4gKwkJ aWYgKHJldCA8IDApCj4gKwkJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCQlicmVhazsKPiArCj4g KwlkZWZhdWx0Ogo+ICsJCS8qIG5vIG1hdGNoZWQgY29tbWFuZCwgbm90aGluZyB0byBkby4uIGp1 c3QgcmV0dXJuIGVycm9yICovCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJcmV0 dXJuIHJlcS0+Y29tbWFuZDsKPiArfQo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3hlbi9oeXBlcl9k bWFidWYvaHlwZXJfZG1hYnVmX21zZy5oIGIvZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVy X2RtYWJ1Zl9tc2cuaAo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uNDRi ZmI3MAo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlw ZXJfZG1hYnVmX21zZy5oCj4gQEAgLTAsMCArMSw0NSBAQAo+ICsjaWZuZGVmIF9fSFlQRVJfRE1B QlVGX01TR19IX18KPiArI2RlZmluZSBfX0hZUEVSX0RNQUJVRl9NU0dfSF9fCj4gKwo+ICtlbnVt IGh5cGVyX2RtYWJ1Zl9jb21tYW5kIHsKPiArCUhZUEVSX0RNQUJVRl9FWFBPUlQgPSAweDEwLAo+ ICsJSFlQRVJfRE1BQlVGX0RFU1RST1ksCj4gKwlIWVBFUl9ETUFCVUZfREVTVFJPWV9GSU5JU0gs Cj4gKwlIWVBFUl9ETUFCVUZfT1BTX1RPX1JFTU9URSwKPiArCUhZUEVSX0RNQUJVRl9PUFNfVE9f U09VUkNFLAo+ICsJSFlQRVJfRE1BQlVGX0VYUE9SVEVSX1JJTkdfU0VUVVAsIC8qIHJlcXVlc3Rp bmcgcmVtb3RlIGRvbWFpbiB0byBzZXQgdXAgZXhwb3J0ZXIncyByaW5nICovCj4gKwlIWVBFUl9E TUFCVUZfSU1QT1JURVJfUklOR19TRVRVUCwgLyogcmVxdWVzdGluZyByZW1vdGUgZG9tYWluIHRv IHNldCB1cCBpbXBvcnRlcidzIHJpbmcgKi8KPiArfTsKPiArCj4gK2VudW0gaHlwZXJfZG1hYnVm X29wcyB7Cj4gKwlIWVBFUl9ETUFCVUZfT1BTX0FUVEFDSCA9IDB4MTAwMCwKPiArCUhZUEVSX0RN QUJVRl9PUFNfREVUQUNILAo+ICsJSFlQRVJfRE1BQlVGX09QU19NQVAsCj4gKwlIWVBFUl9ETUFC VUZfT1BTX1VOTUFQLAo+ICsJSFlQRVJfRE1BQlVGX09QU19SRUxFQVNFLAo+ICsJSFlQRVJfRE1B QlVGX09QU19CRUdJTl9DUFVfQUNDRVNTLAo+ICsJSFlQRVJfRE1BQlVGX09QU19FTkRfQ1BVX0FD Q0VTUywKPiArCUhZUEVSX0RNQUJVRl9PUFNfS01BUF9BVE9NSUMsCj4gKwlIWVBFUl9ETUFCVUZf T1BTX0tVTk1BUF9BVE9NSUMsCj4gKwlIWVBFUl9ETUFCVUZfT1BTX0tNQVAsCj4gKwlIWVBFUl9E TUFCVUZfT1BTX0tVTk1BUCwKPiArCUhZUEVSX0RNQUJVRl9PUFNfTU1BUCwKPiArCUhZUEVSX0RN QUJVRl9PUFNfVk1BUCwKPiArCUhZUEVSX0RNQUJVRl9PUFNfVlVOTUFQLAo+ICt9Owo+ICsKPiAr ZW51bSBoeXBlcl9kbWFidWZfcmVxX2ZlZWRiYWNrIHsKPiArCUhZUEVSX0RNQUJVRl9SRVFfUFJP Q0VTU0VEID0gMHgxMDAsCj4gKwlIWVBFUl9ETUFCVUZfUkVRX05FRURTX0ZPTExPV19VUCwKPiAr CUhZUEVSX0RNQUJVRl9SRVFfRVJST1IsCj4gKwlIWVBFUl9ETUFCVUZfUkVRX05PVF9SRVNQT05E RUQKPiArfTsKPiArCj4gKy8qIGNyZWF0ZSBhIHJlcXVlc3QgcGFja2V0IHdpdGggZ2l2ZW4gY29t bWFuZCBhbmQgb3BlcmFuZHMgKi8KPiArdm9pZCBoeXBlcl9kbWFidWZfY3JlYXRlX3JlcXVlc3Qo c3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX3JxICpyZXF1ZXN0LAo+ICsgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgZW51bSBoeXBlcl9kbWFidWZfY29tbWFuZCBjb21tYW5k LCBpbnQgKm9wZXJhbmRzKTsKPiArCj4gKy8qIHBhcnNlIGluY29taW5nIHJlcXVlc3QgcGFja2V0 IChvciByZXNwb25zZSkgYW5kIHRha2UgYXBwcm9wcmlhdGUgYWN0aW9ucyBmb3IgdGhvc2UgKi8K PiAraW50IGh5cGVyX2RtYWJ1Zl9tc2dfcGFyc2UoaW50IGRvbWlkLCBzdHJ1Y3QgaHlwZXJfZG1h YnVmX3JpbmdfcnEgKnJlcSk7Cj4gKwo+ICsjZW5kaWYgLy8gX19IWVBFUl9ETUFCVUZfTVNHX0hf Xwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX3F1 ZXJ5LmggYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX3F1ZXJ5LmgKPiBu ZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLmE1NzcxNjcKPiAtLS0gL2Rldi9u dWxsCj4gKysrIGIvZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9xdWVyeS5o Cj4gQEAgLTAsMCArMSwxNiBAQAo+ICsjaWZuZGVmIF9fSFlQRVJfRE1BQlVGX1FVRVJZX0hfXwo+ ICsjZGVmaW5lIF9fSFlQRVJfRE1BQlVGX1FVRVJZX0hfXwo+ICsKPiArZW51bSBoeXBlcl9kbWFi dWZfcXVlcnkgewo+ICsJRE1BQlVGX1FVRVJZX1RZUEVfTElTVCA9IDB4MTAsCj4gKwlETUFCVUZf UVVFUllfRVhQT1JURVIsCj4gKwlETUFCVUZfUVVFUllfSU1QT1JURVIsCj4gKwlETUFCVUZfUVVF UllfU0laRQo+ICt9Owo+ICsKPiArZW51bSBoeXBlcl9kbWFidWZfc3RhdHVzIHsKPiArCUVYUE9S VEVEID0gMHgwMSwKPiArCUlNUE9SVEVECj4gK307Cj4gKwo+ICsjZW5kaWYgLyogX19IWVBFUl9E TUFCVUZfUVVFUllfSF9fICovCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1 Zi9oeXBlcl9kbWFidWZfc3RydWN0LmggYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJf ZG1hYnVmX3N0cnVjdC5oCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwLi5j OGEyZjRkCj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9o eXBlcl9kbWFidWZfc3RydWN0LmgKPiBAQCAtMCwwICsxLDcwIEBACj4gKyNpZm5kZWYgX19IWVBF Ul9ETUFCVUZfU1RSVUNUX0hfXwo+ICsjZGVmaW5lIF9fSFlQRVJfRE1BQlVGX1NUUlVDVF9IX18K PiArCj4gKyNpbmNsdWRlIDx4ZW4vaW50ZXJmYWNlL2dyYW50X3RhYmxlLmg+Cj4gKwo+ICsvKiBJ bXBvcnRlciBjb21iaW5lIHNvdXJjZSBkb21haW4gaWQgd2l0aCBnaXZlbiBoeXBlcl9kbWFidWZf aWQKPiArICogdG8gbWFrZSBpdCB1bmlxdWUgaW4gY2FzZSB0aGVyZSBhcmUgbXVsdGlwbGUgZXhw b3J0ZXJzICovCj4gKwo+ICsjZGVmaW5lIEhZUEVSX0RNQUJVRl9JRF9JTVBPUlRFUihzZG9tYWlu LCBpZCkgXAo+ICsJKCgoKHNkb21haW4pICYgMHhGRikgPDwgMjQpIHwgKChpZCkgJiAweEZGRkZG RikpCj4gKwo+ICsjZGVmaW5lIEhZUEVSX0RNQUJVRl9JRF9JTVBPUlRFUl9HRVRfU0RPTUFJTl9J RChpZCkgXAo+ICsJKCgoaWQpID4+IDI0KSAmIDB4RkYpCj4gKwo+ICsvKiBlYWNoIGdyYW50X3Jl Zl90IGlzIDQgYnl0ZXMsIHNvIHRvdGFsIDQwOTYgZ3JhbnRfcmVmX3QgY2FuIGJlCj4gKyAqIGlu IHRoaXMgYmxvY2sgbWVhbmluZyB3ZSBjYW4gc2hhcmUgNEtCKjQwOTYgPSAxNk1CIG9mIGJ1ZmZl cgo+ICsgKiAobmVlZHMgdG8gYmUgaW5jcmVhc2VkIGZvciBsYXJnZSBidWZmZXIgdXNlLWNhc2Vz IHN1Y2ggYXMgNEsKPiArICogZnJhbWUgYnVmZmVyKSAqLwo+ICsjZGVmaW5lIE1BWF9BTExPV0VE X05VTV9QQUdFU19GT1JfR1JFRl9OVU1fQVJSQVlTIDQKPiArCj4gK3N0cnVjdCBoeXBlcl9kbWFi dWZfc2hhcmVkX3BhZ2VzX2luZm8gewo+ICsJZ3JhbnRfcmVmX3QgKmRhdGFfcmVmczsJLyogdGFi bGUgd2l0aCBzaGFyZWQgYnVmZmVyIHBhZ2VzIHJlZmlkICovCj4gKwlncmFudF9yZWZfdCAqYWRk cl9wYWdlczsgLyogcGFnZXMgb2YgMm5kIGxldmVsIGFkZHJlc3NpbmcgKi8KPiArCWdyYW50X3Jl Zl90ICp0b3BfbGV2ZWxfcGFnZTsgLyogcGFnZSBvZiB0b3AgbGV2ZWwgYWRkcmVzc2luZywgaXQg Y29udGFpbnMgcmVmaWRzIG9mIDJuZCBsZXZlbCBwYWdlcyAqLwo+ICsJZ3JhbnRfcmVmX3QgdG9w X2xldmVsX3JlZjsgLyogdG9wIGxldmVsIHJlZmlkICovCj4gKwlzdHJ1Y3QgZ250dGFiX3VubWFw X2dyYW50X3JlZiogdW5tYXBfb3BzOyAvKiB1bm1hcCBvcHMgZm9yIG1hcHBlZCBwYWdlcyAqLwo+ ICsJc3RydWN0IHBhZ2UgKipkYXRhX3BhZ2VzOyAvKiBkYXRhIHBhZ2VzIHRvIGJlIHVubWFwcGVk ICovCj4gK307Cj4gKwo+ICsvKiBFeHBvcnRlciBidWlsZHMgcGFnZXNfaW5mbyBiZWZvcmUgc2hh cmluZyBwYWdlcyAqLwo+ICtzdHJ1Y3QgaHlwZXJfZG1hYnVmX3BhZ2VzX2luZm8gewo+ICsgICAg ICAgIGludCBoeXBlcl9kbWFidWZfaWQ7IC8qIHVuaXF1ZSBpZCB0byByZWZlcmVuY2UgZG1hYnVm IGluIHNvdXJjZSBkb21haW4gKi8KPiArICAgICAgICBpbnQgaHlwZXJfZG1hYnVmX3Jkb21haW47 IC8qIGN1cnJlbnRpbmcgY29uc2lkZXJpbmcganVzdCBvbmUgcmVtb3RlIGRvbWFpbiBhY2Nlc3Mg aXQgKi8KPiArICAgICAgICBpbnQgZnJzdF9vZnN0OyAvKiBvZmZzZXQgb2YgZGF0YSBpbiB0aGUg Zmlyc3QgcGFnZSAqLwo+ICsgICAgICAgIGludCBsYXN0X2xlbjsgLyogbGVuZ3RoIG9mIGRhdGEg aW4gdGhlIGxhc3QgcGFnZSAqLwo+ICsgICAgICAgIGludCBuZW50czsgLyogIyBvZiBwYWdlcyAq Lwo+ICsgICAgICAgIHN0cnVjdCBwYWdlICoqcGFnZXM7IC8qIHBhZ2VzIHRoYXQgY29udGFpbnMg cmVmZXJlbmNlIG51bWJlcnMgb2Ygc2hhcmVkIHBhZ2VzKi8KPiArfTsKPiArCj4gKy8qIEJvdGgg aW1wb3J0ZXIgYW5kIGV4cG9ydGVyIHVzZSB0aGlzIHN0cnVjdHVyZSB0byBwb2ludCB0byBzZyBs aXN0cwo+ICsgKgo+ICsgKiBFeHBvcnRlciBzdG9yZXMgcmVmZXJlbmNlcyB0byBzZ3QgaW4gYSBo YXNoIHRhYmxlCj4gKyAqIEV4cG9ydGVyIGtlZXBzIHRoZXNlIHJlZmVyZW5jZXMgZm9yIHN5bmNo cm9uaXphdGlvbiBhbmQgdHJhY2tpbmcgcHVycG9zZXMKPiArICoKPiArICogSW1wb3J0ZXIgdXNl IHRoaXMgc3RydWN0dXJlIGV4cG9ydGluZyB0byBvdGhlciBkcml2ZXJzIGluIHRoZSBzYW1lIGRv bWFpbiAqLwo+ICtzdHJ1Y3QgaHlwZXJfZG1hYnVmX3NndF9pbmZvIHsKPiArICAgICAgICBpbnQg aHlwZXJfZG1hYnVmX2lkOyAvKiB1bmlxdWUgaWQgdG8gcmVmZXJlbmNlIGRtYWJ1ZiBpbiByZW1v dGUgZG9tYWluICovCj4gKwlpbnQgaHlwZXJfZG1hYnVmX3Jkb21haW47IC8qIGRvbWFpbiBpbXBv cnRpbmcgdGhpcyBzZ3QgKi8KPiArICAgICAgICBzdHJ1Y3Qgc2dfdGFibGUgKnNndDsgLyogcG9p bnRlciB0byBzZ3QgKi8KPiArCXN0cnVjdCBkbWFfYnVmICpkbWFfYnVmOyAvKiBuZWVkZWQgdG8g c3RvcmUgdGhpcyBmb3IgZnJlZWluZyBpdCBsYXRlciAqLwo+ICsJc3RydWN0IGRtYV9idWZfYXR0 YWNobWVudCAqYXR0YWNobWVudDsgLyogbmVlZGVkIHRvIHN0b3JlIHRoaXMgZm9yIGZyZWVpbmcg dGhpcyBsYXRlciAqLwo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9zaGFyZWRfcGFnZXNfaW5mbyBz aGFyZWRfcGFnZXNfaW5mbzsKPiArCWludCBwcml2YXRlWzRdOyAvKiBkZXZpY2Ugc3BlY2lmaWMg aW5mbyAoZS5nLiBpbWFnZSdzIG1ldGEgaW5mbz8pICovCj4gK307Cj4gKwo+ICsvKiBJbXBvcnRl ciBzdG9yZSByZWZlcmVuY2VzIChiZWZvcmUgbWFwcGluZykgb24gc2hhcmVkIHBhZ2VzCj4gKyAq IEltcG9ydGVyIHN0b3JlIHRoZXNlIHJlZmVyZW5jZXMgaW4gdGhlIHRhYmxlIGFuZCBtYXAgaXQg aW4KPiArICogaXRzIG93biBtZW1vcnkgbWFwIG9uY2UgdXNlcnNwYWNlIGFza3MgZm9yIHJlZmVy ZW5jZSBmb3IgdGhlIGJ1ZmZlciAqLwo+ICtzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9ydGVkX3Nn dF9pbmZvIHsKPiArCWludCBoeXBlcl9kbWFidWZfaWQ7IC8qIHVuaXF1ZSBpZCB0byByZWZlcmVu Y2UgZG1hYnVmIChIWVBFUl9ETUFCVUZfSURfSU1QT1JURVIoc291cmNlIGRvbWFpbiBpZCwgZXhw b3J0ZXIncyBoeXBlcl9kbWFidWZfaWQgKi8KPiArCWludCBmcnN0X29mc3Q7CS8qIHN0YXJ0IG9m ZnNldCBpbiBzaGFyZWQgcGFnZSAjMSAqLwo+ICsJaW50IGxhc3RfbGVuOwkvKiBsZW5ndGggb2Yg ZGF0YSBpbiB0aGUgbGFzdCBzaGFyZWQgcGFnZSAqLwo+ICsJaW50IG5lbnRzOwkvKiBudW1iZXIg b2YgcGFnZXMgdG8gYmUgc2hhcmVkICovCj4gKwlncmFudF9yZWZfdCBncmVmOyAvKiByZWZlcmVu Y2UgbnVtYmVyIG9mIHRvcCBsZXZlbCBhZGRyZXNzaW5nIHBhZ2Ugb2Ygc2hhcmVkIHBhZ2VzICov Cj4gKwlzdHJ1Y3Qgc2dfdGFibGUgKnNndDsgLyogc2d0IHBvaW50ZXIgYWZ0ZXIgaW1wb3J0aW5n IGJ1ZmZlciAqLwo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9zaGFyZWRfcGFnZXNfaW5mbyBzaGFy ZWRfcGFnZXNfaW5mbzsKPiArCWludCBwcml2YXRlWzRdOyAvKiBkZXZpY2Ugc3BlY2lmaWMgaW5m byAoZS5nLiBpbWFnZSdzIG1ldGEgaW5mbz8pICovCj4gK307Cj4gKwo+ICsjZW5kaWYgLyogX19I WVBFUl9ETUFCVUZfU1RSVUNUX0hfXyAqLwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3hlbi9oeXBl cl9kbWFidWYveGVuL2h5cGVyX2RtYWJ1Zl94ZW5fY29tbS5jIGIvZHJpdmVycy94ZW4vaHlwZXJf ZG1hYnVmL3hlbi9oeXBlcl9kbWFidWZfeGVuX2NvbW0uYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0 Cj4gaW5kZXggMDAwMDAwMC4uMjJmMmVmMAo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJz L3hlbi9oeXBlcl9kbWFidWYveGVuL2h5cGVyX2RtYWJ1Zl94ZW5fY29tbS5jCj4gQEAgLTAsMCAr MSwzMjggQEAKPiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgo+ICsjaW5jbHVkZSA8bGludXgv ZXJybm8uaD4KPiArI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgv c2xhYi5oPgo+ICsjaW5jbHVkZSA8bGludXgvd29ya3F1ZXVlLmg+Cj4gKyNpbmNsdWRlIDx4ZW4v Z3JhbnRfdGFibGUuaD4KPiArI2luY2x1ZGUgPHhlbi9ldmVudHMuaD4KPiArI2luY2x1ZGUgPHhl bi94ZW5idXMuaD4KPiArI2luY2x1ZGUgPGFzbS94ZW4vcGFnZS5oPgo+ICsjaW5jbHVkZSAiaHlw ZXJfZG1hYnVmX3hlbl9jb21tLmgiCj4gKyNpbmNsdWRlICJoeXBlcl9kbWFidWZfeGVuX2NvbW1f bGlzdC5oIgo+ICsjaW5jbHVkZSAiLi4vaHlwZXJfZG1hYnVmX2ltcC5oIgo+ICsjaW5jbHVkZSAi Li4vaHlwZXJfZG1hYnVmX2xpc3QuaCIKPiArI2luY2x1ZGUgIi4uL2h5cGVyX2RtYWJ1Zl9tc2cu aCIKPiArCj4gK3N0YXRpYyBpbnQgZXhwb3J0X3JlcV9pZCA9IDA7Cj4gK3N0YXRpYyBpbnQgaW1w b3J0X3JlcV9pZCA9IDA7Cj4gKwo+ICtpbnQzMl90IGh5cGVyX2RtYWJ1Zl9nZXRfZG9taWQodm9p ZCkKPiArewo+ICsJc3RydWN0IHhlbmJ1c190cmFuc2FjdGlvbiB4YnQ7Cj4gKwlpbnQzMl90IGRv bWlkOwo+ICsKPiArICAgICAgICB4ZW5idXNfdHJhbnNhY3Rpb25fc3RhcnQoJnhidCk7Cj4gKwo+ ICsgICAgICAgIGlmICgheGVuYnVzX3NjYW5mKHhidCwgImRvbWlkIiwiIiwgIiVkIiwgJmRvbWlk KSkgewo+ICsJCWRvbWlkID0gLTE7Cj4gKyAgICAgICAgfQo+ICsgICAgICAgIHhlbmJ1c190cmFu c2FjdGlvbl9lbmQoeGJ0LCAwKTsKPiArCj4gKwlyZXR1cm4gZG9taWQ7Cj4gK30KPiArCj4gK2lu dCBoeXBlcl9kbWFidWZfbmV4dF9yZXFfaWRfZXhwb3J0KHZvaWQpCj4gK3sKPiArICAgICAgICBl eHBvcnRfcmVxX2lkKys7Cj4gKyAgICAgICAgcmV0dXJuIGV4cG9ydF9yZXFfaWQ7Cj4gK30KPiAr Cj4gK2ludCBoeXBlcl9kbWFidWZfbmV4dF9yZXFfaWRfaW1wb3J0KHZvaWQpCj4gK3sKPiArICAg ICAgICBpbXBvcnRfcmVxX2lkKys7Cj4gKyAgICAgICAgcmV0dXJuIGltcG9ydF9yZXFfaWQ7Cj4g K30KPiArCj4gKy8qIEZvciBub3cgY2FjaGUgbGF0YXN0IHJpbmdzIGFzIGdsb2JhbCB2YXJpYWJs ZXMgVE9ETzoga2VlcCB0aGVtIGluIGxpc3QqLwo+ICtzdGF0aWMgaXJxcmV0dXJuX3QgaHlwZXJf ZG1hYnVmX2Zyb250X3JpbmdfaXNyKGludCBpcnEsIHZvaWQgKmRldl9pZCk7Cj4gK3N0YXRpYyBp cnFyZXR1cm5fdCBoeXBlcl9kbWFidWZfYmFja19yaW5nX2lzcihpbnQgaXJxLCB2b2lkICpkZXZf aWQpOwo+ICsKPiArLyogZXhwb3J0ZXIgbmVlZHMgdG8gZ2VuZXJhdGVkIGluZm8gZm9yIHBhZ2Ug c2hhcmluZyAqLwo+ICtpbnQgaHlwZXJfZG1hYnVmX2V4cG9ydGVyX3JpbmdidWZfaW5pdChpbnQg cmRvbWFpbiwgZ3JhbnRfcmVmX3QgKnJlZmlkLCBpbnQgKnBvcnQpCj4gK3sKPiArCXN0cnVjdCBo eXBlcl9kbWFidWZfcmluZ19pbmZvX2V4cG9ydCAqcmluZ19pbmZvOwo+ICsJc3RydWN0IGh5cGVy X2RtYWJ1Zl9zcmluZyAqc3Jpbmc7Cj4gKwlzdHJ1Y3QgZXZ0Y2huX2FsbG9jX3VuYm91bmQgYWxs b2NfdW5ib3VuZDsKPiArCXN0cnVjdCBldnRjaG5fY2xvc2UgY2xvc2U7Cj4gKwo+ICsJdm9pZCAq c2hhcmVkX3Jpbmc7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXJpbmdfaW5mbyA9IChzdHJ1Y3QgaHlw ZXJfZG1hYnVmX3JpbmdfaW5mb19leHBvcnQqKQo+ICsJCQkJa21hbGxvYyhzaXplb2YoKnJpbmdf aW5mbyksIEdGUF9LRVJORUwpOwo+ICsKPiArCS8qIGZyb20gZXhwb3J0ZXIgdG8gaW1wb3J0ZXIg Ki8KPiArCXNoYXJlZF9yaW5nID0gKHZvaWQgKilfX2dldF9mcmVlX3BhZ2VzKEdGUF9LRVJORUws IDEpOwo+ICsJaWYgKHNoYXJlZF9yaW5nID09IDApIHsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiAr CX0KPiArCj4gKwlzcmluZyA9IChzdHJ1Y3QgaHlwZXJfZG1hYnVmX3NyaW5nICopIHNoYXJlZF9y aW5nOwo+ICsKPiArCVNIQVJFRF9SSU5HX0lOSVQoc3JpbmcpOwo+ICsKPiArCUZST05UX1JJTkdf SU5JVCgmKHJpbmdfaW5mby0+cmluZ19mcm9udCksIHNyaW5nLCBQQUdFX1NJWkUpOwo+ICsKPiAr CXJpbmdfaW5mby0+Z3JlZl9yaW5nID0gZ250dGFiX2dyYW50X2ZvcmVpZ25fYWNjZXNzKHJkb21h aW4sCj4gKwkJCQkJCQl2aXJ0X3RvX21mbihzaGFyZWRfcmluZyksIDApOwo+ICsJaWYgKHJpbmdf aW5mby0+Z3JlZl9yaW5nIDwgMCkgewo+ICsJCXJldHVybiAtRUlOVkFMOyAvKiBmYWlsIHRvIGdl dCBncmVmICovCj4gKwl9Cj4gKwo+ICsJYWxsb2NfdW5ib3VuZC5kb20gPSBET01JRF9TRUxGOwo+ ICsJYWxsb2NfdW5ib3VuZC5yZW1vdGVfZG9tID0gcmRvbWFpbjsKPiArCXJldCA9IEhZUEVSVklT T1JfZXZlbnRfY2hhbm5lbF9vcChFVlRDSE5PUF9hbGxvY191bmJvdW5kLCAmYWxsb2NfdW5ib3Vu ZCk7Cj4gKwlpZiAocmV0ICE9IDApIHsKPiArCQlwcmludGsoIkNhbm5vdCBhbGxvY2F0ZSBldmVu dCBjaGFubmVsXG4iKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwkvKiBzZXR0 aW5nIHVwIGludGVycnVwdCAqLwo+ICsJcmV0ID0gYmluZF9ldnRjaG5fdG9faXJxaGFuZGxlcihh bGxvY191bmJvdW5kLnBvcnQsCj4gKwkJCQkJaHlwZXJfZG1hYnVmX2Zyb250X3JpbmdfaXNyLCAw LAo+ICsJCQkJCU5VTEwsICh2b2lkKikgcmluZ19pbmZvKTsKPiArCj4gKwlpZiAocmV0IDwgMCkg ewo+ICsJCXByaW50aygiRmFpbGVkIHRvIHNldHVwIGV2ZW50IGNoYW5uZWxcbiIpOwo+ICsJCWNs b3NlLnBvcnQgPSBhbGxvY191bmJvdW5kLnBvcnQ7Cj4gKwkJSFlQRVJWSVNPUl9ldmVudF9jaGFu bmVsX29wKEVWVENITk9QX2Nsb3NlLCAmY2xvc2UpOwo+ICsJCWdudHRhYl9lbmRfZm9yZWlnbl9h Y2Nlc3MocmluZ19pbmZvLT5ncmVmX3JpbmcsIDAsIHZpcnRfdG9fbWZuKHNoYXJlZF9yaW5nKSk7 Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJcmluZ19pbmZvLT5yZG9tYWluID0g cmRvbWFpbjsKPiArCXJpbmdfaW5mby0+aXJxID0gcmV0Owo+ICsJcmluZ19pbmZvLT5wb3J0ID0g YWxsb2NfdW5ib3VuZC5wb3J0Owo+ICsKPiArCS8qIHN0b3JlIHJlZmlkIGFuZCBwb3J0IG51bWJl cnMgZm9yIHVzZXJzcGFjZSdzIHVzZSAqLwo+ICsJKnJlZmlkID0gcmluZ19pbmZvLT5ncmVmX3Jp bmc7Cj4gKwkqcG9ydCA9IHJpbmdfaW5mby0+cG9ydDsKPiArCj4gKwlwcmludGsoIiVzOiBhbGxv Y2F0ZWQgZXZlbnRjaGFubmVsIGdyZWYgJWQgIHBvcnQ6ICVkICBpcnE6ICVkXG4iLCBfX2Z1bmNf XywKPiArCQlyaW5nX2luZm8tPmdyZWZfcmluZywKPiArCQlyaW5nX2luZm8tPnBvcnQsCj4gKwkJ cmluZ19pbmZvLT5pcnEpOwo+ICsKPiArCS8qIHJlZ2lzdGVyIHJpbmcgaW5mbyAqLwo+ICsJcmV0 ID0gaHlwZXJfZG1hYnVmX3JlZ2lzdGVyX2V4cG9ydGVyX3JpbmcocmluZ19pbmZvKTsKPiArCj4g KwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICsvKiBpbXBvcnRlciBuZWVkcyB0byBrbm93IGFib3V0 IHNoYXJlZCBwYWdlIGFuZCBwb3J0IG51bWJlcnMgZm9yIHJpbmcgYnVmZmVyIGFuZCBldmVudCBj aGFubmVsICovCj4gK2ludCBoeXBlcl9kbWFidWZfaW1wb3J0ZXJfcmluZ2J1Zl9pbml0KGludCBz ZG9tYWluLCBncmFudF9yZWZfdCBncmVmLCBpbnQgcG9ydCkKPiArewo+ICsJc3RydWN0IGh5cGVy X2RtYWJ1Zl9yaW5nX2luZm9faW1wb3J0ICpyaW5nX2luZm87Cj4gKwlzdHJ1Y3QgaHlwZXJfZG1h YnVmX3NyaW5nICpzcmluZzsKPiArCj4gKwlzdHJ1Y3QgcGFnZSAqc2hhcmVkX3Jpbmc7Cj4gKwo+ ICsJc3RydWN0IGdudHRhYl9tYXBfZ3JhbnRfcmVmICpvcHM7Cj4gKwlzdHJ1Y3QgZ250dGFiX3Vu bWFwX2dyYW50X3JlZiAqdW5tYXBfb3BzOwo+ICsJaW50IHJldDsKPiArCj4gKwlyaW5nX2luZm8g PSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9faW1wb3J0ICopCj4gKwkJCWttYWxsb2Mo c2l6ZW9mKCpyaW5nX2luZm8pLCBHRlBfS0VSTkVMKTsKPiArCj4gKwlyaW5nX2luZm8tPnNkb21h aW4gPSBzZG9tYWluOwo+ICsJcmluZ19pbmZvLT5ldnRjaG4gPSBwb3J0Owo+ICsKPiArCW9wcyA9 IChzdHJ1Y3QgZ250dGFiX21hcF9ncmFudF9yZWYqKWttYWxsb2Moc2l6ZW9mKCpvcHMpLCBHRlBf S0VSTkVMKTsKPiArCXVubWFwX29wcyA9IChzdHJ1Y3QgZ250dGFiX3VubWFwX2dyYW50X3JlZiop a21hbGxvYyhzaXplb2YoKnVubWFwX29wcyksIEdGUF9LRVJORUwpOwo+ICsKPiArCWlmIChnbnR0 YWJfYWxsb2NfcGFnZXMoMSwgJnNoYXJlZF9yaW5nKSkgewo+ICsJCXJldHVybiAtRUlOVkFMOwo+ ICsJfQo+ICsKPiArCWdudHRhYl9zZXRfbWFwX29wKCZvcHNbMF0sICh1bnNpZ25lZCBsb25nKXBm bl90b19rYWRkcihwYWdlX3RvX3BmbihzaGFyZWRfcmluZykpLAo+ICsJCQlHTlRNQVBfaG9zdF9t YXAsIGdyZWYsIHNkb21haW4pOwo+ICsKPiArCXJldCA9IGdudHRhYl9tYXBfcmVmcyhvcHMsIE5V TEwsICZzaGFyZWRfcmluZywgMSk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXByaW50aygiQ2Fu bm90IG1hcCByaW5nXG4iKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlpZiAo b3BzWzBdLnN0YXR1cykgewo+ICsJCXByaW50aygiUmluZyBtYXBwaW5nIGZhaWxlZFxuIik7Cj4g KwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJc3JpbmcgPSAoc3RydWN0IGh5cGVyX2Rt YWJ1Zl9zcmluZyopIHBmbl90b19rYWRkcihwYWdlX3RvX3BmbihzaGFyZWRfcmluZykpOwo+ICsK PiArCUJBQ0tfUklOR19JTklUKCZyaW5nX2luZm8tPnJpbmdfYmFjaywgc3JpbmcsIFBBR0VfU0la RSk7Cj4gKwo+ICsJcmV0ID0gYmluZF9pbnRlcmRvbWFpbl9ldnRjaG5fdG9faXJxaGFuZGxlcihz ZG9tYWluLCBwb3J0LCBoeXBlcl9kbWFidWZfYmFja19yaW5nX2lzciwgMCwKPiArCQkJCQkJICAg IE5VTEwsICh2b2lkKilyaW5nX2luZm8pOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlyZXR1cm4g LUVJTlZBTDsKPiArCX0KPiArCj4gKwlyaW5nX2luZm8tPmlycSA9IHJldDsKPiArCj4gKwlwcmlu dGsoIiVzOiBib3VuZCB0byBldmVudGNoYW5uZWwgcG9ydDogJWQgIGlycTogJWRcbiIsIF9fZnVu Y19fLAo+ICsJCXBvcnQsCj4gKwkJcmluZ19pbmZvLT5pcnEpOwo+ICsKPiArCXJldCA9IGh5cGVy X2RtYWJ1Zl9yZWdpc3Rlcl9pbXBvcnRlcl9yaW5nKHJpbmdfaW5mbyk7Cj4gKwo+ICsJcmV0dXJu IHJldDsKPiArfQo+ICsKPiAraW50IGh5cGVyX2RtYWJ1Zl9zZW5kX3JlcXVlc3QoaW50IGRvbWFp biwgc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX3JxICpyZXEpCj4gK3sKPiArCXN0cnVjdCBoeXBl cl9kbWFidWZfZnJvbnRfcmluZyAqcmluZzsKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19y cSAqbmV3X3JlcTsKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19pbmZvX2V4cG9ydCAqcmlu Z19pbmZvOwo+ICsJaW50IG5vdGlmeTsKPiArCj4gKwkvKiBmaW5kIGEgcmluZyBpbmZvIGZvciB0 aGUgY2hhbm5lbCAqLwo+ICsJcmluZ19pbmZvID0gaHlwZXJfZG1hYnVmX2ZpbmRfZXhwb3J0ZXJf cmluZyhkb21haW4pOwo+ICsJaWYgKCFyaW5nX2luZm8pIHsKPiArCQlwcmludGsoIkNhbid0IGZp bmQgcmluZyBpbmZvIGZvciB0aGUgY2hhbm5lbFxuIik7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4g Kwl9Cj4gKwo+ICsJcmluZyA9ICZyaW5nX2luZm8tPnJpbmdfZnJvbnQ7Cj4gKwo+ICsJaWYgKFJJ TkdfRlVMTChyaW5nKSkKPiArCQlyZXR1cm4gLUVCVVNZOwo+ICsKPiArCW5ld19yZXEgPSBSSU5H X0dFVF9SRVFVRVNUKHJpbmcsIHJpbmctPnJlcV9wcm9kX3B2dCk7Cj4gKwlpZiAoIW5ld19yZXEp IHsKPiArCQlwcmludGsoIk5VTEwgUkVRVUVTVFxuIik7Cj4gKwkJcmV0dXJuIC1FSU87Cj4gKwl9 Cj4gKwo+ICsJbWVtY3B5KG5ld19yZXEsIHJlcSwgc2l6ZW9mKCpuZXdfcmVxKSk7Cj4gKwo+ICsJ cmluZy0+cmVxX3Byb2RfcHZ0Kys7Cj4gKwo+ICsJUklOR19QVVNIX1JFUVVFU1RTX0FORF9DSEVD S19OT1RJRlkocmluZywgbm90aWZ5KTsKPiArCWlmIChub3RpZnkpIHsKPiArCQlub3RpZnlfcmVt b3RlX3ZpYV9pcnEocmluZ19pbmZvLT5pcnEpOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9 Cj4gKwo+ICsvKiBjYWxsZWQgYnkgaW50ZXJydXB0IChXT1JLUVVFVUUpICovCj4gK2ludCBoeXBl cl9kbWFidWZfc2VuZF9yZXNwb25zZShzdHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfcnAqIHJlc3Bv bnNlLCBpbnQgZG9tYWluKQo+ICt7Cj4gKwkvKiBhcyBhIGltcG9ydGVyIGFuZCBhcyBhIGV4cG9y dGVyICovCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArLyogSVNSIGZvciByZXF1ZXN0IGZyb20g ZXhwb3J0ZXIgKGFzIGFuIGltcG9ydGVyKSAqLwo+ICtzdGF0aWMgaXJxcmV0dXJuX3QgaHlwZXJf ZG1hYnVmX2JhY2tfcmluZ19pc3IoaW50IGlycSwgdm9pZCAqZGV2X2lkKQo+ICt7Cj4gKwlSSU5H X0lEWCByYywgcnA7Cj4gKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfcnEgcmVxdWVzdDsKPiAr CXN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19ycCByZXNwb25zZTsKPiArCWludCBub3RpZnksIG1v cmVfdG9fZG87Cj4gKwlpbnQgcmV0Owo+ICsvLwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3dvcmsgKndv cms7Cj4gKwo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9faW1wb3J0ICpyaW5nX2lu Zm8gPSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9faW1wb3J0ICopZGV2X2lkOwo+ICsJ c3RydWN0IGh5cGVyX2RtYWJ1Zl9iYWNrX3JpbmcgKnJpbmc7Cj4gKwo+ICsJcmluZyA9ICZyaW5n X2luZm8tPnJpbmdfYmFjazsKPiArCj4gKwlkbyB7Cj4gKwkJcmMgPSByaW5nLT5yZXFfY29uczsK PiArCQlycCA9IHJpbmctPnNyaW5nLT5yZXFfcHJvZDsKPiArCj4gKwkJd2hpbGUgKHJjICE9IHJw KSB7Cj4gKwkJCWlmIChSSU5HX1JFUVVFU1RfQ09OU19PVkVSRkxPVyhyaW5nLCByYykpCj4gKwkJ CQlicmVhazsKPiArCj4gKwkJCW1lbWNweSgmcmVxdWVzdCwgUklOR19HRVRfUkVRVUVTVChyaW5n LCByYyksIHNpemVvZihyZXF1ZXN0KSk7Cj4gKwkJCXByaW50aygiR290IHJlcXVlc3RcbiIpOwo+ ICsJCQlyaW5nLT5yZXFfY29ucyA9ICsrcmM7Cj4gKwo+ICsJCQkvKiBUT0RPOiBwcm9iYWJseSB1 c2luZyBsaW5rZWQgbGlzdCBmb3IgbXVsdGlwbGUgcmVxdWVzdHMgdGhlbiBsZXQKPiArCQkJICog YSB0YXNrIGluIGEgd29ya3F1ZXVlIHRvIHByb2Nlc3MgdGhvc2UgaXMgYmV0dGVyIGlkZWEgYmVj dWFzZQo+ICsJCQkgKiB3ZSBkbyBub3Qgd2FudCB0byBzdGF5IGluIElTUiBmb3IgbG9uZy4KPiAr CQkJICovCj4gKwkJCXJldCA9IGh5cGVyX2RtYWJ1Zl9tc2dfcGFyc2UocmluZ19pbmZvLT5zZG9t YWluLCAmcmVxdWVzdCk7Cj4gKwo+ICsJCQlpZiAocmV0ID4gMCkgewo+ICsJCQkJLyogYnVpbGQg cmVzcG9uc2UgKi8KPiArCQkJCW1lbWNweSgmcmVzcG9uc2UsICZyZXF1ZXN0LCBzaXplb2YocmVz cG9uc2UpKTsKPiArCj4gKwkJCQkvKiB3ZSBzZW50IGJhY2sgbW9kaWZpZWQgcmVxdWVzdCBhcyBh IHJlc3BvbnNlLi4gd2UgbWlnaHQganVzdCBuZWVkIHRvIGhhdmUgcmVxdWVzdCBvbmx5Li4qLwo+ ICsJCQkJbWVtY3B5KFJJTkdfR0VUX1JFU1BPTlNFKHJpbmcsIHJpbmctPnJzcF9wcm9kX3B2dCks ICZyZXNwb25zZSwgc2l6ZW9mKHJlc3BvbnNlKSk7Cj4gKwkJCQlyaW5nLT5yc3BfcHJvZF9wdnQr KzsKPiArCj4gKwkJCQlSSU5HX1BVU0hfUkVTUE9OU0VTX0FORF9DSEVDS19OT1RJRlkocmluZywg bm90aWZ5KTsKPiArCj4gKwkJCQlpZiAobm90aWZ5KSB7Cj4gKwkJCQkJcHJpbnRrKCJOb3R5Zmlu Z1xuIik7Cj4gKwkJCQkJbm90aWZ5X3JlbW90ZV92aWFfaXJxKHJpbmdfaW5mby0+aXJxKTsKPiAr CQkJCX0KPiArCQkJfQo+ICsKPiArCQkJUklOR19GSU5BTF9DSEVDS19GT1JfUkVRVUVTVFMocmlu ZywgbW9yZV90b19kbyk7Cj4gKwkJCXByaW50aygiRmluYWwgY2hlY2sgZm9yIHJlcXVlc3RzICVk XG4iLCBtb3JlX3RvX2RvKTsKPiArCQl9Cj4gKwl9IHdoaWxlIChtb3JlX3RvX2RvKTsKPiArCj4g KwlyZXR1cm4gSVJRX0hBTkRMRUQ7Cj4gK30KPiArCj4gKy8qIElTUiBmb3IgcmVzcG9uc2VzIGZy b20gaW1wb3J0ZXIgKi8KPiArc3RhdGljIGlycXJldHVybl90IGh5cGVyX2RtYWJ1Zl9mcm9udF9y aW5nX2lzcihpbnQgaXJxLCB2b2lkICpkZXZfaWQpCj4gK3sKPiArCS8qIGZyb250IHJpbmcgb25s eSBjYXJlIGFib3V0IHJlc3BvbnNlIGZyb20gYmFjayAqLwo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1 Zl9yaW5nX3JwICpyZXNwb25zZTsKPiArCVJJTkdfSURYIGksIHJwOwo+ICsJaW50IG1vcmVfdG9f ZG8sIHJldDsKPiArCj4gKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfaW5mb19leHBvcnQgKnJp bmdfaW5mbyA9IChzdHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfaW5mb19leHBvcnQgKilkZXZfaWQ7 Cj4gKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX2Zyb250X3JpbmcgKnJpbmc7Cj4gKwlyaW5nID0gJnJp bmdfaW5mby0+cmluZ19mcm9udDsKPiArCj4gKwlkbyB7Cj4gKwkJbW9yZV90b19kbyA9IDA7Cj4g KwkJcnAgPSByaW5nLT5zcmluZy0+cnNwX3Byb2Q7Cj4gKwkJZm9yIChpID0gcmluZy0+cnNwX2Nv bnM7IGkgIT0gcnA7IGkrKykgewo+ICsJCQl1bnNpZ25lZCBsb25nIGlkOwo+ICsKPiArCQkJcmVz cG9uc2UgPSBSSU5HX0dFVF9SRVNQT05TRShyaW5nLCBpKTsKPiArCQkJaWQgPSByZXNwb25zZS0+ cmVzcG9uc2VfaWQ7Cj4gKwo+ICsJCQlpZiAocmVzcG9uc2UtPnN0YXR1cyA9PSBIWVBFUl9ETUFC VUZfUkVRX05FRURTX0ZPTExPV19VUCkgewo+ICsJCQkJLyogcGFyc2luZyByZXNwb25zZSAqLwo+ ICsJCQkJcmV0ID0gaHlwZXJfZG1hYnVmX21zZ19wYXJzZShyaW5nX2luZm8tPnJkb21haW4sIChz dHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfcnEqKXJlc3BvbnNlKTsKPiArCj4gKwkJCQlpZiAocmV0 IDwgMCkgewo+ICsJCQkJCXByaW50aygiZ2V0dGluZyBlcnJvciB3aGlsZSBwYXJzaW5nIHJlc3Bv bnNlXG4iKTsKPiArCQkJCX0KPiArCQkJfSBlbHNlIGlmIChyZXNwb25zZS0+c3RhdHVzID09IEhZ UEVSX0RNQUJVRl9SRVFfRVJST1IpIHsKPiArCQkJCXByaW50aygicmVtb3RlIGRvbWFpbiAlZCBj b3VsZG4ndCBwcm9jZXNzIHJlcXVlc3QgJWRcbiIsIHJpbmdfaW5mby0+cmRvbWFpbiwgcmVzcG9u c2UtPmNvbW1hbmQpOwo+ICsJCQl9Cj4gKwo+ICsJCX0KPiArCj4gKwkJcmluZy0+cnNwX2NvbnMg PSBpOwo+ICsKPiArCQlpZiAoaSAhPSByaW5nLT5yZXFfcHJvZF9wdnQpIHsKPiArCQkJUklOR19G SU5BTF9DSEVDS19GT1JfUkVTUE9OU0VTKHJpbmcsIG1vcmVfdG9fZG8pOwo+ICsJCQlwcmludGso Im1vcmUgdG8gZG8gJWRcbiIsIG1vcmVfdG9fZG8pOwo+ICsJCX0gZWxzZSB7Cj4gKwkJCXJpbmct PnNyaW5nLT5yc3BfZXZlbnQgPSBpKzE7Cj4gKwkJfQo+ICsJfSB3aGlsZSAobW9yZV90b19kbyk7 Cj4gKwo+ICsJcmV0dXJuIElSUV9IQU5ETEVEOwo+ICt9Cj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMv eGVuL2h5cGVyX2RtYWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tLmggYi9kcml2ZXJzL3hl bi9oeXBlcl9kbWFidWYveGVuL2h5cGVyX2RtYWJ1Zl94ZW5fY29tbS5oCj4gbmV3IGZpbGUgbW9k ZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwLi4yNzU0OTE3Cj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBi L2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tLmgKPiBA QCAtMCwwICsxLDYyIEBACj4gKyNpZm5kZWYgX19IWVBFUl9ETUFCVUZfWEVOX0NPTU1fSF9fCj4g KyNkZWZpbmUgX19IWVBFUl9ETUFCVUZfWEVOX0NPTU1fSF9fCj4gKwo+ICsjaW5jbHVkZSAieGVu L2ludGVyZmFjZS9pby9yaW5nLmgiCj4gKwo+ICsjZGVmaW5lIE1BWF9OVU1CRVJfT0ZfT1BFUkFO RFMgOQo+ICsKPiArc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX3JxIHsKPiArICAgICAgICB1bnNp Z25lZCBpbnQgcmVxdWVzdF9pZDsKPiArICAgICAgICB1bnNpZ25lZCBpbnQgc3RhdHVzOwo+ICsg ICAgICAgIHVuc2lnbmVkIGludCBjb21tYW5kOwo+ICsgICAgICAgIHVuc2lnbmVkIGludCBvcGVy YW5kc1tNQVhfTlVNQkVSX09GX09QRVJBTkRTXTsKPiArfTsKPiArCj4gK3N0cnVjdCBoeXBlcl9k bWFidWZfcmluZ19ycCB7Cj4gKyAgICAgICAgdW5zaWduZWQgaW50IHJlc3BvbnNlX2lkOwo+ICsg ICAgICAgIHVuc2lnbmVkIGludCBzdGF0dXM7Cj4gKyAgICAgICAgdW5zaWduZWQgaW50IGNvbW1h bmQ7Cj4gKyAgICAgICAgdW5zaWduZWQgaW50IG9wZXJhbmRzW01BWF9OVU1CRVJfT0ZfT1BFUkFO RFNdOwo+ICt9Owo+ICsKPiArREVGSU5FX1JJTkdfVFlQRVMoaHlwZXJfZG1hYnVmLCBzdHJ1Y3Qg aHlwZXJfZG1hYnVmX3JpbmdfcnEsIHN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19ycCk7Cj4gKwo+ ICtzdHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfaW5mb19leHBvcnQgewo+ICsgICAgICAgIHN0cnVj dCBoeXBlcl9kbWFidWZfZnJvbnRfcmluZyByaW5nX2Zyb250Owo+ICsJaW50IHJkb21haW47Cj4g KyAgICAgICAgaW50IGdyZWZfcmluZzsKPiArICAgICAgICBpbnQgaXJxOwo+ICsgICAgICAgIGlu dCBwb3J0Owo+ICt9Owo+ICsKPiArc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9faW1wb3J0 IHsKPiArICAgICAgICBpbnQgc2RvbWFpbjsKPiArICAgICAgICBpbnQgaXJxOwo+ICsgICAgICAg IGludCBldnRjaG47Cj4gKyAgICAgICAgc3RydWN0IGh5cGVyX2RtYWJ1Zl9iYWNrX3Jpbmcgcmlu Z19iYWNrOwo+ICt9Owo+ICsKPiArLy9zdHJ1Y3QgaHlwZXJfZG1hYnVmX3dvcmsgewo+ICsvLwlo eXBlcl9kbWFidWZfcmluZ19ycSByZXF1cmVzdDsKPiArLy8Jc3RydWN0IHdvcmtfc3RydWN0IG1z Z19wYXJzZTsKPiArLy99Owo+ICsKPiAraW50MzJfdCBoeXBlcl9kbWFidWZfZ2V0X2RvbWlkKHZv aWQpOwo+ICsKPiAraW50IGh5cGVyX2RtYWJ1Zl9uZXh0X3JlcV9pZF9leHBvcnQodm9pZCk7Cj4g Kwo+ICtpbnQgaHlwZXJfZG1hYnVmX25leHRfcmVxX2lkX2ltcG9ydCh2b2lkKTsKPiArCj4gKy8q IGV4cG9ydGVyIG5lZWRzIHRvIGdlbmVyYXRlZCBpbmZvIGZvciBwYWdlIHNoYXJpbmcgKi8KPiAr aW50IGh5cGVyX2RtYWJ1Zl9leHBvcnRlcl9yaW5nYnVmX2luaXQoaW50IHJkb21haW4sIGdyYW50 X3JlZl90ICpncmVmLCBpbnQgKnBvcnQpOwo+ICsKPiArLyogaW1wb3J0ZXIgbmVlZHMgdG8ga25v dyBhYm91dCBzaGFyZWQgcGFnZSBhbmQgcG9ydCBudW1iZXJzIGZvciByaW5nIGJ1ZmZlciBhbmQg ZXZlbnQgY2hhbm5lbCAqLwo+ICtpbnQgaHlwZXJfZG1hYnVmX2ltcG9ydGVyX3JpbmdidWZfaW5p dChpbnQgc2RvbWFpbiwgZ3JhbnRfcmVmX3QgZ3JlZiwgaW50IHBvcnQpOwo+ICsKPiArLyogc2Vu ZCByZXF1ZXN0IHRvIHRoZSByZW1vdGUgZG9tYWluICovCj4gK2ludCBoeXBlcl9kbWFidWZfc2Vu ZF9yZXF1ZXN0KGludCBkb21haW4sIHN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19ycSAqcmVxKTsK PiArCj4gKy8qIGNhbGxlZCBieSBpbnRlcnJ1cHQgKFdPUktRVUVVRSkgKi8KPiAraW50IGh5cGVy X2RtYWJ1Zl9zZW5kX3Jlc3BvbnNlKHN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19ycCogcmVzcG9u c2UsIGludCBkb21haW4pOwo+ICsKPiArI2VuZGlmIC8vIF9fSFlQRVJfRE1BQlVGX1hFTl9DT01N X0hfXwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYveGVuL2h5cGVyX2Rt YWJ1Zl94ZW5fY29tbV9saXN0LmMgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYveGVuL2h5cGVy X2RtYWJ1Zl94ZW5fY29tbV9saXN0LmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAw MDAwMDAuLjE1YzlkMjkKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy94ZW4vaHlwZXJf ZG1hYnVmL3hlbi9oeXBlcl9kbWFidWZfeGVuX2NvbW1fbGlzdC5jCj4gQEAgLTAsMCArMSwxMDYg QEAKPiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgo+ICsjaW5jbHVkZSA8bGludXgvZXJybm8u aD4KPiArI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvc2xhYi5o Pgo+ICsjaW5jbHVkZSA8bGludXgvY2Rldi5oPgo+ICsjaW5jbHVkZSA8YXNtL3VhY2Nlc3MuaD4K PiArI2luY2x1ZGUgPGxpbnV4L2hhc2h0YWJsZS5oPgo+ICsjaW5jbHVkZSA8eGVuL2dyYW50X3Rh YmxlLmg+Cj4gKyNpbmNsdWRlICJoeXBlcl9kbWFidWZfeGVuX2NvbW0uaCIKPiArI2luY2x1ZGUg Imh5cGVyX2RtYWJ1Zl94ZW5fY29tbV9saXN0LmgiCj4gKwo+ICtERUNMQVJFX0hBU0hUQUJMRSho eXBlcl9kbWFidWZfaGFzaF9pbXBvcnRlcl9yaW5nLCBNQVhfRU5UUllfSU1QT1JUX1JJTkcpOwo+ ICtERUNMQVJFX0hBU0hUQUJMRShoeXBlcl9kbWFidWZfaGFzaF9leHBvcnRlcl9yaW5nLCBNQVhf RU5UUllfRVhQT1JUX1JJTkcpOwo+ICsKPiAraW50IGh5cGVyX2RtYWJ1Zl9yaW5nX3RhYmxlX2lu aXQoKQo+ICt7Cj4gKwloYXNoX2luaXQoaHlwZXJfZG1hYnVmX2hhc2hfaW1wb3J0ZXJfcmluZyk7 Cj4gKwloYXNoX2luaXQoaHlwZXJfZG1hYnVmX2hhc2hfZXhwb3J0ZXJfcmluZyk7Cj4gKwlyZXR1 cm4gMDsKPiArfQo+ICsKPiAraW50IGh5cGVyX2RtYWJ1Zl9yaW5nX3RhYmxlX2Rlc3Ryb3koKQo+ ICt7Cj4gKwkvKiBUT0RPOiBjbGVhbnVwIHRhYmxlcyovCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsK PiAraW50IGh5cGVyX2RtYWJ1Zl9yZWdpc3Rlcl9leHBvcnRlcl9yaW5nKHN0cnVjdCBoeXBlcl9k bWFidWZfcmluZ19pbmZvX2V4cG9ydCAqcmluZ19pbmZvKQo+ICt7Cj4gKwlzdHJ1Y3QgaHlwZXJf ZG1hYnVmX2V4cG9ydGVyX3JpbmdfaW5mbyAqaW5mb19lbnRyeTsKPiArCj4gKwlpbmZvX2VudHJ5 ID0ga21hbGxvYyhzaXplb2YoKmluZm9fZW50cnkpLCBHRlBfS0VSTkVMKTsKPiArCj4gKwlpbmZv X2VudHJ5LT5pbmZvID0gcmluZ19pbmZvOwo+ICsKPiArCWhhc2hfYWRkKGh5cGVyX2RtYWJ1Zl9o YXNoX2V4cG9ydGVyX3JpbmcsICZpbmZvX2VudHJ5LT5ub2RlLAo+ICsJCWluZm9fZW50cnktPmlu Zm8tPnJkb21haW4pOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtpbnQgaHlwZXJfZG1h YnVmX3JlZ2lzdGVyX2ltcG9ydGVyX3Jpbmcoc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9f aW1wb3J0ICpyaW5nX2luZm8pCj4gK3sKPiArCXN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZXJf cmluZ19pbmZvICppbmZvX2VudHJ5Owo+ICsKPiArCWluZm9fZW50cnkgPSBrbWFsbG9jKHNpemVv ZigqaW5mb19lbnRyeSksIEdGUF9LRVJORUwpOwo+ICsKPiArCWluZm9fZW50cnktPmluZm8gPSBy aW5nX2luZm87Cj4gKwo+ICsJaGFzaF9hZGQoaHlwZXJfZG1hYnVmX2hhc2hfaW1wb3J0ZXJfcmlu ZywgJmluZm9fZW50cnktPm5vZGUsCj4gKwkJaW5mb19lbnRyeS0+aW5mby0+c2RvbWFpbik7Cj4g Kwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19pbmZv X2V4cG9ydCAqaHlwZXJfZG1hYnVmX2ZpbmRfZXhwb3J0ZXJfcmluZyhpbnQgZG9taWQpCj4gK3sK PiArCXN0cnVjdCBoeXBlcl9kbWFidWZfZXhwb3J0ZXJfcmluZ19pbmZvICppbmZvX2VudHJ5Owo+ ICsJaW50IGJrdDsKPiArCj4gKwloYXNoX2Zvcl9lYWNoKGh5cGVyX2RtYWJ1Zl9oYXNoX2V4cG9y dGVyX3JpbmcsIGJrdCwgaW5mb19lbnRyeSwgbm9kZSkKPiArCQlpZihpbmZvX2VudHJ5LT5pbmZv LT5yZG9tYWluID09IGRvbWlkKQo+ICsJCQlyZXR1cm4gaW5mb19lbnRyeS0+aW5mbzsKPiArCj4g KwlyZXR1cm4gTlVMTDsKPiArfQo+ICsKPiArc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9f aW1wb3J0ICpoeXBlcl9kbWFidWZfZmluZF9pbXBvcnRlcl9yaW5nKGludCBkb21pZCkKPiArewo+ ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlcl9yaW5nX2luZm8gKmluZm9fZW50cnk7Cj4g KwlpbnQgYmt0Owo+ICsKPiArCWhhc2hfZm9yX2VhY2goaHlwZXJfZG1hYnVmX2hhc2hfaW1wb3J0 ZXJfcmluZywgYmt0LCBpbmZvX2VudHJ5LCBub2RlKQo+ICsJCWlmKGluZm9fZW50cnktPmluZm8t PnNkb21haW4gPT0gZG9taWQpCj4gKwkJCXJldHVybiBpbmZvX2VudHJ5LT5pbmZvOwo+ICsKPiAr CXJldHVybiBOVUxMOwo+ICt9Cj4gKwo+ICtpbnQgaHlwZXJfZG1hYnVmX3JlbW92ZV9leHBvcnRl cl9yaW5nKGludCBkb21pZCkKPiArewo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9leHBvcnRlcl9y aW5nX2luZm8gKmluZm9fZW50cnk7Cj4gKwlpbnQgYmt0Owo+ICsKPiArCWhhc2hfZm9yX2VhY2go aHlwZXJfZG1hYnVmX2hhc2hfZXhwb3J0ZXJfcmluZywgYmt0LCBpbmZvX2VudHJ5LCBub2RlKQo+ ICsJCWlmKGluZm9fZW50cnktPmluZm8tPnJkb21haW4gPT0gZG9taWQpIHsKPiArCQkJaGFzaF9k ZWwoJmluZm9fZW50cnktPm5vZGUpOwo+ICsJCQlyZXR1cm4gMDsKPiArCQl9Cj4gKwo+ICsJcmV0 dXJuIC0xOwo+ICt9Cj4gKwo+ICtpbnQgaHlwZXJfZG1hYnVmX3JlbW92ZV9pbXBvcnRlcl9yaW5n KGludCBkb21pZCkKPiArewo+ICsJc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlcl9yaW5nX2lu Zm8gKmluZm9fZW50cnk7Cj4gKwlpbnQgYmt0Owo+ICsKPiArCWhhc2hfZm9yX2VhY2goaHlwZXJf ZG1hYnVmX2hhc2hfaW1wb3J0ZXJfcmluZywgYmt0LCBpbmZvX2VudHJ5LCBub2RlKQo+ICsJCWlm KGluZm9fZW50cnktPmluZm8tPnNkb21haW4gPT0gZG9taWQpIHsKPiArCQkJaGFzaF9kZWwoJmlu Zm9fZW50cnktPm5vZGUpOwo+ICsJCQlyZXR1cm4gMDsKPiArCQl9Cj4gKwo+ICsJcmV0dXJuIC0x Owo+ICt9Cj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi94ZW4vaHlwZXJf ZG1hYnVmX3hlbl9jb21tX2xpc3QuaCBiL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi94ZW4vaHlw ZXJfZG1hYnVmX3hlbl9jb21tX2xpc3QuaAo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXgg MDAwMDAwMC4uNTkyOWY5OQo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL3hlbi9oeXBl cl9kbWFidWYveGVuL2h5cGVyX2RtYWJ1Zl94ZW5fY29tbV9saXN0LmgKPiBAQCAtMCwwICsxLDM1 IEBACj4gKyNpZm5kZWYgX19IWVBFUl9ETUFCVUZfWEVOX0NPTU1fTElTVF9IX18KPiArI2RlZmlu ZSBfX0hZUEVSX0RNQUJVRl9YRU5fQ09NTV9MSVNUX0hfXwo+ICsKPiArLyogbnVtYmVyIG9mIGJp dHMgdG8gYmUgdXNlZCBmb3IgZXhwb3J0ZWQgZG1hYnVmcyBoYXNoIHRhYmxlICovCj4gKyNkZWZp bmUgTUFYX0VOVFJZX0VYUE9SVF9SSU5HIDcKPiArLyogbnVtYmVyIG9mIGJpdHMgdG8gYmUgdXNl ZCBmb3IgaW1wb3J0ZWQgZG1hYnVmcyBoYXNoIHRhYmxlICovCj4gKyNkZWZpbmUgTUFYX0VOVFJZ X0lNUE9SVF9SSU5HIDcKPiArCj4gK3N0cnVjdCBoeXBlcl9kbWFidWZfZXhwb3J0ZXJfcmluZ19p bmZvIHsKPiArICAgICAgICBzdHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfaW5mb19leHBvcnQgKmlu Zm87Cj4gKyAgICAgICAgc3RydWN0IGhsaXN0X25vZGUgbm9kZTsKPiArfTsKPiArCj4gK3N0cnVj dCBoeXBlcl9kbWFidWZfaW1wb3J0ZXJfcmluZ19pbmZvIHsKPiArICAgICAgICBzdHJ1Y3QgaHlw ZXJfZG1hYnVmX3JpbmdfaW5mb19pbXBvcnQgKmluZm87Cj4gKyAgICAgICAgc3RydWN0IGhsaXN0 X25vZGUgbm9kZTsKPiArfTsKPiArCj4gK2ludCBoeXBlcl9kbWFidWZfcmluZ190YWJsZV9pbml0 KHZvaWQpOwo+ICsKPiAraW50IGh5cGVyX2RtYWJ1Zl9yaW5nX3RhYmxlX2Rlc3Ryb3kodm9pZCk7 Cj4gKwo+ICtpbnQgaHlwZXJfZG1hYnVmX3JlZ2lzdGVyX2V4cG9ydGVyX3Jpbmcoc3RydWN0IGh5 cGVyX2RtYWJ1Zl9yaW5nX2luZm9fZXhwb3J0ICpyaW5nX2luZm8pOwo+ICsKPiAraW50IGh5cGVy X2RtYWJ1Zl9yZWdpc3Rlcl9pbXBvcnRlcl9yaW5nKHN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19p bmZvX2ltcG9ydCAqcmluZ19pbmZvKTsKPiArCj4gK3N0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19p bmZvX2V4cG9ydCAqaHlwZXJfZG1hYnVmX2ZpbmRfZXhwb3J0ZXJfcmluZyhpbnQgZG9taWQpOwo+ ICsKPiArc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9faW1wb3J0ICpoeXBlcl9kbWFidWZf ZmluZF9pbXBvcnRlcl9yaW5nKGludCBkb21pZCk7Cj4gKwo+ICtpbnQgaHlwZXJfZG1hYnVmX3Jl bW92ZV9leHBvcnRlcl9yaW5nKGludCBkb21pZCk7Cj4gKwo+ICtpbnQgaHlwZXJfZG1hYnVmX3Jl bW92ZV9pbXBvcnRlcl9yaW5nKGludCBkb21pZCk7Cj4gKwo+ICsjZW5kaWYgLy8gX19IWVBFUl9E TUFCVUZfWEVOX0NPTU1fTElTVF9IX18KPiAtLSAKPiAyLjcuNAo+IAo+IApfX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpkcmktZGV2ZWwgbWFpbGluZyBsaXN0 CmRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcKaHR0cHM6Ly9saXN0cy5mcmVlZGVza3Rv cC5vcmcvbWFpbG1hbi9saXN0aW5mby9kcmktZGV2ZWwK