From mboxrd@z Thu Jan 1 00:00:00 1970 From: atish.patra@wdc.com (Atish Patra) Date: Fri, 2 Nov 2018 17:00:57 -0700 Subject: SBI extension proposal In-Reply-To: References: <7f2a546a-6ebb-43c6-83a0-5e712ec2e2c7@wdc.com> <3245c74a8dc9f651cb07e382585fa311@mailhost.ics.forth.gr> <5725574a-60c3-26f4-565b-4498c757a8f8@wdc.com> Message-ID: To: linux-riscv@lists.infradead.org List-Id: linux-riscv.lists.infradead.org On 11/2/18 4:45 PM, Nick Kossifidis wrote: > ???? 2018-11-03 01:12, Atish Patra ??????: >> On 11/2/18 8:25 AM, Nick Kossifidis wrote: >>> Hello Atish and thanks for bringing this up, >>> >>> ???? 2018-10-31 20:23, Atish Patra ??????: >>>> Here is a proposal to make SBI a flexible and extensible interface. >>>> It is based on the foundation policy of RISC-V i.e. modularity and >>>> openness. It is designed in such a way that it introduces very few >>>> new >>>> mandatory SBI APIs that are absolutely required to maintain backward >>>> compatibility. Everything else is optional so that it remains an open >>>> standard yet robust. >>>> >>>> 1. Introduction: >>>> ---------------- >>>> The current RISC-V SBI only defines a few mandatory functions such as >>>> inter-processor interrupts (IPI) interface, reprogramming timer, >>>> serial >>>> console and memory barrier instructions. The existing SBI >>>> documentation >>>> can be found here [1]. Many important functionalities such as power >>>> management/cpu-hotplug are not yet defined due to difficulties in >>>> accommodating modifications without breaking the backward >>>> compatibility >>>> with the current interface. >>>> >>>> Its design is inspired by Power State Coordination Interface (PSCI) >>>> from >>>> ARM world. However, it adds only two new mandatory SBI calls >>>> providing >>>> version information and supported APIs, unlike PSCI where a >>>> significant >>>> number of functions are mandatory. The version of the existing SBI >>>> will >>>> be defined as a minimum version(0.1) which will always be backward >>>> compatible. Similarly, any Linux kernel with newer feature will fall >>>> back if an older version of SBI does not support the updated >>>> capabilities. Both the operating system and SEE can be implemented to >>>> be two way backward compatible. >>>> >>>> 2. New functions: >>>> ----------------- >>>> >>>> -- u32 sbi_get_version(void): >>>> >>>> Returns the current SBI version implemented by the firmware. >>>> version: uint32: Bits[31:16] Major Version >>>> Bits[15:0] Minor Version >>>> >>>> The existing SBI version can be 0.1. The proposed version will be at >>>> 0.2 >>>> A different major version may indicate possible incompatible >>>> functions. >>>> A different minor version must be compatible with each other even if >>>> they have a higher number of features. >>>> >>>> -- u32 sbi_check_api(unsigned long start_api_id, unsigned long >>>> count): >>>> >>>> Accepts a start_api_id as an argument and returns if start_api_id to >>>> (start_api_id + count - 1) are supported or not. >>>> The API numbering scheme is described in section 3. >>>> >>>> A count is introduced so that a range of APIs can be checked at one >>>> SBI >>>> call to minimize the M-mode traps. >>>> >>> >>> Is this really needed ? We can determine the SBI version from >>> sbi_get_version, why >>> include an SBI call to perform a check that can easily be performed by >>> the caller >>> instead ? >>> >> >> This API is still in discussion. Probably, an API returning bitmask of >> all the features make more sense ? >> >> However, I feel a separate API is required from sbi_get_version as >> there vendors can choose not to implement some of the features that is >> specified by a version as most of the API set are optional. >> > > We can always rely on the SBI_NOT_SUPPORTED error code you've already > included ;-) That's what sbi_check_api will return if a single API or set of API is not supported. We potentially can return it from individual function calls but having a separate API helps in avoiding making those calls in first place from supervisor level. If we use a bitmask for capabilities we'll be limited by > the encoding. > That was the reason sbi_check_api was introduced. But looking back, I wonder if we ever have more than 24 SBI APIs to deal with!! >>>> -- int sbi_hart_up(unsigned long hartid, unsigned long start, >>>> unsigned >>>> long priv) >>>> >>>> Brings up "hartid" either during initial boot or after a >>>> sbi_hart_down >>>> SBI call. >>>> >>>> "start" points to a runtime-specified address where a hart can enter >>>> into supervisor mode. This must be a physical address. >>>> >>>> "priv" is a private data that caller can use to pass information >>>> about >>>> execution context. >>>> >>>> Return the appropriate SBI error code. >>>> >>>> -- int sbi_hart_suspend(u32 state, unsigned long resume_entry, >>>> unsigned >>>> long priv) >>>> >>>> Suspends the calling hart to a particular power state. Suspended hart >>>> will automatically wake-up based on some wakeup events at >>>> resume_entry >>>> physical address. >>>> >>>> "priv" is a private data that caller can use to pass information >>>> about >>>> execution context. The SBI implementation must save a copy so that >>>> caller can reuse while restoring hart from suspend. >>>> >>>> Return the appropriate SBI error code. >>>> >>>> -- int sbi_hart_down() >>>> >>>> It powers off the hart and will be used in cpu-hotplug. >>>> Only individual hart can remove itself from supervisor mode. It can >>>> be >>>> moved to normal state only by sbi_hart_up function. >>>> >>>> Return the appropriate SBI error code. >>>> >>>> -- u32 sbi_hart_state(unsigned long hartid) >>>> >>>> Returns the RISCV_POWER_STATE for a specific hartid. This will help >>>> make >>>> kexec like functionality more robust. >>>> >>> >>> Instead of the above I believe it would be cleaner and simpler to have >>> an sbi_get_hart_state and an sbi_set_hart_state call. This way we can >>> better handle state transitions and, handle ON/OFF/STANDBY/RETENTION >>> and any other state we come up with, without adding extra sbi calls. >>> >> >> When do you want to use sbi_set_hart_state ? >> The power states will be modified as a part of sbi_hart_down or >> sbi_shutdown/suspend calls anyways. >> > > The idea is to have sbi_set_hart_state instead of > sbi_hart_down/shutdown/suspend/etc. > Instead of having different calls for different states we just have two > calls, one > to get the state and one to set it. This way we have fewer calls and if > we add a > new state we can add it without having to add a new call. > Ahh I see it now. IMHO, having explicit names makes more sense. >>>> -- void sbi_system_shutdown() >>>> >>>> Powers off the entire system. >>>> >>> >>> Don't we already have that ? What's the difference between >>> sbi_system_shutdown >>> and sbi_shutdown ? Does it make sense to use sbi_shutdown and leave >>> the >>> system >>> on with all the harts down ? Maybe we can just say that sbi_shutdown >>> also >>> powers down the system and rename it to sbi_system_shutdown with the >>> same >>> function ID. >>> >> >> Yeah. That's a better. >> >> >>>> 3. SBI API ID numbering scheme: >>>> ------------------------------ >>>> An API Set is a set of SBI APIs which collectively implement some >>>> kind of feature/functionality. >>>> >>>> Let's say SBI API ID is u32 then >>>> Bit[31:24] = API Set Number >>>> Bit[23:0] = API Number within API Set >>>> >>>> Here are few API Sets for SBI v0.2: >>>> 1. Base APIs >>>> API Set Number: 0x0 >>>> Description: Base APIs mandatory for any SBI version >>>> >>>> 2. HART PM APIs >>>> API Set Number: 0x1 >>>> Description: Hart UP/Down/Suspend APIs for per-Hart >>>> power management >>>> >>>> 3. System PM APIs >>>> API Set Number; 0x2 >>>> Description: System Shutdown/Reboot/Suspend for system-level >>>> power management >>>> >>>> 4. Vendor APIs >>>> API Set Number: 0xff >>>> Description: Vendor specific APIs. >>>> There is a possibility that different vendors can choose to assign >>>> same API numbers for different functionality. In that case, vendor >>>> specific strings in Device Tree can be used to verify if a specific >>>> API belongs to the intended vendor or not. >>>> >>> >>> I understand the rationale behind this but I believe it's better to >>> call them services or functions instead of APIs, they are not sets >>> of APIs the way I see it. Also since we are moving that path why call >>> it SBI and restrict it only to be used by the supervisor ? I'd love to >>> have another category for the secure monitor calls for example, >>> but on the software architecture that we are discussing on the TEE >>> group, such calls can also originate from U mode or HS/HU modes. >>> The same goes for vendor specific calls, there are lots of use case >>> scenarios where vendors would like to be able to call their stuff >>> from U mode for example (e.g. a user space library talking to a >>> smart card directly). >>> >>> I suggest we rename it from SBI to something more generic that is not >>> defined by who is calling it but by what we are calling, which in this >>> case is the firmware (FBI?). >> >> possible conflict with a very famous law enforcement agency :) :). >> >> Jokes aside, renaming to something more generic is a good idea. But it >> will probably break a ton of documentation/spec in RISC-V which I >> don't want to deal with right now. May be in future versions ? >> > > I get that updating the documentation can be a pain, I can help with > that if you want (and I promise I'll stay away from law enforcement > agencies !). I suggest we do the renaming as early as possible > because we are going to carry it for a long time instead and it'll > only get harder to change later on. > Thanks. I guess we need Palmer/Andrew to pitch in first on this before we decide anything. >>> Since you mentioned ARM, in their case >>> the ABI used for PSCI is the Secure Monitor Call (which is the >>> alternative >>> to what is defined on the first paragraph of the SBI document), but it >>> has the same limitation. According to the documentation if an SMC >>> comes >>> from a user application, we get an undefined exception. We can do >>> better >>> ! >>> >> >> >> >>> >>>> 4. Return error code Table: >>>> --------------------------- >>>> >>>> Here are the SBI return error codes defined. >>>> >>>> SBI_SUCCESS 0 >>>> SBI_NOT_SUPPORTED -1 >>>> SBI_INVALID_PARAM -2 >>>> SBI_DENIED -3 >>>> SBI_INVALID_ADDRESS -4 >>>> >>>> A mapping function between SBI error code & Linux error code should >>>> be >>>> provided. >>>> >>> >>> I believe it should be up to the OS to translate the SBI error codes >>> to >>> its >>> native ones. >>> >> >> Correct. Olof also pointed this out. I will remove it in next version. >> >>>> 5. Power State >>>> -------------- >>>> >>>> A RISC-V core can exist in any of the following power states. >>>> >>>> enum RISCV_POWER_STATE { >>>> //Powered up & operational. >>>> RISCV_HART_ON = 0, >>>> //Powered up but at reduced energy consumption. WFI >>>> instruction >>>> can be used to achieve this state. >>>> RISCV_HART_STANDBY = 1, >>>> //Deeper low power state. No reset required but higher wakeup >>>> latency. >>>> RISCV_HART_RETENTION = 2, >>>> //Powered off. Reset of the core required after power >>>> restore. >>>> RISCV_HART_OFF = 3 >>>> } >>>> >>>> TODO: >>>> Any other power management related features or state? >>>> >>> >>> How about LOCKSTEP ? We could have a way of declaring a hart as a >>> "mirror" of another >>> hart (https://en.wikipedia.org/wiki/Lockstep_(computing)). We can have >>> an extra argument >>> on sbi_get/set_state when the LOCKSTEP state is used, that will >>> get/set >>> the hart that >>> this hart is mirroring. >>> >> >> Not sure if we need it right now. I want to keep it simple and focus >> on the bare minimum ones. We can always add exotic ones once we have >> feature/versioning in place. >> > > I agree, I mentioned LOCKSTEP because it'll need an extra argument > when setting the state. Btw I know lockstep sounds exotic at this point > but it's needed by many industries that deal with safety (automotive > stuff, > medical devices etc). However it needs more thinking. > >>>> 6. Implementation >>>> ------------------- >>>> Currently, SBI is implemented as a part of BBL. There is a different >>>> SBI implementation available in coreboot as well. >>>> >>>> Alternatively, a separate open BSD/MIT licensed SBI project can be >>>> created which can be used by anybody to avoid these kind of SBI >>>> fragmentation in future. This project can generate both a firmware >>>> binary (to executed directly in M mode) or a static library that can >>>> be used by different boot loaders. It will also help individual boot >>>> loaders to either work from M or S mode without a separate SBI >>>> implementation. >>>> >>> >>> Why implement this at the boot loader level ? This is more like a >>> firmware interface >>> than something that belongs to the bootloader. The bootloader should >>> use >>> this interface >>> not provide it. >> It depends on the bootloader. For example, there are patches in >> coreboot that implements SBI. The idea with OpenSBI implementation is >> to avoid such fragmentation. >> >>> Also this is something that belongs to the M mode, a >>> bootloader >>> should belong to the S mode, running the bootloader in M mode is not >>> right from >>> a security point of view. We can provide something like "RISC-V >>> Firmware >>> Services" >>> that's code running on M mode after the first stage boot >>> loader/BootROM >>> and let >>> bootloaders use it without having to implement it. >> >> That's the idea for S mode bootloaders. However, there are folks who >> are interested in M mode ones and I understand their usecase. Thus, >> idea is to implement OpenSBI in such a way that, everybody can make >> use of it. >> > > I guess then we can provide it as a library and also provide a reference > implementation around it. Yup. That is the exact idea. However I still believe that something like > "RISC-V Firmware Services" is more appropriate, we can structure this > in a client/server way and let bootloaders use the server part and > OS drivers/modules use the client part. This way we can also avoid > fragmentation across OSes. > Thanks for the idea. Let me think about it more. We have just started working on OpenSBI project. I will update when we have something working. Regards, Atish > Regards, > Nick > 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=-2.5 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SPF_PASS, URIBL_BLOCKED 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 BC0ACC32789 for ; Sat, 3 Nov 2018 00:01:15 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 77E472082D for ; Sat, 3 Nov 2018 00:01:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="hB77n2iW"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="r7fNuAw0" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 77E472082D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=wdc.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-riscv-bounces+infradead-linux-riscv=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender:Content-Type: Content-Transfer-Encoding:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date:Message-ID:From: References:To:Subject:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=p3FmpqfW3j98S13KiYA6Ctvo4PHPMOYwGqajGC4VP3M=; b=hB77n2iWVe63VSa4h99rRAeSi QftoIzsY45STYgvqjwQznyk4ulnLJYTKq/vAhDmCvzw44go7K0hsTGmq/6V671CNO/irfw6HaimT+ C1i7eiO5/QuC7YwtKxyiMTY2W01WkBpkOXwbw+hUnwMDLAW0CyykfSIgzTfQnOGfneC0YfwwjhXJc eoSVojK6UXeuc7AlEd9vgz72Cse+Q0lVYdmcZ5F6aadeNzm1TGllzjPo+q0/H4Zz+uNmbViEEl+M0 OduvdeIentsQiJg9/03yMTLFImiLB/fvy4aCTw1Q9xvVONS+ezJgT3TTIwTtWkn/OdupKpxjAIRYB +ZOH8+WfQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gIjNK-0006rU-Hx; Sat, 03 Nov 2018 00:01:14 +0000 Received: from esa2.hgst.iphmx.com ([68.232.143.124]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gIjNG-0006qQ-Cb for linux-riscv@lists.infradead.org; Sat, 03 Nov 2018 00:01:12 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1541203354; x=1572739354; h=subject:to:cc:references:from:message-id:date: mime-version:in-reply-to:content-transfer-encoding; bh=DJ+RFzk4flDh7lK1r3HrjJWgA4jomIWtEznOvlXfOJA=; b=r7fNuAw0acu60BX0J1ZcBmH1NGA/oax7diKC6pGIEuWY5Ld0qbjcibiS B3i7ifrRwpjNEsqhMadYswYd1OICzDj3I0M79BBmQ+rfKCNDHGGCXgyJc vi0GS0adpxrOH7AIEPT9INj8yMS/nJCM4lk3pVDDSQAfNsxfVq1veSaQ+ F1fSJWGORrI1Ef6c8YLDTKQcPav+rn9mvBlt3AXkeIqGfTPqSmrnZycMg UpE2chui3H/vcPWu06nEfwKEbVm9jsR1gkCPoIZfop9klGKHnnuQsYPF5 SL+2Wb05GaH6HnPfcr2ceZ1FgTUETxhoaNXMUaueAgQrWK5pYxdWVtz8W Q==; X-IronPort-AV: E=Sophos;i="5.54,457,1534780800"; d="scan'208";a="191169071" Received: from uls-op-cesaip02.wdc.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 03 Nov 2018 08:02:17 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep02.wdc.com with ESMTP; 02 Nov 2018 16:44:42 -0700 Received: from c02v91rdhtd5.sdcorp.global.sandisk.com (HELO [10.111.69.187]) ([10.111.69.187]) by uls-op-cesaip02.wdc.com with ESMTP; 02 Nov 2018 17:00:58 -0700 Subject: Re: SBI extension proposal To: Nick Kossifidis References: <7f2a546a-6ebb-43c6-83a0-5e712ec2e2c7@wdc.com> <3245c74a8dc9f651cb07e382585fa311@mailhost.ics.forth.gr> <5725574a-60c3-26f4-565b-4498c757a8f8@wdc.com> From: Atish Patra Message-ID: Date: Fri, 2 Nov 2018 17:00:57 -0700 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181102_170110_509079_40B04E35 X-CRM114-Status: GOOD ( 38.18 ) X-BeenThere: linux-riscv@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "mark.rutland@arm.com" , Zong Li , Damien Le Moal , Olof Johansson , Andrew Waterman , Alan Kao , Anup Patel , Palmer Dabbelt , "Rwmjones.fedora" , Christoph Hellwig , "vincentc@andestech.com" , Michael Clark , Arnd Bergmann , Paul Walmsley , "linux-riscv@lists.infradead.org" , "Chang, Abner \(HPS SW/FW Technologist\)" , "David.Abdurachmanov@cern.ch" Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Sender: "linux-riscv" Errors-To: linux-riscv-bounces+infradead-linux-riscv=archiver.kernel.org@lists.infradead.org Message-ID: <20181103000057.IZGN7kys9EklHwV8HEoChwcsEU0hm7h0OQD4Bh29VF4@z> T24gMTEvMi8xOCA0OjQ1IFBNLCBOaWNrIEtvc3NpZmlkaXMgd3JvdGU6Cj4gzqPPhM65z4IgMjAx OC0xMS0wMyAwMToxMiwgQXRpc2ggUGF0cmEgzq3Os8+BzrHPiM61Ogo+PiBPbiAxMS8yLzE4IDg6 MjUgQU0sIE5pY2sgS29zc2lmaWRpcyB3cm90ZToKPj4+IEhlbGxvIEF0aXNoIGFuZCB0aGFua3Mg Zm9yIGJyaW5naW5nIHRoaXMgdXAsCj4+Pgo+Pj4gzqPPhM65z4IgMjAxOC0xMC0zMSAyMDoyMywg QXRpc2ggUGF0cmEgzq3Os8+BzrHPiM61Ogo+Pj4+IEhlcmUgaXMgYSBwcm9wb3NhbCB0byBtYWtl IFNCSSBhIGZsZXhpYmxlIGFuZCBleHRlbnNpYmxlIGludGVyZmFjZS4KPj4+PiBJdCBpcyBiYXNl ZCBvbiB0aGUgZm91bmRhdGlvbiBwb2xpY3kgb2YgUklTQy1WIGkuZS4gbW9kdWxhcml0eSBhbmQK Pj4+PiBvcGVubmVzcy4gSXQgaXMgZGVzaWduZWQgaW4gc3VjaCBhIHdheSB0aGF0IGl0IGludHJv ZHVjZXMgdmVyeSBmZXcKPj4+PiBuZXcKPj4+PiBtYW5kYXRvcnkgU0JJIEFQSXMgdGhhdCBhcmUg YWJzb2x1dGVseSByZXF1aXJlZCB0byBtYWludGFpbiBiYWNrd2FyZAo+Pj4+IGNvbXBhdGliaWxp dHkuIEV2ZXJ5dGhpbmcgZWxzZSBpcyBvcHRpb25hbCBzbyB0aGF0IGl0IHJlbWFpbnMgYW4gb3Bl bgo+Pj4+IHN0YW5kYXJkIHlldCByb2J1c3QuCj4+Pj4KPj4+PiAxLiBJbnRyb2R1Y3Rpb246Cj4+ Pj4gLS0tLS0tLS0tLS0tLS0tLQo+Pj4+IFRoZSBjdXJyZW50IFJJU0MtViBTQkkgb25seSBkZWZp bmVzIGEgZmV3IG1hbmRhdG9yeSBmdW5jdGlvbnMgc3VjaCBhcwo+Pj4+IGludGVyLXByb2Nlc3Nv ciBpbnRlcnJ1cHRzIChJUEkpIGludGVyZmFjZSwgcmVwcm9ncmFtbWluZyB0aW1lciwKPj4+PiBz ZXJpYWwKPj4+PiBjb25zb2xlIGFuZCBtZW1vcnkgYmFycmllciBpbnN0cnVjdGlvbnMuIFRoZSBl eGlzdGluZyBTQkkKPj4+PiBkb2N1bWVudGF0aW9uCj4+Pj4gY2FuIGJlIGZvdW5kIGhlcmUgWzFd LiBNYW55IGltcG9ydGFudCBmdW5jdGlvbmFsaXRpZXMgc3VjaCBhcyBwb3dlcgo+Pj4+IG1hbmFn ZW1lbnQvY3B1LWhvdHBsdWcgYXJlIG5vdCB5ZXQgZGVmaW5lZCBkdWUgdG8gZGlmZmljdWx0aWVz IGluCj4+Pj4gYWNjb21tb2RhdGluZyBtb2RpZmljYXRpb25zIHdpdGhvdXQgYnJlYWtpbmcgdGhl IGJhY2t3YXJkCj4+Pj4gY29tcGF0aWJpbGl0eQo+Pj4+IHdpdGggdGhlIGN1cnJlbnQgaW50ZXJm YWNlLgo+Pj4+Cj4+Pj4gSXRzIGRlc2lnbiBpcyBpbnNwaXJlZCBieSBQb3dlciBTdGF0ZSBDb29y ZGluYXRpb24gSW50ZXJmYWNlIChQU0NJKQo+Pj4+IGZyb20KPj4+PiBBUk0gd29ybGQuIEhvd2V2 ZXIsIGl0IGFkZHMgb25seSB0d28gbmV3IG1hbmRhdG9yeSBTQkkgY2FsbHMKPj4+PiBwcm92aWRp bmcKPj4+PiB2ZXJzaW9uIGluZm9ybWF0aW9uIGFuZCBzdXBwb3J0ZWQgQVBJcywgdW5saWtlIFBT Q0kgd2hlcmUgYQo+Pj4+IHNpZ25pZmljYW50Cj4+Pj4gbnVtYmVyIG9mIGZ1bmN0aW9ucyBhcmUg bWFuZGF0b3J5LiBUaGUgdmVyc2lvbiBvZiB0aGUgZXhpc3RpbmcgU0JJCj4+Pj4gd2lsbAo+Pj4+ IGJlIGRlZmluZWQgYXMgYSBtaW5pbXVtIHZlcnNpb24oMC4xKSB3aGljaCB3aWxsIGFsd2F5cyBi ZSBiYWNrd2FyZAo+Pj4+IGNvbXBhdGlibGUuIFNpbWlsYXJseSwgYW55IExpbnV4IGtlcm5lbCB3 aXRoIG5ld2VyIGZlYXR1cmUgd2lsbCBmYWxsCj4+Pj4gYmFjayBpZiBhbiBvbGRlciB2ZXJzaW9u IG9mIFNCSSBkb2VzIG5vdCBzdXBwb3J0IHRoZSB1cGRhdGVkCj4+Pj4gY2FwYWJpbGl0aWVzLiBC b3RoIHRoZSBvcGVyYXRpbmcgc3lzdGVtIGFuZCBTRUUgY2FuIGJlIGltcGxlbWVudGVkIHRvCj4+ Pj4gYmUgdHdvIHdheSBiYWNrd2FyZCBjb21wYXRpYmxlLgo+Pj4+Cj4+Pj4gMi4gTmV3IGZ1bmN0 aW9uczoKPj4+PiAtLS0tLS0tLS0tLS0tLS0tLQo+Pj4+Cj4+Pj4gLS0gdTMyIHNiaV9nZXRfdmVy c2lvbih2b2lkKToKPj4+Pgo+Pj4+IFJldHVybnMgdGhlIGN1cnJlbnQgU0JJIHZlcnNpb24gaW1w bGVtZW50ZWQgYnkgdGhlIGZpcm13YXJlLgo+Pj4+IHZlcnNpb246IHVpbnQzMjogQml0c1szMTox Nl0gTWFqb3IgVmVyc2lvbgo+Pj4+ICAgICAgICAgICAgICAgIEJpdHNbMTU6MF0gTWlub3IgVmVy c2lvbgo+Pj4+Cj4+Pj4gVGhlIGV4aXN0aW5nIFNCSSB2ZXJzaW9uIGNhbiBiZSAwLjEuIFRoZSBw cm9wb3NlZCB2ZXJzaW9uIHdpbGwgYmUgYXQKPj4+PiAwLjIKPj4+PiBBIGRpZmZlcmVudCBtYWpv ciB2ZXJzaW9uIG1heSBpbmRpY2F0ZSBwb3NzaWJsZSBpbmNvbXBhdGlibGUKPj4+PiBmdW5jdGlv bnMuCj4+Pj4gQSBkaWZmZXJlbnQgbWlub3IgdmVyc2lvbiBtdXN0IGJlIGNvbXBhdGlibGUgd2l0 aCBlYWNoIG90aGVyIGV2ZW4gaWYKPj4+PiB0aGV5IGhhdmUgYSBoaWdoZXIgbnVtYmVyIG9mIGZl YXR1cmVzLgo+Pj4+Cj4+Pj4gLS0gdTMyIHNiaV9jaGVja19hcGkodW5zaWduZWQgbG9uZyBzdGFy dF9hcGlfaWQsIHVuc2lnbmVkIGxvbmcKPj4+PiBjb3VudCk6Cj4+Pj4KPj4+PiBBY2NlcHRzIGEg c3RhcnRfYXBpX2lkIGFzIGFuIGFyZ3VtZW50IGFuZCByZXR1cm5zIGlmIHN0YXJ0X2FwaV9pZCB0 bwo+Pj4+IChzdGFydF9hcGlfaWQgKyBjb3VudCAtIDEpIGFyZSBzdXBwb3J0ZWQgb3Igbm90Lgo+ Pj4+IFRoZSBBUEkgbnVtYmVyaW5nIHNjaGVtZSBpcyBkZXNjcmliZWQgaW4gc2VjdGlvbiAzLgo+ Pj4+Cj4+Pj4gQSBjb3VudCBpcyBpbnRyb2R1Y2VkIHNvIHRoYXQgYSByYW5nZSBvZiBBUElzIGNh biBiZSBjaGVja2VkIGF0IG9uZQo+Pj4+IFNCSQo+Pj4+IGNhbGwgdG8gbWluaW1pemUgdGhlIE0t bW9kZSB0cmFwcy4KPj4+Pgo+Pj4KPj4+IElzIHRoaXMgcmVhbGx5IG5lZWRlZCA/IFdlIGNhbiBk ZXRlcm1pbmUgdGhlIFNCSSB2ZXJzaW9uIGZyb20KPj4+IHNiaV9nZXRfdmVyc2lvbiwgd2h5Cj4+ PiBpbmNsdWRlIGFuIFNCSSBjYWxsIHRvIHBlcmZvcm0gYSBjaGVjayB0aGF0IGNhbiBlYXNpbHkg YmUgcGVyZm9ybWVkIGJ5Cj4+PiB0aGUgY2FsbGVyCj4+PiBpbnN0ZWFkID8KPj4+Cj4+Cj4+IFRo aXMgQVBJIGlzIHN0aWxsIGluIGRpc2N1c3Npb24uIFByb2JhYmx5LCBhbiBBUEkgcmV0dXJuaW5n IGJpdG1hc2sgb2YKPj4gYWxsIHRoZSBmZWF0dXJlcyBtYWtlIG1vcmUgc2Vuc2UgPwo+Pgo+PiBI b3dldmVyLCBJIGZlZWwgYSBzZXBhcmF0ZSBBUEkgaXMgcmVxdWlyZWQgZnJvbSBzYmlfZ2V0X3Zl cnNpb24gYXMKPj4gdGhlcmUgdmVuZG9ycyBjYW4gY2hvb3NlIG5vdCB0byBpbXBsZW1lbnQgc29t ZSBvZiB0aGUgZmVhdHVyZXMgdGhhdCBpcwo+PiBzcGVjaWZpZWQgYnkgYSB2ZXJzaW9uIGFzIG1v c3Qgb2YgdGhlIEFQSSBzZXQgYXJlIG9wdGlvbmFsLgo+Pgo+IAo+IFdlIGNhbiBhbHdheXMgcmVs eSBvbiB0aGUgU0JJX05PVF9TVVBQT1JURUQgZXJyb3IgY29kZSB5b3UndmUgYWxyZWFkeQo+IGlu Y2x1ZGVkIDstKSAKCgpUaGF0J3Mgd2hhdCBzYmlfY2hlY2tfYXBpIHdpbGwgcmV0dXJuIGlmIGEg c2luZ2xlIEFQSSBvciBzZXQgb2YgQVBJIGlzIApub3Qgc3VwcG9ydGVkLiBXZSBwb3RlbnRpYWxs eSBjYW4gcmV0dXJuIGl0IGZyb20gaW5kaXZpZHVhbCBmdW5jdGlvbiAKY2FsbHMgYnV0IGhhdmlu ZyBhIHNlcGFyYXRlIEFQSSBoZWxwcyBpbiBhdm9pZGluZyBtYWtpbmcgdGhvc2UgY2FsbHMgaW4g CmZpcnN0IHBsYWNlIGZyb20gc3VwZXJ2aXNvciBsZXZlbC4KCklmIHdlIHVzZSBhIGJpdG1hc2sg Zm9yIGNhcGFiaWxpdGllcyB3ZSdsbCBiZSBsaW1pdGVkIGJ5Cj4gdGhlIGVuY29kaW5nLgo+IApU aGF0IHdhcyB0aGUgcmVhc29uIHNiaV9jaGVja19hcGkgd2FzIGludHJvZHVjZWQuIEJ1dCBsb29r aW5nIGJhY2ssIEkgCndvbmRlciBpZiB3ZSBldmVyIGhhdmUgbW9yZSB0aGFuIDI0IFNCSSBBUElz IHRvIGRlYWwgd2l0aCEhCgoKPj4+PiAtLSBpbnQgc2JpX2hhcnRfdXAodW5zaWduZWQgbG9uZyBo YXJ0aWQsIHVuc2lnbmVkIGxvbmcgc3RhcnQsCj4+Pj4gdW5zaWduZWQKPj4+PiBsb25nIHByaXYp Cj4+Pj4KPj4+PiBCcmluZ3MgdXAgImhhcnRpZCIgZWl0aGVyIGR1cmluZyBpbml0aWFsIGJvb3Qg b3IgYWZ0ZXIgYQo+Pj4+IHNiaV9oYXJ0X2Rvd24KPj4+PiBTQkkgY2FsbC4KPj4+Pgo+Pj4+ICJz dGFydCIgcG9pbnRzIHRvIGEgcnVudGltZS1zcGVjaWZpZWQgYWRkcmVzcyB3aGVyZSBhIGhhcnQg Y2FuIGVudGVyCj4+Pj4gaW50byBzdXBlcnZpc29yIG1vZGUuIFRoaXMgbXVzdCBiZSBhIHBoeXNp Y2FsIGFkZHJlc3MuCj4+Pj4KPj4+PiAicHJpdiIgaXMgYSBwcml2YXRlIGRhdGEgdGhhdCBjYWxs ZXIgY2FuIHVzZSB0byBwYXNzIGluZm9ybWF0aW9uCj4+Pj4gYWJvdXQKPj4+PiBleGVjdXRpb24g Y29udGV4dC4KPj4+Pgo+Pj4+IFJldHVybiB0aGUgYXBwcm9wcmlhdGUgU0JJIGVycm9yIGNvZGUu Cj4+Pj4KPj4+PiAtLSBpbnQgc2JpX2hhcnRfc3VzcGVuZCh1MzIgc3RhdGUsIHVuc2lnbmVkIGxv bmcgcmVzdW1lX2VudHJ5LAo+Pj4+IHVuc2lnbmVkCj4+Pj4gbG9uZyBwcml2KQo+Pj4+Cj4+Pj4g U3VzcGVuZHMgdGhlIGNhbGxpbmcgaGFydCB0byBhIHBhcnRpY3VsYXIgcG93ZXIgc3RhdGUuIFN1 c3BlbmRlZCBoYXJ0Cj4+Pj4gd2lsbCBhdXRvbWF0aWNhbGx5IHdha2UtdXAgYmFzZWQgb24gc29t ZSB3YWtldXAgZXZlbnRzIGF0Cj4+Pj4gcmVzdW1lX2VudHJ5Cj4+Pj4gcGh5c2ljYWwgYWRkcmVz cy4KPj4+Pgo+Pj4+ICJwcml2IiBpcyBhIHByaXZhdGUgZGF0YSB0aGF0IGNhbGxlciBjYW4gdXNl IHRvIHBhc3MgaW5mb3JtYXRpb24KPj4+PiBhYm91dAo+Pj4+IGV4ZWN1dGlvbiBjb250ZXh0LiBU aGUgU0JJIGltcGxlbWVudGF0aW9uIG11c3Qgc2F2ZSBhIGNvcHkgc28gdGhhdAo+Pj4+IGNhbGxl ciBjYW4gcmV1c2Ugd2hpbGUgcmVzdG9yaW5nIGhhcnQgZnJvbSBzdXNwZW5kLgo+Pj4+Cj4+Pj4g UmV0dXJuIHRoZSBhcHByb3ByaWF0ZSBTQkkgZXJyb3IgY29kZS4KPj4+Pgo+Pj4+IC0tIGludCBz YmlfaGFydF9kb3duKCkKPj4+Pgo+Pj4+IEl0IHBvd2VycyBvZmYgdGhlIGhhcnQgYW5kIHdpbGwg YmUgdXNlZCBpbiBjcHUtaG90cGx1Zy4KPj4+PiBPbmx5IGluZGl2aWR1YWwgaGFydCBjYW4gcmVt b3ZlIGl0c2VsZiBmcm9tIHN1cGVydmlzb3IgbW9kZS4gSXQgY2FuCj4+Pj4gYmUKPj4+PiBtb3Zl ZCB0byBub3JtYWwgc3RhdGUgb25seSBieSBzYmlfaGFydF91cCBmdW5jdGlvbi4KPj4+Pgo+Pj4+ IFJldHVybiB0aGUgYXBwcm9wcmlhdGUgU0JJIGVycm9yIGNvZGUuCj4+Pj4KPj4+PiAtLSB1MzIg c2JpX2hhcnRfc3RhdGUodW5zaWduZWQgbG9uZyBoYXJ0aWQpCj4+Pj4KPj4+PiBSZXR1cm5zIHRo ZSBSSVNDVl9QT1dFUl9TVEFURSBmb3IgYSBzcGVjaWZpYyBoYXJ0aWQuIFRoaXMgd2lsbCBoZWxw Cj4+Pj4gbWFrZQo+Pj4+IGtleGVjIGxpa2UgZnVuY3Rpb25hbGl0eSBtb3JlIHJvYnVzdC4KPj4+ Pgo+Pj4KPj4+IEluc3RlYWQgb2YgdGhlIGFib3ZlIEkgYmVsaWV2ZSBpdCB3b3VsZCBiZSBjbGVh bmVyIGFuZCBzaW1wbGVyIHRvIGhhdmUKPj4+IGFuIHNiaV9nZXRfaGFydF9zdGF0ZSBhbmQgYW4g c2JpX3NldF9oYXJ0X3N0YXRlIGNhbGwuIFRoaXMgd2F5IHdlIGNhbgo+Pj4gYmV0dGVyIGhhbmRs ZSBzdGF0ZSB0cmFuc2l0aW9ucyBhbmQsIGhhbmRsZSBPTi9PRkYvU1RBTkRCWS9SRVRFTlRJT04K Pj4+IGFuZCBhbnkgb3RoZXIgc3RhdGUgd2UgY29tZSB1cCB3aXRoLCB3aXRob3V0IGFkZGluZyBl eHRyYSBzYmkgY2FsbHMuCj4+Pgo+Pgo+PiBXaGVuIGRvIHlvdSB3YW50IHRvIHVzZSBzYmlfc2V0 X2hhcnRfc3RhdGUgPwo+PiBUaGUgcG93ZXIgc3RhdGVzIHdpbGwgYmUgbW9kaWZpZWQgYXMgYSBw YXJ0IG9mIHNiaV9oYXJ0X2Rvd24gb3IKPj4gc2JpX3NodXRkb3duL3N1c3BlbmQgY2FsbHMgYW55 d2F5cy4KPj4KPiAKPiBUaGUgaWRlYSBpcyB0byBoYXZlIHNiaV9zZXRfaGFydF9zdGF0ZSBpbnN0 ZWFkIG9mCj4gc2JpX2hhcnRfZG93bi9zaHV0ZG93bi9zdXNwZW5kL2V0Yy4KPiBJbnN0ZWFkIG9m IGhhdmluZyBkaWZmZXJlbnQgY2FsbHMgZm9yIGRpZmZlcmVudCBzdGF0ZXMgd2UganVzdCBoYXZl IHR3bwo+IGNhbGxzLCBvbmUKPiB0byBnZXQgdGhlIHN0YXRlIGFuZCBvbmUgdG8gc2V0IGl0LiBU aGlzIHdheSB3ZSBoYXZlIGZld2VyIGNhbGxzIGFuZCBpZgo+IHdlIGFkZCBhCj4gbmV3IHN0YXRl IHdlIGNhbiBhZGQgaXQgd2l0aG91dCBoYXZpbmcgdG8gYWRkIGEgbmV3IGNhbGwuCj4gCkFoaCBJ IHNlZSBpdCBub3cuIElNSE8sIGhhdmluZyBleHBsaWNpdCBuYW1lcyBtYWtlcyBtb3JlIHNlbnNl LgoKCj4+Pj4gLS0gdm9pZCBzYmlfc3lzdGVtX3NodXRkb3duKCkKPj4+Pgo+Pj4+IFBvd2VycyBv ZmYgdGhlIGVudGlyZSBzeXN0ZW0uCj4+Pj4KPj4+Cj4+PiBEb24ndCB3ZSBhbHJlYWR5IGhhdmUg dGhhdCA/IFdoYXQncyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuCj4+PiBzYmlfc3lzdGVtX3NodXRk b3duCj4+PiBhbmQgc2JpX3NodXRkb3duID8gRG9lcyBpdCBtYWtlIHNlbnNlIHRvIHVzZSBzYmlf c2h1dGRvd24gYW5kIGxlYXZlCj4+PiB0aGUKPj4+IHN5c3RlbQo+Pj4gb24gd2l0aCBhbGwgdGhl IGhhcnRzIGRvd24gPyBNYXliZSB3ZSBjYW4ganVzdCBzYXkgdGhhdCBzYmlfc2h1dGRvd24KPj4+ IGFsc28KPj4+IHBvd2VycyBkb3duIHRoZSBzeXN0ZW0gYW5kIHJlbmFtZSBpdCB0byBzYmlfc3lz dGVtX3NodXRkb3duIHdpdGggdGhlCj4+PiBzYW1lCj4+PiBmdW5jdGlvbiBJRC4KPj4+Cj4+Cj4+ IFllYWguIFRoYXQncyBhIGJldHRlci4KPj4KPj4KPj4+PiAzLiBTQkkgQVBJIElEIG51bWJlcmlu ZyBzY2hlbWU6Cj4+Pj4gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCj4+Pj4gQW4gQVBJ IFNldCBpcyBhIHNldCBvZiBTQkkgQVBJcyB3aGljaCBjb2xsZWN0aXZlbHkgaW1wbGVtZW50IHNv bWUKPj4+PiBraW5kIG9mIGZlYXR1cmUvZnVuY3Rpb25hbGl0eS4KPj4+Pgo+Pj4+IExldCdzIHNh eSBTQkkgQVBJIElEIGlzIHUzMiAgdGhlbgo+Pj4+IEJpdFszMToyNF0gPSAgQVBJIFNldCBOdW1i ZXIKPj4+PiBCaXRbMjM6MF0gPSBBUEkgTnVtYmVyIHdpdGhpbiBBUEkgU2V0Cj4+Pj4KPj4+PiBI ZXJlIGFyZSBmZXcgQVBJIFNldHMgZm9yIFNCSSB2MC4yOgo+Pj4+IDEuIEJhc2UgQVBJcwo+Pj4+ IEFQSSBTZXQgTnVtYmVyOiAweDAKPj4+PiBEZXNjcmlwdGlvbjogQmFzZSBBUElzIG1hbmRhdG9y eSBmb3IgYW55IFNCSSB2ZXJzaW9uCj4+Pj4KPj4+PiAyLiBIQVJUIFBNIEFQSXMKPj4+PiBBUEkg U2V0IE51bWJlcjogMHgxCj4+Pj4gRGVzY3JpcHRpb246IEhhcnQgVVAvRG93bi9TdXNwZW5kIEFQ SXMgZm9yIHBlci1IYXJ0Cj4+Pj4gcG93ZXIgbWFuYWdlbWVudAo+Pj4+Cj4+Pj4gMy4gU3lzdGVt IFBNIEFQSXMKPj4+PiBBUEkgU2V0IE51bWJlcjsgMHgyCj4+Pj4gRGVzY3JpcHRpb246IFN5c3Rl bSBTaHV0ZG93bi9SZWJvb3QvU3VzcGVuZCBmb3Igc3lzdGVtLWxldmVsCj4+Pj4gcG93ZXIgbWFu YWdlbWVudAo+Pj4+Cj4+Pj4gNC4gVmVuZG9yIEFQSXMKPj4+PiBBUEkgU2V0IE51bWJlcjogMHhm Zgo+Pj4+IERlc2NyaXB0aW9uOiBWZW5kb3Igc3BlY2lmaWMgQVBJcy4KPj4+PiBUaGVyZSBpcyBh IHBvc3NpYmlsaXR5IHRoYXQgZGlmZmVyZW50IHZlbmRvcnMgY2FuIGNob29zZSB0byBhc3NpZ24K Pj4+PiBzYW1lIEFQSSBudW1iZXJzIGZvciBkaWZmZXJlbnQgZnVuY3Rpb25hbGl0eS4gSW4gdGhh dCBjYXNlLCB2ZW5kb3IKPj4+PiBzcGVjaWZpYyBzdHJpbmdzIGluIERldmljZSBUcmVlIGNhbiBi ZSB1c2VkIHRvIHZlcmlmeSBpZiBhIHNwZWNpZmljCj4+Pj4gQVBJIGJlbG9uZ3MgdG8gdGhlIGlu dGVuZGVkIHZlbmRvciBvciBub3QuCj4+Pj4KPj4+Cj4+PiBJIHVuZGVyc3RhbmQgdGhlIHJhdGlv bmFsZSBiZWhpbmQgdGhpcyBidXQgSSBiZWxpZXZlIGl0J3MgYmV0dGVyIHRvCj4+PiBjYWxsIHRo ZW0gc2VydmljZXMgb3IgZnVuY3Rpb25zIGluc3RlYWQgb2YgQVBJcywgdGhleSBhcmUgbm90IHNl dHMKPj4+IG9mIEFQSXMgdGhlIHdheSBJIHNlZSBpdC4gQWxzbyBzaW5jZSB3ZSBhcmUgbW92aW5n IHRoYXQgcGF0aCB3aHkgY2FsbAo+Pj4gaXQgU0JJIGFuZCByZXN0cmljdCBpdCBvbmx5IHRvIGJl IHVzZWQgYnkgdGhlIHN1cGVydmlzb3IgPyBJJ2QgbG92ZSB0bwo+Pj4gaGF2ZSBhbm90aGVyIGNh dGVnb3J5IGZvciB0aGUgc2VjdXJlIG1vbml0b3IgY2FsbHMgZm9yIGV4YW1wbGUsCj4+PiBidXQg b24gdGhlIHNvZnR3YXJlIGFyY2hpdGVjdHVyZSB0aGF0IHdlIGFyZSBkaXNjdXNzaW5nIG9uIHRo ZSBURUUKPj4+IGdyb3VwLCBzdWNoIGNhbGxzIGNhbiBhbHNvIG9yaWdpbmF0ZSBmcm9tIFUgbW9k ZSBvciBIUy9IVSBtb2Rlcy4KPj4+IFRoZSBzYW1lIGdvZXMgZm9yIHZlbmRvciBzcGVjaWZpYyBj YWxscywgdGhlcmUgYXJlIGxvdHMgb2YgdXNlIGNhc2UKPj4+IHNjZW5hcmlvcyB3aGVyZSB2ZW5k b3JzIHdvdWxkIGxpa2UgdG8gYmUgYWJsZSB0byBjYWxsIHRoZWlyIHN0dWZmCj4+PiBmcm9tIFUg bW9kZSBmb3IgZXhhbXBsZSAoZS5nLiBhIHVzZXIgc3BhY2UgbGlicmFyeSB0YWxraW5nIHRvIGEK Pj4+IHNtYXJ0IGNhcmQgZGlyZWN0bHkpLgo+Pj4KPj4+IEkgc3VnZ2VzdCB3ZSByZW5hbWUgaXQg ZnJvbSBTQkkgdG8gc29tZXRoaW5nIG1vcmUgZ2VuZXJpYyB0aGF0IGlzIG5vdAo+Pj4gZGVmaW5l ZCBieSB3aG8gaXMgY2FsbGluZyBpdCBidXQgYnkgd2hhdCB3ZSBhcmUgY2FsbGluZywgd2hpY2gg aW4gdGhpcwo+Pj4gY2FzZSBpcyB0aGUgZmlybXdhcmUgKEZCST8pLgo+Pgo+PiBwb3NzaWJsZSBj b25mbGljdCB3aXRoIGEgdmVyeSBmYW1vdXMgbGF3IGVuZm9yY2VtZW50IGFnZW5jeSA6KSA6KS4K Pj4KPj4gSm9rZXMgYXNpZGUsIHJlbmFtaW5nIHRvIHNvbWV0aGluZyBtb3JlIGdlbmVyaWMgaXMg YSBnb29kIGlkZWEuIEJ1dCBpdAo+PiB3aWxsIHByb2JhYmx5IGJyZWFrIGEgdG9uIG9mIGRvY3Vt ZW50YXRpb24vc3BlYyBpbiBSSVNDLVYgd2hpY2ggSQo+PiBkb24ndCB3YW50IHRvIGRlYWwgd2l0 aCByaWdodCBub3cuIE1heSBiZSBpbiBmdXR1cmUgdmVyc2lvbnMgPwo+Pgo+IAo+IEkgZ2V0IHRo YXQgdXBkYXRpbmcgdGhlIGRvY3VtZW50YXRpb24gY2FuIGJlIGEgcGFpbiwgSSBjYW4gaGVscCB3 aXRoCj4gdGhhdCBpZiB5b3Ugd2FudCAoYW5kIEkgcHJvbWlzZSBJJ2xsIHN0YXkgYXdheSBmcm9t IGxhdyBlbmZvcmNlbWVudAo+IGFnZW5jaWVzICEpLiBJIHN1Z2dlc3Qgd2UgZG8gdGhlIHJlbmFt aW5nIGFzIGVhcmx5IGFzIHBvc3NpYmxlCj4gYmVjYXVzZSB3ZSBhcmUgZ29pbmcgdG8gY2Fycnkg aXQgZm9yIGEgbG9uZyB0aW1lIGluc3RlYWQgYW5kIGl0J2xsCj4gb25seSBnZXQgaGFyZGVyIHRv IGNoYW5nZSBsYXRlciBvbi4KPiAKVGhhbmtzLiBJIGd1ZXNzIHdlIG5lZWQgUGFsbWVyL0FuZHJl dyB0byBwaXRjaCBpbiBmaXJzdCBvbiB0aGlzIGJlZm9yZSAKd2UgZGVjaWRlIGFueXRoaW5nLgoK Pj4+IFNpbmNlIHlvdSBtZW50aW9uZWQgQVJNLCBpbiB0aGVpciBjYXNlCj4+PiB0aGUgQUJJIHVz ZWQgZm9yIFBTQ0kgaXMgdGhlIFNlY3VyZSBNb25pdG9yIENhbGwgKHdoaWNoIGlzIHRoZQo+Pj4g YWx0ZXJuYXRpdmUKPj4+IHRvIHdoYXQgaXMgZGVmaW5lZCBvbiB0aGUgZmlyc3QgcGFyYWdyYXBo IG9mIHRoZSBTQkkgZG9jdW1lbnQpLCBidXQgaXQKPj4+IGhhcyB0aGUgc2FtZSBsaW1pdGF0aW9u LiBBY2NvcmRpbmcgdG8gdGhlIGRvY3VtZW50YXRpb24gaWYgYW4gU01DCj4+PiBjb21lcwo+Pj4g ZnJvbSBhIHVzZXIgYXBwbGljYXRpb24sIHdlIGdldCBhbiB1bmRlZmluZWQgZXhjZXB0aW9uLiBX ZSBjYW4gZG8KPj4+IGJldHRlcgo+Pj4gIQo+Pj4KPj4KPj4KPj4KPj4+Cj4+Pj4gNC4gUmV0dXJu IGVycm9yIGNvZGUgVGFibGU6Cj4+Pj4gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCj4+Pj4K Pj4+PiBIZXJlIGFyZSB0aGUgU0JJIHJldHVybiBlcnJvciBjb2RlcyBkZWZpbmVkLgo+Pj4+Cj4+ Pj4gICAgICAgICBTQklfU1VDQ0VTUyAgICAgICAgICAgMAo+Pj4+ICAgICAgICAgU0JJX05PVF9T VVBQT1JURUQgICAgLTEKPj4+PiAgICAgICAgIFNCSV9JTlZBTElEX1BBUkFNICAgIC0yCj4+Pj4g ICAgICAgICBTQklfREVOSUVEICAgICAgICAgICAtMwo+Pj4+ICAgICAgICAgU0JJX0lOVkFMSURf QUREUkVTUyAgLTQKPj4+Pgo+Pj4+IEEgbWFwcGluZyBmdW5jdGlvbiBiZXR3ZWVuIFNCSSBlcnJv ciBjb2RlICYgTGludXggZXJyb3IgY29kZSBzaG91bGQKPj4+PiBiZQo+Pj4+IHByb3ZpZGVkLgo+ Pj4+Cj4+Pgo+Pj4gSSBiZWxpZXZlIGl0IHNob3VsZCBiZSB1cCB0byB0aGUgT1MgdG8gdHJhbnNs YXRlIHRoZSBTQkkgZXJyb3IgY29kZXMKPj4+IHRvCj4+PiBpdHMKPj4+IG5hdGl2ZSBvbmVzLgo+ Pj4KPj4KPj4gQ29ycmVjdC4gT2xvZiBhbHNvIHBvaW50ZWQgdGhpcyBvdXQuIEkgd2lsbCByZW1v dmUgaXQgaW4gbmV4dCB2ZXJzaW9uLgo+Pgo+Pj4+IDUuIFBvd2VyIFN0YXRlCj4+Pj4gLS0tLS0t LS0tLS0tLS0KPj4+Pgo+Pj4+IEEgUklTQy1WIGNvcmUgY2FuIGV4aXN0IGluIGFueSBvZiB0aGUg Zm9sbG93aW5nIHBvd2VyIHN0YXRlcy4KPj4+Pgo+Pj4+IGVudW0gUklTQ1ZfUE9XRVJfU1RBVEUg ewo+Pj4+ICAgICAgICAgIC8vUG93ZXJlZCB1cCAmIG9wZXJhdGlvbmFsLgo+Pj4+ICAgICAgICAg IFJJU0NWX0hBUlRfT04gICAgICAgICAgICAgID0gIDAsCj4+Pj4gICAgICAgICAgLy9Qb3dlcmVk IHVwIGJ1dCBhdCByZWR1Y2VkIGVuZXJneSBjb25zdW1wdGlvbi4gV0ZJCj4+Pj4gaW5zdHJ1Y3Rp b24KPj4+PiBjYW4gYmUgdXNlZCB0byBhY2hpZXZlIHRoaXMgc3RhdGUuCj4+Pj4gICAgICAgICAg UklTQ1ZfSEFSVF9TVEFOREJZICAgICAgICA9ICAgMSwKPj4+PiAgICAgICAgICAvL0RlZXBlciBs b3cgcG93ZXIgc3RhdGUuIE5vIHJlc2V0IHJlcXVpcmVkIGJ1dCBoaWdoZXIgd2FrZXVwCj4+Pj4g bGF0ZW5jeS4KPj4+PiAgICAgICAgICBSSVNDVl9IQVJUX1JFVEVOVElPTiAgICAgICA9ICAyLAo+ Pj4+ICAgICAgICAgIC8vUG93ZXJlZCBvZmYuIFJlc2V0IG9mIHRoZSBjb3JlIHJlcXVpcmVkIGFm dGVyIHBvd2VyCj4+Pj4gcmVzdG9yZS4KPj4+PiAgICAgICAgICBSSVNDVl9IQVJUX09GRiAgICAg ICAgICAgICA9ICAzCj4+Pj4gfQo+Pj4+Cj4+Pj4gVE9ETzoKPj4+PiBBbnkgb3RoZXIgcG93ZXIg bWFuYWdlbWVudCByZWxhdGVkIGZlYXR1cmVzIG9yIHN0YXRlPwo+Pj4+Cj4+Pgo+Pj4gSG93IGFi b3V0IExPQ0tTVEVQID8gV2UgY291bGQgaGF2ZSBhIHdheSBvZiBkZWNsYXJpbmcgYSBoYXJ0IGFz IGEKPj4+ICJtaXJyb3IiIG9mIGFub3RoZXIKPj4+IGhhcnQgKGh0dHBzOi8vZW4ud2lraXBlZGlh Lm9yZy93aWtpL0xvY2tzdGVwXyhjb21wdXRpbmcpKS4gV2UgY2FuIGhhdmUKPj4+IGFuIGV4dHJh IGFyZ3VtZW50Cj4+PiBvbiBzYmlfZ2V0L3NldF9zdGF0ZSB3aGVuIHRoZSBMT0NLU1RFUCBzdGF0 ZSBpcyB1c2VkLCB0aGF0IHdpbGwKPj4+IGdldC9zZXQKPj4+IHRoZSBoYXJ0IHRoYXQKPj4+IHRo aXMgaGFydCBpcyBtaXJyb3JpbmcuCj4+Pgo+Pgo+PiBOb3Qgc3VyZSBpZiB3ZSBuZWVkIGl0IHJp Z2h0IG5vdy4gSSB3YW50IHRvIGtlZXAgaXQgc2ltcGxlIGFuZCBmb2N1cwo+PiBvbiB0aGUgYmFy ZSBtaW5pbXVtIG9uZXMuIFdlIGNhbiBhbHdheXMgYWRkIGV4b3RpYyBvbmVzIG9uY2Ugd2UgaGF2 ZQo+PiBmZWF0dXJlL3ZlcnNpb25pbmcgaW4gcGxhY2UuCj4+Cj4gCj4gSSBhZ3JlZSwgSSBtZW50 aW9uZWQgTE9DS1NURVAgYmVjYXVzZSBpdCdsbCBuZWVkIGFuIGV4dHJhIGFyZ3VtZW50Cj4gd2hl biBzZXR0aW5nIHRoZSBzdGF0ZS4gQnR3IEkga25vdyBsb2Nrc3RlcCBzb3VuZHMgZXhvdGljIGF0 IHRoaXMgcG9pbnQKPiBidXQgaXQncyBuZWVkZWQgYnkgbWFueSBpbmR1c3RyaWVzIHRoYXQgZGVh bCB3aXRoIHNhZmV0eSAoYXV0b21vdGl2ZQo+IHN0dWZmLAo+IG1lZGljYWwgZGV2aWNlcyBldGMp LiBIb3dldmVyIGl0IG5lZWRzIG1vcmUgdGhpbmtpbmcuCj4gCj4+Pj4gNi4gSW1wbGVtZW50YXRp b24KPj4+PiAtLS0tLS0tLS0tLS0tLS0tLS0tCj4+Pj4gQ3VycmVudGx5LCBTQkkgaXMgaW1wbGVt ZW50ZWQgYXMgYSBwYXJ0IG9mIEJCTC4gVGhlcmUgaXMgYSBkaWZmZXJlbnQKPj4+PiBTQkkgaW1w bGVtZW50YXRpb24gYXZhaWxhYmxlIGluIGNvcmVib290IGFzIHdlbGwuCj4+Pj4KPj4+PiBBbHRl cm5hdGl2ZWx5LCBhIHNlcGFyYXRlIG9wZW4gQlNEL01JVCBsaWNlbnNlZCBTQkkgcHJvamVjdCBj YW4gYmUKPj4+PiBjcmVhdGVkIHdoaWNoIGNhbiBiZSB1c2VkIGJ5IGFueWJvZHkgdG8gYXZvaWQg dGhlc2Uga2luZCBvZiBTQkkKPj4+PiBmcmFnbWVudGF0aW9uIGluIGZ1dHVyZS4gVGhpcyBwcm9q ZWN0IGNhbiBnZW5lcmF0ZSBib3RoIGEgZmlybXdhcmUKPj4+PiBiaW5hcnkgKHRvIGV4ZWN1dGVk IGRpcmVjdGx5IGluIE0gbW9kZSkgb3IgYSBzdGF0aWMgbGlicmFyeSB0aGF0IGNhbgo+Pj4+IGJl IHVzZWQgYnkgZGlmZmVyZW50IGJvb3QgbG9hZGVycy4gSXQgd2lsbCBhbHNvIGhlbHAgaW5kaXZp ZHVhbCBib290Cj4+Pj4gbG9hZGVycyB0byBlaXRoZXIgd29yayBmcm9tIE0gb3IgUyBtb2RlIHdp dGhvdXQgYSBzZXBhcmF0ZSBTQkkKPj4+PiBpbXBsZW1lbnRhdGlvbi4KPj4+Pgo+Pj4KPj4+IFdo eSBpbXBsZW1lbnQgdGhpcyBhdCB0aGUgYm9vdCBsb2FkZXIgbGV2ZWwgPyBUaGlzIGlzIG1vcmUg bGlrZSBhCj4+PiBmaXJtd2FyZSBpbnRlcmZhY2UKPj4+IHRoYW4gc29tZXRoaW5nIHRoYXQgYmVs b25ncyB0byB0aGUgYm9vdGxvYWRlci4gVGhlIGJvb3Rsb2FkZXIgc2hvdWxkCj4+PiB1c2UKPj4+ IHRoaXMgaW50ZXJmYWNlCj4+PiBub3QgcHJvdmlkZSBpdC4KPj4gSXQgZGVwZW5kcyBvbiB0aGUg Ym9vdGxvYWRlci4gRm9yIGV4YW1wbGUsIHRoZXJlIGFyZSBwYXRjaGVzIGluCj4+IGNvcmVib290 IHRoYXQgaW1wbGVtZW50cyBTQkkuIFRoZSBpZGVhIHdpdGggT3BlblNCSSBpbXBsZW1lbnRhdGlv biBpcwo+PiB0byBhdm9pZCBzdWNoIGZyYWdtZW50YXRpb24uCj4+Cj4+PiBBbHNvIHRoaXMgaXMg c29tZXRoaW5nIHRoYXQgYmVsb25ncyB0byB0aGUgTSBtb2RlLCBhCj4+PiBib290bG9hZGVyCj4+ PiBzaG91bGQgYmVsb25nIHRvIHRoZSBTIG1vZGUsIHJ1bm5pbmcgdGhlIGJvb3Rsb2FkZXIgaW4g TSBtb2RlIGlzIG5vdAo+Pj4gcmlnaHQgZnJvbQo+Pj4gYSBzZWN1cml0eSBwb2ludCBvZiB2aWV3 LiBXZSBjYW4gcHJvdmlkZSBzb21ldGhpbmcgbGlrZSAiUklTQy1WCj4+PiBGaXJtd2FyZQo+Pj4g U2VydmljZXMiCj4+PiB0aGF0J3MgY29kZSBydW5uaW5nIG9uIE0gbW9kZSBhZnRlciB0aGUgZmly c3Qgc3RhZ2UgYm9vdAo+Pj4gbG9hZGVyL0Jvb3RST00KPj4+IGFuZCBsZXQKPj4+IGJvb3Rsb2Fk ZXJzIHVzZSBpdCB3aXRob3V0IGhhdmluZyB0byBpbXBsZW1lbnQgaXQuCj4+Cj4+IFRoYXQncyB0 aGUgaWRlYSBmb3IgUyBtb2RlIGJvb3Rsb2FkZXJzLiBIb3dldmVyLCB0aGVyZSBhcmUgZm9sa3Mg d2hvCj4+IGFyZSBpbnRlcmVzdGVkIGluIE0gbW9kZSBvbmVzIGFuZCBJIHVuZGVyc3RhbmQgdGhl aXIgdXNlY2FzZS4gVGh1cywKPj4gaWRlYSBpcyB0byBpbXBsZW1lbnQgT3BlblNCSSBpbiBzdWNo IGEgd2F5IHRoYXQsIGV2ZXJ5Ym9keSBjYW4gbWFrZQo+PiB1c2Ugb2YgaXQuCj4+Cj4gCj4gSSBn dWVzcyB0aGVuIHdlIGNhbiBwcm92aWRlIGl0IGFzIGEgbGlicmFyeSBhbmQgYWxzbyBwcm92aWRl IGEgcmVmZXJlbmNlCj4gaW1wbGVtZW50YXRpb24gYXJvdW5kIGl0LiAKCll1cC4gVGhhdCBpcyB0 aGUgZXhhY3QgaWRlYS4KCkhvd2V2ZXIgSSBzdGlsbCBiZWxpZXZlIHRoYXQgc29tZXRoaW5nIGxp a2UKPiAiUklTQy1WIEZpcm13YXJlIFNlcnZpY2VzIiBpcyBtb3JlIGFwcHJvcHJpYXRlLCB3ZSBj YW4gc3RydWN0dXJlIHRoaXMKPiBpbiBhIGNsaWVudC9zZXJ2ZXIgd2F5IGFuZCBsZXQgYm9vdGxv YWRlcnMgdXNlIHRoZSBzZXJ2ZXIgcGFydCBhbmQKPiBPUyBkcml2ZXJzL21vZHVsZXMgdXNlIHRo ZSBjbGllbnQgcGFydC4gVGhpcyB3YXkgd2UgY2FuIGFsc28gYXZvaWQKPiBmcmFnbWVudGF0aW9u IGFjcm9zcyBPU2VzLgo+IApUaGFua3MgZm9yIHRoZSBpZGVhLiBMZXQgbWUgdGhpbmsgYWJvdXQg aXQgbW9yZS4gV2UgaGF2ZSBqdXN0IHN0YXJ0ZWQgCndvcmtpbmcgb24gT3BlblNCSSBwcm9qZWN0 LiBJIHdpbGwgdXBkYXRlIHdoZW4gd2UgaGF2ZSBzb21ldGhpbmcgd29ya2luZy4KClJlZ2FyZHMs CkF0aXNoCj4gUmVnYXJkcywKPiBOaWNrCj4gCgoKX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX18KbGludXgtcmlzY3YgbWFpbGluZyBsaXN0CmxpbnV4LXJpc2N2 QGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9s aXN0aW5mby9saW51eC1yaXNjdgo=