From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 976F130EF7F for ; Thu, 29 Jan 2026 19:01:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769713287; cv=none; b=dz95l8BY3ZuCFHtzb9f6hySiNjyjViFlQnioj+ybbCla/yHhbd5lqaETuQtHEOEfw/Th2IQ/56Zefzn6ilLuhvaNm4ABD9K9vYuE6FmvQEyApfwRomUGTq4ugpCt/vvAe68eEasu4UcCwf7LV8i9l0cV6aoYToLD0+W+9WEu5Sg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769713287; c=relaxed/simple; bh=W4oiW3ZCreBFKnt1WN4t37yUfwwWI+rWsckbWFsLrZA=; h=From:To:Cc:Subject:In-Reply-To:References:Date:Message-ID: MIME-Version:Content-Type; b=aAw7P+oKY25gUYVzXBR/u4Ul+BJxjwWQvJ4f1o6xvcIN6Dr/Smcn2GC6pzsST7px8cwEgwvoJ0SqWfHfRj3gdx7XfoGn6LE4PagChnEaon5w4LgwomkrqSPXb7FQt0EpCOq37Sengail7QrMdEp8W2UR1Jj6qwW9KZ+O96aDYmM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=W6sG3Nl1; arc=none smtp.client-ip=185.171.202.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="W6sG3Nl1" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 645C6C22F4C; Thu, 29 Jan 2026 19:01:23 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 4300B60746; Thu, 29 Jan 2026 19:01:20 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 69B46119A880F; Thu, 29 Jan 2026 20:01:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1769713279; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=R3bTYiE5fmpx2hKk+ij/xNGunlQDmY23LY/sHyFCZyM=; b=W6sG3Nl1IURGhJrQDPhEb6hFjjFnVg/wK5hJxzooruVb0xYppeZtsNqWhZykDVhuNC4mFK 772UVOkszbjzC41lJE5koR+krq3ooTxFgdxEMJm30e2qMhrrkOEZNNyX4Ni/sdlXju9BHQ 2Uz9tnuQ8OoGuYJMRbIQvuWruQAdg/vvxIasozv4XB2l/kEnALQw2CE231VwWZmizceTDG u34EdPCIjgeb5erQg1BkBF4ePuMr4YSSx8dfxUvbbzEg2qCaS7ZAmHodMa7m/3VnH0/6BB sVO5fwcZ6qczQfx1wZ753Mv7WRGVojypwDCpi7E7UGc7ZKzFsU3g0qnEm3PJmQ== From: Miquel Raynal To: Junhao Xie Cc: Bjorn Andersson , Konrad Dybcio , Richard Weinberger , Vignesh Raghavendra , linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, Xilin Wu Subject: Re: [PATCH v2 2/2] mtd: devices: Add Qualcomm SCM storage driver In-Reply-To: <20260126-scm-storage-v2-v2-2-fa045c7e7699@radxa.com> (Junhao Xie's message of "Mon, 26 Jan 2026 19:44:52 +0800") References: <20260126-scm-storage-v2-v2-0-fa045c7e7699@radxa.com> <20260126-scm-storage-v2-v2-2-fa045c7e7699@radxa.com> User-Agent: mu4e 1.12.7; emacs 30.2 Date: Thu, 29 Jan 2026 20:01:12 +0100 Message-ID: <87a4xwkzuv.fsf@bootlin.com> Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Hello Junhao, > +static int qcom_scm_storage_erase(struct mtd_info *mtd, > + struct erase_info *instr) > +{ > + struct qcom_scm_storage *host =3D mtd->priv; > + size_t block_size; > + > + if (instr->addr % host->mtd.erasesize || > + instr->len % host->mtd.erasesize) > + return -EINVAL; Can theses situations realistically happen? Erases are in theory eraseblock aligned, so I doubt this case shall be checked in device drivers. > + > + block_size =3D le32_to_cpu(host->info.block_size); You seem to store the SCM info structure as-is and always make conversions on the fly. May I suggest to store the fields you need directly in the correct format/endianness? > + > + guard(mutex)(&host->lock); > + > + return qcom_scm_storage_send_cmd(QCOM_SCM_STORAGE_SPINOR, > + QCOM_SCM_STORAGE_ERASE, > + instr->addr / block_size, Actually what you need instead of block_size is to use mtd->erasesize directly, no need to store "block_size" in your structure, you already have it. > + 0, instr->len); > +} > + > +static int qcom_scm_storage_read(struct mtd_info *mtd, > + loff_t from, size_t len, > + size_t *retlen, u_char *buf) u_char? Can we use a more common type? > +{ > + struct qcom_scm_storage *host =3D mtd->priv; > + loff_t block_start, block_off, lba; > + size_t block_size, chunk, to_read; > + int ret; > + > + if (retlen) > + *retlen =3D 0; Are there cases where retlen can be absent? > + > + if (from + len > mtd->size) > + return -EINVAL; This check should be done at the core level already. > + if (len =3D=3D 0) > + return 0; Ditto (see mtdchar_read()). > + block_size =3D le32_to_cpu(host->info.block_size); > + > + guard(mutex)(&host->lock); > + > + while (len > 0) { > + block_start =3D round_down(from, block_size); > + block_off =3D from - block_start; > + lba =3D block_start / block_size; > + > + if (block_off || len < block_size) { > + chunk =3D min_t(size_t, block_size - block_off, len); > + to_read =3D block_size; > + } else { > + chunk =3D round_down(len, block_size); > + chunk =3D min_t(size_t, chunk, host->buffer_size); > + to_read =3D chunk; > + } > + > + ret =3D qcom_scm_storage_send_cmd(QCOM_SCM_STORAGE_SPINOR, > + QCOM_SCM_STORAGE_READ, > + lba, host->buffer, > + to_read); > + if (ret) > + return ret; > + > + memcpy(buf, host->buffer + block_off, chunk); > + > + buf +=3D chunk; > + from +=3D chunk; > + len -=3D chunk; > + if (retlen) > + *retlen +=3D chunk; > + } > + > + return 0; > +} > + > +static int qcom_scm_storage_write(struct mtd_info *mtd, > + loff_t to, size_t len, > + size_t *retlen, const u_char *buf) > +{ > + struct qcom_scm_storage *host =3D mtd->priv; > + loff_t block_start, block_off, lba; > + size_t block_size, chunk, to_write; > + int ret; > + > + if (retlen) > + *retlen =3D 0; > + > + if (to + len > mtd->size) > + return -EINVAL; > + > + if (len =3D=3D 0) > + return 0; > + > + block_size =3D le32_to_cpu(host->info.block_size); > + > + guard(mutex)(&host->lock); > + > + while (len > 0) { > + block_start =3D round_down(to, block_size); > + block_off =3D to - block_start; > + lba =3D block_start / block_size; > + > + if (block_off || len < block_size) { > + chunk =3D min_t(size_t, block_size - block_off, len); > + to_write =3D block_size; > + > + ret =3D qcom_scm_storage_send_cmd(QCOM_SCM_STORAGE_SPINOR, > + QCOM_SCM_STORAGE_READ, > + lba, host->buffer, > + block_size); This is strange. Does it really work? My understanding: you're trying to handle a non aligned write access (I'm not even sure this is possible as you set writesize =3D=3D erasesize) by reading the existing data before writing. If that's what you intend to do, you'll forcibly get 1s instead of actual data because erases are mandatory before writes, which means your read will happen too late. I might be totally wrong, but I believe this approach is incorrect. Please explain what you're trying to do otherwise. > + if (ret) > + return ret; > + } else { > + chunk =3D round_down(len, block_size); > + chunk =3D min_t(size_t, chunk, host->buffer_size); > + to_write =3D chunk; > + } > + > + memcpy(host->buffer + block_off, buf, chunk); > + > + ret =3D qcom_scm_storage_send_cmd(QCOM_SCM_STORAGE_SPINOR, > + QCOM_SCM_STORAGE_WRITE, > + lba, host->buffer, > + to_write); > + if (ret) > + return ret; > + > + buf +=3D chunk; > + to +=3D chunk; > + len -=3D chunk; > + if (retlen) > + *retlen +=3D chunk; > + } > + > + return 0; > +} > + > +static int qcom_scm_storage_probe(struct platform_device *pdev) > +{ > + struct device *dev =3D &pdev->dev; > + struct qcom_scm_storage *host; > + u64 total_blocks, serial_num; > + u32 block_size; > + int ret; > + > + host =3D devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); > + if (!host) > + return -ENOMEM; > + > + platform_set_drvdata(pdev, host); > + host->dev =3D dev; > + > + ret =3D devm_mutex_init(dev, &host->lock); > + if (ret) > + return ret; > + > + host->buffer_size =3D SZ_256K; > + host->buffer =3D devm_kzalloc(dev, host->buffer_size, GFP_KERNEL); Do you really need 256K of adjacent memory? If this is a DMA-able buffer, then yes. Also, the check (block_size vs. buffer_size) should happen before this allocation, and you should not need to allocate 256k blindly, just use the NOR geometry knowledge. > + if (!host->buffer) > + return -ENOMEM; > + > + ret =3D qcom_scm_storage_send_cmd(QCOM_SCM_STORAGE_SPINOR, > + QCOM_SCM_STORAGE_GET_INFO, > + 0, &host->info, > + sizeof(host->info)); > + if (ret < 0) > + return dev_err_probe(dev, ret, > + "failed to get storage info\n"); Maybe this print can be enhanced, it may also mean the firmware does not implement the required system call? > + > + total_blocks =3D le64_to_cpu(host->info.total_blocks); > + serial_num =3D le64_to_cpu(host->info.serial_num); > + block_size =3D le32_to_cpu(host->info.block_size); > + > + if (!block_size || !total_blocks) > + return dev_err_probe(dev, -EINVAL, > + "invalid storage geometry\n"); > + > + if (block_size > host->buffer_size) > + return dev_err_probe(dev, -EINVAL, > + "block size %u exceeds buffer size\n", > + block_size); I am now in favour of reducing logs in the kernel, maybe you can group these two prints into one, indicating the info you get from firmware is incorrect? Also, what is the point of using dev_err_probe() here, as you cannot have an EPROBE_DEFER? > + > + host->mtd.priv =3D host; > + host->mtd.name =3D dev_name(dev); > + host->mtd.owner =3D THIS_MODULE; > + host->mtd.dev.parent =3D dev; > + host->mtd.size =3D total_blocks * block_size; > + host->mtd.erasesize =3D block_size; > + host->mtd.writesize =3D block_size; > + host->mtd.writebufsize =3D block_size; > + host->mtd.type =3D MTD_NORFLASH; > + host->mtd.flags =3D MTD_WRITEABLE; > + host->mtd._erase =3D qcom_scm_storage_erase; > + host->mtd._read =3D qcom_scm_storage_read; > + host->mtd._write =3D qcom_scm_storage_write; > + > + dev_info(dev, "scm storage 0x%llx registered with size %llu bytes\n", > + serial_num, host->mtd.size); Please drop this message, it is not useful. ... > +static struct platform_driver qcom_scm_storage_driver =3D { > + .probe =3D qcom_scm_storage_probe, > + .remove =3D qcom_scm_storage_remove, > + .driver =3D { > + .name =3D "qcom_scm_storage", > + }, > + .id_table =3D qcom_scm_storage_ids, I am surprised you have an id_table here, this is likely not for an OF based platform, do you confirm? Thanks, Miqu=C3=A8l 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 76EC9D73E83 for ; Thu, 29 Jan 2026 19:01:40 +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:MIME-Version:Message-ID:Date:References :In-Reply-To:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=57SJGm0A0JSJMGcm5NEe/bVlkWLrcGnhS0cJB8mx8eo=; b=oDOX6xIm8ovzOm uVVUwwfikHu8Jd7DdEMKkgkzsJBsNfbv3ErKikffd0PeHkeqsqxtWnd77/kwMunuZ6ahxFwiaX1oh y5al7VZ20zS8vfTjkkQu0y0DBs8BV/AkeYr6Rn9NBeqxtDIhP+1kTDn7CMbvSI++3eLin1P44rUzG JABjvhjPJsNB2K9cb+LZEAR9frIaVf/zmc0toABaQZlpjT3Yzt13I9EY6RPRrFpNDCDVhIq3TxSgc WYNivAMiIbtAQo2I3R9HJkZYDhELyTsuEGvgDtQjVKEaiBpAZOhJbwMIS85NBF3berehVrHeUSHjd 3K/qCNy7Y143Ns2+xL2w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux)) id 1vlXGo-00000000XTO-07Oh; Thu, 29 Jan 2026 19:01:34 +0000 Received: from smtpout-02.galae.net ([185.246.84.56]) by bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux)) id 1vlXGd-00000000XSy-1SC3 for linux-mtd@lists.infradead.org; Thu, 29 Jan 2026 19:01:27 +0000 Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 742AC1A2B0F; Thu, 29 Jan 2026 19:01:20 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 4300B60746; Thu, 29 Jan 2026 19:01:20 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 69B46119A880F; Thu, 29 Jan 2026 20:01:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1769713279; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=R3bTYiE5fmpx2hKk+ij/xNGunlQDmY23LY/sHyFCZyM=; b=W6sG3Nl1IURGhJrQDPhEb6hFjjFnVg/wK5hJxzooruVb0xYppeZtsNqWhZykDVhuNC4mFK 772UVOkszbjzC41lJE5koR+krq3ooTxFgdxEMJm30e2qMhrrkOEZNNyX4Ni/sdlXju9BHQ 2Uz9tnuQ8OoGuYJMRbIQvuWruQAdg/vvxIasozv4XB2l/kEnALQw2CE231VwWZmizceTDG u34EdPCIjgeb5erQg1BkBF4ePuMr4YSSx8dfxUvbbzEg2qCaS7ZAmHodMa7m/3VnH0/6BB sVO5fwcZ6qczQfx1wZ753Mv7WRGVojypwDCpi7E7UGc7ZKzFsU3g0qnEm3PJmQ== From: Miquel Raynal To: Junhao Xie Cc: Bjorn Andersson , Konrad Dybcio , Richard Weinberger , Vignesh Raghavendra , linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, Xilin Wu Subject: Re: [PATCH v2 2/2] mtd: devices: Add Qualcomm SCM storage driver In-Reply-To: <20260126-scm-storage-v2-v2-2-fa045c7e7699@radxa.com> (Junhao Xie's message of "Mon, 26 Jan 2026 19:44:52 +0800") References: <20260126-scm-storage-v2-v2-0-fa045c7e7699@radxa.com> <20260126-scm-storage-v2-v2-2-fa045c7e7699@radxa.com> User-Agent: mu4e 1.12.7; emacs 30.2 Date: Thu, 29 Jan 2026 20:01:12 +0100 Message-ID: <87a4xwkzuv.fsf@bootlin.com> MIME-Version: 1.0 X-Last-TLS-Session-Version: TLSv1.3 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260129_110123_526561_706720E5 X-CRM114-Status: GOOD ( 26.52 ) X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+linux-mtd=archiver.kernel.org@lists.infradead.org SGVsbG8gSnVuaGFvLAoKPiArc3RhdGljIGludCBxY29tX3NjbV9zdG9yYWdlX2VyYXNlKHN0cnVj dCBtdGRfaW5mbyAqbXRkLAo+ICsJCQkJICBzdHJ1Y3QgZXJhc2VfaW5mbyAqaW5zdHIpCj4gK3sK PiArCXN0cnVjdCBxY29tX3NjbV9zdG9yYWdlICpob3N0ID0gbXRkLT5wcml2Owo+ICsJc2l6ZV90 IGJsb2NrX3NpemU7Cj4gKwo+ICsJaWYgKGluc3RyLT5hZGRyICUgaG9zdC0+bXRkLmVyYXNlc2l6 ZSB8fAo+ICsJICAgIGluc3RyLT5sZW4gJSBob3N0LT5tdGQuZXJhc2VzaXplKQo+ICsJCXJldHVy biAtRUlOVkFMOwoKQ2FuIHRoZXNlcyBzaXR1YXRpb25zIHJlYWxpc3RpY2FsbHkgaGFwcGVuPyBF cmFzZXMgYXJlIGluIHRoZW9yeQplcmFzZWJsb2NrIGFsaWduZWQsIHNvIEkgZG91YnQgdGhpcyBj YXNlIHNoYWxsIGJlIGNoZWNrZWQgaW4gZGV2aWNlIGRyaXZlcnMuCgo+ICsKPiArCWJsb2NrX3Np emUgPSBsZTMyX3RvX2NwdShob3N0LT5pbmZvLmJsb2NrX3NpemUpOwoKWW91IHNlZW0gdG8gc3Rv cmUgdGhlIFNDTSBpbmZvIHN0cnVjdHVyZSBhcy1pcyBhbmQgYWx3YXlzIG1ha2UKY29udmVyc2lv bnMgb24gdGhlIGZseS4gTWF5IEkgc3VnZ2VzdCB0byBzdG9yZSB0aGUgZmllbGRzIHlvdSBuZWVk CmRpcmVjdGx5IGluIHRoZSBjb3JyZWN0IGZvcm1hdC9lbmRpYW5uZXNzPwoKPiArCj4gKwlndWFy ZChtdXRleCkoJmhvc3QtPmxvY2spOwo+ICsKPiArCXJldHVybiBxY29tX3NjbV9zdG9yYWdlX3Nl bmRfY21kKFFDT01fU0NNX1NUT1JBR0VfU1BJTk9SLAo+ICsJCQkJCSBRQ09NX1NDTV9TVE9SQUdF X0VSQVNFLAo+ICsJCQkJCSBpbnN0ci0+YWRkciAvIGJsb2NrX3NpemUsCgpBY3R1YWxseSB3aGF0 IHlvdSBuZWVkIGluc3RlYWQgb2YgYmxvY2tfc2l6ZSBpcyB0byB1c2UgbXRkLT5lcmFzZXNpemUK ZGlyZWN0bHksIG5vIG5lZWQgdG8gc3RvcmUgImJsb2NrX3NpemUiIGluIHlvdXIgc3RydWN0dXJl LCB5b3UgYWxyZWFkeQpoYXZlIGl0LgoKPiArCQkJCQkgMCwgaW5zdHItPmxlbik7Cj4gK30KPiAr Cj4gK3N0YXRpYyBpbnQgcWNvbV9zY21fc3RvcmFnZV9yZWFkKHN0cnVjdCBtdGRfaW5mbyAqbXRk LAo+ICsJCQkJIGxvZmZfdCBmcm9tLCBzaXplX3QgbGVuLAo+ICsJCQkJIHNpemVfdCAqcmV0bGVu LCB1X2NoYXIgKmJ1ZikKCnVfY2hhcj8gQ2FuIHdlIHVzZSBhIG1vcmUgY29tbW9uIHR5cGU/Cgo+ ICt7Cj4gKwlzdHJ1Y3QgcWNvbV9zY21fc3RvcmFnZSAqaG9zdCA9IG10ZC0+cHJpdjsKPiArCWxv ZmZfdCBibG9ja19zdGFydCwgYmxvY2tfb2ZmLCBsYmE7Cj4gKwlzaXplX3QgYmxvY2tfc2l6ZSwg Y2h1bmssIHRvX3JlYWQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWlmIChyZXRsZW4pCj4gKwkJKnJl dGxlbiA9IDA7CgpBcmUgdGhlcmUgY2FzZXMgd2hlcmUgcmV0bGVuIGNhbiBiZSBhYnNlbnQ/Cgo+ ICsKPiArCWlmIChmcm9tICsgbGVuID4gbXRkLT5zaXplKQo+ICsJCXJldHVybiAtRUlOVkFMOwoK VGhpcyBjaGVjayBzaG91bGQgYmUgZG9uZSBhdCB0aGUgY29yZSBsZXZlbCBhbHJlYWR5LgoKPiAr CWlmIChsZW4gPT0gMCkKPiArCQlyZXR1cm4gMDsKCkRpdHRvIChzZWUgbXRkY2hhcl9yZWFkKCkp LgoKPiArCWJsb2NrX3NpemUgPSBsZTMyX3RvX2NwdShob3N0LT5pbmZvLmJsb2NrX3NpemUpOwo+ ICsKPiArCWd1YXJkKG11dGV4KSgmaG9zdC0+bG9jayk7Cj4gKwo+ICsJd2hpbGUgKGxlbiA+IDAp IHsKPiArCQlibG9ja19zdGFydCA9IHJvdW5kX2Rvd24oZnJvbSwgYmxvY2tfc2l6ZSk7Cj4gKwkJ YmxvY2tfb2ZmID0gZnJvbSAtIGJsb2NrX3N0YXJ0Owo+ICsJCWxiYSA9IGJsb2NrX3N0YXJ0IC8g YmxvY2tfc2l6ZTsKPiArCj4gKwkJaWYgKGJsb2NrX29mZiB8fCBsZW4gPCBibG9ja19zaXplKSB7 Cj4gKwkJCWNodW5rID0gbWluX3Qoc2l6ZV90LCBibG9ja19zaXplIC0gYmxvY2tfb2ZmLCBsZW4p Owo+ICsJCQl0b19yZWFkID0gYmxvY2tfc2l6ZTsKPiArCQl9IGVsc2Ugewo+ICsJCQljaHVuayA9 IHJvdW5kX2Rvd24obGVuLCBibG9ja19zaXplKTsKPiArCQkJY2h1bmsgPSBtaW5fdChzaXplX3Qs IGNodW5rLCBob3N0LT5idWZmZXJfc2l6ZSk7Cj4gKwkJCXRvX3JlYWQgPSBjaHVuazsKPiArCQl9 Cj4gKwo+ICsJCXJldCA9IHFjb21fc2NtX3N0b3JhZ2Vfc2VuZF9jbWQoUUNPTV9TQ01fU1RPUkFH RV9TUElOT1IsCj4gKwkJCQkJCVFDT01fU0NNX1NUT1JBR0VfUkVBRCwKPiArCQkJCQkJbGJhLCBo b3N0LT5idWZmZXIsCj4gKwkJCQkJCXRvX3JlYWQpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJldHVy biByZXQ7Cj4gKwo+ICsJCW1lbWNweShidWYsIGhvc3QtPmJ1ZmZlciArIGJsb2NrX29mZiwgY2h1 bmspOwo+ICsKPiArCQlidWYgKz0gY2h1bms7Cj4gKwkJZnJvbSArPSBjaHVuazsKPiArCQlsZW4g LT0gY2h1bms7Cj4gKwkJaWYgKHJldGxlbikKPiArCQkJKnJldGxlbiArPSBjaHVuazsKPiArCX0K PiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBxY29tX3NjbV9zdG9yYWdl X3dyaXRlKHN0cnVjdCBtdGRfaW5mbyAqbXRkLAo+ICsJCQkJICBsb2ZmX3QgdG8sIHNpemVfdCBs ZW4sCj4gKwkJCQkgIHNpemVfdCAqcmV0bGVuLCBjb25zdCB1X2NoYXIgKmJ1ZikKPiArewo+ICsJ c3RydWN0IHFjb21fc2NtX3N0b3JhZ2UgKmhvc3QgPSBtdGQtPnByaXY7Cj4gKwlsb2ZmX3QgYmxv Y2tfc3RhcnQsIGJsb2NrX29mZiwgbGJhOwo+ICsJc2l6ZV90IGJsb2NrX3NpemUsIGNodW5rLCB0 b193cml0ZTsKPiArCWludCByZXQ7Cj4gKwo+ICsJaWYgKHJldGxlbikKPiArCQkqcmV0bGVuID0g MDsKPiArCj4gKwlpZiAodG8gKyBsZW4gPiBtdGQtPnNpemUpCj4gKwkJcmV0dXJuIC1FSU5WQUw7 Cj4gKwo+ICsJaWYgKGxlbiA9PSAwKQo+ICsJCXJldHVybiAwOwo+ICsKPiArCWJsb2NrX3NpemUg PSBsZTMyX3RvX2NwdShob3N0LT5pbmZvLmJsb2NrX3NpemUpOwo+ICsKPiArCWd1YXJkKG11dGV4 KSgmaG9zdC0+bG9jayk7Cj4gKwo+ICsJd2hpbGUgKGxlbiA+IDApIHsKPiArCQlibG9ja19zdGFy dCA9IHJvdW5kX2Rvd24odG8sIGJsb2NrX3NpemUpOwo+ICsJCWJsb2NrX29mZiA9IHRvIC0gYmxv Y2tfc3RhcnQ7Cj4gKwkJbGJhID0gYmxvY2tfc3RhcnQgLyBibG9ja19zaXplOwo+ICsKPiArCQlp ZiAoYmxvY2tfb2ZmIHx8IGxlbiA8IGJsb2NrX3NpemUpIHsKPiArCQkJY2h1bmsgPSBtaW5fdChz aXplX3QsIGJsb2NrX3NpemUgLSBibG9ja19vZmYsIGxlbik7Cj4gKwkJCXRvX3dyaXRlID0gYmxv Y2tfc2l6ZTsKPiArCj4gKwkJCXJldCA9IHFjb21fc2NtX3N0b3JhZ2Vfc2VuZF9jbWQoUUNPTV9T Q01fU1RPUkFHRV9TUElOT1IsCj4gKwkJCQkJCQlRQ09NX1NDTV9TVE9SQUdFX1JFQUQsCj4gKwkJ CQkJCQlsYmEsIGhvc3QtPmJ1ZmZlciwKPiArCQkJCQkJCWJsb2NrX3NpemUpOwoKVGhpcyBpcyBz dHJhbmdlLiBEb2VzIGl0IHJlYWxseSB3b3JrPyBNeSB1bmRlcnN0YW5kaW5nOiB5b3UncmUgdHJ5 aW5nIHRvCmhhbmRsZSBhIG5vbiBhbGlnbmVkIHdyaXRlIGFjY2VzcyAoSSdtIG5vdCBldmVuIHN1 cmUgdGhpcyBpcyBwb3NzaWJsZSBhcwp5b3Ugc2V0IHdyaXRlc2l6ZSA9PSBlcmFzZXNpemUpIGJ5 IHJlYWRpbmcgdGhlIGV4aXN0aW5nIGRhdGEgYmVmb3JlCndyaXRpbmcuIElmIHRoYXQncyB3aGF0 IHlvdSBpbnRlbmQgdG8gZG8sIHlvdSdsbCBmb3JjaWJseSBnZXQgMXMgaW5zdGVhZApvZiBhY3R1 YWwgZGF0YSBiZWNhdXNlIGVyYXNlcyBhcmUgbWFuZGF0b3J5IGJlZm9yZSB3cml0ZXMsIHdoaWNo IG1lYW5zCnlvdXIgcmVhZCB3aWxsIGhhcHBlbiB0b28gbGF0ZS4KCkkgbWlnaHQgYmUgdG90YWxs eSB3cm9uZywgYnV0IEkgYmVsaWV2ZSB0aGlzIGFwcHJvYWNoIGlzCmluY29ycmVjdC4gUGxlYXNl IGV4cGxhaW4gd2hhdCB5b3UncmUgdHJ5aW5nIHRvIGRvIG90aGVyd2lzZS4KCj4gKwkJCWlmIChy ZXQpCj4gKwkJCQlyZXR1cm4gcmV0Owo+ICsJCX0gZWxzZSB7Cj4gKwkJCWNodW5rID0gcm91bmRf ZG93bihsZW4sIGJsb2NrX3NpemUpOwo+ICsJCQljaHVuayA9IG1pbl90KHNpemVfdCwgY2h1bmss IGhvc3QtPmJ1ZmZlcl9zaXplKTsKPiArCQkJdG9fd3JpdGUgPSBjaHVuazsKPiArCQl9Cj4gKwo+ ICsJCW1lbWNweShob3N0LT5idWZmZXIgKyBibG9ja19vZmYsIGJ1ZiwgY2h1bmspOwo+ICsKPiAr CQlyZXQgPSBxY29tX3NjbV9zdG9yYWdlX3NlbmRfY21kKFFDT01fU0NNX1NUT1JBR0VfU1BJTk9S LAo+ICsJCQkJCQlRQ09NX1NDTV9TVE9SQUdFX1dSSVRFLAo+ICsJCQkJCQlsYmEsIGhvc3QtPmJ1 ZmZlciwKPiArCQkJCQkJdG9fd3JpdGUpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJldHVybiByZXQ7 Cj4gKwo+ICsJCWJ1ZiArPSBjaHVuazsKPiArCQl0byArPSBjaHVuazsKPiArCQlsZW4gLT0gY2h1 bms7Cj4gKwkJaWYgKHJldGxlbikKPiArCQkJKnJldGxlbiArPSBjaHVuazsKPiArCX0KPiArCj4g KwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBxY29tX3NjbV9zdG9yYWdlX3Byb2Jl KHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBkZXZpY2UgKmRl diA9ICZwZGV2LT5kZXY7Cj4gKwlzdHJ1Y3QgcWNvbV9zY21fc3RvcmFnZSAqaG9zdDsKPiArCXU2 NCB0b3RhbF9ibG9ja3MsIHNlcmlhbF9udW07Cj4gKwl1MzIgYmxvY2tfc2l6ZTsKPiArCWludCBy ZXQ7Cj4gKwo+ICsJaG9zdCA9IGRldm1fa3phbGxvYyhkZXYsIHNpemVvZigqaG9zdCksIEdGUF9L RVJORUwpOwo+ICsJaWYgKCFob3N0KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCXBsYXRm b3JtX3NldF9kcnZkYXRhKHBkZXYsIGhvc3QpOwo+ICsJaG9zdC0+ZGV2ID0gZGV2Owo+ICsKPiAr CXJldCA9IGRldm1fbXV0ZXhfaW5pdChkZXYsICZob3N0LT5sb2NrKTsKPiArCWlmIChyZXQpCj4g KwkJcmV0dXJuIHJldDsKPiArCj4gKwlob3N0LT5idWZmZXJfc2l6ZSA9IFNaXzI1Nks7Cj4gKwlo b3N0LT5idWZmZXIgPSBkZXZtX2t6YWxsb2MoZGV2LCBob3N0LT5idWZmZXJfc2l6ZSwgR0ZQX0tF Uk5FTCk7CgpEbyB5b3UgcmVhbGx5IG5lZWQgMjU2SyBvZiBhZGphY2VudCBtZW1vcnk/IElmIHRo aXMgaXMgYSBETUEtYWJsZQpidWZmZXIsIHRoZW4geWVzLiBBbHNvLCB0aGUgY2hlY2sgKGJsb2Nr X3NpemUgdnMuIGJ1ZmZlcl9zaXplKSBzaG91bGQKaGFwcGVuIGJlZm9yZSB0aGlzIGFsbG9jYXRp b24sIGFuZCB5b3Ugc2hvdWxkIG5vdCBuZWVkIHRvIGFsbG9jYXRlIDI1NmsKYmxpbmRseSwganVz dCB1c2UgdGhlIE5PUiBnZW9tZXRyeSBrbm93bGVkZ2UuCgo+ICsJaWYgKCFob3N0LT5idWZmZXIp Cj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJcmV0ID0gcWNvbV9zY21fc3RvcmFnZV9zZW5k X2NtZChRQ09NX1NDTV9TVE9SQUdFX1NQSU5PUiwKPiArCQkJCQlRQ09NX1NDTV9TVE9SQUdFX0dF VF9JTkZPLAo+ICsJCQkJCTAsICZob3N0LT5pbmZvLAo+ICsJCQkJCXNpemVvZihob3N0LT5pbmZv KSk7Cj4gKwlpZiAocmV0IDwgMCkKPiArCQlyZXR1cm4gZGV2X2Vycl9wcm9iZShkZXYsIHJldCwK PiArCQkJCSAgICAgImZhaWxlZCB0byBnZXQgc3RvcmFnZSBpbmZvXG4iKTsKCk1heWJlIHRoaXMg cHJpbnQgY2FuIGJlIGVuaGFuY2VkLCBpdCBtYXkgYWxzbyBtZWFuIHRoZSBmaXJtd2FyZSBkb2Vz IG5vdAppbXBsZW1lbnQgdGhlIHJlcXVpcmVkIHN5c3RlbSBjYWxsPwoKPiArCj4gKwl0b3RhbF9i bG9ja3MgPSBsZTY0X3RvX2NwdShob3N0LT5pbmZvLnRvdGFsX2Jsb2Nrcyk7Cj4gKwlzZXJpYWxf bnVtID0gbGU2NF90b19jcHUoaG9zdC0+aW5mby5zZXJpYWxfbnVtKTsKPiArCWJsb2NrX3NpemUg PSBsZTMyX3RvX2NwdShob3N0LT5pbmZvLmJsb2NrX3NpemUpOwo+ICsKPiArCWlmICghYmxvY2tf c2l6ZSB8fCAhdG90YWxfYmxvY2tzKQo+ICsJCXJldHVybiBkZXZfZXJyX3Byb2JlKGRldiwgLUVJ TlZBTCwKPiArCQkJCSAgICAgImludmFsaWQgc3RvcmFnZSBnZW9tZXRyeVxuIik7Cj4gKwo+ICsJ aWYgKGJsb2NrX3NpemUgPiBob3N0LT5idWZmZXJfc2l6ZSkKPiArCQlyZXR1cm4gZGV2X2Vycl9w cm9iZShkZXYsIC1FSU5WQUwsCj4gKwkJCQkgICAgICJibG9jayBzaXplICV1IGV4Y2VlZHMgYnVm ZmVyIHNpemVcbiIsCj4gKwkJCQkgICAgIGJsb2NrX3NpemUpOwoKSSBhbSBub3cgaW4gZmF2b3Vy IG9mIHJlZHVjaW5nIGxvZ3MgaW4gdGhlIGtlcm5lbCwgbWF5YmUgeW91IGNhbiBncm91cAp0aGVz ZSB0d28gcHJpbnRzIGludG8gb25lLCBpbmRpY2F0aW5nIHRoZSBpbmZvIHlvdSBnZXQgZnJvbSBm aXJtd2FyZSBpcwppbmNvcnJlY3Q/IEFsc28sIHdoYXQgaXMgdGhlIHBvaW50IG9mIHVzaW5nIGRl dl9lcnJfcHJvYmUoKSBoZXJlLCBhcyB5b3UKY2Fubm90IGhhdmUgYW4gRVBST0JFX0RFRkVSPwoK PiArCj4gKwlob3N0LT5tdGQucHJpdiA9IGhvc3Q7Cj4gKwlob3N0LT5tdGQubmFtZSA9IGRldl9u YW1lKGRldik7Cj4gKwlob3N0LT5tdGQub3duZXIgPSBUSElTX01PRFVMRTsKPiArCWhvc3QtPm10 ZC5kZXYucGFyZW50ID0gZGV2Owo+ICsJaG9zdC0+bXRkLnNpemUgPSB0b3RhbF9ibG9ja3MgKiBi bG9ja19zaXplOwo+ICsJaG9zdC0+bXRkLmVyYXNlc2l6ZSA9IGJsb2NrX3NpemU7Cj4gKwlob3N0 LT5tdGQud3JpdGVzaXplID0gYmxvY2tfc2l6ZTsKPiArCWhvc3QtPm10ZC53cml0ZWJ1ZnNpemUg PSBibG9ja19zaXplOwo+ICsJaG9zdC0+bXRkLnR5cGUgPSBNVERfTk9SRkxBU0g7Cj4gKwlob3N0 LT5tdGQuZmxhZ3MgPSBNVERfV1JJVEVBQkxFOwo+ICsJaG9zdC0+bXRkLl9lcmFzZSA9IHFjb21f c2NtX3N0b3JhZ2VfZXJhc2U7Cj4gKwlob3N0LT5tdGQuX3JlYWQgPSBxY29tX3NjbV9zdG9yYWdl X3JlYWQ7Cj4gKwlob3N0LT5tdGQuX3dyaXRlID0gcWNvbV9zY21fc3RvcmFnZV93cml0ZTsKPiAr Cj4gKwlkZXZfaW5mbyhkZXYsICJzY20gc3RvcmFnZSAweCVsbHggcmVnaXN0ZXJlZCB3aXRoIHNp emUgJWxsdSBieXRlc1xuIiwKPiArCQkgc2VyaWFsX251bSwgaG9zdC0+bXRkLnNpemUpOwoKUGxl YXNlIGRyb3AgdGhpcyBtZXNzYWdlLCBpdCBpcyBub3QgdXNlZnVsLgoKLi4uCgo+ICtzdGF0aWMg c3RydWN0IHBsYXRmb3JtX2RyaXZlciBxY29tX3NjbV9zdG9yYWdlX2RyaXZlciA9IHsKPiArCS5w cm9iZQk9IHFjb21fc2NtX3N0b3JhZ2VfcHJvYmUsCj4gKwkucmVtb3ZlCT0gcWNvbV9zY21fc3Rv cmFnZV9yZW1vdmUsCj4gKwkuZHJpdmVyID0gewo+ICsJCS5uYW1lCT0gInFjb21fc2NtX3N0b3Jh Z2UiLAo+ICsJfSwKPiArCS5pZF90YWJsZSA9IHFjb21fc2NtX3N0b3JhZ2VfaWRzLAoKSSBhbSBz dXJwcmlzZWQgeW91IGhhdmUgYW4gaWRfdGFibGUgaGVyZSwgdGhpcyBpcyBsaWtlbHkgbm90IGZv ciBhbiBPRgpiYXNlZCBwbGF0Zm9ybSwgZG8geW91IGNvbmZpcm0/CgpUaGFua3MsCk1pcXXDqGwK Cl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpM aW51eCBNVEQgZGlzY3Vzc2lvbiBtYWlsaW5nIGxpc3QKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5v cmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1tdGQvCg==