From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 15B22C0015E for ; Wed, 9 Aug 2023 22:52:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230330AbjHIWwA (ORCPT ); Wed, 9 Aug 2023 18:52:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35664 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229581AbjHIWv7 (ORCPT ); Wed, 9 Aug 2023 18:51:59 -0400 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 00904E40; Wed, 9 Aug 2023 15:51:56 -0700 (PDT) Received: by mail.gandi.net (Postfix) with ESMTPSA id 7AD3B1BF203; Wed, 9 Aug 2023 22:51:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1691621515; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jEZMIjoThHvWDZsE2t+JOKqFu6GJgeCpp6/meCiTKh0=; b=lWkaGs+8EJwvimk1mkbgDCw4Ba5PKhoyBJwdO+81/HIHIZfUsvBh2T016eclaaWqK4ReIf u3YdEvX9VzXu9j2ysJtbSLvFc0MkLuutFuWDMZ4l0EPfPOTdrKBfT1GjHrxvDzWJcZyJp9 y84yNlFmXMkcpNQT/K0jI0dJbNtgYx+jMAzINDzPsnU4ZCQ+xwNcjWd0TP6d1fpTRx/Y/l o5t2S4J58WsiudZd0n3aGR8GrrZHOmITEKF3oHvteJMeLsj4cbh7BRRi81Z4K5Wiv4aObt gd/Iq0Jyc+WVxlsJpGPu7dEuFEvvfK2I7hwjvCrht9gyCLQ0UekV3A/M5d43XA== Date: Thu, 10 Aug 2023 00:51:53 +0200 From: Alexandre Belloni To: Jacky Huang Cc: a.zummo@towertech.it, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, linux-rtc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, soc@kernel.org, mjchen@nuvoton.com, schung@nuvoton.com, Jacky Huang Subject: Re: [RESEND PATCH v2 3/3] rtc: Add driver for Nuvoton ma35d1 rtc controller Message-ID: <2023080922515326db190e@mail.local> References: <20230809011542.429945-1-ychuang570808@gmail.com> <20230809011542.429945-4-ychuang570808@gmail.com> <20230809021025a7c0daec@mail.local> <426130f6-7b8a-91f9-559b-afc5afdc656e@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <426130f6-7b8a-91f9-559b-afc5afdc656e@gmail.com> X-GND-Sasl: alexandre.belloni@bootlin.com Precedence: bulk List-ID: X-Mailing-List: linux-rtc@vger.kernel.org On 09/08/2023 16:12:54+0800, Jacky Huang wrote: > > > On 2023/8/9 上午 10:10, Alexandre Belloni wrote: > > Hello, > > > > On 09/08/2023 01:15:42+0000, Jacky Huang wrote: > > > + > > > +struct ma35_bcd_time { > > > + int bcd_sec; > > > + int bcd_min; > > > + int bcd_hour; > > > + int bcd_mday; > > > + int bcd_mon; > > > + int bcd_year; > > > +}; > > I don't get why this struct is useful. > > I will remove this and modify code. > > > > > + > > > +static irqreturn_t ma35d1_rtc_interrupt(int irq, void *data) > > > +{ > > > + struct ma35_rtc *rtc = (struct ma35_rtc *)data; > > > + unsigned long events = 0, rtc_irq; > > > + > > > + rtc_irq = rtc_reg_read(rtc, MA35_REG_RTC_INTSTS); > > > + > > > + if (rtc_irq & RTC_INTSTS_ALMIF) { > > > + rtc_reg_write(rtc, MA35_REG_RTC_INTSTS, RTC_INTSTS_ALMIF); > > > + events |= RTC_AF | RTC_IRQF; > > > + } > > > + > > > + if (rtc_irq & RTC_INTSTS_TICKIF) { > > > + rtc_reg_write(rtc, MA35_REG_RTC_INTSTS, RTC_INTSTS_TICKIF); > > > + events |= RTC_UF | RTC_IRQF; > > How did you test this path? > > We use BusyBox 'date' command to observe the time changed. > In addition, we wrote a simple code to test it. > (https://github.com/OpenNuvoton/MA35D1_Linux_Applications/tree/master/examples/rtc) > You should probably run rtctest: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/testing/selftests/rtc/rtctest.c > > > + if (settm->tm_year < 100) { > > > + dev_warn(dev, "The year will be between 1970-1999, right?\n"); > > No, don't do that, properly set the rtc hardware range and let the user > > choose their time offset/window. > > We will modify the code as: > > #define MA35_BASE_YEAR 2000 /* assume 20YY not 19YY */ > > int year; > > year = tm->tm_year + 1900 – MA35_BASE_YEAR; > if (year < 0) { >     dev_err(dev, "invalid year: %d\n", year); >     return -EINVAL; > } This is not needed as the rtc core is going to check the value is in the range once you set it. > > > + time = rtc_reg_read(rtc, MA35_REG_RTC_TIME); > > > + cal = rtc_reg_read(rtc, MA35_REG_RTC_CAL); > > > + wday = rtc_reg_read(rtc, MA35_REG_RTC_WEEKDAY); > > Are the registers properly latched when reading? How do you ensure that > > MA35_REG_RTC_TIME didn't change before reading MA35_REG_RTC_CAL ? > > We will update the code as > > do { >     time = rtc_reg_read(rtc, MA35_REG_RTC_TIME); >     cal  = rtc_reg_read(rtc, MA35_REG_RTC_CAL); >     wday = rtc_reg_read(rtc, MA35_REG_RTC_WEEKDAY); > } while ((time != rtc_reg_read(rtc, MA35_REG_RTC_TIME)) || >          (cal != rtc_reg_read(rtc, MA35_REG_RTC_CAL)) || >          (wday != = rtc_reg_read(rtc, MA35_REG_RTC_WEEKDAY)) ); Ok, so this mean your hardware doesn't do latching. I don't think it is necessary to check MA35_REG_RTC_WEEKDAY. > > > > > + > > > + return ma35d1_rtc_bcd2bin(time, cal, wday, tm); > > > +} > > > + > > > +static int ma35d1_rtc_set_time(struct device *dev, struct rtc_time *tm) > > > +{ > > > + struct ma35_rtc *rtc = dev_get_drvdata(dev); > > > + struct ma35_bcd_time gettm; > > > + u32 val; > > > + > > > + ma35d1_rtc_bin2bcd(dev, tm, &gettm); > > > + > > > + val = gettm.bcd_mday | gettm.bcd_mon | gettm.bcd_year; > > > + rtc_reg_write(rtc, MA35_REG_RTC_CAL, val); > > > + > > > + val = gettm.bcd_sec | gettm.bcd_min | gettm.bcd_hour; > > > + rtc_reg_write(rtc, MA35_REG_RTC_TIME, val); > > > + > > Same question about latching, shouldn't you stop the rtc while doing > > this? > > In fact, once enabled, the RTC hardware of MA35D1 cannot be stopped; this is > how the hardware is designed. > Inside the MA35D1 RTC, there's an internal counter that advances by 128 > counts per second. > When the time or date register is updated, the internal counter of the RTC > hardware will automatically reset to 0, > so there is no need to worry about memory latch issues. Ok, great > > > > > + val = tm->tm_wday; > > > + rtc_reg_write(rtc, MA35_REG_RTC_WEEKDAY, val); > > > + > > > + return 0; > > > +} > > > + > > > +static int ma35d1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) > > > +{ > > > + struct ma35_rtc *rtc = dev_get_drvdata(dev); > > > + struct ma35_bcd_time tm; > > > + unsigned long val; > > > + > > > + ma35d1_rtc_bin2bcd(dev, &alrm->time, &tm); > > > + > > > + val = tm.bcd_mday | tm.bcd_mon | tm.bcd_year; > > > + rtc_reg_write(rtc, MA35_REG_RTC_CALM, val); > > > + > > > + val = tm.bcd_sec | tm.bcd_min | tm.bcd_hour; > > > + rtc_reg_write(rtc, MA35_REG_RTC_TALM, val); > > > + > > What about handling alrm.enabled here? > > The MA35D1 RTC hardware design does not have an alarm enable/disable bit. > The decision to utilize the alarm can only be made through enabling or > disabling the alarm interrupt. Exactly, you should use alrm.enabled to enable or disable the alarm interrupt. You can simply call ma35d1_alarm_irq_enable, many drivers are doing this. > > > > + return 0; > > > +} > > > + > > > +static const struct rtc_class_ops ma35d1_rtc_ops = { > > > + .read_time = ma35d1_rtc_read_time, > > > + .set_time = ma35d1_rtc_set_time, > > > + .read_alarm = ma35d1_rtc_read_alarm, > > > + .set_alarm = ma35d1_rtc_set_alarm, > > > + .alarm_irq_enable = ma35d1_alarm_irq_enable, > > > +}; > > > + > > > +static int ma35d1_rtc_probe(struct platform_device *pdev) > > > +{ > > > + struct ma35_rtc *rtc; > > > + struct clk *clk; > > > + u32 regval; > > > + int err; > > > + > > > + rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); > > > + if (!rtc) > > > + return -ENOMEM; > > > + > > > + rtc->rtc_reg = devm_platform_ioremap_resource(pdev, 0); > > > + if (IS_ERR(rtc->rtc_reg)) > > > + return PTR_ERR(rtc->rtc_reg); > > > + > > > + clk = of_clk_get(pdev->dev.of_node, 0); > > > + if (IS_ERR(clk)) > > > + return dev_err_probe(&pdev->dev, PTR_ERR(clk), "failed to find rtc clock\n"); > > > + > > > + err = clk_prepare_enable(clk); > > > + if (err) > > > + return -ENOENT; > > > + > > > + platform_set_drvdata(pdev, rtc); > > > + > > > + rtc->rtcdev = devm_rtc_device_register(&pdev->dev, pdev->name, > > > + &ma35d1_rtc_ops, THIS_MODULE); > > > + if (IS_ERR(rtc->rtcdev)) > > > + return dev_err_probe(&pdev->dev, PTR_ERR(rtc->rtcdev), > > > + "failed to register rtc device\n"); > > This MUST be done last in probe, else you open a race with userspace. > > > > Yes, I will moved it to last in probe. > > > > > + > > > + err = ma35d1_rtc_init(rtc, RTC_INIT_TIMEOUT); > > > + if (err) > > > + return err; > > > + > > I don't believe you should do this on every probe but only when this > > hasn't been done yet. > > > > > + regval = rtc_reg_read(rtc, MA35_REG_RTC_CLKFMT); > > > + regval |= RTC_CLKFMT_24HEN; > > > + rtc_reg_write(rtc, MA35_REG_RTC_CLKFMT, regval); > > > + > > ditto > > I will modify them as: > > If (!(rtc_reg_read(rtc, MA35_REG_RTC_INIT) & RTC_INIT_ACK)) { >     err = ma35d1_rtc_init(rtc, RTC_INIT_TIMEOUT); >     if (err) >         return err; >     regval = rtc_reg_read(rtc, MA35_REG_RTC_CLKFMT); >     regval |= RTC_CLKFMT_24HEN; >     rtc_reg_write(rtc, MA35_REG_RTC_CLKFMT, regval);} > } > > > > > + rtc->irq_num = platform_get_irq(pdev, 0); > > > + > > > + err = devm_request_irq(&pdev->dev, rtc->irq_num, ma35d1_rtc_interrupt, > > > + IRQF_NO_SUSPEND, "ma35d1rtc", rtc); > > > + if (err) > > > + return dev_err_probe(&pdev->dev, err, "Failed to request rtc irq\n"); > > > + > > > + regval = rtc_reg_read(rtc, MA35_REG_RTC_INTEN); > > > + regval |= RTC_INTEN_TICKIEN; > > > + rtc_reg_write(rtc, MA35_REG_RTC_INTEN, regval); > > > + > > > + device_init_wakeup(&pdev->dev, true); > > > + > > You must set the rtc range here. > > I will add: > ma35d1_rtc->rtcdev->range_min = RTC_TIMESTAMP_BEGIN_2000; > ma35d1_rtc->rtcdev->range_max = RTC_TIMESTAMP_END_2099; > Perfect. Maybe you should run rtc-range to check for proper operation in the range: https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/rtc-tools.git/tree/rtc-range.c > > > > + return 0; > > > +} > > > + > > > +static int ma35d1_rtc_suspend(struct platform_device *pdev, pm_message_t state) > > > +{ > > > + struct ma35_rtc *rtc = platform_get_drvdata(pdev); > > > + u32 regval; > > > + > > > + if (device_may_wakeup(&pdev->dev)) > > > + enable_irq_wake(rtc->irq_num); > > > + > > > + regval = rtc_reg_read(rtc, MA35_REG_RTC_INTEN); > > > + regval &= ~RTC_INTEN_TICKIEN; > > > + rtc_reg_write(rtc, MA35_REG_RTC_INTEN, regval); > > This is not what the user is asking, don't do this. Also, how was this > > tested? > > Sure, I will remove these three lines of code. > > We test it with "echo mem > /sys/power/state". > Yes, my point is that if UIE is enabled, then the user wants to be woken up every second. If this is not what is wanted, then UIE has to be disabled before going to suspend. My question is why are you enabling RTC_INTEN_TICKIEN in probe? I don't expect anyone to use an actual hardware tick interrupt, unless the alarm is broken and can't be set every second. This is why I questioned the RTC_UF path because I don't expect it to be taken at all. > > > + > > > + return 0; > > > +} > > > + > > > +static int ma35d1_rtc_resume(struct platform_device *pdev) > > > +{ > > > + struct ma35_rtc *rtc = platform_get_drvdata(pdev); > > > + u32 regval; > > > + > > > + if (device_may_wakeup(&pdev->dev)) > > > + disable_irq_wake(rtc->irq_num); > > > + > > > + regval = rtc_reg_read(rtc, MA35_REG_RTC_INTEN); > > > + regval |= RTC_INTEN_TICKIEN; > > > + rtc_reg_write(rtc, MA35_REG_RTC_INTEN, regval); > > > + > > > + return 0; > > > +} > > > + > > > +static const struct of_device_id ma35d1_rtc_of_match[] = { > > > + { .compatible = "nuvoton,ma35d1-rtc", }, > > > + {}, > > > +}; > > > +MODULE_DEVICE_TABLE(of, ma35d1_rtc_of_match); > > > + > > > +static struct platform_driver ma35d1_rtc_driver = { > > > + .suspend = ma35d1_rtc_suspend, > > > + .resume = ma35d1_rtc_resume, > > > + .probe = ma35d1_rtc_probe, > > > + .driver = { > > > + .name = "rtc-ma35d1", > > > + .of_match_table = ma35d1_rtc_of_match, > > > + }, > > > +}; > > > + > > > +module_platform_driver(ma35d1_rtc_driver); > > > + > > > +MODULE_AUTHOR("Min-Jen Chen "); > > > +MODULE_DESCRIPTION("MA35D1 RTC driver"); > > > +MODULE_LICENSE("GPL"); > > > -- > > > 2.34.1 > > > > > > Best Regards, > Jacky Huang > -- Alexandre Belloni, co-owner and COO, Bootlin Embedded Linux and Kernel engineering https://bootlin.com From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 01F5DC001DE for ; Wed, 9 Aug 2023 22:52:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:Cc:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=YnXpj0BYS77becbsC7/uGKuCj5ADjqa+FFmixgHqwMM=; b=Vy1zbbDrYZUGmQ Pv4PDGeXv/Hg5kRDe8r3JnoPEaxYC6lIiavNA0JaApklNi6ts1nVOlOfnPO7ErvpSOJMXC5caIipO IpxSlWGWMhyYFVb2vFPqzDuvWd8Fkj7Mh4CkOOiZqjJR5mZTS/HoyN1JmhOQtan834HvK89zNCbkC 5/6b8sYzq+LrQO8nj7z3vxeG6GOlrLENTn+VygjxRo4acdqGLuvkzTaKs2/NI6WxA0icqzf0xWHxK /2xekvK+4ys6H2lB1FqrpACCm4seKmgx0+rqClyjlYVgfprhXxx+4BX6AGegt5yaJ1BUjp0bSrl4C 4GzTohA4tAHjAT42stIg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qTs27-0061Kc-2u; Wed, 09 Aug 2023 22:52:03 +0000 Received: from relay8-d.mail.gandi.net ([2001:4b98:dc4:8::228]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qTs23-0061JD-3C for linux-arm-kernel@lists.infradead.org; Wed, 09 Aug 2023 22:52:02 +0000 Received: by mail.gandi.net (Postfix) with ESMTPSA id 7AD3B1BF203; Wed, 9 Aug 2023 22:51:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1691621515; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jEZMIjoThHvWDZsE2t+JOKqFu6GJgeCpp6/meCiTKh0=; b=lWkaGs+8EJwvimk1mkbgDCw4Ba5PKhoyBJwdO+81/HIHIZfUsvBh2T016eclaaWqK4ReIf u3YdEvX9VzXu9j2ysJtbSLvFc0MkLuutFuWDMZ4l0EPfPOTdrKBfT1GjHrxvDzWJcZyJp9 y84yNlFmXMkcpNQT/K0jI0dJbNtgYx+jMAzINDzPsnU4ZCQ+xwNcjWd0TP6d1fpTRx/Y/l o5t2S4J58WsiudZd0n3aGR8GrrZHOmITEKF3oHvteJMeLsj4cbh7BRRi81Z4K5Wiv4aObt gd/Iq0Jyc+WVxlsJpGPu7dEuFEvvfK2I7hwjvCrht9gyCLQ0UekV3A/M5d43XA== Date: Thu, 10 Aug 2023 00:51:53 +0200 From: Alexandre Belloni To: Jacky Huang Cc: a.zummo@towertech.it, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, linux-rtc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, soc@kernel.org, mjchen@nuvoton.com, schung@nuvoton.com, Jacky Huang Subject: Re: [RESEND PATCH v2 3/3] rtc: Add driver for Nuvoton ma35d1 rtc controller Message-ID: <2023080922515326db190e@mail.local> References: <20230809011542.429945-1-ychuang570808@gmail.com> <20230809011542.429945-4-ychuang570808@gmail.com> <20230809021025a7c0daec@mail.local> <426130f6-7b8a-91f9-559b-afc5afdc656e@gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <426130f6-7b8a-91f9-559b-afc5afdc656e@gmail.com> X-GND-Sasl: alexandre.belloni@bootlin.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230809_155200_479510_66640FB4 X-CRM114-Status: GOOD ( 43.97 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org T24gMDkvMDgvMjAyMyAxNjoxMjo1NCswODAwLCBKYWNreSBIdWFuZyB3cm90ZToKPiAKPiAKPiBP biAyMDIzLzgvOSDkuIrljYggMTA6MTAsIEFsZXhhbmRyZSBCZWxsb25pIHdyb3RlOgo+ID4gSGVs bG8sCj4gPiAKPiA+IE9uIDA5LzA4LzIwMjMgMDE6MTU6NDIrMDAwMCwgSmFja3kgSHVhbmcgd3Jv dGU6Cj4gPiA+ICsKPiA+ID4gK3N0cnVjdCBtYTM1X2JjZF90aW1lIHsKPiA+ID4gKwlpbnQgYmNk X3NlYzsKPiA+ID4gKwlpbnQgYmNkX21pbjsKPiA+ID4gKwlpbnQgYmNkX2hvdXI7Cj4gPiA+ICsJ aW50IGJjZF9tZGF5Owo+ID4gPiArCWludCBiY2RfbW9uOwo+ID4gPiArCWludCBiY2RfeWVhcjsK PiA+ID4gK307Cj4gPiBJIGRvbid0IGdldCB3aHkgdGhpcyBzdHJ1Y3QgaXMgdXNlZnVsLgo+IAo+ IEkgd2lsbCByZW1vdmUgdGhpcyBhbmQgbW9kaWZ5IGNvZGUuCj4gCj4gCj4gPiA+ICsKPiA+ID4g K3N0YXRpYyBpcnFyZXR1cm5fdCBtYTM1ZDFfcnRjX2ludGVycnVwdChpbnQgaXJxLCB2b2lkICpk YXRhKQo+ID4gPiArewo+ID4gPiArCXN0cnVjdCBtYTM1X3J0YyAqcnRjID0gKHN0cnVjdCBtYTM1 X3J0YyAqKWRhdGE7Cj4gPiA+ICsJdW5zaWduZWQgbG9uZyBldmVudHMgPSAwLCBydGNfaXJxOwo+ ID4gPiArCj4gPiA+ICsJcnRjX2lycSA9IHJ0Y19yZWdfcmVhZChydGMsIE1BMzVfUkVHX1JUQ19J TlRTVFMpOwo+ID4gPiArCj4gPiA+ICsJaWYgKHJ0Y19pcnEgJiBSVENfSU5UU1RTX0FMTUlGKSB7 Cj4gPiA+ICsJCXJ0Y19yZWdfd3JpdGUocnRjLCBNQTM1X1JFR19SVENfSU5UU1RTLCBSVENfSU5U U1RTX0FMTUlGKTsKPiA+ID4gKwkJZXZlbnRzIHw9IFJUQ19BRiB8IFJUQ19JUlFGOwo+ID4gPiAr CX0KPiA+ID4gKwo+ID4gPiArCWlmIChydGNfaXJxICYgUlRDX0lOVFNUU19USUNLSUYpIHsKPiA+ ID4gKwkJcnRjX3JlZ193cml0ZShydGMsIE1BMzVfUkVHX1JUQ19JTlRTVFMsIFJUQ19JTlRTVFNf VElDS0lGKTsKPiA+ID4gKwkJZXZlbnRzIHw9IFJUQ19VRiB8IFJUQ19JUlFGOwo+ID4gSG93IGRp ZCB5b3UgdGVzdCB0aGlzIHBhdGg/Cj4gCj4gV2UgdXNlIEJ1c3lCb3ggJ2RhdGUnIGNvbW1hbmQg dG8gb2JzZXJ2ZSB0aGUgdGltZSBjaGFuZ2VkLgo+IEluIGFkZGl0aW9uLCB3ZSB3cm90ZSBhIHNp bXBsZSBjb2RlIHRvIHRlc3QgaXQuCj4gKGh0dHBzOi8vZ2l0aHViLmNvbS9PcGVuTnV2b3Rvbi9N QTM1RDFfTGludXhfQXBwbGljYXRpb25zL3RyZWUvbWFzdGVyL2V4YW1wbGVzL3J0YykKPiAKCllv dSBzaG91bGQgcHJvYmFibHkgcnVuIHJ0Y3Rlc3Q6CgpodHRwczovL2dpdC5rZXJuZWwub3JnL3B1 Yi9zY20vbGludXgva2VybmVsL2dpdC90b3J2YWxkcy9saW51eC5naXQvdHJlZS90b29scy90ZXN0 aW5nL3NlbGZ0ZXN0cy9ydGMvcnRjdGVzdC5jCgoKPiA+ID4gKwlpZiAoc2V0dG0tPnRtX3llYXIg PCAxMDApIHsKPiA+ID4gKwkJZGV2X3dhcm4oZGV2LCAiVGhlIHllYXIgd2lsbCBiZSBiZXR3ZWVu IDE5NzAtMTk5OSwgcmlnaHQ/XG4iKTsKPiA+IE5vLCBkb24ndCBkbyB0aGF0LCBwcm9wZXJseSBz ZXQgdGhlIHJ0YyBoYXJkd2FyZSByYW5nZSBhbmQgbGV0IHRoZSB1c2VyCj4gPiBjaG9vc2UgdGhl aXIgdGltZSBvZmZzZXQvd2luZG93Lgo+IAo+IFdlIHdpbGwgbW9kaWZ5IHRoZSBjb2RlIGFzOgo+ IAo+ICNkZWZpbmUgTUEzNV9CQVNFX1lFQVIgMjAwMCAvKiBhc3N1bWUgMjBZWSBub3QgMTlZWSAq Lwo+IAo+IGludCB5ZWFyOwo+IAo+IHllYXIgPSB0bS0+dG1feWVhciArIDE5MDAg4oCTIE1BMzVf QkFTRV9ZRUFSOwo+IGlmICh5ZWFyIDwgMCkgewo+IMKgwqDCoCBkZXZfZXJyKGRldiwgImludmFs aWQgeWVhcjogJWRcbiIsIHllYXIpOwo+IMKgwqDCoCByZXR1cm4gLUVJTlZBTDsKPiB9CgpUaGlz IGlzIG5vdCBuZWVkZWQgYXMgdGhlIHJ0YyBjb3JlIGlzIGdvaW5nIHRvIGNoZWNrIHRoZSB2YWx1 ZSBpcyBpbiB0aGUKcmFuZ2Ugb25jZSB5b3Ugc2V0IGl0LgoKPiA+ID4gKwl0aW1lID0gcnRjX3Jl Z19yZWFkKHJ0YywgTUEzNV9SRUdfUlRDX1RJTUUpOwo+ID4gPiArCWNhbCAgPSBydGNfcmVnX3Jl YWQocnRjLCBNQTM1X1JFR19SVENfQ0FMKTsKPiA+ID4gKwl3ZGF5ID0gcnRjX3JlZ19yZWFkKHJ0 YywgTUEzNV9SRUdfUlRDX1dFRUtEQVkpOwo+ID4gQXJlIHRoZSByZWdpc3RlcnMgcHJvcGVybHkg bGF0Y2hlZCB3aGVuIHJlYWRpbmc/IEhvdyBkbyB5b3UgZW5zdXJlIHRoYXQKPiA+IE1BMzVfUkVH X1JUQ19USU1FIGRpZG4ndCBjaGFuZ2UgYmVmb3JlIHJlYWRpbmcgTUEzNV9SRUdfUlRDX0NBTCA/ Cj4gCj4gV2Ugd2lsbCB1cGRhdGUgdGhlIGNvZGUgYXMKPiAKPiBkbyB7Cj4gwqDCoCDCoHRpbWUg PSBydGNfcmVnX3JlYWQocnRjLCBNQTM1X1JFR19SVENfVElNRSk7Cj4gwqDCoCDCoGNhbMKgID0g cnRjX3JlZ19yZWFkKHJ0YywgTUEzNV9SRUdfUlRDX0NBTCk7Cj4gwqDCoCDCoHdkYXkgPSBydGNf cmVnX3JlYWQocnRjLCBNQTM1X1JFR19SVENfV0VFS0RBWSk7Cj4gfSB3aGlsZSAoKHRpbWUgIT0g cnRjX3JlZ19yZWFkKHJ0YywgTUEzNV9SRUdfUlRDX1RJTUUpKSB8fAo+IMKgwqAgwqDCoMKgwqDC oCAoY2FsICE9IHJ0Y19yZWdfcmVhZChydGMsIE1BMzVfUkVHX1JUQ19DQUwpKSB8fAo+IMKgwqAg wqDCoMKgwqDCoCAod2RheSAhPSA9IHJ0Y19yZWdfcmVhZChydGMsIE1BMzVfUkVHX1JUQ19XRUVL REFZKSkgKTsKCk9rLCBzbyB0aGlzIG1lYW4geW91ciBoYXJkd2FyZSBkb2Vzbid0IGRvIGxhdGNo aW5nLiBJIGRvbid0IHRoaW5rIGl0IGlzCm5lY2Vzc2FyeSB0byBjaGVjayBNQTM1X1JFR19SVENf V0VFS0RBWS4KCj4gCj4gCj4gPiA+ICsKPiA+ID4gKwlyZXR1cm4gbWEzNWQxX3J0Y19iY2QyYmlu KHRpbWUsIGNhbCwgd2RheSwgdG0pOwo+ID4gPiArfQo+ID4gPiArCj4gPiA+ICtzdGF0aWMgaW50 IG1hMzVkMV9ydGNfc2V0X3RpbWUoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgcnRjX3RpbWUg KnRtKQo+ID4gPiArewo+ID4gPiArCXN0cnVjdCBtYTM1X3J0YyAqcnRjID0gZGV2X2dldF9kcnZk YXRhKGRldik7Cj4gPiA+ICsJc3RydWN0IG1hMzVfYmNkX3RpbWUgZ2V0dG07Cj4gPiA+ICsJdTMy IHZhbDsKPiA+ID4gKwo+ID4gPiArCW1hMzVkMV9ydGNfYmluMmJjZChkZXYsIHRtLCAmZ2V0dG0p Owo+ID4gPiArCj4gPiA+ICsJdmFsID0gZ2V0dG0uYmNkX21kYXkgfCBnZXR0bS5iY2RfbW9uIHwg Z2V0dG0uYmNkX3llYXI7Cj4gPiA+ICsJcnRjX3JlZ193cml0ZShydGMsIE1BMzVfUkVHX1JUQ19D QUwsIHZhbCk7Cj4gPiA+ICsKPiA+ID4gKwl2YWwgPSBnZXR0bS5iY2Rfc2VjIHwgZ2V0dG0uYmNk X21pbiB8IGdldHRtLmJjZF9ob3VyOwo+ID4gPiArCXJ0Y19yZWdfd3JpdGUocnRjLCBNQTM1X1JF R19SVENfVElNRSwgdmFsKTsKPiA+ID4gKwo+ID4gU2FtZSBxdWVzdGlvbiBhYm91dCBsYXRjaGlu Zywgc2hvdWxkbid0IHlvdSBzdG9wIHRoZSBydGMgd2hpbGUgZG9pbmcKPiA+IHRoaXM/Cj4gCj4g SW4gZmFjdCwgb25jZSBlbmFibGVkLCB0aGUgUlRDIGhhcmR3YXJlIG9mIE1BMzVEMSBjYW5ub3Qg YmUgc3RvcHBlZDsgdGhpcyBpcwo+IGhvdyB0aGUgaGFyZHdhcmUgaXMgZGVzaWduZWQuCj4gSW5z aWRlIHRoZSBNQTM1RDEgUlRDLCB0aGVyZSdzIGFuIGludGVybmFsIGNvdW50ZXIgdGhhdCBhZHZh bmNlcyBieSAxMjgKPiBjb3VudHMgcGVyIHNlY29uZC4KPiBXaGVuIHRoZSB0aW1lIG9yIGRhdGUg cmVnaXN0ZXIgaXMgdXBkYXRlZCwgdGhlIGludGVybmFsIGNvdW50ZXIgb2YgdGhlIFJUQwo+IGhh cmR3YXJlIHdpbGwgYXV0b21hdGljYWxseSByZXNldCB0byAwLAo+IHNvIHRoZXJlIGlzIG5vIG5l ZWQgdG8gd29ycnkgYWJvdXQgbWVtb3J5IGxhdGNoIGlzc3Vlcy4KCk9rLCBncmVhdAoKPiAKPiAK PiA+ID4gKwl2YWwgPSB0bS0+dG1fd2RheTsKPiA+ID4gKwlydGNfcmVnX3dyaXRlKHJ0YywgTUEz NV9SRUdfUlRDX1dFRUtEQVksIHZhbCk7Cj4gPiA+ICsKPiA+ID4gKwlyZXR1cm4gMDsKPiA+ID4g K30KPiA+ID4gKwo+ID4gPiArc3RhdGljIGludCBtYTM1ZDFfcnRjX3NldF9hbGFybShzdHJ1Y3Qg ZGV2aWNlICpkZXYsIHN0cnVjdCBydGNfd2thbHJtICphbHJtKQo+ID4gPiArewo+ID4gPiArCXN0 cnVjdCBtYTM1X3J0YyAqcnRjID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gPiA+ICsJc3RydWN0 IG1hMzVfYmNkX3RpbWUgdG07Cj4gPiA+ICsJdW5zaWduZWQgbG9uZyB2YWw7Cj4gPiA+ICsKPiA+ ID4gKwltYTM1ZDFfcnRjX2JpbjJiY2QoZGV2LCAmYWxybS0+dGltZSwgJnRtKTsKPiA+ID4gKwo+ ID4gPiArCXZhbCA9IHRtLmJjZF9tZGF5IHwgdG0uYmNkX21vbiB8IHRtLmJjZF95ZWFyOwo+ID4g PiArCXJ0Y19yZWdfd3JpdGUocnRjLCBNQTM1X1JFR19SVENfQ0FMTSwgdmFsKTsKPiA+ID4gKwo+ ID4gPiArCXZhbCA9IHRtLmJjZF9zZWMgfCB0bS5iY2RfbWluIHwgdG0uYmNkX2hvdXI7Cj4gPiA+ ICsJcnRjX3JlZ193cml0ZShydGMsIE1BMzVfUkVHX1JUQ19UQUxNLCB2YWwpOwo+ID4gPiArCj4g PiBXaGF0IGFib3V0IGhhbmRsaW5nIGFscm0uZW5hYmxlZCBoZXJlPwo+IAo+IFRoZSBNQTM1RDEg UlRDIGhhcmR3YXJlIGRlc2lnbiBkb2VzIG5vdCBoYXZlIGFuIGFsYXJtIGVuYWJsZS9kaXNhYmxl IGJpdC4KPiBUaGUgZGVjaXNpb24gdG8gdXRpbGl6ZSB0aGUgYWxhcm0gY2FuIG9ubHkgYmUgbWFk ZSB0aHJvdWdoIGVuYWJsaW5nIG9yCj4gZGlzYWJsaW5nIHRoZSBhbGFybSBpbnRlcnJ1cHQuCgpF eGFjdGx5LCB5b3Ugc2hvdWxkIHVzZSBhbHJtLmVuYWJsZWQgdG8gZW5hYmxlIG9yIGRpc2FibGUg dGhlIGFsYXJtCmludGVycnVwdC4gWW91IGNhbiBzaW1wbHkgY2FsbCBtYTM1ZDFfYWxhcm1faXJx X2VuYWJsZSwgbWFueSBkcml2ZXJzIGFyZQpkb2luZyB0aGlzLgoKPiAKPiA+ID4gKwlyZXR1cm4g MDsKPiA+ID4gK30KPiA+ID4gKwo+ID4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBydGNfY2xhc3Nf b3BzIG1hMzVkMV9ydGNfb3BzID0gewo+ID4gPiArCS5yZWFkX3RpbWUgPSBtYTM1ZDFfcnRjX3Jl YWRfdGltZSwKPiA+ID4gKwkuc2V0X3RpbWUgPSBtYTM1ZDFfcnRjX3NldF90aW1lLAo+ID4gPiAr CS5yZWFkX2FsYXJtID0gbWEzNWQxX3J0Y19yZWFkX2FsYXJtLAo+ID4gPiArCS5zZXRfYWxhcm0g PSBtYTM1ZDFfcnRjX3NldF9hbGFybSwKPiA+ID4gKwkuYWxhcm1faXJxX2VuYWJsZSA9IG1hMzVk MV9hbGFybV9pcnFfZW5hYmxlLAo+ID4gPiArfTsKPiA+ID4gKwo+ID4gPiArc3RhdGljIGludCBt YTM1ZDFfcnRjX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gPiA+ICt7Cj4g PiA+ICsJc3RydWN0IG1hMzVfcnRjICpydGM7Cj4gPiA+ICsJc3RydWN0IGNsayAqY2xrOwo+ID4g PiArCXUzMiByZWd2YWw7Cj4gPiA+ICsJaW50IGVycjsKPiA+ID4gKwo+ID4gPiArCXJ0YyA9IGRl dm1fa3phbGxvYygmcGRldi0+ZGV2LCBzaXplb2YoKnJ0YyksIEdGUF9LRVJORUwpOwo+ID4gPiAr CWlmICghcnRjKQo+ID4gPiArCQlyZXR1cm4gLUVOT01FTTsKPiA+ID4gKwo+ID4gPiArCXJ0Yy0+ cnRjX3JlZyA9IGRldm1fcGxhdGZvcm1faW9yZW1hcF9yZXNvdXJjZShwZGV2LCAwKTsKPiA+ID4g KwlpZiAoSVNfRVJSKHJ0Yy0+cnRjX3JlZykpCj4gPiA+ICsJCXJldHVybiBQVFJfRVJSKHJ0Yy0+ cnRjX3JlZyk7Cj4gPiA+ICsKPiA+ID4gKwljbGsgPSBvZl9jbGtfZ2V0KHBkZXYtPmRldi5vZl9u b2RlLCAwKTsKPiA+ID4gKwlpZiAoSVNfRVJSKGNsaykpCj4gPiA+ICsJCXJldHVybiBkZXZfZXJy X3Byb2JlKCZwZGV2LT5kZXYsIFBUUl9FUlIoY2xrKSwgImZhaWxlZCB0byBmaW5kIHJ0YyBjbG9j a1xuIik7Cj4gPiA+ICsKPiA+ID4gKwllcnIgPSBjbGtfcHJlcGFyZV9lbmFibGUoY2xrKTsKPiA+ ID4gKwlpZiAoZXJyKQo+ID4gPiArCQlyZXR1cm4gLUVOT0VOVDsKPiA+ID4gKwo+ID4gPiArCXBs YXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHJ0Yyk7Cj4gPiA+ICsKPiA+ID4gKwlydGMtPnJ0Y2Rl diA9IGRldm1fcnRjX2RldmljZV9yZWdpc3RlcigmcGRldi0+ZGV2LCBwZGV2LT5uYW1lLAo+ID4g PiArCQkJCQkgICAgICAgJm1hMzVkMV9ydGNfb3BzLCBUSElTX01PRFVMRSk7Cj4gPiA+ICsJaWYg KElTX0VSUihydGMtPnJ0Y2RldikpCj4gPiA+ICsJCXJldHVybiBkZXZfZXJyX3Byb2JlKCZwZGV2 LT5kZXYsIFBUUl9FUlIocnRjLT5ydGNkZXYpLAo+ID4gPiArCQkJCSAgICAgImZhaWxlZCB0byBy ZWdpc3RlciBydGMgZGV2aWNlXG4iKTsKPiA+IFRoaXMgTVVTVCBiZSBkb25lIGxhc3QgaW4gcHJv YmUsIGVsc2UgeW91IG9wZW4gYSByYWNlIHdpdGggdXNlcnNwYWNlLgo+ID4gCj4gCj4gWWVzLCBJ IHdpbGwgbW92ZWQgaXQgdG8gbGFzdCBpbiBwcm9iZS4KPiAKPiAKPiA+ID4gKwo+ID4gPiArCWVy ciA9IG1hMzVkMV9ydGNfaW5pdChydGMsIFJUQ19JTklUX1RJTUVPVVQpOwo+ID4gPiArCWlmIChl cnIpCj4gPiA+ICsJCXJldHVybiBlcnI7Cj4gPiA+ICsKPiA+IEkgZG9uJ3QgYmVsaWV2ZSB5b3Ug c2hvdWxkIGRvIHRoaXMgb24gZXZlcnkgcHJvYmUgYnV0IG9ubHkgd2hlbiB0aGlzCj4gPiBoYXNu J3QgYmVlbiBkb25lIHlldC4KPiA+IAo+ID4gPiArCXJlZ3ZhbCA9IHJ0Y19yZWdfcmVhZChydGMs IE1BMzVfUkVHX1JUQ19DTEtGTVQpOwo+ID4gPiArCXJlZ3ZhbCB8PSBSVENfQ0xLRk1UXzI0SEVO Owo+ID4gPiArCXJ0Y19yZWdfd3JpdGUocnRjLCBNQTM1X1JFR19SVENfQ0xLRk1ULCByZWd2YWwp Owo+ID4gPiArCj4gPiBkaXR0bwo+IAo+IEkgd2lsbCBtb2RpZnkgdGhlbSBhczoKPiAKPiBJZiAo IShydGNfcmVnX3JlYWQocnRjLCBNQTM1X1JFR19SVENfSU5JVCkgJiBSVENfSU5JVF9BQ0spKSB7 Cj4gwqDCoCDCoGVyciA9IG1hMzVkMV9ydGNfaW5pdChydGMsIFJUQ19JTklUX1RJTUVPVVQpOwo+ IMKgwqAgwqBpZiAoZXJyKQo+IMKgwqAgwqDCoMKgwqAgcmV0dXJuIGVycjsKPiDCoMKgIMKgcmVn dmFsID0gcnRjX3JlZ19yZWFkKHJ0YywgTUEzNV9SRUdfUlRDX0NMS0ZNVCk7Cj4gwqDCoCDCoHJl Z3ZhbCB8PSBSVENfQ0xLRk1UXzI0SEVOOwo+IMKgwqAgwqBydGNfcmVnX3dyaXRlKHJ0YywgTUEz NV9SRUdfUlRDX0NMS0ZNVCwgcmVndmFsKTt9Cj4gfQo+IAo+IAo+ID4gPiArCXJ0Yy0+aXJxX251 bSA9IHBsYXRmb3JtX2dldF9pcnEocGRldiwgMCk7Cj4gPiA+ICsKPiA+ID4gKwllcnIgPSBkZXZt X3JlcXVlc3RfaXJxKCZwZGV2LT5kZXYsIHJ0Yy0+aXJxX251bSwgbWEzNWQxX3J0Y19pbnRlcnJ1 cHQsCj4gPiA+ICsJCQkgICAgICAgSVJRRl9OT19TVVNQRU5ELCAibWEzNWQxcnRjIiwgcnRjKTsK PiA+ID4gKwlpZiAoZXJyKQo+ID4gPiArCQlyZXR1cm4gZGV2X2Vycl9wcm9iZSgmcGRldi0+ZGV2 LCBlcnIsICJGYWlsZWQgdG8gcmVxdWVzdCBydGMgaXJxXG4iKTsKPiA+ID4gKwo+ID4gPiArCXJl Z3ZhbCA9IHJ0Y19yZWdfcmVhZChydGMsIE1BMzVfUkVHX1JUQ19JTlRFTik7Cj4gPiA+ICsJcmVn dmFsIHw9IFJUQ19JTlRFTl9USUNLSUVOOwo+ID4gPiArCXJ0Y19yZWdfd3JpdGUocnRjLCBNQTM1 X1JFR19SVENfSU5URU4sIHJlZ3ZhbCk7Cj4gPiA+ICsKPiA+ID4gKwlkZXZpY2VfaW5pdF93YWtl dXAoJnBkZXYtPmRldiwgdHJ1ZSk7Cj4gPiA+ICsKPiA+IFlvdSBtdXN0IHNldCB0aGUgcnRjIHJh bmdlIGhlcmUuCj4gCj4gSSB3aWxsIGFkZDoKPiBtYTM1ZDFfcnRjLT5ydGNkZXYtPnJhbmdlX21p biA9IFJUQ19USU1FU1RBTVBfQkVHSU5fMjAwMDsKPiBtYTM1ZDFfcnRjLT5ydGNkZXYtPnJhbmdl X21heCA9IFJUQ19USU1FU1RBTVBfRU5EXzIwOTk7Cj4gCgpQZXJmZWN0LiBNYXliZSB5b3Ugc2hv dWxkIHJ1biBydGMtcmFuZ2UgdG8gY2hlY2sgZm9yIHByb3BlciBvcGVyYXRpb24gaW4KdGhlIHJh bmdlOgpodHRwczovL2dpdC5rZXJuZWwub3JnL3B1Yi9zY20vbGludXgva2VybmVsL2dpdC9hYmVs bG9uaS9ydGMtdG9vbHMuZ2l0L3RyZWUvcnRjLXJhbmdlLmMKCj4gCj4gPiA+ICsJcmV0dXJuIDA7 Cj4gPiA+ICt9Cj4gPiA+ICsKPiA+ID4gK3N0YXRpYyBpbnQgbWEzNWQxX3J0Y19zdXNwZW5kKHN0 cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYsIHBtX21lc3NhZ2VfdCBzdGF0ZSkKPiA+ID4gK3sK PiA+ID4gKwlzdHJ1Y3QgbWEzNV9ydGMgKnJ0YyA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYp Owo+ID4gPiArCXUzMiByZWd2YWw7Cj4gPiA+ICsKPiA+ID4gKwlpZiAoZGV2aWNlX21heV93YWtl dXAoJnBkZXYtPmRldikpCj4gPiA+ICsJCWVuYWJsZV9pcnFfd2FrZShydGMtPmlycV9udW0pOwo+ ID4gPiArCj4gPiA+ICsJcmVndmFsID0gcnRjX3JlZ19yZWFkKHJ0YywgTUEzNV9SRUdfUlRDX0lO VEVOKTsKPiA+ID4gKwlyZWd2YWwgJj0gflJUQ19JTlRFTl9USUNLSUVOOwo+ID4gPiArCXJ0Y19y ZWdfd3JpdGUocnRjLCBNQTM1X1JFR19SVENfSU5URU4sIHJlZ3ZhbCk7Cj4gPiBUaGlzIGlzIG5v dCB3aGF0IHRoZSB1c2VyIGlzIGFza2luZywgZG9uJ3QgZG8gdGhpcy4gQWxzbywgaG93IHdhcyB0 aGlzCj4gPiB0ZXN0ZWQ/Cj4gCj4gU3VyZSwgSSB3aWxsIHJlbW92ZSB0aGVzZSB0aHJlZSBsaW5l cyBvZiBjb2RlLgo+IAo+IFdlIHRlc3QgaXQgd2l0aCAiZWNobyBtZW0gPiAvc3lzL3Bvd2VyL3N0 YXRlIi4KPiAKClllcywgbXkgcG9pbnQgaXMgdGhhdCBpZiBVSUUgaXMgZW5hYmxlZCwgdGhlbiB0 aGUgdXNlciB3YW50cyB0byBiZSB3b2tlbgp1cCBldmVyeSBzZWNvbmQuIElmIHRoaXMgaXMgbm90 IHdoYXQgaXMgd2FudGVkLCB0aGVuIFVJRSBoYXMgdG8gYmUKZGlzYWJsZWQgYmVmb3JlIGdvaW5n IHRvIHN1c3BlbmQuCgpNeSBxdWVzdGlvbiBpcyB3aHkgYXJlIHlvdSBlbmFibGluZyBSVENfSU5U RU5fVElDS0lFTiBpbiBwcm9iZT8gSSBkb24ndApleHBlY3QgYW55b25lIHRvIHVzZSBhbiBhY3R1 YWwgaGFyZHdhcmUgdGljayBpbnRlcnJ1cHQsIHVubGVzcyB0aGUgYWxhcm0KaXMgYnJva2VuIGFu ZCBjYW4ndCBiZSBzZXQgZXZlcnkgc2Vjb25kLiBUaGlzIGlzIHdoeSBJIHF1ZXN0aW9uZWQgdGhl ClJUQ19VRiBwYXRoIGJlY2F1c2UgSSBkb24ndCBleHBlY3QgaXQgdG8gYmUgdGFrZW4gYXQgYWxs LgoKPiA+ID4gKwo+ID4gPiArCXJldHVybiAwOwo+ID4gPiArfQo+ID4gPiArCj4gPiA+ICtzdGF0 aWMgaW50IG1hMzVkMV9ydGNfcmVzdW1lKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4g PiA+ICt7Cj4gPiA+ICsJc3RydWN0IG1hMzVfcnRjICpydGMgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0 YShwZGV2KTsKPiA+ID4gKwl1MzIgcmVndmFsOwo+ID4gPiArCj4gPiA+ICsJaWYgKGRldmljZV9t YXlfd2FrZXVwKCZwZGV2LT5kZXYpKQo+ID4gPiArCQlkaXNhYmxlX2lycV93YWtlKHJ0Yy0+aXJx X251bSk7Cj4gPiA+ICsKPiA+ID4gKwlyZWd2YWwgPSBydGNfcmVnX3JlYWQocnRjLCBNQTM1X1JF R19SVENfSU5URU4pOwo+ID4gPiArCXJlZ3ZhbCB8PSBSVENfSU5URU5fVElDS0lFTjsKPiA+ID4g KwlydGNfcmVnX3dyaXRlKHJ0YywgTUEzNV9SRUdfUlRDX0lOVEVOLCByZWd2YWwpOwo+ID4gPiAr Cj4gPiA+ICsJcmV0dXJuIDA7Cj4gPiA+ICt9Cj4gPiA+ICsKPiA+ID4gK3N0YXRpYyBjb25zdCBz dHJ1Y3Qgb2ZfZGV2aWNlX2lkIG1hMzVkMV9ydGNfb2ZfbWF0Y2hbXSA9IHsKPiA+ID4gKwl7IC5j b21wYXRpYmxlID0gIm51dm90b24sbWEzNWQxLXJ0YyIsIH0sCj4gPiA+ICsJe30sCj4gPiA+ICt9 Owo+ID4gPiArTU9EVUxFX0RFVklDRV9UQUJMRShvZiwgbWEzNWQxX3J0Y19vZl9tYXRjaCk7Cj4g PiA+ICsKPiA+ID4gK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIG1hMzVkMV9ydGNfZHJp dmVyID0gewo+ID4gPiArCS5zdXNwZW5kICAgID0gbWEzNWQxX3J0Y19zdXNwZW5kLAo+ID4gPiAr CS5yZXN1bWUgICAgID0gbWEzNWQxX3J0Y19yZXN1bWUsCj4gPiA+ICsJLnByb2JlICAgICAgPSBt YTM1ZDFfcnRjX3Byb2JlLAo+ID4gPiArCS5kcml2ZXIJCT0gewo+ID4gPiArCQkubmFtZQk9ICJy dGMtbWEzNWQxIiwKPiA+ID4gKwkJLm9mX21hdGNoX3RhYmxlID0gbWEzNWQxX3J0Y19vZl9tYXRj aCwKPiA+ID4gKwl9LAo+ID4gPiArfTsKPiA+ID4gKwo+ID4gPiArbW9kdWxlX3BsYXRmb3JtX2Ry aXZlcihtYTM1ZDFfcnRjX2RyaXZlcik7Cj4gPiA+ICsKPiA+ID4gK01PRFVMRV9BVVRIT1IoIk1p bi1KZW4gQ2hlbiA8bWpjaGVuQG51dm90b24uY29tPiIpOwo+ID4gPiArTU9EVUxFX0RFU0NSSVBU SU9OKCJNQTM1RDEgUlRDIGRyaXZlciIpOwo+ID4gPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo+ ID4gPiAtLSAKPiA+ID4gMi4zNC4xCj4gPiA+IAo+IAo+IAo+IEJlc3QgUmVnYXJkcywKPiBKYWNr eSBIdWFuZwo+IAoKLS0gCkFsZXhhbmRyZSBCZWxsb25pLCBjby1vd25lciBhbmQgQ09PLCBCb290 bGluCkVtYmVkZGVkIExpbnV4IGFuZCBLZXJuZWwgZW5naW5lZXJpbmcKaHR0cHM6Ly9ib290bGlu LmNvbQoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbGlu dXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRl YWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgt YXJtLWtlcm5lbAo=