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=-8.2 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, USER_AGENT_SANE_2 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 7075EC33CA1 for ; Mon, 20 Jan 2020 10:03:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 340D520882 for ; Mon, 20 Jan 2020 10:03:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726465AbgATKDS convert rfc822-to-8bit (ORCPT ); Mon, 20 Jan 2020 05:03:18 -0500 Received: from relay5-d.mail.gandi.net ([217.70.183.197]:36811 "EHLO relay5-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726573AbgATKDR (ORCPT ); Mon, 20 Jan 2020 05:03:17 -0500 X-Originating-IP: 90.76.211.102 Received: from xps13 (lfbn-tou-1-1151-102.w90-76.abo.wanadoo.fr [90.76.211.102]) (Authenticated sender: miquel.raynal@bootlin.com) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id 3C40A1C001A; Mon, 20 Jan 2020 10:03:06 +0000 (UTC) Date: Mon, 20 Jan 2020 11:03:06 +0100 From: Miquel Raynal To: WeiXiong Liao Cc: Kees Cook , Anton Vorontsov , Colin Cross , Tony Luck , Jonathan Corbet , Richard Weinberger , Vignesh Raghavendra , Mauro Carvalho Chehab , "David S. Miller" , Rob Herring , Greg Kroah-Hartman , Jonathan Cameron , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org Subject: Re: [PATCH v1 11/11] mtd: new support oops logger based on pstore/blk Message-ID: <20200120110306.32e53fd8@xps13> In-Reply-To: <1579482233-2672-12-git-send-email-liaoweixiong@allwinnertech.com> References: <1579482233-2672-1-git-send-email-liaoweixiong@allwinnertech.com> <1579482233-2672-12-git-send-email-liaoweixiong@allwinnertech.com> Organization: Bootlin X-Mailer: Claws Mail 3.17.4 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8BIT Sender: linux-doc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-doc@vger.kernel.org Hi WeiXiong, WeiXiong Liao wrote on Mon, 20 Jan 2020 09:03:53 +0800: > It's the last one of a series of patches for adaptive to MTD device. > > The mtdpstore is similar to mtdoops but more powerful. It bases on > pstore/blk, aims to store panic and oops log to a flash partition, logs? > where it can be read back as files after mounting pstore filesystem. > > The pstore/blk and blkoops, a wrapper for pstore/blk, are designed for > block device at the very beginning, but now, compatible to not only > block device. After this series of patches, pstore/blk can also work > for MTD device. To make it work, 'blkdev' on kconfig or module > parameter of blkoops should be set as mtd device name or mtd number. > See more about pstore/blk and blkoops on: > Documentation/admin-guide/pstore-block.rst > > Why do we need mtdpstore? > 1. repetitive jobs between pstore and mtdoops > Both of pstore and mtdoops do the same jobs that store panic/oops log. > They have much similar logic that register to kmsg dumper and store > log to several chunks one by one. > 2. do what a driver should do > To me, a driver should provide methods instead of policies. What MTD > should do is to provide read/write/erase operations, geting rid of codes > about chunk management, kmsg dumper and configuration. > 3. enhanced feature > Not only store log, but also show it as files. > Not only log, but also trigger time and trigger count. > Not only panic/oops log, but also log recorder for pmsg, console and > ftrace in the future. > > Signed-off-by: WeiXiong Liao > Reported-by: kbuild test robot I don't thing the test robot has a meaning here. > --- > drivers/mtd/Kconfig | 10 + > drivers/mtd/Makefile | 1 + > drivers/mtd/mtdpstore.c | 530 ++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 541 insertions(+) > create mode 100644 drivers/mtd/mtdpstore.c > > diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig > index 42d401ea60ee..a6e59495a738 100644 > --- a/drivers/mtd/Kconfig > +++ b/drivers/mtd/Kconfig > @@ -170,6 +170,16 @@ config MTD_OOPS > buffer in a flash partition where it can be read back at some > later point. > > +config MTD_PSTORE > + tristate "Log panic/oops to an MTD buffer base on pstore" based > + depends on PSTORE_BLKOOPS > + help > + This enables panic and oops messages to be logged to a circular > + buffer in a flash partition where it can be read back as files after > + mounting pstore filesystem. > + > + If unsure, say N. > + > config MTD_SWAP > tristate "Swap on MTD device support" > depends on MTD && SWAP > diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile > index 56cc60ccc477..593d0593a038 100644 > --- a/drivers/mtd/Makefile > +++ b/drivers/mtd/Makefile > @@ -20,6 +20,7 @@ obj-$(CONFIG_RFD_FTL) += rfd_ftl.o > obj-$(CONFIG_SSFDC) += ssfdc.o > obj-$(CONFIG_SM_FTL) += sm_ftl.o > obj-$(CONFIG_MTD_OOPS) += mtdoops.o > +obj-$(CONFIG_MTD_PSTORE) += mtdpstore.o > obj-$(CONFIG_MTD_SWAP) += mtdswap.o > > nftl-objs := nftlcore.o nftlmount.o > diff --git a/drivers/mtd/mtdpstore.c b/drivers/mtd/mtdpstore.c > new file mode 100644 > index 000000000000..ab4acd3a9011 > --- /dev/null > +++ b/drivers/mtd/mtdpstore.c > @@ -0,0 +1,530 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * MTD Oops/Panic loger for pstore/blk > + * > + * Copyright (C) 2019 WeiXiong Liao > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. The license text is not needed since you added SPDX tag. > + * > + */ > +#define pr_fmt(fmt) "mtdoops-pstore: " fmt > + > +#include > +#include > +#include > +#include > +#include > + > +/* Maximum MTD partition size */ > +#define MTDPSTORE_MAX_MTD_SIZE (8 * 1024 * 1024) SZ_8M > + > +static struct mtdpstore_context { > + int index; > + struct blkoops_info bo_info; > + struct blkoops_device bo_dev; > + struct mtd_info *mtd; > + unsigned long *rmmap; /* removed bit map */ > + unsigned long *usedmap; /* used bit map */ > + /* > + * used for panic write > + * As there are no block_isbad for panic case, we should keep this > + * status before panic to ensure panic_write not failed. > + */ > + unsigned long *badmap; /* bad block bit map */ > +} oops_cxt; > + > +static int mtdpstore_block_isbad(struct mtdpstore_context *cxt, loff_t off) > +{ > + int ret; > + struct mtd_info *mtd = cxt->mtd; > + u64 blknum = div_u64(off, mtd->erasesize); > + > + if (test_bit(blknum, cxt->badmap)) > + return true; > + ret = mtd_block_isbad(mtd, off); > + if (ret < 0) { > + pr_err("mtd_block_isbad failed, aborting\n"); > + return ret; > + } else if (ret > 0) { > + set_bit(blknum, cxt->badmap); > + return true; > + } > + return false; > +} > + > +static inline int mtdpstore_panic_block_isbad(struct mtdpstore_context *cxt, > + loff_t off) > +{ > + struct mtd_info *mtd = cxt->mtd; > + u64 blknum = div_u64(off, mtd->erasesize); > + > + return test_bit(blknum, cxt->badmap); > +} > + > +static inline void mtdpstore_mark_used(struct mtdpstore_context *cxt, > + loff_t off) > +{ > + u64 zonenum = div_u64(off, cxt->bo_info.dmesg_size); > + > + pr_debug("mark zone %llu used\n", zonenum); > + set_bit(zonenum, cxt->usedmap); > +} > + > +static inline void mtdpstore_mark_unused(struct mtdpstore_context *cxt, > + loff_t off) > +{ > + u64 zonenum = div_u64(off, cxt->bo_info.dmesg_size); > + > + pr_debug("mark zone %llu unused\n", zonenum); > + clear_bit(zonenum, cxt->usedmap); > +} > + > +static inline void mtdpstore_block_mark_unused(struct mtdpstore_context *cxt, > + loff_t off) > +{ > + u64 zonenum = div_u64(off, cxt->bo_info.dmesg_size); > + u32 zonecnt = cxt->mtd->erasesize / cxt->bo_info.dmesg_size; > + > + while (zonecnt > 0) { > + pr_debug("mark zone %llu unused\n", zonenum); > + clear_bit(zonenum, cxt->usedmap); > + zonenum++; > + zonecnt--; > + } > +} > + > +static inline int mtdpstore_is_used(struct mtdpstore_context *cxt, loff_t off) > +{ > + u64 zonenum = div_u64(off, cxt->bo_info.dmesg_size); > + u64 blknum = div_u64(off, cxt->mtd->erasesize); > + > + if (test_bit(blknum, cxt->badmap)) > + return true; > + return test_bit(zonenum, cxt->usedmap); > +} > + > +static int mtdpstore_block_is_used(struct mtdpstore_context *cxt, > + loff_t off) > +{ > + u64 zonenum = div_u64(off, cxt->bo_info.dmesg_size); > + u32 zonecnt = cxt->mtd->erasesize / cxt->bo_info.dmesg_size; > + > + while (zonecnt > 0) { > + if (test_bit(zonenum, cxt->usedmap)) > + return true; > + zonenum++; > + zonecnt--; > + } > + return false; > +} > + > +static int mtdpstore_is_empty(struct mtdpstore_context *cxt, char *buf, > + size_t size) > +{ > + struct mtd_info *mtd = cxt->mtd; > + size_t sz; > + int i; > + > + sz = min_t(uint32_t, size, mtd->writesize / 4); > + for (i = 0; i < sz; i++) { > + if (buf[i] != (char)0xFF) > + return false; > + } > + return true; > +} > + > +static void mtdpstore_mark_removed(struct mtdpstore_context *cxt, loff_t off) > +{ > + u64 zonenum = div_u64(off, cxt->bo_info.dmesg_size); > + > + pr_debug("mark zone %llu removed\n", zonenum); > + set_bit(zonenum, cxt->rmmap); > +} > + > +static void mtdpstore_block_clear_removed(struct mtdpstore_context *cxt, > + loff_t off) > +{ > + u64 zonenum = div_u64(off, cxt->bo_info.dmesg_size); > + u32 zonecnt = cxt->mtd->erasesize / cxt->bo_info.dmesg_size; > + > + while (zonecnt > 0) { > + clear_bit(zonenum, cxt->rmmap); > + zonenum++; > + zonecnt--; > + } > +} > + > +static int mtdpstore_block_is_removed(struct mtdpstore_context *cxt, > + loff_t off) > +{ > + u64 zonenum = div_u64(off, cxt->bo_info.dmesg_size); > + u32 zonecnt = cxt->mtd->erasesize / cxt->bo_info.dmesg_size; > + > + while (zonecnt > 0) { > + if (test_bit(zonenum, cxt->rmmap)) > + return true; > + zonenum++; > + zonecnt--; > + } > + return false; > +} > + > +static int mtdpstore_erase_do(struct mtdpstore_context *cxt, loff_t off) > +{ > + struct erase_info erase; > + int ret; > + > + pr_debug("try to erase off 0x%llx\n", off); > + erase.len = cxt->mtd->erasesize; > + erase.addr = off; > + ret = mtd_erase(cxt->mtd, &erase); > + if (!ret) > + mtdpstore_block_clear_removed(cxt, off); > + else > + pr_err("erase of region [0x%llx, 0x%llx] on \"%s\" failed\n", > + (unsigned long long)erase.addr, > + (unsigned long long)erase.len, cxt->bo_info.device); > + return ret; > +} > + > +/* > + * called while removing file > + * > + * Avoiding over erasing, do erase only when all zones are removed or unused. > + * Ensure to remove when unregister by reading, erasing and wrtiing back. > + */ > +static ssize_t mtdpstore_erase(size_t size, loff_t off) > +{ > + struct mtdpstore_context *cxt = &oops_cxt; > + > + if (mtdpstore_block_isbad(cxt, off)) > + return -EIO; > + > + mtdpstore_mark_unused(cxt, off); > + > + if (likely(mtdpstore_block_is_used(cxt, off))) { > + mtdpstore_mark_removed(cxt, off); > + return 0; > + } > + > + /* all zones are unused, erase it */ > + off = ALIGN_DOWN(off, cxt->mtd->erasesize); > + return mtdpstore_erase_do(cxt, off); > +} > + > +/* > + * What is securety for mtdpstore? security > + * As there is no erase for panic case, we should ensure at least one zone > + * is writable. Otherwise, panic write will be failed. will fail. > + * If zone is used, write operation will return -ENEXT, which means that > + * pstore/blk will try one by one until get a empty zone. So, it's no need it gets an empty zone. So it is not needed to ... > + * to ensure next zone is empty, but at least one. the > + */ > +static int mtdpstore_security(struct mtdpstore_context *cxt, loff_t off) > +{ > + int ret = 0, i; > + u32 zonenum = (u32)div_u64(off, cxt->bo_info.dmesg_size); > + u32 zonecnt = (u32)div_u64(cxt->mtd->size, cxt->bo_info.dmesg_size); > + u32 blkcnt = (u32)div_u64(cxt->mtd->size, cxt->mtd->erasesize); > + u32 erasesize = cxt->mtd->erasesize; > + > + for (i = 0; i < zonecnt; i++) { > + u32 num = (zonenum + i) % zonecnt; > + > + /* found empty zone */ > + if (!test_bit(num, cxt->usedmap)) > + return 0; > + } > + > + /* If there is no any empty zone, we have no way but to do erase */ > + off = ALIGN_DOWN(off, erasesize); > + while (blkcnt--) { > + div64_u64_rem(off + erasesize, cxt->mtd->size, (u64 *)&off); > + > + if (mtdpstore_block_isbad(cxt, off)) > + continue; > + > + ret = mtdpstore_erase_do(cxt, off); > + if (!ret) { > + mtdpstore_block_mark_unused(cxt, off); > + break; > + } > + } > + > + if (ret) > + pr_err("all blocks bad!\n"); > + pr_debug("end security\n"); > + return ret; > +} > + > +static ssize_t mtdpstore_write(const char *buf, size_t size, loff_t off) > +{ > + struct mtdpstore_context *cxt = &oops_cxt; > + size_t retlen; > + int ret; > + > + if (mtdpstore_block_isbad(cxt, off)) > + return -ENEXT; > + > + /* zone is used, please try next one */ > + if (mtdpstore_is_used(cxt, off)) > + return -ENEXT; > + > + pr_debug("try to write off 0x%llx size %zu\n", off, size); > + ret = mtd_write(cxt->mtd, off, size, &retlen, (u_char *)buf); > + if (ret < 0 || retlen != size) { > + pr_err("write failure at %lld (%zu of %zu written), err %d\n", > + off, retlen, size, ret); > + return -EIO; > + } > + mtdpstore_mark_used(cxt, off); > + > + mtdpstore_security(cxt, off); > + return retlen; > +} > + > +/* > + * All zones will be read as pstore/blk will read zone one by one when do > + * recover. > + */ > +static ssize_t mtdpstore_read(char *buf, size_t size, loff_t off) > +{ > + struct mtdpstore_context *cxt = &oops_cxt; > + size_t retlen; > + int ret; > + > + if (mtdpstore_block_isbad(cxt, off)) > + return -ENEXT; > + > + pr_debug("try to read off 0x%llx size %zu\n", off, size); > + ret = mtd_read(cxt->mtd, off, size, &retlen, (u_char *)buf); > + if ((ret < 0 && !mtd_is_bitflip(ret)) || size != retlen) { IIRC size != retlen does not mean it failed, but that you should continue reading after retlen bytes, no? Also, mtd_is_bitflip() does not mean that you are reading a false buffer, but that the data has been corrected as it contained bitflips. mtd_is_eccerr() however, would be meaningful. > + pr_err("read failure at %lld (%zu of %zu read), err %d\n", > + off, retlen, size, ret); > + return -EIO; > + } > + > + if (mtdpstore_is_empty(cxt, buf, size)) > + mtdpstore_mark_unused(cxt, off); > + else > + mtdpstore_mark_used(cxt, off); > + > + mtdpstore_security(cxt, off); > + return retlen; > +} > + > +static ssize_t mtdpstore_panic_write(const char *buf, size_t size, loff_t off) > +{ > + struct mtdpstore_context *cxt = &oops_cxt; > + size_t retlen; > + int ret; > + > + if (mtdpstore_panic_block_isbad(cxt, off)) > + return -ENEXT; > + > + /* zone is used, please try next one */ > + if (mtdpstore_is_used(cxt, off)) > + return -ENEXT; > + > + ret = mtd_panic_write(cxt->mtd, off, size, &retlen, (u_char *)buf); > + if (ret < 0 || size != retlen) { > + pr_err("panic write failure at %lld (%zu of %zu read), err %d\n", > + off, retlen, size, ret); > + return -EIO; > + } > + mtdpstore_mark_used(cxt, off); > + > + return retlen; > +} > + > +static void mtdpstore_notify_add(struct mtd_info *mtd) > +{ > + int ret; > + struct mtdpstore_context *cxt = &oops_cxt; > + struct blkoops_info *info = &cxt->bo_info; > + unsigned long longcnt; > + > + if (!strcmp(mtd->name, info->device)) > + cxt->index = mtd->index; > + > + if (mtd->index != cxt->index || cxt->index < 0) > + return; > + > + pr_debug("found matching MTD device %s\n", mtd->name); > + > + if (mtd->size < info->dmesg_size * 2) { > + pr_err("MTD partition %d not big enough\n", mtd->index); > + return; > + } > + if (mtd->erasesize < info->dmesg_size) { > + pr_err("eraseblock size of MTD partition %d too small\n", > + mtd->index); What is the usual size of dmesg? Could this check be too limiting? > + return; > + } > + if (unlikely(info->dmesg_size % mtd->writesize)) { > + pr_err("record size %lu KB must align to write size %d KB\n", > + info->dmesg_size / 1024, > + mtd->writesize / 1024); This condition is weird, why would you check this? > + return; > + } > + if (unlikely(mtd->size > MTDPSTORE_MAX_MTD_SIZE)) { > + pr_err("mtd%d is too large (limit is %d MiB)\n", > + mtd->index, > + MTDPSTORE_MAX_MTD_SIZE / 1024 / 1024); Same question? I could understand that it is easier to manage blocks knowing their maximum number though. > + return; > + } > + > + longcnt = BITS_TO_LONGS(div_u64(mtd->size, info->dmesg_size)); > + cxt->rmmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); > + cxt->usedmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); > + > + longcnt = BITS_TO_LONGS(div_u64(mtd->size, mtd->erasesize)); > + cxt->badmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); > + > + cxt->bo_dev.total_size = mtd->size; > + /* just support dmesg right now */ > + cxt->bo_dev.flags = BLKOOPS_DEV_SUPPORT_DMESG; > + cxt->bo_dev.read = mtdpstore_read; > + cxt->bo_dev.write = mtdpstore_write; > + cxt->bo_dev.erase = mtdpstore_erase; > + cxt->bo_dev.panic_write = mtdpstore_panic_write; > + > + ret = blkoops_register_device(&cxt->bo_dev); > + if (ret) { > + pr_err("mtd%d register to blkoops failed\n", mtd->index); > + return; > + } > + cxt->mtd = mtd; > + pr_info("Attached to MTD device %d\n", mtd->index); > +} > + > +static int mtdpstore_flush_removed_do(struct mtdpstore_context *cxt, > + loff_t off, size_t size) > +{ > + struct mtd_info *mtd = cxt->mtd; > + u_char *buf; > + int ret; > + size_t retlen; > + struct erase_info erase; > + > + buf = kmalloc(mtd->erasesize, GFP_KERNEL); > + if (!buf) > + return -ENOMEM; > + > + /* 1st. read to cache */ > + ret = mtd_read(mtd, off, mtd->erasesize, &retlen, buf); > + if (ret || retlen != mtd->erasesize) > + goto free; > + > + /* 2nd. erase block */ > + erase.len = mtd->erasesize; > + erase.addr = off; > + ret = mtd_erase(mtd, &erase); > + if (ret) > + goto free; > + > + /* 3rd. write back */ > + while (size) { > + unsigned int zonesize = cxt->bo_info.dmesg_size; > + > + /* remove must clear used bit */ > + if (mtdpstore_is_used(cxt, off)) > + mtd_write(mtd, off, zonesize, &retlen, buf); Besides the fact that should definitely check the write return code, I don't understand what you do in this function. What does flush_removed_do mean? > + > + off += zonesize; > + size -= min_t(unsigned int, zonesize, size); > + } > + > +free: > + kfree(buf); > + return ret; > +} > + > +static int mtdpstore_flush_removed(struct mtdpstore_context *cxt) > +{ > + struct mtd_info *mtd = cxt->mtd; > + int ret; > + loff_t off; > + u32 blkcnt = (u32)div_u64(mtd->size, mtd->erasesize); > + > + for (off = 0; blkcnt > 0; blkcnt--, off += mtd->erasesize) { > + ret = mtdpstore_block_is_removed(cxt, off); > + if (!ret) { > + off += mtd->erasesize; > + continue; > + } > + > + ret = mtdpstore_flush_removed_do(cxt, off, mtd->erasesize); > + if (ret) > + return ret; > + } > + return 0; > +} > + > +static void mtdpstore_notify_remove(struct mtd_info *mtd) > +{ > + struct mtdpstore_context *cxt = &oops_cxt; > + > + if (mtd->index != cxt->index || cxt->index < 0) > + return; > + > + mtdpstore_flush_removed(cxt); > + > + blkoops_unregister_device(&cxt->bo_dev); > + kfree(cxt->badmap); > + kfree(cxt->usedmap); > + kfree(cxt->rmmap); > + cxt->mtd = NULL; > + cxt->index = -1; > +} > + > +static struct mtd_notifier mtdpstore_notifier = { > + .add = mtdpstore_notify_add, > + .remove = mtdpstore_notify_remove, > +}; > + > +static int __init mtdpstore_init(void) > +{ > + int ret; > + struct mtdpstore_context *cxt = &oops_cxt; > + struct blkoops_info *info = &cxt->bo_info; > + > + ret = blkoops_info(info); > + if (unlikely(ret)) > + return ret; > + > + if (strlen(info->device) == 0) { > + pr_err("mtd device must be supplied\n"); > + return -EINVAL; > + } > + if (!info->dmesg_size) { > + pr_err("no recorder enabled\n"); > + return -EINVAL; > + } > + > + /* Setup the MTD device to use */ > + ret = kstrtoint((char *)info->device, 0, &cxt->index); > + if (ret) > + cxt->index = -1; > + > + register_mtd_user(&mtdpstore_notifier); > + return 0; > +} > +module_init(mtdpstore_init); > + > +static void __exit mtdpstore_exit(void) > +{ > + unregister_mtd_user(&mtdpstore_notifier); > +} > +module_exit(mtdpstore_exit); > + > +MODULE_LICENSE("GPL"); > +MODULE_AUTHOR("WeiXiong Liao "); > +MODULE_DESCRIPTION("MTD Oops/Panic console logger/driver"); Thanks, Miquèl 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=-8.3 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_2 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 23246C2D0DB for ; Mon, 20 Jan 2020 10:03:43 +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 DB5DE2087E for ; Mon, 20 Jan 2020 10:03:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="X2KMp0UI" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org DB5DE2087E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-mtd-bounces+linux-mtd=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-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Subject: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=bdK1UtOtVH7GS6rN6kUMN7HPIhvbLkERz6X6lApR95o=; b=X2KMp0UI4zLBnT OfyNhR/RjenYI6E64EvrEEhNsBydeT3Gabi9H8+Ip4JrVe1HaAmqvi5RXpq8UEKDD0wCSe52b7EAp O8d+IUnWlVNfc9DDTzs+WSjTq2nV3Whpq4MOTyRvbarM/2/jxVrSecGf414r8p2j1Ad5RdQzvaj7M 4E+A63EYPy5Xqo2ePt6lJSTAthD8u3LbhYJ7JISrtjvjxGFlovS27fWmwBgpy8kn+ZZ8y29ryMUCD q1+rEjJ03BO7bwG1ATDhr9YOGR/4qf4sc9YkCfbnvWyj9UTsA/zWe4hYFw4BSqtHpWFiKzYdkXjss P5/eyIKRIxrLoT4MUudQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1itTu5-00058A-D0; Mon, 20 Jan 2020 10:03:29 +0000 Received: from relay5-d.mail.gandi.net ([217.70.183.197]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1itTty-0004yF-2R for linux-mtd@lists.infradead.org; Mon, 20 Jan 2020 10:03:28 +0000 X-Originating-IP: 90.76.211.102 Received: from xps13 (lfbn-tou-1-1151-102.w90-76.abo.wanadoo.fr [90.76.211.102]) (Authenticated sender: miquel.raynal@bootlin.com) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id 3C40A1C001A; Mon, 20 Jan 2020 10:03:06 +0000 (UTC) Date: Mon, 20 Jan 2020 11:03:06 +0100 From: Miquel Raynal To: WeiXiong Liao Subject: Re: [PATCH v1 11/11] mtd: new support oops logger based on pstore/blk Message-ID: <20200120110306.32e53fd8@xps13> In-Reply-To: <1579482233-2672-12-git-send-email-liaoweixiong@allwinnertech.com> References: <1579482233-2672-1-git-send-email-liaoweixiong@allwinnertech.com> <1579482233-2672-12-git-send-email-liaoweixiong@allwinnertech.com> Organization: Bootlin X-Mailer: Claws Mail 3.17.4 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200120_020322_411326_75980F92 X-CRM114-Status: GOOD ( 36.97 ) X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Rob Herring , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, Greg Kroah-Hartman , linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, Jonathan Cameron , Colin Cross , Mauro Carvalho Chehab , "David S. Miller" , Vignesh Raghavendra 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 SGkgV2VpWGlvbmcsCgpXZWlYaW9uZyBMaWFvIDxsaWFvd2VpeGlvbmdAYWxsd2lubmVydGVjaC5j b20+IHdyb3RlIG9uIE1vbiwgMjAgSmFuCjIwMjAgMDk6MDM6NTMgKzA4MDA6Cgo+IEl0J3MgdGhl IGxhc3Qgb25lIG9mIGEgc2VyaWVzIG9mIHBhdGNoZXMgZm9yIGFkYXB0aXZlIHRvIE1URCBkZXZp Y2UuCj4gCj4gVGhlIG10ZHBzdG9yZSBpcyBzaW1pbGFyIHRvIG10ZG9vcHMgYnV0IG1vcmUgcG93 ZXJmdWwuIEl0IGJhc2VzIG9uCj4gcHN0b3JlL2JsaywgYWltcyB0byBzdG9yZSBwYW5pYyBhbmQg b29wcyBsb2cgdG8gYSBmbGFzaCBwYXJ0aXRpb24sCgogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgbG9ncz8KCj4gd2hlcmUgaXQgY2FuIGJlIHJlYWQgYmFjayBhcyBm aWxlcyBhZnRlciBtb3VudGluZyBwc3RvcmUgZmlsZXN5c3RlbS4KPiAKPiBUaGUgcHN0b3JlL2Js ayBhbmQgYmxrb29wcywgYSB3cmFwcGVyIGZvciBwc3RvcmUvYmxrLCBhcmUgZGVzaWduZWQgZm9y Cj4gYmxvY2sgZGV2aWNlIGF0IHRoZSB2ZXJ5IGJlZ2lubmluZywgYnV0IG5vdywgY29tcGF0aWJs ZSB0byBub3Qgb25seQo+IGJsb2NrIGRldmljZS4gQWZ0ZXIgdGhpcyBzZXJpZXMgb2YgcGF0Y2hl cywgcHN0b3JlL2JsayBjYW4gYWxzbyB3b3JrCj4gZm9yIE1URCBkZXZpY2UuIFRvIG1ha2UgaXQg d29yaywgJ2Jsa2Rldicgb24ga2NvbmZpZyBvciBtb2R1bGUKPiBwYXJhbWV0ZXIgb2YgYmxrb29w cyBzaG91bGQgYmUgc2V0IGFzIG10ZCBkZXZpY2UgbmFtZSBvciBtdGQgbnVtYmVyLgo+IFNlZSBt b3JlIGFib3V0IHBzdG9yZS9ibGsgYW5kIGJsa29vcHMgb246Cj4gICAgIERvY3VtZW50YXRpb24v YWRtaW4tZ3VpZGUvcHN0b3JlLWJsb2NrLnJzdAo+IAo+IFdoeSBkbyB3ZSBuZWVkIG10ZHBzdG9y ZT8KPiAxLiByZXBldGl0aXZlIGpvYnMgYmV0d2VlbiBwc3RvcmUgYW5kIG10ZG9vcHMKPiAgICBC b3RoIG9mIHBzdG9yZSBhbmQgbXRkb29wcyBkbyB0aGUgc2FtZSBqb2JzIHRoYXQgc3RvcmUgcGFu aWMvb29wcyBsb2cuCj4gICAgVGhleSBoYXZlIG11Y2ggc2ltaWxhciBsb2dpYyB0aGF0IHJlZ2lz dGVyIHRvIGttc2cgZHVtcGVyIGFuZCBzdG9yZQo+ICAgIGxvZyB0byBzZXZlcmFsIGNodW5rcyBv bmUgYnkgb25lLgo+IDIuIGRvIHdoYXQgYSBkcml2ZXIgc2hvdWxkIGRvCj4gICAgVG8gbWUsIGEg ZHJpdmVyIHNob3VsZCBwcm92aWRlIG1ldGhvZHMgaW5zdGVhZCBvZiBwb2xpY2llcy4gV2hhdCBN VEQKPiAgICBzaG91bGQgZG8gaXMgdG8gcHJvdmlkZSByZWFkL3dyaXRlL2VyYXNlIG9wZXJhdGlv bnMsIGdldGluZyByaWQgb2YgY29kZXMKPiAgICBhYm91dCBjaHVuayBtYW5hZ2VtZW50LCBrbXNn IGR1bXBlciBhbmQgY29uZmlndXJhdGlvbi4KPiAzLiBlbmhhbmNlZCBmZWF0dXJlCj4gICAgTm90 IG9ubHkgc3RvcmUgbG9nLCBidXQgYWxzbyBzaG93IGl0IGFzIGZpbGVzLgo+ICAgIE5vdCBvbmx5 IGxvZywgYnV0IGFsc28gdHJpZ2dlciB0aW1lIGFuZCB0cmlnZ2VyIGNvdW50Lgo+ICAgIE5vdCBv bmx5IHBhbmljL29vcHMgbG9nLCBidXQgYWxzbyBsb2cgcmVjb3JkZXIgZm9yIHBtc2csIGNvbnNv bGUgYW5kCj4gICAgZnRyYWNlIGluIHRoZSBmdXR1cmUuCj4gCj4gU2lnbmVkLW9mZi1ieTogV2Vp WGlvbmcgTGlhbyA8bGlhb3dlaXhpb25nQGFsbHdpbm5lcnRlY2guY29tPgo+IFJlcG9ydGVkLWJ5 OiBrYnVpbGQgdGVzdCByb2JvdCA8bGtwQGludGVsLmNvbT4KCkkgZG9uJ3QgdGhpbmcgdGhlIHRl c3Qgcm9ib3QgaGFzIGEgbWVhbmluZyBoZXJlLgoKPiAtLS0KPiAgZHJpdmVycy9tdGQvS2NvbmZp ZyAgICAgfCAgMTAgKwo+ICBkcml2ZXJzL210ZC9NYWtlZmlsZSAgICB8ICAgMSArCj4gIGRyaXZl cnMvbXRkL210ZHBzdG9yZS5jIHwgNTMwICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKwo+ICAzIGZpbGVzIGNoYW5nZWQsIDU0MSBpbnNlcnRpb25zKCspCj4g IGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL210ZC9tdGRwc3RvcmUuYwo+IAo+IGRpZmYgLS1n aXQgYS9kcml2ZXJzL210ZC9LY29uZmlnIGIvZHJpdmVycy9tdGQvS2NvbmZpZwo+IGluZGV4IDQy ZDQwMWVhNjBlZS4uYTZlNTk0OTVhNzM4IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvbXRkL0tjb25m aWcKPiArKysgYi9kcml2ZXJzL210ZC9LY29uZmlnCj4gQEAgLTE3MCw2ICsxNzAsMTYgQEAgY29u ZmlnIE1URF9PT1BTCj4gIAkgIGJ1ZmZlciBpbiBhIGZsYXNoIHBhcnRpdGlvbiB3aGVyZSBpdCBj YW4gYmUgcmVhZCBiYWNrIGF0IHNvbWUKPiAgCSAgbGF0ZXIgcG9pbnQuCj4gIAo+ICtjb25maWcg TVREX1BTVE9SRQo+ICsJdHJpc3RhdGUgIkxvZyBwYW5pYy9vb3BzIHRvIGFuIE1URCBidWZmZXIg YmFzZSBvbiBwc3RvcmUiCgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIGJhc2VkCgo+ICsJZGVwZW5kcyBvbiBQU1RPUkVfQkxLT09QUwo+ICsJaGVscAo+ ICsJICBUaGlzIGVuYWJsZXMgcGFuaWMgYW5kIG9vcHMgbWVzc2FnZXMgdG8gYmUgbG9nZ2VkIHRv IGEgY2lyY3VsYXIKPiArCSAgYnVmZmVyIGluIGEgZmxhc2ggcGFydGl0aW9uIHdoZXJlIGl0IGNh biBiZSByZWFkIGJhY2sgYXMgZmlsZXMgYWZ0ZXIKPiArCSAgbW91bnRpbmcgcHN0b3JlIGZpbGVz eXN0ZW0uCj4gKwo+ICsJICBJZiB1bnN1cmUsIHNheSBOLgo+ICsKPiAgY29uZmlnIE1URF9TV0FQ Cj4gIAl0cmlzdGF0ZSAiU3dhcCBvbiBNVEQgZGV2aWNlIHN1cHBvcnQiCj4gIAlkZXBlbmRzIG9u IE1URCAmJiBTV0FQCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbXRkL01ha2VmaWxlIGIvZHJpdmVy cy9tdGQvTWFrZWZpbGUKPiBpbmRleCA1NmNjNjBjY2M0NzcuLjU5M2QwNTkzYTAzOCAxMDA2NDQK PiAtLS0gYS9kcml2ZXJzL210ZC9NYWtlZmlsZQo+ICsrKyBiL2RyaXZlcnMvbXRkL01ha2VmaWxl Cj4gQEAgLTIwLDYgKzIwLDcgQEAgb2JqLSQoQ09ORklHX1JGRF9GVEwpCQkrPSByZmRfZnRsLm8K PiAgb2JqLSQoQ09ORklHX1NTRkRDKQkJKz0gc3NmZGMubwo+ICBvYmotJChDT05GSUdfU01fRlRM KQkJKz0gc21fZnRsLm8KPiAgb2JqLSQoQ09ORklHX01URF9PT1BTKQkJKz0gbXRkb29wcy5vCj4g K29iai0kKENPTkZJR19NVERfUFNUT1JFKQkrPSBtdGRwc3RvcmUubwo+ICBvYmotJChDT05GSUdf TVREX1NXQVApCQkrPSBtdGRzd2FwLm8KPiAgCj4gIG5mdGwtb2JqcwkJOj0gbmZ0bGNvcmUubyBu ZnRsbW91bnQubwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL210ZC9tdGRwc3RvcmUuYyBiL2RyaXZl cnMvbXRkL210ZHBzdG9yZS5jCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAw MDAwMDAuLmFiNGFjZDNhOTAxMQo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL210ZC9t dGRwc3RvcmUuYwo+IEBAIC0wLDAgKzEsNTMwIEBACj4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlm aWVyOiBHUEwtMi4wCj4gKy8qCj4gKyAqIE1URCBPb3BzL1BhbmljIGxvZ2VyIGZvciBwc3RvcmUv YmxrCj4gKyAqCj4gKyAqIENvcHlyaWdodCAoQykgMjAxOSBXZWlYaW9uZyBMaWFvIDxsaWFvd2Vp eGlvbmdAZ2FsbHdpbm5lcnRlY2guY29tPgo+ICsgKgo+ICsgKiBUaGlzIHByb2dyYW0gaXMgZnJl ZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQo+ICsgKiBp dCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNp b24gMiBhcwo+ICsgKiBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4K PiArICoKPiArICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQg aXQgd2lsbCBiZSB1c2VmdWwsCj4gKyAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91 dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCj4gKyAqIE1FUkNIQU5UQUJJTElUWSBvciBG SVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZQo+ICsgKiBHTlUgR2VuZXJh bCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgoKVGhlIGxpY2Vuc2UgdGV4dCBpcyBu b3QgbmVlZGVkIHNpbmNlIHlvdSBhZGRlZCBTUERYIHRhZy4KCj4gKyAqCj4gKyAqLwo+ICsjZGVm aW5lIHByX2ZtdChmbXQpICJtdGRvb3BzLXBzdG9yZTogIiBmbXQKPiArCj4gKyNpbmNsdWRlIDxs aW51eC9rZXJuZWwuaD4KPiArI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8 bGludXgvYmxrb29wcy5oPgo+ICsjaW5jbHVkZSA8bGludXgvbXRkL210ZC5oPgo+ICsjaW5jbHVk ZSA8bGludXgvYml0b3BzLmg+Cj4gKwo+ICsvKiBNYXhpbXVtIE1URCBwYXJ0aXRpb24gc2l6ZSAq Lwo+ICsjZGVmaW5lIE1URFBTVE9SRV9NQVhfTVREX1NJWkUgKDggKiAxMDI0ICogMTAyNCkKCiAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTWl84TQoKPiArCj4gK3N0YXRpYyBzdHJ1 Y3QgbXRkcHN0b3JlX2NvbnRleHQgewo+ICsJaW50IGluZGV4Owo+ICsJc3RydWN0IGJsa29vcHNf aW5mbyBib19pbmZvOwo+ICsJc3RydWN0IGJsa29vcHNfZGV2aWNlIGJvX2RldjsKPiArCXN0cnVj dCBtdGRfaW5mbyAqbXRkOwo+ICsJdW5zaWduZWQgbG9uZyAqcm1tYXA7CQkvKiByZW1vdmVkIGJp dCBtYXAgKi8KPiArCXVuc2lnbmVkIGxvbmcgKnVzZWRtYXA7CQkvKiB1c2VkIGJpdCBtYXAgKi8K PiArCS8qCj4gKwkgKiB1c2VkIGZvciBwYW5pYyB3cml0ZQo+ICsJICogQXMgdGhlcmUgYXJlIG5v IGJsb2NrX2lzYmFkIGZvciBwYW5pYyBjYXNlLCB3ZSBzaG91bGQga2VlcCB0aGlzCj4gKwkgKiBz dGF0dXMgYmVmb3JlIHBhbmljIHRvIGVuc3VyZSBwYW5pY193cml0ZSBub3QgZmFpbGVkLgo+ICsJ ICovCj4gKwl1bnNpZ25lZCBsb25nICpiYWRtYXA7CQkvKiBiYWQgYmxvY2sgYml0IG1hcCAqLwo+ ICt9IG9vcHNfY3h0Owo+ICsKPiArc3RhdGljIGludCBtdGRwc3RvcmVfYmxvY2tfaXNiYWQoc3Ry dWN0IG10ZHBzdG9yZV9jb250ZXh0ICpjeHQsIGxvZmZfdCBvZmYpCj4gK3sKPiArCWludCByZXQ7 Cj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IGN4dC0+bXRkOwo+ICsJdTY0IGJsa251bSA9IGRp dl91NjQob2ZmLCBtdGQtPmVyYXNlc2l6ZSk7Cj4gKwo+ICsJaWYgKHRlc3RfYml0KGJsa251bSwg Y3h0LT5iYWRtYXApKQo+ICsJCXJldHVybiB0cnVlOwo+ICsJcmV0ID0gbXRkX2Jsb2NrX2lzYmFk KG10ZCwgb2ZmKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJcHJfZXJyKCJtdGRfYmxvY2tfaXNi YWQgZmFpbGVkLCBhYm9ydGluZ1xuIik7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0gZWxzZSBpZiAo cmV0ID4gMCkgewo+ICsJCXNldF9iaXQoYmxrbnVtLCBjeHQtPmJhZG1hcCk7Cj4gKwkJcmV0dXJu IHRydWU7Cj4gKwl9Cj4gKwlyZXR1cm4gZmFsc2U7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUg aW50IG10ZHBzdG9yZV9wYW5pY19ibG9ja19pc2JhZChzdHJ1Y3QgbXRkcHN0b3JlX2NvbnRleHQg KmN4dCwKPiArCQlsb2ZmX3Qgb2ZmKQo+ICt7Cj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IGN4 dC0+bXRkOwo+ICsJdTY0IGJsa251bSA9IGRpdl91NjQob2ZmLCBtdGQtPmVyYXNlc2l6ZSk7Cj4g Kwo+ICsJcmV0dXJuIHRlc3RfYml0KGJsa251bSwgY3h0LT5iYWRtYXApOwo+ICt9Cj4gKwo+ICtz dGF0aWMgaW5saW5lIHZvaWQgbXRkcHN0b3JlX21hcmtfdXNlZChzdHJ1Y3QgbXRkcHN0b3JlX2Nv bnRleHQgKmN4dCwKPiArCQlsb2ZmX3Qgb2ZmKQo+ICt7Cj4gKwl1NjQgem9uZW51bSA9IGRpdl91 NjQob2ZmLCBjeHQtPmJvX2luZm8uZG1lc2dfc2l6ZSk7Cj4gKwo+ICsJcHJfZGVidWcoIm1hcmsg em9uZSAlbGx1IHVzZWRcbiIsIHpvbmVudW0pOwo+ICsJc2V0X2JpdCh6b25lbnVtLCBjeHQtPnVz ZWRtYXApOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIHZvaWQgbXRkcHN0b3JlX21hcmtfdW51 c2VkKHN0cnVjdCBtdGRwc3RvcmVfY29udGV4dCAqY3h0LAo+ICsJCWxvZmZfdCBvZmYpCj4gK3sK PiArCXU2NCB6b25lbnVtID0gZGl2X3U2NChvZmYsIGN4dC0+Ym9faW5mby5kbWVzZ19zaXplKTsK PiArCj4gKwlwcl9kZWJ1ZygibWFyayB6b25lICVsbHUgdW51c2VkXG4iLCB6b25lbnVtKTsKPiAr CWNsZWFyX2JpdCh6b25lbnVtLCBjeHQtPnVzZWRtYXApOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5s aW5lIHZvaWQgbXRkcHN0b3JlX2Jsb2NrX21hcmtfdW51c2VkKHN0cnVjdCBtdGRwc3RvcmVfY29u dGV4dCAqY3h0LAo+ICsJCWxvZmZfdCBvZmYpCj4gK3sKPiArCXU2NCB6b25lbnVtID0gZGl2X3U2 NChvZmYsIGN4dC0+Ym9faW5mby5kbWVzZ19zaXplKTsKPiArCXUzMiB6b25lY250ID0gY3h0LT5t dGQtPmVyYXNlc2l6ZSAvIGN4dC0+Ym9faW5mby5kbWVzZ19zaXplOwo+ICsKPiArCXdoaWxlICh6 b25lY250ID4gMCkgewo+ICsJCXByX2RlYnVnKCJtYXJrIHpvbmUgJWxsdSB1bnVzZWRcbiIsIHpv bmVudW0pOwo+ICsJCWNsZWFyX2JpdCh6b25lbnVtLCBjeHQtPnVzZWRtYXApOwo+ICsJCXpvbmVu dW0rKzsKPiArCQl6b25lY250LS07Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgaW50 IG10ZHBzdG9yZV9pc191c2VkKHN0cnVjdCBtdGRwc3RvcmVfY29udGV4dCAqY3h0LCBsb2ZmX3Qg b2ZmKQo+ICt7Cj4gKwl1NjQgem9uZW51bSA9IGRpdl91NjQob2ZmLCBjeHQtPmJvX2luZm8uZG1l c2dfc2l6ZSk7Cj4gKwl1NjQgYmxrbnVtID0gZGl2X3U2NChvZmYsIGN4dC0+bXRkLT5lcmFzZXNp emUpOwo+ICsKPiArCWlmICh0ZXN0X2JpdChibGtudW0sIGN4dC0+YmFkbWFwKSkKPiArCQlyZXR1 cm4gdHJ1ZTsKPiArCXJldHVybiB0ZXN0X2JpdCh6b25lbnVtLCBjeHQtPnVzZWRtYXApOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IG10ZHBzdG9yZV9ibG9ja19pc191c2VkKHN0cnVjdCBtdGRwc3Rv cmVfY29udGV4dCAqY3h0LAo+ICsJCWxvZmZfdCBvZmYpCj4gK3sKPiArCXU2NCB6b25lbnVtID0g ZGl2X3U2NChvZmYsIGN4dC0+Ym9faW5mby5kbWVzZ19zaXplKTsKPiArCXUzMiB6b25lY250ID0g Y3h0LT5tdGQtPmVyYXNlc2l6ZSAvIGN4dC0+Ym9faW5mby5kbWVzZ19zaXplOwo+ICsKPiArCXdo aWxlICh6b25lY250ID4gMCkgewo+ICsJCWlmICh0ZXN0X2JpdCh6b25lbnVtLCBjeHQtPnVzZWRt YXApKQo+ICsJCQlyZXR1cm4gdHJ1ZTsKPiArCQl6b25lbnVtKys7Cj4gKwkJem9uZWNudC0tOwo+ ICsJfQo+ICsJcmV0dXJuIGZhbHNlOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IG10ZHBzdG9yZV9p c19lbXB0eShzdHJ1Y3QgbXRkcHN0b3JlX2NvbnRleHQgKmN4dCwgY2hhciAqYnVmLAo+ICsJCXNp emVfdCBzaXplKQo+ICt7Cj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IGN4dC0+bXRkOwo+ICsJ c2l6ZV90IHN6Owo+ICsJaW50IGk7Cj4gKwo+ICsJc3ogPSBtaW5fdCh1aW50MzJfdCwgc2l6ZSwg bXRkLT53cml0ZXNpemUgLyA0KTsKPiArCWZvciAoaSA9IDA7IGkgPCBzejsgaSsrKSB7Cj4gKwkJ aWYgKGJ1ZltpXSAhPSAoY2hhcikweEZGKQo+ICsJCQlyZXR1cm4gZmFsc2U7Cj4gKwl9Cj4gKwly ZXR1cm4gdHJ1ZTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgbXRkcHN0b3JlX21hcmtfcmVtb3Zl ZChzdHJ1Y3QgbXRkcHN0b3JlX2NvbnRleHQgKmN4dCwgbG9mZl90IG9mZikKPiArewo+ICsJdTY0 IHpvbmVudW0gPSBkaXZfdTY0KG9mZiwgY3h0LT5ib19pbmZvLmRtZXNnX3NpemUpOwo+ICsKPiAr CXByX2RlYnVnKCJtYXJrIHpvbmUgJWxsdSByZW1vdmVkXG4iLCB6b25lbnVtKTsKPiArCXNldF9i aXQoem9uZW51bSwgY3h0LT5ybW1hcCk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIG10ZHBzdG9y ZV9ibG9ja19jbGVhcl9yZW1vdmVkKHN0cnVjdCBtdGRwc3RvcmVfY29udGV4dCAqY3h0LAo+ICsJ CWxvZmZfdCBvZmYpCj4gK3sKPiArCXU2NCB6b25lbnVtID0gZGl2X3U2NChvZmYsIGN4dC0+Ym9f aW5mby5kbWVzZ19zaXplKTsKPiArCXUzMiB6b25lY250ID0gY3h0LT5tdGQtPmVyYXNlc2l6ZSAv IGN4dC0+Ym9faW5mby5kbWVzZ19zaXplOwo+ICsKPiArCXdoaWxlICh6b25lY250ID4gMCkgewo+ ICsJCWNsZWFyX2JpdCh6b25lbnVtLCBjeHQtPnJtbWFwKTsKPiArCQl6b25lbnVtKys7Cj4gKwkJ em9uZWNudC0tOwo+ICsJfQo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IG10ZHBzdG9yZV9ibG9ja19p c19yZW1vdmVkKHN0cnVjdCBtdGRwc3RvcmVfY29udGV4dCAqY3h0LAo+ICsJCWxvZmZfdCBvZmYp Cj4gK3sKPiArCXU2NCB6b25lbnVtID0gZGl2X3U2NChvZmYsIGN4dC0+Ym9faW5mby5kbWVzZ19z aXplKTsKPiArCXUzMiB6b25lY250ID0gY3h0LT5tdGQtPmVyYXNlc2l6ZSAvIGN4dC0+Ym9faW5m by5kbWVzZ19zaXplOwo+ICsKPiArCXdoaWxlICh6b25lY250ID4gMCkgewo+ICsJCWlmICh0ZXN0 X2JpdCh6b25lbnVtLCBjeHQtPnJtbWFwKSkKPiArCQkJcmV0dXJuIHRydWU7Cj4gKwkJem9uZW51 bSsrOwo+ICsJCXpvbmVjbnQtLTsKPiArCX0KPiArCXJldHVybiBmYWxzZTsKPiArfQo+ICsKPiAr c3RhdGljIGludCBtdGRwc3RvcmVfZXJhc2VfZG8oc3RydWN0IG10ZHBzdG9yZV9jb250ZXh0ICpj eHQsIGxvZmZfdCBvZmYpCj4gK3sKPiArCXN0cnVjdCBlcmFzZV9pbmZvIGVyYXNlOwo+ICsJaW50 IHJldDsKPiArCj4gKwlwcl9kZWJ1ZygidHJ5IHRvIGVyYXNlIG9mZiAweCVsbHhcbiIsIG9mZik7 Cj4gKwllcmFzZS5sZW4gPSBjeHQtPm10ZC0+ZXJhc2VzaXplOwo+ICsJZXJhc2UuYWRkciA9IG9m ZjsKPiArCXJldCA9IG10ZF9lcmFzZShjeHQtPm10ZCwgJmVyYXNlKTsKPiArCWlmICghcmV0KQo+ ICsJCW10ZHBzdG9yZV9ibG9ja19jbGVhcl9yZW1vdmVkKGN4dCwgb2ZmKTsKPiArCWVsc2UKPiAr CQlwcl9lcnIoImVyYXNlIG9mIHJlZ2lvbiBbMHglbGx4LCAweCVsbHhdIG9uIFwiJXNcIiBmYWls ZWRcbiIsCj4gKwkJICAgICAgICh1bnNpZ25lZCBsb25nIGxvbmcpZXJhc2UuYWRkciwKPiArCQkg ICAgICAgKHVuc2lnbmVkIGxvbmcgbG9uZyllcmFzZS5sZW4sIGN4dC0+Ym9faW5mby5kZXZpY2Up Owo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArLyoKPiArICogY2FsbGVkIHdoaWxlIHJlbW92 aW5nIGZpbGUKPiArICoKPiArICogQXZvaWRpbmcgb3ZlciBlcmFzaW5nLCBkbyBlcmFzZSBvbmx5 IHdoZW4gYWxsIHpvbmVzIGFyZSByZW1vdmVkIG9yIHVudXNlZC4KPiArICogRW5zdXJlIHRvIHJl bW92ZSB3aGVuIHVucmVnaXN0ZXIgYnkgcmVhZGluZywgZXJhc2luZyBhbmQgd3J0aWluZyBiYWNr Lgo+ICsgKi8KPiArc3RhdGljIHNzaXplX3QgbXRkcHN0b3JlX2VyYXNlKHNpemVfdCBzaXplLCBs b2ZmX3Qgb2ZmKQo+ICt7Cj4gKwlzdHJ1Y3QgbXRkcHN0b3JlX2NvbnRleHQgKmN4dCA9ICZvb3Bz X2N4dDsKPiArCj4gKwlpZiAobXRkcHN0b3JlX2Jsb2NrX2lzYmFkKGN4dCwgb2ZmKSkKPiArCQly ZXR1cm4gLUVJTzsKPiArCj4gKwltdGRwc3RvcmVfbWFya191bnVzZWQoY3h0LCBvZmYpOwo+ICsK PiArCWlmIChsaWtlbHkobXRkcHN0b3JlX2Jsb2NrX2lzX3VzZWQoY3h0LCBvZmYpKSkgewo+ICsJ CW10ZHBzdG9yZV9tYXJrX3JlbW92ZWQoY3h0LCBvZmYpOwo+ICsJCXJldHVybiAwOwo+ICsJfQo+ ICsKPiArCS8qIGFsbCB6b25lcyBhcmUgdW51c2VkLCBlcmFzZSBpdCAqLwo+ICsJb2ZmID0gQUxJ R05fRE9XTihvZmYsIGN4dC0+bXRkLT5lcmFzZXNpemUpOwo+ICsJcmV0dXJuIG10ZHBzdG9yZV9l cmFzZV9kbyhjeHQsIG9mZik7Cj4gK30KPiArCj4gKy8qCj4gKyAqIFdoYXQgaXMgc2VjdXJldHkg Zm9yIG10ZHBzdG9yZT8KCiAgICAgICAgICAgICAgc2VjdXJpdHkKCj4gKyAqIEFzIHRoZXJlIGlz IG5vIGVyYXNlIGZvciBwYW5pYyBjYXNlLCB3ZSBzaG91bGQgZW5zdXJlIGF0IGxlYXN0IG9uZSB6 b25lCj4gKyAqIGlzIHdyaXRhYmxlLiBPdGhlcndpc2UsIHBhbmljIHdyaXRlIHdpbGwgYmUgZmFp bGVkLgoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lsbCBmYWls LgoKPiArICogSWYgem9uZSBpcyB1c2VkLCB3cml0ZSBvcGVyYXRpb24gd2lsbCByZXR1cm4gLUVO RVhULCB3aGljaCBtZWFucyB0aGF0Cj4gKyAqIHBzdG9yZS9ibGsgd2lsbCB0cnkgb25lIGJ5IG9u ZSB1bnRpbCBnZXQgYSBlbXB0eSB6b25lLiBTbywgaXQncyBubyBuZWVkCgogICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXQgZ2V0cyBhbiBlbXB0eSB6b25lLiBTbyBp dAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMgbm90IG5lZWRl ZCB0byAuLi4KICAgIAo+ICsgKiB0byBlbnN1cmUgbmV4dCB6b25lIGlzIGVtcHR5LCBidXQgYXQg bGVhc3Qgb25lLgoKICAgICAgICAgICAgICAgdGhlCgo+ICsgKi8KPiArc3RhdGljIGludCBtdGRw c3RvcmVfc2VjdXJpdHkoc3RydWN0IG10ZHBzdG9yZV9jb250ZXh0ICpjeHQsIGxvZmZfdCBvZmYp Cj4gK3sKPiArCWludCByZXQgPSAwLCBpOwo+ICsJdTMyIHpvbmVudW0gPSAodTMyKWRpdl91NjQo b2ZmLCBjeHQtPmJvX2luZm8uZG1lc2dfc2l6ZSk7Cj4gKwl1MzIgem9uZWNudCA9ICh1MzIpZGl2 X3U2NChjeHQtPm10ZC0+c2l6ZSwgY3h0LT5ib19pbmZvLmRtZXNnX3NpemUpOwo+ICsJdTMyIGJs a2NudCA9ICh1MzIpZGl2X3U2NChjeHQtPm10ZC0+c2l6ZSwgY3h0LT5tdGQtPmVyYXNlc2l6ZSk7 Cj4gKwl1MzIgZXJhc2VzaXplID0gY3h0LT5tdGQtPmVyYXNlc2l6ZTsKPiArCj4gKwlmb3IgKGkg PSAwOyBpIDwgem9uZWNudDsgaSsrKSB7Cj4gKwkJdTMyIG51bSA9ICh6b25lbnVtICsgaSkgJSB6 b25lY250Owo+ICsKPiArCQkvKiBmb3VuZCBlbXB0eSB6b25lICovCj4gKwkJaWYgKCF0ZXN0X2Jp dChudW0sIGN4dC0+dXNlZG1hcCkpCj4gKwkJCXJldHVybiAwOwo+ICsJfQo+ICsKPiArCS8qIElm IHRoZXJlIGlzIG5vIGFueSBlbXB0eSB6b25lLCB3ZSBoYXZlIG5vIHdheSBidXQgdG8gZG8gZXJh c2UgKi8KPiArCW9mZiA9IEFMSUdOX0RPV04ob2ZmLCBlcmFzZXNpemUpOwo+ICsJd2hpbGUgKGJs a2NudC0tKSB7Cj4gKwkJZGl2NjRfdTY0X3JlbShvZmYgKyBlcmFzZXNpemUsIGN4dC0+bXRkLT5z aXplLCAodTY0ICopJm9mZik7Cj4gKwo+ICsJCWlmIChtdGRwc3RvcmVfYmxvY2tfaXNiYWQoY3h0 LCBvZmYpKQo+ICsJCQljb250aW51ZTsKPiArCj4gKwkJcmV0ID0gbXRkcHN0b3JlX2VyYXNlX2Rv KGN4dCwgb2ZmKTsKPiArCQlpZiAoIXJldCkgewo+ICsJCQltdGRwc3RvcmVfYmxvY2tfbWFya191 bnVzZWQoY3h0LCBvZmYpOwo+ICsJCQlicmVhazsKPiArCQl9Cj4gKwl9Cj4gKwo+ICsJaWYgKHJl dCkKPiArCQlwcl9lcnIoImFsbCBibG9ja3MgYmFkIVxuIik7Cj4gKwlwcl9kZWJ1ZygiZW5kIHNl Y3VyaXR5XG4iKTsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBzc2l6ZV90IG10 ZHBzdG9yZV93cml0ZShjb25zdCBjaGFyICpidWYsIHNpemVfdCBzaXplLCBsb2ZmX3Qgb2ZmKQo+ ICt7Cj4gKwlzdHJ1Y3QgbXRkcHN0b3JlX2NvbnRleHQgKmN4dCA9ICZvb3BzX2N4dDsKPiArCXNp emVfdCByZXRsZW47Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWlmIChtdGRwc3RvcmVfYmxvY2tfaXNi YWQoY3h0LCBvZmYpKQo+ICsJCXJldHVybiAtRU5FWFQ7Cj4gKwo+ICsJLyogem9uZSBpcyB1c2Vk LCBwbGVhc2UgdHJ5IG5leHQgb25lICovCj4gKwlpZiAobXRkcHN0b3JlX2lzX3VzZWQoY3h0LCBv ZmYpKQo+ICsJCXJldHVybiAtRU5FWFQ7Cj4gKwo+ICsJcHJfZGVidWcoInRyeSB0byB3cml0ZSBv ZmYgMHglbGx4IHNpemUgJXp1XG4iLCBvZmYsIHNpemUpOwo+ICsJcmV0ID0gbXRkX3dyaXRlKGN4 dC0+bXRkLCBvZmYsIHNpemUsICZyZXRsZW4sICh1X2NoYXIgKilidWYpOwo+ICsJaWYgKHJldCA8 IDAgfHwgcmV0bGVuICE9IHNpemUpIHsKPiArCQlwcl9lcnIoIndyaXRlIGZhaWx1cmUgYXQgJWxs ZCAoJXp1IG9mICV6dSB3cml0dGVuKSwgZXJyICVkXG4iLAo+ICsJCQkJb2ZmLCByZXRsZW4sIHNp emUsIHJldCk7Cj4gKwkJcmV0dXJuIC1FSU87Cj4gKwl9Cj4gKwltdGRwc3RvcmVfbWFya191c2Vk KGN4dCwgb2ZmKTsKPiArCj4gKwltdGRwc3RvcmVfc2VjdXJpdHkoY3h0LCBvZmYpOwo+ICsJcmV0 dXJuIHJldGxlbjsKPiArfQo+ICsKPiArLyoKPiArICogQWxsIHpvbmVzIHdpbGwgYmUgcmVhZCBh cyBwc3RvcmUvYmxrIHdpbGwgcmVhZCB6b25lIG9uZSBieSBvbmUgd2hlbiBkbwo+ICsgKiByZWNv dmVyLgo+ICsgKi8KPiArc3RhdGljIHNzaXplX3QgbXRkcHN0b3JlX3JlYWQoY2hhciAqYnVmLCBz aXplX3Qgc2l6ZSwgbG9mZl90IG9mZikKPiArewo+ICsJc3RydWN0IG10ZHBzdG9yZV9jb250ZXh0 ICpjeHQgPSAmb29wc19jeHQ7Cj4gKwlzaXplX3QgcmV0bGVuOwo+ICsJaW50IHJldDsKPiArCj4g KwlpZiAobXRkcHN0b3JlX2Jsb2NrX2lzYmFkKGN4dCwgb2ZmKSkKPiArCQlyZXR1cm4gLUVORVhU Owo+ICsKPiArCXByX2RlYnVnKCJ0cnkgdG8gcmVhZCBvZmYgMHglbGx4IHNpemUgJXp1XG4iLCBv ZmYsIHNpemUpOwo+ICsJcmV0ID0gbXRkX3JlYWQoY3h0LT5tdGQsIG9mZiwgc2l6ZSwgJnJldGxl biwgKHVfY2hhciAqKWJ1Zik7Cj4gKwlpZiAoKHJldCA8IDAgJiYgIW10ZF9pc19iaXRmbGlwKHJl dCkpIHx8IHNpemUgIT0gcmV0bGVuKSAgewoKSUlSQyBzaXplICE9IHJldGxlbiBkb2VzIG5vdCBt ZWFuIGl0IGZhaWxlZCwgYnV0IHRoYXQgeW91IHNob3VsZApjb250aW51ZSByZWFkaW5nIGFmdGVy IHJldGxlbiBieXRlcywgbm8/CgpBbHNvLCBtdGRfaXNfYml0ZmxpcCgpIGRvZXMgbm90IG1lYW4g dGhhdCB5b3UgYXJlIHJlYWRpbmcgYSBmYWxzZQpidWZmZXIsIGJ1dCB0aGF0IHRoZSBkYXRhIGhh cyBiZWVuIGNvcnJlY3RlZCBhcyBpdCBjb250YWluZWQgYml0ZmxpcHMuCm10ZF9pc19lY2NlcnIo KSBob3dldmVyLCB3b3VsZCBiZSBtZWFuaW5nZnVsLgoKPiArCQlwcl9lcnIoInJlYWQgZmFpbHVy ZSBhdCAlbGxkICglenUgb2YgJXp1IHJlYWQpLCBlcnIgJWRcbiIsCj4gKwkJCQlvZmYsIHJldGxl biwgc2l6ZSwgcmV0KTsKPiArCQlyZXR1cm4gLUVJTzsKPiArCX0KPiArCj4gKwlpZiAobXRkcHN0 b3JlX2lzX2VtcHR5KGN4dCwgYnVmLCBzaXplKSkKPiArCQltdGRwc3RvcmVfbWFya191bnVzZWQo Y3h0LCBvZmYpOwo+ICsJZWxzZQo+ICsJCW10ZHBzdG9yZV9tYXJrX3VzZWQoY3h0LCBvZmYpOwo+ ICsKPiArCW10ZHBzdG9yZV9zZWN1cml0eShjeHQsIG9mZik7Cj4gKwlyZXR1cm4gcmV0bGVuOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgc3NpemVfdCBtdGRwc3RvcmVfcGFuaWNfd3JpdGUoY29uc3QgY2hh ciAqYnVmLCBzaXplX3Qgc2l6ZSwgbG9mZl90IG9mZikKPiArewo+ICsJc3RydWN0IG10ZHBzdG9y ZV9jb250ZXh0ICpjeHQgPSAmb29wc19jeHQ7Cj4gKwlzaXplX3QgcmV0bGVuOwo+ICsJaW50IHJl dDsKPiArCj4gKwlpZiAobXRkcHN0b3JlX3BhbmljX2Jsb2NrX2lzYmFkKGN4dCwgb2ZmKSkKPiAr CQlyZXR1cm4gLUVORVhUOwo+ICsKPiArCS8qIHpvbmUgaXMgdXNlZCwgcGxlYXNlIHRyeSBuZXh0 IG9uZSAqLwo+ICsJaWYgKG10ZHBzdG9yZV9pc191c2VkKGN4dCwgb2ZmKSkKPiArCQlyZXR1cm4g LUVORVhUOwo+ICsKPiArCXJldCA9IG10ZF9wYW5pY193cml0ZShjeHQtPm10ZCwgb2ZmLCBzaXpl LCAmcmV0bGVuLCAodV9jaGFyICopYnVmKTsKPiArCWlmIChyZXQgPCAwIHx8IHNpemUgIT0gcmV0 bGVuKSB7Cj4gKwkJcHJfZXJyKCJwYW5pYyB3cml0ZSBmYWlsdXJlIGF0ICVsbGQgKCV6dSBvZiAl enUgcmVhZCksIGVyciAlZFxuIiwKPiArCQkJCW9mZiwgcmV0bGVuLCBzaXplLCByZXQpOwo+ICsJ CXJldHVybiAtRUlPOwo+ICsJfQo+ICsJbXRkcHN0b3JlX21hcmtfdXNlZChjeHQsIG9mZik7Cj4g Kwo+ICsJcmV0dXJuIHJldGxlbjsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgbXRkcHN0b3JlX25v dGlmeV9hZGQoc3RydWN0IG10ZF9pbmZvICptdGQpCj4gK3sKPiArCWludCByZXQ7Cj4gKwlzdHJ1 Y3QgbXRkcHN0b3JlX2NvbnRleHQgKmN4dCA9ICZvb3BzX2N4dDsKPiArCXN0cnVjdCBibGtvb3Bz X2luZm8gKmluZm8gPSAmY3h0LT5ib19pbmZvOwo+ICsJdW5zaWduZWQgbG9uZyBsb25nY250Owo+ ICsKPiArCWlmICghc3RyY21wKG10ZC0+bmFtZSwgaW5mby0+ZGV2aWNlKSkKPiArCQljeHQtPmlu ZGV4ID0gbXRkLT5pbmRleDsKPiArCj4gKwlpZiAobXRkLT5pbmRleCAhPSBjeHQtPmluZGV4IHx8 IGN4dC0+aW5kZXggPCAwKQo+ICsJCXJldHVybjsKPiArCj4gKwlwcl9kZWJ1ZygiZm91bmQgbWF0 Y2hpbmcgTVREIGRldmljZSAlc1xuIiwgbXRkLT5uYW1lKTsKPiArCj4gKwlpZiAobXRkLT5zaXpl IDwgaW5mby0+ZG1lc2dfc2l6ZSAqIDIpIHsKPiArCQlwcl9lcnIoIk1URCBwYXJ0aXRpb24gJWQg bm90IGJpZyBlbm91Z2hcbiIsIG10ZC0+aW5kZXgpOwo+ICsJCXJldHVybjsKPiArCX0KPiArCWlm IChtdGQtPmVyYXNlc2l6ZSA8IGluZm8tPmRtZXNnX3NpemUpIHsKPiArCQlwcl9lcnIoImVyYXNl YmxvY2sgc2l6ZSBvZiBNVEQgcGFydGl0aW9uICVkIHRvbyBzbWFsbFxuIiwKPiArCQkJCW10ZC0+ aW5kZXgpOwoKV2hhdCBpcyB0aGUgdXN1YWwgc2l6ZSBvZiBkbWVzZz8gQ291bGQgdGhpcyBjaGVj ayBiZSB0b28gbGltaXRpbmc/Cgo+ICsJCXJldHVybjsKPiArCX0KPiArCWlmICh1bmxpa2VseShp bmZvLT5kbWVzZ19zaXplICUgbXRkLT53cml0ZXNpemUpKSB7Cj4gKwkJcHJfZXJyKCJyZWNvcmQg c2l6ZSAlbHUgS0IgbXVzdCBhbGlnbiB0byB3cml0ZSBzaXplICVkIEtCXG4iLAo+ICsJCQkJaW5m by0+ZG1lc2dfc2l6ZSAvIDEwMjQsCj4gKwkJCQltdGQtPndyaXRlc2l6ZSAvIDEwMjQpOwoKVGhp cyBjb25kaXRpb24gaXMgd2VpcmQsIHdoeSB3b3VsZCB5b3UgY2hlY2sgdGhpcz8KCj4gKwkJcmV0 dXJuOwo+ICsJfQo+ICsJaWYgKHVubGlrZWx5KG10ZC0+c2l6ZSA+IE1URFBTVE9SRV9NQVhfTVRE X1NJWkUpKSB7Cj4gKwkJcHJfZXJyKCJtdGQlZCBpcyB0b28gbGFyZ2UgKGxpbWl0IGlzICVkIE1p QilcbiIsCj4gKwkJCQltdGQtPmluZGV4LAo+ICsJCQkJTVREUFNUT1JFX01BWF9NVERfU0laRSAv IDEwMjQgLyAxMDI0KTsKClNhbWUgcXVlc3Rpb24/IEkgY291bGQgdW5kZXJzdGFuZCB0aGF0IGl0 IGlzIGVhc2llciB0byBtYW5hZ2UgYmxvY2tzCmtub3dpbmcgdGhlaXIgbWF4aW11bSBudW1iZXIg dGhvdWdoLgoKPiArCQlyZXR1cm47Cj4gKwl9Cj4gKwo+ICsJbG9uZ2NudCA9IEJJVFNfVE9fTE9O R1MoZGl2X3U2NChtdGQtPnNpemUsIGluZm8tPmRtZXNnX3NpemUpKTsKPiArCWN4dC0+cm1tYXAg PSBrY2FsbG9jKGxvbmdjbnQsIHNpemVvZihsb25nKSwgR0ZQX0tFUk5FTCk7Cj4gKwljeHQtPnVz ZWRtYXAgPSBrY2FsbG9jKGxvbmdjbnQsIHNpemVvZihsb25nKSwgR0ZQX0tFUk5FTCk7Cj4gKwo+ ICsJbG9uZ2NudCA9IEJJVFNfVE9fTE9OR1MoZGl2X3U2NChtdGQtPnNpemUsIG10ZC0+ZXJhc2Vz aXplKSk7Cj4gKwljeHQtPmJhZG1hcCA9IGtjYWxsb2MobG9uZ2NudCwgc2l6ZW9mKGxvbmcpLCBH RlBfS0VSTkVMKTsKPiArCj4gKwljeHQtPmJvX2Rldi50b3RhbF9zaXplID0gbXRkLT5zaXplOwo+ ICsJLyoganVzdCBzdXBwb3J0IGRtZXNnIHJpZ2h0IG5vdyAqLwo+ICsJY3h0LT5ib19kZXYuZmxh Z3MgPSBCTEtPT1BTX0RFVl9TVVBQT1JUX0RNRVNHOwo+ICsJY3h0LT5ib19kZXYucmVhZCA9IG10 ZHBzdG9yZV9yZWFkOwo+ICsJY3h0LT5ib19kZXYud3JpdGUgPSBtdGRwc3RvcmVfd3JpdGU7Cj4g KwljeHQtPmJvX2Rldi5lcmFzZSA9IG10ZHBzdG9yZV9lcmFzZTsKPiArCWN4dC0+Ym9fZGV2LnBh bmljX3dyaXRlID0gbXRkcHN0b3JlX3BhbmljX3dyaXRlOwo+ICsKPiArCXJldCA9IGJsa29vcHNf cmVnaXN0ZXJfZGV2aWNlKCZjeHQtPmJvX2Rldik7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJcHJfZXJy KCJtdGQlZCByZWdpc3RlciB0byBibGtvb3BzIGZhaWxlZFxuIiwgbXRkLT5pbmRleCk7Cj4gKwkJ cmV0dXJuOwo+ICsJfQo+ICsJY3h0LT5tdGQgPSBtdGQ7Cj4gKwlwcl9pbmZvKCJBdHRhY2hlZCB0 byBNVEQgZGV2aWNlICVkXG4iLCBtdGQtPmluZGV4KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBt dGRwc3RvcmVfZmx1c2hfcmVtb3ZlZF9kbyhzdHJ1Y3QgbXRkcHN0b3JlX2NvbnRleHQgKmN4dCwK PiArCQlsb2ZmX3Qgb2ZmLCBzaXplX3Qgc2l6ZSkKPiArewo+ICsJc3RydWN0IG10ZF9pbmZvICpt dGQgPSBjeHQtPm10ZDsKPiArCXVfY2hhciAqYnVmOwo+ICsJaW50IHJldDsKPiArCXNpemVfdCBy ZXRsZW47Cj4gKwlzdHJ1Y3QgZXJhc2VfaW5mbyBlcmFzZTsKPiArCj4gKwlidWYgPSBrbWFsbG9j KG10ZC0+ZXJhc2VzaXplLCBHRlBfS0VSTkVMKTsKPiArCWlmICghYnVmKQo+ICsJCXJldHVybiAt RU5PTUVNOwo+ICsKPiArCS8qIDFzdC4gcmVhZCB0byBjYWNoZSAqLwo+ICsJcmV0ID0gbXRkX3Jl YWQobXRkLCBvZmYsIG10ZC0+ZXJhc2VzaXplLCAmcmV0bGVuLCBidWYpOwo+ICsJaWYgKHJldCB8 fCByZXRsZW4gIT0gbXRkLT5lcmFzZXNpemUpCj4gKwkJZ290byBmcmVlOwo+ICsKPiArCS8qIDJu ZC4gZXJhc2UgYmxvY2sgKi8KPiArCWVyYXNlLmxlbiA9IG10ZC0+ZXJhc2VzaXplOwo+ICsJZXJh c2UuYWRkciA9IG9mZjsKPiArCXJldCA9IG10ZF9lcmFzZShtdGQsICZlcmFzZSk7Cj4gKwlpZiAo cmV0KQo+ICsJCWdvdG8gZnJlZTsKPiArCj4gKwkvKiAzcmQuIHdyaXRlIGJhY2sgKi8KPiArCXdo aWxlIChzaXplKSB7Cj4gKwkJdW5zaWduZWQgaW50IHpvbmVzaXplID0gY3h0LT5ib19pbmZvLmRt ZXNnX3NpemU7Cj4gKwo+ICsJCS8qIHJlbW92ZSBtdXN0IGNsZWFyIHVzZWQgYml0ICovCj4gKwkJ aWYgKG10ZHBzdG9yZV9pc191c2VkKGN4dCwgb2ZmKSkKPiArCQkJbXRkX3dyaXRlKG10ZCwgb2Zm LCB6b25lc2l6ZSwgJnJldGxlbiwgYnVmKTsKCkJlc2lkZXMgdGhlIGZhY3QgdGhhdCBzaG91bGQg ZGVmaW5pdGVseSBjaGVjayB0aGUgd3JpdGUgcmV0dXJuIGNvZGUsIEkKZG9uJ3QgdW5kZXJzdGFu ZCB3aGF0IHlvdSBkbyBpbiB0aGlzIGZ1bmN0aW9uLiBXaGF0IGRvZXMKZmx1c2hfcmVtb3ZlZF9k byBtZWFuPwoKPiArCj4gKwkJb2ZmICs9IHpvbmVzaXplOwo+ICsJCXNpemUgLT0gbWluX3QodW5z aWduZWQgaW50LCB6b25lc2l6ZSwgc2l6ZSk7Cj4gKwl9Cj4gKwo+ICtmcmVlOgo+ICsJa2ZyZWUo YnVmKTsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgbXRkcHN0b3JlX2Zs dXNoX3JlbW92ZWQoc3RydWN0IG10ZHBzdG9yZV9jb250ZXh0ICpjeHQpCj4gK3sKPiArCXN0cnVj dCBtdGRfaW5mbyAqbXRkID0gY3h0LT5tdGQ7Cj4gKwlpbnQgcmV0Owo+ICsJbG9mZl90IG9mZjsK PiArCXUzMiBibGtjbnQgPSAodTMyKWRpdl91NjQobXRkLT5zaXplLCBtdGQtPmVyYXNlc2l6ZSk7 Cj4gKwo+ICsJZm9yIChvZmYgPSAwOyBibGtjbnQgPiAwOyBibGtjbnQtLSwgb2ZmICs9IG10ZC0+ ZXJhc2VzaXplKSB7Cj4gKwkJcmV0ID0gbXRkcHN0b3JlX2Jsb2NrX2lzX3JlbW92ZWQoY3h0LCBv ZmYpOwo+ICsJCWlmICghcmV0KSB7Cj4gKwkJCW9mZiArPSBtdGQtPmVyYXNlc2l6ZTsKPiArCQkJ Y29udGludWU7Cj4gKwkJfQo+ICsKPiArCQlyZXQgPSBtdGRwc3RvcmVfZmx1c2hfcmVtb3ZlZF9k byhjeHQsIG9mZiwgbXRkLT5lcmFzZXNpemUpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJldHVybiBy ZXQ7Cj4gKwl9Cj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgbXRkcHN0b3Jl X25vdGlmeV9yZW1vdmUoc3RydWN0IG10ZF9pbmZvICptdGQpCj4gK3sKPiArCXN0cnVjdCBtdGRw c3RvcmVfY29udGV4dCAqY3h0ID0gJm9vcHNfY3h0Owo+ICsKPiArCWlmIChtdGQtPmluZGV4ICE9 IGN4dC0+aW5kZXggfHwgY3h0LT5pbmRleCA8IDApCj4gKwkJcmV0dXJuOwo+ICsKPiArCW10ZHBz dG9yZV9mbHVzaF9yZW1vdmVkKGN4dCk7Cj4gKwo+ICsJYmxrb29wc191bnJlZ2lzdGVyX2Rldmlj ZSgmY3h0LT5ib19kZXYpOwo+ICsJa2ZyZWUoY3h0LT5iYWRtYXApOwo+ICsJa2ZyZWUoY3h0LT51 c2VkbWFwKTsKPiArCWtmcmVlKGN4dC0+cm1tYXApOwo+ICsJY3h0LT5tdGQgPSBOVUxMOwo+ICsJ Y3h0LT5pbmRleCA9IC0xOwo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IG10ZF9ub3RpZmllciBt dGRwc3RvcmVfbm90aWZpZXIgPSB7Cj4gKwkuYWRkCT0gbXRkcHN0b3JlX25vdGlmeV9hZGQsCj4g KwkucmVtb3ZlCT0gbXRkcHN0b3JlX25vdGlmeV9yZW1vdmUsCj4gK307Cj4gKwo+ICtzdGF0aWMg aW50IF9faW5pdCBtdGRwc3RvcmVfaW5pdCh2b2lkKQo+ICt7Cj4gKwlpbnQgcmV0Owo+ICsJc3Ry dWN0IG10ZHBzdG9yZV9jb250ZXh0ICpjeHQgPSAmb29wc19jeHQ7Cj4gKwlzdHJ1Y3QgYmxrb29w c19pbmZvICppbmZvID0gJmN4dC0+Ym9faW5mbzsKPiArCj4gKwlyZXQgPSBibGtvb3BzX2luZm8o aW5mbyk7Cj4gKwlpZiAodW5saWtlbHkocmV0KSkKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCWlm IChzdHJsZW4oaW5mby0+ZGV2aWNlKSA9PSAwKSB7Cj4gKwkJcHJfZXJyKCJtdGQgZGV2aWNlIG11 c3QgYmUgc3VwcGxpZWRcbiIpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsJaWYgKCFp bmZvLT5kbWVzZ19zaXplKSB7Cj4gKwkJcHJfZXJyKCJubyByZWNvcmRlciBlbmFibGVkXG4iKTsK PiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwkvKiBTZXR1cCB0aGUgTVREIGRldmlj ZSB0byB1c2UgKi8KPiArCXJldCA9IGtzdHJ0b2ludCgoY2hhciAqKWluZm8tPmRldmljZSwgMCwg JmN4dC0+aW5kZXgpOwo+ICsJaWYgKHJldCkKPiArCQljeHQtPmluZGV4ID0gLTE7Cj4gKwo+ICsJ cmVnaXN0ZXJfbXRkX3VzZXIoJm10ZHBzdG9yZV9ub3RpZmllcik7Cj4gKwlyZXR1cm4gMDsKPiAr fQo+ICttb2R1bGVfaW5pdChtdGRwc3RvcmVfaW5pdCk7Cj4gKwo+ICtzdGF0aWMgdm9pZCBfX2V4 aXQgbXRkcHN0b3JlX2V4aXQodm9pZCkKPiArewo+ICsJdW5yZWdpc3Rlcl9tdGRfdXNlcigmbXRk cHN0b3JlX25vdGlmaWVyKTsKPiArfQo+ICttb2R1bGVfZXhpdChtdGRwc3RvcmVfZXhpdCk7Cj4g Kwo+ICtNT0RVTEVfTElDRU5TRSgiR1BMIik7Cj4gK01PRFVMRV9BVVRIT1IoIldlaVhpb25nIExp YW8gPGxpYW93ZWl4aW9uZ0BhbGx3aW5uZXJ0ZWNoLmNvbT4iKTsKPiArTU9EVUxFX0RFU0NSSVBU SU9OKCJNVEQgT29wcy9QYW5pYyBjb25zb2xlIGxvZ2dlci9kcml2ZXIiKTsKCgoKClRoYW5rcywK TWlxdcOobAoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fCkxpbnV4IE1URCBkaXNjdXNzaW9uIG1haWxpbmcgbGlzdApodHRwOi8vbGlzdHMuaW5m cmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LW10ZC8K