From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-21.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 059BDC433E0 for ; Wed, 20 Jan 2021 17:15:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AAF10233E2 for ; Wed, 20 Jan 2021 17:15:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404108AbhATRPM (ORCPT ); Wed, 20 Jan 2021 12:15:12 -0500 Received: from asav21.altibox.net ([109.247.116.8]:32920 "EHLO asav21.altibox.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404155AbhATRMI (ORCPT ); Wed, 20 Jan 2021 12:12:08 -0500 X-Greylist: delayed 595 seconds by postgrey-1.27 at vger.kernel.org; Wed, 20 Jan 2021 12:11:52 EST Received: from localhost.localdomain (unknown [81.166.168.211]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: noralf.tronnes@ebnett.no) by asav21.altibox.net (Postfix) with ESMTPSA id A68D280161; Wed, 20 Jan 2021 18:00:53 +0100 (CET) From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Cc: linux-usb@vger.kernel.org, sam@ravnborg.org, peter@stuge.se, lkundrak@v3.sk, markus@raatikainen.cc, pontus.fuchs@gmail.com, hudson@trmm.net, th020394@gmail.com, =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Subject: [PATCH v4 3/3] drm: Add Generic USB Display driver Date: Wed, 20 Jan 2021 18:00:33 +0100 Message-Id: <20210120170033.38468-4-noralf@tronnes.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20210120170033.38468-1-noralf@tronnes.org> References: <20210120170033.38468-1-noralf@tronnes.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-CMAE-Score: 0 X-CMAE-Analysis: v=2.3 cv=LfoSFAXi c=1 sm=1 tr=0 a=OYZzhG0JTxDrWp/F2OJbnw==:117 a=OYZzhG0JTxDrWp/F2OJbnw==:17 a=IkcTkHD0fZMA:10 a=M51BFTxLslgA:10 a=SJz97ENfAAAA:8 a=gAmX6pxEAAAA:20 a=e5mUnYsNAAAA:8 a=20KFwNOVAAAA:8 a=5BARwAl1Z-KXKs0cIXUA:9 a=Xr9BYLAfEHlT6O8Q:21 a=rLqREtmTxl6zVh9-:21 a=QEXdDO2ut3YA:10 a=vFet0B0WnEQeilDPIY6i:22 a=Vxmtnl_E_bksehYqCbjh:22 a=pHzHmUro8NiASowvMSCR:22 a=nt3jZW36AmriUCFCBwmW:22 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This adds a generic USB display driver with the intention that it can be used with future USB interfaced low end displays/adapters. The Linux gadget device driver will serve as the canonical device implementation. The following DRM properties are supported: - Plane rotation - Connector TV properties There is also support for backlight brightness exposed as a backlight device. Display modes can be made available to the host driver either as DRM display modes or through EDID. If both are present, EDID is just passed on to userspace. Performance is preferred over color depth, so if the device supports RGB565, DRM_CAP_DUMB_PREFERRED_DEPTH will return 16. If the device transfer buffer can't fit an uncompressed framebuffer update, the update is split up into parts that do fit. Optimal user experience is achieved by providing damage reports either by setting FB_DAMAGE_CLIPS on pageflips or calling DRM_IOCTL_MODE_DIRTYFB. LZ4 compression is used if the device supports it. The driver supports a one bit monochrome transfer format: R1. This is not implemented in the gadget driver. It is added in preparation for future monochrome e-ink displays. The driver is MIT licensed to smooth the path for any BSD port of the driver. v2: - Use devm_drm_dev_alloc() and drmm_mode_config_init() - drm_fbdev_generic_setup: Use preferred_bpp=0, 16 was a copy paste error - The drm_backlight_helper is dropped, copy in the code - Support protocol version backwards compatibility for device v3: - Use donated Openmoko USB pid - Use direct compression from framebuffer when pitch matches, not only on full frames, so split updates can benefit - Use __le16 in struct gud_drm_req_get_connector_status - Set edid property when the device only provides edid - Clear compression fields in struct gud_drm_req_set_buffer - Fix protocol version negotiation - Remove mode->vrefresh, it's calculated v4: - Drop the status req polling which was a workaround for something that turned out to be a dwc2 udc driver problem - Add a flag for the Linux gadget to require a status request on SET operations. Other devices will only get status req on STALL errors - Use protocol specific error codes (Peter) - Add a flag for devices that want to receive the entire framebuffer on each flush (Lubomir) - Retry a failed framebuffer flush - If mode has changed wait for worker and clear pending damage before queuing up new damage, fb width/height might have changed - Increase error counter on bulk transfer failures - Use DRM_MODE_CONNECTOR_USB - Handle R1 kmalloc error (Peter) - Don't try and replicate the USB get descriptor request standard for the display descriptor (Peter) - Make max_buffer_size optional (Peter), drop the pow2 requirement since it's not necessary anymore. - Don't pre-alloc a control request buffer, it was only 4k - Let gud.h describe the whole protocol explicitly and don't let DRM leak into it (Peter) - Drop display mode .hskew and .vscan from the protocol - Shorten names: s/GUD_DRM_/GUD_/ s/gud_drm_/gud_/ (Peter) - Fix gud_pipe_check() connector picking when switching connector - Drop gud_drm_driver_gem_create_object() cached is default now - Retrieve USB device from struct drm_device.dev instead of keeping a pointer - Honour fb->offsets[0] - Fix mode fetching when connector status is forced - Check EDID length reported by the device - Use drm_do_get_edid() so userspace can overrride EDID - Set epoch counter to signal connector status change - gud_drm_driver can be const now Cc: Peter Stuge Cc: Lubomir Rintel Signed-off-by: Noralf Trønnes --- MAINTAINERS | 8 + drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/gud/Kconfig | 14 + drivers/gpu/drm/gud/Makefile | 4 + drivers/gpu/drm/gud/gud_connector.c | 722 ++++++++++++++++++++++++++++ drivers/gpu/drm/gud/gud_drv.c | 620 ++++++++++++++++++++++++ drivers/gpu/drm/gud/gud_internal.h | 148 ++++++ drivers/gpu/drm/gud/gud_pipe.c | 472 ++++++++++++++++++ include/drm/gud.h | 356 ++++++++++++++ 10 files changed, 2347 insertions(+) create mode 100644 drivers/gpu/drm/gud/Kconfig create mode 100644 drivers/gpu/drm/gud/Makefile create mode 100644 drivers/gpu/drm/gud/gud_connector.c create mode 100644 drivers/gpu/drm/gud/gud_drv.c create mode 100644 drivers/gpu/drm/gud/gud_internal.h create mode 100644 drivers/gpu/drm/gud/gud_pipe.c create mode 100644 include/drm/gud.h diff --git a/MAINTAINERS b/MAINTAINERS index 00112c044608..e7f71ac55f08 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5525,6 +5525,14 @@ S: Maintained F: Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.yaml F: drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c +DRM DRIVER FOR GENERIC USB DISPLAY +M: Noralf Trønnes +S: Maintained +W: https://github.com/notro/gud/wiki +T: git git://anongit.freedesktop.org/drm/drm-misc +F: drivers/gpu/drm/gud/ +F: include/drm/gud.h + DRM DRIVER FOR GRAIN MEDIA GM12U320 PROJECTORS M: Hans de Goede S: Maintained diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 147d61b9674e..6d3f47933e51 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -388,6 +388,8 @@ source "drivers/gpu/drm/tidss/Kconfig" source "drivers/gpu/drm/xlnx/Kconfig" +source "drivers/gpu/drm/gud/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACY diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 81569009f884..78dd8e12525d 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -124,3 +124,4 @@ obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/ obj-$(CONFIG_DRM_MCDE) += mcde/ obj-$(CONFIG_DRM_TIDSS) += tidss/ obj-y += xlnx/ +obj-y += gud/ diff --git a/drivers/gpu/drm/gud/Kconfig b/drivers/gpu/drm/gud/Kconfig new file mode 100644 index 000000000000..d832cd63687c --- /dev/null +++ b/drivers/gpu/drm/gud/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 + +config DRM_GUD + tristate "Generic USB Display" + depends on DRM && USB + select LZ4_COMPRESS + select DRM_KMS_HELPER + select DRM_GEM_SHMEM_HELPER + select BACKLIGHT_CLASS_DEVICE + help + This is a DRM display driver for Generic USB Displays or display + adapters. + + If M is selected the module will be called gud. diff --git a/drivers/gpu/drm/gud/Makefile b/drivers/gpu/drm/gud/Makefile new file mode 100644 index 000000000000..d2bb53a65de6 --- /dev/null +++ b/drivers/gpu/drm/gud/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +gud-objs := gud_drv.o gud_pipe.o gud_connector.o +obj-$(CONFIG_DRM_GUD) += gud.o diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c new file mode 100644 index 000000000000..a4b9bbf48e19 --- /dev/null +++ b/drivers/gpu/drm/gud/gud_connector.c @@ -0,0 +1,722 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2020 Noralf Trønnes + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gud_internal.h" + +struct gud_connector { + struct drm_connector connector; + struct drm_encoder encoder; + struct backlight_device *backlight; + + /* Supported properties */ + u16 *properties; + unsigned int num_properties; + + /* Initial gadget tv state if applicable, applied on state reset */ + struct drm_tv_connector_state initial_tv_state; + + /* + * Initial gadget backlight brightness if applicable, applied on state reset. + * The value -ENODEV is used to signal no backlight. + */ + int initial_brightness; + + unsigned int num_modes; + size_t edid_len; +}; + +static inline struct gud_connector *to_gud_connector(struct drm_connector *connector) +{ + return container_of(connector, struct gud_connector, connector); +} + +static int gud_connector_backlight_update_status(struct backlight_device *bd) +{ + struct drm_connector *connector = bl_get_data(bd); + struct drm_connector_state *connector_state; + struct drm_device *dev = connector->dev; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; + int ret; + + state = drm_atomic_state_alloc(dev); + if (!state) + return -ENOMEM; + + drm_modeset_acquire_init(&ctx, 0); + state->acquire_ctx = &ctx; +retry: + connector_state = drm_atomic_get_connector_state(state, connector); + if (IS_ERR(connector_state)) { + ret = PTR_ERR(connector_state); + goto out; + } + + /* Reuse tv.brightness to avoid having to subclass */ + connector_state->tv.brightness = bd->props.brightness; + + ret = drm_atomic_commit(state); +out: + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + drm_modeset_backoff(&ctx); + goto retry; + } + + drm_atomic_state_put(state); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + return ret; +} + +static int gud_connector_backlight_get_brightness(struct backlight_device *bd) +{ + struct drm_connector *connector = bl_get_data(bd); + struct drm_device *dev = connector->dev; + int brightness; + + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + brightness = connector->state->tv.brightness; + drm_modeset_unlock(&dev->mode_config.connection_mutex); + + return brightness; +} + +static const struct backlight_ops gud_connector_backlight_ops = { + .get_brightness = gud_connector_backlight_get_brightness, + .update_status = gud_connector_backlight_update_status, +}; + +static int gud_connector_backlight_register(struct gud_connector *gconn) +{ + struct drm_connector *connector = &gconn->connector; + struct backlight_device *bd; + const char *name; + const struct backlight_properties props = { + .type = BACKLIGHT_RAW, + .scale = BACKLIGHT_SCALE_NON_LINEAR, + .max_brightness = 100, + }; + + name = kasprintf(GFP_KERNEL, "card%d-%s-backlight", + connector->dev->primary->index, connector->name); + if (!name) + return -ENOMEM; + + bd = backlight_device_register(name, connector->kdev, connector, + &gud_connector_backlight_ops, &props); + kfree(name); + if (IS_ERR(bd)) + return PTR_ERR(bd); + + gconn->backlight = bd; + + return 0; +} + +static int gud_connector_status_request(struct drm_connector *connector) +{ + struct gud_connector *gconn = to_gud_connector(connector); + struct gud_device *gdrm = to_gud_device(connector->dev); + struct gud_connector_status_req req; + u16 num_modes, edid_len; + int ret; + + ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_STATUS, + connector->index, &req, sizeof(req)); + if (ret) + return ret; + + switch (req.status & GUD_CONNECTOR_STATUS_CONNECTED_MASK) { + case GUD_CONNECTOR_STATUS_DISCONNECTED: + ret = connector_status_disconnected; + break; + case GUD_CONNECTOR_STATUS_CONNECTED: + ret = connector_status_connected; + break; + default: + ret = connector_status_unknown; + break; + }; + + num_modes = le16_to_cpu(req.num_modes); + edid_len = le16_to_cpu(req.edid_len); + + if (edid_len % EDID_LENGTH) { + drm_err(connector->dev, "%s: Invalid EDID size: %u\n", connector->name, edid_len); + edid_len = 0; + } + + if (req.status & GUD_CONNECTOR_STATUS_CHANGED || + gconn->num_modes != num_modes || gconn->edid_len != edid_len) + connector->epoch_counter += 1; + + gconn->num_modes = num_modes; + gconn->edid_len = edid_len; + + if (!num_modes && !edid_len && ret != connector_status_disconnected) + drm_dbg_kms(connector->dev, "%s: No modes or EDID.\n", connector->name); + + return ret; +} + +static int gud_connector_detect(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, bool force) +{ + struct gud_device *gdrm = to_gud_device(connector->dev); + int idx, ret; + + if (!drm_dev_enter(connector->dev, &idx)) + return connector_status_disconnected; + + if (force) { + ret = gud_usb_set(gdrm, GUD_REQ_SET_CONNECTOR_FORCE_DETECT, + connector->index, NULL, 0); + if (ret) { + ret = connector_status_unknown; + goto exit; + } + } + + ret = gud_connector_status_request(connector); + if (ret < 0) + ret = connector_status_unknown; +exit: + drm_dev_exit(idx); + + return ret; +} + +struct gud_connector_get_edid_ctx { + struct gud_connector *gconn; + void *buf; +}; + +static int gud_connector_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len) +{ + struct gud_connector_get_edid_ctx *ctx = data; + struct gud_connector *gconn = ctx->gconn; + size_t start = block * EDID_LENGTH; + + if (start + len > gconn->edid_len) + return -1; + + if (!block) { + struct gud_device *gdrm = to_gud_device(gconn->connector.dev); + int ret; + + /* Check because drm_do_get_edid() will retry on failure */ + if (!ctx->buf) + ctx->buf = kmalloc(gconn->edid_len, GFP_KERNEL); + if (!ctx->buf) + return -1; + + ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_EDID, gconn->connector.index, + ctx->buf, gconn->edid_len); + if (ret) + return -1; + } + + memcpy(buf, ctx->buf + start, len); + + return 0; +} + +static int gud_connector_get_modes(struct drm_connector *connector) +{ + struct gud_connector *gconn = to_gud_connector(connector); + struct gud_device *gdrm = to_gud_device(connector->dev); + struct gud_connector_get_edid_ctx edid_ctx = { + .gconn = gconn, + }; + struct gud_display_mode_req *reqmodes = NULL; + unsigned int i, num_modes = 0; + struct edid *edid = NULL; + bool edid_override; + int idx, ret; + + if (!drm_dev_enter(connector->dev, &idx)) + return 0; + + if (connector->force) { + ret = gud_connector_status_request(connector); + if (ret < 0) + goto out; + } + + edid = drm_do_get_edid(connector, gud_connector_get_edid_block, &edid_ctx); + edid_override = edid && !edid_ctx.buf; + kfree(edid_ctx.buf); + drm_connector_update_edid_property(connector, edid); + + if (!gconn->num_modes || edid_override) { + num_modes = drm_add_edid_modes(connector, edid); + goto out; + } + + reqmodes = kmalloc_array(gconn->num_modes, sizeof(*reqmodes), GFP_KERNEL); + if (!reqmodes) + goto out; + + ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_MODES, connector->index, + reqmodes, gconn->num_modes * sizeof(*reqmodes)); + if (ret) + goto out; + + for (i = 0; i < gconn->num_modes; i++) { + struct drm_display_mode *mode; + + mode = drm_mode_create(connector->dev); + if (!mode) + goto out; + + gud_to_display_mode(mode, &reqmodes[i]); + drm_mode_probed_add(connector, mode); + num_modes++; + } +out: + kfree(reqmodes); + kfree(edid); + drm_dev_exit(idx); + + return num_modes; +} + +static int gud_connector_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *new_state; + struct drm_crtc_state *new_crtc_state; + struct drm_connector_state *old_state; + + new_state = drm_atomic_get_new_connector_state(state, connector); + if (!new_state->crtc) + return 0; + + old_state = drm_atomic_get_old_connector_state(state, connector); + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc); + + if (old_state->tv.margins.left != new_state->tv.margins.left || + old_state->tv.margins.right != new_state->tv.margins.right || + old_state->tv.margins.top != new_state->tv.margins.top || + old_state->tv.margins.bottom != new_state->tv.margins.bottom || + old_state->tv.mode != new_state->tv.mode || + old_state->tv.brightness != new_state->tv.brightness || + old_state->tv.contrast != new_state->tv.contrast || + old_state->tv.flicker_reduction != new_state->tv.flicker_reduction || + old_state->tv.overscan != new_state->tv.overscan || + old_state->tv.saturation != new_state->tv.saturation || + old_state->tv.hue != new_state->tv.hue) + new_crtc_state->connectors_changed = true; + + return 0; +} + +static const struct drm_connector_helper_funcs gud_connector_helper_funcs = { + .detect_ctx = gud_connector_detect, + .get_modes = gud_connector_get_modes, + .atomic_check = gud_connector_atomic_check, +}; + +static int gud_connector_late_register(struct drm_connector *connector) +{ + struct gud_connector *gconn = to_gud_connector(connector); + + if (gconn->initial_brightness < 0) + return 0; + + return gud_connector_backlight_register(gconn); +} + +static void gud_connector_early_unregister(struct drm_connector *connector) +{ + struct gud_connector *gconn = to_gud_connector(connector); + + backlight_device_unregister(gconn->backlight); +} + +static void gud_connector_destroy(struct drm_connector *connector) +{ + struct gud_connector *gconn = to_gud_connector(connector); + + drm_connector_cleanup(connector); + kfree(gconn->properties); + kfree(gconn); +} + +static void gud_connector_reset(struct drm_connector *connector) +{ + struct gud_connector *gconn = to_gud_connector(connector); + + drm_atomic_helper_connector_reset(connector); + connector->state->tv = gconn->initial_tv_state; + /* Set margins from command line */ + drm_atomic_helper_connector_tv_reset(connector); + if (gconn->initial_brightness >= 0) + connector->state->tv.brightness = gconn->initial_brightness; +} + +static const struct drm_connector_funcs gud_connector_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .late_register = gud_connector_late_register, + .early_unregister = gud_connector_early_unregister, + .destroy = gud_connector_destroy, + .reset = gud_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +/* + * The tv.mode property is shared among the connectors and its enum names are + * driver specific. This means that if more than one connector uses tv.mode, + * the enum names has to be the same. + */ +static int gud_connector_add_tv_mode(struct gud_device *gdrm, + struct drm_connector *connector, u64 val) +{ + unsigned int i, num_modes; + const char **modes; + size_t buf_len; + char *buf; + int ret; + + num_modes = val >> GUD_CONNECTOR_TV_MODE_NUM_SHIFT; + + if (!num_modes) + return -EINVAL; + + buf_len = num_modes * GUD_CONNECTOR_TV_MODE_NAME_LEN; + modes = kmalloc_array(num_modes, sizeof(*modes), GFP_KERNEL); + buf = kmalloc(buf_len, GFP_KERNEL); + if (!modes || !buf) { + ret = -ENOMEM; + goto free; + } + + ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_TV_MODE_VALUES, + connector->index, buf, buf_len); + if (ret) + goto free; + + for (i = 0; i < num_modes; i++) + modes[i] = &buf[i * GUD_CONNECTOR_TV_MODE_NAME_LEN]; + + ret = drm_mode_create_tv_properties(connector->dev, num_modes, modes); +free: + kfree(modes); + kfree(buf); + + return ret; +} + +static struct drm_property * +gud_connector_property_lookup(struct drm_connector *connector, u16 prop) +{ + struct drm_mode_config *config = &connector->dev->mode_config; + + switch (prop) { + case GUD_PROPERTY_TV_LEFT_MARGIN: + return config->tv_left_margin_property; + case GUD_PROPERTY_TV_RIGHT_MARGIN: + return config->tv_right_margin_property; + case GUD_PROPERTY_TV_TOP_MARGIN: + return config->tv_top_margin_property; + case GUD_PROPERTY_TV_BOTTOM_MARGIN: + return config->tv_bottom_margin_property; + case GUD_PROPERTY_TV_MODE: + return config->tv_mode_property; + case GUD_PROPERTY_TV_BRIGHTNESS: + return config->tv_brightness_property; + case GUD_PROPERTY_TV_CONTRAST: + return config->tv_contrast_property; + case GUD_PROPERTY_TV_FLICKER_REDUCTION: + return config->tv_flicker_reduction_property; + case GUD_PROPERTY_TV_OVERSCAN: + return config->tv_overscan_property; + case GUD_PROPERTY_TV_SATURATION: + return config->tv_saturation_property; + case GUD_PROPERTY_TV_HUE: + return config->tv_hue_property; + default: + return ERR_PTR(-EINVAL); + } +} + +static unsigned int *gud_connector_tv_state_val(u16 prop, struct drm_tv_connector_state *state) +{ + switch (prop) { + case GUD_PROPERTY_TV_LEFT_MARGIN: + return &state->margins.left; + case GUD_PROPERTY_TV_RIGHT_MARGIN: + return &state->margins.right; + case GUD_PROPERTY_TV_TOP_MARGIN: + return &state->margins.top; + case GUD_PROPERTY_TV_BOTTOM_MARGIN: + return &state->margins.bottom; + case GUD_PROPERTY_TV_MODE: + return &state->mode; + case GUD_PROPERTY_TV_BRIGHTNESS: + return &state->brightness; + case GUD_PROPERTY_TV_CONTRAST: + return &state->contrast; + case GUD_PROPERTY_TV_FLICKER_REDUCTION: + return &state->flicker_reduction; + case GUD_PROPERTY_TV_OVERSCAN: + return &state->overscan; + case GUD_PROPERTY_TV_SATURATION: + return &state->saturation; + case GUD_PROPERTY_TV_HUE: + return &state->hue; + default: + return ERR_PTR(-EINVAL); + } +} + +static int gud_connector_add_properties(struct gud_device *gdrm, struct gud_connector *gconn, + unsigned int num_properties) +{ + struct drm_device *drm = &gdrm->drm; + struct drm_connector *connector = &gconn->connector; + struct gud_property_req *properties; + unsigned int i; + int ret; + + gconn->properties = kcalloc(num_properties, sizeof(*gconn->properties), GFP_KERNEL); + if (!gconn->properties) + return -ENOMEM; + + properties = kcalloc(num_properties, sizeof(*properties), GFP_KERNEL); + if (!properties) + return -ENOMEM; + + ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_PROPERTIES, connector->index, + properties, num_properties * sizeof(*properties)); + if (ret) + goto out; + + for (i = 0; i < num_properties; i++) { + u16 prop = le16_to_cpu(properties[i].prop); + u64 val = le64_to_cpu(properties[i].val); + struct drm_property *property; + unsigned int *state_val; + + drm_dbg(drm, "property: %u = %llu(0x%llx)\n", prop, val, val); + + switch (prop) { + case GUD_PROPERTY_TV_LEFT_MARGIN: + fallthrough; + case GUD_PROPERTY_TV_RIGHT_MARGIN: + fallthrough; + case GUD_PROPERTY_TV_TOP_MARGIN: + fallthrough; + case GUD_PROPERTY_TV_BOTTOM_MARGIN: + ret = drm_mode_create_tv_margin_properties(drm); + if (ret) + goto out; + break; + case GUD_PROPERTY_TV_MODE: + ret = gud_connector_add_tv_mode(gdrm, connector, val); + if (ret) + goto out; + val = val & (BIT(GUD_CONNECTOR_TV_MODE_NUM_SHIFT) - 1); + break; + case GUD_PROPERTY_TV_BRIGHTNESS: + fallthrough; + case GUD_PROPERTY_TV_CONTRAST: + fallthrough; + case GUD_PROPERTY_TV_FLICKER_REDUCTION: + fallthrough; + case GUD_PROPERTY_TV_OVERSCAN: + fallthrough; + case GUD_PROPERTY_TV_SATURATION: + fallthrough; + case GUD_PROPERTY_TV_HUE: + /* This is a no-op if already added. */ + ret = drm_mode_create_tv_properties(drm, 0, NULL); + if (ret) + goto out; + break; + case GUD_PROPERTY_BACKLIGHT_BRIGHTNESS: + if (val > 100) { + ret = -EINVAL; + goto out; + } + gconn->initial_brightness = val; + break; + default: + /* New ones might show up in future devices, skip those we don't know. */ + drm_dbg(drm, "Unknown property: %u\n", prop); + continue; + } + + gconn->properties[gconn->num_properties++] = prop; + + if (prop == GUD_PROPERTY_BACKLIGHT_BRIGHTNESS) + continue; /* not a DRM property */ + + property = gud_connector_property_lookup(connector, prop); + if (WARN_ON(IS_ERR(property))) + continue; + + state_val = gud_connector_tv_state_val(prop, &gconn->initial_tv_state); + if (WARN_ON(IS_ERR(state_val))) + continue; + + *state_val = val; + drm_object_attach_property(&connector->base, property, 0); + } +out: + kfree(properties); + + return ret; +} + +int gud_connector_fill_properties(struct drm_connector *connector, + struct drm_connector_state *connector_state, + struct gud_property_req *properties) +{ + struct gud_connector *gconn; + unsigned int i; + + gconn = to_gud_connector(connector); + + /* Only interested in the count? */ + if (!connector_state) + return gconn->num_properties; + + for (i = 0; i < gconn->num_properties; i++) { + u16 prop = gconn->properties[i]; + u64 val; + + if (prop == GUD_PROPERTY_BACKLIGHT_BRIGHTNESS) { + val = connector_state->tv.brightness; + } else { + unsigned int *state_val; + + state_val = gud_connector_tv_state_val(prop, &connector_state->tv); + if (WARN_ON_ONCE(IS_ERR(state_val))) + return PTR_ERR(state_val); + + val = *state_val; + } + + properties[i].prop = cpu_to_le16(prop); + properties[i].val = cpu_to_le64(val); + } + + return gconn->num_properties; +} + +int gud_connector_create(struct gud_device *gdrm, unsigned int index) +{ + struct gud_connector_descriptor_req desc; + struct drm_device *drm = &gdrm->drm; + struct gud_connector *gconn; + struct drm_connector *connector; + struct drm_encoder *encoder; + int ret, connector_type; + u32 flags; + + ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR, index, &desc, sizeof(desc)); + if (ret) + return ret; + + gconn = kzalloc(sizeof(*gconn), GFP_KERNEL); + if (!gconn) + return -ENOMEM; + + gconn->initial_brightness = -ENODEV; + flags = le32_to_cpu(desc.flags); + connector = &gconn->connector; + + drm_dbg(drm, "Connector: index=%u type=%u flags=0x%x num_properties=%u\n", + index, desc.connector_type, flags, desc.num_properties); + + switch (desc.connector_type) { + case GUD_CONNECTOR_TYPE_PANEL: + connector_type = DRM_MODE_CONNECTOR_USB; + break; + case GUD_CONNECTOR_TYPE_VGA: + connector_type = DRM_MODE_CONNECTOR_VGA; + break; + case GUD_CONNECTOR_TYPE_DVI: + connector_type = DRM_MODE_CONNECTOR_DVID; + break; + case GUD_CONNECTOR_TYPE_COMPOSITE: + connector_type = DRM_MODE_CONNECTOR_Composite; + break; + case GUD_CONNECTOR_TYPE_SVIDEO: + connector_type = DRM_MODE_CONNECTOR_SVIDEO; + break; + case GUD_CONNECTOR_TYPE_COMPONENT: + connector_type = DRM_MODE_CONNECTOR_Component; + break; + case GUD_CONNECTOR_TYPE_DISPLAYPORT: + connector_type = DRM_MODE_CONNECTOR_DisplayPort; + break; + case GUD_CONNECTOR_TYPE_HDMI: + connector_type = DRM_MODE_CONNECTOR_HDMIA; + break; + default: /* future types */ + connector_type = DRM_MODE_CONNECTOR_USB; + break; + }; + + drm_connector_helper_add(connector, &gud_connector_helper_funcs); + ret = drm_connector_init(drm, connector, &gud_connector_funcs, connector_type); + if (ret) { + kfree(connector); + return ret; + } + + if (WARN_ON(connector->index != index)) + return -EINVAL; + + if (flags & GUD_CONNECTOR_FLAGS_POLL_STATUS) + connector->polled = (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT); + if (flags & GUD_CONNECTOR_FLAGS_INTERLACE) + connector->interlace_allowed = true; + if (flags & GUD_CONNECTOR_FLAGS_DOUBLESCAN) + connector->doublescan_allowed = true; + + if (desc.num_properties) { + ret = gud_connector_add_properties(gdrm, gconn, desc.num_properties); + if (ret) { + dev_err(drm->dev, "Failed to add connector/%u properties\n", index); + return ret; + } + } + + /* The first connector is attached to the existing simple pipe encoder */ + if (!connector->index) { + encoder = &gdrm->pipe.encoder; + } else { + encoder = &gconn->encoder; + + ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_NONE); + if (ret) + return ret; + + encoder->possible_crtcs = 1; + } + + return drm_connector_attach_encoder(connector, encoder); +} diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c new file mode 100644 index 000000000000..6c5e9eeb8cdc --- /dev/null +++ b/drivers/gpu/drm/gud/gud_drv.c @@ -0,0 +1,620 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2020 Noralf Trønnes + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gud_internal.h" + +/* Only used internally */ +static const struct drm_format_info gud_drm_format_r1 = { + .format = GUD_DRM_FORMAT_R1, + .num_planes = 1, + .char_per_block = { 1, 0, 0 }, + .block_w = { 8, 0, 0 }, + .block_h = { 1, 0, 0 }, + .hsub = 1, + .vsub = 1, +}; + +static int gud_usb_control_msg(struct usb_device *usb, u8 ifnum, bool in, + u8 request, u16 value, void *buf, size_t len) +{ + u8 requesttype = USB_TYPE_VENDOR | USB_RECIP_INTERFACE; + unsigned int pipe; + int ret; + + if (in) { + pipe = usb_rcvctrlpipe(usb, 0); + requesttype |= USB_DIR_IN; + } else { + pipe = usb_sndctrlpipe(usb, 0); + requesttype |= USB_DIR_OUT; + } + + ret = usb_control_msg(usb, pipe, request, requesttype, value, + ifnum, buf, len, USB_CTRL_GET_TIMEOUT); + if (ret < 0) + return ret; + if (ret != len) + return -EIO; + + return 0; +} + +static int gud_get_display_descriptor(struct usb_interface *interface, + struct gud_display_descriptor_req *desc) +{ + u8 ifnum = interface->cur_altsetting->desc.bInterfaceNumber; + struct usb_device *usb = interface_to_usbdev(interface); + void *buf; + int ret; + + buf = kmalloc(sizeof(*desc), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = gud_usb_control_msg(usb, ifnum, true, GUD_REQ_GET_DESCRIPTOR, 0, buf, sizeof(*desc)); + memcpy(desc, buf, sizeof(*desc)); + kfree(buf); + if (ret) + return ret; + + if (desc->magic != GUD_DISPLAY_MAGIC) + return -ENODATA; + + DRM_DEV_DEBUG_DRIVER(&interface->dev, + "version=%u flags=0x%x compression=0x%x num_formats=%u num_connectors=%u max_buffer_size=%u\n", + desc->version, le32_to_cpu(desc->flags), desc->compression, + desc->num_formats, desc->num_connectors, + le32_to_cpu(desc->max_buffer_size)); + + if (!desc->version || !desc->num_formats || !desc->num_connectors || + !desc->max_width || !desc->max_height || + le32_to_cpu(desc->min_width) > le32_to_cpu(desc->max_width) || + le32_to_cpu(desc->min_height) > le32_to_cpu(desc->max_height)) + return -EINVAL; + + return 0; +} + +static int gud_usb_get_status(struct usb_device *usb, u8 ifnum, u8 *status) +{ + u8 *buf; + int ret; + + buf = kmalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = gud_usb_control_msg(usb, ifnum, true, GUD_REQ_GET_STATUS, 0, buf, sizeof(*buf)); + *status = *buf; + kfree(buf); + + return ret; +} + +static int gud_status_to_errno(u8 status) +{ + switch (status) { + case GUD_STATUS_OK: + return 0; + case GUD_STATUS_BUSY: + return -EBUSY; + case GUD_STATUS_REQUEST_NOT_SUPPORTED: + return -EOPNOTSUPP; + case GUD_STATUS_PROTOCOL_ERROR: + return -EPROTO; + case GUD_STATUS_INVALID_PARAMETER: + return -EINVAL; + case GUD_STATUS_ERROR: + return -EREMOTEIO; + default: + return -EREMOTEIO; + } +} + +static int gud_usb_transfer(struct gud_device *gdrm, bool in, u8 request, u16 index, + void *buf, size_t len) +{ + struct usb_device *usb = gud_to_usb_device(gdrm); + void *trbuf = NULL; + int idx, ret; + + drm_dbg(&gdrm->drm, "%s: request=0x%x index=%u len=%zu\n", + in ? "get" : "set", request, index, len); + + if (!drm_dev_enter(&gdrm->drm, &idx)) + return -ENODEV; + + mutex_lock(&gdrm->ctrl_lock); + + if (buf) { + if (in) + trbuf = kmalloc(len, GFP_KERNEL); + else + trbuf = kmemdup(buf, len, GFP_KERNEL); + if (!trbuf) { + ret = -ENOMEM; + goto unlock; + } + } + + ret = gud_usb_control_msg(usb, gdrm->ifnum, in, request, index, trbuf, len); + if (ret == -EPIPE || (!ret && !in && (gdrm->flags & GUD_DISPLAY_FLAG_STATUS_ON_SET))) { + bool error = ret; + u8 status; + + ret = gud_usb_get_status(usb, gdrm->ifnum, &status); + if (!ret) { + if (error && status == GUD_STATUS_OK) { + dev_err_once(gdrm->drm.dev, + "Unexpected status OK for failed transfer\n"); + ret = -EPIPE; + } else { + ret = gud_status_to_errno(status); + } + } + } + + if (!ret && in && buf) + memcpy(buf, trbuf, len); + + if (ret) { + drm_dbg(&gdrm->drm, "ret=%d\n", ret); + gdrm->stats_num_errors++; + } + + kfree(trbuf); +unlock: + mutex_unlock(&gdrm->ctrl_lock); + drm_dev_exit(idx); + + return ret; +} + +int gud_usb_get(struct gud_device *gdrm, u8 request, u16 index, void *buf, size_t len) +{ + return gud_usb_transfer(gdrm, true, request, index, buf, len); +} + +int gud_usb_set(struct gud_device *gdrm, u8 request, u16 index, void *buf, size_t len) +{ + return gud_usb_transfer(gdrm, false, request, index, buf, len); +} + +int gud_usb_write8(struct gud_device *gdrm, u8 request, u8 val) +{ + return gud_usb_set(gdrm, request, 0, &val, sizeof(val)); +} + +static int gud_set_version(struct usb_device *usb, u8 ifnum, u32 flags, u8 version) +{ + u8 *buf; + int ret; + + buf = kmalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + *buf = version; + ret = gud_usb_control_msg(usb, ifnum, false, GUD_REQ_SET_VERSION, 0, buf, sizeof(*buf)); + kfree(buf); + if (ret == -EPIPE) + return -EPROTONOSUPPORT; + if (ret) + return ret; + + if (flags & GUD_DISPLAY_FLAG_STATUS_ON_SET) { + u8 status; + + ret = gud_usb_get_status(usb, ifnum, &status); + if (!ret && status != GUD_STATUS_OK) + ret = -EPROTONOSUPPORT; + } + + return ret; +} + +static int gud_get_properties(struct gud_device *gdrm, unsigned int num_properties) +{ + struct gud_property_req *properties; + unsigned int i; + int ret; + + if (!num_properties) + return 0; + + gdrm->properties = drmm_kcalloc(&gdrm->drm, num_properties, sizeof(*gdrm->properties), + GFP_KERNEL); + if (!gdrm->properties) + return -ENOMEM; + + properties = kcalloc(num_properties, sizeof(*properties), GFP_KERNEL); + if (!properties) + return -ENOMEM; + + ret = gud_usb_get(gdrm, GUD_REQ_GET_PROPERTIES, 0, + properties, num_properties * sizeof(*properties)); + if (ret) + goto out; + + for (i = 0; i < num_properties; i++) { + u16 prop = le16_to_cpu(properties[i].prop); + u64 val = le64_to_cpu(properties[i].val); + + switch (prop) { + case GUD_PROPERTY_ROTATION: + /* + * DRM UAPI matches the protocol so use the value directly, + * but mask out any additions on future devices. + */ + val &= GUD_ROTATION_MASK; + ret = drm_plane_create_rotation_property(&gdrm->pipe.plane, + DRM_MODE_ROTATE_0, val); + break; + default: + /* New ones might show up in future devices, skip those we don't know. */ + drm_dbg(&gdrm->drm, "Unknown property: %u\n", prop); + continue; + } + + if (ret) + goto out; + + gdrm->properties[gdrm->num_properties++] = prop; + } +out: + kfree(properties); + + return ret; +} + +static int gud_stats_debugfs(struct seq_file *m, void *data) +{ + struct drm_info_node *node = m->private; + struct gud_device *gdrm = to_gud_device(node->minor->dev); + char buf[10]; + + string_get_size(gdrm->bulk_len, 1, STRING_UNITS_2, buf, sizeof(buf)); + seq_printf(m, "Max buffer size: %s\n", buf); + seq_printf(m, "Number of errors: %u\n", gdrm->stats_num_errors); + + seq_puts(m, "Compression: "); + if (gdrm->compression & GUD_COMPRESSION_LZ4) + seq_puts(m, " lz4"); + seq_puts(m, "\n"); + + if (gdrm->compression) { + u64 remainder; + u64 ratio = div64_u64_rem(gdrm->stats_length, gdrm->stats_actual_length, + &remainder); + u64 ratio_frac = div64_u64(remainder * 10, gdrm->stats_actual_length); + + seq_printf(m, "Compression ratio: %llu.%llu\n", ratio, ratio_frac); + } + + return 0; +} + +static const struct drm_info_list gud_debugfs_list[] = { + { "stats", gud_stats_debugfs, 0, NULL }, +}; + +static void gud_debugfs_init(struct drm_minor *minor) +{ + drm_debugfs_create_files(gud_debugfs_list, ARRAY_SIZE(gud_debugfs_list), + minor->debugfs_root, minor); +} + +static const struct drm_simple_display_pipe_funcs gud_pipe_funcs = { + .check = gud_pipe_check, + .update = gud_pipe_update, + .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, +}; + +static const struct drm_mode_config_funcs gud_mode_config_funcs = { + .fb_create = drm_gem_fb_create_with_dirty, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static const u64 gud_pipe_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + +DEFINE_DRM_GEM_FOPS(gud_fops); + +static const struct drm_driver gud_drm_driver = { + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, + .fops = &gud_fops, + DRM_GEM_SHMEM_DRIVER_OPS, + .debugfs_init = gud_debugfs_init, + + .name = "gud", + .desc = "Generic USB Display", + .date = "20200422", + .major = 1, + .minor = 0, +}; + +static void gud_free_buffers_and_mutex(struct drm_device *drm, void *unused) +{ + struct gud_device *gdrm = to_gud_device(drm); + + vfree(gdrm->compress_buf); + kfree(gdrm->bulk_buf); + mutex_destroy(&gdrm->ctrl_lock); + mutex_destroy(&gdrm->damage_lock); +} + +static int gud_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + u8 ifnum = interface->cur_altsetting->desc.bInterfaceNumber; + struct usb_device *usb = interface_to_usbdev(interface); + struct device *dev = &interface->dev; + const struct drm_format_info *xrgb8888_emulation_format = NULL; + bool rgb565_supported = false, xrgb8888_supported = false; + struct usb_endpoint_descriptor *bulk_out; + struct gud_display_descriptor_req desc; + unsigned int num_formats = 0; + struct gud_device *gdrm; + size_t max_buffer_size = 0; + struct drm_device *drm; + u8 *formats_dev; + u32 *formats; + int ret, i; + + ret = usb_find_bulk_out_endpoint(interface->cur_altsetting, &bulk_out); + if (ret) + return ret; + + ret = gud_get_display_descriptor(interface, &desc); + if (ret) { + DRM_DEV_DEBUG_DRIVER(dev, "Not a display interface: ret=%d\n", ret); + return -ENODEV; + } + + if (desc.version > 1) { + ret = gud_set_version(usb, ifnum, le32_to_cpu(desc.flags), 1); + if (ret) { + if (ret == -EPROTONOSUPPORT) + dev_err(dev, "Protocol version %u is not supported\n", + desc.version); + return ret; + } + } + + gdrm = devm_drm_dev_alloc(dev, &gud_drm_driver, struct gud_device, drm); + if (IS_ERR(gdrm)) + return PTR_ERR(gdrm); + + drm = &gdrm->drm; + drm->mode_config.funcs = &gud_mode_config_funcs; + ret = drmm_mode_config_init(drm); + if (ret) + return ret; + + gdrm->ifnum = ifnum; + gdrm->flags = le32_to_cpu(desc.flags); + gdrm->compression = desc.compression & GUD_COMPRESSION_LZ4; + + if (gdrm->flags & GUD_DISPLAY_FLAG_FULL_UPDATE && gdrm->compression) + return -EINVAL; + + mutex_init(&gdrm->ctrl_lock); + mutex_init(&gdrm->damage_lock); + INIT_WORK(&gdrm->work, gud_flush_work); + gud_clear_damage(gdrm); + + ret = drmm_add_action_or_reset(drm, gud_free_buffers_and_mutex, NULL); + if (ret) + return ret; + + drm->mode_config.min_width = le32_to_cpu(desc.min_width); + drm->mode_config.max_width = le32_to_cpu(desc.max_width); + drm->mode_config.min_height = le32_to_cpu(desc.min_height); + drm->mode_config.max_height = le32_to_cpu(desc.max_height); + + formats_dev = devm_kmalloc(dev, desc.num_formats, GFP_KERNEL); + /* Add room for emulated XRGB8888 */ + formats = devm_kmalloc_array(dev, desc.num_formats + 1, sizeof(*formats), GFP_KERNEL); + if (!formats_dev || !formats) + return -ENOMEM; + + ret = gud_usb_get(gdrm, GUD_REQ_GET_FORMATS, 0, formats_dev, desc.num_formats); + if (ret) + return ret; + + for (i = 0; i < desc.num_formats; i++) { + const struct drm_format_info *info; + size_t fmt_buf_size; + u32 format; + + format = gud_to_fourcc(formats_dev[i]); + if (!format) { + drm_dbg(drm, "Unsupported format: 0x%02x\n", formats_dev[i]); + continue; + } + + if (format == GUD_DRM_FORMAT_R1) + info = &gud_drm_format_r1; + else + info = drm_format_info(format); + + switch (format) { + case GUD_DRM_FORMAT_R1: + xrgb8888_emulation_format = info; + break; + case DRM_FORMAT_RGB565: + rgb565_supported = true; + if (!xrgb8888_emulation_format) + xrgb8888_emulation_format = info; + break; + case DRM_FORMAT_XRGB8888: + xrgb8888_supported = true; + break; + }; + + fmt_buf_size = drm_format_info_min_pitch(info, 0, drm->mode_config.max_width) * + drm->mode_config.max_height; + max_buffer_size = max(max_buffer_size, fmt_buf_size); + + if (format == GUD_DRM_FORMAT_R1) + continue; /* Internal not for userspace */ + + formats[num_formats++] = format; + } + + if (!num_formats && !xrgb8888_emulation_format) { + dev_err(dev, "No supported pixel formats found\n"); + return -EINVAL; + } + + /* Prefer speed over color depth */ + if (rgb565_supported) + drm->mode_config.preferred_depth = 16; + + if (!xrgb8888_supported && xrgb8888_emulation_format) { + gdrm->xrgb8888_emulation_format = xrgb8888_emulation_format; + formats[num_formats++] = DRM_FORMAT_XRGB8888; + } + + if (desc.max_buffer_size) + max_buffer_size = le32_to_cpu(desc.max_buffer_size); +retry: + /* + * Use plain kmalloc here since devm_kmalloc() places struct devres at the beginning + * of the buffer it allocates. This wastes a lot of memory when allocating big buffers. + * Asking for 2M would actually allocate 4M. This would also prevent getting the biggest + * possible buffer potentially leading to split transfers. + */ + gdrm->bulk_buf = kmalloc(max_buffer_size, GFP_KERNEL | __GFP_NOWARN); + if (!gdrm->bulk_buf) { + max_buffer_size = roundup_pow_of_two(max_buffer_size) / 2; + if (max_buffer_size < SZ_512K) + return -ENOMEM; + goto retry; + } + + gdrm->bulk_pipe = usb_sndbulkpipe(usb, usb_endpoint_num(bulk_out)); + gdrm->bulk_len = max_buffer_size; + + if (gdrm->compression & GUD_COMPRESSION_LZ4) { + gdrm->lz4_comp_mem = devm_kmalloc(dev, LZ4_MEM_COMPRESS, GFP_KERNEL); + if (!gdrm->lz4_comp_mem) + return -ENOMEM; + + gdrm->compress_buf = vmalloc(gdrm->bulk_len); + if (!gdrm->compress_buf) + return -ENOMEM; + } + + ret = drm_simple_display_pipe_init(drm, &gdrm->pipe, &gud_pipe_funcs, + formats, num_formats, + gud_pipe_modifiers, NULL); + if (ret) + return ret; + + devm_kfree(dev, formats); + devm_kfree(dev, formats_dev); + + ret = gud_get_properties(gdrm, desc.num_properties); + if (ret) + return ret; + + drm_plane_enable_fb_damage_clips(&gdrm->pipe.plane); + + for (i = 0; i < desc.num_connectors; i++) { + ret = gud_connector_create(gdrm, i); + if (ret) + return ret; + } + + drm_mode_config_reset(drm); + + usb_set_intfdata(interface, gdrm); + + ret = drm_dev_register(drm, 0); + if (ret) + return ret; + + drm_kms_helper_poll_init(drm); + + drm_fbdev_generic_setup(drm, 0); + + return 0; +} + +static void gud_disconnect(struct usb_interface *interface) +{ + struct gud_device *gdrm = usb_get_intfdata(interface); + struct drm_device *drm = &gdrm->drm; + + drm_dbg(drm, "%s:\n", __func__); + + drm_kms_helper_poll_fini(drm); + drm_dev_unplug(drm); + drm_atomic_helper_shutdown(drm); +} + +static int gud_suspend(struct usb_interface *interface, pm_message_t message) +{ + struct gud_device *gdrm = usb_get_intfdata(interface); + + return drm_mode_config_helper_suspend(&gdrm->drm); +} + +static int gud_resume(struct usb_interface *interface) +{ + struct gud_device *gdrm = usb_get_intfdata(interface); + + drm_mode_config_helper_resume(&gdrm->drm); + + return 0; +} + +static const struct usb_device_id gud_id_table[] = { + { USB_DEVICE_INTERFACE_CLASS(0x1d50, 0x614d, USB_CLASS_VENDOR_SPEC) }, + { } +}; + +MODULE_DEVICE_TABLE(usb, gud_id_table); + +static struct usb_driver gud_usb_driver = { + .name = "gud", + .probe = gud_probe, + .disconnect = gud_disconnect, + .id_table = gud_id_table, + .suspend = gud_suspend, + .resume = gud_resume, + .reset_resume = gud_resume, +}; + +module_usb_driver(gud_usb_driver); + +MODULE_AUTHOR("Noralf Trønnes"); +MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/gpu/drm/gud/gud_internal.h b/drivers/gpu/drm/gud/gud_internal.h new file mode 100644 index 000000000000..46e7d7ed2c69 --- /dev/null +++ b/drivers/gpu/drm/gud/gud_internal.h @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef __LINUX_GUD_INTERNAL_H +#define __LINUX_GUD_INTERNAL_H + +#include +#include +#include +#include +#include + +#include +#include + +struct gud_device { + struct drm_device drm; + struct drm_simple_display_pipe pipe; + struct work_struct work; + u8 ifnum; + u32 flags; + const struct drm_format_info *xrgb8888_emulation_format; + + u16 *properties; + unsigned int num_properties; + + unsigned int bulk_pipe; + void *bulk_buf; + size_t bulk_len; + + u8 compression; + void *lz4_comp_mem; + void *compress_buf; + + u64 stats_length; + u64 stats_actual_length; + unsigned int stats_num_errors; + + struct mutex ctrl_lock; /* Serialize get/set and status transfers */ + + struct mutex damage_lock; /* Protects the following members: */ + struct drm_framebuffer *fb; + struct drm_rect damage; + bool prev_flush_failed; +}; + +static inline struct gud_device *to_gud_device(struct drm_device *drm) +{ + return container_of(drm, struct gud_device, drm); +} + +static inline struct usb_device *gud_to_usb_device(struct gud_device *gdrm) +{ + return interface_to_usbdev(to_usb_interface(gdrm->drm.dev)); +} + +int gud_usb_get(struct gud_device *gdrm, u8 request, u16 index, void *buf, size_t len); +int gud_usb_set(struct gud_device *gdrm, u8 request, u16 index, void *buf, size_t len); +int gud_usb_write8(struct gud_device *gdrm, u8 request, u8 val); + +void gud_clear_damage(struct gud_device *gdrm); +void gud_flush_work(struct work_struct *work); +int gud_pipe_check(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *new_plane_state, + struct drm_crtc_state *new_crtc_state); +void gud_pipe_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *old_state); +int gud_connector_fill_properties(struct drm_connector *connector, + struct drm_connector_state *connector_state, + struct gud_property_req *properties); +int gud_connector_create(struct gud_device *gdrm, unsigned int index); + +#define GUD_DRM_FORMAT_R1 fourcc_code('R', '1', ' ', ' ') + +static inline u8 gud_from_fourcc(u32 fourcc) +{ + switch (fourcc) { + case GUD_DRM_FORMAT_R1: + return GUD_PIXEL_FORMAT_R1; + case DRM_FORMAT_RGB565: + return GUD_PIXEL_FORMAT_RGB565; + case DRM_FORMAT_XRGB8888: + return GUD_PIXEL_FORMAT_XRGB8888; + case DRM_FORMAT_ARGB8888: + return GUD_PIXEL_FORMAT_ARGB8888; + }; + + return 0; +} + +static inline u32 gud_to_fourcc(u8 format) +{ + switch (format) { + case GUD_PIXEL_FORMAT_R1: + return GUD_DRM_FORMAT_R1; + case GUD_PIXEL_FORMAT_RGB565: + return DRM_FORMAT_RGB565; + case GUD_PIXEL_FORMAT_XRGB8888: + return DRM_FORMAT_XRGB8888; + case GUD_PIXEL_FORMAT_ARGB8888: + return DRM_FORMAT_ARGB8888; + }; + + return 0; +} + +static inline void gud_from_display_mode(struct gud_display_mode_req *dst, + const struct drm_display_mode *src) +{ + u32 flags = src->flags & GUD_DISPLAY_MODE_FLAG_USER_MASK; + + if (src->type & DRM_MODE_TYPE_PREFERRED) + flags |= GUD_DISPLAY_MODE_FLAG_PREFERRED; + + dst->clock = cpu_to_le32(src->clock); + dst->hdisplay = cpu_to_le16(src->hdisplay); + dst->hsync_start = cpu_to_le16(src->hsync_start); + dst->hsync_end = cpu_to_le16(src->hsync_end); + dst->htotal = cpu_to_le16(src->htotal); + dst->vdisplay = cpu_to_le16(src->vdisplay); + dst->vsync_start = cpu_to_le16(src->vsync_start); + dst->vsync_end = cpu_to_le16(src->vsync_end); + dst->vtotal = cpu_to_le16(src->vtotal); + dst->flags = cpu_to_le32(flags); +} + +static inline void gud_to_display_mode(struct drm_display_mode *dst, + const struct gud_display_mode_req *src) +{ + u32 flags = le32_to_cpu(src->flags); + + memset(dst, 0, sizeof(*dst)); + dst->clock = le32_to_cpu(src->clock); + dst->hdisplay = le16_to_cpu(src->hdisplay); + dst->hsync_start = le16_to_cpu(src->hsync_start); + dst->hsync_end = le16_to_cpu(src->hsync_end); + dst->htotal = le16_to_cpu(src->htotal); + dst->vdisplay = le16_to_cpu(src->vdisplay); + dst->vsync_start = le16_to_cpu(src->vsync_start); + dst->vsync_end = le16_to_cpu(src->vsync_end); + dst->vtotal = le16_to_cpu(src->vtotal); + dst->flags = flags & GUD_DISPLAY_MODE_FLAG_USER_MASK; + dst->type = DRM_MODE_TYPE_DRIVER; + if (flags & GUD_DISPLAY_MODE_FLAG_PREFERRED) + dst->type |= DRM_MODE_TYPE_PREFERRED; + drm_mode_set_name(dst); +} + +#endif diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c new file mode 100644 index 000000000000..1eef930bcf9b --- /dev/null +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -0,0 +1,472 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2020 Noralf Trønnes + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gud_internal.h" + +static bool gud_is_big_endian(void) +{ +#if defined(__BIG_ENDIAN) + return true; +#else + return false; +#endif +} + +static size_t gud_xrgb8888_to_r124(u8 *dst, const struct drm_format_info *format, + void *src, struct drm_framebuffer *fb, + struct drm_rect *rect) +{ + unsigned int block_width = drm_format_info_block_width(format, 0); + unsigned int bits_per_pixel = 8 / block_width; + unsigned int x, y, width, height; + u8 *p, *block = dst; /* Assign to silence compiler warning */ + size_t len; + void *buf; + + WARN_ON_ONCE(format->char_per_block[0] != 1); + + /* Start on a byte boundary */ + rect->x1 = ALIGN_DOWN(rect->x1, block_width); + width = drm_rect_width(rect); + height = drm_rect_height(rect); + len = drm_format_info_min_pitch(format, 0, width) * height; + + buf = kmalloc(width * height, GFP_KERNEL); + if (!buf) + return 0; + + drm_fb_xrgb8888_to_gray8(buf, src, fb, rect); + + p = buf; + for (y = 0; y < drm_rect_height(rect); y++) { + for (x = 0; x < drm_rect_width(rect); x++) { + if (!(x % block_width)) { + block = dst++; + *block = 0; + } + + *block <<= bits_per_pixel; + *block |= (*p++) >> (8 - bits_per_pixel); + } + } + + kfree(buf); + + return len; +} + +static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, + const struct drm_format_info *format, struct drm_rect *rect, + struct gud_set_buffer_req *req) +{ + struct dma_buf_attachment *import_attach = fb->obj[0]->import_attach; + u8 compression = gdrm->compression; + struct dma_buf_map map; + void *vaddr, *buf; + size_t pitch, len; + int ret = 0; + + pitch = drm_format_info_min_pitch(format, 0, drm_rect_width(rect)); + len = pitch * drm_rect_height(rect); + if (len > gdrm->bulk_len) + return -E2BIG; + + ret = drm_gem_shmem_vmap(fb->obj[0], &map); + if (ret) + return ret; + + vaddr = map.vaddr + fb->offsets[0]; + + if (import_attach) { + ret = dma_buf_begin_cpu_access(import_attach->dmabuf, DMA_FROM_DEVICE); + if (ret) + goto vunmap; + } +retry: + if (compression) + buf = gdrm->compress_buf; + else + buf = gdrm->bulk_buf; + + /* + * Imported buffers are assumed to be write-combined and thus uncached + * with slow reads (at least on ARM). + */ + if (format != fb->format) { + if (format->format == GUD_DRM_FORMAT_R1) { + len = gud_xrgb8888_to_r124(buf, format, vaddr, fb, rect); + if (!len) { + ret = -ENOMEM; + goto end_cpu_access; + } + } else if (format->format == DRM_FORMAT_RGB565) { + drm_fb_xrgb8888_to_rgb565(buf, vaddr, fb, rect, gud_is_big_endian()); + } + } else if (gud_is_big_endian() && format->cpp[0] > 1) { + drm_fb_swab(buf, vaddr, fb, rect, !import_attach); + } else if (compression && !import_attach && pitch == fb->pitches[0]) { + /* can compress directly from the framebuffer */ + buf = vaddr + rect->y1 * pitch; + } else { + drm_fb_memcpy(buf, vaddr, fb, rect); + } + + memset(req, 0, sizeof(*req)); + req->x = cpu_to_le32(rect->x1); + req->y = cpu_to_le32(rect->y1); + req->width = cpu_to_le32(drm_rect_width(rect)); + req->height = cpu_to_le32(drm_rect_height(rect)); + req->length = cpu_to_le32(len); + + if (compression & GUD_COMPRESSION_LZ4) { + int complen; + + complen = LZ4_compress_default(buf, gdrm->bulk_buf, len, len, gdrm->lz4_comp_mem); + if (complen < 0) { + compression = 0; + goto retry; + } + + req->compression = GUD_COMPRESSION_LZ4; + req->compressed_length = cpu_to_le32(complen); + } + +end_cpu_access: + if (import_attach) + dma_buf_end_cpu_access(import_attach->dmabuf, DMA_FROM_DEVICE); +vunmap: + drm_gem_shmem_vunmap(fb->obj[0], &map); + + return ret; +} + +static int gud_flush_rect(struct gud_device *gdrm, struct drm_framebuffer *fb, + const struct drm_format_info *format, struct drm_rect *rect) +{ + struct usb_device *usb = gud_to_usb_device(gdrm); + struct gud_set_buffer_req req; + int ret, actual_length; + size_t len, trlen; + + drm_dbg(&gdrm->drm, "Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); + + ret = gud_prep_flush(gdrm, fb, format, rect, &req); + if (ret) + return ret; + + len = le32_to_cpu(req.length); + + if (req.compression) + trlen = le32_to_cpu(req.compressed_length); + else + trlen = len; + + gdrm->stats_length += len; + /* Did it wrap around? */ + if (gdrm->stats_length <= len && gdrm->stats_actual_length) { + gdrm->stats_length = len; + gdrm->stats_actual_length = 0; + } + gdrm->stats_actual_length += trlen; + + if (!(gdrm->flags & GUD_DISPLAY_FLAG_FULL_UPDATE) || gdrm->prev_flush_failed) { + ret = gud_usb_set(gdrm, GUD_REQ_SET_BUFFER, 0, &req, sizeof(req)); + if (ret) + return ret; + } + + ret = usb_bulk_msg(usb, gdrm->bulk_pipe, gdrm->bulk_buf, trlen, + &actual_length, msecs_to_jiffies(3000)); + if (!ret && trlen != actual_length) + ret = -EIO; + if (ret) + gdrm->stats_num_errors++; + + return ret; +} + +void gud_clear_damage(struct gud_device *gdrm) +{ + gdrm->damage.x1 = INT_MAX; + gdrm->damage.y1 = INT_MAX; + gdrm->damage.x2 = 0; + gdrm->damage.y2 = 0; +} + +static void gud_add_damage(struct gud_device *gdrm, struct drm_rect *damage) +{ + gdrm->damage.x1 = min(gdrm->damage.x1, damage->x1); + gdrm->damage.y1 = min(gdrm->damage.y1, damage->y1); + gdrm->damage.x2 = max(gdrm->damage.x2, damage->x2); + gdrm->damage.y2 = max(gdrm->damage.y2, damage->y2); +} + +static void gud_retry_failed_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, + struct drm_rect *damage) +{ + /* + * pipe_update waits for the worker when the display mode is going to change. + * This ensures that the width and height is still the same making it safe to + * add back the damage. + */ + + mutex_lock(&gdrm->damage_lock); + if (!gdrm->fb) { + drm_framebuffer_get(fb); + gdrm->fb = fb; + } + gud_add_damage(gdrm, damage); + mutex_unlock(&gdrm->damage_lock); + + /* Retry only once to avoid a possible storm in case of continues errors. */ + if (!gdrm->prev_flush_failed) + queue_work(system_long_wq, &gdrm->work); + gdrm->prev_flush_failed = true; +} + +void gud_flush_work(struct work_struct *work) +{ + struct gud_device *gdrm = container_of(work, struct gud_device, work); + const struct drm_format_info *format; + struct drm_framebuffer *fb; + struct drm_rect damage; + unsigned int i, lines; + int idx, ret = 0; + size_t pitch; + + if (!drm_dev_enter(&gdrm->drm, &idx)) + return; + + mutex_lock(&gdrm->damage_lock); + fb = gdrm->fb; + gdrm->fb = NULL; + damage = gdrm->damage; + gud_clear_damage(gdrm); + mutex_unlock(&gdrm->damage_lock); + + if (!fb) + goto out; + + format = fb->format; + if (format->format == DRM_FORMAT_XRGB8888 && gdrm->xrgb8888_emulation_format) + format = gdrm->xrgb8888_emulation_format; + + /* Split update if it's too big */ + pitch = drm_format_info_min_pitch(format, 0, drm_rect_width(&damage)); + lines = drm_rect_height(&damage); + + if (gdrm->bulk_len < lines * pitch) + lines = gdrm->bulk_len / pitch; + + for (i = 0; i < DIV_ROUND_UP(drm_rect_height(&damage), lines); i++) { + struct drm_rect rect = damage; + + rect.y1 += i * lines; + rect.y2 = min_t(u32, rect.y1 + lines, damage.y2); + + ret = gud_flush_rect(gdrm, fb, format, &rect); + if (ret) { + if (ret != -ENODEV && ret != -ECONNRESET && + ret != -ESHUTDOWN && ret != -EPROTO) { + gud_retry_failed_flush(gdrm, fb, &damage); + dev_err_once(fb->dev->dev, + "Failed to flush framebuffer: error=%d\n", ret); + } + break; + } + + gdrm->prev_flush_failed = false; + } + + drm_framebuffer_put(fb); +out: + drm_dev_exit(idx); +} + +static void gud_fb_queue_damage(struct gud_device *gdrm, struct drm_framebuffer *fb, + struct drm_rect *damage) +{ + struct drm_framebuffer *old_fb = NULL; + + mutex_lock(&gdrm->damage_lock); + + if (fb != gdrm->fb) { + old_fb = gdrm->fb; + drm_framebuffer_get(fb); + gdrm->fb = fb; + } + + gud_add_damage(gdrm, damage); + + mutex_unlock(&gdrm->damage_lock); + + queue_work(system_long_wq, &gdrm->work); + + if (old_fb) + drm_framebuffer_put(old_fb); +} + +int gud_pipe_check(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *new_plane_state, + struct drm_crtc_state *new_crtc_state) +{ + struct gud_device *gdrm = to_gud_device(pipe->crtc.dev); + struct drm_plane_state *old_plane_state = pipe->plane.state; + const struct drm_display_mode *mode = &new_crtc_state->mode; + struct drm_atomic_state *state = new_plane_state->state; + struct drm_framebuffer *old_fb = old_plane_state->fb; + struct drm_connector_state *connector_state = NULL; + struct drm_framebuffer *fb = new_plane_state->fb; + const struct drm_format_info *format = fb->format; + struct drm_connector *connector; + int idx, ret, num_properties; + struct gud_state_req *req; + unsigned int i; + size_t len; + + if (WARN_ON_ONCE(!fb)) + return -EINVAL; + + if (old_plane_state->rotation != new_plane_state->rotation) + new_crtc_state->mode_changed = true; + + if (old_fb && old_fb->format != format) + new_crtc_state->mode_changed = true; + + if (!new_crtc_state->mode_changed && !new_crtc_state->connectors_changed) + return 0; + + /* Only one connector is supported */ + if (hweight32(new_crtc_state->connector_mask) != 1) + return -EINVAL; + + if (format->format == DRM_FORMAT_XRGB8888 && gdrm->xrgb8888_emulation_format) + format = gdrm->xrgb8888_emulation_format; + + for_each_new_connector_in_state(state, connector, connector_state, i) { + if (connector_state->crtc) + break; + } + + if (WARN_ON_ONCE(!connector_state)) + return -ENOENT; + + num_properties = gud_connector_fill_properties(connector, NULL, NULL); + if (num_properties < 0) + return num_properties; + + num_properties += gdrm->num_properties; + + len = struct_size(req, properties, num_properties); + req = kzalloc(len, GFP_KERNEL); + if (!req) + return -ENOMEM; + + gud_from_display_mode(&req->mode, mode); + + req->format = gud_from_fourcc(format->format); + if (WARN_ON_ONCE(!req->format)) + return -EINVAL; + + req->connector = drm_connector_index(connector); + req->num_properties = num_properties; + + num_properties = gud_connector_fill_properties(connector, connector_state, + req->properties); + + for (i = 0; i < gdrm->num_properties; i++) { + u16 prop = gdrm->properties[i]; + u64 val; + + switch (prop) { + case GUD_PROPERTY_ROTATION: + /* DRM UAPI matches the protocol so use value directly */ + val = new_plane_state->rotation; + break; + default: + WARN_ON_ONCE(1); + ret = -EINVAL; + goto out; + } + + req->properties[num_properties + i].prop = cpu_to_le16(prop); + req->properties[num_properties + i].val = cpu_to_le64(val); + } + + if (drm_dev_enter(fb->dev, &idx)) { + ret = gud_usb_set(gdrm, GUD_REQ_SET_STATE_CHECK, 0, req, len); + drm_dev_exit(idx); + } else { + ret = -ENODEV; + } +out: + kfree(req); + + return ret; +} + +void gud_pipe_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *old_state) +{ + struct drm_device *drm = pipe->crtc.dev; + struct gud_device *gdrm = to_gud_device(drm); + struct drm_plane_state *state = pipe->plane.state; + struct drm_framebuffer *fb = state->fb; + struct drm_crtc *crtc = &pipe->crtc; + struct drm_rect damage; + int idx; + + if (crtc->state->mode_changed || !crtc->state->enable) { + cancel_work_sync(&gdrm->work); + mutex_lock(&gdrm->damage_lock); + if (gdrm->fb) { + drm_framebuffer_put(gdrm->fb); + gdrm->fb = NULL; + } + gud_clear_damage(gdrm); + mutex_unlock(&gdrm->damage_lock); + } + + if (!drm_dev_enter(drm, &idx)) + return; + + if (!old_state->fb) + gud_usb_write8(gdrm, GUD_REQ_SET_CONTROLLER_ENABLE, 1); + + if (fb && (crtc->state->mode_changed || crtc->state->connectors_changed)) + gud_usb_set(gdrm, GUD_REQ_SET_STATE_COMMIT, 0, NULL, 0); + + if (crtc->state->active_changed) + gud_usb_write8(gdrm, GUD_REQ_SET_DISPLAY_ENABLE, crtc->state->active); + + if (drm_atomic_helper_damage_merged(old_state, state, &damage)) { + if (gdrm->flags & GUD_DISPLAY_FLAG_FULL_UPDATE) + drm_rect_init(&damage, 0, 0, fb->width, fb->height); + gud_fb_queue_damage(gdrm, fb, &damage); + } + + if (!crtc->state->enable) + gud_usb_write8(gdrm, GUD_REQ_SET_CONTROLLER_ENABLE, 0); + + drm_dev_exit(idx); +} diff --git a/include/drm/gud.h b/include/drm/gud.h new file mode 100644 index 000000000000..ebf19f50f780 --- /dev/null +++ b/include/drm/gud.h @@ -0,0 +1,356 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2020 Noralf Trønnes + */ + +#ifndef __LINUX_GUD_H +#define __LINUX_GUD_H + +#include + +/* + * struct gud_display_descriptor_req - Display descriptor + * @magic: Magic value GUD_DISPLAY_MAGIC + * @version: Protocol version + * @flags: Flags + * - STATUS_ON_SET: Always do a status request after a SET request. + * This is used by the Linux gadget driver since it has + * no way to control the status stage of a control OUT + * request that has a payload. + * - FULL_UPDATE: Always send the entire framebuffer when flushing changes. + * The GUD_REQ_SET_BUFFER request will not be sent + * before each bulk transfer, it will only be sent if the + * previous bulk transfer had failed. This gives the device + * a chance to reset its state machine if needed. + * This flag can not be used in combination with compression. + * @compression: Supported compression types + * - GUD_COMPRESSION_LZ4: LZ4 lossless compression. + * @max_buffer_size: Maximum buffer size the device can handle (optional). + * This is useful for devices that don't have a big enough + * buffer to decompress the entire framebuffer in one go. + * @min_width: Minimum pixel width the controller can handle + * @max_width: Maximum width + * @min_height: Minimum height + * @max_height: Maximum height + * @num_formats: Number of supported pixel formats + * @num_properties: Number of properties that are not connector properties + * @num_connectors: Number of connectors + * + * Devices that have only one display mode will have min_width == max_width + * and min_height == max_height. + */ +struct gud_display_descriptor_req { + __u32 magic; +#define GUD_DISPLAY_MAGIC 0x1d50614d + __u8 version; + __le32 flags; +#define GUD_DISPLAY_FLAG_STATUS_ON_SET BIT(0) +#define GUD_DISPLAY_FLAG_FULL_UPDATE BIT(1) + __u8 compression; +#define GUD_COMPRESSION_LZ4 BIT(0) + __le32 max_buffer_size; + __le32 min_width; + __le32 max_width; + __le32 min_height; + __le32 max_height; + __u8 num_formats; + __u8 num_properties; + __u8 num_connectors; +} __packed; + +/* + * struct gud_property_req - Property + * @prop: Property + * @val: Value + */ +struct gud_property_req { + __le16 prop; + __le64 val; +} __packed; + +/* + * struct gud_display_mode_req - Display mode + * @clock: Pixel clock in kHz + * @hdisplay: Horizontal display size + * @hsync_start: Horizontal sync start + * @hsync_end: Horizontal sync end + * @htotal: Horizontal total size + * @vdisplay: Vertical display size + * @vsync_start: Vertical sync start + * @vsync_end: Vertical sync end + * @vtotal: Vertical total size + * @flags: Bits 0-13 are the same as in the RandR protocol and also what DRM uses. + * The deprecated bits are reused for internal protocol flags leaving us + * free to follow DRM for the other bits in the future. + * - FLAG_PREFERRED: Set on the preferred display mode. + */ +struct gud_display_mode_req { + __le32 clock; + __le16 hdisplay; + __le16 hsync_start; + __le16 hsync_end; + __le16 htotal; + __le16 vdisplay; + __le16 vsync_start; + __le16 vsync_end; + __le16 vtotal; + __le32 flags; +#define GUD_DISPLAY_MODE_FLAG_PHSYNC BIT(0) +#define GUD_DISPLAY_MODE_FLAG_NHSYNC BIT(1) +#define GUD_DISPLAY_MODE_FLAG_PVSYNC BIT(2) +#define GUD_DISPLAY_MODE_FLAG_NVSYNC BIT(3) +#define GUD_DISPLAY_MODE_FLAG_INTERLACE BIT(4) +#define GUD_DISPLAY_MODE_FLAG_DBLSCAN BIT(5) +#define GUD_DISPLAY_MODE_FLAG_CSYNC BIT(6) +#define GUD_DISPLAY_MODE_FLAG_PCSYNC BIT(7) +#define GUD_DISPLAY_MODE_FLAG_NCSYNC BIT(8) +#define GUD_DISPLAY_MODE_FLAG_HSKEW BIT(9) +/* BCast and PixelMultiplex are deprecated */ +#define GUD_DISPLAY_MODE_FLAG_DBLCLK BIT(12) +#define GUD_DISPLAY_MODE_FLAG_CLKDIV2 BIT(13) +#define GUD_DISPLAY_MODE_FLAG_USER_MASK \ + (GUD_DISPLAY_MODE_FLAG_PHSYNC | GUD_DISPLAY_MODE_FLAG_NHSYNC | \ + GUD_DISPLAY_MODE_FLAG_PVSYNC | GUD_DISPLAY_MODE_FLAG_NVSYNC | \ + GUD_DISPLAY_MODE_FLAG_INTERLACE | GUD_DISPLAY_MODE_FLAG_DBLSCAN | \ + GUD_DISPLAY_MODE_FLAG_CSYNC | GUD_DISPLAY_MODE_FLAG_PCSYNC | \ + GUD_DISPLAY_MODE_FLAG_NCSYNC | GUD_DISPLAY_MODE_FLAG_HSKEW | \ + GUD_DISPLAY_MODE_FLAG_DBLCLK | GUD_DISPLAY_MODE_FLAG_CLKDIV2) +/* Internal protocol flags */ +#define GUD_DISPLAY_MODE_FLAG_PREFERRED BIT(10) +} __packed; + +/* + * struct gud_connector_descriptor_req - Connector descriptor + * @connector_type: Connector type (GUD_CONNECTOR_TYPE_*). + * If the host doesn't support the type it should fall back to PANEL. + * @flags: Flags + * - POLL_STATUS: Connector status can change (polled every 10 seconds) + * - INTERLACE: Interlaced modes are supported + * - DOUBLESCAN: Doublescan modes are supported + * @num_properties: Number of supported properties + */ +struct gud_connector_descriptor_req { + __u8 connector_type; +#define GUD_CONNECTOR_TYPE_PANEL 0 +#define GUD_CONNECTOR_TYPE_VGA 1 +#define GUD_CONNECTOR_TYPE_COMPOSITE 2 +#define GUD_CONNECTOR_TYPE_SVIDEO 3 +#define GUD_CONNECTOR_TYPE_COMPONENT 4 +#define GUD_CONNECTOR_TYPE_DVI 5 +#define GUD_CONNECTOR_TYPE_DISPLAYPORT 6 +#define GUD_CONNECTOR_TYPE_HDMI 7 + __le32 flags; +#define GUD_CONNECTOR_FLAGS_POLL_STATUS BIT(0) +#define GUD_CONNECTOR_FLAGS_INTERLACE BIT(1) +#define GUD_CONNECTOR_FLAGS_DOUBLESCAN BIT(2) + __u8 num_properties; +} __packed; + +/* + * struct gud_connector_status_req - Connector status + * @status: Status + * - DISCONNECTED: Connector is disconnected + * - CONNECTED: Connector is connected + * - UNKNOWN: Connection status is unknown + * Flags: + * - CHANGED: A change has happened since the last request + * @num_modes: Number of available display modes + * @edid_len: Length of EDID data + * + * If @num_modes is zero, EDID is used to create display modes. + * If both @num_modes and @edid_len are set, EDID is just passed on to userspace + * in the EDID connector property. + * + * Userspace will get a HOTPLUG uevent if one of the following is true: + * - Connection status has changed + * - @num_modes or @edid_len has changed + * - CHANGED is set + */ +struct gud_connector_status_req { + __u8 status; +#define GUD_CONNECTOR_STATUS_DISCONNECTED 0x00 +#define GUD_CONNECTOR_STATUS_CONNECTED 0x01 +#define GUD_CONNECTOR_STATUS_UNKNOWN 0x02 +#define GUD_CONNECTOR_STATUS_CONNECTED_MASK 0x03 +#define GUD_CONNECTOR_STATUS_CHANGED BIT(7) + __le16 num_modes; + __le16 edid_len; +} __packed; + +/* + * struct gud_set_buffer_req - Set buffer transfer info + * @x: X position of rectangle + * @y: Y position + * @width: Pixel width of rectangle + * @height: Pixel height + * @length: Buffer length in bytes + * @compression: Transfer compression + * @compressed_length: Compressed buffer length + * + * This request is issued right before the bulk transfer. + * @x, @y, @width and @height specifies the rectangle where the buffer should be + * placed inside the framebuffer. + */ +struct gud_set_buffer_req { + __le32 x; + __le32 y; + __le32 width; + __le32 height; + __le32 length; + __u8 compression; + __le32 compressed_length; +} __packed; + +/* + * struct gud_state_req - Display state + * @mode: Display mode + * @format: Pixel format GUD_PIXEL_FORMAT_* + * @connector: Connector index + * @num_properties: Number of properties in the state + * @properties: Array of properties + * + * The entire state is transferred each time there's a change. + */ +struct gud_state_req { + struct gud_display_mode_req mode; + __u8 format; + __u8 connector; + __u8 num_properties; + struct gud_property_req properties[]; +} __packed; + +/* List of supported connector properties: */ + +/* Margins in pixels to deal with overscan, range 0-100 */ +#define GUD_PROPERTY_TV_LEFT_MARGIN 1 +#define GUD_PROPERTY_TV_RIGHT_MARGIN 2 +#define GUD_PROPERTY_TV_TOP_MARGIN 3 +#define GUD_PROPERTY_TV_BOTTOM_MARGIN 4 +/* Number of modes are placed at _SHIFT in val on retrieval */ +#define GUD_PROPERTY_TV_MODE 5 + #define GUD_CONNECTOR_TV_MODE_NUM_SHIFT 16 +/* Brightness in percent, range 0-100 */ +#define GUD_PROPERTY_TV_BRIGHTNESS 6 +/* Contrast in percent, range 0-100 */ +#define GUD_PROPERTY_TV_CONTRAST 7 +/* Flicker reduction in percent, range 0-100 */ +#define GUD_PROPERTY_TV_FLICKER_REDUCTION 8 +/* Overscan in percent, range 0-100 */ +#define GUD_PROPERTY_TV_OVERSCAN 9 +/* Saturation in percent, range 0-100 */ +#define GUD_PROPERTY_TV_SATURATION 10 +/* Hue in percent, range 0-100 */ +#define GUD_PROPERTY_TV_HUE 11 + +/* + * Backlight brightness is in the range 0-100 inclusive. The value represents the human perceptual + * brightness and not a linear PWM value. 0 is minimum brightness which should not turn the + * backlight completely off. The DPMS connector property should be used to control power which will + * trigger a GUD_REQ_SET_DISPLAY_ENABLE request. + * + * This does not map to a DRM property, it is used with the backlight device. + */ +#define GUD_PROPERTY_BACKLIGHT_BRIGHTNESS 12 + +/* List of supported properties that are not connector propeties: */ + +/* + * Plane rotation. Should return the supported bitmask on + * GUD_REQ_GET_PROPERTIES. GUD_ROTATION_0 is mandatory. + * + * Note: This is not display rotation so 90/270 will need scaling to make it fit (unless squared). + */ +#define GUD_PROPERTY_ROTATION 50 + #define GUD_ROTATION_0 BIT(0) + #define GUD_ROTATION_90 BIT(1) + #define GUD_ROTATION_180 BIT(2) + #define GUD_ROTATION_270 BIT(3) + #define GUD_ROTATION_REFLECT_X BIT(4) + #define GUD_ROTATION_REFLECT_Y BIT(5) + #define GUD_ROTATION_MASK (GUD_ROTATION_0 | GUD_ROTATION_90 | \ + GUD_ROTATION_180 | GUD_ROTATION_270 | \ + GUD_ROTATION_REFLECT_X | GUD_ROTATION_REFLECT_Y) + +/* USB Control requests: */ + +/* Get status from the last GET/SET control request. Value is u8. */ +#define GUD_REQ_GET_STATUS 0x00 + /* Status values: */ + #define GUD_STATUS_OK 0x00 + #define GUD_STATUS_BUSY 0x01 + #define GUD_STATUS_REQUEST_NOT_SUPPORTED 0x02 + #define GUD_STATUS_PROTOCOL_ERROR 0x03 + #define GUD_STATUS_INVALID_PARAMETER 0x04 + #define GUD_STATUS_ERROR 0x05 + +/* Get display descriptor as a &gud_display_descriptor_req */ +#define GUD_REQ_GET_DESCRIPTOR 0x01 + +/* + * If the host driver doesn't support the device protocol version it will send the versions it + * supports starting with the latest. If the device isn't backwards compatible or doesn't support + * the version the host suggests, it shall stall the request. The version is sent as u8. + */ +#define GUD_REQ_SET_VERSION 0x30 + +/* Get supported pixel formats as a byte array of GUD_PIXEL_FORMAT_* */ +#define GUD_REQ_GET_FORMATS 0x40 + /* R1 is a 1-bit monochrome transfer format presented to userspace as XRGB8888 */ + #define GUD_PIXEL_FORMAT_R1 0x01 + #define GUD_PIXEL_FORMAT_RGB565 0x40 + #define GUD_PIXEL_FORMAT_XRGB8888 0x80 + #define GUD_PIXEL_FORMAT_ARGB8888 0x81 + +/* + * Get supported properties that are not connector propeties as a &gud_property_req array. + * gud_property_req.val often contains the initial value for the property. + */ +#define GUD_REQ_GET_PROPERTIES 0x41 + +/* Connector requests have the connector index passed in the wValue field */ + +/* Get connector descriptor as a &gud_connector_descriptor_req */ +#define GUD_REQ_GET_CONNECTOR 0x50 + +/* + * Get properties supported by the connector as a &gud_property_req array. + * gud_property_req.val often contains the initial value for the property. + */ +#define GUD_REQ_GET_CONNECTOR_PROPERTIES 0x51 + +/* + * Issued when there's a TV_MODE property present. + * Gets an array of the supported TV_MODE names each entry of length + * GUD_CONNECTOR_TV_MODE_NAME_LEN. Names must be NUL-terminated. + */ +#define GUD_REQ_GET_CONNECTOR_TV_MODE_VALUES 0x52 + #define GUD_CONNECTOR_TV_MODE_NAME_LEN 16 + +/* When userspace checks connector status, this is issued first, not used for poll requests. */ +#define GUD_REQ_SET_CONNECTOR_FORCE_DETECT 0x53 + +/* Get connector status as &gud_connector_status_req. */ +#define GUD_REQ_GET_CONNECTOR_STATUS 0x54 + +/* Get &gud_display_mode_req array of supported display modes */ +#define GUD_REQ_GET_CONNECTOR_MODES 0x55 + +/* Get Extended Display Identification Data */ +#define GUD_REQ_GET_CONNECTOR_EDID 0x56 + +/* Set buffer properties before bulk transfer as &gud_set_buffer_req */ +#define GUD_REQ_SET_BUFFER 0x60 + +/* Check display configuration as &gud_state_req */ +#define GUD_REQ_SET_STATE_CHECK 0x61 + +/* Apply the previous STATE_CHECK configuration */ +#define GUD_REQ_SET_STATE_COMMIT 0x62 + +/* Enable/disable the display controller, value is u8: 0/1 */ +#define GUD_REQ_SET_CONTROLLER_ENABLE 0x63 + +/* Enable/disable display/output (DPMS), value is u8: 0/1 */ +#define GUD_REQ_SET_DISPLAY_ENABLE 0x64 + +#endif -- 2.23.0 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-21.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 76A35C433DB for ; Wed, 20 Jan 2021 17:11:01 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3CB3F2242A for ; Wed, 20 Jan 2021 17:11:01 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3CB3F2242A Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=tronnes.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7D3586E418; Wed, 20 Jan 2021 17:11:00 +0000 (UTC) X-Greylist: delayed 596 seconds by postgrey-1.36 at gabe; Wed, 20 Jan 2021 17:10:51 UTC Received: from asav21.altibox.net (asav21.altibox.net [109.247.116.8]) by gabe.freedesktop.org (Postfix) with ESMTPS id 9A8336E0C4 for ; Wed, 20 Jan 2021 17:10:51 +0000 (UTC) Received: from localhost.localdomain (unknown [81.166.168.211]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: noralf.tronnes@ebnett.no) by asav21.altibox.net (Postfix) with ESMTPSA id A68D280161; Wed, 20 Jan 2021 18:00:53 +0100 (CET) From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Subject: [PATCH v4 3/3] drm: Add Generic USB Display driver Date: Wed, 20 Jan 2021 18:00:33 +0100 Message-Id: <20210120170033.38468-4-noralf@tronnes.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20210120170033.38468-1-noralf@tronnes.org> References: <20210120170033.38468-1-noralf@tronnes.org> MIME-Version: 1.0 X-CMAE-Score: 0 X-CMAE-Analysis: v=2.3 cv=LfoSFAXi c=1 sm=1 tr=0 a=OYZzhG0JTxDrWp/F2OJbnw==:117 a=OYZzhG0JTxDrWp/F2OJbnw==:17 a=IkcTkHD0fZMA:10 a=M51BFTxLslgA:10 a=SJz97ENfAAAA:8 a=gAmX6pxEAAAA:20 a=e5mUnYsNAAAA:8 a=20KFwNOVAAAA:8 a=5BARwAl1Z-KXKs0cIXUA:9 a=Xr9BYLAfEHlT6O8Q:21 a=rLqREtmTxl6zVh9-:21 a=QEXdDO2ut3YA:10 a=vFet0B0WnEQeilDPIY6i:22 a=Vxmtnl_E_bksehYqCbjh:22 a=pHzHmUro8NiASowvMSCR:22 a=nt3jZW36AmriUCFCBwmW:22 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: hudson@trmm.net, markus@raatikainen.cc, sam@ravnborg.org, linux-usb@vger.kernel.org, th020394@gmail.com, lkundrak@v3.sk, pontus.fuchs@gmail.com, peter@stuge.se Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" VGhpcyBhZGRzIGEgZ2VuZXJpYyBVU0IgZGlzcGxheSBkcml2ZXIgd2l0aCB0aGUgaW50ZW50aW9u IHRoYXQgaXQgY2FuIGJlCnVzZWQgd2l0aCBmdXR1cmUgVVNCIGludGVyZmFjZWQgbG93IGVuZCBk aXNwbGF5cy9hZGFwdGVycy4gVGhlIExpbnV4CmdhZGdldCBkZXZpY2UgZHJpdmVyIHdpbGwgc2Vy dmUgYXMgdGhlIGNhbm9uaWNhbCBkZXZpY2UgaW1wbGVtZW50YXRpb24uCgpUaGUgZm9sbG93aW5n IERSTSBwcm9wZXJ0aWVzIGFyZSBzdXBwb3J0ZWQ6Ci0gUGxhbmUgcm90YXRpb24KLSBDb25uZWN0 b3IgVFYgcHJvcGVydGllcwoKVGhlcmUgaXMgYWxzbyBzdXBwb3J0IGZvciBiYWNrbGlnaHQgYnJp Z2h0bmVzcyBleHBvc2VkIGFzIGEgYmFja2xpZ2h0CmRldmljZS4KCkRpc3BsYXkgbW9kZXMgY2Fu IGJlIG1hZGUgYXZhaWxhYmxlIHRvIHRoZSBob3N0IGRyaXZlciBlaXRoZXIgYXMgRFJNCmRpc3Bs YXkgbW9kZXMgb3IgdGhyb3VnaCBFRElELiBJZiBib3RoIGFyZSBwcmVzZW50LCBFRElEIGlzIGp1 c3QgcGFzc2VkCm9uIHRvIHVzZXJzcGFjZS4KClBlcmZvcm1hbmNlIGlzIHByZWZlcnJlZCBvdmVy IGNvbG9yIGRlcHRoLCBzbyBpZiB0aGUgZGV2aWNlIHN1cHBvcnRzClJHQjU2NSwgRFJNX0NBUF9E VU1CX1BSRUZFUlJFRF9ERVBUSCB3aWxsIHJldHVybiAxNi4KCklmIHRoZSBkZXZpY2UgdHJhbnNm ZXIgYnVmZmVyIGNhbid0IGZpdCBhbiB1bmNvbXByZXNzZWQgZnJhbWVidWZmZXIKdXBkYXRlLCB0 aGUgdXBkYXRlIGlzIHNwbGl0IHVwIGludG8gcGFydHMgdGhhdCBkbyBmaXQuCgpPcHRpbWFsIHVz ZXIgZXhwZXJpZW5jZSBpcyBhY2hpZXZlZCBieSBwcm92aWRpbmcgZGFtYWdlIHJlcG9ydHMgZWl0 aGVyIGJ5CnNldHRpbmcgRkJfREFNQUdFX0NMSVBTIG9uIHBhZ2VmbGlwcyBvciBjYWxsaW5nIERS TV9JT0NUTF9NT0RFX0RJUlRZRkIuCgpMWjQgY29tcHJlc3Npb24gaXMgdXNlZCBpZiB0aGUgZGV2 aWNlIHN1cHBvcnRzIGl0LgoKVGhlIGRyaXZlciBzdXBwb3J0cyBhIG9uZSBiaXQgbW9ub2Nocm9t ZSB0cmFuc2ZlciBmb3JtYXQ6IFIxLiBUaGlzIGlzIG5vdAppbXBsZW1lbnRlZCBpbiB0aGUgZ2Fk Z2V0IGRyaXZlci4gSXQgaXMgYWRkZWQgaW4gcHJlcGFyYXRpb24gZm9yIGZ1dHVyZQptb25vY2hy b21lIGUtaW5rIGRpc3BsYXlzLgoKVGhlIGRyaXZlciBpcyBNSVQgbGljZW5zZWQgdG8gc21vb3Ro IHRoZSBwYXRoIGZvciBhbnkgQlNEIHBvcnQgb2YgdGhlCmRyaXZlci4KCnYyOgotIFVzZSBkZXZt X2RybV9kZXZfYWxsb2MoKSBhbmQgZHJtbV9tb2RlX2NvbmZpZ19pbml0KCkKLSBkcm1fZmJkZXZf Z2VuZXJpY19zZXR1cDogVXNlIHByZWZlcnJlZF9icHA9MCwgMTYgd2FzIGEgY29weSBwYXN0ZSBl cnJvcgotIFRoZSBkcm1fYmFja2xpZ2h0X2hlbHBlciBpcyBkcm9wcGVkLCBjb3B5IGluIHRoZSBj b2RlCi0gU3VwcG9ydCBwcm90b2NvbCB2ZXJzaW9uIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IGZv ciBkZXZpY2UKCnYzOgotIFVzZSBkb25hdGVkIE9wZW5tb2tvIFVTQiBwaWQKLSBVc2UgZGlyZWN0 IGNvbXByZXNzaW9uIGZyb20gZnJhbWVidWZmZXIgd2hlbiBwaXRjaCBtYXRjaGVzLCBub3Qgb25s eSBvbgogIGZ1bGwgZnJhbWVzLCBzbyBzcGxpdCB1cGRhdGVzIGNhbiBiZW5lZml0Ci0gVXNlIF9f bGUxNiBpbiBzdHJ1Y3QgZ3VkX2RybV9yZXFfZ2V0X2Nvbm5lY3Rvcl9zdGF0dXMKLSBTZXQgZWRp ZCBwcm9wZXJ0eSB3aGVuIHRoZSBkZXZpY2Ugb25seSBwcm92aWRlcyBlZGlkCi0gQ2xlYXIgY29t cHJlc3Npb24gZmllbGRzIGluIHN0cnVjdCBndWRfZHJtX3JlcV9zZXRfYnVmZmVyCi0gRml4IHBy b3RvY29sIHZlcnNpb24gbmVnb3RpYXRpb24KLSBSZW1vdmUgbW9kZS0+dnJlZnJlc2gsIGl0J3Mg Y2FsY3VsYXRlZAoKdjQ6Ci0gRHJvcCB0aGUgc3RhdHVzIHJlcSBwb2xsaW5nIHdoaWNoIHdhcyBh IHdvcmthcm91bmQgZm9yIHNvbWV0aGluZyB0aGF0CiAgdHVybmVkIG91dCB0byBiZSBhIGR3YzIg dWRjIGRyaXZlciBwcm9ibGVtCi0gQWRkIGEgZmxhZyBmb3IgdGhlIExpbnV4IGdhZGdldCB0byBy ZXF1aXJlIGEgc3RhdHVzIHJlcXVlc3Qgb24KICBTRVQgb3BlcmF0aW9ucy4gT3RoZXIgZGV2aWNl cyB3aWxsIG9ubHkgZ2V0IHN0YXR1cyByZXEgb24gU1RBTEwgZXJyb3JzCi0gVXNlIHByb3RvY29s IHNwZWNpZmljIGVycm9yIGNvZGVzIChQZXRlcikKLSBBZGQgYSBmbGFnIGZvciBkZXZpY2VzIHRo YXQgd2FudCB0byByZWNlaXZlIHRoZSBlbnRpcmUgZnJhbWVidWZmZXIgb24KICBlYWNoIGZsdXNo IChMdWJvbWlyKQotIFJldHJ5IGEgZmFpbGVkIGZyYW1lYnVmZmVyIGZsdXNoCi0gSWYgbW9kZSBo YXMgY2hhbmdlZCB3YWl0IGZvciB3b3JrZXIgYW5kIGNsZWFyIHBlbmRpbmcgZGFtYWdlIGJlZm9y ZQogIHF1ZXVpbmcgdXAgbmV3IGRhbWFnZSwgZmIgd2lkdGgvaGVpZ2h0IG1pZ2h0IGhhdmUgY2hh bmdlZAotIEluY3JlYXNlIGVycm9yIGNvdW50ZXIgb24gYnVsayB0cmFuc2ZlciBmYWlsdXJlcwot IFVzZSBEUk1fTU9ERV9DT05ORUNUT1JfVVNCCi0gSGFuZGxlIFIxIGttYWxsb2MgZXJyb3IgKFBl dGVyKQotIERvbid0IHRyeSBhbmQgcmVwbGljYXRlIHRoZSBVU0IgZ2V0IGRlc2NyaXB0b3IgcmVx dWVzdCBzdGFuZGFyZCBmb3IgdGhlCiAgZGlzcGxheSBkZXNjcmlwdG9yIChQZXRlcikKLSBNYWtl IG1heF9idWZmZXJfc2l6ZSBvcHRpb25hbCAoUGV0ZXIpLCBkcm9wIHRoZSBwb3cyIHJlcXVpcmVt ZW50IHNpbmNlCiAgaXQncyBub3QgbmVjZXNzYXJ5IGFueW1vcmUuCi0gRG9uJ3QgcHJlLWFsbG9j IGEgY29udHJvbCByZXF1ZXN0IGJ1ZmZlciwgaXQgd2FzIG9ubHkgNGsKLSBMZXQgZ3VkLmggZGVz Y3JpYmUgdGhlIHdob2xlIHByb3RvY29sIGV4cGxpY2l0bHkgYW5kIGRvbid0IGxldCBEUk0KICBs ZWFrIGludG8gaXQgKFBldGVyKQotIERyb3AgZGlzcGxheSBtb2RlIC5oc2tldyBhbmQgLnZzY2Fu IGZyb20gdGhlIHByb3RvY29sCi0gU2hvcnRlbiBuYW1lczogcy9HVURfRFJNXy9HVURfLyBzL2d1 ZF9kcm1fL2d1ZF8vIChQZXRlcikKLSBGaXggZ3VkX3BpcGVfY2hlY2soKSBjb25uZWN0b3IgcGlj a2luZyB3aGVuIHN3aXRjaGluZyBjb25uZWN0b3IKLSBEcm9wIGd1ZF9kcm1fZHJpdmVyX2dlbV9j cmVhdGVfb2JqZWN0KCkgY2FjaGVkIGlzIGRlZmF1bHQgbm93Ci0gUmV0cmlldmUgVVNCIGRldmlj ZSBmcm9tIHN0cnVjdCBkcm1fZGV2aWNlLmRldiBpbnN0ZWFkIG9mIGtlZXBpbmcgYQogIHBvaW50 ZXIKLSBIb25vdXIgZmItPm9mZnNldHNbMF0KLSBGaXggbW9kZSBmZXRjaGluZyB3aGVuIGNvbm5l Y3RvciBzdGF0dXMgaXMgZm9yY2VkCi0gQ2hlY2sgRURJRCBsZW5ndGggcmVwb3J0ZWQgYnkgdGhl IGRldmljZQotIFVzZSBkcm1fZG9fZ2V0X2VkaWQoKSBzbyB1c2Vyc3BhY2UgY2FuIG92ZXJycmlk ZSBFRElECi0gU2V0IGVwb2NoIGNvdW50ZXIgdG8gc2lnbmFsIGNvbm5lY3RvciBzdGF0dXMgY2hh bmdlCi0gZ3VkX2RybV9kcml2ZXIgY2FuIGJlIGNvbnN0IG5vdwoKQ2M6IFBldGVyIFN0dWdlIDxw ZXRlckBzdHVnZS5zZT4KQ2M6IEx1Ym9taXIgUmludGVsIDxsa3VuZHJha0B2My5zaz4KU2lnbmVk LW9mZi1ieTogTm9yYWxmIFRyw7hubmVzIDxub3JhbGZAdHJvbm5lcy5vcmc+Ci0tLQogTUFJTlRB SU5FUlMgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIDggKwogZHJpdmVycy9ncHUvZHJtL0tj b25maWcgICAgICAgICAgICAgfCAgIDIgKwogZHJpdmVycy9ncHUvZHJtL01ha2VmaWxlICAgICAg ICAgICAgfCAgIDEgKwogZHJpdmVycy9ncHUvZHJtL2d1ZC9LY29uZmlnICAgICAgICAgfCAgMTQg KwogZHJpdmVycy9ncHUvZHJtL2d1ZC9NYWtlZmlsZSAgICAgICAgfCAgIDQgKwogZHJpdmVycy9n cHUvZHJtL2d1ZC9ndWRfY29ubmVjdG9yLmMgfCA3MjIgKysrKysrKysrKysrKysrKysrKysrKysr KysrKwogZHJpdmVycy9ncHUvZHJtL2d1ZC9ndWRfZHJ2LmMgICAgICAgfCA2MjAgKysrKysrKysr KysrKysrKysrKysrKysrCiBkcml2ZXJzL2dwdS9kcm0vZ3VkL2d1ZF9pbnRlcm5hbC5oICB8IDE0 OCArKysrKysKIGRyaXZlcnMvZ3B1L2RybS9ndWQvZ3VkX3BpcGUuYyAgICAgIHwgNDcyICsrKysr KysrKysrKysrKysrKwogaW5jbHVkZS9kcm0vZ3VkLmggICAgICAgICAgICAgICAgICAgfCAzNTYg KysrKysrKysrKysrKysKIDEwIGZpbGVzIGNoYW5nZWQsIDIzNDcgaW5zZXJ0aW9ucygrKQogY3Jl YXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvZ3B1L2RybS9ndWQvS2NvbmZpZwogY3JlYXRlIG1vZGUg MTAwNjQ0IGRyaXZlcnMvZ3B1L2RybS9ndWQvTWFrZWZpbGUKIGNyZWF0ZSBtb2RlIDEwMDY0NCBk cml2ZXJzL2dwdS9kcm0vZ3VkL2d1ZF9jb25uZWN0b3IuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRy aXZlcnMvZ3B1L2RybS9ndWQvZ3VkX2Rydi5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9n cHUvZHJtL2d1ZC9ndWRfaW50ZXJuYWwuaAogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvZ3B1 L2RybS9ndWQvZ3VkX3BpcGUuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGluY2x1ZGUvZHJtL2d1ZC5o CgpkaWZmIC0tZ2l0IGEvTUFJTlRBSU5FUlMgYi9NQUlOVEFJTkVSUwppbmRleCAwMDExMmMwNDQ2 MDguLmU3ZjcxYWM1NWYwOCAxMDA2NDQKLS0tIGEvTUFJTlRBSU5FUlMKKysrIGIvTUFJTlRBSU5F UlMKQEAgLTU1MjUsNiArNTUyNSwxNCBAQCBTOglNYWludGFpbmVkCiBGOglEb2N1bWVudGF0aW9u L2RldmljZXRyZWUvYmluZGluZ3MvZGlzcGxheS9wYW5lbC9mZWl5YW5nLGZ5MDcwMjRkaTI2YTMw ZC55YW1sCiBGOglkcml2ZXJzL2dwdS9kcm0vcGFuZWwvcGFuZWwtZmVpeWFuZy1meTA3MDI0ZGky NmEzMGQuYwogCitEUk0gRFJJVkVSIEZPUiBHRU5FUklDIFVTQiBESVNQTEFZCitNOglOb3JhbGYg VHLDuG5uZXMgPG5vcmFsZkB0cm9ubmVzLm9yZz4KK1M6CU1haW50YWluZWQKK1c6CWh0dHBzOi8v Z2l0aHViLmNvbS9ub3Ryby9ndWQvd2lraQorVDoJZ2l0IGdpdDovL2Fub25naXQuZnJlZWRlc2t0 b3Aub3JnL2RybS9kcm0tbWlzYworRjoJZHJpdmVycy9ncHUvZHJtL2d1ZC8KK0Y6CWluY2x1ZGUv ZHJtL2d1ZC5oCisKIERSTSBEUklWRVIgRk9SIEdSQUlOIE1FRElBIEdNMTJVMzIwIFBST0pFQ1RP UlMKIE06CUhhbnMgZGUgR29lZGUgPGhkZWdvZWRlQHJlZGhhdC5jb20+CiBTOglNYWludGFpbmVk CmRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vS2NvbmZpZyBiL2RyaXZlcnMvZ3B1L2RybS9L Y29uZmlnCmluZGV4IDE0N2Q2MWI5Njc0ZS4uNmQzZjQ3OTMzZTUxIDEwMDY0NAotLS0gYS9kcml2 ZXJzL2dwdS9kcm0vS2NvbmZpZworKysgYi9kcml2ZXJzL2dwdS9kcm0vS2NvbmZpZwpAQCAtMzg4 LDYgKzM4OCw4IEBAIHNvdXJjZSAiZHJpdmVycy9ncHUvZHJtL3RpZHNzL0tjb25maWciCiAKIHNv dXJjZSAiZHJpdmVycy9ncHUvZHJtL3hsbngvS2NvbmZpZyIKIAorc291cmNlICJkcml2ZXJzL2dw dS9kcm0vZ3VkL0tjb25maWciCisKICMgS2VlcCBsZWdhY3kgZHJpdmVycyBsYXN0CiAKIG1lbnVj b25maWcgRFJNX0xFR0FDWQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL01ha2VmaWxlIGIv ZHJpdmVycy9ncHUvZHJtL01ha2VmaWxlCmluZGV4IDgxNTY5MDA5Zjg4NC4uNzhkZDhlMTI1MjVk IDEwMDY0NAotLS0gYS9kcml2ZXJzL2dwdS9kcm0vTWFrZWZpbGUKKysrIGIvZHJpdmVycy9ncHUv ZHJtL01ha2VmaWxlCkBAIC0xMjQsMyArMTI0LDQgQEAgb2JqLSQoQ09ORklHX0RSTV9BU1BFRURf R0ZYKSArPSBhc3BlZWQvCiBvYmotJChDT05GSUdfRFJNX01DREUpICs9IG1jZGUvCiBvYmotJChD T05GSUdfRFJNX1RJRFNTKSArPSB0aWRzcy8KIG9iai15CQkJKz0geGxueC8KK29iai15CQkJKz0g Z3VkLwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2d1ZC9LY29uZmlnIGIvZHJpdmVycy9n cHUvZHJtL2d1ZC9LY29uZmlnCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAw MC4uZDgzMmNkNjM2ODdjCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9ncHUvZHJtL2d1ZC9L Y29uZmlnCkBAIC0wLDAgKzEsMTQgQEAKKyMgU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0y LjAKKworY29uZmlnIERSTV9HVUQKKwl0cmlzdGF0ZSAiR2VuZXJpYyBVU0IgRGlzcGxheSIKKwlk ZXBlbmRzIG9uIERSTSAmJiBVU0IKKwlzZWxlY3QgTFo0X0NPTVBSRVNTCisJc2VsZWN0IERSTV9L TVNfSEVMUEVSCisJc2VsZWN0IERSTV9HRU1fU0hNRU1fSEVMUEVSCisJc2VsZWN0IEJBQ0tMSUdI VF9DTEFTU19ERVZJQ0UKKwloZWxwCisJICBUaGlzIGlzIGEgRFJNIGRpc3BsYXkgZHJpdmVyIGZv ciBHZW5lcmljIFVTQiBEaXNwbGF5cyBvciBkaXNwbGF5CisJICBhZGFwdGVycy4KKworCSAgSWYg TSBpcyBzZWxlY3RlZCB0aGUgbW9kdWxlIHdpbGwgYmUgY2FsbGVkIGd1ZC4KZGlmZiAtLWdpdCBh L2RyaXZlcnMvZ3B1L2RybS9ndWQvTWFrZWZpbGUgYi9kcml2ZXJzL2dwdS9kcm0vZ3VkL01ha2Vm aWxlCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uZDJiYjUzYTY1ZGU2 Ci0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9ncHUvZHJtL2d1ZC9NYWtlZmlsZQpAQCAtMCww ICsxLDQgQEAKKyMgU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAKKworZ3VkLW9ianMJ CQk6PSBndWRfZHJ2Lm8gZ3VkX3BpcGUubyBndWRfY29ubmVjdG9yLm8KK29iai0kKENPTkZJR19E Uk1fR1VEKQkJKz0gZ3VkLm8KZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9ndWQvZ3VkX2Nv bm5lY3Rvci5jIGIvZHJpdmVycy9ncHUvZHJtL2d1ZC9ndWRfY29ubmVjdG9yLmMKbmV3IGZpbGUg bW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi5hNGI5YmJmNDhlMTkKLS0tIC9kZXYvbnVs bAorKysgYi9kcml2ZXJzL2dwdS9kcm0vZ3VkL2d1ZF9jb25uZWN0b3IuYwpAQCAtMCwwICsxLDcy MiBAQAorLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVAorLyoKKyAqIENvcHlyaWdodCAy MDIwIE5vcmFsZiBUcsO4bm5lcworICovCisKKyNpbmNsdWRlIDxsaW51eC9iYWNrbGlnaHQuaD4K KworI2luY2x1ZGUgPGRybS9kcm1fYXRvbWljLmg+CisjaW5jbHVkZSA8ZHJtL2RybV9hdG9taWNf c3RhdGVfaGVscGVyLmg+CisjaW5jbHVkZSA8ZHJtL2RybV9jb25uZWN0b3IuaD4KKyNpbmNsdWRl IDxkcm0vZHJtX2Rydi5oPgorI2luY2x1ZGUgPGRybS9kcm1fZW5jb2Rlci5oPgorI2luY2x1ZGUg PGRybS9kcm1fZmlsZS5oPgorI2luY2x1ZGUgPGRybS9kcm1fbW9kZXNldF9oZWxwZXJfdnRhYmxl cy5oPgorI2luY2x1ZGUgPGRybS9kcm1fcHJpbnQuaD4KKyNpbmNsdWRlIDxkcm0vZHJtX3Byb2Jl X2hlbHBlci5oPgorI2luY2x1ZGUgPGRybS9kcm1fc2ltcGxlX2ttc19oZWxwZXIuaD4KKyNpbmNs dWRlIDxkcm0vZ3VkLmg+CisKKyNpbmNsdWRlICJndWRfaW50ZXJuYWwuaCIKKworc3RydWN0IGd1 ZF9jb25uZWN0b3IgeworCXN0cnVjdCBkcm1fY29ubmVjdG9yIGNvbm5lY3RvcjsKKwlzdHJ1Y3Qg ZHJtX2VuY29kZXIgZW5jb2RlcjsKKwlzdHJ1Y3QgYmFja2xpZ2h0X2RldmljZSAqYmFja2xpZ2h0 OworCisJLyogU3VwcG9ydGVkIHByb3BlcnRpZXMgKi8KKwl1MTYgKnByb3BlcnRpZXM7CisJdW5z aWduZWQgaW50IG51bV9wcm9wZXJ0aWVzOworCisJLyogSW5pdGlhbCBnYWRnZXQgdHYgc3RhdGUg aWYgYXBwbGljYWJsZSwgYXBwbGllZCBvbiBzdGF0ZSByZXNldCAqLworCXN0cnVjdCBkcm1fdHZf Y29ubmVjdG9yX3N0YXRlIGluaXRpYWxfdHZfc3RhdGU7CisKKwkvKgorCSAqIEluaXRpYWwgZ2Fk Z2V0IGJhY2tsaWdodCBicmlnaHRuZXNzIGlmIGFwcGxpY2FibGUsIGFwcGxpZWQgb24gc3RhdGUg cmVzZXQuCisJICogVGhlIHZhbHVlIC1FTk9ERVYgaXMgdXNlZCB0byBzaWduYWwgbm8gYmFja2xp Z2h0LgorCSAqLworCWludCBpbml0aWFsX2JyaWdodG5lc3M7CisKKwl1bnNpZ25lZCBpbnQgbnVt X21vZGVzOworCXNpemVfdCBlZGlkX2xlbjsKK307CisKK3N0YXRpYyBpbmxpbmUgc3RydWN0IGd1 ZF9jb25uZWN0b3IgKnRvX2d1ZF9jb25uZWN0b3Ioc3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5l Y3RvcikKK3sKKwlyZXR1cm4gY29udGFpbmVyX29mKGNvbm5lY3Rvciwgc3RydWN0IGd1ZF9jb25u ZWN0b3IsIGNvbm5lY3Rvcik7Cit9CisKK3N0YXRpYyBpbnQgZ3VkX2Nvbm5lY3Rvcl9iYWNrbGln aHRfdXBkYXRlX3N0YXR1cyhzdHJ1Y3QgYmFja2xpZ2h0X2RldmljZSAqYmQpCit7CisJc3RydWN0 IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvciA9IGJsX2dldF9kYXRhKGJkKTsKKwlzdHJ1Y3QgZHJt X2Nvbm5lY3Rvcl9zdGF0ZSAqY29ubmVjdG9yX3N0YXRlOworCXN0cnVjdCBkcm1fZGV2aWNlICpk ZXYgPSBjb25uZWN0b3ItPmRldjsKKwlzdHJ1Y3QgZHJtX21vZGVzZXRfYWNxdWlyZV9jdHggY3R4 OworCXN0cnVjdCBkcm1fYXRvbWljX3N0YXRlICpzdGF0ZTsKKwlpbnQgcmV0OworCisJc3RhdGUg PSBkcm1fYXRvbWljX3N0YXRlX2FsbG9jKGRldik7CisJaWYgKCFzdGF0ZSkKKwkJcmV0dXJuIC1F Tk9NRU07CisKKwlkcm1fbW9kZXNldF9hY3F1aXJlX2luaXQoJmN0eCwgMCk7CisJc3RhdGUtPmFj cXVpcmVfY3R4ID0gJmN0eDsKK3JldHJ5OgorCWNvbm5lY3Rvcl9zdGF0ZSA9IGRybV9hdG9taWNf Z2V0X2Nvbm5lY3Rvcl9zdGF0ZShzdGF0ZSwgY29ubmVjdG9yKTsKKwlpZiAoSVNfRVJSKGNvbm5l Y3Rvcl9zdGF0ZSkpIHsKKwkJcmV0ID0gUFRSX0VSUihjb25uZWN0b3Jfc3RhdGUpOworCQlnb3Rv IG91dDsKKwl9CisKKwkvKiBSZXVzZSB0di5icmlnaHRuZXNzIHRvIGF2b2lkIGhhdmluZyB0byBz dWJjbGFzcyAqLworCWNvbm5lY3Rvcl9zdGF0ZS0+dHYuYnJpZ2h0bmVzcyA9IGJkLT5wcm9wcy5i cmlnaHRuZXNzOworCisJcmV0ID0gZHJtX2F0b21pY19jb21taXQoc3RhdGUpOworb3V0OgorCWlm IChyZXQgPT0gLUVERUFETEspIHsKKwkJZHJtX2F0b21pY19zdGF0ZV9jbGVhcihzdGF0ZSk7CisJ CWRybV9tb2Rlc2V0X2JhY2tvZmYoJmN0eCk7CisJCWdvdG8gcmV0cnk7CisJfQorCisJZHJtX2F0 b21pY19zdGF0ZV9wdXQoc3RhdGUpOworCisJZHJtX21vZGVzZXRfZHJvcF9sb2NrcygmY3R4KTsK Kwlkcm1fbW9kZXNldF9hY3F1aXJlX2ZpbmkoJmN0eCk7CisKKwlyZXR1cm4gcmV0OworfQorCitz dGF0aWMgaW50IGd1ZF9jb25uZWN0b3JfYmFja2xpZ2h0X2dldF9icmlnaHRuZXNzKHN0cnVjdCBi YWNrbGlnaHRfZGV2aWNlICpiZCkKK3sKKwlzdHJ1Y3QgZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9y ID0gYmxfZ2V0X2RhdGEoYmQpOworCXN0cnVjdCBkcm1fZGV2aWNlICpkZXYgPSBjb25uZWN0b3It PmRldjsKKwlpbnQgYnJpZ2h0bmVzczsKKworCWRybV9tb2Rlc2V0X2xvY2soJmRldi0+bW9kZV9j b25maWcuY29ubmVjdGlvbl9tdXRleCwgTlVMTCk7CisJYnJpZ2h0bmVzcyA9IGNvbm5lY3Rvci0+ c3RhdGUtPnR2LmJyaWdodG5lc3M7CisJZHJtX21vZGVzZXRfdW5sb2NrKCZkZXYtPm1vZGVfY29u ZmlnLmNvbm5lY3Rpb25fbXV0ZXgpOworCisJcmV0dXJuIGJyaWdodG5lc3M7Cit9CisKK3N0YXRp YyBjb25zdCBzdHJ1Y3QgYmFja2xpZ2h0X29wcyBndWRfY29ubmVjdG9yX2JhY2tsaWdodF9vcHMg PSB7CisJLmdldF9icmlnaHRuZXNzID0gZ3VkX2Nvbm5lY3Rvcl9iYWNrbGlnaHRfZ2V0X2JyaWdo dG5lc3MsCisJLnVwZGF0ZV9zdGF0dXMJPSBndWRfY29ubmVjdG9yX2JhY2tsaWdodF91cGRhdGVf c3RhdHVzLAorfTsKKworc3RhdGljIGludCBndWRfY29ubmVjdG9yX2JhY2tsaWdodF9yZWdpc3Rl cihzdHJ1Y3QgZ3VkX2Nvbm5lY3RvciAqZ2Nvbm4pCit7CisJc3RydWN0IGRybV9jb25uZWN0b3Ig KmNvbm5lY3RvciA9ICZnY29ubi0+Y29ubmVjdG9yOworCXN0cnVjdCBiYWNrbGlnaHRfZGV2aWNl ICpiZDsKKwljb25zdCBjaGFyICpuYW1lOworCWNvbnN0IHN0cnVjdCBiYWNrbGlnaHRfcHJvcGVy dGllcyBwcm9wcyA9IHsKKwkJLnR5cGUgPSBCQUNLTElHSFRfUkFXLAorCQkuc2NhbGUgPSBCQUNL TElHSFRfU0NBTEVfTk9OX0xJTkVBUiwKKwkJLm1heF9icmlnaHRuZXNzID0gMTAwLAorCX07CisK KwluYW1lID0ga2FzcHJpbnRmKEdGUF9LRVJORUwsICJjYXJkJWQtJXMtYmFja2xpZ2h0IiwKKwkJ CSBjb25uZWN0b3ItPmRldi0+cHJpbWFyeS0+aW5kZXgsIGNvbm5lY3Rvci0+bmFtZSk7CisJaWYg KCFuYW1lKQorCQlyZXR1cm4gLUVOT01FTTsKKworCWJkID0gYmFja2xpZ2h0X2RldmljZV9yZWdp c3RlcihuYW1lLCBjb25uZWN0b3ItPmtkZXYsIGNvbm5lY3RvciwKKwkJCQkgICAgICAgJmd1ZF9j b25uZWN0b3JfYmFja2xpZ2h0X29wcywgJnByb3BzKTsKKwlrZnJlZShuYW1lKTsKKwlpZiAoSVNf RVJSKGJkKSkKKwkJcmV0dXJuIFBUUl9FUlIoYmQpOworCisJZ2Nvbm4tPmJhY2tsaWdodCA9IGJk OworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgZ3VkX2Nvbm5lY3Rvcl9zdGF0dXNfcmVx dWVzdChzdHJ1Y3QgZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9yKQoreworCXN0cnVjdCBndWRfY29u bmVjdG9yICpnY29ubiA9IHRvX2d1ZF9jb25uZWN0b3IoY29ubmVjdG9yKTsKKwlzdHJ1Y3QgZ3Vk X2RldmljZSAqZ2RybSA9IHRvX2d1ZF9kZXZpY2UoY29ubmVjdG9yLT5kZXYpOworCXN0cnVjdCBn dWRfY29ubmVjdG9yX3N0YXR1c19yZXEgcmVxOworCXUxNiBudW1fbW9kZXMsIGVkaWRfbGVuOwor CWludCByZXQ7CisKKwlyZXQgPSBndWRfdXNiX2dldChnZHJtLCBHVURfUkVRX0dFVF9DT05ORUNU T1JfU1RBVFVTLAorCQkJICBjb25uZWN0b3ItPmluZGV4LCAmcmVxLCBzaXplb2YocmVxKSk7CisJ aWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCXN3aXRjaCAocmVxLnN0YXR1cyAmIEdVRF9DT05O RUNUT1JfU1RBVFVTX0NPTk5FQ1RFRF9NQVNLKSB7CisJY2FzZSBHVURfQ09OTkVDVE9SX1NUQVRV U19ESVNDT05ORUNURUQ6CisJCXJldCA9IGNvbm5lY3Rvcl9zdGF0dXNfZGlzY29ubmVjdGVkOwor CQlicmVhazsKKwljYXNlIEdVRF9DT05ORUNUT1JfU1RBVFVTX0NPTk5FQ1RFRDoKKwkJcmV0ID0g Y29ubmVjdG9yX3N0YXR1c19jb25uZWN0ZWQ7CisJCWJyZWFrOworCWRlZmF1bHQ6CisJCXJldCA9 IGNvbm5lY3Rvcl9zdGF0dXNfdW5rbm93bjsKKwkJYnJlYWs7CisJfTsKKworCW51bV9tb2RlcyA9 IGxlMTZfdG9fY3B1KHJlcS5udW1fbW9kZXMpOworCWVkaWRfbGVuID0gbGUxNl90b19jcHUocmVx LmVkaWRfbGVuKTsKKworCWlmIChlZGlkX2xlbiAlIEVESURfTEVOR1RIKSB7CisJCWRybV9lcnIo Y29ubmVjdG9yLT5kZXYsICIlczogSW52YWxpZCBFRElEIHNpemU6ICV1XG4iLCBjb25uZWN0b3It Pm5hbWUsIGVkaWRfbGVuKTsKKwkJZWRpZF9sZW4gPSAwOworCX0KKworCWlmIChyZXEuc3RhdHVz ICYgR1VEX0NPTk5FQ1RPUl9TVEFUVVNfQ0hBTkdFRCB8fAorCSAgICBnY29ubi0+bnVtX21vZGVz ICE9IG51bV9tb2RlcyB8fCBnY29ubi0+ZWRpZF9sZW4gIT0gZWRpZF9sZW4pCisJCWNvbm5lY3Rv ci0+ZXBvY2hfY291bnRlciArPSAxOworCisJZ2Nvbm4tPm51bV9tb2RlcyA9IG51bV9tb2RlczsK KwlnY29ubi0+ZWRpZF9sZW4gPSBlZGlkX2xlbjsKKworCWlmICghbnVtX21vZGVzICYmICFlZGlk X2xlbiAmJiByZXQgIT0gY29ubmVjdG9yX3N0YXR1c19kaXNjb25uZWN0ZWQpCisJCWRybV9kYmdf a21zKGNvbm5lY3Rvci0+ZGV2LCAiJXM6IE5vIG1vZGVzIG9yIEVESUQuXG4iLCBjb25uZWN0b3It Pm5hbWUpOworCisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBndWRfY29ubmVjdG9yX2Rl dGVjdChzdHJ1Y3QgZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9yLAorCQkJCXN0cnVjdCBkcm1fbW9k ZXNldF9hY3F1aXJlX2N0eCAqY3R4LCBib29sIGZvcmNlKQoreworCXN0cnVjdCBndWRfZGV2aWNl ICpnZHJtID0gdG9fZ3VkX2RldmljZShjb25uZWN0b3ItPmRldik7CisJaW50IGlkeCwgcmV0Owor CisJaWYgKCFkcm1fZGV2X2VudGVyKGNvbm5lY3Rvci0+ZGV2LCAmaWR4KSkKKwkJcmV0dXJuIGNv bm5lY3Rvcl9zdGF0dXNfZGlzY29ubmVjdGVkOworCisJaWYgKGZvcmNlKSB7CisJCXJldCA9IGd1 ZF91c2Jfc2V0KGdkcm0sIEdVRF9SRVFfU0VUX0NPTk5FQ1RPUl9GT1JDRV9ERVRFQ1QsCisJCQkJ ICBjb25uZWN0b3ItPmluZGV4LCBOVUxMLCAwKTsKKwkJaWYgKHJldCkgeworCQkJcmV0ID0gY29u bmVjdG9yX3N0YXR1c191bmtub3duOworCQkJZ290byBleGl0OworCQl9CisJfQorCisJcmV0ID0g Z3VkX2Nvbm5lY3Rvcl9zdGF0dXNfcmVxdWVzdChjb25uZWN0b3IpOworCWlmIChyZXQgPCAwKQor CQlyZXQgPSBjb25uZWN0b3Jfc3RhdHVzX3Vua25vd247CitleGl0OgorCWRybV9kZXZfZXhpdChp ZHgpOworCisJcmV0dXJuIHJldDsKK30KKworc3RydWN0IGd1ZF9jb25uZWN0b3JfZ2V0X2VkaWRf Y3R4IHsKKwlzdHJ1Y3QgZ3VkX2Nvbm5lY3RvciAqZ2Nvbm47CisJdm9pZCAqYnVmOworfTsKKwor c3RhdGljIGludCBndWRfY29ubmVjdG9yX2dldF9lZGlkX2Jsb2NrKHZvaWQgKmRhdGEsIHU4ICpi dWYsIHVuc2lnbmVkIGludCBibG9jaywgc2l6ZV90IGxlbikKK3sKKwlzdHJ1Y3QgZ3VkX2Nvbm5l Y3Rvcl9nZXRfZWRpZF9jdHggKmN0eCA9IGRhdGE7CisJc3RydWN0IGd1ZF9jb25uZWN0b3IgKmdj b25uID0gY3R4LT5nY29ubjsKKwlzaXplX3Qgc3RhcnQgPSBibG9jayAqIEVESURfTEVOR1RIOwor CisJaWYgKHN0YXJ0ICsgbGVuID4gZ2Nvbm4tPmVkaWRfbGVuKQorCQlyZXR1cm4gLTE7CisKKwlp ZiAoIWJsb2NrKSB7CisJCXN0cnVjdCBndWRfZGV2aWNlICpnZHJtID0gdG9fZ3VkX2RldmljZShn Y29ubi0+Y29ubmVjdG9yLmRldik7CisJCWludCByZXQ7CisKKwkJLyogQ2hlY2sgYmVjYXVzZSBk cm1fZG9fZ2V0X2VkaWQoKSB3aWxsIHJldHJ5IG9uIGZhaWx1cmUgKi8KKwkJaWYgKCFjdHgtPmJ1 ZikKKwkJCWN0eC0+YnVmID0ga21hbGxvYyhnY29ubi0+ZWRpZF9sZW4sIEdGUF9LRVJORUwpOwor CQlpZiAoIWN0eC0+YnVmKQorCQkJcmV0dXJuIC0xOworCisJCXJldCA9IGd1ZF91c2JfZ2V0KGdk cm0sIEdVRF9SRVFfR0VUX0NPTk5FQ1RPUl9FRElELCBnY29ubi0+Y29ubmVjdG9yLmluZGV4LAor CQkJCSAgY3R4LT5idWYsIGdjb25uLT5lZGlkX2xlbik7CisJCWlmIChyZXQpCisJCQlyZXR1cm4g LTE7CisJfQorCisJbWVtY3B5KGJ1ZiwgY3R4LT5idWYgKyBzdGFydCwgbGVuKTsKKworCXJldHVy biAwOworfQorCitzdGF0aWMgaW50IGd1ZF9jb25uZWN0b3JfZ2V0X21vZGVzKHN0cnVjdCBkcm1f Y29ubmVjdG9yICpjb25uZWN0b3IpCit7CisJc3RydWN0IGd1ZF9jb25uZWN0b3IgKmdjb25uID0g dG9fZ3VkX2Nvbm5lY3Rvcihjb25uZWN0b3IpOworCXN0cnVjdCBndWRfZGV2aWNlICpnZHJtID0g dG9fZ3VkX2RldmljZShjb25uZWN0b3ItPmRldik7CisJc3RydWN0IGd1ZF9jb25uZWN0b3JfZ2V0 X2VkaWRfY3R4IGVkaWRfY3R4ID0geworCQkuZ2Nvbm4gPSBnY29ubiwKKwl9OworCXN0cnVjdCBn dWRfZGlzcGxheV9tb2RlX3JlcSAqcmVxbW9kZXMgPSBOVUxMOworCXVuc2lnbmVkIGludCBpLCBu dW1fbW9kZXMgPSAwOworCXN0cnVjdCBlZGlkICplZGlkID0gTlVMTDsKKwlib29sIGVkaWRfb3Zl cnJpZGU7CisJaW50IGlkeCwgcmV0OworCisJaWYgKCFkcm1fZGV2X2VudGVyKGNvbm5lY3Rvci0+ ZGV2LCAmaWR4KSkKKwkJcmV0dXJuIDA7CisKKwlpZiAoY29ubmVjdG9yLT5mb3JjZSkgeworCQly ZXQgPSBndWRfY29ubmVjdG9yX3N0YXR1c19yZXF1ZXN0KGNvbm5lY3Rvcik7CisJCWlmIChyZXQg PCAwKQorCQkJZ290byBvdXQ7CisJfQorCisJZWRpZCA9IGRybV9kb19nZXRfZWRpZChjb25uZWN0 b3IsIGd1ZF9jb25uZWN0b3JfZ2V0X2VkaWRfYmxvY2ssICZlZGlkX2N0eCk7CisJZWRpZF9vdmVy cmlkZSA9IGVkaWQgJiYgIWVkaWRfY3R4LmJ1ZjsKKwlrZnJlZShlZGlkX2N0eC5idWYpOworCWRy bV9jb25uZWN0b3JfdXBkYXRlX2VkaWRfcHJvcGVydHkoY29ubmVjdG9yLCBlZGlkKTsKKworCWlm ICghZ2Nvbm4tPm51bV9tb2RlcyB8fCBlZGlkX292ZXJyaWRlKSB7CisJCW51bV9tb2RlcyA9IGRy bV9hZGRfZWRpZF9tb2Rlcyhjb25uZWN0b3IsIGVkaWQpOworCQlnb3RvIG91dDsKKwl9CisKKwly ZXFtb2RlcyA9IGttYWxsb2NfYXJyYXkoZ2Nvbm4tPm51bV9tb2Rlcywgc2l6ZW9mKCpyZXFtb2Rl cyksIEdGUF9LRVJORUwpOworCWlmICghcmVxbW9kZXMpCisJCWdvdG8gb3V0OworCisJcmV0ID0g Z3VkX3VzYl9nZXQoZ2RybSwgR1VEX1JFUV9HRVRfQ09OTkVDVE9SX01PREVTLCBjb25uZWN0b3It PmluZGV4LAorCQkJICByZXFtb2RlcywgZ2Nvbm4tPm51bV9tb2RlcyAqIHNpemVvZigqcmVxbW9k ZXMpKTsKKwlpZiAocmV0KQorCQlnb3RvIG91dDsKKworCWZvciAoaSA9IDA7IGkgPCBnY29ubi0+ bnVtX21vZGVzOyBpKyspIHsKKwkJc3RydWN0IGRybV9kaXNwbGF5X21vZGUgKm1vZGU7CisKKwkJ bW9kZSA9IGRybV9tb2RlX2NyZWF0ZShjb25uZWN0b3ItPmRldik7CisJCWlmICghbW9kZSkKKwkJ CWdvdG8gb3V0OworCisJCWd1ZF90b19kaXNwbGF5X21vZGUobW9kZSwgJnJlcW1vZGVzW2ldKTsK KwkJZHJtX21vZGVfcHJvYmVkX2FkZChjb25uZWN0b3IsIG1vZGUpOworCQludW1fbW9kZXMrKzsK Kwl9CitvdXQ6CisJa2ZyZWUocmVxbW9kZXMpOworCWtmcmVlKGVkaWQpOworCWRybV9kZXZfZXhp dChpZHgpOworCisJcmV0dXJuIG51bV9tb2RlczsKK30KKworc3RhdGljIGludCBndWRfY29ubmVj dG9yX2F0b21pY19jaGVjayhzdHJ1Y3QgZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9yLAorCQkJCSAg ICAgIHN0cnVjdCBkcm1fYXRvbWljX3N0YXRlICpzdGF0ZSkKK3sKKwlzdHJ1Y3QgZHJtX2Nvbm5l Y3Rvcl9zdGF0ZSAqbmV3X3N0YXRlOworCXN0cnVjdCBkcm1fY3J0Y19zdGF0ZSAqbmV3X2NydGNf c3RhdGU7CisJc3RydWN0IGRybV9jb25uZWN0b3Jfc3RhdGUgKm9sZF9zdGF0ZTsKKworCW5ld19z dGF0ZSA9IGRybV9hdG9taWNfZ2V0X25ld19jb25uZWN0b3Jfc3RhdGUoc3RhdGUsIGNvbm5lY3Rv cik7CisJaWYgKCFuZXdfc3RhdGUtPmNydGMpCisJCXJldHVybiAwOworCisJb2xkX3N0YXRlID0g ZHJtX2F0b21pY19nZXRfb2xkX2Nvbm5lY3Rvcl9zdGF0ZShzdGF0ZSwgY29ubmVjdG9yKTsKKwlu ZXdfY3J0Y19zdGF0ZSA9IGRybV9hdG9taWNfZ2V0X25ld19jcnRjX3N0YXRlKHN0YXRlLCBuZXdf c3RhdGUtPmNydGMpOworCisJaWYgKG9sZF9zdGF0ZS0+dHYubWFyZ2lucy5sZWZ0ICE9IG5ld19z dGF0ZS0+dHYubWFyZ2lucy5sZWZ0IHx8CisJICAgIG9sZF9zdGF0ZS0+dHYubWFyZ2lucy5yaWdo dCAhPSBuZXdfc3RhdGUtPnR2Lm1hcmdpbnMucmlnaHQgfHwKKwkgICAgb2xkX3N0YXRlLT50di5t YXJnaW5zLnRvcCAhPSBuZXdfc3RhdGUtPnR2Lm1hcmdpbnMudG9wIHx8CisJICAgIG9sZF9zdGF0 ZS0+dHYubWFyZ2lucy5ib3R0b20gIT0gbmV3X3N0YXRlLT50di5tYXJnaW5zLmJvdHRvbSB8fAor CSAgICBvbGRfc3RhdGUtPnR2Lm1vZGUgIT0gbmV3X3N0YXRlLT50di5tb2RlIHx8CisJICAgIG9s ZF9zdGF0ZS0+dHYuYnJpZ2h0bmVzcyAhPSBuZXdfc3RhdGUtPnR2LmJyaWdodG5lc3MgfHwKKwkg ICAgb2xkX3N0YXRlLT50di5jb250cmFzdCAhPSBuZXdfc3RhdGUtPnR2LmNvbnRyYXN0IHx8CisJ ICAgIG9sZF9zdGF0ZS0+dHYuZmxpY2tlcl9yZWR1Y3Rpb24gIT0gbmV3X3N0YXRlLT50di5mbGlj a2VyX3JlZHVjdGlvbiB8fAorCSAgICBvbGRfc3RhdGUtPnR2Lm92ZXJzY2FuICE9IG5ld19zdGF0 ZS0+dHYub3ZlcnNjYW4gfHwKKwkgICAgb2xkX3N0YXRlLT50di5zYXR1cmF0aW9uICE9IG5ld19z dGF0ZS0+dHYuc2F0dXJhdGlvbiB8fAorCSAgICBvbGRfc3RhdGUtPnR2Lmh1ZSAhPSBuZXdfc3Rh dGUtPnR2Lmh1ZSkKKwkJbmV3X2NydGNfc3RhdGUtPmNvbm5lY3RvcnNfY2hhbmdlZCA9IHRydWU7 CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGNvbnN0IHN0cnVjdCBkcm1fY29ubmVjdG9yX2hl bHBlcl9mdW5jcyBndWRfY29ubmVjdG9yX2hlbHBlcl9mdW5jcyA9IHsKKwkuZGV0ZWN0X2N0eCA9 IGd1ZF9jb25uZWN0b3JfZGV0ZWN0LAorCS5nZXRfbW9kZXMgPSBndWRfY29ubmVjdG9yX2dldF9t b2RlcywKKwkuYXRvbWljX2NoZWNrID0gZ3VkX2Nvbm5lY3Rvcl9hdG9taWNfY2hlY2ssCit9Owor CitzdGF0aWMgaW50IGd1ZF9jb25uZWN0b3JfbGF0ZV9yZWdpc3RlcihzdHJ1Y3QgZHJtX2Nvbm5l Y3RvciAqY29ubmVjdG9yKQoreworCXN0cnVjdCBndWRfY29ubmVjdG9yICpnY29ubiA9IHRvX2d1 ZF9jb25uZWN0b3IoY29ubmVjdG9yKTsKKworCWlmIChnY29ubi0+aW5pdGlhbF9icmlnaHRuZXNz IDwgMCkKKwkJcmV0dXJuIDA7CisKKwlyZXR1cm4gZ3VkX2Nvbm5lY3Rvcl9iYWNrbGlnaHRfcmVn aXN0ZXIoZ2Nvbm4pOworfQorCitzdGF0aWMgdm9pZCBndWRfY29ubmVjdG9yX2Vhcmx5X3VucmVn aXN0ZXIoc3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvcikKK3sKKwlzdHJ1Y3QgZ3VkX2Nv bm5lY3RvciAqZ2Nvbm4gPSB0b19ndWRfY29ubmVjdG9yKGNvbm5lY3Rvcik7CisKKwliYWNrbGln aHRfZGV2aWNlX3VucmVnaXN0ZXIoZ2Nvbm4tPmJhY2tsaWdodCk7Cit9CisKK3N0YXRpYyB2b2lk IGd1ZF9jb25uZWN0b3JfZGVzdHJveShzdHJ1Y3QgZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9yKQor eworCXN0cnVjdCBndWRfY29ubmVjdG9yICpnY29ubiA9IHRvX2d1ZF9jb25uZWN0b3IoY29ubmVj dG9yKTsKKworCWRybV9jb25uZWN0b3JfY2xlYW51cChjb25uZWN0b3IpOworCWtmcmVlKGdjb25u LT5wcm9wZXJ0aWVzKTsKKwlrZnJlZShnY29ubik7Cit9CisKK3N0YXRpYyB2b2lkIGd1ZF9jb25u ZWN0b3JfcmVzZXQoc3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvcikKK3sKKwlzdHJ1Y3Qg Z3VkX2Nvbm5lY3RvciAqZ2Nvbm4gPSB0b19ndWRfY29ubmVjdG9yKGNvbm5lY3Rvcik7CisKKwlk cm1fYXRvbWljX2hlbHBlcl9jb25uZWN0b3JfcmVzZXQoY29ubmVjdG9yKTsKKwljb25uZWN0b3It PnN0YXRlLT50diA9IGdjb25uLT5pbml0aWFsX3R2X3N0YXRlOworCS8qIFNldCBtYXJnaW5zIGZy b20gY29tbWFuZCBsaW5lICovCisJZHJtX2F0b21pY19oZWxwZXJfY29ubmVjdG9yX3R2X3Jlc2V0 KGNvbm5lY3Rvcik7CisJaWYgKGdjb25uLT5pbml0aWFsX2JyaWdodG5lc3MgPj0gMCkKKwkJY29u bmVjdG9yLT5zdGF0ZS0+dHYuYnJpZ2h0bmVzcyA9IGdjb25uLT5pbml0aWFsX2JyaWdodG5lc3M7 Cit9CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZHJtX2Nvbm5lY3Rvcl9mdW5jcyBndWRfY29ubmVj dG9yX2Z1bmNzID0geworCS5maWxsX21vZGVzID0gZHJtX2hlbHBlcl9wcm9iZV9zaW5nbGVfY29u bmVjdG9yX21vZGVzLAorCS5sYXRlX3JlZ2lzdGVyID0gZ3VkX2Nvbm5lY3Rvcl9sYXRlX3JlZ2lz dGVyLAorCS5lYXJseV91bnJlZ2lzdGVyID0gZ3VkX2Nvbm5lY3Rvcl9lYXJseV91bnJlZ2lzdGVy LAorCS5kZXN0cm95ID0gZ3VkX2Nvbm5lY3Rvcl9kZXN0cm95LAorCS5yZXNldCA9IGd1ZF9jb25u ZWN0b3JfcmVzZXQsCisJLmF0b21pY19kdXBsaWNhdGVfc3RhdGUgPSBkcm1fYXRvbWljX2hlbHBl cl9jb25uZWN0b3JfZHVwbGljYXRlX3N0YXRlLAorCS5hdG9taWNfZGVzdHJveV9zdGF0ZSA9IGRy bV9hdG9taWNfaGVscGVyX2Nvbm5lY3Rvcl9kZXN0cm95X3N0YXRlLAorfTsKKworLyoKKyAqIFRo ZSB0di5tb2RlIHByb3BlcnR5IGlzIHNoYXJlZCBhbW9uZyB0aGUgY29ubmVjdG9ycyBhbmQgaXRz IGVudW0gbmFtZXMgYXJlCisgKiBkcml2ZXIgc3BlY2lmaWMuIFRoaXMgbWVhbnMgdGhhdCBpZiBt b3JlIHRoYW4gb25lIGNvbm5lY3RvciB1c2VzIHR2Lm1vZGUsCisgKiB0aGUgZW51bSBuYW1lcyBo YXMgdG8gYmUgdGhlIHNhbWUuCisgKi8KK3N0YXRpYyBpbnQgZ3VkX2Nvbm5lY3Rvcl9hZGRfdHZf bW9kZShzdHJ1Y3QgZ3VkX2RldmljZSAqZ2RybSwKKwkJCQkgICAgIHN0cnVjdCBkcm1fY29ubmVj dG9yICpjb25uZWN0b3IsIHU2NCB2YWwpCit7CisJdW5zaWduZWQgaW50IGksIG51bV9tb2RlczsK Kwljb25zdCBjaGFyICoqbW9kZXM7CisJc2l6ZV90IGJ1Zl9sZW47CisJY2hhciAqYnVmOworCWlu dCByZXQ7CisKKwludW1fbW9kZXMgPSB2YWwgPj4gR1VEX0NPTk5FQ1RPUl9UVl9NT0RFX05VTV9T SElGVDsKKworCWlmICghbnVtX21vZGVzKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCWJ1Zl9sZW4g PSBudW1fbW9kZXMgKiBHVURfQ09OTkVDVE9SX1RWX01PREVfTkFNRV9MRU47CisJbW9kZXMgPSBr bWFsbG9jX2FycmF5KG51bV9tb2Rlcywgc2l6ZW9mKCptb2RlcyksIEdGUF9LRVJORUwpOworCWJ1 ZiA9IGttYWxsb2MoYnVmX2xlbiwgR0ZQX0tFUk5FTCk7CisJaWYgKCFtb2RlcyB8fCAhYnVmKSB7 CisJCXJldCA9IC1FTk9NRU07CisJCWdvdG8gZnJlZTsKKwl9CisKKwlyZXQgPSBndWRfdXNiX2dl dChnZHJtLCBHVURfUkVRX0dFVF9DT05ORUNUT1JfVFZfTU9ERV9WQUxVRVMsCisJCQkgIGNvbm5l Y3Rvci0+aW5kZXgsIGJ1ZiwgYnVmX2xlbik7CisJaWYgKHJldCkKKwkJZ290byBmcmVlOworCisJ Zm9yIChpID0gMDsgaSA8IG51bV9tb2RlczsgaSsrKQorCQltb2Rlc1tpXSA9ICZidWZbaSAqIEdV RF9DT05ORUNUT1JfVFZfTU9ERV9OQU1FX0xFTl07CisKKwlyZXQgPSBkcm1fbW9kZV9jcmVhdGVf dHZfcHJvcGVydGllcyhjb25uZWN0b3ItPmRldiwgbnVtX21vZGVzLCBtb2Rlcyk7CitmcmVlOgor CWtmcmVlKG1vZGVzKTsKKwlrZnJlZShidWYpOworCisJcmV0dXJuIHJldDsKK30KKworc3RhdGlj IHN0cnVjdCBkcm1fcHJvcGVydHkgKgorZ3VkX2Nvbm5lY3Rvcl9wcm9wZXJ0eV9sb29rdXAoc3Ry dWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvciwgdTE2IHByb3ApCit7CisJc3RydWN0IGRybV9t b2RlX2NvbmZpZyAqY29uZmlnID0gJmNvbm5lY3Rvci0+ZGV2LT5tb2RlX2NvbmZpZzsKKworCXN3 aXRjaCAocHJvcCkgeworCWNhc2UgR1VEX1BST1BFUlRZX1RWX0xFRlRfTUFSR0lOOgorCQlyZXR1 cm4gY29uZmlnLT50dl9sZWZ0X21hcmdpbl9wcm9wZXJ0eTsKKwljYXNlIEdVRF9QUk9QRVJUWV9U Vl9SSUdIVF9NQVJHSU46CisJCXJldHVybiBjb25maWctPnR2X3JpZ2h0X21hcmdpbl9wcm9wZXJ0 eTsKKwljYXNlIEdVRF9QUk9QRVJUWV9UVl9UT1BfTUFSR0lOOgorCQlyZXR1cm4gY29uZmlnLT50 dl90b3BfbWFyZ2luX3Byb3BlcnR5OworCWNhc2UgR1VEX1BST1BFUlRZX1RWX0JPVFRPTV9NQVJH SU46CisJCXJldHVybiBjb25maWctPnR2X2JvdHRvbV9tYXJnaW5fcHJvcGVydHk7CisJY2FzZSBH VURfUFJPUEVSVFlfVFZfTU9ERToKKwkJcmV0dXJuIGNvbmZpZy0+dHZfbW9kZV9wcm9wZXJ0eTsK KwljYXNlIEdVRF9QUk9QRVJUWV9UVl9CUklHSFRORVNTOgorCQlyZXR1cm4gY29uZmlnLT50dl9i cmlnaHRuZXNzX3Byb3BlcnR5OworCWNhc2UgR1VEX1BST1BFUlRZX1RWX0NPTlRSQVNUOgorCQly ZXR1cm4gY29uZmlnLT50dl9jb250cmFzdF9wcm9wZXJ0eTsKKwljYXNlIEdVRF9QUk9QRVJUWV9U Vl9GTElDS0VSX1JFRFVDVElPTjoKKwkJcmV0dXJuIGNvbmZpZy0+dHZfZmxpY2tlcl9yZWR1Y3Rp b25fcHJvcGVydHk7CisJY2FzZSBHVURfUFJPUEVSVFlfVFZfT1ZFUlNDQU46CisJCXJldHVybiBj b25maWctPnR2X292ZXJzY2FuX3Byb3BlcnR5OworCWNhc2UgR1VEX1BST1BFUlRZX1RWX1NBVFVS QVRJT046CisJCXJldHVybiBjb25maWctPnR2X3NhdHVyYXRpb25fcHJvcGVydHk7CisJY2FzZSBH VURfUFJPUEVSVFlfVFZfSFVFOgorCQlyZXR1cm4gY29uZmlnLT50dl9odWVfcHJvcGVydHk7CisJ ZGVmYXVsdDoKKwkJcmV0dXJuIEVSUl9QVFIoLUVJTlZBTCk7CisJfQorfQorCitzdGF0aWMgdW5z aWduZWQgaW50ICpndWRfY29ubmVjdG9yX3R2X3N0YXRlX3ZhbCh1MTYgcHJvcCwgc3RydWN0IGRy bV90dl9jb25uZWN0b3Jfc3RhdGUgKnN0YXRlKQoreworCXN3aXRjaCAocHJvcCkgeworCWNhc2Ug R1VEX1BST1BFUlRZX1RWX0xFRlRfTUFSR0lOOgorCQlyZXR1cm4gJnN0YXRlLT5tYXJnaW5zLmxl ZnQ7CisJY2FzZSBHVURfUFJPUEVSVFlfVFZfUklHSFRfTUFSR0lOOgorCQlyZXR1cm4gJnN0YXRl LT5tYXJnaW5zLnJpZ2h0OworCWNhc2UgR1VEX1BST1BFUlRZX1RWX1RPUF9NQVJHSU46CisJCXJl dHVybiAmc3RhdGUtPm1hcmdpbnMudG9wOworCWNhc2UgR1VEX1BST1BFUlRZX1RWX0JPVFRPTV9N QVJHSU46CisJCXJldHVybiAmc3RhdGUtPm1hcmdpbnMuYm90dG9tOworCWNhc2UgR1VEX1BST1BF UlRZX1RWX01PREU6CisJCXJldHVybiAmc3RhdGUtPm1vZGU7CisJY2FzZSBHVURfUFJPUEVSVFlf VFZfQlJJR0hUTkVTUzoKKwkJcmV0dXJuICZzdGF0ZS0+YnJpZ2h0bmVzczsKKwljYXNlIEdVRF9Q Uk9QRVJUWV9UVl9DT05UUkFTVDoKKwkJcmV0dXJuICZzdGF0ZS0+Y29udHJhc3Q7CisJY2FzZSBH VURfUFJPUEVSVFlfVFZfRkxJQ0tFUl9SRURVQ1RJT046CisJCXJldHVybiAmc3RhdGUtPmZsaWNr ZXJfcmVkdWN0aW9uOworCWNhc2UgR1VEX1BST1BFUlRZX1RWX09WRVJTQ0FOOgorCQlyZXR1cm4g JnN0YXRlLT5vdmVyc2NhbjsKKwljYXNlIEdVRF9QUk9QRVJUWV9UVl9TQVRVUkFUSU9OOgorCQly ZXR1cm4gJnN0YXRlLT5zYXR1cmF0aW9uOworCWNhc2UgR1VEX1BST1BFUlRZX1RWX0hVRToKKwkJ cmV0dXJuICZzdGF0ZS0+aHVlOworCWRlZmF1bHQ6CisJCXJldHVybiBFUlJfUFRSKC1FSU5WQUwp OworCX0KK30KKworc3RhdGljIGludCBndWRfY29ubmVjdG9yX2FkZF9wcm9wZXJ0aWVzKHN0cnVj dCBndWRfZGV2aWNlICpnZHJtLCBzdHJ1Y3QgZ3VkX2Nvbm5lY3RvciAqZ2Nvbm4sCisJCQkJCXVu c2lnbmVkIGludCBudW1fcHJvcGVydGllcykKK3sKKwlzdHJ1Y3QgZHJtX2RldmljZSAqZHJtID0g Jmdkcm0tPmRybTsKKwlzdHJ1Y3QgZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9yID0gJmdjb25uLT5j b25uZWN0b3I7CisJc3RydWN0IGd1ZF9wcm9wZXJ0eV9yZXEgKnByb3BlcnRpZXM7CisJdW5zaWdu ZWQgaW50IGk7CisJaW50IHJldDsKKworCWdjb25uLT5wcm9wZXJ0aWVzID0ga2NhbGxvYyhudW1f cHJvcGVydGllcywgc2l6ZW9mKCpnY29ubi0+cHJvcGVydGllcyksIEdGUF9LRVJORUwpOworCWlm ICghZ2Nvbm4tPnByb3BlcnRpZXMpCisJCXJldHVybiAtRU5PTUVNOworCisJcHJvcGVydGllcyA9 IGtjYWxsb2MobnVtX3Byb3BlcnRpZXMsIHNpemVvZigqcHJvcGVydGllcyksIEdGUF9LRVJORUwp OworCWlmICghcHJvcGVydGllcykKKwkJcmV0dXJuIC1FTk9NRU07CisKKwlyZXQgPSBndWRfdXNi X2dldChnZHJtLCBHVURfUkVRX0dFVF9DT05ORUNUT1JfUFJPUEVSVElFUywgY29ubmVjdG9yLT5p bmRleCwKKwkJCSAgcHJvcGVydGllcywgbnVtX3Byb3BlcnRpZXMgKiBzaXplb2YoKnByb3BlcnRp ZXMpKTsKKwlpZiAocmV0KQorCQlnb3RvIG91dDsKKworCWZvciAoaSA9IDA7IGkgPCBudW1fcHJv cGVydGllczsgaSsrKSB7CisJCXUxNiBwcm9wID0gbGUxNl90b19jcHUocHJvcGVydGllc1tpXS5w cm9wKTsKKwkJdTY0IHZhbCA9IGxlNjRfdG9fY3B1KHByb3BlcnRpZXNbaV0udmFsKTsKKwkJc3Ry dWN0IGRybV9wcm9wZXJ0eSAqcHJvcGVydHk7CisJCXVuc2lnbmVkIGludCAqc3RhdGVfdmFsOwor CisJCWRybV9kYmcoZHJtLCAicHJvcGVydHk6ICV1ID0gJWxsdSgweCVsbHgpXG4iLCBwcm9wLCB2 YWwsIHZhbCk7CisKKwkJc3dpdGNoIChwcm9wKSB7CisJCWNhc2UgR1VEX1BST1BFUlRZX1RWX0xF RlRfTUFSR0lOOgorCQkJZmFsbHRocm91Z2g7CisJCWNhc2UgR1VEX1BST1BFUlRZX1RWX1JJR0hU X01BUkdJTjoKKwkJCWZhbGx0aHJvdWdoOworCQljYXNlIEdVRF9QUk9QRVJUWV9UVl9UT1BfTUFS R0lOOgorCQkJZmFsbHRocm91Z2g7CisJCWNhc2UgR1VEX1BST1BFUlRZX1RWX0JPVFRPTV9NQVJH SU46CisJCQlyZXQgPSBkcm1fbW9kZV9jcmVhdGVfdHZfbWFyZ2luX3Byb3BlcnRpZXMoZHJtKTsK KwkJCWlmIChyZXQpCisJCQkJZ290byBvdXQ7CisJCQlicmVhazsKKwkJY2FzZSBHVURfUFJPUEVS VFlfVFZfTU9ERToKKwkJCXJldCA9IGd1ZF9jb25uZWN0b3JfYWRkX3R2X21vZGUoZ2RybSwgY29u bmVjdG9yLCB2YWwpOworCQkJaWYgKHJldCkKKwkJCQlnb3RvIG91dDsKKwkJCXZhbCA9IHZhbCAm IChCSVQoR1VEX0NPTk5FQ1RPUl9UVl9NT0RFX05VTV9TSElGVCkgLSAxKTsKKwkJCWJyZWFrOwor CQljYXNlIEdVRF9QUk9QRVJUWV9UVl9CUklHSFRORVNTOgorCQkJZmFsbHRocm91Z2g7CisJCWNh c2UgR1VEX1BST1BFUlRZX1RWX0NPTlRSQVNUOgorCQkJZmFsbHRocm91Z2g7CisJCWNhc2UgR1VE X1BST1BFUlRZX1RWX0ZMSUNLRVJfUkVEVUNUSU9OOgorCQkJZmFsbHRocm91Z2g7CisJCWNhc2Ug R1VEX1BST1BFUlRZX1RWX09WRVJTQ0FOOgorCQkJZmFsbHRocm91Z2g7CisJCWNhc2UgR1VEX1BS T1BFUlRZX1RWX1NBVFVSQVRJT046CisJCQlmYWxsdGhyb3VnaDsKKwkJY2FzZSBHVURfUFJPUEVS VFlfVFZfSFVFOgorCQkJLyogVGhpcyBpcyBhIG5vLW9wIGlmIGFscmVhZHkgYWRkZWQuICovCisJ CQlyZXQgPSBkcm1fbW9kZV9jcmVhdGVfdHZfcHJvcGVydGllcyhkcm0sIDAsIE5VTEwpOworCQkJ aWYgKHJldCkKKwkJCQlnb3RvIG91dDsKKwkJCWJyZWFrOworCQljYXNlIEdVRF9QUk9QRVJUWV9C QUNLTElHSFRfQlJJR0hUTkVTUzoKKwkJCWlmICh2YWwgPiAxMDApIHsKKwkJCQlyZXQgPSAtRUlO VkFMOworCQkJCWdvdG8gb3V0OworCQkJfQorCQkJZ2Nvbm4tPmluaXRpYWxfYnJpZ2h0bmVzcyA9 IHZhbDsKKwkJCWJyZWFrOworCQlkZWZhdWx0OgorCQkJLyogTmV3IG9uZXMgbWlnaHQgc2hvdyB1 cCBpbiBmdXR1cmUgZGV2aWNlcywgc2tpcCB0aG9zZSB3ZSBkb24ndCBrbm93LiAqLworCQkJZHJt X2RiZyhkcm0sICJVbmtub3duIHByb3BlcnR5OiAldVxuIiwgcHJvcCk7CisJCQljb250aW51ZTsK KwkJfQorCisJCWdjb25uLT5wcm9wZXJ0aWVzW2djb25uLT5udW1fcHJvcGVydGllcysrXSA9IHBy b3A7CisKKwkJaWYgKHByb3AgPT0gR1VEX1BST1BFUlRZX0JBQ0tMSUdIVF9CUklHSFRORVNTKQor CQkJY29udGludWU7IC8qIG5vdCBhIERSTSBwcm9wZXJ0eSAqLworCisJCXByb3BlcnR5ID0gZ3Vk X2Nvbm5lY3Rvcl9wcm9wZXJ0eV9sb29rdXAoY29ubmVjdG9yLCBwcm9wKTsKKwkJaWYgKFdBUk5f T04oSVNfRVJSKHByb3BlcnR5KSkpCisJCQljb250aW51ZTsKKworCQlzdGF0ZV92YWwgPSBndWRf Y29ubmVjdG9yX3R2X3N0YXRlX3ZhbChwcm9wLCAmZ2Nvbm4tPmluaXRpYWxfdHZfc3RhdGUpOwor CQlpZiAoV0FSTl9PTihJU19FUlIoc3RhdGVfdmFsKSkpCisJCQljb250aW51ZTsKKworCQkqc3Rh dGVfdmFsID0gdmFsOworCQlkcm1fb2JqZWN0X2F0dGFjaF9wcm9wZXJ0eSgmY29ubmVjdG9yLT5i YXNlLCBwcm9wZXJ0eSwgMCk7CisJfQorb3V0OgorCWtmcmVlKHByb3BlcnRpZXMpOworCisJcmV0 dXJuIHJldDsKK30KKworaW50IGd1ZF9jb25uZWN0b3JfZmlsbF9wcm9wZXJ0aWVzKHN0cnVjdCBk cm1fY29ubmVjdG9yICpjb25uZWN0b3IsCisJCQkJICBzdHJ1Y3QgZHJtX2Nvbm5lY3Rvcl9zdGF0 ZSAqY29ubmVjdG9yX3N0YXRlLAorCQkJCSAgc3RydWN0IGd1ZF9wcm9wZXJ0eV9yZXEgKnByb3Bl cnRpZXMpCit7CisJc3RydWN0IGd1ZF9jb25uZWN0b3IgKmdjb25uOworCXVuc2lnbmVkIGludCBp OworCisJZ2Nvbm4gPSB0b19ndWRfY29ubmVjdG9yKGNvbm5lY3Rvcik7CisKKwkvKiBPbmx5IGlu dGVyZXN0ZWQgaW4gdGhlIGNvdW50PyAqLworCWlmICghY29ubmVjdG9yX3N0YXRlKQorCQlyZXR1 cm4gZ2Nvbm4tPm51bV9wcm9wZXJ0aWVzOworCisJZm9yIChpID0gMDsgaSA8IGdjb25uLT5udW1f cHJvcGVydGllczsgaSsrKSB7CisJCXUxNiBwcm9wID0gZ2Nvbm4tPnByb3BlcnRpZXNbaV07CisJ CXU2NCB2YWw7CisKKwkJaWYgKHByb3AgPT0gR1VEX1BST1BFUlRZX0JBQ0tMSUdIVF9CUklHSFRO RVNTKSB7CisJCQl2YWwgPSBjb25uZWN0b3Jfc3RhdGUtPnR2LmJyaWdodG5lc3M7CisJCX0gZWxz ZSB7CisJCQl1bnNpZ25lZCBpbnQgKnN0YXRlX3ZhbDsKKworCQkJc3RhdGVfdmFsID0gZ3VkX2Nv bm5lY3Rvcl90dl9zdGF0ZV92YWwocHJvcCwgJmNvbm5lY3Rvcl9zdGF0ZS0+dHYpOworCQkJaWYg KFdBUk5fT05fT05DRShJU19FUlIoc3RhdGVfdmFsKSkpCisJCQkJcmV0dXJuIFBUUl9FUlIoc3Rh dGVfdmFsKTsKKworCQkJdmFsID0gKnN0YXRlX3ZhbDsKKwkJfQorCisJCXByb3BlcnRpZXNbaV0u cHJvcCA9IGNwdV90b19sZTE2KHByb3ApOworCQlwcm9wZXJ0aWVzW2ldLnZhbCA9IGNwdV90b19s ZTY0KHZhbCk7CisJfQorCisJcmV0dXJuIGdjb25uLT5udW1fcHJvcGVydGllczsKK30KKworaW50 IGd1ZF9jb25uZWN0b3JfY3JlYXRlKHN0cnVjdCBndWRfZGV2aWNlICpnZHJtLCB1bnNpZ25lZCBp bnQgaW5kZXgpCit7CisJc3RydWN0IGd1ZF9jb25uZWN0b3JfZGVzY3JpcHRvcl9yZXEgZGVzYzsK KwlzdHJ1Y3QgZHJtX2RldmljZSAqZHJtID0gJmdkcm0tPmRybTsKKwlzdHJ1Y3QgZ3VkX2Nvbm5l Y3RvciAqZ2Nvbm47CisJc3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvcjsKKwlzdHJ1Y3Qg ZHJtX2VuY29kZXIgKmVuY29kZXI7CisJaW50IHJldCwgY29ubmVjdG9yX3R5cGU7CisJdTMyIGZs YWdzOworCisJcmV0ID0gZ3VkX3VzYl9nZXQoZ2RybSwgR1VEX1JFUV9HRVRfQ09OTkVDVE9SLCBp bmRleCwgJmRlc2MsIHNpemVvZihkZXNjKSk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKwor CWdjb25uID0ga3phbGxvYyhzaXplb2YoKmdjb25uKSwgR0ZQX0tFUk5FTCk7CisJaWYgKCFnY29u bikKKwkJcmV0dXJuIC1FTk9NRU07CisKKwlnY29ubi0+aW5pdGlhbF9icmlnaHRuZXNzID0gLUVO T0RFVjsKKwlmbGFncyA9IGxlMzJfdG9fY3B1KGRlc2MuZmxhZ3MpOworCWNvbm5lY3RvciA9ICZn Y29ubi0+Y29ubmVjdG9yOworCisJZHJtX2RiZyhkcm0sICJDb25uZWN0b3I6IGluZGV4PSV1IHR5 cGU9JXUgZmxhZ3M9MHgleCBudW1fcHJvcGVydGllcz0ldVxuIiwKKwkJaW5kZXgsIGRlc2MuY29u bmVjdG9yX3R5cGUsIGZsYWdzLCBkZXNjLm51bV9wcm9wZXJ0aWVzKTsKKworCXN3aXRjaCAoZGVz Yy5jb25uZWN0b3JfdHlwZSkgeworCWNhc2UgR1VEX0NPTk5FQ1RPUl9UWVBFX1BBTkVMOgorCQlj b25uZWN0b3JfdHlwZSA9IERSTV9NT0RFX0NPTk5FQ1RPUl9VU0I7CisJCWJyZWFrOworCWNhc2Ug R1VEX0NPTk5FQ1RPUl9UWVBFX1ZHQToKKwkJY29ubmVjdG9yX3R5cGUgPSBEUk1fTU9ERV9DT05O RUNUT1JfVkdBOworCQlicmVhazsKKwljYXNlIEdVRF9DT05ORUNUT1JfVFlQRV9EVkk6CisJCWNv bm5lY3Rvcl90eXBlID0gRFJNX01PREVfQ09OTkVDVE9SX0RWSUQ7CisJCWJyZWFrOworCWNhc2Ug R1VEX0NPTk5FQ1RPUl9UWVBFX0NPTVBPU0lURToKKwkJY29ubmVjdG9yX3R5cGUgPSBEUk1fTU9E RV9DT05ORUNUT1JfQ29tcG9zaXRlOworCQlicmVhazsKKwljYXNlIEdVRF9DT05ORUNUT1JfVFlQ RV9TVklERU86CisJCWNvbm5lY3Rvcl90eXBlID0gRFJNX01PREVfQ09OTkVDVE9SX1NWSURFTzsK KwkJYnJlYWs7CisJY2FzZSBHVURfQ09OTkVDVE9SX1RZUEVfQ09NUE9ORU5UOgorCQljb25uZWN0 b3JfdHlwZSA9IERSTV9NT0RFX0NPTk5FQ1RPUl9Db21wb25lbnQ7CisJCWJyZWFrOworCWNhc2Ug R1VEX0NPTk5FQ1RPUl9UWVBFX0RJU1BMQVlQT1JUOgorCQljb25uZWN0b3JfdHlwZSA9IERSTV9N T0RFX0NPTk5FQ1RPUl9EaXNwbGF5UG9ydDsKKwkJYnJlYWs7CisJY2FzZSBHVURfQ09OTkVDVE9S X1RZUEVfSERNSToKKwkJY29ubmVjdG9yX3R5cGUgPSBEUk1fTU9ERV9DT05ORUNUT1JfSERNSUE7 CisJCWJyZWFrOworCWRlZmF1bHQ6IC8qIGZ1dHVyZSB0eXBlcyAqLworCQljb25uZWN0b3JfdHlw ZSA9IERSTV9NT0RFX0NPTk5FQ1RPUl9VU0I7CisJCWJyZWFrOworCX07CisKKwlkcm1fY29ubmVj dG9yX2hlbHBlcl9hZGQoY29ubmVjdG9yLCAmZ3VkX2Nvbm5lY3Rvcl9oZWxwZXJfZnVuY3MpOwor CXJldCA9IGRybV9jb25uZWN0b3JfaW5pdChkcm0sIGNvbm5lY3RvciwgJmd1ZF9jb25uZWN0b3Jf ZnVuY3MsIGNvbm5lY3Rvcl90eXBlKTsKKwlpZiAocmV0KSB7CisJCWtmcmVlKGNvbm5lY3Rvcik7 CisJCXJldHVybiByZXQ7CisJfQorCisJaWYgKFdBUk5fT04oY29ubmVjdG9yLT5pbmRleCAhPSBp bmRleCkpCisJCXJldHVybiAtRUlOVkFMOworCisJaWYgKGZsYWdzICYgR1VEX0NPTk5FQ1RPUl9G TEFHU19QT0xMX1NUQVRVUykKKwkJY29ubmVjdG9yLT5wb2xsZWQgPSAoRFJNX0NPTk5FQ1RPUl9Q T0xMX0NPTk5FQ1QgfCBEUk1fQ09OTkVDVE9SX1BPTExfRElTQ09OTkVDVCk7CisJaWYgKGZsYWdz ICYgR1VEX0NPTk5FQ1RPUl9GTEFHU19JTlRFUkxBQ0UpCisJCWNvbm5lY3Rvci0+aW50ZXJsYWNl X2FsbG93ZWQgPSB0cnVlOworCWlmIChmbGFncyAmIEdVRF9DT05ORUNUT1JfRkxBR1NfRE9VQkxF U0NBTikKKwkJY29ubmVjdG9yLT5kb3VibGVzY2FuX2FsbG93ZWQgPSB0cnVlOworCisJaWYgKGRl c2MubnVtX3Byb3BlcnRpZXMpIHsKKwkJcmV0ID0gZ3VkX2Nvbm5lY3Rvcl9hZGRfcHJvcGVydGll cyhnZHJtLCBnY29ubiwgZGVzYy5udW1fcHJvcGVydGllcyk7CisJCWlmIChyZXQpIHsKKwkJCWRl dl9lcnIoZHJtLT5kZXYsICJGYWlsZWQgdG8gYWRkIGNvbm5lY3Rvci8ldSBwcm9wZXJ0aWVzXG4i LCBpbmRleCk7CisJCQlyZXR1cm4gcmV0OworCQl9CisJfQorCisJLyogVGhlIGZpcnN0IGNvbm5l Y3RvciBpcyBhdHRhY2hlZCB0byB0aGUgZXhpc3Rpbmcgc2ltcGxlIHBpcGUgZW5jb2RlciAqLwor CWlmICghY29ubmVjdG9yLT5pbmRleCkgeworCQllbmNvZGVyID0gJmdkcm0tPnBpcGUuZW5jb2Rl cjsKKwl9IGVsc2UgeworCQllbmNvZGVyID0gJmdjb25uLT5lbmNvZGVyOworCisJCXJldCA9IGRy bV9zaW1wbGVfZW5jb2Rlcl9pbml0KGRybSwgZW5jb2RlciwgRFJNX01PREVfRU5DT0RFUl9OT05F KTsKKwkJaWYgKHJldCkKKwkJCXJldHVybiByZXQ7CisKKwkJZW5jb2Rlci0+cG9zc2libGVfY3J0 Y3MgPSAxOworCX0KKworCXJldHVybiBkcm1fY29ubmVjdG9yX2F0dGFjaF9lbmNvZGVyKGNvbm5l Y3RvciwgZW5jb2Rlcik7Cit9CmRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vZ3VkL2d1ZF9k cnYuYyBiL2RyaXZlcnMvZ3B1L2RybS9ndWQvZ3VkX2Rydi5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0 CmluZGV4IDAwMDAwMDAwMDAwMC4uNmM1ZTllZWI4Y2RjCi0tLSAvZGV2L251bGwKKysrIGIvZHJp dmVycy9ncHUvZHJtL2d1ZC9ndWRfZHJ2LmMKQEAgLTAsMCArMSw2MjAgQEAKKy8vIFNQRFgtTGlj ZW5zZS1JZGVudGlmaWVyOiBNSVQKKy8qCisgKiBDb3B5cmlnaHQgMjAyMCBOb3JhbGYgVHLDuG5u ZXMKKyAqLworCisjaW5jbHVkZSA8bGludXgvZG1hLWJ1Zi5oPgorI2luY2x1ZGUgPGxpbnV4L2x6 NC5oPgorI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgorI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3Jt X2RldmljZS5oPgorI2luY2x1ZGUgPGxpbnV4L3N0cmluZ19oZWxwZXJzLmg+CisjaW5jbHVkZSA8 bGludXgvdXNiLmg+CisjaW5jbHVkZSA8bGludXgvdm1hbGxvYy5oPgorI2luY2x1ZGUgPGxpbnV4 L3dvcmtxdWV1ZS5oPgorCisjaW5jbHVkZSA8ZHJtL2RybV9hdG9taWNfaGVscGVyLmg+CisjaW5j bHVkZSA8ZHJtL2RybV9kYW1hZ2VfaGVscGVyLmg+CisjaW5jbHVkZSA8ZHJtL2RybV9kZWJ1Z2Zz Lmg+CisjaW5jbHVkZSA8ZHJtL2RybV9kcnYuaD4KKyNpbmNsdWRlIDxkcm0vZHJtX2ZiX2hlbHBl ci5oPgorI2luY2x1ZGUgPGRybS9kcm1fZm91cmNjLmg+CisjaW5jbHVkZSA8ZHJtL2RybV9nZW1f c2htZW1faGVscGVyLmg+CisjaW5jbHVkZSA8ZHJtL2RybV9nZW1fZnJhbWVidWZmZXJfaGVscGVy Lmg+CisjaW5jbHVkZSA8ZHJtL2RybV9tYW5hZ2VkLmg+CisjaW5jbHVkZSA8ZHJtL2RybV9wcmlu dC5oPgorI2luY2x1ZGUgPGRybS9kcm1fcHJvYmVfaGVscGVyLmg+CisjaW5jbHVkZSA8ZHJtL2Ry bV9zaW1wbGVfa21zX2hlbHBlci5oPgorI2luY2x1ZGUgPGRybS9ndWQuaD4KKworI2luY2x1ZGUg Imd1ZF9pbnRlcm5hbC5oIgorCisvKiBPbmx5IHVzZWQgaW50ZXJuYWxseSAqLworc3RhdGljIGNv bnN0IHN0cnVjdCBkcm1fZm9ybWF0X2luZm8gZ3VkX2RybV9mb3JtYXRfcjEgPSB7CisJLmZvcm1h dCA9IEdVRF9EUk1fRk9STUFUX1IxLAorCS5udW1fcGxhbmVzID0gMSwKKwkuY2hhcl9wZXJfYmxv Y2sgPSB7IDEsIDAsIDAgfSwKKwkuYmxvY2tfdyA9IHsgOCwgMCwgMCB9LAorCS5ibG9ja19oID0g eyAxLCAwLCAwIH0sCisJLmhzdWIgPSAxLAorCS52c3ViID0gMSwKK307CisKK3N0YXRpYyBpbnQg Z3VkX3VzYl9jb250cm9sX21zZyhzdHJ1Y3QgdXNiX2RldmljZSAqdXNiLCB1OCBpZm51bSwgYm9v bCBpbiwKKwkJCSAgICAgICB1OCByZXF1ZXN0LCB1MTYgdmFsdWUsIHZvaWQgKmJ1Ziwgc2l6ZV90 IGxlbikKK3sKKwl1OCByZXF1ZXN0dHlwZSA9IFVTQl9UWVBFX1ZFTkRPUiB8IFVTQl9SRUNJUF9J TlRFUkZBQ0U7CisJdW5zaWduZWQgaW50IHBpcGU7CisJaW50IHJldDsKKworCWlmIChpbikgewor CQlwaXBlID0gdXNiX3JjdmN0cmxwaXBlKHVzYiwgMCk7CisJCXJlcXVlc3R0eXBlIHw9IFVTQl9E SVJfSU47CisJfSBlbHNlIHsKKwkJcGlwZSA9IHVzYl9zbmRjdHJscGlwZSh1c2IsIDApOworCQly ZXF1ZXN0dHlwZSB8PSBVU0JfRElSX09VVDsKKwl9CisKKwlyZXQgPSB1c2JfY29udHJvbF9tc2co dXNiLCBwaXBlLCByZXF1ZXN0LCByZXF1ZXN0dHlwZSwgdmFsdWUsCisJCQkgICAgICBpZm51bSwg YnVmLCBsZW4sIFVTQl9DVFJMX0dFVF9USU1FT1VUKTsKKwlpZiAocmV0IDwgMCkKKwkJcmV0dXJu IHJldDsKKwlpZiAocmV0ICE9IGxlbikKKwkJcmV0dXJuIC1FSU87CisKKwlyZXR1cm4gMDsKK30K Kworc3RhdGljIGludCBndWRfZ2V0X2Rpc3BsYXlfZGVzY3JpcHRvcihzdHJ1Y3QgdXNiX2ludGVy ZmFjZSAqaW50ZXJmYWNlLAorCQkJCSAgICAgIHN0cnVjdCBndWRfZGlzcGxheV9kZXNjcmlwdG9y X3JlcSAqZGVzYykKK3sKKwl1OCBpZm51bSA9IGludGVyZmFjZS0+Y3VyX2FsdHNldHRpbmctPmRl c2MuYkludGVyZmFjZU51bWJlcjsKKwlzdHJ1Y3QgdXNiX2RldmljZSAqdXNiID0gaW50ZXJmYWNl X3RvX3VzYmRldihpbnRlcmZhY2UpOworCXZvaWQgKmJ1ZjsKKwlpbnQgcmV0OworCisJYnVmID0g a21hbGxvYyhzaXplb2YoKmRlc2MpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIWJ1ZikKKwkJcmV0dXJu IC1FTk9NRU07CisKKwlyZXQgPSBndWRfdXNiX2NvbnRyb2xfbXNnKHVzYiwgaWZudW0sIHRydWUs IEdVRF9SRVFfR0VUX0RFU0NSSVBUT1IsIDAsIGJ1Ziwgc2l6ZW9mKCpkZXNjKSk7CisJbWVtY3B5 KGRlc2MsIGJ1Ziwgc2l6ZW9mKCpkZXNjKSk7CisJa2ZyZWUoYnVmKTsKKwlpZiAocmV0KQorCQly ZXR1cm4gcmV0OworCisJaWYgKGRlc2MtPm1hZ2ljICE9IEdVRF9ESVNQTEFZX01BR0lDKQorCQly ZXR1cm4gLUVOT0RBVEE7CisKKwlEUk1fREVWX0RFQlVHX0RSSVZFUigmaW50ZXJmYWNlLT5kZXYs CisJCQkgICAgICJ2ZXJzaW9uPSV1IGZsYWdzPTB4JXggY29tcHJlc3Npb249MHgleCBudW1fZm9y bWF0cz0ldSBudW1fY29ubmVjdG9ycz0ldSBtYXhfYnVmZmVyX3NpemU9JXVcbiIsCisJCQkgICAg IGRlc2MtPnZlcnNpb24sIGxlMzJfdG9fY3B1KGRlc2MtPmZsYWdzKSwgZGVzYy0+Y29tcHJlc3Np b24sCisJCQkgICAgIGRlc2MtPm51bV9mb3JtYXRzLCBkZXNjLT5udW1fY29ubmVjdG9ycywKKwkJ CSAgICAgbGUzMl90b19jcHUoZGVzYy0+bWF4X2J1ZmZlcl9zaXplKSk7CisKKwlpZiAoIWRlc2Mt PnZlcnNpb24gfHwgIWRlc2MtPm51bV9mb3JtYXRzIHx8ICFkZXNjLT5udW1fY29ubmVjdG9ycyB8 fAorCSAgICAhZGVzYy0+bWF4X3dpZHRoIHx8ICFkZXNjLT5tYXhfaGVpZ2h0IHx8CisJICAgIGxl MzJfdG9fY3B1KGRlc2MtPm1pbl93aWR0aCkgPiBsZTMyX3RvX2NwdShkZXNjLT5tYXhfd2lkdGgp IHx8CisJICAgIGxlMzJfdG9fY3B1KGRlc2MtPm1pbl9oZWlnaHQpID4gbGUzMl90b19jcHUoZGVz Yy0+bWF4X2hlaWdodCkpCisJCXJldHVybiAtRUlOVkFMOworCisJcmV0dXJuIDA7Cit9CisKK3N0 YXRpYyBpbnQgZ3VkX3VzYl9nZXRfc3RhdHVzKHN0cnVjdCB1c2JfZGV2aWNlICp1c2IsIHU4IGlm bnVtLCB1OCAqc3RhdHVzKQoreworCXU4ICpidWY7CisJaW50IHJldDsKKworCWJ1ZiA9IGttYWxs b2Moc2l6ZW9mKCpidWYpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIWJ1ZikKKwkJcmV0dXJuIC1FTk9N RU07CisKKwlyZXQgPSBndWRfdXNiX2NvbnRyb2xfbXNnKHVzYiwgaWZudW0sIHRydWUsIEdVRF9S RVFfR0VUX1NUQVRVUywgMCwgYnVmLCBzaXplb2YoKmJ1ZikpOworCSpzdGF0dXMgPSAqYnVmOwor CWtmcmVlKGJ1Zik7CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW50IGd1ZF9zdGF0dXNf dG9fZXJybm8odTggc3RhdHVzKQoreworCXN3aXRjaCAoc3RhdHVzKSB7CisJY2FzZSBHVURfU1RB VFVTX09LOgorCQlyZXR1cm4gMDsKKwljYXNlIEdVRF9TVEFUVVNfQlVTWToKKwkJcmV0dXJuIC1F QlVTWTsKKwljYXNlIEdVRF9TVEFUVVNfUkVRVUVTVF9OT1RfU1VQUE9SVEVEOgorCQlyZXR1cm4g LUVPUE5PVFNVUFA7CisJY2FzZSBHVURfU1RBVFVTX1BST1RPQ09MX0VSUk9SOgorCQlyZXR1cm4g LUVQUk9UTzsKKwljYXNlIEdVRF9TVEFUVVNfSU5WQUxJRF9QQVJBTUVURVI6CisJCXJldHVybiAt RUlOVkFMOworCWNhc2UgR1VEX1NUQVRVU19FUlJPUjoKKwkJcmV0dXJuIC1FUkVNT1RFSU87CisJ ZGVmYXVsdDoKKwkJcmV0dXJuIC1FUkVNT1RFSU87CisJfQorfQorCitzdGF0aWMgaW50IGd1ZF91 c2JfdHJhbnNmZXIoc3RydWN0IGd1ZF9kZXZpY2UgKmdkcm0sIGJvb2wgaW4sIHU4IHJlcXVlc3Qs IHUxNiBpbmRleCwKKwkJCSAgICB2b2lkICpidWYsIHNpemVfdCBsZW4pCit7CisJc3RydWN0IHVz Yl9kZXZpY2UgKnVzYiA9IGd1ZF90b191c2JfZGV2aWNlKGdkcm0pOworCXZvaWQgKnRyYnVmID0g TlVMTDsKKwlpbnQgaWR4LCByZXQ7CisKKwlkcm1fZGJnKCZnZHJtLT5kcm0sICIlczogcmVxdWVz dD0weCV4IGluZGV4PSV1IGxlbj0lenVcbiIsCisJCWluID8gImdldCIgOiAic2V0IiwgcmVxdWVz dCwgaW5kZXgsIGxlbik7CisKKwlpZiAoIWRybV9kZXZfZW50ZXIoJmdkcm0tPmRybSwgJmlkeCkp CisJCXJldHVybiAtRU5PREVWOworCisJbXV0ZXhfbG9jaygmZ2RybS0+Y3RybF9sb2NrKTsKKwor CWlmIChidWYpIHsKKwkJaWYgKGluKQorCQkJdHJidWYgPSBrbWFsbG9jKGxlbiwgR0ZQX0tFUk5F TCk7CisJCWVsc2UKKwkJCXRyYnVmID0ga21lbWR1cChidWYsIGxlbiwgR0ZQX0tFUk5FTCk7CisJ CWlmICghdHJidWYpIHsKKwkJCXJldCA9IC1FTk9NRU07CisJCQlnb3RvIHVubG9jazsKKwkJfQor CX0KKworCXJldCA9IGd1ZF91c2JfY29udHJvbF9tc2codXNiLCBnZHJtLT5pZm51bSwgaW4sIHJl cXVlc3QsIGluZGV4LCB0cmJ1ZiwgbGVuKTsKKwlpZiAocmV0ID09IC1FUElQRSB8fCAoIXJldCAm JiAhaW4gJiYgKGdkcm0tPmZsYWdzICYgR1VEX0RJU1BMQVlfRkxBR19TVEFUVVNfT05fU0VUKSkp IHsKKwkJYm9vbCBlcnJvciA9IHJldDsKKwkJdTggc3RhdHVzOworCisJCXJldCA9IGd1ZF91c2Jf Z2V0X3N0YXR1cyh1c2IsIGdkcm0tPmlmbnVtLCAmc3RhdHVzKTsKKwkJaWYgKCFyZXQpIHsKKwkJ CWlmIChlcnJvciAmJiBzdGF0dXMgPT0gR1VEX1NUQVRVU19PSykgeworCQkJCWRldl9lcnJfb25j ZShnZHJtLT5kcm0uZGV2LAorCQkJCQkgICAgICJVbmV4cGVjdGVkIHN0YXR1cyBPSyBmb3IgZmFp bGVkIHRyYW5zZmVyXG4iKTsKKwkJCQlyZXQgPSAtRVBJUEU7CisJCQl9IGVsc2UgeworCQkJCXJl dCA9IGd1ZF9zdGF0dXNfdG9fZXJybm8oc3RhdHVzKTsKKwkJCX0KKwkJfQorCX0KKworCWlmICgh cmV0ICYmIGluICYmIGJ1ZikKKwkJbWVtY3B5KGJ1ZiwgdHJidWYsIGxlbik7CisKKwlpZiAocmV0 KSB7CisJCWRybV9kYmcoJmdkcm0tPmRybSwgInJldD0lZFxuIiwgcmV0KTsKKwkJZ2RybS0+c3Rh dHNfbnVtX2Vycm9ycysrOworCX0KKworCWtmcmVlKHRyYnVmKTsKK3VubG9jazoKKwltdXRleF91 bmxvY2soJmdkcm0tPmN0cmxfbG9jayk7CisJZHJtX2Rldl9leGl0KGlkeCk7CisKKwlyZXR1cm4g cmV0OworfQorCitpbnQgZ3VkX3VzYl9nZXQoc3RydWN0IGd1ZF9kZXZpY2UgKmdkcm0sIHU4IHJl cXVlc3QsIHUxNiBpbmRleCwgdm9pZCAqYnVmLCBzaXplX3QgbGVuKQoreworCXJldHVybiBndWRf dXNiX3RyYW5zZmVyKGdkcm0sIHRydWUsIHJlcXVlc3QsIGluZGV4LCBidWYsIGxlbik7Cit9CisK K2ludCBndWRfdXNiX3NldChzdHJ1Y3QgZ3VkX2RldmljZSAqZ2RybSwgdTggcmVxdWVzdCwgdTE2 IGluZGV4LCB2b2lkICpidWYsIHNpemVfdCBsZW4pCit7CisJcmV0dXJuIGd1ZF91c2JfdHJhbnNm ZXIoZ2RybSwgZmFsc2UsIHJlcXVlc3QsIGluZGV4LCBidWYsIGxlbik7Cit9CisKK2ludCBndWRf dXNiX3dyaXRlOChzdHJ1Y3QgZ3VkX2RldmljZSAqZ2RybSwgdTggcmVxdWVzdCwgdTggdmFsKQor eworCXJldHVybiBndWRfdXNiX3NldChnZHJtLCByZXF1ZXN0LCAwLCAmdmFsLCBzaXplb2YodmFs KSk7Cit9CisKK3N0YXRpYyBpbnQgZ3VkX3NldF92ZXJzaW9uKHN0cnVjdCB1c2JfZGV2aWNlICp1 c2IsIHU4IGlmbnVtLCB1MzIgZmxhZ3MsIHU4IHZlcnNpb24pCit7CisJdTggKmJ1ZjsKKwlpbnQg cmV0OworCisJYnVmID0ga21hbGxvYyhzaXplb2YoKmJ1ZiksIEdGUF9LRVJORUwpOworCWlmICgh YnVmKQorCQlyZXR1cm4gLUVOT01FTTsKKworCSpidWYgPSB2ZXJzaW9uOworCXJldCA9IGd1ZF91 c2JfY29udHJvbF9tc2codXNiLCBpZm51bSwgZmFsc2UsIEdVRF9SRVFfU0VUX1ZFUlNJT04sIDAs IGJ1Ziwgc2l6ZW9mKCpidWYpKTsKKwlrZnJlZShidWYpOworCWlmIChyZXQgPT0gLUVQSVBFKQor CQlyZXR1cm4gLUVQUk9UT05PU1VQUE9SVDsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJ aWYgKGZsYWdzICYgR1VEX0RJU1BMQVlfRkxBR19TVEFUVVNfT05fU0VUKSB7CisJCXU4IHN0YXR1 czsKKworCQlyZXQgPSBndWRfdXNiX2dldF9zdGF0dXModXNiLCBpZm51bSwgJnN0YXR1cyk7CisJ CWlmICghcmV0ICYmIHN0YXR1cyAhPSBHVURfU1RBVFVTX09LKQorCQkJcmV0ID0gLUVQUk9UT05P U1VQUE9SVDsKKwl9CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW50IGd1ZF9nZXRfcHJv cGVydGllcyhzdHJ1Y3QgZ3VkX2RldmljZSAqZ2RybSwgdW5zaWduZWQgaW50IG51bV9wcm9wZXJ0 aWVzKQoreworCXN0cnVjdCBndWRfcHJvcGVydHlfcmVxICpwcm9wZXJ0aWVzOworCXVuc2lnbmVk IGludCBpOworCWludCByZXQ7CisKKwlpZiAoIW51bV9wcm9wZXJ0aWVzKQorCQlyZXR1cm4gMDsK KworCWdkcm0tPnByb3BlcnRpZXMgPSBkcm1tX2tjYWxsb2MoJmdkcm0tPmRybSwgbnVtX3Byb3Bl cnRpZXMsIHNpemVvZigqZ2RybS0+cHJvcGVydGllcyksCisJCQkJCUdGUF9LRVJORUwpOworCWlm ICghZ2RybS0+cHJvcGVydGllcykKKwkJcmV0dXJuIC1FTk9NRU07CisKKwlwcm9wZXJ0aWVzID0g a2NhbGxvYyhudW1fcHJvcGVydGllcywgc2l6ZW9mKCpwcm9wZXJ0aWVzKSwgR0ZQX0tFUk5FTCk7 CisJaWYgKCFwcm9wZXJ0aWVzKQorCQlyZXR1cm4gLUVOT01FTTsKKworCXJldCA9IGd1ZF91c2Jf Z2V0KGdkcm0sIEdVRF9SRVFfR0VUX1BST1BFUlRJRVMsIDAsCisJCQkgIHByb3BlcnRpZXMsIG51 bV9wcm9wZXJ0aWVzICogc2l6ZW9mKCpwcm9wZXJ0aWVzKSk7CisJaWYgKHJldCkKKwkJZ290byBv dXQ7CisKKwlmb3IgKGkgPSAwOyBpIDwgbnVtX3Byb3BlcnRpZXM7IGkrKykgeworCQl1MTYgcHJv cCA9IGxlMTZfdG9fY3B1KHByb3BlcnRpZXNbaV0ucHJvcCk7CisJCXU2NCB2YWwgPSBsZTY0X3Rv X2NwdShwcm9wZXJ0aWVzW2ldLnZhbCk7CisKKwkJc3dpdGNoIChwcm9wKSB7CisJCWNhc2UgR1VE X1BST1BFUlRZX1JPVEFUSU9OOgorCQkJLyoKKwkJCSAqIERSTSBVQVBJIG1hdGNoZXMgdGhlIHBy b3RvY29sIHNvIHVzZSB0aGUgdmFsdWUgZGlyZWN0bHksCisJCQkgKiBidXQgbWFzayBvdXQgYW55 IGFkZGl0aW9ucyBvbiBmdXR1cmUgZGV2aWNlcy4KKwkJCSAqLworCQkJdmFsICY9IEdVRF9ST1RB VElPTl9NQVNLOworCQkJcmV0ID0gZHJtX3BsYW5lX2NyZWF0ZV9yb3RhdGlvbl9wcm9wZXJ0eSgm Z2RybS0+cGlwZS5wbGFuZSwKKwkJCQkJCQkJIERSTV9NT0RFX1JPVEFURV8wLCB2YWwpOworCQkJ YnJlYWs7CisJCWRlZmF1bHQ6CisJCQkvKiBOZXcgb25lcyBtaWdodCBzaG93IHVwIGluIGZ1dHVy ZSBkZXZpY2VzLCBza2lwIHRob3NlIHdlIGRvbid0IGtub3cuICovCisJCQlkcm1fZGJnKCZnZHJt LT5kcm0sICJVbmtub3duIHByb3BlcnR5OiAldVxuIiwgcHJvcCk7CisJCQljb250aW51ZTsKKwkJ fQorCisJCWlmIChyZXQpCisJCQlnb3RvIG91dDsKKworCQlnZHJtLT5wcm9wZXJ0aWVzW2dkcm0t Pm51bV9wcm9wZXJ0aWVzKytdID0gcHJvcDsKKwl9CitvdXQ6CisJa2ZyZWUocHJvcGVydGllcyk7 CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW50IGd1ZF9zdGF0c19kZWJ1Z2ZzKHN0cnVj dCBzZXFfZmlsZSAqbSwgdm9pZCAqZGF0YSkKK3sKKwlzdHJ1Y3QgZHJtX2luZm9fbm9kZSAqbm9k ZSA9IG0tPnByaXZhdGU7CisJc3RydWN0IGd1ZF9kZXZpY2UgKmdkcm0gPSB0b19ndWRfZGV2aWNl KG5vZGUtPm1pbm9yLT5kZXYpOworCWNoYXIgYnVmWzEwXTsKKworCXN0cmluZ19nZXRfc2l6ZShn ZHJtLT5idWxrX2xlbiwgMSwgU1RSSU5HX1VOSVRTXzIsIGJ1Ziwgc2l6ZW9mKGJ1ZikpOworCXNl cV9wcmludGYobSwgIk1heCBidWZmZXIgc2l6ZTogJXNcbiIsIGJ1Zik7CisJc2VxX3ByaW50Ziht LCAiTnVtYmVyIG9mIGVycm9yczogICV1XG4iLCBnZHJtLT5zdGF0c19udW1fZXJyb3JzKTsKKwor CXNlcV9wdXRzKG0sICJDb21wcmVzc2lvbjogICAgICAiKTsKKwlpZiAoZ2RybS0+Y29tcHJlc3Np b24gJiBHVURfQ09NUFJFU1NJT05fTFo0KQorCQlzZXFfcHV0cyhtLCAiIGx6NCIpOworCXNlcV9w dXRzKG0sICJcbiIpOworCisJaWYgKGdkcm0tPmNvbXByZXNzaW9uKSB7CisJCXU2NCByZW1haW5k ZXI7CisJCXU2NCByYXRpbyA9IGRpdjY0X3U2NF9yZW0oZ2RybS0+c3RhdHNfbGVuZ3RoLCBnZHJt LT5zdGF0c19hY3R1YWxfbGVuZ3RoLAorCQkJCQkgICZyZW1haW5kZXIpOworCQl1NjQgcmF0aW9f ZnJhYyA9IGRpdjY0X3U2NChyZW1haW5kZXIgKiAxMCwgZ2RybS0+c3RhdHNfYWN0dWFsX2xlbmd0 aCk7CisKKwkJc2VxX3ByaW50ZihtLCAiQ29tcHJlc3Npb24gcmF0aW86ICVsbHUuJWxsdVxuIiwg cmF0aW8sIHJhdGlvX2ZyYWMpOworCX0KKworCXJldHVybiAwOworfQorCitzdGF0aWMgY29uc3Qg c3RydWN0IGRybV9pbmZvX2xpc3QgZ3VkX2RlYnVnZnNfbGlzdFtdID0geworCXsgInN0YXRzIiwg Z3VkX3N0YXRzX2RlYnVnZnMsIDAsIE5VTEwgfSwKK307CisKK3N0YXRpYyB2b2lkIGd1ZF9kZWJ1 Z2ZzX2luaXQoc3RydWN0IGRybV9taW5vciAqbWlub3IpCit7CisJZHJtX2RlYnVnZnNfY3JlYXRl X2ZpbGVzKGd1ZF9kZWJ1Z2ZzX2xpc3QsIEFSUkFZX1NJWkUoZ3VkX2RlYnVnZnNfbGlzdCksCisJ CQkJIG1pbm9yLT5kZWJ1Z2ZzX3Jvb3QsIG1pbm9yKTsKK30KKworc3RhdGljIGNvbnN0IHN0cnVj dCBkcm1fc2ltcGxlX2Rpc3BsYXlfcGlwZV9mdW5jcyBndWRfcGlwZV9mdW5jcyA9IHsKKwkuY2hl Y2sgICAgICA9IGd1ZF9waXBlX2NoZWNrLAorCS51cGRhdGUJICAgID0gZ3VkX3BpcGVfdXBkYXRl LAorCS5wcmVwYXJlX2ZiID0gZHJtX2dlbV9mYl9zaW1wbGVfZGlzcGxheV9waXBlX3ByZXBhcmVf ZmIsCit9OworCitzdGF0aWMgY29uc3Qgc3RydWN0IGRybV9tb2RlX2NvbmZpZ19mdW5jcyBndWRf bW9kZV9jb25maWdfZnVuY3MgPSB7CisJLmZiX2NyZWF0ZSA9IGRybV9nZW1fZmJfY3JlYXRlX3dp dGhfZGlydHksCisJLmF0b21pY19jaGVjayA9IGRybV9hdG9taWNfaGVscGVyX2NoZWNrLAorCS5h dG9taWNfY29tbWl0ID0gZHJtX2F0b21pY19oZWxwZXJfY29tbWl0LAorfTsKKworc3RhdGljIGNv bnN0IHU2NCBndWRfcGlwZV9tb2RpZmllcnNbXSA9IHsKKwlEUk1fRk9STUFUX01PRF9MSU5FQVIs CisJRFJNX0ZPUk1BVF9NT0RfSU5WQUxJRAorfTsKKworREVGSU5FX0RSTV9HRU1fRk9QUyhndWRf Zm9wcyk7CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZHJtX2RyaXZlciBndWRfZHJtX2RyaXZlciA9 IHsKKwkuZHJpdmVyX2ZlYXR1cmVzCT0gRFJJVkVSX01PREVTRVQgfCBEUklWRVJfR0VNIHwgRFJJ VkVSX0FUT01JQywKKwkuZm9wcwkJCT0gJmd1ZF9mb3BzLAorCURSTV9HRU1fU0hNRU1fRFJJVkVS X09QUywKKwkuZGVidWdmc19pbml0CQk9IGd1ZF9kZWJ1Z2ZzX2luaXQsCisKKwkubmFtZQkJCT0g Imd1ZCIsCisJLmRlc2MJCQk9ICJHZW5lcmljIFVTQiBEaXNwbGF5IiwKKwkuZGF0ZQkJCT0gIjIw MjAwNDIyIiwKKwkubWFqb3IJCQk9IDEsCisJLm1pbm9yCQkJPSAwLAorfTsKKworc3RhdGljIHZv aWQgZ3VkX2ZyZWVfYnVmZmVyc19hbmRfbXV0ZXgoc3RydWN0IGRybV9kZXZpY2UgKmRybSwgdm9p ZCAqdW51c2VkKQoreworCXN0cnVjdCBndWRfZGV2aWNlICpnZHJtID0gdG9fZ3VkX2RldmljZShk cm0pOworCisJdmZyZWUoZ2RybS0+Y29tcHJlc3NfYnVmKTsKKwlrZnJlZShnZHJtLT5idWxrX2J1 Zik7CisJbXV0ZXhfZGVzdHJveSgmZ2RybS0+Y3RybF9sb2NrKTsKKwltdXRleF9kZXN0cm95KCZn ZHJtLT5kYW1hZ2VfbG9jayk7Cit9CisKK3N0YXRpYyBpbnQgZ3VkX3Byb2JlKHN0cnVjdCB1c2Jf aW50ZXJmYWNlICppbnRlcmZhY2UsIGNvbnN0IHN0cnVjdCB1c2JfZGV2aWNlX2lkICppZCkKK3sK Kwl1OCBpZm51bSA9IGludGVyZmFjZS0+Y3VyX2FsdHNldHRpbmctPmRlc2MuYkludGVyZmFjZU51 bWJlcjsKKwlzdHJ1Y3QgdXNiX2RldmljZSAqdXNiID0gaW50ZXJmYWNlX3RvX3VzYmRldihpbnRl cmZhY2UpOworCXN0cnVjdCBkZXZpY2UgKmRldiA9ICZpbnRlcmZhY2UtPmRldjsKKwljb25zdCBz dHJ1Y3QgZHJtX2Zvcm1hdF9pbmZvICp4cmdiODg4OF9lbXVsYXRpb25fZm9ybWF0ID0gTlVMTDsK Kwlib29sIHJnYjU2NV9zdXBwb3J0ZWQgPSBmYWxzZSwgeHJnYjg4ODhfc3VwcG9ydGVkID0gZmFs c2U7CisJc3RydWN0IHVzYl9lbmRwb2ludF9kZXNjcmlwdG9yICpidWxrX291dDsKKwlzdHJ1Y3Qg Z3VkX2Rpc3BsYXlfZGVzY3JpcHRvcl9yZXEgZGVzYzsKKwl1bnNpZ25lZCBpbnQgbnVtX2Zvcm1h dHMgPSAwOworCXN0cnVjdCBndWRfZGV2aWNlICpnZHJtOworCXNpemVfdCBtYXhfYnVmZmVyX3Np emUgPSAwOworCXN0cnVjdCBkcm1fZGV2aWNlICpkcm07CisJdTggKmZvcm1hdHNfZGV2OworCXUz MiAqZm9ybWF0czsKKwlpbnQgcmV0LCBpOworCisJcmV0ID0gdXNiX2ZpbmRfYnVsa19vdXRfZW5k cG9pbnQoaW50ZXJmYWNlLT5jdXJfYWx0c2V0dGluZywgJmJ1bGtfb3V0KTsKKwlpZiAocmV0KQor CQlyZXR1cm4gcmV0OworCisJcmV0ID0gZ3VkX2dldF9kaXNwbGF5X2Rlc2NyaXB0b3IoaW50ZXJm YWNlLCAmZGVzYyk7CisJaWYgKHJldCkgeworCQlEUk1fREVWX0RFQlVHX0RSSVZFUihkZXYsICJO b3QgYSBkaXNwbGF5IGludGVyZmFjZTogcmV0PSVkXG4iLCByZXQpOworCQlyZXR1cm4gLUVOT0RF VjsKKwl9CisKKwlpZiAoZGVzYy52ZXJzaW9uID4gMSkgeworCQlyZXQgPSBndWRfc2V0X3ZlcnNp b24odXNiLCBpZm51bSwgbGUzMl90b19jcHUoZGVzYy5mbGFncyksIDEpOworCQlpZiAocmV0KSB7 CisJCQlpZiAocmV0ID09IC1FUFJPVE9OT1NVUFBPUlQpCisJCQkJZGV2X2VycihkZXYsICJQcm90 b2NvbCB2ZXJzaW9uICV1IGlzIG5vdCBzdXBwb3J0ZWRcbiIsCisJCQkJCWRlc2MudmVyc2lvbik7 CisJCQlyZXR1cm4gcmV0OworCQl9CisJfQorCisJZ2RybSA9IGRldm1fZHJtX2Rldl9hbGxvYyhk ZXYsICZndWRfZHJtX2RyaXZlciwgc3RydWN0IGd1ZF9kZXZpY2UsIGRybSk7CisJaWYgKElTX0VS UihnZHJtKSkKKwkJcmV0dXJuIFBUUl9FUlIoZ2RybSk7CisKKwlkcm0gPSAmZ2RybS0+ZHJtOwor CWRybS0+bW9kZV9jb25maWcuZnVuY3MgPSAmZ3VkX21vZGVfY29uZmlnX2Z1bmNzOworCXJldCA9 IGRybW1fbW9kZV9jb25maWdfaW5pdChkcm0pOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisK KwlnZHJtLT5pZm51bSA9IGlmbnVtOworCWdkcm0tPmZsYWdzID0gbGUzMl90b19jcHUoZGVzYy5m bGFncyk7CisJZ2RybS0+Y29tcHJlc3Npb24gPSBkZXNjLmNvbXByZXNzaW9uICYgR1VEX0NPTVBS RVNTSU9OX0xaNDsKKworCWlmIChnZHJtLT5mbGFncyAmIEdVRF9ESVNQTEFZX0ZMQUdfRlVMTF9V UERBVEUgJiYgZ2RybS0+Y29tcHJlc3Npb24pCisJCXJldHVybiAtRUlOVkFMOworCisJbXV0ZXhf aW5pdCgmZ2RybS0+Y3RybF9sb2NrKTsKKwltdXRleF9pbml0KCZnZHJtLT5kYW1hZ2VfbG9jayk7 CisJSU5JVF9XT1JLKCZnZHJtLT53b3JrLCBndWRfZmx1c2hfd29yayk7CisJZ3VkX2NsZWFyX2Rh bWFnZShnZHJtKTsKKworCXJldCA9IGRybW1fYWRkX2FjdGlvbl9vcl9yZXNldChkcm0sIGd1ZF9m cmVlX2J1ZmZlcnNfYW5kX211dGV4LCBOVUxMKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0Owor CisJZHJtLT5tb2RlX2NvbmZpZy5taW5fd2lkdGggPSBsZTMyX3RvX2NwdShkZXNjLm1pbl93aWR0 aCk7CisJZHJtLT5tb2RlX2NvbmZpZy5tYXhfd2lkdGggPSBsZTMyX3RvX2NwdShkZXNjLm1heF93 aWR0aCk7CisJZHJtLT5tb2RlX2NvbmZpZy5taW5faGVpZ2h0ID0gbGUzMl90b19jcHUoZGVzYy5t aW5faGVpZ2h0KTsKKwlkcm0tPm1vZGVfY29uZmlnLm1heF9oZWlnaHQgPSBsZTMyX3RvX2NwdShk ZXNjLm1heF9oZWlnaHQpOworCisJZm9ybWF0c19kZXYgPSBkZXZtX2ttYWxsb2MoZGV2LCBkZXNj Lm51bV9mb3JtYXRzLCBHRlBfS0VSTkVMKTsKKwkvKiBBZGQgcm9vbSBmb3IgZW11bGF0ZWQgWFJH Qjg4ODggKi8KKwlmb3JtYXRzID0gZGV2bV9rbWFsbG9jX2FycmF5KGRldiwgZGVzYy5udW1fZm9y bWF0cyArIDEsIHNpemVvZigqZm9ybWF0cyksIEdGUF9LRVJORUwpOworCWlmICghZm9ybWF0c19k ZXYgfHwgIWZvcm1hdHMpCisJCXJldHVybiAtRU5PTUVNOworCisJcmV0ID0gZ3VkX3VzYl9nZXQo Z2RybSwgR1VEX1JFUV9HRVRfRk9STUFUUywgMCwgZm9ybWF0c19kZXYsIGRlc2MubnVtX2Zvcm1h dHMpOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwlmb3IgKGkgPSAwOyBpIDwgZGVzYy5u dW1fZm9ybWF0czsgaSsrKSB7CisJCWNvbnN0IHN0cnVjdCBkcm1fZm9ybWF0X2luZm8gKmluZm87 CisJCXNpemVfdCBmbXRfYnVmX3NpemU7CisJCXUzMiBmb3JtYXQ7CisKKwkJZm9ybWF0ID0gZ3Vk X3RvX2ZvdXJjYyhmb3JtYXRzX2RldltpXSk7CisJCWlmICghZm9ybWF0KSB7CisJCQlkcm1fZGJn KGRybSwgIlVuc3VwcG9ydGVkIGZvcm1hdDogMHglMDJ4XG4iLCBmb3JtYXRzX2RldltpXSk7CisJ CQljb250aW51ZTsKKwkJfQorCisJCWlmIChmb3JtYXQgPT0gR1VEX0RSTV9GT1JNQVRfUjEpCisJ CQlpbmZvID0gJmd1ZF9kcm1fZm9ybWF0X3IxOworCQllbHNlCisJCQlpbmZvID0gZHJtX2Zvcm1h dF9pbmZvKGZvcm1hdCk7CisKKwkJc3dpdGNoIChmb3JtYXQpIHsKKwkJY2FzZSBHVURfRFJNX0ZP Uk1BVF9SMToKKwkJCXhyZ2I4ODg4X2VtdWxhdGlvbl9mb3JtYXQgPSBpbmZvOworCQkJYnJlYWs7 CisJCWNhc2UgRFJNX0ZPUk1BVF9SR0I1NjU6CisJCQlyZ2I1NjVfc3VwcG9ydGVkID0gdHJ1ZTsK KwkJCWlmICgheHJnYjg4ODhfZW11bGF0aW9uX2Zvcm1hdCkKKwkJCQl4cmdiODg4OF9lbXVsYXRp b25fZm9ybWF0ID0gaW5mbzsKKwkJCWJyZWFrOworCQljYXNlIERSTV9GT1JNQVRfWFJHQjg4ODg6 CisJCQl4cmdiODg4OF9zdXBwb3J0ZWQgPSB0cnVlOworCQkJYnJlYWs7CisJCX07CisKKwkJZm10 X2J1Zl9zaXplID0gZHJtX2Zvcm1hdF9pbmZvX21pbl9waXRjaChpbmZvLCAwLCBkcm0tPm1vZGVf Y29uZmlnLm1heF93aWR0aCkgKgorCQkJICAgICAgIGRybS0+bW9kZV9jb25maWcubWF4X2hlaWdo dDsKKwkJbWF4X2J1ZmZlcl9zaXplID0gbWF4KG1heF9idWZmZXJfc2l6ZSwgZm10X2J1Zl9zaXpl KTsKKworCQlpZiAoZm9ybWF0ID09IEdVRF9EUk1fRk9STUFUX1IxKQorCQkJY29udGludWU7IC8q IEludGVybmFsIG5vdCBmb3IgdXNlcnNwYWNlICovCisKKwkJZm9ybWF0c1tudW1fZm9ybWF0cysr XSA9IGZvcm1hdDsKKwl9CisKKwlpZiAoIW51bV9mb3JtYXRzICYmICF4cmdiODg4OF9lbXVsYXRp b25fZm9ybWF0KSB7CisJCWRldl9lcnIoZGV2LCAiTm8gc3VwcG9ydGVkIHBpeGVsIGZvcm1hdHMg Zm91bmRcbiIpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwkvKiBQcmVmZXIgc3BlZWQgb3Zl ciBjb2xvciBkZXB0aCAqLworCWlmIChyZ2I1NjVfc3VwcG9ydGVkKQorCQlkcm0tPm1vZGVfY29u ZmlnLnByZWZlcnJlZF9kZXB0aCA9IDE2OworCisJaWYgKCF4cmdiODg4OF9zdXBwb3J0ZWQgJiYg eHJnYjg4ODhfZW11bGF0aW9uX2Zvcm1hdCkgeworCQlnZHJtLT54cmdiODg4OF9lbXVsYXRpb25f Zm9ybWF0ID0geHJnYjg4ODhfZW11bGF0aW9uX2Zvcm1hdDsKKwkJZm9ybWF0c1tudW1fZm9ybWF0 cysrXSA9IERSTV9GT1JNQVRfWFJHQjg4ODg7CisJfQorCisJaWYgKGRlc2MubWF4X2J1ZmZlcl9z aXplKQorCQltYXhfYnVmZmVyX3NpemUgPSBsZTMyX3RvX2NwdShkZXNjLm1heF9idWZmZXJfc2l6 ZSk7CityZXRyeToKKwkvKgorCSAqIFVzZSBwbGFpbiBrbWFsbG9jIGhlcmUgc2luY2UgZGV2bV9r bWFsbG9jKCkgcGxhY2VzIHN0cnVjdCBkZXZyZXMgYXQgdGhlIGJlZ2lubmluZworCSAqIG9mIHRo ZSBidWZmZXIgaXQgYWxsb2NhdGVzLiBUaGlzIHdhc3RlcyBhIGxvdCBvZiBtZW1vcnkgd2hlbiBh bGxvY2F0aW5nIGJpZyBidWZmZXJzLgorCSAqIEFza2luZyBmb3IgMk0gd291bGQgYWN0dWFsbHkg YWxsb2NhdGUgNE0uIFRoaXMgd291bGQgYWxzbyBwcmV2ZW50IGdldHRpbmcgdGhlIGJpZ2dlc3QK KwkgKiBwb3NzaWJsZSBidWZmZXIgcG90ZW50aWFsbHkgbGVhZGluZyB0byBzcGxpdCB0cmFuc2Zl cnMuCisJICovCisJZ2RybS0+YnVsa19idWYgPSBrbWFsbG9jKG1heF9idWZmZXJfc2l6ZSwgR0ZQ X0tFUk5FTCB8IF9fR0ZQX05PV0FSTik7CisJaWYgKCFnZHJtLT5idWxrX2J1ZikgeworCQltYXhf YnVmZmVyX3NpemUgPSByb3VuZHVwX3Bvd19vZl90d28obWF4X2J1ZmZlcl9zaXplKSAvIDI7CisJ CWlmIChtYXhfYnVmZmVyX3NpemUgPCBTWl81MTJLKQorCQkJcmV0dXJuIC1FTk9NRU07CisJCWdv dG8gcmV0cnk7CisJfQorCisJZ2RybS0+YnVsa19waXBlID0gdXNiX3NuZGJ1bGtwaXBlKHVzYiwg dXNiX2VuZHBvaW50X251bShidWxrX291dCkpOworCWdkcm0tPmJ1bGtfbGVuID0gbWF4X2J1ZmZl cl9zaXplOworCisJaWYgKGdkcm0tPmNvbXByZXNzaW9uICYgR1VEX0NPTVBSRVNTSU9OX0xaNCkg eworCQlnZHJtLT5sejRfY29tcF9tZW0gPSBkZXZtX2ttYWxsb2MoZGV2LCBMWjRfTUVNX0NPTVBS RVNTLCBHRlBfS0VSTkVMKTsKKwkJaWYgKCFnZHJtLT5sejRfY29tcF9tZW0pCisJCQlyZXR1cm4g LUVOT01FTTsKKworCQlnZHJtLT5jb21wcmVzc19idWYgPSB2bWFsbG9jKGdkcm0tPmJ1bGtfbGVu KTsKKwkJaWYgKCFnZHJtLT5jb21wcmVzc19idWYpCisJCQlyZXR1cm4gLUVOT01FTTsKKwl9CisK KwlyZXQgPSBkcm1fc2ltcGxlX2Rpc3BsYXlfcGlwZV9pbml0KGRybSwgJmdkcm0tPnBpcGUsICZn dWRfcGlwZV9mdW5jcywKKwkJCQkJICAgZm9ybWF0cywgbnVtX2Zvcm1hdHMsCisJCQkJCSAgIGd1 ZF9waXBlX21vZGlmaWVycywgTlVMTCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCWRl dm1fa2ZyZWUoZGV2LCBmb3JtYXRzKTsKKwlkZXZtX2tmcmVlKGRldiwgZm9ybWF0c19kZXYpOwor CisJcmV0ID0gZ3VkX2dldF9wcm9wZXJ0aWVzKGdkcm0sIGRlc2MubnVtX3Byb3BlcnRpZXMpOwor CWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwlkcm1fcGxhbmVfZW5hYmxlX2ZiX2RhbWFnZV9j bGlwcygmZ2RybS0+cGlwZS5wbGFuZSk7CisKKwlmb3IgKGkgPSAwOyBpIDwgZGVzYy5udW1fY29u bmVjdG9yczsgaSsrKSB7CisJCXJldCA9IGd1ZF9jb25uZWN0b3JfY3JlYXRlKGdkcm0sIGkpOwor CQlpZiAocmV0KQorCQkJcmV0dXJuIHJldDsKKwl9CisKKwlkcm1fbW9kZV9jb25maWdfcmVzZXQo ZHJtKTsKKworCXVzYl9zZXRfaW50ZmRhdGEoaW50ZXJmYWNlLCBnZHJtKTsKKworCXJldCA9IGRy bV9kZXZfcmVnaXN0ZXIoZHJtLCAwKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJZHJt X2ttc19oZWxwZXJfcG9sbF9pbml0KGRybSk7CisKKwlkcm1fZmJkZXZfZ2VuZXJpY19zZXR1cChk cm0sIDApOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyB2b2lkIGd1ZF9kaXNjb25uZWN0KHN0 cnVjdCB1c2JfaW50ZXJmYWNlICppbnRlcmZhY2UpCit7CisJc3RydWN0IGd1ZF9kZXZpY2UgKmdk cm0gPSB1c2JfZ2V0X2ludGZkYXRhKGludGVyZmFjZSk7CisJc3RydWN0IGRybV9kZXZpY2UgKmRy bSA9ICZnZHJtLT5kcm07CisKKwlkcm1fZGJnKGRybSwgIiVzOlxuIiwgX19mdW5jX18pOworCisJ ZHJtX2ttc19oZWxwZXJfcG9sbF9maW5pKGRybSk7CisJZHJtX2Rldl91bnBsdWcoZHJtKTsKKwlk cm1fYXRvbWljX2hlbHBlcl9zaHV0ZG93bihkcm0pOworfQorCitzdGF0aWMgaW50IGd1ZF9zdXNw ZW5kKHN0cnVjdCB1c2JfaW50ZXJmYWNlICppbnRlcmZhY2UsIHBtX21lc3NhZ2VfdCBtZXNzYWdl KQoreworCXN0cnVjdCBndWRfZGV2aWNlICpnZHJtID0gdXNiX2dldF9pbnRmZGF0YShpbnRlcmZh Y2UpOworCisJcmV0dXJuIGRybV9tb2RlX2NvbmZpZ19oZWxwZXJfc3VzcGVuZCgmZ2RybS0+ZHJt KTsKK30KKworc3RhdGljIGludCBndWRfcmVzdW1lKHN0cnVjdCB1c2JfaW50ZXJmYWNlICppbnRl cmZhY2UpCit7CisJc3RydWN0IGd1ZF9kZXZpY2UgKmdkcm0gPSB1c2JfZ2V0X2ludGZkYXRhKGlu dGVyZmFjZSk7CisKKwlkcm1fbW9kZV9jb25maWdfaGVscGVyX3Jlc3VtZSgmZ2RybS0+ZHJtKTsK KworCXJldHVybiAwOworfQorCitzdGF0aWMgY29uc3Qgc3RydWN0IHVzYl9kZXZpY2VfaWQgZ3Vk X2lkX3RhYmxlW10gPSB7CisJeyBVU0JfREVWSUNFX0lOVEVSRkFDRV9DTEFTUygweDFkNTAsIDB4 NjE0ZCwgVVNCX0NMQVNTX1ZFTkRPUl9TUEVDKSB9LAorCXsgfQorfTsKKworTU9EVUxFX0RFVklD RV9UQUJMRSh1c2IsIGd1ZF9pZF90YWJsZSk7CisKK3N0YXRpYyBzdHJ1Y3QgdXNiX2RyaXZlciBn dWRfdXNiX2RyaXZlciA9IHsKKwkubmFtZQkJPSAiZ3VkIiwKKwkucHJvYmUJCT0gZ3VkX3Byb2Jl LAorCS5kaXNjb25uZWN0CT0gZ3VkX2Rpc2Nvbm5lY3QsCisJLmlkX3RhYmxlCT0gZ3VkX2lkX3Rh YmxlLAorCS5zdXNwZW5kCT0gZ3VkX3N1c3BlbmQsCisJLnJlc3VtZQkJPSBndWRfcmVzdW1lLAor CS5yZXNldF9yZXN1bWUJPSBndWRfcmVzdW1lLAorfTsKKworbW9kdWxlX3VzYl9kcml2ZXIoZ3Vk X3VzYl9kcml2ZXIpOworCitNT0RVTEVfQVVUSE9SKCJOb3JhbGYgVHLDuG5uZXMiKTsKK01PRFVM RV9MSUNFTlNFKCJEdWFsIE1JVC9HUEwiKTsKZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9n dWQvZ3VkX2ludGVybmFsLmggYi9kcml2ZXJzL2dwdS9kcm0vZ3VkL2d1ZF9pbnRlcm5hbC5oCm5l dyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uNDZlN2Q3ZWQyYzY5Ci0tLSAv ZGV2L251bGwKKysrIGIvZHJpdmVycy9ncHUvZHJtL2d1ZC9ndWRfaW50ZXJuYWwuaApAQCAtMCww ICsxLDE0OCBAQAorLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVCAqLworCisjaWZuZGVm IF9fTElOVVhfR1VEX0lOVEVSTkFMX0gKKyNkZWZpbmUgX19MSU5VWF9HVURfSU5URVJOQUxfSAor CisjaW5jbHVkZSA8bGludXgvbGlzdC5oPgorI2luY2x1ZGUgPGxpbnV4L211dGV4Lmg+CisjaW5j bHVkZSA8bGludXgvdXNiLmg+CisjaW5jbHVkZSA8bGludXgvd29ya3F1ZXVlLmg+CisjaW5jbHVk ZSA8dWFwaS9kcm0vZHJtX2ZvdXJjYy5oPgorCisjaW5jbHVkZSA8ZHJtL2RybV9tb2Rlcy5oPgor I2luY2x1ZGUgPGRybS9kcm1fc2ltcGxlX2ttc19oZWxwZXIuaD4KKworc3RydWN0IGd1ZF9kZXZp Y2UgeworCXN0cnVjdCBkcm1fZGV2aWNlIGRybTsKKwlzdHJ1Y3QgZHJtX3NpbXBsZV9kaXNwbGF5 X3BpcGUgcGlwZTsKKwlzdHJ1Y3Qgd29ya19zdHJ1Y3Qgd29yazsKKwl1OCBpZm51bTsKKwl1MzIg ZmxhZ3M7CisJY29uc3Qgc3RydWN0IGRybV9mb3JtYXRfaW5mbyAqeHJnYjg4ODhfZW11bGF0aW9u X2Zvcm1hdDsKKworCXUxNiAqcHJvcGVydGllczsKKwl1bnNpZ25lZCBpbnQgbnVtX3Byb3BlcnRp ZXM7CisKKwl1bnNpZ25lZCBpbnQgYnVsa19waXBlOworCXZvaWQgKmJ1bGtfYnVmOworCXNpemVf dCBidWxrX2xlbjsKKworCXU4IGNvbXByZXNzaW9uOworCXZvaWQgKmx6NF9jb21wX21lbTsKKwl2 b2lkICpjb21wcmVzc19idWY7CisKKwl1NjQgc3RhdHNfbGVuZ3RoOworCXU2NCBzdGF0c19hY3R1 YWxfbGVuZ3RoOworCXVuc2lnbmVkIGludCBzdGF0c19udW1fZXJyb3JzOworCisJc3RydWN0IG11 dGV4IGN0cmxfbG9jazsgLyogU2VyaWFsaXplIGdldC9zZXQgYW5kIHN0YXR1cyB0cmFuc2ZlcnMg Ki8KKworCXN0cnVjdCBtdXRleCBkYW1hZ2VfbG9jazsgLyogUHJvdGVjdHMgdGhlIGZvbGxvd2lu ZyBtZW1iZXJzOiAqLworCXN0cnVjdCBkcm1fZnJhbWVidWZmZXIgKmZiOworCXN0cnVjdCBkcm1f cmVjdCBkYW1hZ2U7CisJYm9vbCBwcmV2X2ZsdXNoX2ZhaWxlZDsKK307CisKK3N0YXRpYyBpbmxp bmUgc3RydWN0IGd1ZF9kZXZpY2UgKnRvX2d1ZF9kZXZpY2Uoc3RydWN0IGRybV9kZXZpY2UgKmRy bSkKK3sKKwlyZXR1cm4gY29udGFpbmVyX29mKGRybSwgc3RydWN0IGd1ZF9kZXZpY2UsIGRybSk7 Cit9CisKK3N0YXRpYyBpbmxpbmUgc3RydWN0IHVzYl9kZXZpY2UgKmd1ZF90b191c2JfZGV2aWNl KHN0cnVjdCBndWRfZGV2aWNlICpnZHJtKQoreworCXJldHVybiBpbnRlcmZhY2VfdG9fdXNiZGV2 KHRvX3VzYl9pbnRlcmZhY2UoZ2RybS0+ZHJtLmRldikpOworfQorCitpbnQgZ3VkX3VzYl9nZXQo c3RydWN0IGd1ZF9kZXZpY2UgKmdkcm0sIHU4IHJlcXVlc3QsIHUxNiBpbmRleCwgdm9pZCAqYnVm LCBzaXplX3QgbGVuKTsKK2ludCBndWRfdXNiX3NldChzdHJ1Y3QgZ3VkX2RldmljZSAqZ2RybSwg dTggcmVxdWVzdCwgdTE2IGluZGV4LCB2b2lkICpidWYsIHNpemVfdCBsZW4pOworaW50IGd1ZF91 c2Jfd3JpdGU4KHN0cnVjdCBndWRfZGV2aWNlICpnZHJtLCB1OCByZXF1ZXN0LCB1OCB2YWwpOwor Cit2b2lkIGd1ZF9jbGVhcl9kYW1hZ2Uoc3RydWN0IGd1ZF9kZXZpY2UgKmdkcm0pOwordm9pZCBn dWRfZmx1c2hfd29yayhzdHJ1Y3Qgd29ya19zdHJ1Y3QgKndvcmspOworaW50IGd1ZF9waXBlX2No ZWNrKHN0cnVjdCBkcm1fc2ltcGxlX2Rpc3BsYXlfcGlwZSAqcGlwZSwKKwkJICAgc3RydWN0IGRy bV9wbGFuZV9zdGF0ZSAqbmV3X3BsYW5lX3N0YXRlLAorCQkgICBzdHJ1Y3QgZHJtX2NydGNfc3Rh dGUgKm5ld19jcnRjX3N0YXRlKTsKK3ZvaWQgZ3VkX3BpcGVfdXBkYXRlKHN0cnVjdCBkcm1fc2lt cGxlX2Rpc3BsYXlfcGlwZSAqcGlwZSwKKwkJICAgICBzdHJ1Y3QgZHJtX3BsYW5lX3N0YXRlICpv bGRfc3RhdGUpOworaW50IGd1ZF9jb25uZWN0b3JfZmlsbF9wcm9wZXJ0aWVzKHN0cnVjdCBkcm1f Y29ubmVjdG9yICpjb25uZWN0b3IsCisJCQkJICBzdHJ1Y3QgZHJtX2Nvbm5lY3Rvcl9zdGF0ZSAq Y29ubmVjdG9yX3N0YXRlLAorCQkJCSAgc3RydWN0IGd1ZF9wcm9wZXJ0eV9yZXEgKnByb3BlcnRp ZXMpOworaW50IGd1ZF9jb25uZWN0b3JfY3JlYXRlKHN0cnVjdCBndWRfZGV2aWNlICpnZHJtLCB1 bnNpZ25lZCBpbnQgaW5kZXgpOworCisjZGVmaW5lIEdVRF9EUk1fRk9STUFUX1IxCWZvdXJjY19j b2RlKCdSJywgJzEnLCAnICcsICcgJykKKworc3RhdGljIGlubGluZSB1OCBndWRfZnJvbV9mb3Vy Y2ModTMyIGZvdXJjYykKK3sKKwlzd2l0Y2ggKGZvdXJjYykgeworCWNhc2UgR1VEX0RSTV9GT1JN QVRfUjE6CisJCXJldHVybiBHVURfUElYRUxfRk9STUFUX1IxOworCWNhc2UgRFJNX0ZPUk1BVF9S R0I1NjU6CisJCXJldHVybiBHVURfUElYRUxfRk9STUFUX1JHQjU2NTsKKwljYXNlIERSTV9GT1JN QVRfWFJHQjg4ODg6CisJCXJldHVybiBHVURfUElYRUxfRk9STUFUX1hSR0I4ODg4OworCWNhc2Ug RFJNX0ZPUk1BVF9BUkdCODg4ODoKKwkJcmV0dXJuIEdVRF9QSVhFTF9GT1JNQVRfQVJHQjg4ODg7 CisJfTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgaW5saW5lIHUzMiBndWRfdG9fZm91cmNj KHU4IGZvcm1hdCkKK3sKKwlzd2l0Y2ggKGZvcm1hdCkgeworCWNhc2UgR1VEX1BJWEVMX0ZPUk1B VF9SMToKKwkJcmV0dXJuIEdVRF9EUk1fRk9STUFUX1IxOworCWNhc2UgR1VEX1BJWEVMX0ZPUk1B VF9SR0I1NjU6CisJCXJldHVybiBEUk1fRk9STUFUX1JHQjU2NTsKKwljYXNlIEdVRF9QSVhFTF9G T1JNQVRfWFJHQjg4ODg6CisJCXJldHVybiBEUk1fRk9STUFUX1hSR0I4ODg4OworCWNhc2UgR1VE X1BJWEVMX0ZPUk1BVF9BUkdCODg4ODoKKwkJcmV0dXJuIERSTV9GT1JNQVRfQVJHQjg4ODg7CisJ fTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgaW5saW5lIHZvaWQgZ3VkX2Zyb21fZGlzcGxh eV9tb2RlKHN0cnVjdCBndWRfZGlzcGxheV9tb2RlX3JlcSAqZHN0LAorCQkJCQkgY29uc3Qgc3Ry dWN0IGRybV9kaXNwbGF5X21vZGUgKnNyYykKK3sKKwl1MzIgZmxhZ3MgPSBzcmMtPmZsYWdzICYg R1VEX0RJU1BMQVlfTU9ERV9GTEFHX1VTRVJfTUFTSzsKKworCWlmIChzcmMtPnR5cGUgJiBEUk1f TU9ERV9UWVBFX1BSRUZFUlJFRCkKKwkJZmxhZ3MgfD0gR1VEX0RJU1BMQVlfTU9ERV9GTEFHX1BS RUZFUlJFRDsKKworCWRzdC0+Y2xvY2sgPSBjcHVfdG9fbGUzMihzcmMtPmNsb2NrKTsKKwlkc3Qt PmhkaXNwbGF5ID0gY3B1X3RvX2xlMTYoc3JjLT5oZGlzcGxheSk7CisJZHN0LT5oc3luY19zdGFy dCA9IGNwdV90b19sZTE2KHNyYy0+aHN5bmNfc3RhcnQpOworCWRzdC0+aHN5bmNfZW5kID0gY3B1 X3RvX2xlMTYoc3JjLT5oc3luY19lbmQpOworCWRzdC0+aHRvdGFsID0gY3B1X3RvX2xlMTYoc3Jj LT5odG90YWwpOworCWRzdC0+dmRpc3BsYXkgPSBjcHVfdG9fbGUxNihzcmMtPnZkaXNwbGF5KTsK Kwlkc3QtPnZzeW5jX3N0YXJ0ID0gY3B1X3RvX2xlMTYoc3JjLT52c3luY19zdGFydCk7CisJZHN0 LT52c3luY19lbmQgPSBjcHVfdG9fbGUxNihzcmMtPnZzeW5jX2VuZCk7CisJZHN0LT52dG90YWwg PSBjcHVfdG9fbGUxNihzcmMtPnZ0b3RhbCk7CisJZHN0LT5mbGFncyA9IGNwdV90b19sZTMyKGZs YWdzKTsKK30KKworc3RhdGljIGlubGluZSB2b2lkIGd1ZF90b19kaXNwbGF5X21vZGUoc3RydWN0 IGRybV9kaXNwbGF5X21vZGUgKmRzdCwKKwkJCQkgICAgICAgY29uc3Qgc3RydWN0IGd1ZF9kaXNw bGF5X21vZGVfcmVxICpzcmMpCit7CisJdTMyIGZsYWdzID0gbGUzMl90b19jcHUoc3JjLT5mbGFn cyk7CisKKwltZW1zZXQoZHN0LCAwLCBzaXplb2YoKmRzdCkpOworCWRzdC0+Y2xvY2sgPSBsZTMy X3RvX2NwdShzcmMtPmNsb2NrKTsKKwlkc3QtPmhkaXNwbGF5ID0gbGUxNl90b19jcHUoc3JjLT5o ZGlzcGxheSk7CisJZHN0LT5oc3luY19zdGFydCA9IGxlMTZfdG9fY3B1KHNyYy0+aHN5bmNfc3Rh cnQpOworCWRzdC0+aHN5bmNfZW5kID0gbGUxNl90b19jcHUoc3JjLT5oc3luY19lbmQpOworCWRz dC0+aHRvdGFsID0gbGUxNl90b19jcHUoc3JjLT5odG90YWwpOworCWRzdC0+dmRpc3BsYXkgPSBs ZTE2X3RvX2NwdShzcmMtPnZkaXNwbGF5KTsKKwlkc3QtPnZzeW5jX3N0YXJ0ID0gbGUxNl90b19j cHUoc3JjLT52c3luY19zdGFydCk7CisJZHN0LT52c3luY19lbmQgPSBsZTE2X3RvX2NwdShzcmMt PnZzeW5jX2VuZCk7CisJZHN0LT52dG90YWwgPSBsZTE2X3RvX2NwdShzcmMtPnZ0b3RhbCk7CisJ ZHN0LT5mbGFncyA9IGZsYWdzICYgR1VEX0RJU1BMQVlfTU9ERV9GTEFHX1VTRVJfTUFTSzsKKwlk c3QtPnR5cGUgPSBEUk1fTU9ERV9UWVBFX0RSSVZFUjsKKwlpZiAoZmxhZ3MgJiBHVURfRElTUExB WV9NT0RFX0ZMQUdfUFJFRkVSUkVEKQorCQlkc3QtPnR5cGUgfD0gRFJNX01PREVfVFlQRV9QUkVG RVJSRUQ7CisJZHJtX21vZGVfc2V0X25hbWUoZHN0KTsKK30KKworI2VuZGlmCmRpZmYgLS1naXQg YS9kcml2ZXJzL2dwdS9kcm0vZ3VkL2d1ZF9waXBlLmMgYi9kcml2ZXJzL2dwdS9kcm0vZ3VkL2d1 ZF9waXBlLmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi4xZWVmOTMw YmNmOWIKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2dwdS9kcm0vZ3VkL2d1ZF9waXBlLmMK QEAgLTAsMCArMSw0NzIgQEAKKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVQKKy8qCisg KiBDb3B5cmlnaHQgMjAyMCBOb3JhbGYgVHLDuG5uZXMKKyAqLworCisjaW5jbHVkZSA8bGludXgv ZG1hLWJ1Zi5oPgorI2luY2x1ZGUgPGxpbnV4L2x6NC5oPgorI2luY2x1ZGUgPGxpbnV4L3VzYi5o PgorI2luY2x1ZGUgPGxpbnV4L3dvcmtxdWV1ZS5oPgorCisjaW5jbHVkZSA8ZHJtL2RybV9hdG9t aWMuaD4KKyNpbmNsdWRlIDxkcm0vZHJtX2Nvbm5lY3Rvci5oPgorI2luY2x1ZGUgPGRybS9kcm1f ZGFtYWdlX2hlbHBlci5oPgorI2luY2x1ZGUgPGRybS9kcm1fZHJ2Lmg+CisjaW5jbHVkZSA8ZHJt L2RybV9mb3JtYXRfaGVscGVyLmg+CisjaW5jbHVkZSA8ZHJtL2RybV9mb3VyY2MuaD4KKyNpbmNs dWRlIDxkcm0vZHJtX2ZyYW1lYnVmZmVyLmg+CisjaW5jbHVkZSA8ZHJtL2RybV9nZW1fc2htZW1f aGVscGVyLmg+CisjaW5jbHVkZSA8ZHJtL2RybV9wcmludC5oPgorI2luY2x1ZGUgPGRybS9kcm1f cmVjdC5oPgorI2luY2x1ZGUgPGRybS9kcm1fc2ltcGxlX2ttc19oZWxwZXIuaD4KKyNpbmNsdWRl IDxkcm0vZ3VkLmg+CisKKyNpbmNsdWRlICJndWRfaW50ZXJuYWwuaCIKKworc3RhdGljIGJvb2wg Z3VkX2lzX2JpZ19lbmRpYW4odm9pZCkKK3sKKyNpZiBkZWZpbmVkKF9fQklHX0VORElBTikKKwly ZXR1cm4gdHJ1ZTsKKyNlbHNlCisJcmV0dXJuIGZhbHNlOworI2VuZGlmCit9CisKK3N0YXRpYyBz aXplX3QgZ3VkX3hyZ2I4ODg4X3RvX3IxMjQodTggKmRzdCwgY29uc3Qgc3RydWN0IGRybV9mb3Jt YXRfaW5mbyAqZm9ybWF0LAorCQkJCSAgIHZvaWQgKnNyYywgc3RydWN0IGRybV9mcmFtZWJ1ZmZl ciAqZmIsCisJCQkJICAgc3RydWN0IGRybV9yZWN0ICpyZWN0KQoreworCXVuc2lnbmVkIGludCBi bG9ja193aWR0aCA9IGRybV9mb3JtYXRfaW5mb19ibG9ja193aWR0aChmb3JtYXQsIDApOworCXVu c2lnbmVkIGludCBiaXRzX3Blcl9waXhlbCA9IDggLyBibG9ja193aWR0aDsKKwl1bnNpZ25lZCBp bnQgeCwgeSwgd2lkdGgsIGhlaWdodDsKKwl1OCAqcCwgKmJsb2NrID0gZHN0OyAvKiBBc3NpZ24g dG8gc2lsZW5jZSBjb21waWxlciB3YXJuaW5nICovCisJc2l6ZV90IGxlbjsKKwl2b2lkICpidWY7 CisKKwlXQVJOX09OX09OQ0UoZm9ybWF0LT5jaGFyX3Blcl9ibG9ja1swXSAhPSAxKTsKKworCS8q IFN0YXJ0IG9uIGEgYnl0ZSBib3VuZGFyeSAqLworCXJlY3QtPngxID0gQUxJR05fRE9XTihyZWN0 LT54MSwgYmxvY2tfd2lkdGgpOworCXdpZHRoID0gZHJtX3JlY3Rfd2lkdGgocmVjdCk7CisJaGVp Z2h0ID0gZHJtX3JlY3RfaGVpZ2h0KHJlY3QpOworCWxlbiA9IGRybV9mb3JtYXRfaW5mb19taW5f cGl0Y2goZm9ybWF0LCAwLCB3aWR0aCkgKiBoZWlnaHQ7CisKKwlidWYgPSBrbWFsbG9jKHdpZHRo ICogaGVpZ2h0LCBHRlBfS0VSTkVMKTsKKwlpZiAoIWJ1ZikKKwkJcmV0dXJuIDA7CisKKwlkcm1f ZmJfeHJnYjg4ODhfdG9fZ3JheTgoYnVmLCBzcmMsIGZiLCByZWN0KTsKKworCXAgPSBidWY7CisJ Zm9yICh5ID0gMDsgeSA8IGRybV9yZWN0X2hlaWdodChyZWN0KTsgeSsrKSB7CisJCWZvciAoeCA9 IDA7IHggPCBkcm1fcmVjdF93aWR0aChyZWN0KTsgeCsrKSB7CisJCQlpZiAoISh4ICUgYmxvY2tf d2lkdGgpKSB7CisJCQkJYmxvY2sgPSBkc3QrKzsKKwkJCQkqYmxvY2sgPSAwOworCQkJfQorCisJ CQkqYmxvY2sgPDw9IGJpdHNfcGVyX3BpeGVsOworCQkJKmJsb2NrIHw9ICgqcCsrKSA+PiAoOCAt IGJpdHNfcGVyX3BpeGVsKTsKKwkJfQorCX0KKworCWtmcmVlKGJ1Zik7CisKKwlyZXR1cm4gbGVu OworfQorCitzdGF0aWMgaW50IGd1ZF9wcmVwX2ZsdXNoKHN0cnVjdCBndWRfZGV2aWNlICpnZHJt LCBzdHJ1Y3QgZHJtX2ZyYW1lYnVmZmVyICpmYiwKKwkJCSAgY29uc3Qgc3RydWN0IGRybV9mb3Jt YXRfaW5mbyAqZm9ybWF0LCBzdHJ1Y3QgZHJtX3JlY3QgKnJlY3QsCisJCQkgIHN0cnVjdCBndWRf c2V0X2J1ZmZlcl9yZXEgKnJlcSkKK3sKKwlzdHJ1Y3QgZG1hX2J1Zl9hdHRhY2htZW50ICppbXBv cnRfYXR0YWNoID0gZmItPm9ialswXS0+aW1wb3J0X2F0dGFjaDsKKwl1OCBjb21wcmVzc2lvbiA9 IGdkcm0tPmNvbXByZXNzaW9uOworCXN0cnVjdCBkbWFfYnVmX21hcCBtYXA7CisJdm9pZCAqdmFk ZHIsICpidWY7CisJc2l6ZV90IHBpdGNoLCBsZW47CisJaW50IHJldCA9IDA7CisKKwlwaXRjaCA9 IGRybV9mb3JtYXRfaW5mb19taW5fcGl0Y2goZm9ybWF0LCAwLCBkcm1fcmVjdF93aWR0aChyZWN0 KSk7CisJbGVuID0gcGl0Y2ggKiBkcm1fcmVjdF9oZWlnaHQocmVjdCk7CisJaWYgKGxlbiA+IGdk cm0tPmJ1bGtfbGVuKQorCQlyZXR1cm4gLUUyQklHOworCisJcmV0ID0gZHJtX2dlbV9zaG1lbV92 bWFwKGZiLT5vYmpbMF0sICZtYXApOworCWlmIChyZXQpCisJCXJldHVybiByZXQ7CisKKwl2YWRk ciA9IG1hcC52YWRkciArIGZiLT5vZmZzZXRzWzBdOworCisJaWYgKGltcG9ydF9hdHRhY2gpIHsK KwkJcmV0ID0gZG1hX2J1Zl9iZWdpbl9jcHVfYWNjZXNzKGltcG9ydF9hdHRhY2gtPmRtYWJ1Ziwg RE1BX0ZST01fREVWSUNFKTsKKwkJaWYgKHJldCkKKwkJCWdvdG8gdnVubWFwOworCX0KK3JldHJ5 OgorCWlmIChjb21wcmVzc2lvbikKKwkJYnVmID0gZ2RybS0+Y29tcHJlc3NfYnVmOworCWVsc2UK KwkJYnVmID0gZ2RybS0+YnVsa19idWY7CisKKwkvKgorCSAqIEltcG9ydGVkIGJ1ZmZlcnMgYXJl IGFzc3VtZWQgdG8gYmUgd3JpdGUtY29tYmluZWQgYW5kIHRodXMgdW5jYWNoZWQKKwkgKiB3aXRo IHNsb3cgcmVhZHMgKGF0IGxlYXN0IG9uIEFSTSkuCisJICovCisJaWYgKGZvcm1hdCAhPSBmYi0+ Zm9ybWF0KSB7CisJCWlmIChmb3JtYXQtPmZvcm1hdCA9PSBHVURfRFJNX0ZPUk1BVF9SMSkgewor CQkJbGVuID0gZ3VkX3hyZ2I4ODg4X3RvX3IxMjQoYnVmLCBmb3JtYXQsIHZhZGRyLCBmYiwgcmVj dCk7CisJCQlpZiAoIWxlbikgeworCQkJCXJldCA9IC1FTk9NRU07CisJCQkJZ290byBlbmRfY3B1 X2FjY2VzczsKKwkJCX0KKwkJfSBlbHNlIGlmIChmb3JtYXQtPmZvcm1hdCA9PSBEUk1fRk9STUFU X1JHQjU2NSkgeworCQkJZHJtX2ZiX3hyZ2I4ODg4X3RvX3JnYjU2NShidWYsIHZhZGRyLCBmYiwg cmVjdCwgZ3VkX2lzX2JpZ19lbmRpYW4oKSk7CisJCX0KKwl9IGVsc2UgaWYgKGd1ZF9pc19iaWdf ZW5kaWFuKCkgJiYgZm9ybWF0LT5jcHBbMF0gPiAxKSB7CisJCWRybV9mYl9zd2FiKGJ1ZiwgdmFk ZHIsIGZiLCByZWN0LCAhaW1wb3J0X2F0dGFjaCk7CisJfSBlbHNlIGlmIChjb21wcmVzc2lvbiAm JiAhaW1wb3J0X2F0dGFjaCAmJiBwaXRjaCA9PSBmYi0+cGl0Y2hlc1swXSkgeworCQkvKiBjYW4g Y29tcHJlc3MgZGlyZWN0bHkgZnJvbSB0aGUgZnJhbWVidWZmZXIgKi8KKwkJYnVmID0gdmFkZHIg KyByZWN0LT55MSAqIHBpdGNoOworCX0gZWxzZSB7CisJCWRybV9mYl9tZW1jcHkoYnVmLCB2YWRk ciwgZmIsIHJlY3QpOworCX0KKworCW1lbXNldChyZXEsIDAsIHNpemVvZigqcmVxKSk7CisJcmVx LT54ID0gY3B1X3RvX2xlMzIocmVjdC0+eDEpOworCXJlcS0+eSA9IGNwdV90b19sZTMyKHJlY3Qt PnkxKTsKKwlyZXEtPndpZHRoID0gY3B1X3RvX2xlMzIoZHJtX3JlY3Rfd2lkdGgocmVjdCkpOwor CXJlcS0+aGVpZ2h0ID0gY3B1X3RvX2xlMzIoZHJtX3JlY3RfaGVpZ2h0KHJlY3QpKTsKKwlyZXEt Pmxlbmd0aCA9IGNwdV90b19sZTMyKGxlbik7CisKKwlpZiAoY29tcHJlc3Npb24gJiBHVURfQ09N UFJFU1NJT05fTFo0KSB7CisJCWludCBjb21wbGVuOworCisJCWNvbXBsZW4gPSBMWjRfY29tcHJl c3NfZGVmYXVsdChidWYsIGdkcm0tPmJ1bGtfYnVmLCBsZW4sIGxlbiwgZ2RybS0+bHo0X2NvbXBf bWVtKTsKKwkJaWYgKGNvbXBsZW4gPCAwKSB7CisJCQljb21wcmVzc2lvbiA9IDA7CisJCQlnb3Rv IHJldHJ5OworCQl9CisKKwkJcmVxLT5jb21wcmVzc2lvbiA9IEdVRF9DT01QUkVTU0lPTl9MWjQ7 CisJCXJlcS0+Y29tcHJlc3NlZF9sZW5ndGggPSBjcHVfdG9fbGUzMihjb21wbGVuKTsKKwl9CisK K2VuZF9jcHVfYWNjZXNzOgorCWlmIChpbXBvcnRfYXR0YWNoKQorCQlkbWFfYnVmX2VuZF9jcHVf YWNjZXNzKGltcG9ydF9hdHRhY2gtPmRtYWJ1ZiwgRE1BX0ZST01fREVWSUNFKTsKK3Z1bm1hcDoK Kwlkcm1fZ2VtX3NobWVtX3Z1bm1hcChmYi0+b2JqWzBdLCAmbWFwKTsKKworCXJldHVybiByZXQ7 Cit9CisKK3N0YXRpYyBpbnQgZ3VkX2ZsdXNoX3JlY3Qoc3RydWN0IGd1ZF9kZXZpY2UgKmdkcm0s IHN0cnVjdCBkcm1fZnJhbWVidWZmZXIgKmZiLAorCQkJICBjb25zdCBzdHJ1Y3QgZHJtX2Zvcm1h dF9pbmZvICpmb3JtYXQsIHN0cnVjdCBkcm1fcmVjdCAqcmVjdCkKK3sKKwlzdHJ1Y3QgdXNiX2Rl dmljZSAqdXNiID0gZ3VkX3RvX3VzYl9kZXZpY2UoZ2RybSk7CisJc3RydWN0IGd1ZF9zZXRfYnVm ZmVyX3JlcSByZXE7CisJaW50IHJldCwgYWN0dWFsX2xlbmd0aDsKKwlzaXplX3QgbGVuLCB0cmxl bjsKKworCWRybV9kYmcoJmdkcm0tPmRybSwgIkZsdXNoaW5nIFtGQjolZF0gIiBEUk1fUkVDVF9G TVQgIlxuIiwgZmItPmJhc2UuaWQsIERSTV9SRUNUX0FSRyhyZWN0KSk7CisKKwlyZXQgPSBndWRf cHJlcF9mbHVzaChnZHJtLCBmYiwgZm9ybWF0LCByZWN0LCAmcmVxKTsKKwlpZiAocmV0KQorCQly ZXR1cm4gcmV0OworCisJbGVuID0gbGUzMl90b19jcHUocmVxLmxlbmd0aCk7CisKKwlpZiAocmVx LmNvbXByZXNzaW9uKQorCQl0cmxlbiA9IGxlMzJfdG9fY3B1KHJlcS5jb21wcmVzc2VkX2xlbmd0 aCk7CisJZWxzZQorCQl0cmxlbiA9IGxlbjsKKworCWdkcm0tPnN0YXRzX2xlbmd0aCArPSBsZW47 CisJLyogRGlkIGl0IHdyYXAgYXJvdW5kPyAqLworCWlmIChnZHJtLT5zdGF0c19sZW5ndGggPD0g bGVuICYmIGdkcm0tPnN0YXRzX2FjdHVhbF9sZW5ndGgpIHsKKwkJZ2RybS0+c3RhdHNfbGVuZ3Ro ID0gbGVuOworCQlnZHJtLT5zdGF0c19hY3R1YWxfbGVuZ3RoID0gMDsKKwl9CisJZ2RybS0+c3Rh dHNfYWN0dWFsX2xlbmd0aCArPSB0cmxlbjsKKworCWlmICghKGdkcm0tPmZsYWdzICYgR1VEX0RJ U1BMQVlfRkxBR19GVUxMX1VQREFURSkgfHwgZ2RybS0+cHJldl9mbHVzaF9mYWlsZWQpIHsKKwkJ cmV0ID0gZ3VkX3VzYl9zZXQoZ2RybSwgR1VEX1JFUV9TRVRfQlVGRkVSLCAwLCAmcmVxLCBzaXpl b2YocmVxKSk7CisJCWlmIChyZXQpCisJCQlyZXR1cm4gcmV0OworCX0KKworCXJldCA9IHVzYl9i dWxrX21zZyh1c2IsIGdkcm0tPmJ1bGtfcGlwZSwgZ2RybS0+YnVsa19idWYsIHRybGVuLAorCQkJ ICAgJmFjdHVhbF9sZW5ndGgsIG1zZWNzX3RvX2ppZmZpZXMoMzAwMCkpOworCWlmICghcmV0ICYm IHRybGVuICE9IGFjdHVhbF9sZW5ndGgpCisJCXJldCA9IC1FSU87CisJaWYgKHJldCkKKwkJZ2Ry bS0+c3RhdHNfbnVtX2Vycm9ycysrOworCisJcmV0dXJuIHJldDsKK30KKwordm9pZCBndWRfY2xl YXJfZGFtYWdlKHN0cnVjdCBndWRfZGV2aWNlICpnZHJtKQoreworCWdkcm0tPmRhbWFnZS54MSA9 IElOVF9NQVg7CisJZ2RybS0+ZGFtYWdlLnkxID0gSU5UX01BWDsKKwlnZHJtLT5kYW1hZ2UueDIg PSAwOworCWdkcm0tPmRhbWFnZS55MiA9IDA7Cit9CisKK3N0YXRpYyB2b2lkIGd1ZF9hZGRfZGFt YWdlKHN0cnVjdCBndWRfZGV2aWNlICpnZHJtLCBzdHJ1Y3QgZHJtX3JlY3QgKmRhbWFnZSkKK3sK KwlnZHJtLT5kYW1hZ2UueDEgPSBtaW4oZ2RybS0+ZGFtYWdlLngxLCBkYW1hZ2UtPngxKTsKKwln ZHJtLT5kYW1hZ2UueTEgPSBtaW4oZ2RybS0+ZGFtYWdlLnkxLCBkYW1hZ2UtPnkxKTsKKwlnZHJt LT5kYW1hZ2UueDIgPSBtYXgoZ2RybS0+ZGFtYWdlLngyLCBkYW1hZ2UtPngyKTsKKwlnZHJtLT5k YW1hZ2UueTIgPSBtYXgoZ2RybS0+ZGFtYWdlLnkyLCBkYW1hZ2UtPnkyKTsKK30KKworc3RhdGlj IHZvaWQgZ3VkX3JldHJ5X2ZhaWxlZF9mbHVzaChzdHJ1Y3QgZ3VkX2RldmljZSAqZ2RybSwgc3Ry dWN0IGRybV9mcmFtZWJ1ZmZlciAqZmIsCisJCQkJICAgc3RydWN0IGRybV9yZWN0ICpkYW1hZ2Up Cit7CisJLyoKKwkgKiBwaXBlX3VwZGF0ZSB3YWl0cyBmb3IgdGhlIHdvcmtlciB3aGVuIHRoZSBk aXNwbGF5IG1vZGUgaXMgZ29pbmcgdG8gY2hhbmdlLgorCSAqIFRoaXMgZW5zdXJlcyB0aGF0IHRo ZSB3aWR0aCBhbmQgaGVpZ2h0IGlzIHN0aWxsIHRoZSBzYW1lIG1ha2luZyBpdCBzYWZlIHRvCisJ ICogYWRkIGJhY2sgdGhlIGRhbWFnZS4KKwkgKi8KKworCW11dGV4X2xvY2soJmdkcm0tPmRhbWFn ZV9sb2NrKTsKKwlpZiAoIWdkcm0tPmZiKSB7CisJCWRybV9mcmFtZWJ1ZmZlcl9nZXQoZmIpOwor CQlnZHJtLT5mYiA9IGZiOworCX0KKwlndWRfYWRkX2RhbWFnZShnZHJtLCBkYW1hZ2UpOworCW11 dGV4X3VubG9jaygmZ2RybS0+ZGFtYWdlX2xvY2spOworCisJLyogUmV0cnkgb25seSBvbmNlIHRv IGF2b2lkIGEgcG9zc2libGUgc3Rvcm0gaW4gY2FzZSBvZiBjb250aW51ZXMgZXJyb3JzLiAqLwor CWlmICghZ2RybS0+cHJldl9mbHVzaF9mYWlsZWQpCisJCXF1ZXVlX3dvcmsoc3lzdGVtX2xvbmdf d3EsICZnZHJtLT53b3JrKTsKKwlnZHJtLT5wcmV2X2ZsdXNoX2ZhaWxlZCA9IHRydWU7Cit9CisK K3ZvaWQgZ3VkX2ZsdXNoX3dvcmsoc3RydWN0IHdvcmtfc3RydWN0ICp3b3JrKQoreworCXN0cnVj dCBndWRfZGV2aWNlICpnZHJtID0gY29udGFpbmVyX29mKHdvcmssIHN0cnVjdCBndWRfZGV2aWNl LCB3b3JrKTsKKwljb25zdCBzdHJ1Y3QgZHJtX2Zvcm1hdF9pbmZvICpmb3JtYXQ7CisJc3RydWN0 IGRybV9mcmFtZWJ1ZmZlciAqZmI7CisJc3RydWN0IGRybV9yZWN0IGRhbWFnZTsKKwl1bnNpZ25l ZCBpbnQgaSwgbGluZXM7CisJaW50IGlkeCwgcmV0ID0gMDsKKwlzaXplX3QgcGl0Y2g7CisKKwlp ZiAoIWRybV9kZXZfZW50ZXIoJmdkcm0tPmRybSwgJmlkeCkpCisJCXJldHVybjsKKworCW11dGV4 X2xvY2soJmdkcm0tPmRhbWFnZV9sb2NrKTsKKwlmYiA9IGdkcm0tPmZiOworCWdkcm0tPmZiID0g TlVMTDsKKwlkYW1hZ2UgPSBnZHJtLT5kYW1hZ2U7CisJZ3VkX2NsZWFyX2RhbWFnZShnZHJtKTsK KwltdXRleF91bmxvY2soJmdkcm0tPmRhbWFnZV9sb2NrKTsKKworCWlmICghZmIpCisJCWdvdG8g b3V0OworCisJZm9ybWF0ID0gZmItPmZvcm1hdDsKKwlpZiAoZm9ybWF0LT5mb3JtYXQgPT0gRFJN X0ZPUk1BVF9YUkdCODg4OCAmJiBnZHJtLT54cmdiODg4OF9lbXVsYXRpb25fZm9ybWF0KQorCQlm b3JtYXQgPSBnZHJtLT54cmdiODg4OF9lbXVsYXRpb25fZm9ybWF0OworCisJLyogU3BsaXQgdXBk YXRlIGlmIGl0J3MgdG9vIGJpZyAqLworCXBpdGNoID0gZHJtX2Zvcm1hdF9pbmZvX21pbl9waXRj aChmb3JtYXQsIDAsIGRybV9yZWN0X3dpZHRoKCZkYW1hZ2UpKTsKKwlsaW5lcyA9IGRybV9yZWN0 X2hlaWdodCgmZGFtYWdlKTsKKworCWlmIChnZHJtLT5idWxrX2xlbiA8IGxpbmVzICogcGl0Y2gp CisJCWxpbmVzID0gZ2RybS0+YnVsa19sZW4gLyBwaXRjaDsKKworCWZvciAoaSA9IDA7IGkgPCBE SVZfUk9VTkRfVVAoZHJtX3JlY3RfaGVpZ2h0KCZkYW1hZ2UpLCBsaW5lcyk7IGkrKykgeworCQlz dHJ1Y3QgZHJtX3JlY3QgcmVjdCA9IGRhbWFnZTsKKworCQlyZWN0LnkxICs9IGkgKiBsaW5lczsK KwkJcmVjdC55MiA9IG1pbl90KHUzMiwgcmVjdC55MSArIGxpbmVzLCBkYW1hZ2UueTIpOworCisJ CXJldCA9IGd1ZF9mbHVzaF9yZWN0KGdkcm0sIGZiLCBmb3JtYXQsICZyZWN0KTsKKwkJaWYgKHJl dCkgeworCQkJaWYgKHJldCAhPSAtRU5PREVWICYmIHJldCAhPSAtRUNPTk5SRVNFVCAmJgorCQkJ ICAgIHJldCAhPSAtRVNIVVRET1dOICYmIHJldCAhPSAtRVBST1RPKSB7CisJCQkJZ3VkX3JldHJ5 X2ZhaWxlZF9mbHVzaChnZHJtLCBmYiwgJmRhbWFnZSk7CisJCQkJZGV2X2Vycl9vbmNlKGZiLT5k ZXYtPmRldiwKKwkJCQkJICAgICAiRmFpbGVkIHRvIGZsdXNoIGZyYW1lYnVmZmVyOiBlcnJvcj0l ZFxuIiwgcmV0KTsKKwkJCX0KKwkJCWJyZWFrOworCQl9CisKKwkJZ2RybS0+cHJldl9mbHVzaF9m YWlsZWQgPSBmYWxzZTsKKwl9CisKKwlkcm1fZnJhbWVidWZmZXJfcHV0KGZiKTsKK291dDoKKwlk cm1fZGV2X2V4aXQoaWR4KTsKK30KKworc3RhdGljIHZvaWQgZ3VkX2ZiX3F1ZXVlX2RhbWFnZShz dHJ1Y3QgZ3VkX2RldmljZSAqZ2RybSwgc3RydWN0IGRybV9mcmFtZWJ1ZmZlciAqZmIsCisJCQkJ c3RydWN0IGRybV9yZWN0ICpkYW1hZ2UpCit7CisJc3RydWN0IGRybV9mcmFtZWJ1ZmZlciAqb2xk X2ZiID0gTlVMTDsKKworCW11dGV4X2xvY2soJmdkcm0tPmRhbWFnZV9sb2NrKTsKKworCWlmIChm YiAhPSBnZHJtLT5mYikgeworCQlvbGRfZmIgPSBnZHJtLT5mYjsKKwkJZHJtX2ZyYW1lYnVmZmVy X2dldChmYik7CisJCWdkcm0tPmZiID0gZmI7CisJfQorCisJZ3VkX2FkZF9kYW1hZ2UoZ2RybSwg ZGFtYWdlKTsKKworCW11dGV4X3VubG9jaygmZ2RybS0+ZGFtYWdlX2xvY2spOworCisJcXVldWVf d29yayhzeXN0ZW1fbG9uZ193cSwgJmdkcm0tPndvcmspOworCisJaWYgKG9sZF9mYikKKwkJZHJt X2ZyYW1lYnVmZmVyX3B1dChvbGRfZmIpOworfQorCitpbnQgZ3VkX3BpcGVfY2hlY2soc3RydWN0 IGRybV9zaW1wbGVfZGlzcGxheV9waXBlICpwaXBlLAorCQkgICBzdHJ1Y3QgZHJtX3BsYW5lX3N0 YXRlICpuZXdfcGxhbmVfc3RhdGUsCisJCSAgIHN0cnVjdCBkcm1fY3J0Y19zdGF0ZSAqbmV3X2Ny dGNfc3RhdGUpCit7CisJc3RydWN0IGd1ZF9kZXZpY2UgKmdkcm0gPSB0b19ndWRfZGV2aWNlKHBp cGUtPmNydGMuZGV2KTsKKwlzdHJ1Y3QgZHJtX3BsYW5lX3N0YXRlICpvbGRfcGxhbmVfc3RhdGUg PSBwaXBlLT5wbGFuZS5zdGF0ZTsKKwljb25zdCBzdHJ1Y3QgZHJtX2Rpc3BsYXlfbW9kZSAqbW9k ZSA9ICZuZXdfY3J0Y19zdGF0ZS0+bW9kZTsKKwlzdHJ1Y3QgZHJtX2F0b21pY19zdGF0ZSAqc3Rh dGUgPSBuZXdfcGxhbmVfc3RhdGUtPnN0YXRlOworCXN0cnVjdCBkcm1fZnJhbWVidWZmZXIgKm9s ZF9mYiA9IG9sZF9wbGFuZV9zdGF0ZS0+ZmI7CisJc3RydWN0IGRybV9jb25uZWN0b3Jfc3RhdGUg KmNvbm5lY3Rvcl9zdGF0ZSA9IE5VTEw7CisJc3RydWN0IGRybV9mcmFtZWJ1ZmZlciAqZmIgPSBu ZXdfcGxhbmVfc3RhdGUtPmZiOworCWNvbnN0IHN0cnVjdCBkcm1fZm9ybWF0X2luZm8gKmZvcm1h dCA9IGZiLT5mb3JtYXQ7CisJc3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvcjsKKwlpbnQg aWR4LCByZXQsIG51bV9wcm9wZXJ0aWVzOworCXN0cnVjdCBndWRfc3RhdGVfcmVxICpyZXE7CisJ dW5zaWduZWQgaW50IGk7CisJc2l6ZV90IGxlbjsKKworCWlmIChXQVJOX09OX09OQ0UoIWZiKSkK KwkJcmV0dXJuIC1FSU5WQUw7CisKKwlpZiAob2xkX3BsYW5lX3N0YXRlLT5yb3RhdGlvbiAhPSBu ZXdfcGxhbmVfc3RhdGUtPnJvdGF0aW9uKQorCQluZXdfY3J0Y19zdGF0ZS0+bW9kZV9jaGFuZ2Vk ID0gdHJ1ZTsKKworCWlmIChvbGRfZmIgJiYgb2xkX2ZiLT5mb3JtYXQgIT0gZm9ybWF0KQorCQlu ZXdfY3J0Y19zdGF0ZS0+bW9kZV9jaGFuZ2VkID0gdHJ1ZTsKKworCWlmICghbmV3X2NydGNfc3Rh dGUtPm1vZGVfY2hhbmdlZCAmJiAhbmV3X2NydGNfc3RhdGUtPmNvbm5lY3RvcnNfY2hhbmdlZCkK KwkJcmV0dXJuIDA7CisKKwkvKiBPbmx5IG9uZSBjb25uZWN0b3IgaXMgc3VwcG9ydGVkICovCisJ aWYgKGh3ZWlnaHQzMihuZXdfY3J0Y19zdGF0ZS0+Y29ubmVjdG9yX21hc2spICE9IDEpCisJCXJl dHVybiAtRUlOVkFMOworCisJaWYgKGZvcm1hdC0+Zm9ybWF0ID09IERSTV9GT1JNQVRfWFJHQjg4 ODggJiYgZ2RybS0+eHJnYjg4ODhfZW11bGF0aW9uX2Zvcm1hdCkKKwkJZm9ybWF0ID0gZ2RybS0+ eHJnYjg4ODhfZW11bGF0aW9uX2Zvcm1hdDsKKworCWZvcl9lYWNoX25ld19jb25uZWN0b3JfaW5f c3RhdGUoc3RhdGUsIGNvbm5lY3RvciwgY29ubmVjdG9yX3N0YXRlLCBpKSB7CisJCWlmIChjb25u ZWN0b3Jfc3RhdGUtPmNydGMpCisJCQlicmVhazsKKwl9CisKKwlpZiAoV0FSTl9PTl9PTkNFKCFj b25uZWN0b3Jfc3RhdGUpKQorCQlyZXR1cm4gLUVOT0VOVDsKKworCW51bV9wcm9wZXJ0aWVzID0g Z3VkX2Nvbm5lY3Rvcl9maWxsX3Byb3BlcnRpZXMoY29ubmVjdG9yLCBOVUxMLCBOVUxMKTsKKwlp ZiAobnVtX3Byb3BlcnRpZXMgPCAwKQorCQlyZXR1cm4gbnVtX3Byb3BlcnRpZXM7CisKKwludW1f cHJvcGVydGllcyArPSBnZHJtLT5udW1fcHJvcGVydGllczsKKworCWxlbiA9IHN0cnVjdF9zaXpl KHJlcSwgcHJvcGVydGllcywgbnVtX3Byb3BlcnRpZXMpOworCXJlcSA9IGt6YWxsb2MobGVuLCBH RlBfS0VSTkVMKTsKKwlpZiAoIXJlcSkKKwkJcmV0dXJuIC1FTk9NRU07CisKKwlndWRfZnJvbV9k aXNwbGF5X21vZGUoJnJlcS0+bW9kZSwgbW9kZSk7CisKKwlyZXEtPmZvcm1hdCA9IGd1ZF9mcm9t X2ZvdXJjYyhmb3JtYXQtPmZvcm1hdCk7CisJaWYgKFdBUk5fT05fT05DRSghcmVxLT5mb3JtYXQp KQorCQlyZXR1cm4gLUVJTlZBTDsKKworCXJlcS0+Y29ubmVjdG9yID0gZHJtX2Nvbm5lY3Rvcl9p bmRleChjb25uZWN0b3IpOworCXJlcS0+bnVtX3Byb3BlcnRpZXMgPSBudW1fcHJvcGVydGllczsK KworCW51bV9wcm9wZXJ0aWVzID0gZ3VkX2Nvbm5lY3Rvcl9maWxsX3Byb3BlcnRpZXMoY29ubmVj dG9yLCBjb25uZWN0b3Jfc3RhdGUsCisJCQkJCQkgICAgICAgcmVxLT5wcm9wZXJ0aWVzKTsKKwor CWZvciAoaSA9IDA7IGkgPCBnZHJtLT5udW1fcHJvcGVydGllczsgaSsrKSB7CisJCXUxNiBwcm9w ID0gZ2RybS0+cHJvcGVydGllc1tpXTsKKwkJdTY0IHZhbDsKKworCQlzd2l0Y2ggKHByb3ApIHsK KwkJY2FzZSBHVURfUFJPUEVSVFlfUk9UQVRJT046CisJCQkvKiBEUk0gVUFQSSBtYXRjaGVzIHRo ZSBwcm90b2NvbCBzbyB1c2UgdmFsdWUgZGlyZWN0bHkgKi8KKwkJCXZhbCA9IG5ld19wbGFuZV9z dGF0ZS0+cm90YXRpb247CisJCQlicmVhazsKKwkJZGVmYXVsdDoKKwkJCVdBUk5fT05fT05DRSgx KTsKKwkJCXJldCA9IC1FSU5WQUw7CisJCQlnb3RvIG91dDsKKwkJfQorCisJCXJlcS0+cHJvcGVy dGllc1tudW1fcHJvcGVydGllcyArIGldLnByb3AgPSBjcHVfdG9fbGUxNihwcm9wKTsKKwkJcmVx LT5wcm9wZXJ0aWVzW251bV9wcm9wZXJ0aWVzICsgaV0udmFsID0gY3B1X3RvX2xlNjQodmFsKTsK Kwl9CisKKwlpZiAoZHJtX2Rldl9lbnRlcihmYi0+ZGV2LCAmaWR4KSkgeworCQlyZXQgPSBndWRf dXNiX3NldChnZHJtLCBHVURfUkVRX1NFVF9TVEFURV9DSEVDSywgMCwgcmVxLCBsZW4pOworCQlk cm1fZGV2X2V4aXQoaWR4KTsKKwl9ICBlbHNlIHsKKwkJcmV0ID0gLUVOT0RFVjsKKwl9CitvdXQ6 CisJa2ZyZWUocmVxKTsKKworCXJldHVybiByZXQ7Cit9CisKK3ZvaWQgZ3VkX3BpcGVfdXBkYXRl KHN0cnVjdCBkcm1fc2ltcGxlX2Rpc3BsYXlfcGlwZSAqcGlwZSwKKwkJICAgICBzdHJ1Y3QgZHJt X3BsYW5lX3N0YXRlICpvbGRfc3RhdGUpCit7CisJc3RydWN0IGRybV9kZXZpY2UgKmRybSA9IHBp cGUtPmNydGMuZGV2OworCXN0cnVjdCBndWRfZGV2aWNlICpnZHJtID0gdG9fZ3VkX2RldmljZShk cm0pOworCXN0cnVjdCBkcm1fcGxhbmVfc3RhdGUgKnN0YXRlID0gcGlwZS0+cGxhbmUuc3RhdGU7 CisJc3RydWN0IGRybV9mcmFtZWJ1ZmZlciAqZmIgPSBzdGF0ZS0+ZmI7CisJc3RydWN0IGRybV9j cnRjICpjcnRjID0gJnBpcGUtPmNydGM7CisJc3RydWN0IGRybV9yZWN0IGRhbWFnZTsKKwlpbnQg aWR4OworCisJaWYgKGNydGMtPnN0YXRlLT5tb2RlX2NoYW5nZWQgfHwgIWNydGMtPnN0YXRlLT5l bmFibGUpIHsKKwkJY2FuY2VsX3dvcmtfc3luYygmZ2RybS0+d29yayk7CisJCW11dGV4X2xvY2so Jmdkcm0tPmRhbWFnZV9sb2NrKTsKKwkJaWYgKGdkcm0tPmZiKSB7CisJCQlkcm1fZnJhbWVidWZm ZXJfcHV0KGdkcm0tPmZiKTsKKwkJCWdkcm0tPmZiID0gTlVMTDsKKwkJfQorCQlndWRfY2xlYXJf ZGFtYWdlKGdkcm0pOworCQltdXRleF91bmxvY2soJmdkcm0tPmRhbWFnZV9sb2NrKTsKKwl9CisK KwlpZiAoIWRybV9kZXZfZW50ZXIoZHJtLCAmaWR4KSkKKwkJcmV0dXJuOworCisJaWYgKCFvbGRf c3RhdGUtPmZiKQorCQlndWRfdXNiX3dyaXRlOChnZHJtLCBHVURfUkVRX1NFVF9DT05UUk9MTEVS X0VOQUJMRSwgMSk7CisKKwlpZiAoZmIgJiYgKGNydGMtPnN0YXRlLT5tb2RlX2NoYW5nZWQgfHwg Y3J0Yy0+c3RhdGUtPmNvbm5lY3RvcnNfY2hhbmdlZCkpCisJCWd1ZF91c2Jfc2V0KGdkcm0sIEdV RF9SRVFfU0VUX1NUQVRFX0NPTU1JVCwgMCwgTlVMTCwgMCk7CisKKwlpZiAoY3J0Yy0+c3RhdGUt PmFjdGl2ZV9jaGFuZ2VkKQorCQlndWRfdXNiX3dyaXRlOChnZHJtLCBHVURfUkVRX1NFVF9ESVNQ TEFZX0VOQUJMRSwgY3J0Yy0+c3RhdGUtPmFjdGl2ZSk7CisKKwlpZiAoZHJtX2F0b21pY19oZWxw ZXJfZGFtYWdlX21lcmdlZChvbGRfc3RhdGUsIHN0YXRlLCAmZGFtYWdlKSkgeworCQlpZiAoZ2Ry bS0+ZmxhZ3MgJiBHVURfRElTUExBWV9GTEFHX0ZVTExfVVBEQVRFKQorCQkJZHJtX3JlY3RfaW5p dCgmZGFtYWdlLCAwLCAwLCBmYi0+d2lkdGgsIGZiLT5oZWlnaHQpOworCQlndWRfZmJfcXVldWVf ZGFtYWdlKGdkcm0sIGZiLCAmZGFtYWdlKTsKKwl9CisKKwlpZiAoIWNydGMtPnN0YXRlLT5lbmFi bGUpCisJCWd1ZF91c2Jfd3JpdGU4KGdkcm0sIEdVRF9SRVFfU0VUX0NPTlRST0xMRVJfRU5BQkxF LCAwKTsKKworCWRybV9kZXZfZXhpdChpZHgpOworfQpkaWZmIC0tZ2l0IGEvaW5jbHVkZS9kcm0v Z3VkLmggYi9pbmNsdWRlL2RybS9ndWQuaApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAw MDAwMDAwMDAuLmViZjE5ZjUwZjc4MAotLS0gL2Rldi9udWxsCisrKyBiL2luY2x1ZGUvZHJtL2d1 ZC5oCkBAIC0wLDAgKzEsMzU2IEBACisvKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUICov CisvKgorICogQ29weXJpZ2h0IDIwMjAgTm9yYWxmIFRyw7hubmVzCisgKi8KKworI2lmbmRlZiBf X0xJTlVYX0dVRF9ICisjZGVmaW5lIF9fTElOVVhfR1VEX0gKKworI2luY2x1ZGUgPGxpbnV4L3R5 cGVzLmg+CisKKy8qCisgKiBzdHJ1Y3QgZ3VkX2Rpc3BsYXlfZGVzY3JpcHRvcl9yZXEgLSBEaXNw bGF5IGRlc2NyaXB0b3IKKyAqIEBtYWdpYzogTWFnaWMgdmFsdWUgR1VEX0RJU1BMQVlfTUFHSUMK KyAqIEB2ZXJzaW9uOiBQcm90b2NvbCB2ZXJzaW9uCisgKiBAZmxhZ3M6IEZsYWdzCisgKiAgICAg ICAgIC0gU1RBVFVTX09OX1NFVDogQWx3YXlzIGRvIGEgc3RhdHVzIHJlcXVlc3QgYWZ0ZXIgYSBT RVQgcmVxdWVzdC4KKyAqICAgICAgICAgICAgICAgICAgICAgICAgICBUaGlzIGlzIHVzZWQgYnkg dGhlIExpbnV4IGdhZGdldCBkcml2ZXIgc2luY2UgaXQgaGFzCisgKiAgICAgICAgICAgICAgICAg ICAgICAgICAgbm8gd2F5IHRvIGNvbnRyb2wgdGhlIHN0YXR1cyBzdGFnZSBvZiBhIGNvbnRyb2wg T1VUCisgKiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdCB0aGF0IGhhcyBhIHBheWxv YWQuCisgKiAgICAgICAgIC0gRlVMTF9VUERBVEU6ICAgQWx3YXlzIHNlbmQgdGhlIGVudGlyZSBm cmFtZWJ1ZmZlciB3aGVuIGZsdXNoaW5nIGNoYW5nZXMuCisgKiAgICAgICAgICAgICAgICAgICAg ICAgICAgVGhlIEdVRF9SRVFfU0VUX0JVRkZFUiByZXF1ZXN0IHdpbGwgbm90IGJlIHNlbnQKKyAq ICAgICAgICAgICAgICAgICAgICAgICAgICBiZWZvcmUgZWFjaCBidWxrIHRyYW5zZmVyLCBpdCB3 aWxsIG9ubHkgYmUgc2VudCBpZiB0aGUKKyAqICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2 aW91cyBidWxrIHRyYW5zZmVyIGhhZCBmYWlsZWQuIFRoaXMgZ2l2ZXMgdGhlIGRldmljZQorICog ICAgICAgICAgICAgICAgICAgICAgICAgIGEgY2hhbmNlIHRvIHJlc2V0IGl0cyBzdGF0ZSBtYWNo aW5lIGlmIG5lZWRlZC4KKyAqICAgICAgICAgICAgICAgICAgICAgICAgICBUaGlzIGZsYWcgY2Fu IG5vdCBiZSB1c2VkIGluIGNvbWJpbmF0aW9uIHdpdGggY29tcHJlc3Npb24uCisgKiBAY29tcHJl c3Npb246IFN1cHBvcnRlZCBjb21wcmVzc2lvbiB0eXBlcworICogICAgICAgICAgICAgICAtIEdV RF9DT01QUkVTU0lPTl9MWjQ6IExaNCBsb3NzbGVzcyBjb21wcmVzc2lvbi4KKyAqIEBtYXhfYnVm ZmVyX3NpemU6IE1heGltdW0gYnVmZmVyIHNpemUgdGhlIGRldmljZSBjYW4gaGFuZGxlIChvcHRp b25hbCkuCisgKiAgICAgICAgICAgICAgICAgICBUaGlzIGlzIHVzZWZ1bCBmb3IgZGV2aWNlcyB0 aGF0IGRvbid0IGhhdmUgYSBiaWcgZW5vdWdoCisgKiAgICAgICAgICAgICAgICAgICBidWZmZXIg dG8gZGVjb21wcmVzcyB0aGUgZW50aXJlIGZyYW1lYnVmZmVyIGluIG9uZSBnby4KKyAqIEBtaW5f d2lkdGg6IE1pbmltdW0gcGl4ZWwgd2lkdGggdGhlIGNvbnRyb2xsZXIgY2FuIGhhbmRsZQorICog QG1heF93aWR0aDogTWF4aW11bSB3aWR0aAorICogQG1pbl9oZWlnaHQ6IE1pbmltdW0gaGVpZ2h0 CisgKiBAbWF4X2hlaWdodDogTWF4aW11bSBoZWlnaHQKKyAqIEBudW1fZm9ybWF0czogTnVtYmVy IG9mIHN1cHBvcnRlZCBwaXhlbCBmb3JtYXRzCisgKiBAbnVtX3Byb3BlcnRpZXM6IE51bWJlciBv ZiBwcm9wZXJ0aWVzIHRoYXQgYXJlIG5vdCBjb25uZWN0b3IgcHJvcGVydGllcworICogQG51bV9j b25uZWN0b3JzOiBOdW1iZXIgb2YgY29ubmVjdG9ycworICoKKyAqIERldmljZXMgdGhhdCBoYXZl IG9ubHkgb25lIGRpc3BsYXkgbW9kZSB3aWxsIGhhdmUgbWluX3dpZHRoID09IG1heF93aWR0aAor ICogYW5kIG1pbl9oZWlnaHQgPT0gbWF4X2hlaWdodC4KKyAqLworc3RydWN0IGd1ZF9kaXNwbGF5 X2Rlc2NyaXB0b3JfcmVxIHsKKwlfX3UzMiBtYWdpYzsKKyNkZWZpbmUgR1VEX0RJU1BMQVlfTUFH SUMJCQkweDFkNTA2MTRkCisJX191OCB2ZXJzaW9uOworCV9fbGUzMiBmbGFnczsKKyNkZWZpbmUg R1VEX0RJU1BMQVlfRkxBR19TVEFUVVNfT05fU0VUCQlCSVQoMCkKKyNkZWZpbmUgR1VEX0RJU1BM QVlfRkxBR19GVUxMX1VQREFURQkJQklUKDEpCisJX191OCBjb21wcmVzc2lvbjsKKyNkZWZpbmUg R1VEX0NPTVBSRVNTSU9OX0xaNAkJCUJJVCgwKQorCV9fbGUzMiBtYXhfYnVmZmVyX3NpemU7CisJ X19sZTMyIG1pbl93aWR0aDsKKwlfX2xlMzIgbWF4X3dpZHRoOworCV9fbGUzMiBtaW5faGVpZ2h0 OworCV9fbGUzMiBtYXhfaGVpZ2h0OworCV9fdTggbnVtX2Zvcm1hdHM7CisJX191OCBudW1fcHJv cGVydGllczsKKwlfX3U4IG51bV9jb25uZWN0b3JzOworfSBfX3BhY2tlZDsKKworLyoKKyAqIHN0 cnVjdCBndWRfcHJvcGVydHlfcmVxIC0gUHJvcGVydHkKKyAqIEBwcm9wOiBQcm9wZXJ0eQorICog QHZhbDogVmFsdWUKKyAqLworc3RydWN0IGd1ZF9wcm9wZXJ0eV9yZXEgeworCV9fbGUxNiBwcm9w OworCV9fbGU2NCB2YWw7Cit9IF9fcGFja2VkOworCisvKgorICogc3RydWN0IGd1ZF9kaXNwbGF5 X21vZGVfcmVxIC0gRGlzcGxheSBtb2RlCisgKiBAY2xvY2s6IFBpeGVsIGNsb2NrIGluIGtIegor ICogQGhkaXNwbGF5OiBIb3Jpem9udGFsIGRpc3BsYXkgc2l6ZQorICogQGhzeW5jX3N0YXJ0OiBI b3Jpem9udGFsIHN5bmMgc3RhcnQKKyAqIEBoc3luY19lbmQ6IEhvcml6b250YWwgc3luYyBlbmQK KyAqIEBodG90YWw6IEhvcml6b250YWwgdG90YWwgc2l6ZQorICogQHZkaXNwbGF5OiBWZXJ0aWNh bCBkaXNwbGF5IHNpemUKKyAqIEB2c3luY19zdGFydDogVmVydGljYWwgc3luYyBzdGFydAorICog QHZzeW5jX2VuZDogVmVydGljYWwgc3luYyBlbmQKKyAqIEB2dG90YWw6IFZlcnRpY2FsIHRvdGFs IHNpemUKKyAqIEBmbGFnczogQml0cyAwLTEzIGFyZSB0aGUgc2FtZSBhcyBpbiB0aGUgUmFuZFIg cHJvdG9jb2wgYW5kIGFsc28gd2hhdCBEUk0gdXNlcy4KKyAqICAgICAgICAgVGhlIGRlcHJlY2F0 ZWQgYml0cyBhcmUgcmV1c2VkIGZvciBpbnRlcm5hbCBwcm90b2NvbCBmbGFncyBsZWF2aW5nIHVz CisgKiAgICAgICAgIGZyZWUgdG8gZm9sbG93IERSTSBmb3IgdGhlIG90aGVyIGJpdHMgaW4gdGhl IGZ1dHVyZS4KKyAqICAgICAgICAgLSBGTEFHX1BSRUZFUlJFRDogU2V0IG9uIHRoZSBwcmVmZXJy ZWQgZGlzcGxheSBtb2RlLgorICovCitzdHJ1Y3QgZ3VkX2Rpc3BsYXlfbW9kZV9yZXEgeworCV9f bGUzMiBjbG9jazsKKwlfX2xlMTYgaGRpc3BsYXk7CisJX19sZTE2IGhzeW5jX3N0YXJ0OworCV9f bGUxNiBoc3luY19lbmQ7CisJX19sZTE2IGh0b3RhbDsKKwlfX2xlMTYgdmRpc3BsYXk7CisJX19s ZTE2IHZzeW5jX3N0YXJ0OworCV9fbGUxNiB2c3luY19lbmQ7CisJX19sZTE2IHZ0b3RhbDsKKwlf X2xlMzIgZmxhZ3M7CisjZGVmaW5lIEdVRF9ESVNQTEFZX01PREVfRkxBR19QSFNZTkMJCUJJVCgw KQorI2RlZmluZSBHVURfRElTUExBWV9NT0RFX0ZMQUdfTkhTWU5DCQlCSVQoMSkKKyNkZWZpbmUg R1VEX0RJU1BMQVlfTU9ERV9GTEFHX1BWU1lOQwkJQklUKDIpCisjZGVmaW5lIEdVRF9ESVNQTEFZ X01PREVfRkxBR19OVlNZTkMJCUJJVCgzKQorI2RlZmluZSBHVURfRElTUExBWV9NT0RFX0ZMQUdf SU5URVJMQUNFCQlCSVQoNCkKKyNkZWZpbmUgR1VEX0RJU1BMQVlfTU9ERV9GTEFHX0RCTFNDQU4J CUJJVCg1KQorI2RlZmluZSBHVURfRElTUExBWV9NT0RFX0ZMQUdfQ1NZTkMJCUJJVCg2KQorI2Rl ZmluZSBHVURfRElTUExBWV9NT0RFX0ZMQUdfUENTWU5DCQlCSVQoNykKKyNkZWZpbmUgR1VEX0RJ U1BMQVlfTU9ERV9GTEFHX05DU1lOQwkJQklUKDgpCisjZGVmaW5lIEdVRF9ESVNQTEFZX01PREVf RkxBR19IU0tFVwkJQklUKDkpCisvKiBCQ2FzdCBhbmQgUGl4ZWxNdWx0aXBsZXggYXJlIGRlcHJl Y2F0ZWQgKi8KKyNkZWZpbmUgR1VEX0RJU1BMQVlfTU9ERV9GTEFHX0RCTENMSwkJQklUKDEyKQor I2RlZmluZSBHVURfRElTUExBWV9NT0RFX0ZMQUdfQ0xLRElWMgkJQklUKDEzKQorI2RlZmluZSBH VURfRElTUExBWV9NT0RFX0ZMQUdfVVNFUl9NQVNLCQlcCisJCShHVURfRElTUExBWV9NT0RFX0ZM QUdfUEhTWU5DIHwgR1VEX0RJU1BMQVlfTU9ERV9GTEFHX05IU1lOQyB8IFwKKwkJR1VEX0RJU1BM QVlfTU9ERV9GTEFHX1BWU1lOQyB8IEdVRF9ESVNQTEFZX01PREVfRkxBR19OVlNZTkMgfCBcCisJ CUdVRF9ESVNQTEFZX01PREVfRkxBR19JTlRFUkxBQ0UgfCBHVURfRElTUExBWV9NT0RFX0ZMQUdf REJMU0NBTiB8IFwKKwkJR1VEX0RJU1BMQVlfTU9ERV9GTEFHX0NTWU5DIHwgR1VEX0RJU1BMQVlf TU9ERV9GTEFHX1BDU1lOQyB8IFwKKwkJR1VEX0RJU1BMQVlfTU9ERV9GTEFHX05DU1lOQyB8IEdV RF9ESVNQTEFZX01PREVfRkxBR19IU0tFVyB8IFwKKwkJR1VEX0RJU1BMQVlfTU9ERV9GTEFHX0RC TENMSyB8IEdVRF9ESVNQTEFZX01PREVfRkxBR19DTEtESVYyKQorLyogSW50ZXJuYWwgcHJvdG9j b2wgZmxhZ3MgKi8KKyNkZWZpbmUgR1VEX0RJU1BMQVlfTU9ERV9GTEFHX1BSRUZFUlJFRAkJQklU KDEwKQorfSBfX3BhY2tlZDsKKworLyoKKyAqIHN0cnVjdCBndWRfY29ubmVjdG9yX2Rlc2NyaXB0 b3JfcmVxIC0gQ29ubmVjdG9yIGRlc2NyaXB0b3IKKyAqIEBjb25uZWN0b3JfdHlwZTogQ29ubmVj dG9yIHR5cGUgKEdVRF9DT05ORUNUT1JfVFlQRV8qKS4KKyAqICAgICAgICAgICAgICAgICAgSWYg dGhlIGhvc3QgZG9lc24ndCBzdXBwb3J0IHRoZSB0eXBlIGl0IHNob3VsZCBmYWxsIGJhY2sgdG8g UEFORUwuCisgKiBAZmxhZ3M6IEZsYWdzCisgKiAgICAgICAgIC0gUE9MTF9TVEFUVVM6IENvbm5l Y3RvciBzdGF0dXMgY2FuIGNoYW5nZSAocG9sbGVkIGV2ZXJ5IDEwIHNlY29uZHMpCisgKiAgICAg ICAgIC0gSU5URVJMQUNFOiBJbnRlcmxhY2VkIG1vZGVzIGFyZSBzdXBwb3J0ZWQKKyAqICAgICAg ICAgLSBET1VCTEVTQ0FOOiBEb3VibGVzY2FuIG1vZGVzIGFyZSBzdXBwb3J0ZWQKKyAqIEBudW1f cHJvcGVydGllczogTnVtYmVyIG9mIHN1cHBvcnRlZCBwcm9wZXJ0aWVzCisgKi8KK3N0cnVjdCBn dWRfY29ubmVjdG9yX2Rlc2NyaXB0b3JfcmVxIHsKKwlfX3U4IGNvbm5lY3Rvcl90eXBlOworI2Rl ZmluZSBHVURfQ09OTkVDVE9SX1RZUEVfUEFORUwJCTAKKyNkZWZpbmUgR1VEX0NPTk5FQ1RPUl9U WVBFX1ZHQQkJCTEKKyNkZWZpbmUgR1VEX0NPTk5FQ1RPUl9UWVBFX0NPTVBPU0lURQkJMgorI2Rl ZmluZSBHVURfQ09OTkVDVE9SX1RZUEVfU1ZJREVPCQkzCisjZGVmaW5lIEdVRF9DT05ORUNUT1Jf VFlQRV9DT01QT05FTlQJCTQKKyNkZWZpbmUgR1VEX0NPTk5FQ1RPUl9UWVBFX0RWSQkJCTUKKyNk ZWZpbmUgR1VEX0NPTk5FQ1RPUl9UWVBFX0RJU1BMQVlQT1JUCQk2CisjZGVmaW5lIEdVRF9DT05O RUNUT1JfVFlQRV9IRE1JCQkJNworCV9fbGUzMiBmbGFnczsKKyNkZWZpbmUgR1VEX0NPTk5FQ1RP Ul9GTEFHU19QT0xMX1NUQVRVUwkJQklUKDApCisjZGVmaW5lIEdVRF9DT05ORUNUT1JfRkxBR1Nf SU5URVJMQUNFCQlCSVQoMSkKKyNkZWZpbmUgR1VEX0NPTk5FQ1RPUl9GTEFHU19ET1VCTEVTQ0FO CQlCSVQoMikKKwlfX3U4IG51bV9wcm9wZXJ0aWVzOworfSBfX3BhY2tlZDsKKworLyoKKyAqIHN0 cnVjdCBndWRfY29ubmVjdG9yX3N0YXR1c19yZXEgLSBDb25uZWN0b3Igc3RhdHVzCisgKiBAc3Rh dHVzOiBTdGF0dXMKKyAqICAgICAgICAgIC0gRElTQ09OTkVDVEVEOiBDb25uZWN0b3IgaXMgZGlz Y29ubmVjdGVkCisgKiAgICAgICAgICAtIENPTk5FQ1RFRDogQ29ubmVjdG9yIGlzIGNvbm5lY3Rl ZAorICogICAgICAgICAgLSBVTktOT1dOOiBDb25uZWN0aW9uIHN0YXR1cyBpcyB1bmtub3duCisg KiAgICAgICAgICBGbGFnczoKKyAqICAgICAgICAgIC0gQ0hBTkdFRDogQSBjaGFuZ2UgaGFzIGhh cHBlbmVkIHNpbmNlIHRoZSBsYXN0IHJlcXVlc3QKKyAqIEBudW1fbW9kZXM6IE51bWJlciBvZiBh dmFpbGFibGUgZGlzcGxheSBtb2RlcworICogQGVkaWRfbGVuOiBMZW5ndGggb2YgRURJRCBkYXRh CisgKgorICogSWYgQG51bV9tb2RlcyBpcyB6ZXJvLCBFRElEIGlzIHVzZWQgdG8gY3JlYXRlIGRp c3BsYXkgbW9kZXMuCisgKiBJZiBib3RoIEBudW1fbW9kZXMgYW5kIEBlZGlkX2xlbiBhcmUgc2V0 LCBFRElEIGlzIGp1c3QgcGFzc2VkIG9uIHRvIHVzZXJzcGFjZQorICogaW4gdGhlIEVESUQgY29u bmVjdG9yIHByb3BlcnR5LgorICoKKyAqIFVzZXJzcGFjZSB3aWxsIGdldCBhIEhPVFBMVUcgdWV2 ZW50IGlmIG9uZSBvZiB0aGUgZm9sbG93aW5nIGlzIHRydWU6CisgKiAtIENvbm5lY3Rpb24gc3Rh dHVzIGhhcyBjaGFuZ2VkCisgKiAtIEBudW1fbW9kZXMgb3IgQGVkaWRfbGVuIGhhcyBjaGFuZ2Vk CisgKiAtIENIQU5HRUQgaXMgc2V0CisgKi8KK3N0cnVjdCBndWRfY29ubmVjdG9yX3N0YXR1c19y ZXEgeworCV9fdTggc3RhdHVzOworI2RlZmluZSBHVURfQ09OTkVDVE9SX1NUQVRVU19ESVNDT05O RUNURUQJMHgwMAorI2RlZmluZSBHVURfQ09OTkVDVE9SX1NUQVRVU19DT05ORUNURUQJCTB4MDEK KyNkZWZpbmUgR1VEX0NPTk5FQ1RPUl9TVEFUVVNfVU5LTk9XTgkJMHgwMgorI2RlZmluZSBHVURf Q09OTkVDVE9SX1NUQVRVU19DT05ORUNURURfTUFTSwkweDAzCisjZGVmaW5lIEdVRF9DT05ORUNU T1JfU1RBVFVTX0NIQU5HRUQJCUJJVCg3KQorCV9fbGUxNiBudW1fbW9kZXM7CisJX19sZTE2IGVk aWRfbGVuOworfSBfX3BhY2tlZDsKKworLyoKKyAqIHN0cnVjdCBndWRfc2V0X2J1ZmZlcl9yZXEg LSBTZXQgYnVmZmVyIHRyYW5zZmVyIGluZm8KKyAqIEB4OiBYIHBvc2l0aW9uIG9mIHJlY3Rhbmds ZQorICogQHk6IFkgcG9zaXRpb24KKyAqIEB3aWR0aDogUGl4ZWwgd2lkdGggb2YgcmVjdGFuZ2xl CisgKiBAaGVpZ2h0OiBQaXhlbCBoZWlnaHQKKyAqIEBsZW5ndGg6IEJ1ZmZlciBsZW5ndGggaW4g Ynl0ZXMKKyAqIEBjb21wcmVzc2lvbjogVHJhbnNmZXIgY29tcHJlc3Npb24KKyAqIEBjb21wcmVz c2VkX2xlbmd0aDogQ29tcHJlc3NlZCBidWZmZXIgbGVuZ3RoCisgKgorICogVGhpcyByZXF1ZXN0 IGlzIGlzc3VlZCByaWdodCBiZWZvcmUgdGhlIGJ1bGsgdHJhbnNmZXIuCisgKiBAeCwgQHksIEB3 aWR0aCBhbmQgQGhlaWdodCBzcGVjaWZpZXMgdGhlIHJlY3RhbmdsZSB3aGVyZSB0aGUgYnVmZmVy IHNob3VsZCBiZQorICogcGxhY2VkIGluc2lkZSB0aGUgZnJhbWVidWZmZXIuCisgKi8KK3N0cnVj dCBndWRfc2V0X2J1ZmZlcl9yZXEgeworCV9fbGUzMiB4OworCV9fbGUzMiB5OworCV9fbGUzMiB3 aWR0aDsKKwlfX2xlMzIgaGVpZ2h0OworCV9fbGUzMiBsZW5ndGg7CisJX191OCBjb21wcmVzc2lv bjsKKwlfX2xlMzIgY29tcHJlc3NlZF9sZW5ndGg7Cit9IF9fcGFja2VkOworCisvKgorICogc3Ry dWN0IGd1ZF9zdGF0ZV9yZXEgLSBEaXNwbGF5IHN0YXRlCisgKiBAbW9kZTogRGlzcGxheSBtb2Rl CisgKiBAZm9ybWF0OiBQaXhlbCBmb3JtYXQgR1VEX1BJWEVMX0ZPUk1BVF8qCisgKiBAY29ubmVj dG9yOiBDb25uZWN0b3IgaW5kZXgKKyAqIEBudW1fcHJvcGVydGllczogTnVtYmVyIG9mIHByb3Bl cnRpZXMgaW4gdGhlIHN0YXRlCisgKiBAcHJvcGVydGllczogQXJyYXkgb2YgcHJvcGVydGllcwor ICoKKyAqIFRoZSBlbnRpcmUgc3RhdGUgaXMgdHJhbnNmZXJyZWQgZWFjaCB0aW1lIHRoZXJlJ3Mg YSBjaGFuZ2UuCisgKi8KK3N0cnVjdCBndWRfc3RhdGVfcmVxIHsKKwlzdHJ1Y3QgZ3VkX2Rpc3Bs YXlfbW9kZV9yZXEgbW9kZTsKKwlfX3U4IGZvcm1hdDsKKwlfX3U4IGNvbm5lY3RvcjsKKwlfX3U4 IG51bV9wcm9wZXJ0aWVzOworCXN0cnVjdCBndWRfcHJvcGVydHlfcmVxIHByb3BlcnRpZXNbXTsK K30gX19wYWNrZWQ7CisKKy8qIExpc3Qgb2Ygc3VwcG9ydGVkIGNvbm5lY3RvciBwcm9wZXJ0aWVz OiAqLworCisvKiBNYXJnaW5zIGluIHBpeGVscyB0byBkZWFsIHdpdGggb3ZlcnNjYW4sIHJhbmdl IDAtMTAwICovCisjZGVmaW5lIEdVRF9QUk9QRVJUWV9UVl9MRUZUX01BUkdJTgkJCTEKKyNkZWZp bmUgR1VEX1BST1BFUlRZX1RWX1JJR0hUX01BUkdJTgkJCTIKKyNkZWZpbmUgR1VEX1BST1BFUlRZ X1RWX1RPUF9NQVJHSU4JCQkzCisjZGVmaW5lIEdVRF9QUk9QRVJUWV9UVl9CT1RUT01fTUFSR0lO CQkJNAorLyogTnVtYmVyIG9mIG1vZGVzIGFyZSBwbGFjZWQgYXQgX1NISUZUIGluIHZhbCBvbiBy ZXRyaWV2YWwgKi8KKyNkZWZpbmUgR1VEX1BST1BFUlRZX1RWX01PREUJCQkJNQorICAjZGVmaW5l IEdVRF9DT05ORUNUT1JfVFZfTU9ERV9OVU1fU0hJRlQJMTYKKy8qIEJyaWdodG5lc3MgaW4gcGVy Y2VudCwgcmFuZ2UgMC0xMDAgKi8KKyNkZWZpbmUgR1VEX1BST1BFUlRZX1RWX0JSSUdIVE5FU1MJ CQk2CisvKiBDb250cmFzdCBpbiBwZXJjZW50LCByYW5nZSAwLTEwMCAqLworI2RlZmluZSBHVURf UFJPUEVSVFlfVFZfQ09OVFJBU1QJCQk3CisvKiBGbGlja2VyIHJlZHVjdGlvbiBpbiBwZXJjZW50 LCByYW5nZSAwLTEwMCAqLworI2RlZmluZSBHVURfUFJPUEVSVFlfVFZfRkxJQ0tFUl9SRURVQ1RJ T04JCTgKKy8qIE92ZXJzY2FuIGluIHBlcmNlbnQsIHJhbmdlIDAtMTAwICovCisjZGVmaW5lIEdV RF9QUk9QRVJUWV9UVl9PVkVSU0NBTgkJCTkKKy8qIFNhdHVyYXRpb24gaW4gcGVyY2VudCwgcmFu Z2UgMC0xMDAgKi8KKyNkZWZpbmUgR1VEX1BST1BFUlRZX1RWX1NBVFVSQVRJT04JCQkxMAorLyog SHVlIGluIHBlcmNlbnQsIHJhbmdlIDAtMTAwICovCisjZGVmaW5lIEdVRF9QUk9QRVJUWV9UVl9I VUUJCQkJMTEKKworLyoKKyAqIEJhY2tsaWdodCBicmlnaHRuZXNzIGlzIGluIHRoZSByYW5nZSAw LTEwMCBpbmNsdXNpdmUuIFRoZSB2YWx1ZSByZXByZXNlbnRzIHRoZSBodW1hbiBwZXJjZXB0dWFs CisgKiBicmlnaHRuZXNzIGFuZCBub3QgYSBsaW5lYXIgUFdNIHZhbHVlLiAwIGlzIG1pbmltdW0g YnJpZ2h0bmVzcyB3aGljaCBzaG91bGQgbm90IHR1cm4gdGhlCisgKiBiYWNrbGlnaHQgY29tcGxl dGVseSBvZmYuIFRoZSBEUE1TIGNvbm5lY3RvciBwcm9wZXJ0eSBzaG91bGQgYmUgdXNlZCB0byBj b250cm9sIHBvd2VyIHdoaWNoIHdpbGwKKyAqIHRyaWdnZXIgYSBHVURfUkVRX1NFVF9ESVNQTEFZ X0VOQUJMRSByZXF1ZXN0LgorICoKKyAqIFRoaXMgZG9lcyBub3QgbWFwIHRvIGEgRFJNIHByb3Bl cnR5LCBpdCBpcyB1c2VkIHdpdGggdGhlIGJhY2tsaWdodCBkZXZpY2UuCisgKi8KKyNkZWZpbmUg R1VEX1BST1BFUlRZX0JBQ0tMSUdIVF9CUklHSFRORVNTCQkxMgorCisvKiBMaXN0IG9mIHN1cHBv cnRlZCBwcm9wZXJ0aWVzIHRoYXQgYXJlIG5vdCBjb25uZWN0b3IgcHJvcGV0aWVzOiAqLworCisv KgorICogUGxhbmUgcm90YXRpb24uIFNob3VsZCByZXR1cm4gdGhlIHN1cHBvcnRlZCBiaXRtYXNr IG9uCisgKiBHVURfUkVRX0dFVF9QUk9QRVJUSUVTLiBHVURfUk9UQVRJT05fMCBpcyBtYW5kYXRv cnkuCisgKgorICogTm90ZTogVGhpcyBpcyBub3QgZGlzcGxheSByb3RhdGlvbiBzbyA5MC8yNzAg d2lsbCBuZWVkIHNjYWxpbmcgdG8gbWFrZSBpdCBmaXQgKHVubGVzcyBzcXVhcmVkKS4KKyAqLwor I2RlZmluZSBHVURfUFJPUEVSVFlfUk9UQVRJT04JCQkJNTAKKyAgI2RlZmluZSBHVURfUk9UQVRJ T05fMAkJCUJJVCgwKQorICAjZGVmaW5lIEdVRF9ST1RBVElPTl85MAkJCUJJVCgxKQorICAjZGVm aW5lIEdVRF9ST1RBVElPTl8xODAJCQlCSVQoMikKKyAgI2RlZmluZSBHVURfUk9UQVRJT05fMjcw CQkJQklUKDMpCisgICNkZWZpbmUgR1VEX1JPVEFUSU9OX1JFRkxFQ1RfWAkJQklUKDQpCisgICNk ZWZpbmUgR1VEX1JPVEFUSU9OX1JFRkxFQ1RfWQkJQklUKDUpCisgICNkZWZpbmUgR1VEX1JPVEFU SU9OX01BU0sJCQkoR1VEX1JPVEFUSU9OXzAgfCBHVURfUk9UQVRJT05fOTAgfCBcCisJCQkJCQlH VURfUk9UQVRJT05fMTgwIHwgR1VEX1JPVEFUSU9OXzI3MCB8IFwKKwkJCQkJCUdVRF9ST1RBVElP Tl9SRUZMRUNUX1ggfCBHVURfUk9UQVRJT05fUkVGTEVDVF9ZKQorCisvKiBVU0IgQ29udHJvbCBy ZXF1ZXN0czogKi8KKworLyogR2V0IHN0YXR1cyBmcm9tIHRoZSBsYXN0IEdFVC9TRVQgY29udHJv bCByZXF1ZXN0LiBWYWx1ZSBpcyB1OC4gKi8KKyNkZWZpbmUgR1VEX1JFUV9HRVRfU1RBVFVTCQkJ CTB4MDAKKyAgLyogU3RhdHVzIHZhbHVlczogKi8KKyAgI2RlZmluZSBHVURfU1RBVFVTX09LCQkJ CTB4MDAKKyAgI2RlZmluZSBHVURfU1RBVFVTX0JVU1kJCQkweDAxCisgICNkZWZpbmUgR1VEX1NU QVRVU19SRVFVRVNUX05PVF9TVVBQT1JURUQJMHgwMgorICAjZGVmaW5lIEdVRF9TVEFUVVNfUFJP VE9DT0xfRVJST1IJCTB4MDMKKyAgI2RlZmluZSBHVURfU1RBVFVTX0lOVkFMSURfUEFSQU1FVEVS CQkweDA0CisgICNkZWZpbmUgR1VEX1NUQVRVU19FUlJPUgkJCTB4MDUKKworLyogR2V0IGRpc3Bs YXkgZGVzY3JpcHRvciBhcyBhICZndWRfZGlzcGxheV9kZXNjcmlwdG9yX3JlcSAqLworI2RlZmlu ZSBHVURfUkVRX0dFVF9ERVNDUklQVE9SCQkJCTB4MDEKKworLyoKKyAqIElmIHRoZSBob3N0IGRy aXZlciBkb2Vzbid0IHN1cHBvcnQgdGhlIGRldmljZSBwcm90b2NvbCB2ZXJzaW9uIGl0IHdpbGwg c2VuZCB0aGUgdmVyc2lvbnMgaXQKKyAqIHN1cHBvcnRzIHN0YXJ0aW5nIHdpdGggdGhlIGxhdGVz dC4gSWYgdGhlIGRldmljZSBpc24ndCBiYWNrd2FyZHMgY29tcGF0aWJsZSBvciBkb2Vzbid0IHN1 cHBvcnQKKyAqIHRoZSB2ZXJzaW9uIHRoZSBob3N0IHN1Z2dlc3RzLCBpdCBzaGFsbCBzdGFsbCB0 aGUgcmVxdWVzdC4gVGhlIHZlcnNpb24gaXMgc2VudCBhcyB1OC4KKyAqLworI2RlZmluZSBHVURf UkVRX1NFVF9WRVJTSU9OCQkJCTB4MzAKKworLyogR2V0IHN1cHBvcnRlZCBwaXhlbCBmb3JtYXRz IGFzIGEgYnl0ZSBhcnJheSBvZiBHVURfUElYRUxfRk9STUFUXyogKi8KKyNkZWZpbmUgR1VEX1JF UV9HRVRfRk9STUFUUwkJCQkweDQwCisgIC8qIFIxIGlzIGEgMS1iaXQgbW9ub2Nocm9tZSB0cmFu c2ZlciBmb3JtYXQgcHJlc2VudGVkIHRvIHVzZXJzcGFjZSBhcyBYUkdCODg4OCAqLworICAjZGVm aW5lIEdVRF9QSVhFTF9GT1JNQVRfUjEJCQkweDAxCisgICNkZWZpbmUgR1VEX1BJWEVMX0ZPUk1B VF9SR0I1NjUJCTB4NDAKKyAgI2RlZmluZSBHVURfUElYRUxfRk9STUFUX1hSR0I4ODg4CQkweDgw CisgICNkZWZpbmUgR1VEX1BJWEVMX0ZPUk1BVF9BUkdCODg4OAkJMHg4MQorCisvKgorICogR2V0 IHN1cHBvcnRlZCBwcm9wZXJ0aWVzIHRoYXQgYXJlIG5vdCBjb25uZWN0b3IgcHJvcGV0aWVzIGFz IGEgJmd1ZF9wcm9wZXJ0eV9yZXEgYXJyYXkuCisgKiBndWRfcHJvcGVydHlfcmVxLnZhbCBvZnRl biBjb250YWlucyB0aGUgaW5pdGlhbCB2YWx1ZSBmb3IgdGhlIHByb3BlcnR5LgorICovCisjZGVm aW5lIEdVRF9SRVFfR0VUX1BST1BFUlRJRVMJCQkJMHg0MQorCisvKiBDb25uZWN0b3IgcmVxdWVz dHMgaGF2ZSB0aGUgY29ubmVjdG9yIGluZGV4IHBhc3NlZCBpbiB0aGUgd1ZhbHVlIGZpZWxkICov CisKKy8qIEdldCBjb25uZWN0b3IgZGVzY3JpcHRvciBhcyBhICZndWRfY29ubmVjdG9yX2Rlc2Ny aXB0b3JfcmVxICovCisjZGVmaW5lIEdVRF9SRVFfR0VUX0NPTk5FQ1RPUgkJCQkweDUwCisKKy8q CisgKiBHZXQgcHJvcGVydGllcyBzdXBwb3J0ZWQgYnkgdGhlIGNvbm5lY3RvciBhcyBhICZndWRf cHJvcGVydHlfcmVxIGFycmF5LgorICogZ3VkX3Byb3BlcnR5X3JlcS52YWwgb2Z0ZW4gY29udGFp bnMgdGhlIGluaXRpYWwgdmFsdWUgZm9yIHRoZSBwcm9wZXJ0eS4KKyAqLworI2RlZmluZSBHVURf UkVRX0dFVF9DT05ORUNUT1JfUFJPUEVSVElFUwkJMHg1MQorCisvKgorICogSXNzdWVkIHdoZW4g dGhlcmUncyBhIFRWX01PREUgcHJvcGVydHkgcHJlc2VudC4KKyAqIEdldHMgYW4gYXJyYXkgb2Yg dGhlIHN1cHBvcnRlZCBUVl9NT0RFIG5hbWVzIGVhY2ggZW50cnkgb2YgbGVuZ3RoCisgKiBHVURf Q09OTkVDVE9SX1RWX01PREVfTkFNRV9MRU4uIE5hbWVzIG11c3QgYmUgTlVMLXRlcm1pbmF0ZWQu CisgKi8KKyNkZWZpbmUgR1VEX1JFUV9HRVRfQ09OTkVDVE9SX1RWX01PREVfVkFMVUVTCQkweDUy CisgICNkZWZpbmUgR1VEX0NPTk5FQ1RPUl9UVl9NT0RFX05BTUVfTEVOCTE2CisKKy8qIFdoZW4g dXNlcnNwYWNlIGNoZWNrcyBjb25uZWN0b3Igc3RhdHVzLCB0aGlzIGlzIGlzc3VlZCBmaXJzdCwg bm90IHVzZWQgZm9yIHBvbGwgcmVxdWVzdHMuICovCisjZGVmaW5lIEdVRF9SRVFfU0VUX0NPTk5F Q1RPUl9GT1JDRV9ERVRFQ1QJCTB4NTMKKworLyogR2V0IGNvbm5lY3RvciBzdGF0dXMgYXMgJmd1 ZF9jb25uZWN0b3Jfc3RhdHVzX3JlcS4gKi8KKyNkZWZpbmUgR1VEX1JFUV9HRVRfQ09OTkVDVE9S X1NUQVRVUwkJCTB4NTQKKworLyogR2V0ICZndWRfZGlzcGxheV9tb2RlX3JlcSBhcnJheSBvZiBz dXBwb3J0ZWQgZGlzcGxheSBtb2RlcyAqLworI2RlZmluZSBHVURfUkVRX0dFVF9DT05ORUNUT1Jf TU9ERVMJCQkweDU1CisKKy8qIEdldCBFeHRlbmRlZCBEaXNwbGF5IElkZW50aWZpY2F0aW9uIERh dGEgKi8KKyNkZWZpbmUgR1VEX1JFUV9HRVRfQ09OTkVDVE9SX0VESUQJCQkweDU2CisKKy8qIFNl dCBidWZmZXIgcHJvcGVydGllcyBiZWZvcmUgYnVsayB0cmFuc2ZlciBhcyAmZ3VkX3NldF9idWZm ZXJfcmVxICovCisjZGVmaW5lIEdVRF9SRVFfU0VUX0JVRkZFUgkJCQkweDYwCisKKy8qIENoZWNr IGRpc3BsYXkgY29uZmlndXJhdGlvbiBhcyAmZ3VkX3N0YXRlX3JlcSAqLworI2RlZmluZSBHVURf UkVRX1NFVF9TVEFURV9DSEVDSwkJCQkweDYxCisKKy8qIEFwcGx5IHRoZSBwcmV2aW91cyBTVEFU RV9DSEVDSyBjb25maWd1cmF0aW9uICovCisjZGVmaW5lIEdVRF9SRVFfU0VUX1NUQVRFX0NPTU1J VAkJCTB4NjIKKworLyogRW5hYmxlL2Rpc2FibGUgdGhlIGRpc3BsYXkgY29udHJvbGxlciwgdmFs dWUgaXMgdTg6IDAvMSAqLworI2RlZmluZSBHVURfUkVRX1NFVF9DT05UUk9MTEVSX0VOQUJMRQkJ CTB4NjMKKworLyogRW5hYmxlL2Rpc2FibGUgZGlzcGxheS9vdXRwdXQgKERQTVMpLCB2YWx1ZSBp cyB1ODogMC8xICovCisjZGVmaW5lIEdVRF9SRVFfU0VUX0RJU1BMQVlfRU5BQkxFCQkJMHg2NAor CisjZW5kaWYKLS0gCjIuMjMuMAoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX18KZHJpLWRldmVsIG1haWxpbmcgbGlzdApkcmktZGV2ZWxAbGlzdHMuZnJlZWRl c2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8v ZHJpLWRldmVsCg==