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=-15.1 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 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 85516C433DB for ; Sun, 24 Jan 2021 16:19:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4E55A229F0 for ; Sun, 24 Jan 2021 16:19:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726442AbhAXQTF (ORCPT ); Sun, 24 Jan 2021 11:19:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42402 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726344AbhAXQTD (ORCPT ); Sun, 24 Jan 2021 11:19:03 -0500 Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B05ACC061573 for ; Sun, 24 Jan 2021 08:18:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org ; s=ds202012; h=Content-Transfer-Encoding:Content-Type:In-Reply-To: MIME-Version:Date:Message-ID:From:References:Cc:To:Subject:Sender:Reply-To: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=R/e/wQACrTuY60ofCuTTcu9boTWoCwco1UOGZQjtRQI=; b=gvjC/yIdgGbkKapLceDPRKb9pe SbK6H4spolAe6YgCmqlFfqp52BjkA3pIMsNOp+ufEMvWWiYbP1ZURmVQVKFVP/HRZXk6VATFUNBl0 to4It2m24I2eIeCwEkyG5FGXAPLkmgTc/DdmjchMxoc1m/qz4tdVw+wo6qm/p2yATSpgSefyqIKeT Z/oLdXtAn4SV5KJuKHFyQzYEkXdx506LMIcnn+iHvvOaI8RF7+I0rCzPF6AZ+3n5Be53hplDA6du4 Lb6mk0FliYehsXmHeEqRotUOIHQJrh+SRA+UVRz+AMI7Hm2NNdKWqlk2oJem2lKgysY81zstkXjvU YISc2ddA==; Received: from [2a01:799:95f:4600:a14b:28a5:23ac:14a3] (port=58261) by smtp.domeneshop.no with esmtpsa (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1l3i5Q-0000hZ-2L; Sun, 24 Jan 2021 17:18:00 +0100 Subject: Re: [PATCH v4 3/3] drm: Add Generic USB Display driver To: Daniel Vetter Cc: dri-devel , hudson@trmm.net, markus@raatikainen.cc, Sam Ravnborg , USB list , Tyler Hardin , Lubomir Rintel , pontus.fuchs@gmail.com, peter@stuge.se References: <20210120170033.38468-1-noralf@tronnes.org> <20210120170033.38468-4-noralf@tronnes.org> From: =?UTF-8?Q?Noralf_Tr=c3=b8nnes?= Message-ID: Date: Sun, 24 Jan 2021 17:17:54 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.6.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Den 20.01.2021 19.02, skrev Daniel Vetter: > On Wed, Jan 20, 2021 at 6:11 PM Noralf Trønnes wrote: >> >> 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 > > I think the backlight is still a bit problematic, since you're using > kms locks within the backlight callbacks. Other display drivers use > backlight within their kms locks. This means inconsistent locking > rules, which upsets lockdep. > > Since you're already handling brightness as a special case in many > places I don't think it's a big shuffle: > - add a mutex to the connector struct > - move brightness value to connector struct, out of the connector_state > - use the new mutex to protect backlight state both from modeset side > (if needed, I'm not entirely sure about that) and the backlight side > It's not enough to store the value I need to send it to the device as well. Currently I send the entire state each time there's a change. To continue that I would need to keep a copy of the state that I can use when brightness changes. Or I can treat backlight as an exception and add a USB control request just for backlight. There is some special treatment of the backlight in the driver, but I would really like to handle the backlight brightness through the atomic machinery. I want to avoid special treatment of backlight in the USB protocol. I can avoid the lockdep problem by letting a worker commit the state and schedule it from the backlight update callback. I'll do that unless you see other issues with that approach. Is it ok to take the connection_mutex lock in the get_brightness callback to get to the connector state and the brightness value? i915 takes that lock in intel_backlight_device_update_status() and intel_backlight_device_get_brightness(). > Some more things below, but in general I'd say Acked-by: Daniel Vetter > fwiw (probably not so much). > Thanks for taking a look, much appreciated. Noralf. >> 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); > > Would be nice to do that with drmm_, but we don't have the > drmm_connector_alloc wrapper yet. > >> + 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); >> +} 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=-15.1 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 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 92BFFC433E0 for ; Sun, 24 Jan 2021 16:18:08 +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 F0C41229F0 for ; Sun, 24 Jan 2021 16:18:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F0C41229F0 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 D3E1A89EAC; Sun, 24 Jan 2021 16:18:06 +0000 (UTC) Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 10E2E89EAC for ; Sun, 24 Jan 2021 16:18:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tronnes.org ; s=ds202012; h=Content-Transfer-Encoding:Content-Type:In-Reply-To: MIME-Version:Date:Message-ID:From:References:Cc:To:Subject:Sender:Reply-To: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=R/e/wQACrTuY60ofCuTTcu9boTWoCwco1UOGZQjtRQI=; b=gvjC/yIdgGbkKapLceDPRKb9pe SbK6H4spolAe6YgCmqlFfqp52BjkA3pIMsNOp+ufEMvWWiYbP1ZURmVQVKFVP/HRZXk6VATFUNBl0 to4It2m24I2eIeCwEkyG5FGXAPLkmgTc/DdmjchMxoc1m/qz4tdVw+wo6qm/p2yATSpgSefyqIKeT Z/oLdXtAn4SV5KJuKHFyQzYEkXdx506LMIcnn+iHvvOaI8RF7+I0rCzPF6AZ+3n5Be53hplDA6du4 Lb6mk0FliYehsXmHeEqRotUOIHQJrh+SRA+UVRz+AMI7Hm2NNdKWqlk2oJem2lKgysY81zstkXjvU YISc2ddA==; Received: from [2a01:799:95f:4600:a14b:28a5:23ac:14a3] (port=58261) by smtp.domeneshop.no with esmtpsa (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1l3i5Q-0000hZ-2L; Sun, 24 Jan 2021 17:18:00 +0100 Subject: Re: [PATCH v4 3/3] drm: Add Generic USB Display driver To: Daniel Vetter References: <20210120170033.38468-1-noralf@tronnes.org> <20210120170033.38468-4-noralf@tronnes.org> From: =?UTF-8?Q?Noralf_Tr=c3=b8nnes?= Message-ID: Date: Sun, 24 Jan 2021 17:17:54 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.6.1 MIME-Version: 1.0 In-Reply-To: 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, peter@stuge.se, USB list , dri-devel , Tyler Hardin , Lubomir Rintel , pontus.fuchs@gmail.com, Sam Ravnborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" CgpEZW4gMjAuMDEuMjAyMSAxOS4wMiwgc2tyZXYgRGFuaWVsIFZldHRlcjoKPiBPbiBXZWQsIEph biAyMCwgMjAyMSBhdCA2OjExIFBNIE5vcmFsZiBUcsO4bm5lcyA8bm9yYWxmQHRyb25uZXMub3Jn PiB3cm90ZToKPj4KPj4gVGhpcyBhZGRzIGEgZ2VuZXJpYyBVU0IgZGlzcGxheSBkcml2ZXIgd2l0 aCB0aGUgaW50ZW50aW9uIHRoYXQgaXQgY2FuIGJlCj4+IHVzZWQgd2l0aCBmdXR1cmUgVVNCIGlu dGVyZmFjZWQgbG93IGVuZCBkaXNwbGF5cy9hZGFwdGVycy4gVGhlIExpbnV4Cj4+IGdhZGdldCBk ZXZpY2UgZHJpdmVyIHdpbGwgc2VydmUgYXMgdGhlIGNhbm9uaWNhbCBkZXZpY2UgaW1wbGVtZW50 YXRpb24uCj4+Cj4+IFRoZSBmb2xsb3dpbmcgRFJNIHByb3BlcnRpZXMgYXJlIHN1cHBvcnRlZDoK Pj4gLSBQbGFuZSByb3RhdGlvbgo+PiAtIENvbm5lY3RvciBUViBwcm9wZXJ0aWVzCj4+Cj4+IFRo ZXJlIGlzIGFsc28gc3VwcG9ydCBmb3IgYmFja2xpZ2h0IGJyaWdodG5lc3MgZXhwb3NlZCBhcyBh IGJhY2tsaWdodAo+PiBkZXZpY2UuCj4+Cj4+IERpc3BsYXkgbW9kZXMgY2FuIGJlIG1hZGUgYXZh aWxhYmxlIHRvIHRoZSBob3N0IGRyaXZlciBlaXRoZXIgYXMgRFJNCj4+IGRpc3BsYXkgbW9kZXMg b3IgdGhyb3VnaCBFRElELiBJZiBib3RoIGFyZSBwcmVzZW50LCBFRElEIGlzIGp1c3QgcGFzc2Vk Cj4+IG9uIHRvIHVzZXJzcGFjZS4KPj4KPj4gUGVyZm9ybWFuY2UgaXMgcHJlZmVycmVkIG92ZXIg Y29sb3IgZGVwdGgsIHNvIGlmIHRoZSBkZXZpY2Ugc3VwcG9ydHMKPj4gUkdCNTY1LCBEUk1fQ0FQ X0RVTUJfUFJFRkVSUkVEX0RFUFRIIHdpbGwgcmV0dXJuIDE2Lgo+Pgo+PiBJZiB0aGUgZGV2aWNl IHRyYW5zZmVyIGJ1ZmZlciBjYW4ndCBmaXQgYW4gdW5jb21wcmVzc2VkIGZyYW1lYnVmZmVyCj4+ IHVwZGF0ZSwgdGhlIHVwZGF0ZSBpcyBzcGxpdCB1cCBpbnRvIHBhcnRzIHRoYXQgZG8gZml0Lgo+ Pgo+PiBPcHRpbWFsIHVzZXIgZXhwZXJpZW5jZSBpcyBhY2hpZXZlZCBieSBwcm92aWRpbmcgZGFt YWdlIHJlcG9ydHMgZWl0aGVyIGJ5Cj4+IHNldHRpbmcgRkJfREFNQUdFX0NMSVBTIG9uIHBhZ2Vm bGlwcyBvciBjYWxsaW5nIERSTV9JT0NUTF9NT0RFX0RJUlRZRkIuCj4+Cj4+IExaNCBjb21wcmVz c2lvbiBpcyB1c2VkIGlmIHRoZSBkZXZpY2Ugc3VwcG9ydHMgaXQuCj4+Cj4+IFRoZSBkcml2ZXIg c3VwcG9ydHMgYSBvbmUgYml0IG1vbm9jaHJvbWUgdHJhbnNmZXIgZm9ybWF0OiBSMS4gVGhpcyBp cyBub3QKPj4gaW1wbGVtZW50ZWQgaW4gdGhlIGdhZGdldCBkcml2ZXIuIEl0IGlzIGFkZGVkIGlu IHByZXBhcmF0aW9uIGZvciBmdXR1cmUKPj4gbW9ub2Nocm9tZSBlLWluayBkaXNwbGF5cy4KPj4K Pj4gVGhlIGRyaXZlciBpcyBNSVQgbGljZW5zZWQgdG8gc21vb3RoIHRoZSBwYXRoIGZvciBhbnkg QlNEIHBvcnQgb2YgdGhlCj4+IGRyaXZlci4KPj4KPj4gdjI6Cj4+IC0gVXNlIGRldm1fZHJtX2Rl dl9hbGxvYygpIGFuZCBkcm1tX21vZGVfY29uZmlnX2luaXQoKQo+PiAtIGRybV9mYmRldl9nZW5l cmljX3NldHVwOiBVc2UgcHJlZmVycmVkX2JwcD0wLCAxNiB3YXMgYSBjb3B5IHBhc3RlIGVycm9y Cj4+IC0gVGhlIGRybV9iYWNrbGlnaHRfaGVscGVyIGlzIGRyb3BwZWQsIGNvcHkgaW4gdGhlIGNv ZGUKPiAKPiBJIHRoaW5rIHRoZSBiYWNrbGlnaHQgaXMgc3RpbGwgYSBiaXQgcHJvYmxlbWF0aWMs IHNpbmNlIHlvdSdyZSB1c2luZwo+IGttcyBsb2NrcyB3aXRoaW4gdGhlIGJhY2tsaWdodCBjYWxs YmFja3MuIE90aGVyIGRpc3BsYXkgZHJpdmVycyB1c2UKPiBiYWNrbGlnaHQgd2l0aGluIHRoZWly IGttcyBsb2Nrcy4gVGhpcyBtZWFucyBpbmNvbnNpc3RlbnQgbG9ja2luZwo+IHJ1bGVzLCB3aGlj aCB1cHNldHMgbG9ja2RlcC4KPiAKPiBTaW5jZSB5b3UncmUgYWxyZWFkeSBoYW5kbGluZyBicmln aHRuZXNzIGFzIGEgc3BlY2lhbCBjYXNlIGluIG1hbnkKPiBwbGFjZXMgSSBkb24ndCB0aGluayBp dCdzIGEgYmlnIHNodWZmbGU6Cj4gLSBhZGQgYSBtdXRleCB0byB0aGUgY29ubmVjdG9yIHN0cnVj dAo+IC0gbW92ZSBicmlnaHRuZXNzIHZhbHVlIHRvIGNvbm5lY3RvciBzdHJ1Y3QsIG91dCBvZiB0 aGUgY29ubmVjdG9yX3N0YXRlCj4gLSB1c2UgdGhlIG5ldyBtdXRleCB0byBwcm90ZWN0IGJhY2ts aWdodCBzdGF0ZSBib3RoIGZyb20gbW9kZXNldCBzaWRlCj4gKGlmIG5lZWRlZCwgSSdtIG5vdCBl bnRpcmVseSBzdXJlIGFib3V0IHRoYXQpIGFuZCB0aGUgYmFja2xpZ2h0IHNpZGUKPiAKCkl0J3Mg bm90IGVub3VnaCB0byBzdG9yZSB0aGUgdmFsdWUgSSBuZWVkIHRvIHNlbmQgaXQgdG8gdGhlIGRl dmljZSBhcwp3ZWxsLiBDdXJyZW50bHkgSSBzZW5kIHRoZSBlbnRpcmUgc3RhdGUgZWFjaCB0aW1l IHRoZXJlJ3MgYSBjaGFuZ2UuIFRvCmNvbnRpbnVlIHRoYXQgSSB3b3VsZCBuZWVkIHRvIGtlZXAg YSBjb3B5IG9mIHRoZSBzdGF0ZSB0aGF0IEkgY2FuIHVzZQp3aGVuIGJyaWdodG5lc3MgY2hhbmdl cy4gT3IgSSBjYW4gdHJlYXQgYmFja2xpZ2h0IGFzIGFuIGV4Y2VwdGlvbiBhbmQKYWRkIGEgVVNC IGNvbnRyb2wgcmVxdWVzdCBqdXN0IGZvciBiYWNrbGlnaHQuCgpUaGVyZSBpcyBzb21lIHNwZWNp YWwgdHJlYXRtZW50IG9mIHRoZSBiYWNrbGlnaHQgaW4gdGhlIGRyaXZlciwgYnV0IEkKd291bGQg cmVhbGx5IGxpa2UgdG8gaGFuZGxlIHRoZSBiYWNrbGlnaHQgYnJpZ2h0bmVzcyB0aHJvdWdoIHRo ZSBhdG9taWMKbWFjaGluZXJ5LiBJIHdhbnQgdG8gYXZvaWQgc3BlY2lhbCB0cmVhdG1lbnQgb2Yg YmFja2xpZ2h0IGluIHRoZSBVU0IKcHJvdG9jb2wuCgpJIGNhbiBhdm9pZCB0aGUgbG9ja2RlcCBw cm9ibGVtIGJ5IGxldHRpbmcgYSB3b3JrZXIgY29tbWl0IHRoZSBzdGF0ZSBhbmQKc2NoZWR1bGUg aXQgZnJvbSB0aGUgYmFja2xpZ2h0IHVwZGF0ZSBjYWxsYmFjay4gSSdsbCBkbyB0aGF0IHVubGVz cyB5b3UKc2VlIG90aGVyIGlzc3VlcyB3aXRoIHRoYXQgYXBwcm9hY2guCgpJcyBpdCBvayB0byB0 YWtlIHRoZSBjb25uZWN0aW9uX211dGV4IGxvY2sgaW4gdGhlIGdldF9icmlnaHRuZXNzCmNhbGxi YWNrIHRvIGdldCB0byB0aGUgY29ubmVjdG9yIHN0YXRlIGFuZCB0aGUgYnJpZ2h0bmVzcyB2YWx1 ZT8KCmk5MTUgdGFrZXMgdGhhdCBsb2NrIGluIGludGVsX2JhY2tsaWdodF9kZXZpY2VfdXBkYXRl X3N0YXR1cygpIGFuZAppbnRlbF9iYWNrbGlnaHRfZGV2aWNlX2dldF9icmlnaHRuZXNzKCkuCgo+ IFNvbWUgbW9yZSB0aGluZ3MgYmVsb3csIGJ1dCBpbiBnZW5lcmFsIEknZCBzYXkgQWNrZWQtYnk6 IERhbmllbCBWZXR0ZXIKPiA8ZGFuaWVsLnZldHRlcj4gZndpdyAocHJvYmFibHkgbm90IHNvIG11 Y2gpLgo+IAoKVGhhbmtzIGZvciB0YWtpbmcgYSBsb29rLCBtdWNoIGFwcHJlY2lhdGVkLgoKTm9y YWxmLgoKCj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vZ3VkL2d1ZF9jb25uZWN0b3Iu YyBiL2RyaXZlcnMvZ3B1L2RybS9ndWQvZ3VkX2Nvbm5lY3Rvci5jCj4+IG5ldyBmaWxlIG1vZGUg MTAwNjQ0Cj4+IGluZGV4IDAwMDAwMDAwMDAwMC4uYTRiOWJiZjQ4ZTE5Cj4+IC0tLSAvZGV2L251 bGwKPj4gKysrIGIvZHJpdmVycy9ncHUvZHJtL2d1ZC9ndWRfY29ubmVjdG9yLmMKPj4gQEAgLTAs MCArMSw3MjIgQEAKPj4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVQKPj4gKy8qCj4+ ICsgKiBDb3B5cmlnaHQgMjAyMCBOb3JhbGYgVHLDuG5uZXMKPj4gKyAqLwo+PiArCj4+ICsjaW5j bHVkZSA8bGludXgvYmFja2xpZ2h0Lmg+Cj4+ICsKPj4gKyNpbmNsdWRlIDxkcm0vZHJtX2F0b21p Yy5oPgo+PiArI2luY2x1ZGUgPGRybS9kcm1fYXRvbWljX3N0YXRlX2hlbHBlci5oPgo+PiArI2lu Y2x1ZGUgPGRybS9kcm1fY29ubmVjdG9yLmg+Cj4+ICsjaW5jbHVkZSA8ZHJtL2RybV9kcnYuaD4K Pj4gKyNpbmNsdWRlIDxkcm0vZHJtX2VuY29kZXIuaD4KPj4gKyNpbmNsdWRlIDxkcm0vZHJtX2Zp bGUuaD4KPj4gKyNpbmNsdWRlIDxkcm0vZHJtX21vZGVzZXRfaGVscGVyX3Z0YWJsZXMuaD4KPj4g KyNpbmNsdWRlIDxkcm0vZHJtX3ByaW50Lmg+Cj4+ICsjaW5jbHVkZSA8ZHJtL2RybV9wcm9iZV9o ZWxwZXIuaD4KPj4gKyNpbmNsdWRlIDxkcm0vZHJtX3NpbXBsZV9rbXNfaGVscGVyLmg+Cj4+ICsj aW5jbHVkZSA8ZHJtL2d1ZC5oPgo+PiArCj4+ICsjaW5jbHVkZSAiZ3VkX2ludGVybmFsLmgiCj4+ ICsKPj4gK3N0cnVjdCBndWRfY29ubmVjdG9yIHsKPj4gKyAgICAgICBzdHJ1Y3QgZHJtX2Nvbm5l Y3RvciBjb25uZWN0b3I7Cj4+ICsgICAgICAgc3RydWN0IGRybV9lbmNvZGVyIGVuY29kZXI7Cj4+ ICsgICAgICAgc3RydWN0IGJhY2tsaWdodF9kZXZpY2UgKmJhY2tsaWdodDsKPj4gKwo+PiArICAg ICAgIC8qIFN1cHBvcnRlZCBwcm9wZXJ0aWVzICovCj4+ICsgICAgICAgdTE2ICpwcm9wZXJ0aWVz Owo+PiArICAgICAgIHVuc2lnbmVkIGludCBudW1fcHJvcGVydGllczsKPj4gKwo+PiArICAgICAg IC8qIEluaXRpYWwgZ2FkZ2V0IHR2IHN0YXRlIGlmIGFwcGxpY2FibGUsIGFwcGxpZWQgb24gc3Rh dGUgcmVzZXQgKi8KPj4gKyAgICAgICBzdHJ1Y3QgZHJtX3R2X2Nvbm5lY3Rvcl9zdGF0ZSBpbml0 aWFsX3R2X3N0YXRlOwo+PiArCj4+ICsgICAgICAgLyoKPj4gKyAgICAgICAgKiBJbml0aWFsIGdh ZGdldCBiYWNrbGlnaHQgYnJpZ2h0bmVzcyBpZiBhcHBsaWNhYmxlLCBhcHBsaWVkIG9uIHN0YXRl IHJlc2V0Lgo+PiArICAgICAgICAqIFRoZSB2YWx1ZSAtRU5PREVWIGlzIHVzZWQgdG8gc2lnbmFs IG5vIGJhY2tsaWdodC4KPj4gKyAgICAgICAgKi8KPj4gKyAgICAgICBpbnQgaW5pdGlhbF9icmln aHRuZXNzOwo+PiArCj4+ICsgICAgICAgdW5zaWduZWQgaW50IG51bV9tb2RlczsKPj4gKyAgICAg ICBzaXplX3QgZWRpZF9sZW47Cj4+ICt9Owo+PiArCj4+ICtzdGF0aWMgaW5saW5lIHN0cnVjdCBn dWRfY29ubmVjdG9yICp0b19ndWRfY29ubmVjdG9yKHN0cnVjdCBkcm1fY29ubmVjdG9yICpjb25u ZWN0b3IpCj4+ICt7Cj4+ICsgICAgICAgcmV0dXJuIGNvbnRhaW5lcl9vZihjb25uZWN0b3IsIHN0 cnVjdCBndWRfY29ubmVjdG9yLCBjb25uZWN0b3IpOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW50 IGd1ZF9jb25uZWN0b3JfYmFja2xpZ2h0X3VwZGF0ZV9zdGF0dXMoc3RydWN0IGJhY2tsaWdodF9k ZXZpY2UgKmJkKQo+PiArewo+PiArICAgICAgIHN0cnVjdCBkcm1fY29ubmVjdG9yICpjb25uZWN0 b3IgPSBibF9nZXRfZGF0YShiZCk7Cj4+ICsgICAgICAgc3RydWN0IGRybV9jb25uZWN0b3Jfc3Rh dGUgKmNvbm5lY3Rvcl9zdGF0ZTsKPj4gKyAgICAgICBzdHJ1Y3QgZHJtX2RldmljZSAqZGV2ID0g Y29ubmVjdG9yLT5kZXY7Cj4+ICsgICAgICAgc3RydWN0IGRybV9tb2Rlc2V0X2FjcXVpcmVfY3R4 IGN0eDsKPj4gKyAgICAgICBzdHJ1Y3QgZHJtX2F0b21pY19zdGF0ZSAqc3RhdGU7Cj4+ICsgICAg ICAgaW50IHJldDsKPj4gKwo+PiArICAgICAgIHN0YXRlID0gZHJtX2F0b21pY19zdGF0ZV9hbGxv YyhkZXYpOwo+PiArICAgICAgIGlmICghc3RhdGUpCj4+ICsgICAgICAgICAgICAgICByZXR1cm4g LUVOT01FTTsKPj4gKwo+PiArICAgICAgIGRybV9tb2Rlc2V0X2FjcXVpcmVfaW5pdCgmY3R4LCAw KTsKPj4gKyAgICAgICBzdGF0ZS0+YWNxdWlyZV9jdHggPSAmY3R4Owo+PiArcmV0cnk6Cj4+ICsg ICAgICAgY29ubmVjdG9yX3N0YXRlID0gZHJtX2F0b21pY19nZXRfY29ubmVjdG9yX3N0YXRlKHN0 YXRlLCBjb25uZWN0b3IpOwo+PiArICAgICAgIGlmIChJU19FUlIoY29ubmVjdG9yX3N0YXRlKSkg ewo+PiArICAgICAgICAgICAgICAgcmV0ID0gUFRSX0VSUihjb25uZWN0b3Jfc3RhdGUpOwo+PiAr ICAgICAgICAgICAgICAgZ290byBvdXQ7Cj4+ICsgICAgICAgfQo+PiArCj4+ICsgICAgICAgLyog UmV1c2UgdHYuYnJpZ2h0bmVzcyB0byBhdm9pZCBoYXZpbmcgdG8gc3ViY2xhc3MgKi8KPj4gKyAg ICAgICBjb25uZWN0b3Jfc3RhdGUtPnR2LmJyaWdodG5lc3MgPSBiZC0+cHJvcHMuYnJpZ2h0bmVz czsKPj4gKwo+PiArICAgICAgIHJldCA9IGRybV9hdG9taWNfY29tbWl0KHN0YXRlKTsKPj4gK291 dDoKPj4gKyAgICAgICBpZiAocmV0ID09IC1FREVBRExLKSB7Cj4+ICsgICAgICAgICAgICAgICBk cm1fYXRvbWljX3N0YXRlX2NsZWFyKHN0YXRlKTsKPj4gKyAgICAgICAgICAgICAgIGRybV9tb2Rl c2V0X2JhY2tvZmYoJmN0eCk7Cj4+ICsgICAgICAgICAgICAgICBnb3RvIHJldHJ5Owo+PiArICAg ICAgIH0KPj4gKwo+PiArICAgICAgIGRybV9hdG9taWNfc3RhdGVfcHV0KHN0YXRlKTsKPj4gKwo+ PiArICAgICAgIGRybV9tb2Rlc2V0X2Ryb3BfbG9ja3MoJmN0eCk7Cj4+ICsgICAgICAgZHJtX21v ZGVzZXRfYWNxdWlyZV9maW5pKCZjdHgpOwo+PiArCj4+ICsgICAgICAgcmV0dXJuIHJldDsKPj4g K30KPj4gKwo+PiArc3RhdGljIGludCBndWRfY29ubmVjdG9yX2JhY2tsaWdodF9nZXRfYnJpZ2h0 bmVzcyhzdHJ1Y3QgYmFja2xpZ2h0X2RldmljZSAqYmQpCj4+ICt7Cj4+ICsgICAgICAgc3RydWN0 IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvciA9IGJsX2dldF9kYXRhKGJkKTsKPj4gKyAgICAgICBz dHJ1Y3QgZHJtX2RldmljZSAqZGV2ID0gY29ubmVjdG9yLT5kZXY7Cj4+ICsgICAgICAgaW50IGJy aWdodG5lc3M7Cj4+ICsKPj4gKyAgICAgICBkcm1fbW9kZXNldF9sb2NrKCZkZXYtPm1vZGVfY29u ZmlnLmNvbm5lY3Rpb25fbXV0ZXgsIE5VTEwpOwo+PiArICAgICAgIGJyaWdodG5lc3MgPSBjb25u ZWN0b3ItPnN0YXRlLT50di5icmlnaHRuZXNzOwo+PiArICAgICAgIGRybV9tb2Rlc2V0X3VubG9j aygmZGV2LT5tb2RlX2NvbmZpZy5jb25uZWN0aW9uX211dGV4KTsKPj4gKwo+PiArICAgICAgIHJl dHVybiBicmlnaHRuZXNzOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGJhY2ts aWdodF9vcHMgZ3VkX2Nvbm5lY3Rvcl9iYWNrbGlnaHRfb3BzID0gewo+PiArICAgICAgIC5nZXRf YnJpZ2h0bmVzcyA9IGd1ZF9jb25uZWN0b3JfYmFja2xpZ2h0X2dldF9icmlnaHRuZXNzLAo+PiAr ICAgICAgIC51cGRhdGVfc3RhdHVzICA9IGd1ZF9jb25uZWN0b3JfYmFja2xpZ2h0X3VwZGF0ZV9z dGF0dXMsCj4+ICt9Owo+PiArCj4+ICtzdGF0aWMgaW50IGd1ZF9jb25uZWN0b3JfYmFja2xpZ2h0 X3JlZ2lzdGVyKHN0cnVjdCBndWRfY29ubmVjdG9yICpnY29ubikKPj4gK3sKPj4gKyAgICAgICBz dHJ1Y3QgZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9yID0gJmdjb25uLT5jb25uZWN0b3I7Cj4+ICsg ICAgICAgc3RydWN0IGJhY2tsaWdodF9kZXZpY2UgKmJkOwo+PiArICAgICAgIGNvbnN0IGNoYXIg Km5hbWU7Cj4+ICsgICAgICAgY29uc3Qgc3RydWN0IGJhY2tsaWdodF9wcm9wZXJ0aWVzIHByb3Bz ID0gewo+PiArICAgICAgICAgICAgICAgLnR5cGUgPSBCQUNLTElHSFRfUkFXLAo+PiArICAgICAg ICAgICAgICAgLnNjYWxlID0gQkFDS0xJR0hUX1NDQUxFX05PTl9MSU5FQVIsCj4+ICsgICAgICAg ICAgICAgICAubWF4X2JyaWdodG5lc3MgPSAxMDAsCj4+ICsgICAgICAgfTsKPj4gKwo+PiArICAg ICAgIG5hbWUgPSBrYXNwcmludGYoR0ZQX0tFUk5FTCwgImNhcmQlZC0lcy1iYWNrbGlnaHQiLAo+ PiArICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdG9yLT5kZXYtPnByaW1hcnktPmluZGV4 LCBjb25uZWN0b3ItPm5hbWUpOwo+PiArICAgICAgIGlmICghbmFtZSkKPj4gKyAgICAgICAgICAg ICAgIHJldHVybiAtRU5PTUVNOwo+PiArCj4+ICsgICAgICAgYmQgPSBiYWNrbGlnaHRfZGV2aWNl X3JlZ2lzdGVyKG5hbWUsIGNvbm5lY3Rvci0+a2RldiwgY29ubmVjdG9yLAo+PiArICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmZ3VkX2Nvbm5lY3Rvcl9iYWNrbGlnaHRfb3Bz LCAmcHJvcHMpOwo+PiArICAgICAgIGtmcmVlKG5hbWUpOwo+PiArICAgICAgIGlmIChJU19FUlIo YmQpKQo+PiArICAgICAgICAgICAgICAgcmV0dXJuIFBUUl9FUlIoYmQpOwo+PiArCj4+ICsgICAg ICAgZ2Nvbm4tPmJhY2tsaWdodCA9IGJkOwo+PiArCj4+ICsgICAgICAgcmV0dXJuIDA7Cj4+ICt9 Cj4+ICsKPj4gK3N0YXRpYyBpbnQgZ3VkX2Nvbm5lY3Rvcl9zdGF0dXNfcmVxdWVzdChzdHJ1Y3Qg ZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9yKQo+PiArewo+PiArICAgICAgIHN0cnVjdCBndWRfY29u bmVjdG9yICpnY29ubiA9IHRvX2d1ZF9jb25uZWN0b3IoY29ubmVjdG9yKTsKPj4gKyAgICAgICBz dHJ1Y3QgZ3VkX2RldmljZSAqZ2RybSA9IHRvX2d1ZF9kZXZpY2UoY29ubmVjdG9yLT5kZXYpOwo+ PiArICAgICAgIHN0cnVjdCBndWRfY29ubmVjdG9yX3N0YXR1c19yZXEgcmVxOwo+PiArICAgICAg IHUxNiBudW1fbW9kZXMsIGVkaWRfbGVuOwo+PiArICAgICAgIGludCByZXQ7Cj4+ICsKPj4gKyAg ICAgICByZXQgPSBndWRfdXNiX2dldChnZHJtLCBHVURfUkVRX0dFVF9DT05ORUNUT1JfU1RBVFVT LAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rvci0+aW5kZXgsICZyZXEsIHNp emVvZihyZXEpKTsKPj4gKyAgICAgICBpZiAocmV0KQo+PiArICAgICAgICAgICAgICAgcmV0dXJu IHJldDsKPj4gKwo+PiArICAgICAgIHN3aXRjaCAocmVxLnN0YXR1cyAmIEdVRF9DT05ORUNUT1Jf U1RBVFVTX0NPTk5FQ1RFRF9NQVNLKSB7Cj4+ICsgICAgICAgY2FzZSBHVURfQ09OTkVDVE9SX1NU QVRVU19ESVNDT05ORUNURUQ6Cj4+ICsgICAgICAgICAgICAgICByZXQgPSBjb25uZWN0b3Jfc3Rh dHVzX2Rpc2Nvbm5lY3RlZDsKPj4gKyAgICAgICAgICAgICAgIGJyZWFrOwo+PiArICAgICAgIGNh c2UgR1VEX0NPTk5FQ1RPUl9TVEFUVVNfQ09OTkVDVEVEOgo+PiArICAgICAgICAgICAgICAgcmV0 ID0gY29ubmVjdG9yX3N0YXR1c19jb25uZWN0ZWQ7Cj4+ICsgICAgICAgICAgICAgICBicmVhazsK Pj4gKyAgICAgICBkZWZhdWx0Ogo+PiArICAgICAgICAgICAgICAgcmV0ID0gY29ubmVjdG9yX3N0 YXR1c191bmtub3duOwo+PiArICAgICAgICAgICAgICAgYnJlYWs7Cj4+ICsgICAgICAgfTsKPj4g Kwo+PiArICAgICAgIG51bV9tb2RlcyA9IGxlMTZfdG9fY3B1KHJlcS5udW1fbW9kZXMpOwo+PiAr ICAgICAgIGVkaWRfbGVuID0gbGUxNl90b19jcHUocmVxLmVkaWRfbGVuKTsKPj4gKwo+PiArICAg ICAgIGlmIChlZGlkX2xlbiAlIEVESURfTEVOR1RIKSB7Cj4+ICsgICAgICAgICAgICAgICBkcm1f ZXJyKGNvbm5lY3Rvci0+ZGV2LCAiJXM6IEludmFsaWQgRURJRCBzaXplOiAldVxuIiwgY29ubmVj dG9yLT5uYW1lLCBlZGlkX2xlbik7Cj4+ICsgICAgICAgICAgICAgICBlZGlkX2xlbiA9IDA7Cj4+ ICsgICAgICAgfQo+PiArCj4+ICsgICAgICAgaWYgKHJlcS5zdGF0dXMgJiBHVURfQ09OTkVDVE9S X1NUQVRVU19DSEFOR0VEIHx8Cj4+ICsgICAgICAgICAgIGdjb25uLT5udW1fbW9kZXMgIT0gbnVt X21vZGVzIHx8IGdjb25uLT5lZGlkX2xlbiAhPSBlZGlkX2xlbikKPj4gKyAgICAgICAgICAgICAg IGNvbm5lY3Rvci0+ZXBvY2hfY291bnRlciArPSAxOwo+PiArCj4+ICsgICAgICAgZ2Nvbm4tPm51 bV9tb2RlcyA9IG51bV9tb2RlczsKPj4gKyAgICAgICBnY29ubi0+ZWRpZF9sZW4gPSBlZGlkX2xl bjsKPj4gKwo+PiArICAgICAgIGlmICghbnVtX21vZGVzICYmICFlZGlkX2xlbiAmJiByZXQgIT0g Y29ubmVjdG9yX3N0YXR1c19kaXNjb25uZWN0ZWQpCj4+ICsgICAgICAgICAgICAgICBkcm1fZGJn X2ttcyhjb25uZWN0b3ItPmRldiwgIiVzOiBObyBtb2RlcyBvciBFRElELlxuIiwgY29ubmVjdG9y LT5uYW1lKTsKPj4gKwo+PiArICAgICAgIHJldHVybiByZXQ7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRp YyBpbnQgZ3VkX2Nvbm5lY3Rvcl9kZXRlY3Qoc3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3Rv ciwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3QgZHJtX21vZGVzZXRf YWNxdWlyZV9jdHggKmN0eCwgYm9vbCBmb3JjZSkKPj4gK3sKPj4gKyAgICAgICBzdHJ1Y3QgZ3Vk X2RldmljZSAqZ2RybSA9IHRvX2d1ZF9kZXZpY2UoY29ubmVjdG9yLT5kZXYpOwo+PiArICAgICAg IGludCBpZHgsIHJldDsKPj4gKwo+PiArICAgICAgIGlmICghZHJtX2Rldl9lbnRlcihjb25uZWN0 b3ItPmRldiwgJmlkeCkpCj4+ICsgICAgICAgICAgICAgICByZXR1cm4gY29ubmVjdG9yX3N0YXR1 c19kaXNjb25uZWN0ZWQ7Cj4+ICsKPj4gKyAgICAgICBpZiAoZm9yY2UpIHsKPj4gKyAgICAgICAg ICAgICAgIHJldCA9IGd1ZF91c2Jfc2V0KGdkcm0sIEdVRF9SRVFfU0VUX0NPTk5FQ1RPUl9GT1JD RV9ERVRFQ1QsCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25uZWN0b3It PmluZGV4LCBOVUxMLCAwKTsKPj4gKyAgICAgICAgICAgICAgIGlmIChyZXQpIHsKPj4gKyAgICAg ICAgICAgICAgICAgICAgICAgcmV0ID0gY29ubmVjdG9yX3N0YXR1c191bmtub3duOwo+PiArICAg ICAgICAgICAgICAgICAgICAgICBnb3RvIGV4aXQ7Cj4+ICsgICAgICAgICAgICAgICB9Cj4+ICsg ICAgICAgfQo+PiArCj4+ICsgICAgICAgcmV0ID0gZ3VkX2Nvbm5lY3Rvcl9zdGF0dXNfcmVxdWVz dChjb25uZWN0b3IpOwo+PiArICAgICAgIGlmIChyZXQgPCAwKQo+PiArICAgICAgICAgICAgICAg cmV0ID0gY29ubmVjdG9yX3N0YXR1c191bmtub3duOwo+PiArZXhpdDoKPj4gKyAgICAgICBkcm1f ZGV2X2V4aXQoaWR4KTsKPj4gKwo+PiArICAgICAgIHJldHVybiByZXQ7Cj4+ICt9Cj4+ICsKPj4g K3N0cnVjdCBndWRfY29ubmVjdG9yX2dldF9lZGlkX2N0eCB7Cj4+ICsgICAgICAgc3RydWN0IGd1 ZF9jb25uZWN0b3IgKmdjb25uOwo+PiArICAgICAgIHZvaWQgKmJ1ZjsKPj4gK307Cj4+ICsKPj4g K3N0YXRpYyBpbnQgZ3VkX2Nvbm5lY3Rvcl9nZXRfZWRpZF9ibG9jayh2b2lkICpkYXRhLCB1OCAq YnVmLCB1bnNpZ25lZCBpbnQgYmxvY2ssIHNpemVfdCBsZW4pCj4+ICt7Cj4+ICsgICAgICAgc3Ry dWN0IGd1ZF9jb25uZWN0b3JfZ2V0X2VkaWRfY3R4ICpjdHggPSBkYXRhOwo+PiArICAgICAgIHN0 cnVjdCBndWRfY29ubmVjdG9yICpnY29ubiA9IGN0eC0+Z2Nvbm47Cj4+ICsgICAgICAgc2l6ZV90 IHN0YXJ0ID0gYmxvY2sgKiBFRElEX0xFTkdUSDsKPj4gKwo+PiArICAgICAgIGlmIChzdGFydCAr IGxlbiA+IGdjb25uLT5lZGlkX2xlbikKPj4gKyAgICAgICAgICAgICAgIHJldHVybiAtMTsKPj4g Kwo+PiArICAgICAgIGlmICghYmxvY2spIHsKPj4gKyAgICAgICAgICAgICAgIHN0cnVjdCBndWRf ZGV2aWNlICpnZHJtID0gdG9fZ3VkX2RldmljZShnY29ubi0+Y29ubmVjdG9yLmRldik7Cj4+ICsg ICAgICAgICAgICAgICBpbnQgcmV0Owo+PiArCj4+ICsgICAgICAgICAgICAgICAvKiBDaGVjayBi ZWNhdXNlIGRybV9kb19nZXRfZWRpZCgpIHdpbGwgcmV0cnkgb24gZmFpbHVyZSAqLwo+PiArICAg ICAgICAgICAgICAgaWYgKCFjdHgtPmJ1ZikKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgY3R4 LT5idWYgPSBrbWFsbG9jKGdjb25uLT5lZGlkX2xlbiwgR0ZQX0tFUk5FTCk7Cj4+ICsgICAgICAg ICAgICAgICBpZiAoIWN0eC0+YnVmKQo+PiArICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4g LTE7Cj4+ICsKPj4gKyAgICAgICAgICAgICAgIHJldCA9IGd1ZF91c2JfZ2V0KGdkcm0sIEdVRF9S RVFfR0VUX0NPTk5FQ1RPUl9FRElELCBnY29ubi0+Y29ubmVjdG9yLmluZGV4LAo+PiArICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LT5idWYsIGdjb25uLT5lZGlkX2xlbik7Cj4+ ICsgICAgICAgICAgICAgICBpZiAocmV0KQo+PiArICAgICAgICAgICAgICAgICAgICAgICByZXR1 cm4gLTE7Cj4+ICsgICAgICAgfQo+PiArCj4+ICsgICAgICAgbWVtY3B5KGJ1ZiwgY3R4LT5idWYg KyBzdGFydCwgbGVuKTsKPj4gKwo+PiArICAgICAgIHJldHVybiAwOwo+PiArfQo+PiArCj4+ICtz dGF0aWMgaW50IGd1ZF9jb25uZWN0b3JfZ2V0X21vZGVzKHN0cnVjdCBkcm1fY29ubmVjdG9yICpj b25uZWN0b3IpCj4+ICt7Cj4+ICsgICAgICAgc3RydWN0IGd1ZF9jb25uZWN0b3IgKmdjb25uID0g dG9fZ3VkX2Nvbm5lY3Rvcihjb25uZWN0b3IpOwo+PiArICAgICAgIHN0cnVjdCBndWRfZGV2aWNl ICpnZHJtID0gdG9fZ3VkX2RldmljZShjb25uZWN0b3ItPmRldik7Cj4+ICsgICAgICAgc3RydWN0 IGd1ZF9jb25uZWN0b3JfZ2V0X2VkaWRfY3R4IGVkaWRfY3R4ID0gewo+PiArICAgICAgICAgICAg ICAgLmdjb25uID0gZ2Nvbm4sCj4+ICsgICAgICAgfTsKPj4gKyAgICAgICBzdHJ1Y3QgZ3VkX2Rp c3BsYXlfbW9kZV9yZXEgKnJlcW1vZGVzID0gTlVMTDsKPj4gKyAgICAgICB1bnNpZ25lZCBpbnQg aSwgbnVtX21vZGVzID0gMDsKPj4gKyAgICAgICBzdHJ1Y3QgZWRpZCAqZWRpZCA9IE5VTEw7Cj4+ ICsgICAgICAgYm9vbCBlZGlkX292ZXJyaWRlOwo+PiArICAgICAgIGludCBpZHgsIHJldDsKPj4g Kwo+PiArICAgICAgIGlmICghZHJtX2Rldl9lbnRlcihjb25uZWN0b3ItPmRldiwgJmlkeCkpCj4+ ICsgICAgICAgICAgICAgICByZXR1cm4gMDsKPj4gKwo+PiArICAgICAgIGlmIChjb25uZWN0b3It PmZvcmNlKSB7Cj4+ICsgICAgICAgICAgICAgICByZXQgPSBndWRfY29ubmVjdG9yX3N0YXR1c19y ZXF1ZXN0KGNvbm5lY3Rvcik7Cj4+ICsgICAgICAgICAgICAgICBpZiAocmV0IDwgMCkKPj4gKyAg ICAgICAgICAgICAgICAgICAgICAgZ290byBvdXQ7Cj4+ICsgICAgICAgfQo+PiArCj4+ICsgICAg ICAgZWRpZCA9IGRybV9kb19nZXRfZWRpZChjb25uZWN0b3IsIGd1ZF9jb25uZWN0b3JfZ2V0X2Vk aWRfYmxvY2ssICZlZGlkX2N0eCk7Cj4+ICsgICAgICAgZWRpZF9vdmVycmlkZSA9IGVkaWQgJiYg IWVkaWRfY3R4LmJ1ZjsKPj4gKyAgICAgICBrZnJlZShlZGlkX2N0eC5idWYpOwo+PiArICAgICAg IGRybV9jb25uZWN0b3JfdXBkYXRlX2VkaWRfcHJvcGVydHkoY29ubmVjdG9yLCBlZGlkKTsKPj4g Kwo+PiArICAgICAgIGlmICghZ2Nvbm4tPm51bV9tb2RlcyB8fCBlZGlkX292ZXJyaWRlKSB7Cj4+ ICsgICAgICAgICAgICAgICBudW1fbW9kZXMgPSBkcm1fYWRkX2VkaWRfbW9kZXMoY29ubmVjdG9y LCBlZGlkKTsKPj4gKyAgICAgICAgICAgICAgIGdvdG8gb3V0Owo+PiArICAgICAgIH0KPj4gKwo+ PiArICAgICAgIHJlcW1vZGVzID0ga21hbGxvY19hcnJheShnY29ubi0+bnVtX21vZGVzLCBzaXpl b2YoKnJlcW1vZGVzKSwgR0ZQX0tFUk5FTCk7Cj4+ICsgICAgICAgaWYgKCFyZXFtb2RlcykKPj4g KyAgICAgICAgICAgICAgIGdvdG8gb3V0Owo+PiArCj4+ICsgICAgICAgcmV0ID0gZ3VkX3VzYl9n ZXQoZ2RybSwgR1VEX1JFUV9HRVRfQ09OTkVDVE9SX01PREVTLCBjb25uZWN0b3ItPmluZGV4LAo+ PiArICAgICAgICAgICAgICAgICAgICAgICAgIHJlcW1vZGVzLCBnY29ubi0+bnVtX21vZGVzICog c2l6ZW9mKCpyZXFtb2RlcykpOwo+PiArICAgICAgIGlmIChyZXQpCj4+ICsgICAgICAgICAgICAg ICBnb3RvIG91dDsKPj4gKwo+PiArICAgICAgIGZvciAoaSA9IDA7IGkgPCBnY29ubi0+bnVtX21v ZGVzOyBpKyspIHsKPj4gKyAgICAgICAgICAgICAgIHN0cnVjdCBkcm1fZGlzcGxheV9tb2RlICpt b2RlOwo+PiArCj4+ICsgICAgICAgICAgICAgICBtb2RlID0gZHJtX21vZGVfY3JlYXRlKGNvbm5l Y3Rvci0+ZGV2KTsKPj4gKyAgICAgICAgICAgICAgIGlmICghbW9kZSkKPj4gKyAgICAgICAgICAg ICAgICAgICAgICAgZ290byBvdXQ7Cj4+ICsKPj4gKyAgICAgICAgICAgICAgIGd1ZF90b19kaXNw bGF5X21vZGUobW9kZSwgJnJlcW1vZGVzW2ldKTsKPj4gKyAgICAgICAgICAgICAgIGRybV9tb2Rl X3Byb2JlZF9hZGQoY29ubmVjdG9yLCBtb2RlKTsKPj4gKyAgICAgICAgICAgICAgIG51bV9tb2Rl cysrOwo+PiArICAgICAgIH0KPj4gK291dDoKPj4gKyAgICAgICBrZnJlZShyZXFtb2Rlcyk7Cj4+ ICsgICAgICAga2ZyZWUoZWRpZCk7Cj4+ICsgICAgICAgZHJtX2Rldl9leGl0KGlkeCk7Cj4+ICsK Pj4gKyAgICAgICByZXR1cm4gbnVtX21vZGVzOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW50IGd1 ZF9jb25uZWN0b3JfYXRvbWljX2NoZWNrKHN0cnVjdCBkcm1fY29ubmVjdG9yICpjb25uZWN0b3Is Cj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IGRybV9hdG9t aWNfc3RhdGUgKnN0YXRlKQo+PiArewo+PiArICAgICAgIHN0cnVjdCBkcm1fY29ubmVjdG9yX3N0 YXRlICpuZXdfc3RhdGU7Cj4+ICsgICAgICAgc3RydWN0IGRybV9jcnRjX3N0YXRlICpuZXdfY3J0 Y19zdGF0ZTsKPj4gKyAgICAgICBzdHJ1Y3QgZHJtX2Nvbm5lY3Rvcl9zdGF0ZSAqb2xkX3N0YXRl Owo+PiArCj4+ICsgICAgICAgbmV3X3N0YXRlID0gZHJtX2F0b21pY19nZXRfbmV3X2Nvbm5lY3Rv cl9zdGF0ZShzdGF0ZSwgY29ubmVjdG9yKTsKPj4gKyAgICAgICBpZiAoIW5ld19zdGF0ZS0+Y3J0 YykKPj4gKyAgICAgICAgICAgICAgIHJldHVybiAwOwo+PiArCj4+ICsgICAgICAgb2xkX3N0YXRl ID0gZHJtX2F0b21pY19nZXRfb2xkX2Nvbm5lY3Rvcl9zdGF0ZShzdGF0ZSwgY29ubmVjdG9yKTsK Pj4gKyAgICAgICBuZXdfY3J0Y19zdGF0ZSA9IGRybV9hdG9taWNfZ2V0X25ld19jcnRjX3N0YXRl KHN0YXRlLCBuZXdfc3RhdGUtPmNydGMpOwo+PiArCj4+ICsgICAgICAgaWYgKG9sZF9zdGF0ZS0+ dHYubWFyZ2lucy5sZWZ0ICE9IG5ld19zdGF0ZS0+dHYubWFyZ2lucy5sZWZ0IHx8Cj4+ICsgICAg ICAgICAgIG9sZF9zdGF0ZS0+dHYubWFyZ2lucy5yaWdodCAhPSBuZXdfc3RhdGUtPnR2Lm1hcmdp bnMucmlnaHQgfHwKPj4gKyAgICAgICAgICAgb2xkX3N0YXRlLT50di5tYXJnaW5zLnRvcCAhPSBu ZXdfc3RhdGUtPnR2Lm1hcmdpbnMudG9wIHx8Cj4+ICsgICAgICAgICAgIG9sZF9zdGF0ZS0+dHYu bWFyZ2lucy5ib3R0b20gIT0gbmV3X3N0YXRlLT50di5tYXJnaW5zLmJvdHRvbSB8fAo+PiArICAg ICAgICAgICBvbGRfc3RhdGUtPnR2Lm1vZGUgIT0gbmV3X3N0YXRlLT50di5tb2RlIHx8Cj4+ICsg ICAgICAgICAgIG9sZF9zdGF0ZS0+dHYuYnJpZ2h0bmVzcyAhPSBuZXdfc3RhdGUtPnR2LmJyaWdo dG5lc3MgfHwKPj4gKyAgICAgICAgICAgb2xkX3N0YXRlLT50di5jb250cmFzdCAhPSBuZXdfc3Rh dGUtPnR2LmNvbnRyYXN0IHx8Cj4+ICsgICAgICAgICAgIG9sZF9zdGF0ZS0+dHYuZmxpY2tlcl9y ZWR1Y3Rpb24gIT0gbmV3X3N0YXRlLT50di5mbGlja2VyX3JlZHVjdGlvbiB8fAo+PiArICAgICAg ICAgICBvbGRfc3RhdGUtPnR2Lm92ZXJzY2FuICE9IG5ld19zdGF0ZS0+dHYub3ZlcnNjYW4gfHwK Pj4gKyAgICAgICAgICAgb2xkX3N0YXRlLT50di5zYXR1cmF0aW9uICE9IG5ld19zdGF0ZS0+dHYu c2F0dXJhdGlvbiB8fAo+PiArICAgICAgICAgICBvbGRfc3RhdGUtPnR2Lmh1ZSAhPSBuZXdfc3Rh dGUtPnR2Lmh1ZSkKPj4gKyAgICAgICAgICAgICAgIG5ld19jcnRjX3N0YXRlLT5jb25uZWN0b3Jz X2NoYW5nZWQgPSB0cnVlOwo+PiArCj4+ICsgICAgICAgcmV0dXJuIDA7Cj4+ICt9Cj4+ICsKPj4g K3N0YXRpYyBjb25zdCBzdHJ1Y3QgZHJtX2Nvbm5lY3Rvcl9oZWxwZXJfZnVuY3MgZ3VkX2Nvbm5l Y3Rvcl9oZWxwZXJfZnVuY3MgPSB7Cj4+ICsgICAgICAgLmRldGVjdF9jdHggPSBndWRfY29ubmVj dG9yX2RldGVjdCwKPj4gKyAgICAgICAuZ2V0X21vZGVzID0gZ3VkX2Nvbm5lY3Rvcl9nZXRfbW9k ZXMsCj4+ICsgICAgICAgLmF0b21pY19jaGVjayA9IGd1ZF9jb25uZWN0b3JfYXRvbWljX2NoZWNr LAo+PiArfTsKPj4gKwo+PiArc3RhdGljIGludCBndWRfY29ubmVjdG9yX2xhdGVfcmVnaXN0ZXIo c3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvcikKPj4gK3sKPj4gKyAgICAgICBzdHJ1Y3Qg Z3VkX2Nvbm5lY3RvciAqZ2Nvbm4gPSB0b19ndWRfY29ubmVjdG9yKGNvbm5lY3Rvcik7Cj4+ICsK Pj4gKyAgICAgICBpZiAoZ2Nvbm4tPmluaXRpYWxfYnJpZ2h0bmVzcyA8IDApCj4+ICsgICAgICAg ICAgICAgICByZXR1cm4gMDsKPj4gKwo+PiArICAgICAgIHJldHVybiBndWRfY29ubmVjdG9yX2Jh Y2tsaWdodF9yZWdpc3RlcihnY29ubik7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyB2b2lkIGd1ZF9j b25uZWN0b3JfZWFybHlfdW5yZWdpc3RlcihzdHJ1Y3QgZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9y KQo+PiArewo+PiArICAgICAgIHN0cnVjdCBndWRfY29ubmVjdG9yICpnY29ubiA9IHRvX2d1ZF9j b25uZWN0b3IoY29ubmVjdG9yKTsKPj4gKwo+PiArICAgICAgIGJhY2tsaWdodF9kZXZpY2VfdW5y ZWdpc3RlcihnY29ubi0+YmFja2xpZ2h0KTsKPj4gK30KPj4gKwo+PiArc3RhdGljIHZvaWQgZ3Vk X2Nvbm5lY3Rvcl9kZXN0cm95KHN0cnVjdCBkcm1fY29ubmVjdG9yICpjb25uZWN0b3IpCj4+ICt7 Cj4+ICsgICAgICAgc3RydWN0IGd1ZF9jb25uZWN0b3IgKmdjb25uID0gdG9fZ3VkX2Nvbm5lY3Rv cihjb25uZWN0b3IpOwo+PiArCj4+ICsgICAgICAgZHJtX2Nvbm5lY3Rvcl9jbGVhbnVwKGNvbm5l Y3Rvcik7Cj4+ICsgICAgICAga2ZyZWUoZ2Nvbm4tPnByb3BlcnRpZXMpOwo+PiArICAgICAgIGtm cmVlKGdjb25uKTsKPj4gK30KPj4gKwo+PiArc3RhdGljIHZvaWQgZ3VkX2Nvbm5lY3Rvcl9yZXNl dChzdHJ1Y3QgZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9yKQo+PiArewo+PiArICAgICAgIHN0cnVj dCBndWRfY29ubmVjdG9yICpnY29ubiA9IHRvX2d1ZF9jb25uZWN0b3IoY29ubmVjdG9yKTsKPj4g Kwo+PiArICAgICAgIGRybV9hdG9taWNfaGVscGVyX2Nvbm5lY3Rvcl9yZXNldChjb25uZWN0b3Ip Owo+PiArICAgICAgIGNvbm5lY3Rvci0+c3RhdGUtPnR2ID0gZ2Nvbm4tPmluaXRpYWxfdHZfc3Rh dGU7Cj4+ICsgICAgICAgLyogU2V0IG1hcmdpbnMgZnJvbSBjb21tYW5kIGxpbmUgKi8KPj4gKyAg ICAgICBkcm1fYXRvbWljX2hlbHBlcl9jb25uZWN0b3JfdHZfcmVzZXQoY29ubmVjdG9yKTsKPj4g KyAgICAgICBpZiAoZ2Nvbm4tPmluaXRpYWxfYnJpZ2h0bmVzcyA+PSAwKQo+PiArICAgICAgICAg ICAgICAgY29ubmVjdG9yLT5zdGF0ZS0+dHYuYnJpZ2h0bmVzcyA9IGdjb25uLT5pbml0aWFsX2Jy aWdodG5lc3M7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZHJtX2Nvbm5lY3Rv cl9mdW5jcyBndWRfY29ubmVjdG9yX2Z1bmNzID0gewo+PiArICAgICAgIC5maWxsX21vZGVzID0g ZHJtX2hlbHBlcl9wcm9iZV9zaW5nbGVfY29ubmVjdG9yX21vZGVzLAo+PiArICAgICAgIC5sYXRl X3JlZ2lzdGVyID0gZ3VkX2Nvbm5lY3Rvcl9sYXRlX3JlZ2lzdGVyLAo+PiArICAgICAgIC5lYXJs eV91bnJlZ2lzdGVyID0gZ3VkX2Nvbm5lY3Rvcl9lYXJseV91bnJlZ2lzdGVyLAo+PiArICAgICAg IC5kZXN0cm95ID0gZ3VkX2Nvbm5lY3Rvcl9kZXN0cm95LAo+PiArICAgICAgIC5yZXNldCA9IGd1 ZF9jb25uZWN0b3JfcmVzZXQsCj4+ICsgICAgICAgLmF0b21pY19kdXBsaWNhdGVfc3RhdGUgPSBk cm1fYXRvbWljX2hlbHBlcl9jb25uZWN0b3JfZHVwbGljYXRlX3N0YXRlLAo+PiArICAgICAgIC5h dG9taWNfZGVzdHJveV9zdGF0ZSA9IGRybV9hdG9taWNfaGVscGVyX2Nvbm5lY3Rvcl9kZXN0cm95 X3N0YXRlLAo+PiArfTsKPj4gKwo+PiArLyoKPj4gKyAqIFRoZSB0di5tb2RlIHByb3BlcnR5IGlz IHNoYXJlZCBhbW9uZyB0aGUgY29ubmVjdG9ycyBhbmQgaXRzIGVudW0gbmFtZXMgYXJlCj4+ICsg KiBkcml2ZXIgc3BlY2lmaWMuIFRoaXMgbWVhbnMgdGhhdCBpZiBtb3JlIHRoYW4gb25lIGNvbm5l Y3RvciB1c2VzIHR2Lm1vZGUsCj4+ICsgKiB0aGUgZW51bSBuYW1lcyBoYXMgdG8gYmUgdGhlIHNh bWUuCj4+ICsgKi8KPj4gK3N0YXRpYyBpbnQgZ3VkX2Nvbm5lY3Rvcl9hZGRfdHZfbW9kZShzdHJ1 Y3QgZ3VkX2RldmljZSAqZ2RybSwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIHN0cnVjdCBkcm1fY29ubmVjdG9yICpjb25uZWN0b3IsIHU2NCB2YWwpCj4+ICt7Cj4+ICsg ICAgICAgdW5zaWduZWQgaW50IGksIG51bV9tb2RlczsKPj4gKyAgICAgICBjb25zdCBjaGFyICoq bW9kZXM7Cj4+ICsgICAgICAgc2l6ZV90IGJ1Zl9sZW47Cj4+ICsgICAgICAgY2hhciAqYnVmOwo+ PiArICAgICAgIGludCByZXQ7Cj4+ICsKPj4gKyAgICAgICBudW1fbW9kZXMgPSB2YWwgPj4gR1VE X0NPTk5FQ1RPUl9UVl9NT0RFX05VTV9TSElGVDsKPj4gKwo+PiArICAgICAgIGlmICghbnVtX21v ZGVzKQo+PiArICAgICAgICAgICAgICAgcmV0dXJuIC1FSU5WQUw7Cj4+ICsKPj4gKyAgICAgICBi dWZfbGVuID0gbnVtX21vZGVzICogR1VEX0NPTk5FQ1RPUl9UVl9NT0RFX05BTUVfTEVOOwo+PiAr ICAgICAgIG1vZGVzID0ga21hbGxvY19hcnJheShudW1fbW9kZXMsIHNpemVvZigqbW9kZXMpLCBH RlBfS0VSTkVMKTsKPj4gKyAgICAgICBidWYgPSBrbWFsbG9jKGJ1Zl9sZW4sIEdGUF9LRVJORUwp Owo+PiArICAgICAgIGlmICghbW9kZXMgfHwgIWJ1Zikgewo+PiArICAgICAgICAgICAgICAgcmV0 ID0gLUVOT01FTTsKPj4gKyAgICAgICAgICAgICAgIGdvdG8gZnJlZTsKPj4gKyAgICAgICB9Cj4+ ICsKPj4gKyAgICAgICByZXQgPSBndWRfdXNiX2dldChnZHJtLCBHVURfUkVRX0dFVF9DT05ORUNU T1JfVFZfTU9ERV9WQUxVRVMsCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdG9y LT5pbmRleCwgYnVmLCBidWZfbGVuKTsKPj4gKyAgICAgICBpZiAocmV0KQo+PiArICAgICAgICAg ICAgICAgZ290byBmcmVlOwo+PiArCj4+ICsgICAgICAgZm9yIChpID0gMDsgaSA8IG51bV9tb2Rl czsgaSsrKQo+PiArICAgICAgICAgICAgICAgbW9kZXNbaV0gPSAmYnVmW2kgKiBHVURfQ09OTkVD VE9SX1RWX01PREVfTkFNRV9MRU5dOwo+PiArCj4+ICsgICAgICAgcmV0ID0gZHJtX21vZGVfY3Jl YXRlX3R2X3Byb3BlcnRpZXMoY29ubmVjdG9yLT5kZXYsIG51bV9tb2RlcywgbW9kZXMpOwo+PiAr ZnJlZToKPj4gKyAgICAgICBrZnJlZShtb2Rlcyk7Cj4+ICsgICAgICAga2ZyZWUoYnVmKTsKPj4g Kwo+PiArICAgICAgIHJldHVybiByZXQ7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBzdHJ1Y3QgZHJt X3Byb3BlcnR5ICoKPj4gK2d1ZF9jb25uZWN0b3JfcHJvcGVydHlfbG9va3VwKHN0cnVjdCBkcm1f Y29ubmVjdG9yICpjb25uZWN0b3IsIHUxNiBwcm9wKQo+PiArewo+PiArICAgICAgIHN0cnVjdCBk cm1fbW9kZV9jb25maWcgKmNvbmZpZyA9ICZjb25uZWN0b3ItPmRldi0+bW9kZV9jb25maWc7Cj4+ ICsKPj4gKyAgICAgICBzd2l0Y2ggKHByb3ApIHsKPj4gKyAgICAgICBjYXNlIEdVRF9QUk9QRVJU WV9UVl9MRUZUX01BUkdJTjoKPj4gKyAgICAgICAgICAgICAgIHJldHVybiBjb25maWctPnR2X2xl ZnRfbWFyZ2luX3Byb3BlcnR5Owo+PiArICAgICAgIGNhc2UgR1VEX1BST1BFUlRZX1RWX1JJR0hU X01BUkdJTjoKPj4gKyAgICAgICAgICAgICAgIHJldHVybiBjb25maWctPnR2X3JpZ2h0X21hcmdp bl9wcm9wZXJ0eTsKPj4gKyAgICAgICBjYXNlIEdVRF9QUk9QRVJUWV9UVl9UT1BfTUFSR0lOOgo+ PiArICAgICAgICAgICAgICAgcmV0dXJuIGNvbmZpZy0+dHZfdG9wX21hcmdpbl9wcm9wZXJ0eTsK Pj4gKyAgICAgICBjYXNlIEdVRF9QUk9QRVJUWV9UVl9CT1RUT01fTUFSR0lOOgo+PiArICAgICAg ICAgICAgICAgcmV0dXJuIGNvbmZpZy0+dHZfYm90dG9tX21hcmdpbl9wcm9wZXJ0eTsKPj4gKyAg ICAgICBjYXNlIEdVRF9QUk9QRVJUWV9UVl9NT0RFOgo+PiArICAgICAgICAgICAgICAgcmV0dXJu IGNvbmZpZy0+dHZfbW9kZV9wcm9wZXJ0eTsKPj4gKyAgICAgICBjYXNlIEdVRF9QUk9QRVJUWV9U Vl9CUklHSFRORVNTOgo+PiArICAgICAgICAgICAgICAgcmV0dXJuIGNvbmZpZy0+dHZfYnJpZ2h0 bmVzc19wcm9wZXJ0eTsKPj4gKyAgICAgICBjYXNlIEdVRF9QUk9QRVJUWV9UVl9DT05UUkFTVDoK Pj4gKyAgICAgICAgICAgICAgIHJldHVybiBjb25maWctPnR2X2NvbnRyYXN0X3Byb3BlcnR5Owo+ PiArICAgICAgIGNhc2UgR1VEX1BST1BFUlRZX1RWX0ZMSUNLRVJfUkVEVUNUSU9OOgo+PiArICAg ICAgICAgICAgICAgcmV0dXJuIGNvbmZpZy0+dHZfZmxpY2tlcl9yZWR1Y3Rpb25fcHJvcGVydHk7 Cj4+ICsgICAgICAgY2FzZSBHVURfUFJPUEVSVFlfVFZfT1ZFUlNDQU46Cj4+ICsgICAgICAgICAg ICAgICByZXR1cm4gY29uZmlnLT50dl9vdmVyc2Nhbl9wcm9wZXJ0eTsKPj4gKyAgICAgICBjYXNl IEdVRF9QUk9QRVJUWV9UVl9TQVRVUkFUSU9OOgo+PiArICAgICAgICAgICAgICAgcmV0dXJuIGNv bmZpZy0+dHZfc2F0dXJhdGlvbl9wcm9wZXJ0eTsKPj4gKyAgICAgICBjYXNlIEdVRF9QUk9QRVJU WV9UVl9IVUU6Cj4+ICsgICAgICAgICAgICAgICByZXR1cm4gY29uZmlnLT50dl9odWVfcHJvcGVy dHk7Cj4+ICsgICAgICAgZGVmYXVsdDoKPj4gKyAgICAgICAgICAgICAgIHJldHVybiBFUlJfUFRS KC1FSU5WQUwpOwo+PiArICAgICAgIH0KPj4gK30KPj4gKwo+PiArc3RhdGljIHVuc2lnbmVkIGlu dCAqZ3VkX2Nvbm5lY3Rvcl90dl9zdGF0ZV92YWwodTE2IHByb3AsIHN0cnVjdCBkcm1fdHZfY29u bmVjdG9yX3N0YXRlICpzdGF0ZSkKPj4gK3sKPj4gKyAgICAgICBzd2l0Y2ggKHByb3ApIHsKPj4g KyAgICAgICBjYXNlIEdVRF9QUk9QRVJUWV9UVl9MRUZUX01BUkdJTjoKPj4gKyAgICAgICAgICAg ICAgIHJldHVybiAmc3RhdGUtPm1hcmdpbnMubGVmdDsKPj4gKyAgICAgICBjYXNlIEdVRF9QUk9Q RVJUWV9UVl9SSUdIVF9NQVJHSU46Cj4+ICsgICAgICAgICAgICAgICByZXR1cm4gJnN0YXRlLT5t YXJnaW5zLnJpZ2h0Owo+PiArICAgICAgIGNhc2UgR1VEX1BST1BFUlRZX1RWX1RPUF9NQVJHSU46 Cj4+ICsgICAgICAgICAgICAgICByZXR1cm4gJnN0YXRlLT5tYXJnaW5zLnRvcDsKPj4gKyAgICAg ICBjYXNlIEdVRF9QUk9QRVJUWV9UVl9CT1RUT01fTUFSR0lOOgo+PiArICAgICAgICAgICAgICAg cmV0dXJuICZzdGF0ZS0+bWFyZ2lucy5ib3R0b207Cj4+ICsgICAgICAgY2FzZSBHVURfUFJPUEVS VFlfVFZfTU9ERToKPj4gKyAgICAgICAgICAgICAgIHJldHVybiAmc3RhdGUtPm1vZGU7Cj4+ICsg ICAgICAgY2FzZSBHVURfUFJPUEVSVFlfVFZfQlJJR0hUTkVTUzoKPj4gKyAgICAgICAgICAgICAg IHJldHVybiAmc3RhdGUtPmJyaWdodG5lc3M7Cj4+ICsgICAgICAgY2FzZSBHVURfUFJPUEVSVFlf VFZfQ09OVFJBU1Q6Cj4+ICsgICAgICAgICAgICAgICByZXR1cm4gJnN0YXRlLT5jb250cmFzdDsK Pj4gKyAgICAgICBjYXNlIEdVRF9QUk9QRVJUWV9UVl9GTElDS0VSX1JFRFVDVElPTjoKPj4gKyAg ICAgICAgICAgICAgIHJldHVybiAmc3RhdGUtPmZsaWNrZXJfcmVkdWN0aW9uOwo+PiArICAgICAg IGNhc2UgR1VEX1BST1BFUlRZX1RWX09WRVJTQ0FOOgo+PiArICAgICAgICAgICAgICAgcmV0dXJu ICZzdGF0ZS0+b3ZlcnNjYW47Cj4+ICsgICAgICAgY2FzZSBHVURfUFJPUEVSVFlfVFZfU0FUVVJB VElPTjoKPj4gKyAgICAgICAgICAgICAgIHJldHVybiAmc3RhdGUtPnNhdHVyYXRpb247Cj4+ICsg ICAgICAgY2FzZSBHVURfUFJPUEVSVFlfVFZfSFVFOgo+PiArICAgICAgICAgICAgICAgcmV0dXJu ICZzdGF0ZS0+aHVlOwo+PiArICAgICAgIGRlZmF1bHQ6Cj4+ICsgICAgICAgICAgICAgICByZXR1 cm4gRVJSX1BUUigtRUlOVkFMKTsKPj4gKyAgICAgICB9Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBp bnQgZ3VkX2Nvbm5lY3Rvcl9hZGRfcHJvcGVydGllcyhzdHJ1Y3QgZ3VkX2RldmljZSAqZ2RybSwg c3RydWN0IGd1ZF9jb25uZWN0b3IgKmdjb25uLAo+PiArICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgdW5zaWduZWQgaW50IG51bV9wcm9wZXJ0aWVzKQo+PiArewo+PiArICAg ICAgIHN0cnVjdCBkcm1fZGV2aWNlICpkcm0gPSAmZ2RybS0+ZHJtOwo+PiArICAgICAgIHN0cnVj dCBkcm1fY29ubmVjdG9yICpjb25uZWN0b3IgPSAmZ2Nvbm4tPmNvbm5lY3RvcjsKPj4gKyAgICAg ICBzdHJ1Y3QgZ3VkX3Byb3BlcnR5X3JlcSAqcHJvcGVydGllczsKPj4gKyAgICAgICB1bnNpZ25l ZCBpbnQgaTsKPj4gKyAgICAgICBpbnQgcmV0Owo+PiArCj4+ICsgICAgICAgZ2Nvbm4tPnByb3Bl cnRpZXMgPSBrY2FsbG9jKG51bV9wcm9wZXJ0aWVzLCBzaXplb2YoKmdjb25uLT5wcm9wZXJ0aWVz KSwgR0ZQX0tFUk5FTCk7Cj4+ICsgICAgICAgaWYgKCFnY29ubi0+cHJvcGVydGllcykKPj4gKyAg ICAgICAgICAgICAgIHJldHVybiAtRU5PTUVNOwo+PiArCj4+ICsgICAgICAgcHJvcGVydGllcyA9 IGtjYWxsb2MobnVtX3Byb3BlcnRpZXMsIHNpemVvZigqcHJvcGVydGllcyksIEdGUF9LRVJORUwp Owo+PiArICAgICAgIGlmICghcHJvcGVydGllcykKPj4gKyAgICAgICAgICAgICAgIHJldHVybiAt RU5PTUVNOwo+PiArCj4+ICsgICAgICAgcmV0ID0gZ3VkX3VzYl9nZXQoZ2RybSwgR1VEX1JFUV9H RVRfQ09OTkVDVE9SX1BST1BFUlRJRVMsIGNvbm5lY3Rvci0+aW5kZXgsCj4+ICsgICAgICAgICAg ICAgICAgICAgICAgICAgcHJvcGVydGllcywgbnVtX3Byb3BlcnRpZXMgKiBzaXplb2YoKnByb3Bl cnRpZXMpKTsKPj4gKyAgICAgICBpZiAocmV0KQo+PiArICAgICAgICAgICAgICAgZ290byBvdXQ7 Cj4+ICsKPj4gKyAgICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtX3Byb3BlcnRpZXM7IGkrKykgewo+ PiArICAgICAgICAgICAgICAgdTE2IHByb3AgPSBsZTE2X3RvX2NwdShwcm9wZXJ0aWVzW2ldLnBy b3ApOwo+PiArICAgICAgICAgICAgICAgdTY0IHZhbCA9IGxlNjRfdG9fY3B1KHByb3BlcnRpZXNb aV0udmFsKTsKPj4gKyAgICAgICAgICAgICAgIHN0cnVjdCBkcm1fcHJvcGVydHkgKnByb3BlcnR5 Owo+PiArICAgICAgICAgICAgICAgdW5zaWduZWQgaW50ICpzdGF0ZV92YWw7Cj4+ICsKPj4gKyAg ICAgICAgICAgICAgIGRybV9kYmcoZHJtLCAicHJvcGVydHk6ICV1ID0gJWxsdSgweCVsbHgpXG4i LCBwcm9wLCB2YWwsIHZhbCk7Cj4+ICsKPj4gKyAgICAgICAgICAgICAgIHN3aXRjaCAocHJvcCkg ewo+PiArICAgICAgICAgICAgICAgY2FzZSBHVURfUFJPUEVSVFlfVFZfTEVGVF9NQVJHSU46Cj4+ ICsgICAgICAgICAgICAgICAgICAgICAgIGZhbGx0aHJvdWdoOwo+PiArICAgICAgICAgICAgICAg Y2FzZSBHVURfUFJPUEVSVFlfVFZfUklHSFRfTUFSR0lOOgo+PiArICAgICAgICAgICAgICAgICAg ICAgICBmYWxsdGhyb3VnaDsKPj4gKyAgICAgICAgICAgICAgIGNhc2UgR1VEX1BST1BFUlRZX1RW X1RPUF9NQVJHSU46Cj4+ICsgICAgICAgICAgICAgICAgICAgICAgIGZhbGx0aHJvdWdoOwo+PiAr ICAgICAgICAgICAgICAgY2FzZSBHVURfUFJPUEVSVFlfVFZfQk9UVE9NX01BUkdJTjoKPj4gKyAg ICAgICAgICAgICAgICAgICAgICAgcmV0ID0gZHJtX21vZGVfY3JlYXRlX3R2X21hcmdpbl9wcm9w ZXJ0aWVzKGRybSk7Cj4+ICsgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXQpCj4+ICsgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgZ290byBvdXQ7Cj4+ICsgICAgICAgICAgICAgICAg ICAgICAgIGJyZWFrOwo+PiArICAgICAgICAgICAgICAgY2FzZSBHVURfUFJPUEVSVFlfVFZfTU9E RToKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgcmV0ID0gZ3VkX2Nvbm5lY3Rvcl9hZGRfdHZf bW9kZShnZHJtLCBjb25uZWN0b3IsIHZhbCk7Cj4+ICsgICAgICAgICAgICAgICAgICAgICAgIGlm IChyZXQpCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ290byBvdXQ7Cj4+ICsg ICAgICAgICAgICAgICAgICAgICAgIHZhbCA9IHZhbCAmIChCSVQoR1VEX0NPTk5FQ1RPUl9UVl9N T0RFX05VTV9TSElGVCkgLSAxKTsKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7Cj4+ ICsgICAgICAgICAgICAgICBjYXNlIEdVRF9QUk9QRVJUWV9UVl9CUklHSFRORVNTOgo+PiArICAg ICAgICAgICAgICAgICAgICAgICBmYWxsdGhyb3VnaDsKPj4gKyAgICAgICAgICAgICAgIGNhc2Ug R1VEX1BST1BFUlRZX1RWX0NPTlRSQVNUOgo+PiArICAgICAgICAgICAgICAgICAgICAgICBmYWxs dGhyb3VnaDsKPj4gKyAgICAgICAgICAgICAgIGNhc2UgR1VEX1BST1BFUlRZX1RWX0ZMSUNLRVJf UkVEVUNUSU9OOgo+PiArICAgICAgICAgICAgICAgICAgICAgICBmYWxsdGhyb3VnaDsKPj4gKyAg ICAgICAgICAgICAgIGNhc2UgR1VEX1BST1BFUlRZX1RWX09WRVJTQ0FOOgo+PiArICAgICAgICAg ICAgICAgICAgICAgICBmYWxsdGhyb3VnaDsKPj4gKyAgICAgICAgICAgICAgIGNhc2UgR1VEX1BS T1BFUlRZX1RWX1NBVFVSQVRJT046Cj4+ICsgICAgICAgICAgICAgICAgICAgICAgIGZhbGx0aHJv dWdoOwo+PiArICAgICAgICAgICAgICAgY2FzZSBHVURfUFJPUEVSVFlfVFZfSFVFOgo+PiArICAg ICAgICAgICAgICAgICAgICAgICAvKiBUaGlzIGlzIGEgbm8tb3AgaWYgYWxyZWFkeSBhZGRlZC4g Ki8KPj4gKyAgICAgICAgICAgICAgICAgICAgICAgcmV0ID0gZHJtX21vZGVfY3JlYXRlX3R2X3By b3BlcnRpZXMoZHJtLCAwLCBOVUxMKTsKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJl dCkKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb3RvIG91dDsKPj4gKyAgICAg ICAgICAgICAgICAgICAgICAgYnJlYWs7Cj4+ICsgICAgICAgICAgICAgICBjYXNlIEdVRF9QUk9Q RVJUWV9CQUNLTElHSFRfQlJJR0hUTkVTUzoKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgaWYg KHZhbCA+IDEwMCkgewo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldCA9IC1F SU5WQUw7Cj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ290byBvdXQ7Cj4+ICsg ICAgICAgICAgICAgICAgICAgICAgIH0KPj4gKyAgICAgICAgICAgICAgICAgICAgICAgZ2Nvbm4t PmluaXRpYWxfYnJpZ2h0bmVzcyA9IHZhbDsKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgYnJl YWs7Cj4+ICsgICAgICAgICAgICAgICBkZWZhdWx0Ogo+PiArICAgICAgICAgICAgICAgICAgICAg ICAvKiBOZXcgb25lcyBtaWdodCBzaG93IHVwIGluIGZ1dHVyZSBkZXZpY2VzLCBza2lwIHRob3Nl IHdlIGRvbid0IGtub3cuICovCj4+ICsgICAgICAgICAgICAgICAgICAgICAgIGRybV9kYmcoZHJt LCAiVW5rbm93biBwcm9wZXJ0eTogJXVcbiIsIHByb3ApOwo+PiArICAgICAgICAgICAgICAgICAg ICAgICBjb250aW51ZTsKPj4gKyAgICAgICAgICAgICAgIH0KPj4gKwo+PiArICAgICAgICAgICAg ICAgZ2Nvbm4tPnByb3BlcnRpZXNbZ2Nvbm4tPm51bV9wcm9wZXJ0aWVzKytdID0gcHJvcDsKPj4g Kwo+PiArICAgICAgICAgICAgICAgaWYgKHByb3AgPT0gR1VEX1BST1BFUlRZX0JBQ0tMSUdIVF9C UklHSFRORVNTKQo+PiArICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsgLyogbm90IGEg RFJNIHByb3BlcnR5ICovCj4+ICsKPj4gKyAgICAgICAgICAgICAgIHByb3BlcnR5ID0gZ3VkX2Nv bm5lY3Rvcl9wcm9wZXJ0eV9sb29rdXAoY29ubmVjdG9yLCBwcm9wKTsKPj4gKyAgICAgICAgICAg ICAgIGlmIChXQVJOX09OKElTX0VSUihwcm9wZXJ0eSkpKQo+PiArICAgICAgICAgICAgICAgICAg ICAgICBjb250aW51ZTsKPj4gKwo+PiArICAgICAgICAgICAgICAgc3RhdGVfdmFsID0gZ3VkX2Nv bm5lY3Rvcl90dl9zdGF0ZV92YWwocHJvcCwgJmdjb25uLT5pbml0aWFsX3R2X3N0YXRlKTsKPj4g KyAgICAgICAgICAgICAgIGlmIChXQVJOX09OKElTX0VSUihzdGF0ZV92YWwpKSkKPj4gKyAgICAg ICAgICAgICAgICAgICAgICAgY29udGludWU7Cj4+ICsKPj4gKyAgICAgICAgICAgICAgICpzdGF0 ZV92YWwgPSB2YWw7Cj4+ICsgICAgICAgICAgICAgICBkcm1fb2JqZWN0X2F0dGFjaF9wcm9wZXJ0 eSgmY29ubmVjdG9yLT5iYXNlLCBwcm9wZXJ0eSwgMCk7Cj4+ICsgICAgICAgfQo+PiArb3V0Ogo+ PiArICAgICAgIGtmcmVlKHByb3BlcnRpZXMpOwo+PiArCj4+ICsgICAgICAgcmV0dXJuIHJldDsK Pj4gK30KPj4gKwo+PiAraW50IGd1ZF9jb25uZWN0b3JfZmlsbF9wcm9wZXJ0aWVzKHN0cnVjdCBk cm1fY29ubmVjdG9yICpjb25uZWN0b3IsCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICBzdHJ1Y3QgZHJtX2Nvbm5lY3Rvcl9zdGF0ZSAqY29ubmVjdG9yX3N0YXRlLAo+PiArICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IGd1ZF9wcm9wZXJ0eV9yZXEgKnBy b3BlcnRpZXMpCj4+ICt7Cj4+ICsgICAgICAgc3RydWN0IGd1ZF9jb25uZWN0b3IgKmdjb25uOwo+ PiArICAgICAgIHVuc2lnbmVkIGludCBpOwo+PiArCj4+ICsgICAgICAgZ2Nvbm4gPSB0b19ndWRf Y29ubmVjdG9yKGNvbm5lY3Rvcik7Cj4+ICsKPj4gKyAgICAgICAvKiBPbmx5IGludGVyZXN0ZWQg aW4gdGhlIGNvdW50PyAqLwo+PiArICAgICAgIGlmICghY29ubmVjdG9yX3N0YXRlKQo+PiArICAg ICAgICAgICAgICAgcmV0dXJuIGdjb25uLT5udW1fcHJvcGVydGllczsKPj4gKwo+PiArICAgICAg IGZvciAoaSA9IDA7IGkgPCBnY29ubi0+bnVtX3Byb3BlcnRpZXM7IGkrKykgewo+PiArICAgICAg ICAgICAgICAgdTE2IHByb3AgPSBnY29ubi0+cHJvcGVydGllc1tpXTsKPj4gKyAgICAgICAgICAg ICAgIHU2NCB2YWw7Cj4+ICsKPj4gKyAgICAgICAgICAgICAgIGlmIChwcm9wID09IEdVRF9QUk9Q RVJUWV9CQUNLTElHSFRfQlJJR0hUTkVTUykgewo+PiArICAgICAgICAgICAgICAgICAgICAgICB2 YWwgPSBjb25uZWN0b3Jfc3RhdGUtPnR2LmJyaWdodG5lc3M7Cj4+ICsgICAgICAgICAgICAgICB9 IGVsc2Ugewo+PiArICAgICAgICAgICAgICAgICAgICAgICB1bnNpZ25lZCBpbnQgKnN0YXRlX3Zh bDsKPj4gKwo+PiArICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZV92YWwgPSBndWRfY29ubmVj dG9yX3R2X3N0YXRlX3ZhbChwcm9wLCAmY29ubmVjdG9yX3N0YXRlLT50dik7Cj4+ICsgICAgICAg ICAgICAgICAgICAgICAgIGlmIChXQVJOX09OX09OQ0UoSVNfRVJSKHN0YXRlX3ZhbCkpKQo+PiAr ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBQVFJfRVJSKHN0YXRlX3ZhbCk7 Cj4+ICsKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gKnN0YXRlX3ZhbDsKPj4gKyAg ICAgICAgICAgICAgIH0KPj4gKwo+PiArICAgICAgICAgICAgICAgcHJvcGVydGllc1tpXS5wcm9w ID0gY3B1X3RvX2xlMTYocHJvcCk7Cj4+ICsgICAgICAgICAgICAgICBwcm9wZXJ0aWVzW2ldLnZh bCA9IGNwdV90b19sZTY0KHZhbCk7Cj4+ICsgICAgICAgfQo+PiArCj4+ICsgICAgICAgcmV0dXJu IGdjb25uLT5udW1fcHJvcGVydGllczsKPj4gK30KPj4gKwo+PiAraW50IGd1ZF9jb25uZWN0b3Jf Y3JlYXRlKHN0cnVjdCBndWRfZGV2aWNlICpnZHJtLCB1bnNpZ25lZCBpbnQgaW5kZXgpCj4+ICt7 Cj4+ICsgICAgICAgc3RydWN0IGd1ZF9jb25uZWN0b3JfZGVzY3JpcHRvcl9yZXEgZGVzYzsKPj4g KyAgICAgICBzdHJ1Y3QgZHJtX2RldmljZSAqZHJtID0gJmdkcm0tPmRybTsKPj4gKyAgICAgICBz dHJ1Y3QgZ3VkX2Nvbm5lY3RvciAqZ2Nvbm47Cj4+ICsgICAgICAgc3RydWN0IGRybV9jb25uZWN0 b3IgKmNvbm5lY3RvcjsKPj4gKyAgICAgICBzdHJ1Y3QgZHJtX2VuY29kZXIgKmVuY29kZXI7Cj4+ ICsgICAgICAgaW50IHJldCwgY29ubmVjdG9yX3R5cGU7Cj4+ICsgICAgICAgdTMyIGZsYWdzOwo+ PiArCj4+ICsgICAgICAgcmV0ID0gZ3VkX3VzYl9nZXQoZ2RybSwgR1VEX1JFUV9HRVRfQ09OTkVD VE9SLCBpbmRleCwgJmRlc2MsIHNpemVvZihkZXNjKSk7Cj4+ICsgICAgICAgaWYgKHJldCkKPj4g KyAgICAgICAgICAgICAgIHJldHVybiByZXQ7Cj4+ICsKPj4gKyAgICAgICBnY29ubiA9IGt6YWxs b2Moc2l6ZW9mKCpnY29ubiksIEdGUF9LRVJORUwpOwo+IAo+IFdvdWxkIGJlIG5pY2UgdG8gZG8g dGhhdCB3aXRoIGRybW1fLCBidXQgd2UgZG9uJ3QgaGF2ZSB0aGUKPiBkcm1tX2Nvbm5lY3Rvcl9h bGxvYyB3cmFwcGVyIHlldC4KPiAKPj4gKyAgICAgICBpZiAoIWdjb25uKQo+PiArICAgICAgICAg ICAgICAgcmV0dXJuIC1FTk9NRU07Cj4+ICsKPj4gKyAgICAgICBnY29ubi0+aW5pdGlhbF9icmln aHRuZXNzID0gLUVOT0RFVjsKPj4gKyAgICAgICBmbGFncyA9IGxlMzJfdG9fY3B1KGRlc2MuZmxh Z3MpOwo+PiArICAgICAgIGNvbm5lY3RvciA9ICZnY29ubi0+Y29ubmVjdG9yOwo+PiArCj4+ICsg ICAgICAgZHJtX2RiZyhkcm0sICJDb25uZWN0b3I6IGluZGV4PSV1IHR5cGU9JXUgZmxhZ3M9MHgl eCBudW1fcHJvcGVydGllcz0ldVxuIiwKPj4gKyAgICAgICAgICAgICAgIGluZGV4LCBkZXNjLmNv bm5lY3Rvcl90eXBlLCBmbGFncywgZGVzYy5udW1fcHJvcGVydGllcyk7Cj4+ICsKPj4gKyAgICAg ICBzd2l0Y2ggKGRlc2MuY29ubmVjdG9yX3R5cGUpIHsKPj4gKyAgICAgICBjYXNlIEdVRF9DT05O RUNUT1JfVFlQRV9QQU5FTDoKPj4gKyAgICAgICAgICAgICAgIGNvbm5lY3Rvcl90eXBlID0gRFJN X01PREVfQ09OTkVDVE9SX1VTQjsKPj4gKyAgICAgICAgICAgICAgIGJyZWFrOwo+PiArICAgICAg IGNhc2UgR1VEX0NPTk5FQ1RPUl9UWVBFX1ZHQToKPj4gKyAgICAgICAgICAgICAgIGNvbm5lY3Rv cl90eXBlID0gRFJNX01PREVfQ09OTkVDVE9SX1ZHQTsKPj4gKyAgICAgICAgICAgICAgIGJyZWFr Owo+PiArICAgICAgIGNhc2UgR1VEX0NPTk5FQ1RPUl9UWVBFX0RWSToKPj4gKyAgICAgICAgICAg ICAgIGNvbm5lY3Rvcl90eXBlID0gRFJNX01PREVfQ09OTkVDVE9SX0RWSUQ7Cj4+ICsgICAgICAg ICAgICAgICBicmVhazsKPj4gKyAgICAgICBjYXNlIEdVRF9DT05ORUNUT1JfVFlQRV9DT01QT1NJ VEU6Cj4+ICsgICAgICAgICAgICAgICBjb25uZWN0b3JfdHlwZSA9IERSTV9NT0RFX0NPTk5FQ1RP Ul9Db21wb3NpdGU7Cj4+ICsgICAgICAgICAgICAgICBicmVhazsKPj4gKyAgICAgICBjYXNlIEdV RF9DT05ORUNUT1JfVFlQRV9TVklERU86Cj4+ICsgICAgICAgICAgICAgICBjb25uZWN0b3JfdHlw ZSA9IERSTV9NT0RFX0NPTk5FQ1RPUl9TVklERU87Cj4+ICsgICAgICAgICAgICAgICBicmVhazsK Pj4gKyAgICAgICBjYXNlIEdVRF9DT05ORUNUT1JfVFlQRV9DT01QT05FTlQ6Cj4+ICsgICAgICAg ICAgICAgICBjb25uZWN0b3JfdHlwZSA9IERSTV9NT0RFX0NPTk5FQ1RPUl9Db21wb25lbnQ7Cj4+ ICsgICAgICAgICAgICAgICBicmVhazsKPj4gKyAgICAgICBjYXNlIEdVRF9DT05ORUNUT1JfVFlQ RV9ESVNQTEFZUE9SVDoKPj4gKyAgICAgICAgICAgICAgIGNvbm5lY3Rvcl90eXBlID0gRFJNX01P REVfQ09OTkVDVE9SX0Rpc3BsYXlQb3J0Owo+PiArICAgICAgICAgICAgICAgYnJlYWs7Cj4+ICsg ICAgICAgY2FzZSBHVURfQ09OTkVDVE9SX1RZUEVfSERNSToKPj4gKyAgICAgICAgICAgICAgIGNv bm5lY3Rvcl90eXBlID0gRFJNX01PREVfQ09OTkVDVE9SX0hETUlBOwo+PiArICAgICAgICAgICAg ICAgYnJlYWs7Cj4+ICsgICAgICAgZGVmYXVsdDogLyogZnV0dXJlIHR5cGVzICovCj4+ICsgICAg ICAgICAgICAgICBjb25uZWN0b3JfdHlwZSA9IERSTV9NT0RFX0NPTk5FQ1RPUl9VU0I7Cj4+ICsg ICAgICAgICAgICAgICBicmVhazsKPj4gKyAgICAgICB9Owo+PiArCj4+ICsgICAgICAgZHJtX2Nv bm5lY3Rvcl9oZWxwZXJfYWRkKGNvbm5lY3RvciwgJmd1ZF9jb25uZWN0b3JfaGVscGVyX2Z1bmNz KTsKPj4gKyAgICAgICByZXQgPSBkcm1fY29ubmVjdG9yX2luaXQoZHJtLCBjb25uZWN0b3IsICZn dWRfY29ubmVjdG9yX2Z1bmNzLCBjb25uZWN0b3JfdHlwZSk7Cj4+ICsgICAgICAgaWYgKHJldCkg ewo+PiArICAgICAgICAgICAgICAga2ZyZWUoY29ubmVjdG9yKTsKPj4gKyAgICAgICAgICAgICAg IHJldHVybiByZXQ7Cj4+ICsgICAgICAgfQo+PiArCj4+ICsgICAgICAgaWYgKFdBUk5fT04oY29u bmVjdG9yLT5pbmRleCAhPSBpbmRleCkpCj4+ICsgICAgICAgICAgICAgICByZXR1cm4gLUVJTlZB TDsKPj4gKwo+PiArICAgICAgIGlmIChmbGFncyAmIEdVRF9DT05ORUNUT1JfRkxBR1NfUE9MTF9T VEFUVVMpCj4+ICsgICAgICAgICAgICAgICBjb25uZWN0b3ItPnBvbGxlZCA9IChEUk1fQ09OTkVD VE9SX1BPTExfQ09OTkVDVCB8IERSTV9DT05ORUNUT1JfUE9MTF9ESVNDT05ORUNUKTsKPj4gKyAg ICAgICBpZiAoZmxhZ3MgJiBHVURfQ09OTkVDVE9SX0ZMQUdTX0lOVEVSTEFDRSkKPj4gKyAgICAg ICAgICAgICAgIGNvbm5lY3Rvci0+aW50ZXJsYWNlX2FsbG93ZWQgPSB0cnVlOwo+PiArICAgICAg IGlmIChmbGFncyAmIEdVRF9DT05ORUNUT1JfRkxBR1NfRE9VQkxFU0NBTikKPj4gKyAgICAgICAg ICAgICAgIGNvbm5lY3Rvci0+ZG91Ymxlc2Nhbl9hbGxvd2VkID0gdHJ1ZTsKPj4gKwo+PiArICAg ICAgIGlmIChkZXNjLm51bV9wcm9wZXJ0aWVzKSB7Cj4+ICsgICAgICAgICAgICAgICByZXQgPSBn dWRfY29ubmVjdG9yX2FkZF9wcm9wZXJ0aWVzKGdkcm0sIGdjb25uLCBkZXNjLm51bV9wcm9wZXJ0 aWVzKTsKPj4gKyAgICAgICAgICAgICAgIGlmIChyZXQpIHsKPj4gKyAgICAgICAgICAgICAgICAg ICAgICAgZGV2X2Vycihkcm0tPmRldiwgIkZhaWxlZCB0byBhZGQgY29ubmVjdG9yLyV1IHByb3Bl cnRpZXNcbiIsIGluZGV4KTsKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJldDsK Pj4gKyAgICAgICAgICAgICAgIH0KPj4gKyAgICAgICB9Cj4+ICsKPj4gKyAgICAgICAvKiBUaGUg Zmlyc3QgY29ubmVjdG9yIGlzIGF0dGFjaGVkIHRvIHRoZSBleGlzdGluZyBzaW1wbGUgcGlwZSBl bmNvZGVyICovCj4+ICsgICAgICAgaWYgKCFjb25uZWN0b3ItPmluZGV4KSB7Cj4+ICsgICAgICAg ICAgICAgICBlbmNvZGVyID0gJmdkcm0tPnBpcGUuZW5jb2RlcjsKPj4gKyAgICAgICB9IGVsc2Ug ewo+PiArICAgICAgICAgICAgICAgZW5jb2RlciA9ICZnY29ubi0+ZW5jb2RlcjsKPj4gKwo+PiAr ICAgICAgICAgICAgICAgcmV0ID0gZHJtX3NpbXBsZV9lbmNvZGVyX2luaXQoZHJtLCBlbmNvZGVy LCBEUk1fTU9ERV9FTkNPREVSX05PTkUpOwo+PiArICAgICAgICAgICAgICAgaWYgKHJldCkKPj4g KyAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJldDsKPj4gKwo+PiArICAgICAgICAgICAg ICAgZW5jb2Rlci0+cG9zc2libGVfY3J0Y3MgPSAxOwo+PiArICAgICAgIH0KPj4gKwo+PiArICAg ICAgIHJldHVybiBkcm1fY29ubmVjdG9yX2F0dGFjaF9lbmNvZGVyKGNvbm5lY3RvciwgZW5jb2Rl cik7Cj4+ICt9Cl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f CmRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRldmVsQGxpc3RzLmZyZWVkZXNrdG9wLm9yZwpo dHRwczovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2RyaS1kZXZlbAo=