From mboxrd@z Thu Jan 1 00:00:00 1970 From: architt@codeaurora.org (Archit Taneja) Date: Thu, 21 Jul 2016 15:23:18 +0530 Subject: [PATCH v2 4/7] drm/bridge: Add RGB to VGA bridge support In-Reply-To: <20160720095857.12297-5-maxime.ripard@free-electrons.com> References: <20160720095857.12297-1-maxime.ripard@free-electrons.com> <20160720095857.12297-5-maxime.ripard@free-electrons.com> Message-ID: <57909B8E.7030105@codeaurora.org> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Hi, On 07/20/2016 03:28 PM, Maxime Ripard wrote: > Some boards have an entirely passive RGB to VGA bridge, based on either > DACs or resistor ladders. > > Those might or might not have an i2c bus routed to the VGA connector in > order to access the screen EDIDs. > > Add a bridge that doesn't do anything but expose the modes available on the > screen, either based on the EDIDs if available, or based on the XGA > standards. Our eventual aim is to separate out the connectors from the bridge drivers wherever possible. In the future, a KMS driver using the bridge would be responsible for establishing the links between the bridge and encoder, and the encoder and connector. If in the future we remove the connector pieces from this driver to create a separate generic VGA connector driver, we'll end up with a bridge driver whose main functionality is to convert RGB signals to VGA. The EDID parts would move to the VGA connector driver. In your platform's case, there is no software needed to translate RGB to VGA, but maybe in the future, we might need to add an optional regulator in the driver to support another platform. Therefore, the bridge driver would still be handy to have. Keeping this in consideration, I think this driver (and the DT binding) should be called "dumb-rgb-to-vga-bridge", or "rgb-to-vga-bridge" since that's what the bridge HW primarily does. Thanks, Archit > > Signed-off-by: Maxime Ripard > --- > .../bindings/display/bridge/dumb-vga.txt | 54 +++++ > drivers/gpu/drm/bridge/Kconfig | 6 + > drivers/gpu/drm/bridge/Makefile | 1 + > drivers/gpu/drm/bridge/dumb-vga.c | 232 +++++++++++++++++++++ > 4 files changed, 293 insertions(+) > create mode 100644 Documentation/devicetree/bindings/display/bridge/dumb-vga.txt > create mode 100644 drivers/gpu/drm/bridge/dumb-vga.c > > diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt > new file mode 100644 > index 000000000000..0056ffa2b31d > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt > @@ -0,0 +1,54 @@ > +Passive RGB to VGA bridge > +------------------------- > + > +This binding is aimed for entirely passive RGB to VGA bridges that do not > +require any configuration. > + > +Required properties: > + > +- compatible: Must be "dumb-vga-bridge" > + > +Required nodes: > + > +This device has two video ports. Their connections are modeled using the OF > +graph bindings specified in Documentation/devicetree/bindings/graph.txt. > + > +- Video port 0 for RGB input > +- Video port 1 for VGA output > + > + > +Example > +------- > + > +bridge { > + compatible = "dumb-vga-bridge"; > + #address-cells = <1>; > + #size-cells = <0>; > + > + ports { > + #address-cells = <1>; > + #size-cells = <0>; > + > + port at 0 { > + #address-cells = <1>; > + #size-cells = <0>; > + reg = <0>; > + > + vga_bridge_in: endpoint at 0 { > + reg = <0>; > + remote-endpoint = <&tcon0_out_vga>; > + }; > + }; > + > + port at 1 { > + #address-cells = <1>; > + #size-cells = <0>; > + reg = <1>; > + > + vga_bridge_out: endpoint at 0 { > + reg = <0>; > + remote-endpoint = <&vga_con_in>; > + }; > + }; > + }; > +}; > diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig > index a141921445f4..4a6560714397 100644 > --- a/drivers/gpu/drm/bridge/Kconfig > +++ b/drivers/gpu/drm/bridge/Kconfig > @@ -17,6 +17,12 @@ config DRM_ANALOGIX_ANX78XX > the HDMI output of an application processor to MyDP > or DisplayPort. > > +config DRM_DUMB_VGA > + tristate "Dumb RGB to VGA Bridge support" > + select DRM_KMS_HELPER > + help > + Support for passive RGB to VGA bridges > + > config DRM_DW_HDMI > tristate > select DRM_KMS_HELPER > diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile > index bfec9f8cb9d2..413d783828bb 100644 > --- a/drivers/gpu/drm/bridge/Makefile > +++ b/drivers/gpu/drm/bridge/Makefile > @@ -1,6 +1,7 @@ > ccflags-y := -Iinclude/drm > > obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o > +obj-$(CONFIG_DRM_DUMB_VGA) += dumb-vga.o > obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o > obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o > obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o > diff --git a/drivers/gpu/drm/bridge/dumb-vga.c b/drivers/gpu/drm/bridge/dumb-vga.c > new file mode 100644 > index 000000000000..c197be591fb6 > --- /dev/null > +++ b/drivers/gpu/drm/bridge/dumb-vga.c > @@ -0,0 +1,232 @@ > + > +#include > +#include > + > +#include > +#include > +#include > +#include > + > +struct dumb_vga { > + struct drm_bridge bridge; > + struct drm_connector connector; > + > + struct i2c_adapter *ddc; > +}; > + > +static inline struct dumb_vga * > +drm_bridge_to_dumb_vga(struct drm_bridge *bridge) > +{ > + return container_of(bridge, struct dumb_vga, bridge); > +} > + > +static inline struct dumb_vga * > +drm_connector_to_dumb_vga(struct drm_connector *connector) > +{ > + return container_of(connector, struct dumb_vga, connector); > +} > + > +static int dumb_vga_get_modes(struct drm_connector *connector) > +{ > + struct dumb_vga *vga = drm_connector_to_dumb_vga(connector); > + struct edid *edid; > + int ret; > + > + if (IS_ERR(vga->ddc)) > + goto fallback; > + > + edid = drm_get_edid(connector, vga->ddc); > + if (!edid) { > + DRM_INFO("EDID readout failed, falling back to standard modes\n"); > + goto fallback; > + } > + > + drm_mode_connector_update_edid_property(connector, edid); > + return drm_add_edid_modes(connector, edid); > + > +fallback: > + /* > + * In case we cannot retrieve the EDIDs (broken or missing i2c > + * bus), fallback on the XGA standards > + */ > + ret = drm_add_modes_noedid(connector, 1920, 1200); > + > + /* And prefer a mode pretty much anyone can handle */ > + drm_set_preferred_mode(connector, 1024, 768); > + > + return ret; > +} > + > +static struct drm_encoder * > +dumb_vga_best_encoder(struct drm_connector *connector) > +{ > + struct dumb_vga *vga = drm_connector_to_dumb_vga(connector); > + > + return vga->bridge.encoder; > +} > + > +static struct drm_connector_helper_funcs dumb_vga_con_helper_funcs = { > + .get_modes = dumb_vga_get_modes, > + .best_encoder = dumb_vga_best_encoder, > +}; > + > +static enum drm_connector_status > +dumb_vga_connector_detect(struct drm_connector *connector, bool force) > +{ > + struct dumb_vga *vga = drm_connector_to_dumb_vga(connector); > + > + /* > + * Even if we have an I2C bus, we can't assume that the cable > + * is disconnected if drm_probe_ddc. Some cables don't wire > + * the DDC pins, or the I2C bus might be disfunctional. > + */ > + if (!IS_ERR(vga->ddc) && drm_probe_ddc(vga->ddc)) > + return connector_status_connected; > + > + return connector_status_unknown; > +} > + > +static void > +dumb_vga_connector_destroy(struct drm_connector *connector) > +{ > + drm_connector_cleanup(connector); > +} > + > +static struct drm_connector_funcs dumb_vga_con_funcs = { > + .dpms = drm_atomic_helper_connector_dpms, > + .detect = dumb_vga_connector_detect, > + .fill_modes = drm_helper_probe_single_connector_modes, > + .destroy = dumb_vga_connector_destroy, > + .reset = drm_atomic_helper_connector_reset, > + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, > + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, > +}; > + > +static int dumb_vga_attach(struct drm_bridge *bridge) > +{ > + struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge); > + int ret; > + > + if (!bridge->encoder) { > + DRM_ERROR("Missing encoder\n"); > + return -ENODEV; > + } > + > + drm_connector_helper_add(&vga->connector, > + &dumb_vga_con_helper_funcs); > + ret = drm_connector_init(bridge->dev, &vga->connector, > + &dumb_vga_con_funcs, DRM_MODE_CONNECTOR_VGA); > + if (ret) { > + DRM_ERROR("Failed to initialize connector\n"); > + return ret; > + } > + > + drm_mode_connector_attach_encoder(&vga->connector, > + bridge->encoder); > + > + return 0; > +} > + > +static void dumb_vga_nop(struct drm_bridge *bridge) {}; > + > +static struct drm_bridge_funcs dumb_vga_bridge_funcs = { > + .attach = dumb_vga_attach, > + .enable = dumb_vga_nop, > + .disable = dumb_vga_nop, > + .pre_enable = dumb_vga_nop, > + .post_disable = dumb_vga_nop, We don't need to install nops here, the drm bridge core skips calling the op if it can't find it. > +}; > + > +static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev) > +{ > + struct device_node *end_node, *phandle, *remote; > + struct i2c_adapter *ddc; > + > + end_node = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1); > + if (!end_node) { > + dev_err(dev, "Missing connector endpoint\n"); > + return ERR_PTR(-ENODEV); > + } > + > + remote = of_graph_get_remote_port_parent(end_node); > + of_node_put(end_node); > + if (!remote) { > + dev_err(dev, "Enable to parse remote node\n"); > + return ERR_PTR(-EINVAL); > + } > + > + phandle = of_parse_phandle(remote, "ddc-i2c-bus", 0); > + of_node_put(remote); > + if (!phandle) > + return ERR_PTR(-ENODEV); > + > + ddc = of_get_i2c_adapter_by_node(phandle); > + of_node_put(phandle); > + if (!ddc) > + return ERR_PTR(-EPROBE_DEFER); > + > + return ddc; > +} > + > +static int dumb_vga_probe(struct platform_device *pdev) > +{ > + struct dumb_vga *vga; > + int ret; > + > + vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL); > + if (!vga) > + return -ENOMEM; > + platform_set_drvdata(pdev, vga); > + > + vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev); > + if (IS_ERR(vga->ddc)) { > + if (PTR_ERR(vga->ddc) == -ENODEV) { > + dev_info(&pdev->dev, > + "No i2c bus specified... Disabling EDID readout\n"); > + } else { > + dev_err(&pdev->dev, "Couldn't retrieve i2c bus\n"); > + return PTR_ERR(vga->ddc); > + } > + } > + > + vga->bridge.funcs = &dumb_vga_bridge_funcs; > + vga->bridge.of_node = pdev->dev.of_node; > + > + ret = drm_bridge_add(&vga->bridge); > + if (ret && !IS_ERR(vga->ddc)) > + i2c_put_adapter(vga->ddc); > + > + return ret; > +} > + > +static int dumb_vga_remove(struct platform_device *pdev) > +{ > + struct dumb_vga *vga = platform_get_drvdata(pdev); > + > + drm_bridge_remove(&vga->bridge); > + > + if (!IS_ERR(vga->ddc)) > + i2c_put_adapter(vga->ddc); > + > + return 0; > +} > + > +static const struct of_device_id dumb_vga_match[] = { > + { .compatible = "dumb-vga-bridge" }, > + {}, > +}; > +MODULE_DEVICE_TABLE(of, dumb_vga_match); > + > +struct platform_driver dumb_vga_driver = { > + .probe = dumb_vga_probe, > + .remove = dumb_vga_remove, > + .driver = { > + .name = "dumb-vga-bridge", > + .of_match_table = dumb_vga_match, > + }, > +}; > +module_platform_driver(dumb_vga_driver); > + > +MODULE_AUTHOR("Maxime Ripard "); > +MODULE_DESCRIPTION("Dumb RGB to VGA bridge driver"); > +MODULE_LICENSE("GPL"); > -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project From mboxrd@z Thu Jan 1 00:00:00 1970 From: Archit Taneja Subject: Re: [PATCH v2 4/7] drm/bridge: Add RGB to VGA bridge support Date: Thu, 21 Jul 2016 15:23:18 +0530 Message-ID: <57909B8E.7030105@codeaurora.org> References: <20160720095857.12297-1-maxime.ripard@free-electrons.com> <20160720095857.12297-5-maxime.ripard@free-electrons.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20160720095857.12297-5-maxime.ripard@free-electrons.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Maxime Ripard , Rob Herring , Daniel Vetter , David Airlie Cc: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, Chen-Yu Tsai , Laurent Pinchart , dri-devel@lists.freedesktop.org List-Id: devicetree@vger.kernel.org SGksCgpPbiAwNy8yMC8yMDE2IDAzOjI4IFBNLCBNYXhpbWUgUmlwYXJkIHdyb3RlOgo+IFNvbWUg Ym9hcmRzIGhhdmUgYW4gZW50aXJlbHkgcGFzc2l2ZSBSR0IgdG8gVkdBIGJyaWRnZSwgYmFzZWQg b24gZWl0aGVyCj4gREFDcyBvciByZXNpc3RvciBsYWRkZXJzLgo+Cj4gVGhvc2UgbWlnaHQgb3Ig bWlnaHQgbm90IGhhdmUgYW4gaTJjIGJ1cyByb3V0ZWQgdG8gdGhlIFZHQSBjb25uZWN0b3IgaW4K PiBvcmRlciB0byBhY2Nlc3MgdGhlIHNjcmVlbiBFRElEcy4KPgo+IEFkZCBhIGJyaWRnZSB0aGF0 IGRvZXNuJ3QgZG8gYW55dGhpbmcgYnV0IGV4cG9zZSB0aGUgbW9kZXMgYXZhaWxhYmxlIG9uIHRo ZQo+IHNjcmVlbiwgZWl0aGVyIGJhc2VkIG9uIHRoZSBFRElEcyBpZiBhdmFpbGFibGUsIG9yIGJh c2VkIG9uIHRoZSBYR0EKPiBzdGFuZGFyZHMuCgpPdXIgZXZlbnR1YWwgYWltIGlzIHRvIHNlcGFy YXRlIG91dCB0aGUgY29ubmVjdG9ycyBmcm9tIHRoZSBicmlkZ2UKZHJpdmVycyB3aGVyZXZlciBw b3NzaWJsZS4gSW4gdGhlIGZ1dHVyZSwgYSBLTVMgZHJpdmVyIHVzaW5nIHRoZQpicmlkZ2Ugd291 bGQgYmUgcmVzcG9uc2libGUgZm9yIGVzdGFibGlzaGluZyB0aGUgbGlua3MgYmV0d2Vlbgp0aGUg YnJpZGdlIGFuZCBlbmNvZGVyLCBhbmQgdGhlIGVuY29kZXIgYW5kIGNvbm5lY3Rvci4KCklmIGlu IHRoZSBmdXR1cmUgd2UgcmVtb3ZlIHRoZSBjb25uZWN0b3IgcGllY2VzIGZyb20gdGhpcyBkcml2 ZXIKdG8gY3JlYXRlIGEgc2VwYXJhdGUgZ2VuZXJpYyBWR0EgY29ubmVjdG9yIGRyaXZlciwgd2Un bGwgZW5kIHVwCndpdGggYSBicmlkZ2UgZHJpdmVyIHdob3NlIG1haW4gZnVuY3Rpb25hbGl0eSBp cyB0byBjb252ZXJ0IFJHQgpzaWduYWxzIHRvIFZHQS4gVGhlIEVESUQgcGFydHMgd291bGQgbW92 ZSB0byB0aGUgVkdBIGNvbm5lY3Rvcgpkcml2ZXIuIEluIHlvdXIgcGxhdGZvcm0ncyBjYXNlLCB0 aGVyZSBpcyBubyBzb2Z0d2FyZSBuZWVkZWQKdG8gdHJhbnNsYXRlIFJHQiB0byBWR0EsIGJ1dCBt YXliZSBpbiB0aGUgZnV0dXJlLCB3ZSBtaWdodCBuZWVkCnRvIGFkZCBhbiBvcHRpb25hbCByZWd1 bGF0b3IgaW4gdGhlIGRyaXZlciB0byBzdXBwb3J0IGFub3RoZXIKcGxhdGZvcm0uIFRoZXJlZm9y ZSwgdGhlIGJyaWRnZSBkcml2ZXIgd291bGQgc3RpbGwgYmUgaGFuZHkgdG8KaGF2ZS4KCktlZXBp bmcgdGhpcyBpbiBjb25zaWRlcmF0aW9uLCBJIHRoaW5rIHRoaXMgZHJpdmVyIChhbmQgdGhlIERU CmJpbmRpbmcpIHNob3VsZCBiZSBjYWxsZWQgImR1bWItcmdiLXRvLXZnYS1icmlkZ2UiLCBvcgoi cmdiLXRvLXZnYS1icmlkZ2UiIHNpbmNlIHRoYXQncyB3aGF0IHRoZSBicmlkZ2UgSFcgcHJpbWFy aWx5CmRvZXMuCgpUaGFua3MsCkFyY2hpdAoKPgo+IFNpZ25lZC1vZmYtYnk6IE1heGltZSBSaXBh cmQgPG1heGltZS5yaXBhcmRAZnJlZS1lbGVjdHJvbnMuY29tPgo+IC0tLQo+ICAgLi4uL2JpbmRp bmdzL2Rpc3BsYXkvYnJpZGdlL2R1bWItdmdhLnR4dCAgICAgICAgICAgfCAgNTQgKysrKysKPiAg IGRyaXZlcnMvZ3B1L2RybS9icmlkZ2UvS2NvbmZpZyAgICAgICAgICAgICAgICAgICAgIHwgICA2 ICsKPiAgIGRyaXZlcnMvZ3B1L2RybS9icmlkZ2UvTWFrZWZpbGUgICAgICAgICAgICAgICAgICAg IHwgICAxICsKPiAgIGRyaXZlcnMvZ3B1L2RybS9icmlkZ2UvZHVtYi12Z2EuYyAgICAgICAgICAg ICAgICAgIHwgMjMyICsrKysrKysrKysrKysrKysrKysrKwo+ICAgNCBmaWxlcyBjaGFuZ2VkLCAy OTMgaW5zZXJ0aW9ucygrKQo+ICAgY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRpb24vZGV2 aWNldHJlZS9iaW5kaW5ncy9kaXNwbGF5L2JyaWRnZS9kdW1iLXZnYS50eHQKPiAgIGNyZWF0ZSBt b2RlIDEwMDY0NCBkcml2ZXJzL2dwdS9kcm0vYnJpZGdlL2R1bWItdmdhLmMKPgo+IGRpZmYgLS1n aXQgYS9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvZGlzcGxheS9icmlkZ2UvZHVt Yi12Z2EudHh0IGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2Rpc3BsYXkvYnJp ZGdlL2R1bWItdmdhLnR4dAo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMDAw MDAwLi4wMDU2ZmZhMmIzMWQKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvRG9jdW1lbnRhdGlvbi9k ZXZpY2V0cmVlL2JpbmRpbmdzL2Rpc3BsYXkvYnJpZGdlL2R1bWItdmdhLnR4dAo+IEBAIC0wLDAg KzEsNTQgQEAKPiArUGFzc2l2ZSBSR0IgdG8gVkdBIGJyaWRnZQo+ICstLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tCj4gKwo+ICtUaGlzIGJpbmRpbmcgaXMgYWltZWQgZm9yIGVudGlyZWx5IHBhc3Np dmUgUkdCIHRvIFZHQSBicmlkZ2VzIHRoYXQgZG8gbm90Cj4gK3JlcXVpcmUgYW55IGNvbmZpZ3Vy YXRpb24uCj4gKwo+ICtSZXF1aXJlZCBwcm9wZXJ0aWVzOgo+ICsKPiArLSBjb21wYXRpYmxlOiBN dXN0IGJlICJkdW1iLXZnYS1icmlkZ2UiCj4gKwo+ICtSZXF1aXJlZCBub2RlczoKPiArCj4gK1Ro aXMgZGV2aWNlIGhhcyB0d28gdmlkZW8gcG9ydHMuIFRoZWlyIGNvbm5lY3Rpb25zIGFyZSBtb2Rl bGVkIHVzaW5nIHRoZSBPRgo+ICtncmFwaCBiaW5kaW5ncyBzcGVjaWZpZWQgaW4gRG9jdW1lbnRh dGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2dyYXBoLnR4dC4KPiArCj4gKy0gVmlkZW8gcG9ydCAw IGZvciBSR0IgaW5wdXQKPiArLSBWaWRlbyBwb3J0IDEgZm9yIFZHQSBvdXRwdXQKPiArCj4gKwo+ ICtFeGFtcGxlCj4gKy0tLS0tLS0KPiArCj4gK2JyaWRnZSB7Cj4gKwljb21wYXRpYmxlID0gImR1 bWItdmdhLWJyaWRnZSI7Cj4gKwkjYWRkcmVzcy1jZWxscyA9IDwxPjsKPiArCSNzaXplLWNlbGxz ID0gPDA+Owo+ICsKPiArCXBvcnRzIHsKPiArCQkjYWRkcmVzcy1jZWxscyA9IDwxPjsKPiArCQkj c2l6ZS1jZWxscyA9IDwwPjsKPiArCj4gKwkJcG9ydEAwIHsKPiArCQkJI2FkZHJlc3MtY2VsbHMg PSA8MT47Cj4gKwkJCSNzaXplLWNlbGxzID0gPDA+Owo+ICsJCQlyZWcgPSA8MD47Cj4gKwo+ICsJ CQl2Z2FfYnJpZGdlX2luOiBlbmRwb2ludEAwIHsKPiArCQkJCXJlZyA9IDwwPjsKPiArCQkJCXJl bW90ZS1lbmRwb2ludCA9IDwmdGNvbjBfb3V0X3ZnYT47Cj4gKwkJCX07Cj4gKwkJfTsKPiArCj4g KwkJcG9ydEAxIHsKPiArCQkJI2FkZHJlc3MtY2VsbHMgPSA8MT47Cj4gKwkJCSNzaXplLWNlbGxz ID0gPDA+Owo+ICsJCQlyZWcgPSA8MT47Cj4gKwo+ICsJCQl2Z2FfYnJpZGdlX291dDogZW5kcG9p bnRAMCB7Cj4gKwkJCQlyZWcgPSA8MD47Cj4gKwkJCQlyZW1vdGUtZW5kcG9pbnQgPSA8JnZnYV9j b25faW4+Owo+ICsJCQl9Owo+ICsJCX07Cj4gKwl9Owo+ICt9Owo+IGRpZmYgLS1naXQgYS9kcml2 ZXJzL2dwdS9kcm0vYnJpZGdlL0tjb25maWcgYi9kcml2ZXJzL2dwdS9kcm0vYnJpZGdlL0tjb25m aWcKPiBpbmRleCBhMTQxOTIxNDQ1ZjQuLjRhNjU2MDcxNDM5NyAxMDA2NDQKPiAtLS0gYS9kcml2 ZXJzL2dwdS9kcm0vYnJpZGdlL0tjb25maWcKPiArKysgYi9kcml2ZXJzL2dwdS9kcm0vYnJpZGdl L0tjb25maWcKPiBAQCAtMTcsNiArMTcsMTIgQEAgY29uZmlnIERSTV9BTkFMT0dJWF9BTlg3OFhY Cj4gICAJICB0aGUgSERNSSBvdXRwdXQgb2YgYW4gYXBwbGljYXRpb24gcHJvY2Vzc29yIHRvIE15 RFAKPiAgIAkgIG9yIERpc3BsYXlQb3J0Lgo+Cj4gK2NvbmZpZyBEUk1fRFVNQl9WR0EKPiArCXRy aXN0YXRlICJEdW1iIFJHQiB0byBWR0EgQnJpZGdlIHN1cHBvcnQiCj4gKwlzZWxlY3QgRFJNX0tN U19IRUxQRVIKPiArCWhlbHAKPiArCSAgU3VwcG9ydCBmb3IgcGFzc2l2ZSBSR0IgdG8gVkdBIGJy aWRnZXMKPiArCj4gICBjb25maWcgRFJNX0RXX0hETUkKPiAgIAl0cmlzdGF0ZQo+ICAgCXNlbGVj dCBEUk1fS01TX0hFTFBFUgo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vYnJpZGdlL01h a2VmaWxlIGIvZHJpdmVycy9ncHUvZHJtL2JyaWRnZS9NYWtlZmlsZQo+IGluZGV4IGJmZWM5Zjhj YjlkMi4uNDEzZDc4MzgyOGJiIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvZ3B1L2RybS9icmlkZ2Uv TWFrZWZpbGUKPiArKysgYi9kcml2ZXJzL2dwdS9kcm0vYnJpZGdlL01ha2VmaWxlCj4gQEAgLTEs NiArMSw3IEBACj4gICBjY2ZsYWdzLXkgOj0gLUlpbmNsdWRlL2RybQo+Cj4gICBvYmotJChDT05G SUdfRFJNX0FOQUxPR0lYX0FOWDc4WFgpICs9IGFuYWxvZ2l4LWFueDc4eHgubwo+ICtvYmotJChD T05GSUdfRFJNX0RVTUJfVkdBKSArPSBkdW1iLXZnYS5vCj4gICBvYmotJChDT05GSUdfRFJNX0RX X0hETUkpICs9IGR3LWhkbWkubwo+ICAgb2JqLSQoQ09ORklHX0RSTV9EV19IRE1JX0FIQl9BVURJ TykgKz0gZHctaGRtaS1haGItYXVkaW8ubwo+ICAgb2JqLSQoQ09ORklHX0RSTV9OWFBfUFROMzQ2 MCkgKz0gbnhwLXB0bjM0NjAubwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vYnJpZGdl L2R1bWItdmdhLmMgYi9kcml2ZXJzL2dwdS9kcm0vYnJpZGdlL2R1bWItdmdhLmMKPiBuZXcgZmls ZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAwMDAwMC4uYzE5N2JlNTkxZmI2Cj4gLS0tIC9k ZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9icmlkZ2UvZHVtYi12Z2EuYwo+IEBAIC0w LDAgKzEsMjMyIEBACj4gKwo+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+Cj4gKyNpbmNsdWRl IDxsaW51eC9vZl9ncmFwaC5oPgo+ICsKPiArI2luY2x1ZGUgPGRybS9kcm1QLmg+Cj4gKyNpbmNs dWRlIDxkcm0vZHJtX2F0b21pY19oZWxwZXIuaD4KPiArI2luY2x1ZGUgPGRybS9kcm1fY3J0Yy5o Pgo+ICsjaW5jbHVkZSA8ZHJtL2RybV9jcnRjX2hlbHBlci5oPgo+ICsKPiArc3RydWN0IGR1bWJf dmdhIHsKPiArCXN0cnVjdCBkcm1fYnJpZGdlCWJyaWRnZTsKPiArCXN0cnVjdCBkcm1fY29ubmVj dG9yCWNvbm5lY3RvcjsKPiArCj4gKwlzdHJ1Y3QgaTJjX2FkYXB0ZXIJKmRkYzsKPiArfTsKPiAr Cj4gK3N0YXRpYyBpbmxpbmUgc3RydWN0IGR1bWJfdmdhICoKPiArZHJtX2JyaWRnZV90b19kdW1i X3ZnYShzdHJ1Y3QgZHJtX2JyaWRnZSAqYnJpZGdlKQo+ICt7Cj4gKwlyZXR1cm4gY29udGFpbmVy X29mKGJyaWRnZSwgc3RydWN0IGR1bWJfdmdhLCBicmlkZ2UpOwo+ICt9Cj4gKwo+ICtzdGF0aWMg aW5saW5lIHN0cnVjdCBkdW1iX3ZnYSAqCj4gK2RybV9jb25uZWN0b3JfdG9fZHVtYl92Z2Eoc3Ry dWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvcikKPiArewo+ICsJcmV0dXJuIGNvbnRhaW5lcl9v Zihjb25uZWN0b3IsIHN0cnVjdCBkdW1iX3ZnYSwgY29ubmVjdG9yKTsKPiArfQo+ICsKPiArc3Rh dGljIGludCBkdW1iX3ZnYV9nZXRfbW9kZXMoc3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3Rv cikKPiArewo+ICsJc3RydWN0IGR1bWJfdmdhICp2Z2EgPSBkcm1fY29ubmVjdG9yX3RvX2R1bWJf dmdhKGNvbm5lY3Rvcik7Cj4gKwlzdHJ1Y3QgZWRpZCAqZWRpZDsKPiArCWludCByZXQ7Cj4gKwo+ ICsJaWYgKElTX0VSUih2Z2EtPmRkYykpCj4gKwkJZ290byBmYWxsYmFjazsKPiArCj4gKwllZGlk ID0gZHJtX2dldF9lZGlkKGNvbm5lY3RvciwgdmdhLT5kZGMpOwo+ICsJaWYgKCFlZGlkKSB7Cj4g KwkJRFJNX0lORk8oIkVESUQgcmVhZG91dCBmYWlsZWQsIGZhbGxpbmcgYmFjayB0byBzdGFuZGFy ZCBtb2Rlc1xuIik7Cj4gKwkJZ290byBmYWxsYmFjazsKPiArCX0KPiArCj4gKwlkcm1fbW9kZV9j b25uZWN0b3JfdXBkYXRlX2VkaWRfcHJvcGVydHkoY29ubmVjdG9yLCBlZGlkKTsKPiArCXJldHVy biBkcm1fYWRkX2VkaWRfbW9kZXMoY29ubmVjdG9yLCBlZGlkKTsKPiArCj4gK2ZhbGxiYWNrOgo+ ICsJLyoKPiArCSAqIEluIGNhc2Ugd2UgY2Fubm90IHJldHJpZXZlIHRoZSBFRElEcyAoYnJva2Vu IG9yIG1pc3NpbmcgaTJjCj4gKwkgKiBidXMpLCBmYWxsYmFjayBvbiB0aGUgWEdBIHN0YW5kYXJk cwo+ICsJICovCj4gKwlyZXQgPSBkcm1fYWRkX21vZGVzX25vZWRpZChjb25uZWN0b3IsIDE5MjAs IDEyMDApOwo+ICsKPiArCS8qIEFuZCBwcmVmZXIgYSBtb2RlIHByZXR0eSBtdWNoIGFueW9uZSBj YW4gaGFuZGxlICovCj4gKwlkcm1fc2V0X3ByZWZlcnJlZF9tb2RlKGNvbm5lY3RvciwgMTAyNCwg NzY4KTsKPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IGRybV9l bmNvZGVyICoKPiArZHVtYl92Z2FfYmVzdF9lbmNvZGVyKHN0cnVjdCBkcm1fY29ubmVjdG9yICpj b25uZWN0b3IpCj4gK3sKPiArCXN0cnVjdCBkdW1iX3ZnYSAqdmdhID0gZHJtX2Nvbm5lY3Rvcl90 b19kdW1iX3ZnYShjb25uZWN0b3IpOwo+ICsKPiArCXJldHVybiB2Z2EtPmJyaWRnZS5lbmNvZGVy Owo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IGRybV9jb25uZWN0b3JfaGVscGVyX2Z1bmNzIGR1 bWJfdmdhX2Nvbl9oZWxwZXJfZnVuY3MgPSB7Cj4gKwkuZ2V0X21vZGVzCT0gZHVtYl92Z2FfZ2V0 X21vZGVzLAo+ICsJLmJlc3RfZW5jb2Rlcgk9IGR1bWJfdmdhX2Jlc3RfZW5jb2RlciwKPiArfTsK PiArCj4gK3N0YXRpYyBlbnVtIGRybV9jb25uZWN0b3Jfc3RhdHVzCj4gK2R1bWJfdmdhX2Nvbm5l Y3Rvcl9kZXRlY3Qoc3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvciwgYm9vbCBmb3JjZSkK PiArewo+ICsJc3RydWN0IGR1bWJfdmdhICp2Z2EgPSBkcm1fY29ubmVjdG9yX3RvX2R1bWJfdmdh KGNvbm5lY3Rvcik7Cj4gKwo+ICsJLyoKPiArCSAqIEV2ZW4gaWYgd2UgaGF2ZSBhbiBJMkMgYnVz LCB3ZSBjYW4ndCBhc3N1bWUgdGhhdCB0aGUgY2FibGUKPiArCSAqIGlzIGRpc2Nvbm5lY3RlZCBp ZiBkcm1fcHJvYmVfZGRjLiBTb21lIGNhYmxlcyBkb24ndCB3aXJlCj4gKwkgKiB0aGUgRERDIHBp bnMsIG9yIHRoZSBJMkMgYnVzIG1pZ2h0IGJlIGRpc2Z1bmN0aW9uYWwuCj4gKwkgKi8KPiArCWlm ICghSVNfRVJSKHZnYS0+ZGRjKSAmJiBkcm1fcHJvYmVfZGRjKHZnYS0+ZGRjKSkKPiArCQlyZXR1 cm4gY29ubmVjdG9yX3N0YXR1c19jb25uZWN0ZWQ7Cj4gKwo+ICsJcmV0dXJuIGNvbm5lY3Rvcl9z dGF0dXNfdW5rbm93bjsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQKPiArZHVtYl92Z2FfY29ubmVj dG9yX2Rlc3Ryb3koc3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvcikKPiArewo+ICsJZHJt X2Nvbm5lY3Rvcl9jbGVhbnVwKGNvbm5lY3Rvcik7Cj4gK30KPiArCj4gK3N0YXRpYyBzdHJ1Y3Qg ZHJtX2Nvbm5lY3Rvcl9mdW5jcyBkdW1iX3ZnYV9jb25fZnVuY3MgPSB7Cj4gKwkuZHBtcwkJCT0g ZHJtX2F0b21pY19oZWxwZXJfY29ubmVjdG9yX2RwbXMsCj4gKwkuZGV0ZWN0CQkJPSBkdW1iX3Zn YV9jb25uZWN0b3JfZGV0ZWN0LAo+ICsJLmZpbGxfbW9kZXMJCT0gZHJtX2hlbHBlcl9wcm9iZV9z aW5nbGVfY29ubmVjdG9yX21vZGVzLAo+ICsJLmRlc3Ryb3kJCT0gZHVtYl92Z2FfY29ubmVjdG9y X2Rlc3Ryb3ksCj4gKwkucmVzZXQJCQk9IGRybV9hdG9taWNfaGVscGVyX2Nvbm5lY3Rvcl9yZXNl dCwKPiArCS5hdG9taWNfZHVwbGljYXRlX3N0YXRlCT0gZHJtX2F0b21pY19oZWxwZXJfY29ubmVj dG9yX2R1cGxpY2F0ZV9zdGF0ZSwKPiArCS5hdG9taWNfZGVzdHJveV9zdGF0ZQk9IGRybV9hdG9t aWNfaGVscGVyX2Nvbm5lY3Rvcl9kZXN0cm95X3N0YXRlLAo+ICt9Owo+ICsKPiArc3RhdGljIGlu dCBkdW1iX3ZnYV9hdHRhY2goc3RydWN0IGRybV9icmlkZ2UgKmJyaWRnZSkKPiArewo+ICsJc3Ry dWN0IGR1bWJfdmdhICp2Z2EgPSBkcm1fYnJpZGdlX3RvX2R1bWJfdmdhKGJyaWRnZSk7Cj4gKwlp bnQgcmV0Owo+ICsKPiArCWlmICghYnJpZGdlLT5lbmNvZGVyKSB7Cj4gKwkJRFJNX0VSUk9SKCJN aXNzaW5nIGVuY29kZXJcbiIpOwo+ICsJCXJldHVybiAtRU5PREVWOwo+ICsJfQo+ICsKPiArCWRy bV9jb25uZWN0b3JfaGVscGVyX2FkZCgmdmdhLT5jb25uZWN0b3IsCj4gKwkJCQkgJmR1bWJfdmdh X2Nvbl9oZWxwZXJfZnVuY3MpOwo+ICsJcmV0ID0gZHJtX2Nvbm5lY3Rvcl9pbml0KGJyaWRnZS0+ ZGV2LCAmdmdhLT5jb25uZWN0b3IsCj4gKwkJCQkgJmR1bWJfdmdhX2Nvbl9mdW5jcywgRFJNX01P REVfQ09OTkVDVE9SX1ZHQSk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJRFJNX0VSUk9SKCJGYWlsZWQg dG8gaW5pdGlhbGl6ZSBjb25uZWN0b3JcbiIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ ICsJZHJtX21vZGVfY29ubmVjdG9yX2F0dGFjaF9lbmNvZGVyKCZ2Z2EtPmNvbm5lY3RvciwKPiAr CQkJCQkgIGJyaWRnZS0+ZW5jb2Rlcik7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0 YXRpYyB2b2lkIGR1bWJfdmdhX25vcChzdHJ1Y3QgZHJtX2JyaWRnZSAqYnJpZGdlKSB7fTsKPiAr Cj4gK3N0YXRpYyBzdHJ1Y3QgZHJtX2JyaWRnZV9mdW5jcyBkdW1iX3ZnYV9icmlkZ2VfZnVuY3Mg PSB7Cj4gKwkuYXR0YWNoCQk9IGR1bWJfdmdhX2F0dGFjaCwKPiArCS5lbmFibGUJCT0gZHVtYl92 Z2Ffbm9wLAo+ICsJLmRpc2FibGUJPSBkdW1iX3ZnYV9ub3AsCj4gKwkucHJlX2VuYWJsZQk9IGR1 bWJfdmdhX25vcCwKPiArCS5wb3N0X2Rpc2FibGUJPSBkdW1iX3ZnYV9ub3AsCgpXZSBkb24ndCBu ZWVkIHRvIGluc3RhbGwgbm9wcyBoZXJlLCB0aGUgZHJtIGJyaWRnZSBjb3JlIHNraXBzCmNhbGxp bmcgdGhlIG9wIGlmIGl0IGNhbid0IGZpbmQgaXQuCgo+ICt9Owo+ICsKPiArc3RhdGljIHN0cnVj dCBpMmNfYWRhcHRlciAqZHVtYl92Z2FfcmV0cmlldmVfZGRjKHN0cnVjdCBkZXZpY2UgKmRldikK PiArewo+ICsJc3RydWN0IGRldmljZV9ub2RlICplbmRfbm9kZSwgKnBoYW5kbGUsICpyZW1vdGU7 Cj4gKwlzdHJ1Y3QgaTJjX2FkYXB0ZXIgKmRkYzsKPiArCj4gKwllbmRfbm9kZSA9IG9mX2dyYXBo X2dldF9lbmRwb2ludF9ieV9yZWdzKGRldi0+b2Zfbm9kZSwgMSwgLTEpOwo+ICsJaWYgKCFlbmRf bm9kZSkgewo+ICsJCWRldl9lcnIoZGV2LCAiTWlzc2luZyBjb25uZWN0b3IgZW5kcG9pbnRcbiIp Owo+ICsJCXJldHVybiBFUlJfUFRSKC1FTk9ERVYpOwo+ICsJfQo+ICsKPiArCXJlbW90ZSA9IG9m X2dyYXBoX2dldF9yZW1vdGVfcG9ydF9wYXJlbnQoZW5kX25vZGUpOwo+ICsJb2Zfbm9kZV9wdXQo ZW5kX25vZGUpOwo+ICsJaWYgKCFyZW1vdGUpIHsKPiArCQlkZXZfZXJyKGRldiwgIkVuYWJsZSB0 byBwYXJzZSByZW1vdGUgbm9kZVxuIik7Cj4gKwkJcmV0dXJuIEVSUl9QVFIoLUVJTlZBTCk7Cj4g Kwl9Cj4gKwo+ICsJcGhhbmRsZSA9IG9mX3BhcnNlX3BoYW5kbGUocmVtb3RlLCAiZGRjLWkyYy1i dXMiLCAwKTsKPiArCW9mX25vZGVfcHV0KHJlbW90ZSk7Cj4gKwlpZiAoIXBoYW5kbGUpCj4gKwkJ cmV0dXJuIEVSUl9QVFIoLUVOT0RFVik7Cj4gKwo+ICsJZGRjID0gb2ZfZ2V0X2kyY19hZGFwdGVy X2J5X25vZGUocGhhbmRsZSk7Cj4gKwlvZl9ub2RlX3B1dChwaGFuZGxlKTsKPiArCWlmICghZGRj KQo+ICsJCXJldHVybiBFUlJfUFRSKC1FUFJPQkVfREVGRVIpOwo+ICsKPiArCXJldHVybiBkZGM7 Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgZHVtYl92Z2FfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2Rl dmljZSAqcGRldikKPiArewo+ICsJc3RydWN0IGR1bWJfdmdhICp2Z2E7Cj4gKwlpbnQgcmV0Owo+ ICsKPiArCXZnYSA9IGRldm1fa3phbGxvYygmcGRldi0+ZGV2LCBzaXplb2YoKnZnYSksIEdGUF9L RVJORUwpOwo+ICsJaWYgKCF2Z2EpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwlwbGF0Zm9ybV9z ZXRfZHJ2ZGF0YShwZGV2LCB2Z2EpOwo+ICsKPiArCXZnYS0+ZGRjID0gZHVtYl92Z2FfcmV0cmll dmVfZGRjKCZwZGV2LT5kZXYpOwo+ICsJaWYgKElTX0VSUih2Z2EtPmRkYykpIHsKPiArCQlpZiAo UFRSX0VSUih2Z2EtPmRkYykgPT0gLUVOT0RFVikgewo+ICsJCQlkZXZfaW5mbygmcGRldi0+ZGV2 LAo+ICsJCQkJICJObyBpMmMgYnVzIHNwZWNpZmllZC4uLiBEaXNhYmxpbmcgRURJRCByZWFkb3V0 XG4iKTsKPiArCQl9IGVsc2Ugewo+ICsJCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJDb3VsZG4ndCBy ZXRyaWV2ZSBpMmMgYnVzXG4iKTsKPiArCQkJcmV0dXJuIFBUUl9FUlIodmdhLT5kZGMpOwo+ICsJ CX0KPiArCX0KPiArCj4gKwl2Z2EtPmJyaWRnZS5mdW5jcyA9ICZkdW1iX3ZnYV9icmlkZ2VfZnVu Y3M7Cj4gKwl2Z2EtPmJyaWRnZS5vZl9ub2RlID0gcGRldi0+ZGV2Lm9mX25vZGU7Cj4gKwo+ICsJ cmV0ID0gZHJtX2JyaWRnZV9hZGQoJnZnYS0+YnJpZGdlKTsKPiArCWlmIChyZXQgJiYgIUlTX0VS Uih2Z2EtPmRkYykpCj4gKwkJaTJjX3B1dF9hZGFwdGVyKHZnYS0+ZGRjKTsKPiArCj4gKwlyZXR1 cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGR1bWJfdmdhX3JlbW92ZShzdHJ1Y3QgcGxh dGZvcm1fZGV2aWNlICpwZGV2KQo+ICt7Cj4gKwlzdHJ1Y3QgZHVtYl92Z2EgKnZnYSA9IHBsYXRm b3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsKPiArCWRybV9icmlkZ2VfcmVtb3ZlKCZ2Z2EtPmJy aWRnZSk7Cj4gKwo+ICsJaWYgKCFJU19FUlIodmdhLT5kZGMpKQo+ICsJCWkyY19wdXRfYWRhcHRl cih2Z2EtPmRkYyk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBjb25zdCBz dHJ1Y3Qgb2ZfZGV2aWNlX2lkIGR1bWJfdmdhX21hdGNoW10gPSB7Cj4gKwl7IC5jb21wYXRpYmxl ID0gImR1bWItdmdhLWJyaWRnZSIgfSwKPiArCXt9LAo+ICt9Owo+ICtNT0RVTEVfREVWSUNFX1RB QkxFKG9mLCBkdW1iX3ZnYV9tYXRjaCk7Cj4gKwo+ICtzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIGR1 bWJfdmdhX2RyaXZlciA9IHsKPiArCS5wcm9iZQk9IGR1bWJfdmdhX3Byb2JlLAo+ICsJLnJlbW92 ZQk9IGR1bWJfdmdhX3JlbW92ZSwKPiArCS5kcml2ZXIJCT0gewo+ICsJCS5uYW1lCQk9ICJkdW1i LXZnYS1icmlkZ2UiLAo+ICsJCS5vZl9tYXRjaF90YWJsZQk9IGR1bWJfdmdhX21hdGNoLAo+ICsJ fSwKPiArfTsKPiArbW9kdWxlX3BsYXRmb3JtX2RyaXZlcihkdW1iX3ZnYV9kcml2ZXIpOwo+ICsK PiArTU9EVUxFX0FVVEhPUigiTWF4aW1lIFJpcGFyZCA8bWF4aW1lLnJpcGFyZEBmcmVlLWVsZWN0 cm9ucy5jb20+Iik7Cj4gK01PRFVMRV9ERVNDUklQVElPTigiRHVtYiBSR0IgdG8gVkdBIGJyaWRn ZSBkcml2ZXIiKTsKPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo+CgotLSAKUXVhbGNvbW0gSW5u b3ZhdGlvbiBDZW50ZXIsIEluYy4gaXMgYSBtZW1iZXIgb2YgQ29kZSBBdXJvcmEgRm9ydW0sCmEg TGludXggRm91bmRhdGlvbiBDb2xsYWJvcmF0aXZlIFByb2plY3QKX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX18KZHJpLWRldmVsIG1haWxpbmcgbGlzdApkcmkt ZGV2ZWxAbGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3Jn L21haWxtYW4vbGlzdGluZm8vZHJpLWRldmVsCg==