From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1aaqLJ-0000JK-MR for mharc-grub-devel@gnu.org; Tue, 01 Mar 2016 14:52:25 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39765) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aaqLC-0000HK-Qb for grub-devel@gnu.org; Tue, 01 Mar 2016 14:52:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aaqL7-0005yi-Mo for grub-devel@gnu.org; Tue, 01 Mar 2016 14:52:18 -0500 Received: from mail-lb0-x241.google.com ([2a00:1450:4010:c04::241]:35118) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aaqL7-0005yX-2G for grub-devel@gnu.org; Tue, 01 Mar 2016 14:52:13 -0500 Received: by mail-lb0-x241.google.com with SMTP id h2so7992836lbs.2 for ; Tue, 01 Mar 2016 11:52:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=subject:to:references:cc:from:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding; bh=8Pm+XyAxqh8tS54he3cyYoa1mA1Env1q0ctOU1TzPD4=; b=XAvqOuJPE+tchshYx31zOmedHkkNTIY3JHK0+9XzJnaS6XrDbZI/hbW3cocUc4G4Hh awohEoCukXbTMHOPn0epx5wvlb9WcyJr5EYh3rNYnc/jHl5p93IsFtWZn8pgU2Kyed/O cOyncxIKBWxrAGyPlycujP0uoYf7wxH5FMOZ2kFFmP0jhMgNUa3AQPSGO6ywqhaH1W6q atnrFvyVOe8a45Y/HN1zvXhXbxhk7b1ltnuJVNb9+AgekZwSEw8D/p3zjBjO16q9IVgE mg2XgMHrE7pCUaamdOW0kNW7RDcq4yyQhQt5HqMptNYxtX6ni0hK8jpmKT/AJ+mPq5LH khGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:to:references:cc:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=8Pm+XyAxqh8tS54he3cyYoa1mA1Env1q0ctOU1TzPD4=; b=W0YqzEH4ZTEKFVK/7cQd2xEQ5Vv0izdzUT/7/sFEKsKmiSCDMwPyV+Gu6c6n6SsCXO V0yL+KF4hqQH9ZhSBR5G3n+Y0QsK5fZuDp6d+JKZwD4D/Crbf9utey7BOvffO+8ENRC/ Xf2rIJLG1k8aQMVy3M0fYRppVJ6usxmcR+m/IW+V2ot/o8hGJ4Rtx+yHFWb9blUthDZw u33IXxBUwh2p62DiB6hHSjxOt6mD+8KxElWAzcKoOSCh3rtk9MkPqV9HI1yuSwNUh0/N ZsfTFbIUhGLiBd+x4tP284I7QhNx48rf/YOHq8jz+SOyoDLDDtY37+iNsB80YxijSjHC 6LoQ== X-Gm-Message-State: AD7BkJLjrI/V3bGHkRDsZ8yav8hVGpDpyfvzXXdUCIjrR+qfqsI0dirBFuUO1Mr0+kqcHg== X-Received: by 10.112.54.201 with SMTP id l9mr8680412lbp.105.1456861931865; Tue, 01 Mar 2016 11:52:11 -0800 (PST) Received: from [192.168.1.41] (ppp109-252-76-159.pppoe.spdop.ru. [109.252.76.159]) by smtp.gmail.com with ESMTPSA id f184sm5113565lfe.6.2016.03.01.11.52.10 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 01 Mar 2016 11:52:10 -0800 (PST) Subject: [2.02] Re: [f2fs-dev] [PATCH v7] F2FS support To: Jaegeuk Kim References: <1427185140-41120-1-git-send-email-jaegeuk@kernel.org> <20150403224908.GB25673@jaegeuk-mac02.mot.com> <20151119212824.GA11666@jaegeuk.local> <566E7DAA.4010202@gmail.com> <20151215003421.GD48918@jaegeuk.local> <20151215181439.GA60773@jaegeuk.local> <20160108194132.GA17464@jaegeuk.aosp> <20160222182525.GD10875@jaegeuk.gateway> From: Andrei Borzenkov Message-ID: <56D5F2E9.1070501@gmail.com> Date: Tue, 1 Mar 2016 22:52:09 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 In-Reply-To: <20160222182525.GD10875@jaegeuk.gateway> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:4010:c04::241 Cc: The development of GNU GRUB , linux-f2fs-devel@lists.sourceforge.net X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Mar 2016 19:52:23 -0000 ACK from my side. It is leaf code that does not affect anything so should not cause any regression. 22.02.2016 21:25, Jaegeuk Kim пишет: > Chang log from v6: > o remove redundant filesize check in ->read > o check consistency in ->open regarding to inline_data > > -- >8 -- > From 51c120612fdbc4bc315e9c4c6e91ca888c3f3596 Mon Sep 17 00:00:00 2001 > From: Jaegeuk Kim > Date: Tue, 17 Nov 2015 12:45:13 -0800 > Subject: [PATCH] F2FS support > > "F2FS (Flash-Friendly File System) is flash-friendly file system which was merged > into Linux kernel v3.8 in 2013. > > The motive for F2FS was to build a file system that from the start, takes into > account the characteristics of NAND flash memory-based storage devices (such as > solid-state disks, eMMC, and SD cards). > > F2FS was designed on a basis of a log-structured file system approach, which > remedies some known issues of the older log structured file systems, such as > the snowball effect of wandering trees and high cleaning overhead. In addition, > since a NAND-based storage device shows different characteristics according to > its internal geometry or flash memory management scheme (such as the Flash > Translation Layer or FTL), it supports various parameters not only for > configuring on-disk layout, but also for selecting allocation and cleaning > algorithm.", quote by https://en.wikipedia.org/wiki/F2FS. > > The source codes for F2FS are available from: > > http://git.kernel.org/cgit/linux/kernel/git/jaegeuk/f2fs.git > http://git.kernel.org/cgit/linux/kernel/git/jaegeuk/f2fs-tools.git > > Signed-off-by: Jaegeuk Kim > --- > Makefile.util.def | 7 + > docs/grub.texi | 5 +- > grub-core/Makefile.core.def | 5 + > grub-core/fs/f2fs.c | 1289 ++++++++++++++++++++++++++++++++++++++++++ > po/exclude.pot | 1 + > tests/f2fs_test.in | 19 + > tests/util/grub-fs-tester.in | 10 +- > 7 files changed, 1332 insertions(+), 4 deletions(-) > create mode 100644 grub-core/fs/f2fs.c > create mode 100644 tests/f2fs_test.in > > diff --git a/Makefile.util.def b/Makefile.util.def > index db7e8ec..84627bb 100644 > --- a/Makefile.util.def > +++ b/Makefile.util.def > @@ -99,6 +99,7 @@ library = { > common = grub-core/fs/ext2.c; > common = grub-core/fs/fat.c; > common = grub-core/fs/exfat.c; > + common = grub-core/fs/f2fs.c; > common = grub-core/fs/fshelp.c; > common = grub-core/fs/hfs.c; > common = grub-core/fs/hfsplus.c; > @@ -766,6 +767,12 @@ script = { > > script = { > testcase; > + name = f2fs_test; > + common = tests/f2fs_test.in; > +}; > + > +script = { > + testcase; > name = nilfs2_test; > common = tests/nilfs2_test.in; > }; > diff --git a/docs/grub.texi b/docs/grub.texi > index 1df3db2..e5a80f3 100644 > --- a/docs/grub.texi > +++ b/docs/grub.texi > @@ -360,7 +360,8 @@ blocklist notation. The currently supported filesystem types are @dfn{Amiga > Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS}, > @dfn{BtrFS} (including raid0, raid1, raid10, gzip and lzo), > @dfn{cpio} (little- and big-endian bin, odc and newc variants), > -@dfn{Linux ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{exFAT}, @dfn{HFS}, > +@dfn{Linux ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{exFAT}, > +@dfn{f2fs}, @dfn{HFS}, > @dfn{HFS+}, @dfn{ISO9660} (including Joliet, Rock-ridge and multi-chunk files), > @dfn{JFS}, @dfn{Minix fs} (versions 1, 2 and 3), @dfn{nilfs2}, > @dfn{NTFS} (including compression), @dfn{ReiserFS}, @dfn{ROMFS}, > @@ -5347,7 +5348,7 @@ NTFS, JFS, UDF, HFS+, exFAT, long filenames in FAT, Joliet part of > ISO9660 are treated as UTF-16 as per specification. AFS and BFS are read > as UTF-8, again according to specification. BtrFS, cpio, tar, squash4, minix, > minix2, minix3, ROMFS, ReiserFS, XFS, ext2, ext3, ext4, FAT (short names), > -RockRidge part of ISO9660, nilfs2, UFS1, UFS2 and ZFS are assumed > +f2fs, RockRidge part of ISO9660, nilfs2, UFS1, UFS2 and ZFS are assumed > to be UTF-8. This might be false on systems configured with legacy charset > but as long as the charset used is superset of ASCII you should be able to > access ASCII-named files. And it's recommended to configure your system to use > diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def > index d9fa0e3..b585ade 100644 > --- a/grub-core/Makefile.core.def > +++ b/grub-core/Makefile.core.def > @@ -1278,6 +1278,11 @@ module = { > }; > > module = { > + name = f2fs; > + common = fs/f2fs.c; > +}; > + > +module = { > name = fshelp; > common = fs/fshelp.c; > }; > diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c > new file mode 100644 > index 0000000..cb312b3 > --- /dev/null > +++ b/grub-core/fs/f2fs.c > @@ -0,0 +1,1289 @@ > +/* > + * f2fs.c - Flash-Friendly File System > + * > + * Written by Jaegeuk Kim > + * > + * Copyright (C) 2015 Free Software Foundation, Inc. > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB 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. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see . > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +GRUB_MOD_LICENSE ("GPLv3+"); > + > +/* F2FS Magic Number */ > +#define F2FS_SUPER_MAGIC 0xF2F52010 > +#define CHECKSUM_OFFSET 4092 /* must be aligned 4 bytes */ > +#define U32_CHECKSUM_OFFSET (CHECKSUM_OFFSET >> 2) > + > +/* byte-size offset */ > +#define F2FS_SUPER_OFFSET ((grub_disk_addr_t)1024) > +#define F2FS_SUPER_OFFSET0 (F2FS_SUPER_OFFSET >> GRUB_DISK_SECTOR_BITS) > +#define F2FS_SUPER_OFFSET1 ((F2FS_SUPER_OFFSET + F2FS_BLKSIZE) >> \ > + GRUB_DISK_SECTOR_BITS) > + > +/* 9 bits for 512 bytes */ > +#define F2FS_MIN_LOG_SECTOR_SIZE 9 > + > +/* support only 4KB block */ > +#define F2FS_BLK_BITS 12 > +#define F2FS_BLKSIZE (1 << F2FS_BLK_BITS) > +#define F2FS_BLK_SEC_BITS (F2FS_BLK_BITS - GRUB_DISK_SECTOR_BITS) > + > +#define VERSION_LEN 256 > +#define F2FS_MAX_EXTENSION 64 > + > +#define CP_COMPACT_SUM_FLAG 0x00000004 > +#define CP_UMOUNT_FLAG 0x00000001 > + > +#define MAX_ACTIVE_LOGS 16 > +#define MAX_ACTIVE_NODE_LOGS 8 > +#define MAX_ACTIVE_DATA_LOGS 8 > +#define NR_CURSEG_DATA_TYPE 3 > +#define NR_CURSEG_NODE_TYPE 3 > +#define NR_CURSEG_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE) > + > +#define ENTRIES_IN_SUM 512 > +#define SUMMARY_SIZE 7 > +#define SUM_FOOTER_SIZE 5 > +#define JENTRY_SIZE (sizeof(struct grub_f2fs_nat_jent)) > +#define SUM_ENTRIES_SIZE (SUMMARY_SIZE * ENTRIES_IN_SUM) > +#define SUM_JOURNAL_SIZE (F2FS_BLKSIZE - SUM_FOOTER_SIZE -\ > + SUM_ENTRIES_SIZE) > +#define NAT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) / JENTRY_SIZE) > +#define NAT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) % JENTRY_SIZE) > + > +#define NAT_ENTRY_SIZE (sizeof(struct grub_f2fs_nat_entry)) > +#define NAT_ENTRY_PER_BLOCK (F2FS_BLKSIZE / NAT_ENTRY_SIZE) > + > +#define F2FS_NAME_LEN 255 > +#define F2FS_SLOT_LEN 8 > +#define NR_DENTRY_IN_BLOCK 214 > +#define SIZE_OF_DIR_ENTRY 11 /* by byte */ > +#define BITS_PER_BYTE 8 > +#define SIZE_OF_DENTRY_BITMAP ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \ > + BITS_PER_BYTE) > +#define SIZE_OF_RESERVED (F2FS_BLKSIZE - ((SIZE_OF_DIR_ENTRY + \ > + F2FS_SLOT_LEN) * \ > + NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP)) > + > +#define F2FS_INLINE_XATTR_ADDRS 50 /* 200 bytes for inline xattrs */ > +#define DEF_ADDRS_PER_INODE 923 /* Address Pointers in an Inode */ > + > +#define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */ > +#define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */ > +#define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1) > +#define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2) > +#define NODE_IND1_BLOCK (DEF_ADDRS_PER_INODE + 3) > +#define NODE_IND2_BLOCK (DEF_ADDRS_PER_INODE + 4) > +#define NODE_DIND_BLOCK (DEF_ADDRS_PER_INODE + 5) > + > +#define MAX_INLINE_DATA (4 * (DEF_ADDRS_PER_INODE - \ > + F2FS_INLINE_XATTR_ADDRS - 1)) > +#define NR_INLINE_DENTRY (MAX_INLINE_DATA * BITS_PER_BYTE / \ > + ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \ > + BITS_PER_BYTE + 1)) > +#define INLINE_DENTRY_BITMAP_SIZE ((NR_INLINE_DENTRY + \ > + BITS_PER_BYTE - 1) / BITS_PER_BYTE) > +#define INLINE_RESERVED_SIZE (MAX_INLINE_DATA - \ > + ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \ > + NR_INLINE_DENTRY + INLINE_DENTRY_BITMAP_SIZE)) > +#define CURSEG_HOT_DATA 0 > + > +#define CKPT_FLAG_SET(ckpt, f) \ > + (ckpt)->ckpt_flags & grub_cpu_to_le32_compile_time (f) > + > +#define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */ > +#define F2FS_INLINE_DATA 0x02 /* file inline data flag */ > +#define F2FS_INLINE_DENTRY 0x04 /* file inline dentry flag */ > +#define F2FS_DATA_EXIST 0x08 /* file inline data exist flag */ > +#define F2FS_INLINE_DOTS 0x10 /* file having implicit dot dentries */ > + > +enum FILE_TYPE > +{ > + F2FS_FT_UNKNOWN, > + F2FS_FT_REG_FILE = 1, > + F2FS_FT_DIR = 2, > + F2FS_FT_SYMLINK = 7, > +}; > + > +#define MAX_VOLUME_NAME 512 > + > +struct grub_f2fs_superblock > +{ > + grub_uint32_t magic; > + grub_uint16_t dummy1[2]; > + grub_uint32_t log_sectorsize; > + grub_uint32_t log_sectors_per_block; > + grub_uint32_t log_blocksize; > + grub_uint32_t log_blocks_per_seg; > + grub_uint32_t segs_per_sec; > + grub_uint32_t secs_per_zone; > + grub_uint32_t checksum_offset; > + grub_uint8_t dummy2[40]; > + grub_uint32_t cp_blkaddr; > + grub_uint32_t sit_blkaddr; > + grub_uint32_t nat_blkaddr; > + grub_uint32_t ssa_blkaddr; > + grub_uint32_t main_blkaddr; > + grub_uint32_t root_ino; > + grub_uint32_t node_ino; > + grub_uint32_t meta_ino; > + grub_uint8_t uuid[16]; > + grub_uint16_t volume_name[MAX_VOLUME_NAME]; > + grub_uint32_t extension_count; > + grub_uint8_t extension_list[F2FS_MAX_EXTENSION][8]; > + grub_uint32_t cp_payload; > + grub_uint8_t version[VERSION_LEN]; > + grub_uint8_t init_version[VERSION_LEN]; > +} GRUB_PACKED; > + > +struct grub_f2fs_checkpoint > +{ > + grub_uint64_t checkpoint_ver; > + grub_uint64_t user_block_count; > + grub_uint64_t valid_block_count; > + grub_uint32_t rsvd_segment_count; > + grub_uint32_t overprov_segment_count; > + grub_uint32_t free_segment_count; > + grub_uint32_t cur_node_segno[MAX_ACTIVE_NODE_LOGS]; > + grub_uint16_t cur_node_blkoff[MAX_ACTIVE_NODE_LOGS]; > + grub_uint32_t cur_data_segno[MAX_ACTIVE_DATA_LOGS]; > + grub_uint16_t cur_data_blkoff[MAX_ACTIVE_DATA_LOGS]; > + grub_uint32_t ckpt_flags; > + grub_uint32_t cp_pack_total_block_count; > + grub_uint32_t cp_pack_start_sum; > + grub_uint32_t valid_node_count; > + grub_uint32_t valid_inode_count; > + grub_uint32_t next_free_nid; > + grub_uint32_t sit_ver_bitmap_bytesize; > + grub_uint32_t nat_ver_bitmap_bytesize; > + grub_uint32_t checksum_offset; > + grub_uint64_t elapsed_time; > + grub_uint8_t alloc_type[MAX_ACTIVE_LOGS]; > + grub_uint8_t sit_nat_version_bitmap[3900]; > + grub_uint32_t checksum; > +} GRUB_PACKED; > + > +struct grub_f2fs_nat_entry { > + grub_uint8_t version; > + grub_uint32_t ino; > + grub_uint32_t block_addr; > +} GRUB_PACKED; > + > +struct grub_f2fs_nat_jent > +{ > + grub_uint32_t nid; > + struct grub_f2fs_nat_entry ne; > +} GRUB_PACKED; > + > +struct grub_f2fs_nat_journal { > + grub_uint16_t n_nats; > + struct grub_f2fs_nat_jent entries[NAT_JOURNAL_ENTRIES]; > + grub_uint8_t reserved[NAT_JOURNAL_RESERVED]; > +} GRUB_PACKED; > + > +struct grub_f2fs_nat_block { > + struct grub_f2fs_nat_entry ne[NAT_ENTRY_PER_BLOCK]; > +} GRUB_PACKED; > + > +struct grub_f2fs_dir_entry > +{ > + grub_uint32_t hash_code; > + grub_uint32_t ino; > + grub_uint16_t name_len; > + grub_uint8_t file_type; > +} GRUB_PACKED; > + > +struct grub_f2fs_inline_dentry > +{ > + grub_uint8_t dentry_bitmap[INLINE_DENTRY_BITMAP_SIZE]; > + grub_uint8_t reserved[INLINE_RESERVED_SIZE]; > + struct grub_f2fs_dir_entry dentry[NR_INLINE_DENTRY]; > + grub_uint8_t filename[NR_INLINE_DENTRY][F2FS_SLOT_LEN]; > +} GRUB_PACKED; > + > +struct grub_f2fs_dentry_block { > + grub_uint8_t dentry_bitmap[SIZE_OF_DENTRY_BITMAP]; > + grub_uint8_t reserved[SIZE_OF_RESERVED]; > + struct grub_f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK]; > + grub_uint8_t filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN]; > +} GRUB_PACKED; > + > +struct grub_f2fs_inode > +{ > + grub_uint16_t i_mode; > + grub_uint8_t i_advise; > + grub_uint8_t i_inline; > + grub_uint32_t i_uid; > + grub_uint32_t i_gid; > + grub_uint32_t i_links; > + grub_uint64_t i_size; > + grub_uint64_t i_blocks; > + grub_uint64_t i_atime; > + grub_uint64_t i_ctime; > + grub_uint64_t i_mtime; > + grub_uint32_t i_atime_nsec; > + grub_uint32_t i_ctime_nsec; > + grub_uint32_t i_mtime_nsec; > + grub_uint32_t i_generation; > + grub_uint32_t i_current_depth; > + grub_uint32_t i_xattr_nid; > + grub_uint32_t i_flags; > + grub_uint32_t i_pino; > + grub_uint32_t i_namelen; > + grub_uint8_t i_name[F2FS_NAME_LEN]; > + grub_uint8_t i_dir_level; > + grub_uint8_t i_ext[12]; > + grub_uint32_t i_addr[DEF_ADDRS_PER_INODE]; > + grub_uint32_t i_nid[5]; > +} GRUB_PACKED; > + > +struct grub_direct_node { > + grub_uint32_t addr[ADDRS_PER_BLOCK]; > +} GRUB_PACKED; > + > +struct grub_indirect_node { > + grub_uint32_t nid[NIDS_PER_BLOCK]; > +} GRUB_PACKED; > + > +struct grub_f2fs_node > +{ > + union > + { > + struct grub_f2fs_inode i; > + struct grub_direct_node dn; > + struct grub_indirect_node in; > + char buf[F2FS_BLKSIZE - 40]; /* Should occupy F2FS_BLKSIZE totally */ > + }; > + grub_uint8_t dummy[40]; > +} GRUB_PACKED; > + > +struct grub_fshelp_node > +{ > + struct grub_f2fs_data *data; > + struct grub_f2fs_node inode; > + grub_uint32_t ino; > + int inode_read; > +}; > + > +struct grub_f2fs_data > +{ > + struct grub_f2fs_superblock sblock; > + struct grub_f2fs_checkpoint ckpt; > + > + grub_uint32_t root_ino; > + grub_uint32_t blocks_per_seg; > + grub_uint32_t cp_blkaddr; > + grub_uint32_t nat_blkaddr; > + > + struct grub_f2fs_nat_journal nat_j; > + char *nat_bitmap; > + > + grub_disk_t disk; > + struct grub_f2fs_node *inode; > + struct grub_fshelp_node diropen; > +}; > + > +struct grub_f2fs_dir_iter_ctx > +{ > + struct grub_f2fs_data *data; > + grub_fshelp_iterate_dir_hook_t hook; > + void *hook_data; > + grub_uint8_t *bitmap; > + grub_uint8_t (*filename)[F2FS_SLOT_LEN]; > + struct grub_f2fs_dir_entry *dentry; > + int max; > +}; > + > +struct grub_f2fs_dir_ctx > +{ > + grub_fs_dir_hook_t hook; > + void *hook_data; > + struct grub_f2fs_data *data; > +}; > + > +static grub_dl_t my_mod; > + > +static inline int > +grub_f2fs_test_bit_le (int nr, const grub_uint8_t *addr) > +{ > + return addr[nr >> 3] & (1 << (nr & 7)); > +} > + > +static inline char * > +__inline_addr (struct grub_f2fs_inode *inode) > +{ > + return (char *)&inode->i_addr[1]; > +} > + > +static inline grub_uint64_t > +grub_f2fs_file_size (struct grub_f2fs_inode *inode) > +{ > + return grub_le_to_cpu64 (inode->i_size); > +} > + > +static inline grub_uint32_t > +__start_cp_addr (struct grub_f2fs_data *data) > +{ > + struct grub_f2fs_checkpoint *ckpt = &data->ckpt; > + grub_uint32_t start_addr = data->cp_blkaddr; > + > + if (!(ckpt->checkpoint_ver & grub_cpu_to_le64_compile_time(1))) > + return start_addr + data->blocks_per_seg; > + return start_addr; > +} > + > +static inline grub_uint32_t > +__start_sum_block (struct grub_f2fs_data *data) > +{ > + struct grub_f2fs_checkpoint *ckpt = &data->ckpt; > + > + return __start_cp_addr (data) + grub_le_to_cpu32 (ckpt->cp_pack_start_sum); > +} > + > +static inline grub_uint32_t > +__sum_blk_addr (struct grub_f2fs_data *data, int base, int type) > +{ > + struct grub_f2fs_checkpoint *ckpt = &data->ckpt; > + > + return __start_cp_addr (data) + > + grub_le_to_cpu32 (ckpt->cp_pack_total_block_count) > + - (base + 1) + type; > +} > + > +static inline void * > +__nat_bitmap_ptr (struct grub_f2fs_data *data) > +{ > + struct grub_f2fs_checkpoint *ckpt = &data->ckpt; > + grub_uint32_t offset; > + > + if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0) > + return ckpt->sit_nat_version_bitmap; > + > + offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize); > + return ckpt->sit_nat_version_bitmap + offset; > +} > + > +static inline grub_uint32_t > +__get_node_id (struct grub_f2fs_node *rn, int off, int inode_block) > +{ > + if (inode_block) > + return grub_le_to_cpu32 (rn->i.i_nid[off - NODE_DIR1_BLOCK]); > + return grub_le_to_cpu32 (rn->in.nid[off]); > +} > + > +static inline grub_err_t > +grub_f2fs_block_read (struct grub_f2fs_data *data, grub_uint32_t blkaddr, void *buf) > +{ > + return grub_disk_read (data->disk, > + ((grub_disk_addr_t)blkaddr) << F2FS_BLK_SEC_BITS, > + 0, F2FS_BLKSIZE, buf); > +} > + > +/* > + * CRC32 > +*/ > +#define CRCPOLY_LE 0xedb88320 > + > +static inline grub_uint32_t > +grub_f2fs_cal_crc32 (const void *buf, const grub_uint32_t len) > +{ > + grub_uint32_t crc = F2FS_SUPER_MAGIC; > + unsigned char *p = (unsigned char *)buf; > + grub_uint32_t tmp = len; > + int i; > + > + while (tmp--) > + { > + crc ^= *p++; > + for (i = 0; i < 8; i++) > + crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); > + } > + return crc; > +} > + > +static inline int > +grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, const grub_uint32_t len) > +{ > + grub_uint32_t cal_crc = 0; > + > + cal_crc = grub_f2fs_cal_crc32 (buf, len); > + > + return (cal_crc == blk_crc) ? 1 : 0; > +} > + > +static inline int > +grub_f2fs_test_bit (grub_uint32_t nr, const char *p) > +{ > + int mask; > + > + p += (nr >> 3); > + mask = 1 << (7 - (nr & 0x07)); > + return mask & *p; > +} > + > +static int > +grub_f2fs_sanity_check_sb (struct grub_f2fs_superblock *sb) > +{ > + grub_uint32_t log_sectorsize, log_sectors_per_block; > + > + if (sb->magic != grub_cpu_to_le32_compile_time (F2FS_SUPER_MAGIC)) > + return -1; > + > + if (sb->log_blocksize != grub_cpu_to_le32_compile_time (F2FS_BLK_BITS)) > + return -1; > + > + log_sectorsize = grub_le_to_cpu32 (sb->log_sectorsize); > + log_sectors_per_block = grub_le_to_cpu32 (sb->log_sectors_per_block); > + > + if (log_sectorsize > F2FS_BLK_BITS) > + return -1; > + > + if (log_sectorsize < F2FS_MIN_LOG_SECTOR_SIZE) > + return -1; > + > + if (log_sectors_per_block + log_sectorsize != F2FS_BLK_BITS) > + return -1; > + > + return 0; > +} > + > +static int > +grub_f2fs_read_sb (struct grub_f2fs_data *data, grub_disk_addr_t offset) > +{ > + grub_disk_t disk = data->disk; > + grub_err_t err; > + > + /* Read first super block. */ > + err = grub_disk_read (disk, offset, 0, sizeof (data->sblock), &data->sblock); > + if (err) > + return -1; > + > + return grub_f2fs_sanity_check_sb (&data->sblock); > +} > + > +static void * > +validate_checkpoint (struct grub_f2fs_data *data, grub_uint32_t cp_addr, > + grub_uint64_t *version) > +{ > + grub_uint32_t *cp_page_1, *cp_page_2; > + struct grub_f2fs_checkpoint *cp_block; > + grub_uint64_t cur_version = 0, pre_version = 0; > + grub_uint32_t crc = 0; > + grub_uint32_t crc_offset; > + grub_err_t err; > + > + /* Read the 1st cp block in this CP pack */ > + cp_page_1 = grub_malloc (F2FS_BLKSIZE); > + if (!cp_page_1) > + return NULL; > + > + err = grub_f2fs_block_read (data, cp_addr, cp_page_1); > + if (err) > + goto invalid_cp1; > + > + cp_block = (struct grub_f2fs_checkpoint *)cp_page_1; > + crc_offset = grub_le_to_cpu32 (cp_block->checksum_offset); > + if (crc_offset != CHECKSUM_OFFSET) > + goto invalid_cp1; > + > + crc = grub_le_to_cpu32 (*(cp_page_1 + U32_CHECKSUM_OFFSET)); > + if (!grub_f2fs_crc_valid (crc, cp_block, crc_offset)) > + goto invalid_cp1; > + > + pre_version = grub_le_to_cpu64 (cp_block->checkpoint_ver); > + > + /* Read the 2nd cp block in this CP pack */ > + cp_page_2 = grub_malloc (F2FS_BLKSIZE); > + if (!cp_page_2) > + goto invalid_cp1; > + > + cp_addr += grub_le_to_cpu32 (cp_block->cp_pack_total_block_count) - 1; > + > + err = grub_f2fs_block_read (data, cp_addr, cp_page_2); > + if (err) > + goto invalid_cp2; > + > + cp_block = (struct grub_f2fs_checkpoint *)cp_page_2; > + crc_offset = grub_le_to_cpu32 (cp_block->checksum_offset); > + if (crc_offset != CHECKSUM_OFFSET) > + goto invalid_cp2; > + > + crc = grub_le_to_cpu32 (*(cp_page_2 + U32_CHECKSUM_OFFSET)); > + if (!grub_f2fs_crc_valid (crc, cp_block, crc_offset)) > + goto invalid_cp2; > + > + cur_version = grub_le_to_cpu64 (cp_block->checkpoint_ver); > + if (cur_version == pre_version) > + { > + *version = cur_version; > + grub_free (cp_page_2); > + return cp_page_1; > + } > + > +invalid_cp2: > + grub_free (cp_page_2); > +invalid_cp1: > + grub_free (cp_page_1); > + return NULL; > +} > + > +static grub_err_t > +grub_f2fs_read_cp (struct grub_f2fs_data *data) > +{ > + void *cp1, *cp2, *cur_page; > + grub_uint64_t cp1_version = 0, cp2_version = 0; > + grub_uint64_t cp_start_blk_no; > + > + /* > + * Finding out valid cp block involves read both > + * sets (cp pack1 and cp pack 2) > + */ > + cp_start_blk_no = data->cp_blkaddr; > + cp1 = validate_checkpoint (data, cp_start_blk_no, &cp1_version); > + if (!cp1 && grub_errno) > + return grub_errno; > + > + /* The second checkpoint pack should start at the next segment */ > + cp_start_blk_no += data->blocks_per_seg; > + cp2 = validate_checkpoint (data, cp_start_blk_no, &cp2_version); > + if (!cp2 && grub_errno) > + { > + grub_free (cp1); > + return grub_errno; > + } > + > + if (cp1 && cp2) > + cur_page = (cp2_version > cp1_version) ? cp2 : cp1; > + else if (cp1) > + cur_page = cp1; > + else if (cp2) > + cur_page = cp2; > + else > + return grub_error (GRUB_ERR_BAD_FS, "no checkpoints"); > + > + grub_memcpy (&data->ckpt, cur_page, F2FS_BLKSIZE); > + > + grub_free (cp1); > + grub_free (cp2); > + return 0; > +} > + > +static grub_err_t > +get_nat_journal (struct grub_f2fs_data *data) > +{ > + grub_uint32_t block; > + char *buf; > + grub_err_t err; > + > + buf = grub_malloc (F2FS_BLKSIZE); > + if (!buf) > + return grub_errno; > + > + if (CKPT_FLAG_SET(&data->ckpt, CP_COMPACT_SUM_FLAG)) > + block = __start_sum_block (data); > + else if (CKPT_FLAG_SET (&data->ckpt, CP_UMOUNT_FLAG)) > + block = __sum_blk_addr (data, NR_CURSEG_TYPE, CURSEG_HOT_DATA); > + else > + block = __sum_blk_addr (data, NR_CURSEG_DATA_TYPE, CURSEG_HOT_DATA); > + > + err = grub_f2fs_block_read (data, block, buf); > + if (err) > + goto fail; > + > + if (CKPT_FLAG_SET (&data->ckpt, CP_COMPACT_SUM_FLAG)) > + grub_memcpy (&data->nat_j, buf, SUM_JOURNAL_SIZE); > + else > + grub_memcpy (&data->nat_j, buf + SUM_ENTRIES_SIZE, SUM_JOURNAL_SIZE); > + > +fail: > + grub_free (buf); > + return err; > +} > + > +static grub_uint32_t > +get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid) > +{ > + grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats); > + grub_uint32_t blkaddr = 0; > + grub_uint16_t i; > + > + for (i = 0; i < n; i++) > + { > + if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid) > + { > + blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr); > + break; > + } > + } > + return blkaddr; > +} > + > +static grub_uint32_t > +get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) > +{ > + struct grub_f2fs_nat_block *nat_block; > + grub_uint32_t seg_off, block_off, entry_off, block_addr; > + grub_uint32_t blkaddr; > + grub_err_t err; > + > + blkaddr = get_blkaddr_from_nat_journal (data, nid); > + if (blkaddr) > + return blkaddr; > + > + nat_block = grub_malloc (F2FS_BLKSIZE); > + if (!nat_block) > + return 0; > + > + block_off = nid / NAT_ENTRY_PER_BLOCK; > + entry_off = nid % NAT_ENTRY_PER_BLOCK; > + > + seg_off = block_off / data->blocks_per_seg; > + block_addr = data->nat_blkaddr + > + ((seg_off * data->blocks_per_seg) << 1) + > + (block_off & (data->blocks_per_seg - 1)); > + > + if (grub_f2fs_test_bit (block_off, data->nat_bitmap)) > + block_addr += data->blocks_per_seg; > + > + err = grub_f2fs_block_read (data, block_addr, nat_block); > + if (err) > + { > + grub_free (nat_block); > + return 0; > + } > + > + blkaddr = grub_le_to_cpu32 (nat_block->ne[entry_off].block_addr); > + > + grub_free (nat_block); > + > + return blkaddr; > +} > + > +static int > +grub_get_node_path (struct grub_f2fs_inode *inode, grub_uint32_t block, > + grub_uint32_t offset[4], grub_uint32_t noffset[4]) > +{ > + grub_uint32_t direct_blks = ADDRS_PER_BLOCK; > + grub_uint32_t dptrs_per_blk = NIDS_PER_BLOCK; > + grub_uint32_t indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK; > + grub_uint32_t dindirect_blks = indirect_blks * NIDS_PER_BLOCK; > + grub_uint32_t direct_index = DEF_ADDRS_PER_INODE; > + int n = 0; > + int level = 0; > + > + if (inode->i_inline & F2FS_INLINE_XATTR) > + direct_index -= F2FS_INLINE_XATTR_ADDRS; > + > + noffset[0] = 0; > + > + if (block < direct_index) > + { > + offset[n] = block; > + goto got; > + } > + > + block -= direct_index; > + if (block < direct_blks) > + { > + offset[n++] = NODE_DIR1_BLOCK; > + noffset[n] = 1; > + offset[n] = block; > + level = 1; > + goto got; > + } > + > + block -= direct_blks; > + if (block < direct_blks) > + { > + offset[n++] = NODE_DIR2_BLOCK; > + noffset[n] = 2; > + offset[n] = block; > + level = 1; > + goto got; > + } > + > + block -= direct_blks; > + if (block < indirect_blks) > + { > + offset[n++] = NODE_IND1_BLOCK; > + noffset[n] = 3; > + offset[n++] = block / direct_blks; > + noffset[n] = 4 + offset[n - 1]; > + offset[n] = block % direct_blks; > + level = 2; > + goto got; > + } > + > + block -= indirect_blks; > + if (block < indirect_blks) > + { > + offset[n++] = NODE_IND2_BLOCK; > + noffset[n] = 4 + dptrs_per_blk; > + offset[n++] = block / direct_blks; > + noffset[n] = 5 + dptrs_per_blk + offset[n - 1]; > + offset[n] = block % direct_blks; > + level = 2; > + goto got; > + } > + > + block -= indirect_blks; > + if (block < dindirect_blks) > + { > + offset[n++] = NODE_DIND_BLOCK; > + noffset[n] = 5 + (dptrs_per_blk * 2); > + offset[n++] = block / indirect_blks; > + noffset[n] = 6 + (dptrs_per_blk * 2) + > + offset[n - 1] * (dptrs_per_blk + 1); > + offset[n++] = (block / direct_blks) % dptrs_per_blk; > + noffset[n] = 7 + (dptrs_per_blk * 2) + > + offset[n - 2] * (dptrs_per_blk + 1) + offset[n - 1]; > + offset[n] = block % direct_blks; > + level = 3; > + goto got; > + } > +got: > + return level; > +} > + > +static grub_err_t > +grub_f2fs_read_node (struct grub_f2fs_data *data, > + grub_uint32_t nid, struct grub_f2fs_node *np) > +{ > + grub_uint32_t blkaddr; > + > + blkaddr = get_node_blkaddr (data, nid); > + if (!blkaddr) > + return grub_errno; > + > + return grub_f2fs_block_read (data, blkaddr, np); > +} > + > +static struct grub_f2fs_data * > +grub_f2fs_mount (grub_disk_t disk) > +{ > + struct grub_f2fs_data *data; > + grub_err_t err; > + > + data = grub_malloc (sizeof (*data)); > + if (!data) > + return NULL; > + > + data->disk = disk; > + > + if (grub_f2fs_read_sb (data, F2FS_SUPER_OFFSET0)) > + { > + if (grub_f2fs_read_sb (data, F2FS_SUPER_OFFSET1)) > + { > + if (grub_errno == GRUB_ERR_NONE) > + grub_error (GRUB_ERR_BAD_FS, > + "not a F2FS filesystem (no superblock)"); > + goto fail; > + } > + } > + > + data->root_ino = grub_le_to_cpu32 (data->sblock.root_ino); > + data->cp_blkaddr = grub_le_to_cpu32 (data->sblock.cp_blkaddr); > + data->nat_blkaddr = grub_le_to_cpu32 (data->sblock.nat_blkaddr); > + data->blocks_per_seg = 1 << > + grub_le_to_cpu32 (data->sblock.log_blocks_per_seg); > + > + err = grub_f2fs_read_cp (data); > + if (err) > + goto fail; > + > + data->nat_bitmap = __nat_bitmap_ptr (data); > + > + err = get_nat_journal (data); > + if (err) > + goto fail; > + > + data->diropen.data = data; > + data->diropen.ino = data->root_ino; > + data->diropen.inode_read = 1; > + data->inode = &data->diropen.inode; > + > + err = grub_f2fs_read_node (data, data->root_ino, data->inode); > + if (err) > + goto fail; > + > + return data; > + > +fail: > + grub_free (data); > + return NULL; > +} > + > +/* guarantee inline_data was handled by caller */ > +static grub_disk_addr_t > +grub_f2fs_get_block (grub_fshelp_node_t node, grub_disk_addr_t block_ofs) > +{ > + struct grub_f2fs_data *data = node->data; > + struct grub_f2fs_inode *inode = &node->inode.i; > + grub_uint32_t offset[4], noffset[4], nids[4]; > + struct grub_f2fs_node *node_block; > + grub_uint32_t block_addr = -1; > + int level, i; > + > + level = grub_get_node_path (inode, block_ofs, offset, noffset); > + if (level == 0) > + return grub_le_to_cpu32 (inode->i_addr[offset[0]]); > + > + node_block = grub_malloc (F2FS_BLKSIZE); > + if (!node_block) > + return -1; > + > + nids[1] = __get_node_id (&node->inode, offset[0], 1); > + > + /* get indirect or direct nodes */ > + for (i = 1; i <= level; i++) > + { > + grub_f2fs_read_node (data, nids[i], node_block); > + if (grub_errno) > + goto fail; > + > + if (i < level) > + nids[i + 1] = __get_node_id (node_block, offset[i], 0); > + } > + > + block_addr = grub_le_to_cpu32 (node_block->dn.addr[offset[level]]); > +fail: > + grub_free (node_block); > + return block_addr; > +} > + > +static grub_ssize_t > +grub_f2fs_read_file (grub_fshelp_node_t node, > + grub_disk_read_hook_t read_hook, void *read_hook_data, > + grub_off_t pos, grub_size_t len, char *buf) > +{ > + struct grub_f2fs_inode *inode = &node->inode.i; > + grub_off_t filesize = grub_f2fs_file_size (inode); > + char *inline_addr = __inline_addr (inode); > + > + if (inode->i_inline & F2FS_INLINE_DATA) > + { > + if (filesize > MAX_INLINE_DATA) > + return -1; > + if (len > filesize - pos) > + len = filesize - pos; > + > + grub_memcpy (buf + pos, inline_addr + pos, len); > + return len; > + } > + > + return grub_fshelp_read_file (node->data->disk, node, > + read_hook, read_hook_data, > + pos, len, buf, grub_f2fs_get_block, > + filesize, > + F2FS_BLK_SEC_BITS, 0); > +} > + > +static char * > +grub_f2fs_read_symlink (grub_fshelp_node_t node) > +{ > + char *symlink; > + struct grub_fshelp_node *diro = node; > + grub_uint64_t filesize; > + > + if (!diro->inode_read) > + { > + grub_f2fs_read_node (diro->data, diro->ino, &diro->inode); > + if (grub_errno) > + return 0; > + } > + > + filesize = grub_f2fs_file_size(&diro->inode.i); > + > + symlink = grub_malloc (filesize + 1); > + if (!symlink) > + return 0; > + > + grub_f2fs_read_file (diro, 0, 0, 0, filesize, symlink); > + if (grub_errno) > + { > + grub_free (symlink); > + return 0; > + } > + > + symlink[filesize] = '\0'; > + return symlink; > +} > + > +static int > +grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx) > +{ > + struct grub_fshelp_node *fdiro; > + int i; > + > + for (i = 0; i < ctx->max;) > + { > + char *filename; > + enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; > + enum FILE_TYPE ftype; > + int name_len; > + int ret; > + > + if (grub_f2fs_test_bit_le (i, ctx->bitmap) == 0) > + { > + i++; > + continue; > + } > + > + ftype = ctx->dentry[i].file_type; > + name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len); > + filename = grub_malloc (name_len + 1); > + if (!filename) > + return 0; > + > + grub_memcpy (filename, ctx->filename[i], name_len); > + filename[name_len] = 0; > + > + fdiro = grub_malloc (sizeof (struct grub_fshelp_node)); > + if (!fdiro) > + { > + grub_free(filename); > + return 0; > + } > + > + if (ftype == F2FS_FT_DIR) > + type = GRUB_FSHELP_DIR; > + else if (ftype == F2FS_FT_SYMLINK) > + type = GRUB_FSHELP_SYMLINK; > + else if (ftype == F2FS_FT_REG_FILE) > + type = GRUB_FSHELP_REG; > + > + fdiro->data = ctx->data; > + fdiro->ino = grub_le_to_cpu32 (ctx->dentry[i].ino); > + fdiro->inode_read = 0; > + > + ret = ctx->hook (filename, type, fdiro, ctx->hook_data); > + grub_free(filename); > + if (ret) > + return 1; > + > + i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN; > + } > + return 0; > +} > + > +static int > +grub_f2fs_iterate_inline_dir (struct grub_f2fs_inode *dir, > + struct grub_f2fs_dir_iter_ctx *ctx) > +{ > + struct grub_f2fs_inline_dentry *de_blk; > + > + de_blk = (struct grub_f2fs_inline_dentry *) __inline_addr (dir); > + > + ctx->bitmap = de_blk->dentry_bitmap; > + ctx->dentry = de_blk->dentry; > + ctx->filename = de_blk->filename; > + ctx->max = NR_INLINE_DENTRY; > + > + return grub_f2fs_check_dentries (ctx); > +} > + > +static int > +grub_f2fs_iterate_dir (grub_fshelp_node_t dir, > + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) > +{ > + struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; > + struct grub_f2fs_inode *inode; > + struct grub_f2fs_dir_iter_ctx ctx = { > + .data = diro->data, > + .hook = hook, > + .hook_data = hook_data > + }; > + grub_off_t fpos = 0; > + > + if (!diro->inode_read) > + { > + grub_f2fs_read_node (diro->data, diro->ino, &diro->inode); > + if (grub_errno) > + return 0; > + } > + > + inode = &diro->inode.i; > + > + if (inode->i_inline & F2FS_INLINE_DENTRY) > + return grub_f2fs_iterate_inline_dir (inode, &ctx); > + > + while (fpos < grub_f2fs_file_size (inode)) > + { > + struct grub_f2fs_dentry_block *de_blk; > + char *buf; > + int ret; > + > + buf = grub_zalloc (F2FS_BLKSIZE); > + if (!buf) > + return 0; > + > + grub_f2fs_read_file (diro, 0, 0, fpos, F2FS_BLKSIZE, buf); > + if (grub_errno) > + { > + grub_free (buf); > + return 0; > + } > + > + de_blk = (struct grub_f2fs_dentry_block *) buf; > + > + ctx.bitmap = de_blk->dentry_bitmap; > + ctx.dentry = de_blk->dentry; > + ctx.filename = de_blk->filename; > + ctx.max = NR_DENTRY_IN_BLOCK; > + > + ret = grub_f2fs_check_dentries (&ctx); > + grub_free (buf); > + if (ret) > + return 1; > + > + fpos += F2FS_BLKSIZE; > + } > + return 0; > +} > + > +static int > +grub_f2fs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, > + grub_fshelp_node_t node, void *data) > +{ > + struct grub_f2fs_dir_ctx *ctx = data; > + struct grub_dirhook_info info; > + > + grub_memset (&info, 0, sizeof (info)); > + if (!node->inode_read) > + { > + grub_f2fs_read_node (ctx->data, node->ino, &node->inode); > + if (!grub_errno) > + node->inode_read = 1; > + grub_errno = GRUB_ERR_NONE; > + } > + if (node->inode_read) > + { > + info.mtimeset = 1; > + info.mtime = grub_le_to_cpu64 (node->inode.i.i_mtime); > + } > + > + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); > + grub_free (node); > + return ctx->hook (filename, &info, ctx->hook_data); > +} > + > +static grub_err_t > +grub_f2fs_dir (grub_device_t device, const char *path, > + grub_fs_dir_hook_t hook, void *hook_data) > +{ > + struct grub_f2fs_dir_ctx ctx = { > + .hook = hook, > + .hook_data = hook_data > + }; > + struct grub_fshelp_node *fdiro = 0; > + > + grub_dl_ref (my_mod); > + > + ctx.data = grub_f2fs_mount (device->disk); > + if (!ctx.data) > + goto fail; > + > + grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro, > + grub_f2fs_iterate_dir, grub_f2fs_read_symlink, > + GRUB_FSHELP_DIR); > + if (grub_errno) > + goto fail; > + > + grub_f2fs_iterate_dir (fdiro, grub_f2fs_dir_iter, &ctx); > + > +fail: > + if (fdiro != &ctx.data->diropen) > + grub_free (fdiro); > + grub_free (ctx.data); > + grub_dl_unref (my_mod); > + return grub_errno; > +} > + > + > +/* Open a file named NAME and initialize FILE. */ > +static grub_err_t > +grub_f2fs_open (struct grub_file *file, const char *name) > +{ > + struct grub_f2fs_data *data = NULL; > + struct grub_fshelp_node *fdiro = 0; > + struct grub_f2fs_inode *inode; > + > + grub_dl_ref (my_mod); > + > + data = grub_f2fs_mount (file->device->disk); > + if (!data) > + goto fail; > + > + grub_fshelp_find_file (name, &data->diropen, &fdiro, > + grub_f2fs_iterate_dir, grub_f2fs_read_symlink, > + GRUB_FSHELP_REG); > + if (grub_errno) > + goto fail; > + > + if (!fdiro->inode_read) > + { > + grub_f2fs_read_node (data, fdiro->ino, &fdiro->inode); > + if (grub_errno) > + goto fail; > + } > + > + grub_memcpy (data->inode, &fdiro->inode, sizeof (*data->inode)); > + grub_free (fdiro); > + > + inode = &(data->inode->i); > + file->size = grub_f2fs_file_size (inode); > + file->data = data; > + file->offset = 0; > + > + if (inode->i_inline & F2FS_INLINE_DATA && file->size > MAX_INLINE_DATA) > + grub_error (GRUB_ERR_BAD_FS, "corrupted inline_data: need fsck"); > + return 0; > + > +fail: > + if (fdiro != &data->diropen) > + grub_free (fdiro); > + grub_free (data); > + > + grub_dl_unref (my_mod); > + > + return grub_errno; > +} > + > +static grub_ssize_t > +grub_f2fs_read (grub_file_t file, char *buf, grub_size_t len) > +{ > + struct grub_f2fs_data *data = (struct grub_f2fs_data *) file->data; > + > + return grub_f2fs_read_file (&data->diropen, > + file->read_hook, file->read_hook_data, > + file->offset, len, buf); > +} > + > +static grub_err_t > +grub_f2fs_close (grub_file_t file) > +{ > + struct grub_f2fs_data *data = (struct grub_f2fs_data *) file->data; > + > + grub_free (data); > + > + grub_dl_unref (my_mod); > + > + return GRUB_ERR_NONE; > +} > + > +static grub_uint8_t * > +grub_f2fs_utf16_to_utf8 (grub_uint16_t *in_buf_le) > +{ > + grub_uint16_t in_buf[MAX_VOLUME_NAME]; > + grub_uint8_t *out_buf; > + int len = 0; > + > + out_buf = grub_malloc (MAX_VOLUME_NAME * GRUB_MAX_UTF8_PER_UTF16 + 1); > + if (!out_buf) > + return NULL; > + > + while (*in_buf_le != 0 && len < MAX_VOLUME_NAME) { > + in_buf[len] = grub_le_to_cpu16 (in_buf_le[len]); > + len++; > + } > + > + *grub_utf16_to_utf8 (out_buf, in_buf, len) = '\0'; > + return out_buf; > +} > + > +static grub_err_t > +grub_f2fs_label (grub_device_t device, char **label) > +{ > + struct grub_f2fs_data *data; > + grub_disk_t disk = device->disk; > + > + grub_dl_ref (my_mod); > + > + data = grub_f2fs_mount (disk); > + if (data) > + *label = (char *) grub_f2fs_utf16_to_utf8 (data->sblock.volume_name); > + else > + *label = NULL; > + > + grub_free (data); > + grub_dl_unref (my_mod); > + return grub_errno; > +} > + > +static grub_err_t > +grub_f2fs_uuid (grub_device_t device, char **uuid) > +{ > + struct grub_f2fs_data *data; > + grub_disk_t disk = device->disk; > + > + grub_dl_ref (my_mod); > + > + data = grub_f2fs_mount (disk); > + if (data) > + { > + *uuid = > + grub_xasprintf > + ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", > + data->sblock.uuid[0], data->sblock.uuid[1], > + data->sblock.uuid[2], data->sblock.uuid[3], > + data->sblock.uuid[4], data->sblock.uuid[5], > + data->sblock.uuid[6], data->sblock.uuid[7], > + data->sblock.uuid[8], data->sblock.uuid[9], > + data->sblock.uuid[10], data->sblock.uuid[11], > + data->sblock.uuid[12], data->sblock.uuid[13], > + data->sblock.uuid[14], data->sblock.uuid[15]); > + } > + else > + *uuid = NULL; > + > + grub_free (data); > + grub_dl_unref (my_mod); > + return grub_errno; > +} > + > +static struct grub_fs grub_f2fs_fs = { > + .name = "f2fs", > + .dir = grub_f2fs_dir, > + .open = grub_f2fs_open, > + .read = grub_f2fs_read, > + .close = grub_f2fs_close, > + .label = grub_f2fs_label, > + .uuid = grub_f2fs_uuid, > +#ifdef GRUB_UTIL > + .reserved_first_sector = 1, > + .blocklist_install = 0, > +#endif > + .next = 0 > +}; > + > +GRUB_MOD_INIT (f2fs) > +{ > + grub_fs_register (&grub_f2fs_fs); > + my_mod = mod; > +} > + > +GRUB_MOD_FINI (f2fs) > +{ > + grub_fs_unregister (&grub_f2fs_fs); > +} > diff --git a/po/exclude.pot b/po/exclude.pot > index 0a9b215..816089c 100644 > --- a/po/exclude.pot > +++ b/po/exclude.pot > @@ -1214,6 +1214,7 @@ msgstr "" > > #: grub-core/commands/xnu_uuid.c:75 grub-core/fs/jfs.c:924 > #: grub-core/fs/nilfs2.c:1135 > +#: grub-core/fs/f2fs.c:1259 > #, c-format > msgid "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" > msgstr "" > diff --git a/tests/f2fs_test.in b/tests/f2fs_test.in > new file mode 100644 > index 0000000..1ea77c8 > --- /dev/null > +++ b/tests/f2fs_test.in > @@ -0,0 +1,19 @@ > +#!/bin/sh > + > +set -e > + > +if [ "x$EUID" = "x" ] ; then > + EUID=`id -u` > +fi > + > +if [ "$EUID" != 0 ] ; then > + exit 77 > +fi > + > +if ! which mkfs.f2fs >/dev/null 2>&1; then > + echo "mkfs.f2fs not installed; cannot test f2fs." > + exit 77 > +fi > + > + > +"@builddir@/grub-fs-tester" f2fs > diff --git a/tests/util/grub-fs-tester.in b/tests/util/grub-fs-tester.in > index 424de22..e3e4109 100644 > --- a/tests/util/grub-fs-tester.in > +++ b/tests/util/grub-fs-tester.in > @@ -142,7 +142,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE + > xsquash*) > MINBLKSIZE=4096 > MAXBLKSIZE=1048576;; > - xxfs) > + xxfs|xf2fs) > MINBLKSIZE=$SECSIZE > # OS Limitation: GNU/Linux doesn't accept > 4096 > MAXBLKSIZE=4096;; > @@ -265,6 +265,10 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE + > x"btrfs"*) > FSLABEL="grub_;/testé莭莽😁киритi urewfceniuewruevrewnuuireurevueurnievrewfnerfcnevirivinrewvnirewnivrewiuvcrewvnuewvrrrewniuerwreiuviurewiuviurewnuvewnvrenurnunuvrevuurerejiremvreijnvcreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoireoif";; > > + # FS LIMITATION: f2fs label is at most 512 UTF-16 chars > + x"f2fs") > + FSLABEL="grub_;/testé䏌䐓䏕киритiurewfceniuewruewnuuireurevueurnievrewfnerfcnevirivinrewvnirewnivrewiuvcrewvnuewvrrrewniuerwreiuviurewiuviurewnuvewnvrenurnunuvrevuurerejiremvreijnvvcreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoirvcreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoircreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoireoifoiq";; > + > # FS LIMITATION: exfat is at most 15 UTF-16 chars > x"exfat") > FSLABEL="géт ;/莭莽😁кир";; > @@ -474,7 +478,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE + > # FIXME: Not sure about BtrFS, NTFS, JFS, AFS, UDF and SFS. Check it. > # FS LIMITATION: as far as I know those FS don't store their last modification date. > x"jfs_caseins" | x"jfs" | x"xfs" | x"xfs_crc" | x"btrfs"* | x"reiserfs_old" | x"reiserfs" \ > - | x"bfs" | x"afs" \ > + | x"bfs" | x"afs" | x"f2fs" \ > | x"tarfs" | x"cpio_"* | x"minix" | x"minix2" \ > | x"minix3" | x"ntfs"* | x"udf" | x"sfs"*) > NOFSTIME=y;; > @@ -753,6 +757,8 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE + > MOUNTDEVICE="/dev/mapper/grub_test-testvol" > MOUNTFS=ext2 > "mkfs.ext2" -L "$FSLABEL" -q "${MOUNTDEVICE}" ;; > + xf2fs) > + "mkfs.f2fs" -l "$FSLABEL" -q "${LODEVICES[0]}" ;; > xnilfs2) > "mkfs.nilfs2" -L "$FSLABEL" -b $BLKSIZE -q "${LODEVICES[0]}" ;; > xext2_old) > From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrei Borzenkov Subject: [2.02] Re: [f2fs-dev] [PATCH v7] F2FS support Date: Tue, 1 Mar 2016 22:52:09 +0300 Message-ID: <56D5F2E9.1070501@gmail.com> References: <1427185140-41120-1-git-send-email-jaegeuk@kernel.org> <20150403224908.GB25673@jaegeuk-mac02.mot.com> <20151119212824.GA11666@jaegeuk.local> <566E7DAA.4010202@gmail.com> <20151215003421.GD48918@jaegeuk.local> <20151215181439.GA60773@jaegeuk.local> <20160108194132.GA17464@jaegeuk.aosp> <20160222182525.GD10875@jaegeuk.gateway> Reply-To: The development of GNU GRUB Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20160222182525.GD10875@jaegeuk.gateway> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: grub-devel-bounces+gcbgd-grub-devel=m.gmane.org@gnu.org Sender: grub-devel-bounces+gcbgd-grub-devel=m.gmane.org@gnu.org To: Jaegeuk Kim Cc: The development of GNU GRUB , linux-f2fs-devel@lists.sourceforge.net List-Id: linux-f2fs-devel.lists.sourceforge.net QUNLIGZyb20gbXkgc2lkZS4gSXQgaXMgbGVhZiBjb2RlIHRoYXQgZG9lcyBub3QgYWZmZWN0IGFu eXRoaW5nIHNvCnNob3VsZCBub3QgY2F1c2UgYW55IHJlZ3Jlc3Npb24uCgoyMi4wMi4yMDE2IDIx OjI1LCBKYWVnZXVrIEtpbSDQv9C40YjQtdGCOgo+IENoYW5nIGxvZyBmcm9tIHY2Ogo+ICBvIHJl bW92ZSByZWR1bmRhbnQgZmlsZXNpemUgY2hlY2sgaW4gLT5yZWFkCj4gIG8gY2hlY2sgY29uc2lz dGVuY3kgaW4gLT5vcGVuIHJlZ2FyZGluZyB0byBpbmxpbmVfZGF0YQo+IAo+IC0tID44IC0tCj4g RnJvbSA1MWMxMjA2MTJmZGJjNGJjMzE1ZTljNGM2ZTkxY2E4ODhjM2YzNTk2IE1vbiBTZXAgMTcg MDA6MDA6MDAgMjAwMQo+IEZyb206IEphZWdldWsgS2ltIDxqYWVnZXVrQGtlcm5lbC5vcmc+Cj4g RGF0ZTogVHVlLCAxNyBOb3YgMjAxNSAxMjo0NToxMyAtMDgwMAo+IFN1YmplY3Q6IFtQQVRDSF0g RjJGUyBzdXBwb3J0Cj4gCj4gIkYyRlMgKEZsYXNoLUZyaWVuZGx5IEZpbGUgU3lzdGVtKSBpcyBm bGFzaC1mcmllbmRseSBmaWxlIHN5c3RlbSB3aGljaCB3YXMgbWVyZ2VkCj4gaW50byBMaW51eCBr ZXJuZWwgdjMuOCBpbiAyMDEzLgo+IAo+IFRoZSBtb3RpdmUgZm9yIEYyRlMgd2FzIHRvIGJ1aWxk IGEgZmlsZSBzeXN0ZW0gdGhhdCBmcm9tIHRoZSBzdGFydCwgdGFrZXMgaW50bwo+IGFjY291bnQg dGhlIGNoYXJhY3RlcmlzdGljcyBvZiBOQU5EIGZsYXNoIG1lbW9yeS1iYXNlZCBzdG9yYWdlIGRl dmljZXMgKHN1Y2ggYXMKPiBzb2xpZC1zdGF0ZSBkaXNrcywgZU1NQywgYW5kIFNEIGNhcmRzKS4K PiAKPiBGMkZTIHdhcyBkZXNpZ25lZCBvbiBhIGJhc2lzIG9mIGEgbG9nLXN0cnVjdHVyZWQgZmls ZSBzeXN0ZW0gYXBwcm9hY2gsIHdoaWNoCj4gcmVtZWRpZXMgc29tZSBrbm93biBpc3N1ZXMgb2Yg dGhlIG9sZGVyIGxvZyBzdHJ1Y3R1cmVkIGZpbGUgc3lzdGVtcywgc3VjaCBhcwo+IHRoZSBzbm93 YmFsbCBlZmZlY3Qgb2Ygd2FuZGVyaW5nIHRyZWVzIGFuZCBoaWdoIGNsZWFuaW5nIG92ZXJoZWFk LiBJbiBhZGRpdGlvbiwKPiBzaW5jZSBhIE5BTkQtYmFzZWQgc3RvcmFnZSBkZXZpY2Ugc2hvd3Mg ZGlmZmVyZW50IGNoYXJhY3RlcmlzdGljcyBhY2NvcmRpbmcgdG8KPiBpdHMgaW50ZXJuYWwgZ2Vv bWV0cnkgb3IgZmxhc2ggbWVtb3J5IG1hbmFnZW1lbnQgc2NoZW1lIChzdWNoIGFzIHRoZSBGbGFz aAo+IFRyYW5zbGF0aW9uIExheWVyIG9yIEZUTCksIGl0IHN1cHBvcnRzIHZhcmlvdXMgcGFyYW1l dGVycyBub3Qgb25seSBmb3IKPiBjb25maWd1cmluZyBvbi1kaXNrIGxheW91dCwgYnV0IGFsc28g Zm9yIHNlbGVjdGluZyBhbGxvY2F0aW9uIGFuZCBjbGVhbmluZwo+IGFsZ29yaXRobS4iLCBxdW90 ZSBieSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GMkZTLgo+IAo+IFRoZSBzb3VyY2Ug Y29kZXMgZm9yIEYyRlMgYXJlIGF2YWlsYWJsZSBmcm9tOgo+IAo+IGh0dHA6Ly9naXQua2VybmVs Lm9yZy9jZ2l0L2xpbnV4L2tlcm5lbC9naXQvamFlZ2V1ay9mMmZzLmdpdAo+IGh0dHA6Ly9naXQu a2VybmVsLm9yZy9jZ2l0L2xpbnV4L2tlcm5lbC9naXQvamFlZ2V1ay9mMmZzLXRvb2xzLmdpdAo+ IAo+IFNpZ25lZC1vZmYtYnk6IEphZWdldWsgS2ltIDxqYWVnZXVrQGtlcm5lbC5vcmc+Cj4gLS0t Cj4gIE1ha2VmaWxlLnV0aWwuZGVmICAgICAgICAgICAgfCAgICA3ICsKPiAgZG9jcy9ncnViLnRl eGkgICAgICAgICAgICAgICB8ICAgIDUgKy0KPiAgZ3J1Yi1jb3JlL01ha2VmaWxlLmNvcmUuZGVm ICB8ICAgIDUgKwo+ICBncnViLWNvcmUvZnMvZjJmcy5jICAgICAgICAgIHwgMTI4OSArKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKPiAgcG8vZXhjbHVkZS5wb3QgICAg ICAgICAgICAgICB8ICAgIDEgKwo+ICB0ZXN0cy9mMmZzX3Rlc3QuaW4gICAgICAgICAgIHwgICAx OSArCj4gIHRlc3RzL3V0aWwvZ3J1Yi1mcy10ZXN0ZXIuaW4gfCAgIDEwICstCj4gIDcgZmlsZXMg Y2hhbmdlZCwgMTMzMiBpbnNlcnRpb25zKCspLCA0IGRlbGV0aW9ucygtKQo+ICBjcmVhdGUgbW9k ZSAxMDA2NDQgZ3J1Yi1jb3JlL2ZzL2YyZnMuYwo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgdGVzdHMv ZjJmc190ZXN0LmluCj4gCj4gZGlmZiAtLWdpdCBhL01ha2VmaWxlLnV0aWwuZGVmIGIvTWFrZWZp bGUudXRpbC5kZWYKPiBpbmRleCBkYjdlOGVjLi44NDYyN2JiIDEwMDY0NAo+IC0tLSBhL01ha2Vm aWxlLnV0aWwuZGVmCj4gKysrIGIvTWFrZWZpbGUudXRpbC5kZWYKPiBAQCAtOTksNiArOTksNyBA QCBsaWJyYXJ5ID0gewo+ICAgIGNvbW1vbiA9IGdydWItY29yZS9mcy9leHQyLmM7Cj4gICAgY29t bW9uID0gZ3J1Yi1jb3JlL2ZzL2ZhdC5jOwo+ICAgIGNvbW1vbiA9IGdydWItY29yZS9mcy9leGZh dC5jOwo+ICsgIGNvbW1vbiA9IGdydWItY29yZS9mcy9mMmZzLmM7Cj4gICAgY29tbW9uID0gZ3J1 Yi1jb3JlL2ZzL2ZzaGVscC5jOwo+ICAgIGNvbW1vbiA9IGdydWItY29yZS9mcy9oZnMuYzsKPiAg ICBjb21tb24gPSBncnViLWNvcmUvZnMvaGZzcGx1cy5jOwo+IEBAIC03NjYsNiArNzY3LDEyIEBA IHNjcmlwdCA9IHsKPiAgCj4gIHNjcmlwdCA9IHsKPiAgICB0ZXN0Y2FzZTsKPiArICBuYW1lID0g ZjJmc190ZXN0Owo+ICsgIGNvbW1vbiA9IHRlc3RzL2YyZnNfdGVzdC5pbjsKPiArfTsKPiArCj4g K3NjcmlwdCA9IHsKPiArICB0ZXN0Y2FzZTsKPiAgICBuYW1lID0gbmlsZnMyX3Rlc3Q7Cj4gICAg Y29tbW9uID0gdGVzdHMvbmlsZnMyX3Rlc3QuaW47Cj4gIH07Cj4gZGlmZiAtLWdpdCBhL2RvY3Mv Z3J1Yi50ZXhpIGIvZG9jcy9ncnViLnRleGkKPiBpbmRleCAxZGYzZGIyLi5lNWE4MGYzIDEwMDY0 NAo+IC0tLSBhL2RvY3MvZ3J1Yi50ZXhpCj4gKysrIGIvZG9jcy9ncnViLnRleGkKPiBAQCAtMzYw LDcgKzM2MCw4IEBAIGJsb2NrbGlzdCBub3RhdGlvbi4gVGhlIGN1cnJlbnRseSBzdXBwb3J0ZWQg ZmlsZXN5c3RlbSB0eXBlcyBhcmUgQGRmbntBbWlnYQo+ICBGYXN0IEZpbGVTeXN0ZW0gKEFGRlMp fSwgQGRmbntBdGhlT1MgZnN9LCBAZGZue0JlRlN9LAo+ICBAZGZue0J0ckZTfSAoaW5jbHVkaW5n IHJhaWQwLCByYWlkMSwgcmFpZDEwLCBnemlwIGFuZCBsem8pLAo+ICBAZGZue2NwaW99IChsaXR0 bGUtIGFuZCBiaWctZW5kaWFuIGJpbiwgb2RjIGFuZCBuZXdjIHZhcmlhbnRzKSwKPiAtQGRmbntM aW51eCBleHQyL2V4dDMvZXh0NH0sIEBkZm57RE9TIEZBVDEyL0ZBVDE2L0ZBVDMyfSwgQGRmbntl eEZBVH0sIEBkZm57SEZTfSwKPiArQGRmbntMaW51eCBleHQyL2V4dDMvZXh0NH0sIEBkZm57RE9T IEZBVDEyL0ZBVDE2L0ZBVDMyfSwgQGRmbntleEZBVH0sCj4gK0BkZm57ZjJmc30sIEBkZm57SEZT fSwKPiAgQGRmbntIRlMrfSwgQGRmbntJU085NjYwfSAoaW5jbHVkaW5nIEpvbGlldCwgUm9jay1y aWRnZSBhbmQgbXVsdGktY2h1bmsgZmlsZXMpLAo+ICBAZGZue0pGU30sIEBkZm57TWluaXggZnN9 ICh2ZXJzaW9ucyAxLCAyIGFuZCAzKSwgQGRmbntuaWxmczJ9LAo+ICBAZGZue05URlN9IChpbmNs dWRpbmcgY29tcHJlc3Npb24pLCBAZGZue1JlaXNlckZTfSwgQGRmbntST01GU30sCj4gQEAgLTUz NDcsNyArNTM0OCw3IEBAIE5URlMsIEpGUywgVURGLCBIRlMrLCBleEZBVCwgbG9uZyBmaWxlbmFt ZXMgaW4gRkFULCBKb2xpZXQgcGFydCBvZgo+ICBJU085NjYwIGFyZSB0cmVhdGVkIGFzIFVURi0x NiBhcyBwZXIgc3BlY2lmaWNhdGlvbi4gQUZTIGFuZCBCRlMgYXJlIHJlYWQKPiAgYXMgVVRGLTgs IGFnYWluIGFjY29yZGluZyB0byBzcGVjaWZpY2F0aW9uLiBCdHJGUywgY3BpbywgdGFyLCBzcXVh c2g0LCBtaW5peCwKPiAgbWluaXgyLCBtaW5peDMsIFJPTUZTLCBSZWlzZXJGUywgWEZTLCBleHQy LCBleHQzLCBleHQ0LCBGQVQgKHNob3J0IG5hbWVzKSwKPiAtUm9ja1JpZGdlIHBhcnQgb2YgSVNP OTY2MCwgbmlsZnMyLCBVRlMxLCBVRlMyIGFuZCBaRlMgYXJlIGFzc3VtZWQKPiArZjJmcywgUm9j a1JpZGdlIHBhcnQgb2YgSVNPOTY2MCwgbmlsZnMyLCBVRlMxLCBVRlMyIGFuZCBaRlMgYXJlIGFz c3VtZWQKPiAgdG8gYmUgVVRGLTguIFRoaXMgbWlnaHQgYmUgZmFsc2Ugb24gc3lzdGVtcyBjb25m aWd1cmVkIHdpdGggbGVnYWN5IGNoYXJzZXQKPiAgYnV0IGFzIGxvbmcgYXMgdGhlIGNoYXJzZXQg dXNlZCBpcyBzdXBlcnNldCBvZiBBU0NJSSB5b3Ugc2hvdWxkIGJlIGFibGUgdG8KPiAgYWNjZXNz IEFTQ0lJLW5hbWVkIGZpbGVzLiBBbmQgaXQncyByZWNvbW1lbmRlZCB0byBjb25maWd1cmUgeW91 ciBzeXN0ZW0gdG8gdXNlCj4gZGlmZiAtLWdpdCBhL2dydWItY29yZS9NYWtlZmlsZS5jb3JlLmRl ZiBiL2dydWItY29yZS9NYWtlZmlsZS5jb3JlLmRlZgo+IGluZGV4IGQ5ZmEwZTMuLmI1ODVhZGUg MTAwNjQ0Cj4gLS0tIGEvZ3J1Yi1jb3JlL01ha2VmaWxlLmNvcmUuZGVmCj4gKysrIGIvZ3J1Yi1j b3JlL01ha2VmaWxlLmNvcmUuZGVmCj4gQEAgLTEyNzgsNiArMTI3OCwxMSBAQCBtb2R1bGUgPSB7 Cj4gIH07Cj4gIAo+ICBtb2R1bGUgPSB7Cj4gKyAgbmFtZSA9IGYyZnM7Cj4gKyAgY29tbW9uID0g ZnMvZjJmcy5jOwo+ICt9Owo+ICsKPiArbW9kdWxlID0gewo+ICAgIG5hbWUgPSBmc2hlbHA7Cj4g ICAgY29tbW9uID0gZnMvZnNoZWxwLmM7Cj4gIH07Cj4gZGlmZiAtLWdpdCBhL2dydWItY29yZS9m cy9mMmZzLmMgYi9ncnViLWNvcmUvZnMvZjJmcy5jCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBp bmRleCAwMDAwMDAwLi5jYjMxMmIzCj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2dydWItY29yZS9m cy9mMmZzLmMKPiBAQCAtMCwwICsxLDEyODkgQEAKPiArLyoKPiArICogIGYyZnMuYyAtIEZsYXNo LUZyaWVuZGx5IEZpbGUgU3lzdGVtCj4gKyAqCj4gKyAqICBXcml0dGVuIGJ5IEphZWdldWsgS2lt IDxqYWVnZXVrQGtlcm5lbC5vcmc+Cj4gKyAqCj4gKyAqICBDb3B5cmlnaHQgKEMpIDIwMTUgIEZy ZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgSW5jLgo+ICsgKgo+ICsgKiAgR1JVQiBpcyBmcmVlIHNv ZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5Cj4gKyAqICBpdCB1 bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxp c2hlZCBieQo+ICsgKiAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNp b24gMyBvZiB0aGUgTGljZW5zZSwgb3IKPiArICogIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVy IHZlcnNpb24uCj4gKyAqCj4gKyAqICBHUlVCIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRo YXQgaXQgd2lsbCBiZSB1c2VmdWwsCj4gKyAqICBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdp dGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgo+ICsgKiAgTUVSQ0hBTlRBQklMSVRZ IG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQo+ICsgKiAgR05V IEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KPiArICoKPiArICogIFlv dSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBM aWNlbnNlCj4gKyAqICBhbG9uZyB3aXRoIEdSVUIuICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5n bnUub3JnL2xpY2Vuc2VzLz4uCj4gKyAqLwo+ICsjaW5jbHVkZSA8Z3J1Yi9lcnIuaD4KPiArI2lu Y2x1ZGUgPGdydWIvZmlsZS5oPgo+ICsjaW5jbHVkZSA8Z3J1Yi9tbS5oPgo+ICsjaW5jbHVkZSA8 Z3J1Yi9taXNjLmg+Cj4gKyNpbmNsdWRlIDxncnViL2Rpc2suaD4KPiArI2luY2x1ZGUgPGdydWIv ZGwuaD4KPiArI2luY2x1ZGUgPGdydWIvdHlwZXMuaD4KPiArI2luY2x1ZGUgPGdydWIvY2hhcnNl dC5oPgo+ICsjaW5jbHVkZSA8Z3J1Yi9mc2hlbHAuaD4KPiArCj4gK0dSVUJfTU9EX0xJQ0VOU0Ug KCJHUEx2MysiKTsKPiArCj4gKy8qIEYyRlMgTWFnaWMgTnVtYmVyICovCj4gKyNkZWZpbmUgRjJG U19TVVBFUl9NQUdJQwkweEYyRjUyMDEwCj4gKyNkZWZpbmUgQ0hFQ0tTVU1fT0ZGU0VUCQk0MDky CQkvKiBtdXN0IGJlIGFsaWduZWQgNCBieXRlcyAqLwo+ICsjZGVmaW5lIFUzMl9DSEVDS1NVTV9P RkZTRVQJKENIRUNLU1VNX09GRlNFVCA+PiAyKQo+ICsKPiArLyogYnl0ZS1zaXplIG9mZnNldCAq Lwo+ICsjZGVmaW5lIEYyRlNfU1VQRVJfT0ZGU0VUCSgoZ3J1Yl9kaXNrX2FkZHJfdCkxMDI0KQo+ ICsjZGVmaW5lIEYyRlNfU1VQRVJfT0ZGU0VUMAkoRjJGU19TVVBFUl9PRkZTRVQgPj4gR1JVQl9E SVNLX1NFQ1RPUl9CSVRTKQo+ICsjZGVmaW5lIEYyRlNfU1VQRVJfT0ZGU0VUMQkoKEYyRlNfU1VQ RVJfT0ZGU0VUICsgRjJGU19CTEtTSVpFKSA+PglcCj4gKwkJCQkJCUdSVUJfRElTS19TRUNUT1Jf QklUUykKPiArCj4gKy8qIDkgYml0cyBmb3IgNTEyIGJ5dGVzICovCj4gKyNkZWZpbmUgRjJGU19N SU5fTE9HX1NFQ1RPUl9TSVpFCTkKPiArCj4gKy8qIHN1cHBvcnQgb25seSA0S0IgYmxvY2sgKi8K PiArI2RlZmluZSBGMkZTX0JMS19CSVRTCTEyCj4gKyNkZWZpbmUgRjJGU19CTEtTSVpFCSgxIDw8 IEYyRlNfQkxLX0JJVFMpCj4gKyNkZWZpbmUgRjJGU19CTEtfU0VDX0JJVFMJKEYyRlNfQkxLX0JJ VFMgLSBHUlVCX0RJU0tfU0VDVE9SX0JJVFMpCj4gKwo+ICsjZGVmaW5lIFZFUlNJT05fTEVOCTI1 Ngo+ICsjZGVmaW5lIEYyRlNfTUFYX0VYVEVOU0lPTgk2NAo+ICsKPiArI2RlZmluZSBDUF9DT01Q QUNUX1NVTV9GTEFHCTB4MDAwMDAwMDQKPiArI2RlZmluZSBDUF9VTU9VTlRfRkxBRwkweDAwMDAw MDAxCj4gKwo+ICsjZGVmaW5lIE1BWF9BQ1RJVkVfTE9HUwkxNgo+ICsjZGVmaW5lIE1BWF9BQ1RJ VkVfTk9ERV9MT0dTCTgKPiArI2RlZmluZSBNQVhfQUNUSVZFX0RBVEFfTE9HUwk4Cj4gKyNkZWZp bmUJTlJfQ1VSU0VHX0RBVEFfVFlQRQkzCj4gKyNkZWZpbmUgTlJfQ1VSU0VHX05PREVfVFlQRQkz Cj4gKyNkZWZpbmUgTlJfQ1VSU0VHX1RZUEUJKE5SX0NVUlNFR19EQVRBX1RZUEUgKyBOUl9DVVJT RUdfTk9ERV9UWVBFKQo+ICsKPiArI2RlZmluZSBFTlRSSUVTX0lOX1NVTQk1MTIKPiArI2RlZmlu ZQlTVU1NQVJZX1NJWkUJNwo+ICsjZGVmaW5lCVNVTV9GT09URVJfU0laRQk1Cj4gKyNkZWZpbmUg SkVOVFJZX1NJWkUJKHNpemVvZihzdHJ1Y3QgZ3J1Yl9mMmZzX25hdF9qZW50KSkKPiArI2RlZmlu ZSBTVU1fRU5UUklFU19TSVpFCShTVU1NQVJZX1NJWkUgKiBFTlRSSUVTX0lOX1NVTSkKPiArI2Rl ZmluZSBTVU1fSk9VUk5BTF9TSVpFCShGMkZTX0JMS1NJWkUgLSBTVU1fRk9PVEVSX1NJWkUgLVwK PiArCQkJCVNVTV9FTlRSSUVTX1NJWkUpCj4gKyNkZWZpbmUgTkFUX0pPVVJOQUxfRU5UUklFUwko KFNVTV9KT1VSTkFMX1NJWkUgLSAyKSAvIEpFTlRSWV9TSVpFKQo+ICsjZGVmaW5lIE5BVF9KT1VS TkFMX1JFU0VSVkVECSgoU1VNX0pPVVJOQUxfU0laRSAtIDIpICUgSkVOVFJZX1NJWkUpCj4gKwo+ ICsjZGVmaW5lIE5BVF9FTlRSWV9TSVpFIChzaXplb2Yoc3RydWN0IGdydWJfZjJmc19uYXRfZW50 cnkpKQo+ICsjZGVmaW5lIE5BVF9FTlRSWV9QRVJfQkxPQ0sgKEYyRlNfQkxLU0laRSAvIE5BVF9F TlRSWV9TSVpFKQo+ICsKPiArI2RlZmluZSBGMkZTX05BTUVfTEVOCTI1NQo+ICsjZGVmaW5lIEYy RlNfU0xPVF9MRU4JOAo+ICsjZGVmaW5lIE5SX0RFTlRSWV9JTl9CTE9DSwkyMTQKPiArI2RlZmlu ZSBTSVpFX09GX0RJUl9FTlRSWQkxMQkvKiBieSBieXRlICovCj4gKyNkZWZpbmUgQklUU19QRVJf QllURQk4Cj4gKyNkZWZpbmUgU0laRV9PRl9ERU5UUllfQklUTUFQCSgoTlJfREVOVFJZX0lOX0JM T0NLICsgQklUU19QRVJfQllURSAtIDEpIC8gXAo+ICsJCQkJQklUU19QRVJfQllURSkKPiArI2Rl ZmluZSBTSVpFX09GX1JFU0VSVkVECShGMkZTX0JMS1NJWkUgLSAoKFNJWkVfT0ZfRElSX0VOVFJZ ICsgXAo+ICsJCQkJRjJGU19TTE9UX0xFTikgKiBcCj4gKwkJCQlOUl9ERU5UUllfSU5fQkxPQ0sg KyBTSVpFX09GX0RFTlRSWV9CSVRNQVApKQo+ICsKPiArI2RlZmluZSBGMkZTX0lOTElORV9YQVRU Ul9BRERSUwk1MAkvKiAyMDAgYnl0ZXMgZm9yIGlubGluZSB4YXR0cnMgKi8KPiArI2RlZmluZSBE RUZfQUREUlNfUEVSX0lOT0RFCTkyMwkvKiBBZGRyZXNzIFBvaW50ZXJzIGluIGFuIElub2RlICov Cj4gKwo+ICsjZGVmaW5lIEFERFJTX1BFUl9CTE9DSwkxMDE4CS8qIEFkZHJlc3MgUG9pbnRlcnMg aW4gYSBEaXJlY3QgQmxvY2sgKi8KPiArI2RlZmluZSBOSURTX1BFUl9CTE9DSwkxMDE4CS8qIE5v ZGUgSURzIGluIGFuIEluZGlyZWN0IEJsb2NrICovCj4gKyNkZWZpbmUJTk9ERV9ESVIxX0JMT0NL CShERUZfQUREUlNfUEVSX0lOT0RFICsgMSkKPiArI2RlZmluZQlOT0RFX0RJUjJfQkxPQ0sJKERF Rl9BRERSU19QRVJfSU5PREUgKyAyKQo+ICsjZGVmaW5lCU5PREVfSU5EMV9CTE9DSwkoREVGX0FE RFJTX1BFUl9JTk9ERSArIDMpCj4gKyNkZWZpbmUJTk9ERV9JTkQyX0JMT0NLCShERUZfQUREUlNf UEVSX0lOT0RFICsgNCkKPiArI2RlZmluZQlOT0RFX0RJTkRfQkxPQ0sJKERFRl9BRERSU19QRVJf SU5PREUgKyA1KQo+ICsKPiArI2RlZmluZSBNQVhfSU5MSU5FX0RBVEEJKDQgKiAoREVGX0FERFJT X1BFUl9JTk9ERSAtIFwKPiArCQkJRjJGU19JTkxJTkVfWEFUVFJfQUREUlMgLSAxKSkKPiArI2Rl ZmluZSBOUl9JTkxJTkVfREVOVFJZCShNQVhfSU5MSU5FX0RBVEEgKiBCSVRTX1BFUl9CWVRFIC8g XAo+ICsJCQkoKFNJWkVfT0ZfRElSX0VOVFJZICsgRjJGU19TTE9UX0xFTikgKiBcCj4gKwkJCSBC SVRTX1BFUl9CWVRFICsgMSkpCj4gKyNkZWZpbmUgSU5MSU5FX0RFTlRSWV9CSVRNQVBfU0laRQko KE5SX0lOTElORV9ERU5UUlkgKyBcCj4gKwkJCUJJVFNfUEVSX0JZVEUgLSAxKSAvIEJJVFNfUEVS X0JZVEUpCj4gKyNkZWZpbmUgSU5MSU5FX1JFU0VSVkVEX1NJWkUJKE1BWF9JTkxJTkVfREFUQSAt IFwKPiArCQkJKChTSVpFX09GX0RJUl9FTlRSWSArIEYyRlNfU0xPVF9MRU4pICogXAo+ICsJCQkg TlJfSU5MSU5FX0RFTlRSWSArIElOTElORV9ERU5UUllfQklUTUFQX1NJWkUpKQo+ICsjZGVmaW5l IENVUlNFR19IT1RfREFUQQkwCj4gKwo+ICsjZGVmaW5lIENLUFRfRkxBR19TRVQoY2twdCwgZikJ XAo+ICsJCShja3B0KS0+Y2twdF9mbGFncyAmIGdydWJfY3B1X3RvX2xlMzJfY29tcGlsZV90aW1l IChmKQo+ICsKPiArI2RlZmluZSBGMkZTX0lOTElORV9YQVRUUgkweDAxCS8qIGZpbGUgaW5saW5l IHhhdHRyIGZsYWcgKi8KPiArI2RlZmluZSBGMkZTX0lOTElORV9EQVRBCTB4MDIJLyogZmlsZSBp bmxpbmUgZGF0YSBmbGFnICovCj4gKyNkZWZpbmUgRjJGU19JTkxJTkVfREVOVFJZCTB4MDQJLyog ZmlsZSBpbmxpbmUgZGVudHJ5IGZsYWcgKi8KPiArI2RlZmluZSBGMkZTX0RBVEFfRVhJU1QJCTB4 MDgJLyogZmlsZSBpbmxpbmUgZGF0YSBleGlzdCBmbGFnICovCj4gKyNkZWZpbmUgRjJGU19JTkxJ TkVfRE9UUwkweDEwCS8qIGZpbGUgaGF2aW5nIGltcGxpY2l0IGRvdCBkZW50cmllcyAqLwo+ICsK PiArZW51bSBGSUxFX1RZUEUKPiArewo+ICsgIEYyRlNfRlRfVU5LTk9XTiwKPiArICBGMkZTX0ZU X1JFR19GSUxFID0gMSwKPiArICBGMkZTX0ZUX0RJUiA9IDIsCj4gKyAgRjJGU19GVF9TWU1MSU5L ID0gNywKPiArfTsKPiArCj4gKyNkZWZpbmUgTUFYX1ZPTFVNRV9OQU1FCQk1MTIKPiArCj4gK3N0 cnVjdCBncnViX2YyZnNfc3VwZXJibG9jawo+ICt7Cj4gKyAgZ3J1Yl91aW50MzJfdCBtYWdpYzsK PiArICBncnViX3VpbnQxNl90IGR1bW15MVsyXTsKPiArICBncnViX3VpbnQzMl90IGxvZ19zZWN0 b3JzaXplOwo+ICsgIGdydWJfdWludDMyX3QgbG9nX3NlY3RvcnNfcGVyX2Jsb2NrOwo+ICsgIGdy dWJfdWludDMyX3QgbG9nX2Jsb2Nrc2l6ZTsKPiArICBncnViX3VpbnQzMl90IGxvZ19ibG9ja3Nf cGVyX3NlZzsKPiArICBncnViX3VpbnQzMl90IHNlZ3NfcGVyX3NlYzsKPiArICBncnViX3VpbnQz Ml90IHNlY3NfcGVyX3pvbmU7Cj4gKyAgZ3J1Yl91aW50MzJfdCBjaGVja3N1bV9vZmZzZXQ7Cj4g KyAgZ3J1Yl91aW50OF90IGR1bW15Mls0MF07Cj4gKyAgZ3J1Yl91aW50MzJfdCBjcF9ibGthZGRy Owo+ICsgIGdydWJfdWludDMyX3Qgc2l0X2Jsa2FkZHI7Cj4gKyAgZ3J1Yl91aW50MzJfdCBuYXRf YmxrYWRkcjsKPiArICBncnViX3VpbnQzMl90IHNzYV9ibGthZGRyOwo+ICsgIGdydWJfdWludDMy X3QgbWFpbl9ibGthZGRyOwo+ICsgIGdydWJfdWludDMyX3Qgcm9vdF9pbm87Cj4gKyAgZ3J1Yl91 aW50MzJfdCBub2RlX2lubzsKPiArICBncnViX3VpbnQzMl90IG1ldGFfaW5vOwo+ICsgIGdydWJf dWludDhfdCB1dWlkWzE2XTsKPiArICBncnViX3VpbnQxNl90IHZvbHVtZV9uYW1lW01BWF9WT0xV TUVfTkFNRV07Cj4gKyAgZ3J1Yl91aW50MzJfdCBleHRlbnNpb25fY291bnQ7Cj4gKyAgZ3J1Yl91 aW50OF90IGV4dGVuc2lvbl9saXN0W0YyRlNfTUFYX0VYVEVOU0lPTl1bOF07Cj4gKyAgZ3J1Yl91 aW50MzJfdCBjcF9wYXlsb2FkOwo+ICsgIGdydWJfdWludDhfdCB2ZXJzaW9uW1ZFUlNJT05fTEVO XTsKPiArICBncnViX3VpbnQ4X3QgaW5pdF92ZXJzaW9uW1ZFUlNJT05fTEVOXTsKPiArfSBHUlVC X1BBQ0tFRDsKPiArCj4gK3N0cnVjdCBncnViX2YyZnNfY2hlY2twb2ludAo+ICt7Cj4gKyAgZ3J1 Yl91aW50NjRfdCBjaGVja3BvaW50X3ZlcjsKPiArICBncnViX3VpbnQ2NF90IHVzZXJfYmxvY2tf Y291bnQ7Cj4gKyAgZ3J1Yl91aW50NjRfdCB2YWxpZF9ibG9ja19jb3VudDsKPiArICBncnViX3Vp bnQzMl90IHJzdmRfc2VnbWVudF9jb3VudDsKPiArICBncnViX3VpbnQzMl90IG92ZXJwcm92X3Nl Z21lbnRfY291bnQ7Cj4gKyAgZ3J1Yl91aW50MzJfdCBmcmVlX3NlZ21lbnRfY291bnQ7Cj4gKyAg Z3J1Yl91aW50MzJfdCBjdXJfbm9kZV9zZWdub1tNQVhfQUNUSVZFX05PREVfTE9HU107Cj4gKyAg Z3J1Yl91aW50MTZfdCBjdXJfbm9kZV9ibGtvZmZbTUFYX0FDVElWRV9OT0RFX0xPR1NdOwo+ICsg IGdydWJfdWludDMyX3QgY3VyX2RhdGFfc2Vnbm9bTUFYX0FDVElWRV9EQVRBX0xPR1NdOwo+ICsg IGdydWJfdWludDE2X3QgY3VyX2RhdGFfYmxrb2ZmW01BWF9BQ1RJVkVfREFUQV9MT0dTXTsKPiAr ICBncnViX3VpbnQzMl90IGNrcHRfZmxhZ3M7Cj4gKyAgZ3J1Yl91aW50MzJfdCBjcF9wYWNrX3Rv dGFsX2Jsb2NrX2NvdW50Owo+ICsgIGdydWJfdWludDMyX3QgY3BfcGFja19zdGFydF9zdW07Cj4g KyAgZ3J1Yl91aW50MzJfdCB2YWxpZF9ub2RlX2NvdW50Owo+ICsgIGdydWJfdWludDMyX3QgdmFs aWRfaW5vZGVfY291bnQ7Cj4gKyAgZ3J1Yl91aW50MzJfdCBuZXh0X2ZyZWVfbmlkOwo+ICsgIGdy dWJfdWludDMyX3Qgc2l0X3Zlcl9iaXRtYXBfYnl0ZXNpemU7Cj4gKyAgZ3J1Yl91aW50MzJfdCBu YXRfdmVyX2JpdG1hcF9ieXRlc2l6ZTsKPiArICBncnViX3VpbnQzMl90IGNoZWNrc3VtX29mZnNl dDsKPiArICBncnViX3VpbnQ2NF90IGVsYXBzZWRfdGltZTsKPiArICBncnViX3VpbnQ4X3QgYWxs b2NfdHlwZVtNQVhfQUNUSVZFX0xPR1NdOwo+ICsgIGdydWJfdWludDhfdCBzaXRfbmF0X3ZlcnNp b25fYml0bWFwWzM5MDBdOwo+ICsgIGdydWJfdWludDMyX3QgY2hlY2tzdW07Cj4gK30gR1JVQl9Q QUNLRUQ7Cj4gKwo+ICtzdHJ1Y3QgZ3J1Yl9mMmZzX25hdF9lbnRyeSB7Cj4gKyAgZ3J1Yl91aW50 OF90IHZlcnNpb247Cj4gKyAgZ3J1Yl91aW50MzJfdCBpbm87Cj4gKyAgZ3J1Yl91aW50MzJfdCBi bG9ja19hZGRyOwo+ICt9IEdSVUJfUEFDS0VEOwo+ICsKPiArc3RydWN0IGdydWJfZjJmc19uYXRf amVudAo+ICt7Cj4gKyAgZ3J1Yl91aW50MzJfdCBuaWQ7Cj4gKyAgc3RydWN0IGdydWJfZjJmc19u YXRfZW50cnkgbmU7Cj4gK30gR1JVQl9QQUNLRUQ7Cj4gKwo+ICtzdHJ1Y3QgZ3J1Yl9mMmZzX25h dF9qb3VybmFsIHsKPiArICBncnViX3VpbnQxNl90IG5fbmF0czsKPiArICBzdHJ1Y3QgZ3J1Yl9m MmZzX25hdF9qZW50IGVudHJpZXNbTkFUX0pPVVJOQUxfRU5UUklFU107Cj4gKyAgZ3J1Yl91aW50 OF90IHJlc2VydmVkW05BVF9KT1VSTkFMX1JFU0VSVkVEXTsKPiArfSBHUlVCX1BBQ0tFRDsKPiAr Cj4gK3N0cnVjdCBncnViX2YyZnNfbmF0X2Jsb2NrIHsKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX25h dF9lbnRyeSBuZVtOQVRfRU5UUllfUEVSX0JMT0NLXTsKPiArfSBHUlVCX1BBQ0tFRDsKPiArCj4g K3N0cnVjdCBncnViX2YyZnNfZGlyX2VudHJ5Cj4gK3sKPiArICBncnViX3VpbnQzMl90IGhhc2hf Y29kZTsKPiArICBncnViX3VpbnQzMl90IGlubzsKPiArICBncnViX3VpbnQxNl90IG5hbWVfbGVu Owo+ICsgIGdydWJfdWludDhfdCBmaWxlX3R5cGU7Cj4gK30gR1JVQl9QQUNLRUQ7Cj4gKwo+ICtz dHJ1Y3QgZ3J1Yl9mMmZzX2lubGluZV9kZW50cnkKPiArewo+ICsgIGdydWJfdWludDhfdCBkZW50 cnlfYml0bWFwW0lOTElORV9ERU5UUllfQklUTUFQX1NJWkVdOwo+ICsgIGdydWJfdWludDhfdCBy ZXNlcnZlZFtJTkxJTkVfUkVTRVJWRURfU0laRV07Cj4gKyAgc3RydWN0IGdydWJfZjJmc19kaXJf ZW50cnkgZGVudHJ5W05SX0lOTElORV9ERU5UUlldOwo+ICsgIGdydWJfdWludDhfdCBmaWxlbmFt ZVtOUl9JTkxJTkVfREVOVFJZXVtGMkZTX1NMT1RfTEVOXTsKPiArfSBHUlVCX1BBQ0tFRDsKPiAr Cj4gK3N0cnVjdCBncnViX2YyZnNfZGVudHJ5X2Jsb2NrIHsKPiArICBncnViX3VpbnQ4X3QgZGVu dHJ5X2JpdG1hcFtTSVpFX09GX0RFTlRSWV9CSVRNQVBdOwo+ICsgIGdydWJfdWludDhfdCByZXNl cnZlZFtTSVpFX09GX1JFU0VSVkVEXTsKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2Rpcl9lbnRyeSBk ZW50cnlbTlJfREVOVFJZX0lOX0JMT0NLXTsKPiArICBncnViX3VpbnQ4X3QgZmlsZW5hbWVbTlJf REVOVFJZX0lOX0JMT0NLXVtGMkZTX1NMT1RfTEVOXTsKPiArfSBHUlVCX1BBQ0tFRDsKPiArCj4g K3N0cnVjdCBncnViX2YyZnNfaW5vZGUKPiArewo+ICsgIGdydWJfdWludDE2X3QgaV9tb2RlOwo+ ICsgIGdydWJfdWludDhfdCBpX2FkdmlzZTsKPiArICBncnViX3VpbnQ4X3QgaV9pbmxpbmU7Cj4g KyAgZ3J1Yl91aW50MzJfdCBpX3VpZDsKPiArICBncnViX3VpbnQzMl90IGlfZ2lkOwo+ICsgIGdy dWJfdWludDMyX3QgaV9saW5rczsKPiArICBncnViX3VpbnQ2NF90IGlfc2l6ZTsKPiArICBncnVi X3VpbnQ2NF90IGlfYmxvY2tzOwo+ICsgIGdydWJfdWludDY0X3QgaV9hdGltZTsKPiArICBncnVi X3VpbnQ2NF90IGlfY3RpbWU7Cj4gKyAgZ3J1Yl91aW50NjRfdCBpX210aW1lOwo+ICsgIGdydWJf dWludDMyX3QgaV9hdGltZV9uc2VjOwo+ICsgIGdydWJfdWludDMyX3QgaV9jdGltZV9uc2VjOwo+ ICsgIGdydWJfdWludDMyX3QgaV9tdGltZV9uc2VjOwo+ICsgIGdydWJfdWludDMyX3QgaV9nZW5l cmF0aW9uOwo+ICsgIGdydWJfdWludDMyX3QgaV9jdXJyZW50X2RlcHRoOwo+ICsgIGdydWJfdWlu dDMyX3QgaV94YXR0cl9uaWQ7Cj4gKyAgZ3J1Yl91aW50MzJfdCBpX2ZsYWdzOwo+ICsgIGdydWJf dWludDMyX3QgaV9waW5vOwo+ICsgIGdydWJfdWludDMyX3QgaV9uYW1lbGVuOwo+ICsgIGdydWJf dWludDhfdCBpX25hbWVbRjJGU19OQU1FX0xFTl07Cj4gKyAgZ3J1Yl91aW50OF90IGlfZGlyX2xl dmVsOwo+ICsgIGdydWJfdWludDhfdCBpX2V4dFsxMl07Cj4gKyAgZ3J1Yl91aW50MzJfdCBpX2Fk ZHJbREVGX0FERFJTX1BFUl9JTk9ERV07Cj4gKyAgZ3J1Yl91aW50MzJfdCBpX25pZFs1XTsKPiAr fSBHUlVCX1BBQ0tFRDsKPiArCj4gK3N0cnVjdCBncnViX2RpcmVjdF9ub2RlIHsKPiArICBncnVi X3VpbnQzMl90IGFkZHJbQUREUlNfUEVSX0JMT0NLXTsKPiArfSBHUlVCX1BBQ0tFRDsKPiArCj4g K3N0cnVjdCBncnViX2luZGlyZWN0X25vZGUgewo+ICsgIGdydWJfdWludDMyX3QgbmlkW05JRFNf UEVSX0JMT0NLXTsKPiArfSBHUlVCX1BBQ0tFRDsKPiArCj4gK3N0cnVjdCBncnViX2YyZnNfbm9k ZQo+ICt7Cj4gKyAgdW5pb24KPiArICB7Cj4gKyAgICBzdHJ1Y3QgZ3J1Yl9mMmZzX2lub2RlIGk7 Cj4gKyAgICBzdHJ1Y3QgZ3J1Yl9kaXJlY3Rfbm9kZSBkbjsKPiArICAgIHN0cnVjdCBncnViX2lu ZGlyZWN0X25vZGUgaW47Cj4gKyAgICBjaGFyIGJ1ZltGMkZTX0JMS1NJWkUgLSA0MF07CS8qIFNo b3VsZCBvY2N1cHkgRjJGU19CTEtTSVpFIHRvdGFsbHkgKi8KPiArICB9Owo+ICsgIGdydWJfdWlu dDhfdCBkdW1teVs0MF07Cj4gK30gR1JVQl9QQUNLRUQ7Cj4gKwo+ICtzdHJ1Y3QgZ3J1Yl9mc2hl bHBfbm9kZQo+ICt7Cj4gKyAgc3RydWN0IGdydWJfZjJmc19kYXRhICpkYXRhOwo+ICsgIHN0cnVj dCBncnViX2YyZnNfbm9kZSBpbm9kZTsKPiArICBncnViX3VpbnQzMl90IGlubzsKPiArICBpbnQg aW5vZGVfcmVhZDsKPiArfTsKPiArCj4gK3N0cnVjdCBncnViX2YyZnNfZGF0YQo+ICt7Cj4gKyAg c3RydWN0IGdydWJfZjJmc19zdXBlcmJsb2NrIHNibG9jazsKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZz X2NoZWNrcG9pbnQgY2twdDsKPiArCj4gKyAgZ3J1Yl91aW50MzJfdCByb290X2lubzsKPiArICBn cnViX3VpbnQzMl90IGJsb2Nrc19wZXJfc2VnOwo+ICsgIGdydWJfdWludDMyX3QgY3BfYmxrYWRk cjsKPiArICBncnViX3VpbnQzMl90IG5hdF9ibGthZGRyOwo+ICsKPiArICBzdHJ1Y3QgZ3J1Yl9m MmZzX25hdF9qb3VybmFsIG5hdF9qOwo+ICsgIGNoYXIgKm5hdF9iaXRtYXA7Cj4gKwo+ICsgIGdy dWJfZGlza190IGRpc2s7Cj4gKyAgc3RydWN0IGdydWJfZjJmc19ub2RlICppbm9kZTsKPiArICBz dHJ1Y3QgZ3J1Yl9mc2hlbHBfbm9kZSBkaXJvcGVuOwo+ICt9Owo+ICsKPiArc3RydWN0IGdydWJf ZjJmc19kaXJfaXRlcl9jdHgKPiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0YTsK PiArICBncnViX2ZzaGVscF9pdGVyYXRlX2Rpcl9ob29rX3QgaG9vazsKPiArICB2b2lkICpob29r X2RhdGE7Cj4gKyAgZ3J1Yl91aW50OF90ICpiaXRtYXA7Cj4gKyAgZ3J1Yl91aW50OF90ICgqZmls ZW5hbWUpW0YyRlNfU0xPVF9MRU5dOwo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGlyX2VudHJ5ICpk ZW50cnk7Cj4gKyAgaW50IG1heDsKPiArfTsKPiArCj4gK3N0cnVjdCBncnViX2YyZnNfZGlyX2N0 eAo+ICt7Cj4gKyAgZ3J1Yl9mc19kaXJfaG9va190IGhvb2s7Cj4gKyAgdm9pZCAqaG9va19kYXRh Owo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0YTsKPiArfTsKPiArCj4gK3N0YXRpYyBn cnViX2RsX3QgbXlfbW9kOwo+ICsKPiArc3RhdGljIGlubGluZSBpbnQKPiArZ3J1Yl9mMmZzX3Rl c3RfYml0X2xlIChpbnQgbnIsIGNvbnN0IGdydWJfdWludDhfdCAqYWRkcikKPiArewo+ICsgIHJl dHVybiBhZGRyW25yID4+IDNdICYgKDEgPDwgKG5yICYgNykpOwo+ICt9Cj4gKwo+ICtzdGF0aWMg aW5saW5lIGNoYXIgKgo+ICtfX2lubGluZV9hZGRyIChzdHJ1Y3QgZ3J1Yl9mMmZzX2lub2RlICpp bm9kZSkKPiArewo+ICsgIHJldHVybiAoY2hhciAqKSZpbm9kZS0+aV9hZGRyWzFdOwo+ICt9Cj4g Kwo+ICtzdGF0aWMgaW5saW5lIGdydWJfdWludDY0X3QKPiArZ3J1Yl9mMmZzX2ZpbGVfc2l6ZSAo c3RydWN0IGdydWJfZjJmc19pbm9kZSAqaW5vZGUpCj4gK3sKPiArICByZXR1cm4gZ3J1Yl9sZV90 b19jcHU2NCAoaW5vZGUtPmlfc2l6ZSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgZ3J1Yl91 aW50MzJfdAo+ICtfX3N0YXJ0X2NwX2FkZHIgKHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0YSkK PiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfY2hlY2twb2ludCAqY2twdCA9ICZkYXRhLT5ja3B0 Owo+ICsgIGdydWJfdWludDMyX3Qgc3RhcnRfYWRkciA9IGRhdGEtPmNwX2Jsa2FkZHI7Cj4gKwo+ ICsgIGlmICghKGNrcHQtPmNoZWNrcG9pbnRfdmVyICYgZ3J1Yl9jcHVfdG9fbGU2NF9jb21waWxl X3RpbWUoMSkpKQo+ICsgICAgcmV0dXJuIHN0YXJ0X2FkZHIgKyBkYXRhLT5ibG9ja3NfcGVyX3Nl ZzsKPiArICByZXR1cm4gc3RhcnRfYWRkcjsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBncnVi X3VpbnQzMl90Cj4gK19fc3RhcnRfc3VtX2Jsb2NrIChzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRh dGEpCj4gK3sKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2NoZWNrcG9pbnQgKmNrcHQgPSAmZGF0YS0+ Y2twdDsKPiArCj4gKyAgcmV0dXJuIF9fc3RhcnRfY3BfYWRkciAoZGF0YSkgKyBncnViX2xlX3Rv X2NwdTMyIChja3B0LT5jcF9wYWNrX3N0YXJ0X3N1bSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxp bmUgZ3J1Yl91aW50MzJfdAo+ICtfX3N1bV9ibGtfYWRkciAoc3RydWN0IGdydWJfZjJmc19kYXRh ICpkYXRhLCBpbnQgYmFzZSwgaW50IHR5cGUpCj4gK3sKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2No ZWNrcG9pbnQgKmNrcHQgPSAmZGF0YS0+Y2twdDsKPiArCj4gKyAgcmV0dXJuIF9fc3RhcnRfY3Bf YWRkciAoZGF0YSkgKwo+ICsJZ3J1Yl9sZV90b19jcHUzMiAoY2twdC0+Y3BfcGFja190b3RhbF9i bG9ja19jb3VudCkKPiArCS0gKGJhc2UgKyAxKSArIHR5cGU7Cj4gK30KPiArCj4gK3N0YXRpYyBp bmxpbmUgdm9pZCAqCj4gK19fbmF0X2JpdG1hcF9wdHIgKHN0cnVjdCBncnViX2YyZnNfZGF0YSAq ZGF0YSkKPiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfY2hlY2twb2ludCAqY2twdCA9ICZkYXRh LT5ja3B0Owo+ICsgIGdydWJfdWludDMyX3Qgb2Zmc2V0Owo+ICsKPiArICBpZiAoZ3J1Yl9sZV90 b19jcHUzMiAoZGF0YS0+c2Jsb2NrLmNwX3BheWxvYWQpID4gMCkKPiArICAgIHJldHVybiBja3B0 LT5zaXRfbmF0X3ZlcnNpb25fYml0bWFwOwo+ICsKPiArICBvZmZzZXQgPSBncnViX2xlX3RvX2Nw dTMyIChja3B0LT5zaXRfdmVyX2JpdG1hcF9ieXRlc2l6ZSk7Cj4gKyAgcmV0dXJuIGNrcHQtPnNp dF9uYXRfdmVyc2lvbl9iaXRtYXAgKyBvZmZzZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUg Z3J1Yl91aW50MzJfdAo+ICtfX2dldF9ub2RlX2lkIChzdHJ1Y3QgZ3J1Yl9mMmZzX25vZGUgKnJu LCBpbnQgb2ZmLCBpbnQgaW5vZGVfYmxvY2spCj4gK3sKPiArICBpZiAoaW5vZGVfYmxvY2spCj4g KyAgICByZXR1cm4gZ3J1Yl9sZV90b19jcHUzMiAocm4tPmkuaV9uaWRbb2ZmIC0gTk9ERV9ESVIx X0JMT0NLXSk7Cj4gKyAgcmV0dXJuIGdydWJfbGVfdG9fY3B1MzIgKHJuLT5pbi5uaWRbb2ZmXSk7 Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgZ3J1Yl9lcnJfdAo+ICtncnViX2YyZnNfYmxvY2tf cmVhZCAoc3RydWN0IGdydWJfZjJmc19kYXRhICpkYXRhLCBncnViX3VpbnQzMl90IGJsa2FkZHIs IHZvaWQgKmJ1ZikKPiArewo+ICsgIHJldHVybiBncnViX2Rpc2tfcmVhZCAoZGF0YS0+ZGlzaywK PiArCQkoKGdydWJfZGlza19hZGRyX3QpYmxrYWRkcikgPDwgRjJGU19CTEtfU0VDX0JJVFMsCj4g KwkJMCwgRjJGU19CTEtTSVpFLCBidWYpOwo+ICt9Cj4gKwo+ICsvKgo+ICsgKiBDUkMzMgo+ICsq Lwo+ICsjZGVmaW5lIENSQ1BPTFlfTEUgMHhlZGI4ODMyMAo+ICsKPiArc3RhdGljIGlubGluZSBn cnViX3VpbnQzMl90Cj4gK2dydWJfZjJmc19jYWxfY3JjMzIgKGNvbnN0IHZvaWQgKmJ1ZiwgY29u c3QgZ3J1Yl91aW50MzJfdCBsZW4pCj4gK3sKPiArICBncnViX3VpbnQzMl90IGNyYyA9IEYyRlNf U1VQRVJfTUFHSUM7Cj4gKyAgdW5zaWduZWQgY2hhciAqcCA9ICh1bnNpZ25lZCBjaGFyICopYnVm Owo+ICsgIGdydWJfdWludDMyX3QgdG1wID0gbGVuOwo+ICsgIGludCBpOwo+ICsKPiArICB3aGls ZSAodG1wLS0pCj4gKyAgICB7Cj4gKyAgICAgIGNyYyBePSAqcCsrOwo+ICsgICAgICBmb3IgKGkg PSAwOyBpIDwgODsgaSsrKQo+ICsgICAgICAgIGNyYyA9IChjcmMgPj4gMSkgXiAoKGNyYyAmIDEp ID8gQ1JDUE9MWV9MRSA6IDApOwo+ICsgICAgfQo+ICsgIHJldHVybiBjcmM7Cj4gK30KPiArCj4g K3N0YXRpYyBpbmxpbmUgaW50Cj4gK2dydWJfZjJmc19jcmNfdmFsaWQgKGdydWJfdWludDMyX3Qg YmxrX2NyYywgdm9pZCAqYnVmLCBjb25zdCBncnViX3VpbnQzMl90IGxlbikKPiArewo+ICsgIGdy dWJfdWludDMyX3QgY2FsX2NyYyA9IDA7Cj4gKwo+ICsgIGNhbF9jcmMgPSBncnViX2YyZnNfY2Fs X2NyYzMyIChidWYsIGxlbik7Cj4gKwo+ICsgIHJldHVybiAoY2FsX2NyYyA9PSBibGtfY3JjKSA/ IDEgOiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGludAo+ICtncnViX2YyZnNfdGVzdF9i aXQgKGdydWJfdWludDMyX3QgbnIsIGNvbnN0IGNoYXIgKnApCj4gK3sKPiArICBpbnQgbWFzazsK PiArCj4gKyAgcCArPSAobnIgPj4gMyk7Cj4gKyAgbWFzayA9IDEgPDwgKDcgLSAobnIgJiAweDA3 KSk7Cj4gKyAgcmV0dXJuIG1hc2sgJiAqcDsKPiArfQo+ICsKPiArc3RhdGljIGludAo+ICtncnVi X2YyZnNfc2FuaXR5X2NoZWNrX3NiIChzdHJ1Y3QgZ3J1Yl9mMmZzX3N1cGVyYmxvY2sgKnNiKQo+ ICt7Cj4gKyAgZ3J1Yl91aW50MzJfdCBsb2dfc2VjdG9yc2l6ZSwgbG9nX3NlY3RvcnNfcGVyX2Js b2NrOwo+ICsKPiArICBpZiAoc2ItPm1hZ2ljICE9IGdydWJfY3B1X3RvX2xlMzJfY29tcGlsZV90 aW1lIChGMkZTX1NVUEVSX01BR0lDKSkKPiArICAgIHJldHVybiAtMTsKPiArCj4gKyAgaWYgKHNi LT5sb2dfYmxvY2tzaXplICE9IGdydWJfY3B1X3RvX2xlMzJfY29tcGlsZV90aW1lIChGMkZTX0JM S19CSVRTKSkKPiArICAgIHJldHVybiAtMTsKPiArCj4gKyAgbG9nX3NlY3RvcnNpemUgPSBncnVi X2xlX3RvX2NwdTMyIChzYi0+bG9nX3NlY3RvcnNpemUpOwo+ICsgIGxvZ19zZWN0b3JzX3Blcl9i bG9jayA9IGdydWJfbGVfdG9fY3B1MzIgKHNiLT5sb2dfc2VjdG9yc19wZXJfYmxvY2spOwo+ICsK PiArICBpZiAobG9nX3NlY3RvcnNpemUgPiBGMkZTX0JMS19CSVRTKQo+ICsgICAgcmV0dXJuIC0x Owo+ICsKPiArICBpZiAobG9nX3NlY3RvcnNpemUgPCBGMkZTX01JTl9MT0dfU0VDVE9SX1NJWkUp Cj4gKyAgICByZXR1cm4gLTE7Cj4gKwo+ICsgIGlmIChsb2dfc2VjdG9yc19wZXJfYmxvY2sgKyBs b2dfc2VjdG9yc2l6ZSAhPSBGMkZTX0JMS19CSVRTKQo+ICsgICAgcmV0dXJuIC0xOwo+ICsKPiAr ICByZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludAo+ICtncnViX2YyZnNfcmVhZF9zYiAo c3RydWN0IGdydWJfZjJmc19kYXRhICpkYXRhLCBncnViX2Rpc2tfYWRkcl90IG9mZnNldCkKPiAr ewo+ICsgIGdydWJfZGlza190IGRpc2sgPSBkYXRhLT5kaXNrOwo+ICsgIGdydWJfZXJyX3QgZXJy Owo+ICsKPiArICAvKiBSZWFkIGZpcnN0IHN1cGVyIGJsb2NrLiAqLwo+ICsgIGVyciA9IGdydWJf ZGlza19yZWFkIChkaXNrLCBvZmZzZXQsIDAsIHNpemVvZiAoZGF0YS0+c2Jsb2NrKSwgJmRhdGEt PnNibG9jayk7Cj4gKyAgaWYgKGVycikKPiArICAgIHJldHVybiAtMTsKPiArCj4gKyAgcmV0dXJu IGdydWJfZjJmc19zYW5pdHlfY2hlY2tfc2IgKCZkYXRhLT5zYmxvY2spOwo+ICt9Cj4gKwo+ICtz dGF0aWMgdm9pZCAqCj4gK3ZhbGlkYXRlX2NoZWNrcG9pbnQgKHN0cnVjdCBncnViX2YyZnNfZGF0 YSAqZGF0YSwgZ3J1Yl91aW50MzJfdCBjcF9hZGRyLAo+ICsJZ3J1Yl91aW50NjRfdCAqdmVyc2lv bikKPiArewo+ICsgIGdydWJfdWludDMyX3QgKmNwX3BhZ2VfMSwgKmNwX3BhZ2VfMjsKPiArICBz dHJ1Y3QgZ3J1Yl9mMmZzX2NoZWNrcG9pbnQgKmNwX2Jsb2NrOwo+ICsgIGdydWJfdWludDY0X3Qg Y3VyX3ZlcnNpb24gPSAwLCBwcmVfdmVyc2lvbiA9IDA7Cj4gKyAgZ3J1Yl91aW50MzJfdCBjcmMg PSAwOwo+ICsgIGdydWJfdWludDMyX3QgY3JjX29mZnNldDsKPiArICBncnViX2Vycl90IGVycjsK PiArCj4gKyAgLyogUmVhZCB0aGUgMXN0IGNwIGJsb2NrIGluIHRoaXMgQ1AgcGFjayAqLwo+ICsg IGNwX3BhZ2VfMSA9IGdydWJfbWFsbG9jIChGMkZTX0JMS1NJWkUpOwo+ICsgIGlmICghY3BfcGFn ZV8xKQo+ICsgICAgcmV0dXJuIE5VTEw7Cj4gKwo+ICsgIGVyciA9IGdydWJfZjJmc19ibG9ja19y ZWFkIChkYXRhLCBjcF9hZGRyLCBjcF9wYWdlXzEpOwo+ICsgIGlmIChlcnIpCj4gKyAgICBnb3Rv IGludmFsaWRfY3AxOwo+ICsKPiArICBjcF9ibG9jayA9IChzdHJ1Y3QgZ3J1Yl9mMmZzX2NoZWNr cG9pbnQgKiljcF9wYWdlXzE7Cj4gKyAgY3JjX29mZnNldCA9IGdydWJfbGVfdG9fY3B1MzIgKGNw X2Jsb2NrLT5jaGVja3N1bV9vZmZzZXQpOwo+ICsgIGlmIChjcmNfb2Zmc2V0ICE9IENIRUNLU1VN X09GRlNFVCkKPiArICAgIGdvdG8gaW52YWxpZF9jcDE7Cj4gKwo+ICsgIGNyYyA9IGdydWJfbGVf dG9fY3B1MzIgKCooY3BfcGFnZV8xICsgVTMyX0NIRUNLU1VNX09GRlNFVCkpOwo+ICsgIGlmICgh Z3J1Yl9mMmZzX2NyY192YWxpZCAoY3JjLCBjcF9ibG9jaywgY3JjX29mZnNldCkpCj4gKyAgICBn b3RvIGludmFsaWRfY3AxOwo+ICsKPiArICBwcmVfdmVyc2lvbiA9IGdydWJfbGVfdG9fY3B1NjQg KGNwX2Jsb2NrLT5jaGVja3BvaW50X3Zlcik7Cj4gKwo+ICsgIC8qIFJlYWQgdGhlIDJuZCBjcCBi bG9jayBpbiB0aGlzIENQIHBhY2sgKi8KPiArICBjcF9wYWdlXzIgPSBncnViX21hbGxvYyAoRjJG U19CTEtTSVpFKTsKPiArICBpZiAoIWNwX3BhZ2VfMikKPiArICAgIGdvdG8gaW52YWxpZF9jcDE7 Cj4gKwo+ICsgIGNwX2FkZHIgKz0gZ3J1Yl9sZV90b19jcHUzMiAoY3BfYmxvY2stPmNwX3BhY2tf dG90YWxfYmxvY2tfY291bnQpIC0gMTsKPiArCj4gKyAgZXJyID0gZ3J1Yl9mMmZzX2Jsb2NrX3Jl YWQgKGRhdGEsIGNwX2FkZHIsIGNwX3BhZ2VfMik7Cj4gKyAgaWYgKGVycikKPiArICAgIGdvdG8g aW52YWxpZF9jcDI7Cj4gKwo+ICsgIGNwX2Jsb2NrID0gKHN0cnVjdCBncnViX2YyZnNfY2hlY2tw b2ludCAqKWNwX3BhZ2VfMjsKPiArICBjcmNfb2Zmc2V0ID0gZ3J1Yl9sZV90b19jcHUzMiAoY3Bf YmxvY2stPmNoZWNrc3VtX29mZnNldCk7Cj4gKyAgaWYgKGNyY19vZmZzZXQgIT0gQ0hFQ0tTVU1f T0ZGU0VUKQo+ICsgICAgZ290byBpbnZhbGlkX2NwMjsKPiArCj4gKyAgY3JjID0gZ3J1Yl9sZV90 b19jcHUzMiAoKihjcF9wYWdlXzIgKyBVMzJfQ0hFQ0tTVU1fT0ZGU0VUKSk7Cj4gKyAgaWYgKCFn cnViX2YyZnNfY3JjX3ZhbGlkIChjcmMsIGNwX2Jsb2NrLCBjcmNfb2Zmc2V0KSkKPiArICAgIGdv dG8gaW52YWxpZF9jcDI7Cj4gKwo+ICsgIGN1cl92ZXJzaW9uID0gZ3J1Yl9sZV90b19jcHU2NCAo Y3BfYmxvY2stPmNoZWNrcG9pbnRfdmVyKTsKPiArICBpZiAoY3VyX3ZlcnNpb24gPT0gcHJlX3Zl cnNpb24pCj4gKyAgICB7Cj4gKyAgICAgICp2ZXJzaW9uID0gY3VyX3ZlcnNpb247Cj4gKyAgICAg IGdydWJfZnJlZSAoY3BfcGFnZV8yKTsKPiArICAgICAgcmV0dXJuIGNwX3BhZ2VfMTsKPiArICAg IH0KPiArCj4gK2ludmFsaWRfY3AyOgo+ICsgIGdydWJfZnJlZSAoY3BfcGFnZV8yKTsKPiAraW52 YWxpZF9jcDE6Cj4gKyAgZ3J1Yl9mcmVlIChjcF9wYWdlXzEpOwo+ICsgIHJldHVybiBOVUxMOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgZ3J1Yl9lcnJfdAo+ICtncnViX2YyZnNfcmVhZF9jcCAoc3RydWN0 IGdydWJfZjJmc19kYXRhICpkYXRhKQo+ICt7Cj4gKyAgdm9pZCAqY3AxLCAqY3AyLCAqY3VyX3Bh Z2U7Cj4gKyAgZ3J1Yl91aW50NjRfdCBjcDFfdmVyc2lvbiA9IDAsIGNwMl92ZXJzaW9uID0gMDsK PiArICBncnViX3VpbnQ2NF90IGNwX3N0YXJ0X2Jsa19ubzsKPiArCj4gKyAgLyoKPiArICAgKiBG aW5kaW5nIG91dCB2YWxpZCBjcCBibG9jayBpbnZvbHZlcyByZWFkIGJvdGgKPiArICAgKiBzZXRz IChjcCBwYWNrMSBhbmQgY3AgcGFjayAyKQo+ICsgICAqLwo+ICsgIGNwX3N0YXJ0X2Jsa19ubyA9 IGRhdGEtPmNwX2Jsa2FkZHI7Cj4gKyAgY3AxID0gdmFsaWRhdGVfY2hlY2twb2ludCAoZGF0YSwg Y3Bfc3RhcnRfYmxrX25vLCAmY3AxX3ZlcnNpb24pOwo+ICsgIGlmICghY3AxICYmIGdydWJfZXJy bm8pCj4gKyAgICByZXR1cm4gZ3J1Yl9lcnJubzsKPiArCj4gKyAgLyogVGhlIHNlY29uZCBjaGVj a3BvaW50IHBhY2sgc2hvdWxkIHN0YXJ0IGF0IHRoZSBuZXh0IHNlZ21lbnQgKi8KPiArICBjcF9z dGFydF9ibGtfbm8gKz0gZGF0YS0+YmxvY2tzX3Blcl9zZWc7Cj4gKyAgY3AyID0gdmFsaWRhdGVf Y2hlY2twb2ludCAoZGF0YSwgY3Bfc3RhcnRfYmxrX25vLCAmY3AyX3ZlcnNpb24pOwo+ICsgIGlm ICghY3AyICYmIGdydWJfZXJybm8pCj4gKyAgICB7Cj4gKyAgICAgIGdydWJfZnJlZSAoY3AxKTsK PiArICAgICAgcmV0dXJuIGdydWJfZXJybm87Cj4gKyAgICB9Cj4gKwo+ICsgIGlmIChjcDEgJiYg Y3AyKQo+ICsgICAgY3VyX3BhZ2UgPSAoY3AyX3ZlcnNpb24gPiBjcDFfdmVyc2lvbikgPyBjcDIg OiBjcDE7Cj4gKyAgZWxzZSBpZiAoY3AxKQo+ICsgICAgY3VyX3BhZ2UgPSBjcDE7Cj4gKyAgZWxz ZSBpZiAoY3AyKQo+ICsgICAgY3VyX3BhZ2UgPSBjcDI7Cj4gKyAgZWxzZQo+ICsgICAgcmV0dXJu IGdydWJfZXJyb3IgKEdSVUJfRVJSX0JBRF9GUywgIm5vIGNoZWNrcG9pbnRzIik7Cj4gKwo+ICsg IGdydWJfbWVtY3B5ICgmZGF0YS0+Y2twdCwgY3VyX3BhZ2UsIEYyRlNfQkxLU0laRSk7Cj4gKwo+ ICsgIGdydWJfZnJlZSAoY3AxKTsKPiArICBncnViX2ZyZWUgKGNwMik7Cj4gKyAgcmV0dXJuIDA7 Cj4gK30KPiArCj4gK3N0YXRpYyBncnViX2Vycl90Cj4gK2dldF9uYXRfam91cm5hbCAoc3RydWN0 IGdydWJfZjJmc19kYXRhICpkYXRhKQo+ICt7Cj4gKyAgZ3J1Yl91aW50MzJfdCBibG9jazsKPiAr ICBjaGFyICpidWY7Cj4gKyAgZ3J1Yl9lcnJfdCBlcnI7Cj4gKwo+ICsgIGJ1ZiA9IGdydWJfbWFs bG9jIChGMkZTX0JMS1NJWkUpOwo+ICsgIGlmICghYnVmKQo+ICsgICAgcmV0dXJuIGdydWJfZXJy bm87Cj4gKwo+ICsgIGlmIChDS1BUX0ZMQUdfU0VUKCZkYXRhLT5ja3B0LCBDUF9DT01QQUNUX1NV TV9GTEFHKSkKPiArICAgIGJsb2NrID0gX19zdGFydF9zdW1fYmxvY2sgKGRhdGEpOwo+ICsgIGVs c2UgaWYgKENLUFRfRkxBR19TRVQgKCZkYXRhLT5ja3B0LCBDUF9VTU9VTlRfRkxBRykpCj4gKyAg ICBibG9jayA9IF9fc3VtX2Jsa19hZGRyIChkYXRhLCBOUl9DVVJTRUdfVFlQRSwgQ1VSU0VHX0hP VF9EQVRBKTsKPiArICBlbHNlCj4gKyAgICBibG9jayA9IF9fc3VtX2Jsa19hZGRyIChkYXRhLCBO Ul9DVVJTRUdfREFUQV9UWVBFLCBDVVJTRUdfSE9UX0RBVEEpOwo+ICsKPiArICBlcnIgPSBncnVi X2YyZnNfYmxvY2tfcmVhZCAoZGF0YSwgYmxvY2ssIGJ1Zik7Cj4gKyAgaWYgKGVycikKPiArICAg IGdvdG8gZmFpbDsKPiArCj4gKyAgaWYgKENLUFRfRkxBR19TRVQgKCZkYXRhLT5ja3B0LCBDUF9D T01QQUNUX1NVTV9GTEFHKSkKPiArICAgIGdydWJfbWVtY3B5ICgmZGF0YS0+bmF0X2osIGJ1Ziwg U1VNX0pPVVJOQUxfU0laRSk7Cj4gKyAgZWxzZQo+ICsgICAgZ3J1Yl9tZW1jcHkgKCZkYXRhLT5u YXRfaiwgYnVmICsgU1VNX0VOVFJJRVNfU0laRSwgU1VNX0pPVVJOQUxfU0laRSk7Cj4gKwo+ICtm YWlsOgo+ICsgIGdydWJfZnJlZSAoYnVmKTsKPiArICByZXR1cm4gZXJyOwo+ICt9Cj4gKwo+ICtz dGF0aWMgZ3J1Yl91aW50MzJfdAo+ICtnZXRfYmxrYWRkcl9mcm9tX25hdF9qb3VybmFsIChzdHJ1 Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGEsIGdydWJfdWludDMyX3QgbmlkKQo+ICt7Cj4gKyAgZ3J1 Yl91aW50MTZfdCBuID0gZ3J1Yl9sZV90b19jcHUxNiAoZGF0YS0+bmF0X2oubl9uYXRzKTsKPiAr ICBncnViX3VpbnQzMl90IGJsa2FkZHIgPSAwOwo+ICsgIGdydWJfdWludDE2X3QgaTsKPiArCj4g KyAgZm9yIChpID0gMDsgaSA8IG47IGkrKykKPiArICAgIHsKPiArICAgICAgaWYgKGdydWJfbGVf dG9fY3B1MzIgKGRhdGEtPm5hdF9qLmVudHJpZXNbaV0ubmlkKSA9PSBuaWQpCj4gKyAgICAgICAg ewo+ICsgICAgICAgICAgYmxrYWRkciA9IGdydWJfbGVfdG9fY3B1MzIgKGRhdGEtPm5hdF9qLmVu dHJpZXNbaV0ubmUuYmxvY2tfYWRkcik7Cj4gKyAgICAgICAgICBicmVhazsKPiArICAgICAgICB9 Cj4gKyAgICB9Cj4gKyAgcmV0dXJuIGJsa2FkZHI7Cj4gK30KPiArCj4gK3N0YXRpYyBncnViX3Vp bnQzMl90Cj4gK2dldF9ub2RlX2Jsa2FkZHIgKHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0YSwg Z3J1Yl91aW50MzJfdCBuaWQpCj4gK3sKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX25hdF9ibG9jayAq bmF0X2Jsb2NrOwo+ICsgIGdydWJfdWludDMyX3Qgc2VnX29mZiwgYmxvY2tfb2ZmLCBlbnRyeV9v ZmYsIGJsb2NrX2FkZHI7Cj4gKyAgZ3J1Yl91aW50MzJfdCBibGthZGRyOwo+ICsgIGdydWJfZXJy X3QgZXJyOwo+ICsKPiArICBibGthZGRyID0gZ2V0X2Jsa2FkZHJfZnJvbV9uYXRfam91cm5hbCAo ZGF0YSwgbmlkKTsKPiArICBpZiAoYmxrYWRkcikKPiArICAgIHJldHVybiBibGthZGRyOwo+ICsK PiArICBuYXRfYmxvY2sgPSBncnViX21hbGxvYyAoRjJGU19CTEtTSVpFKTsKPiArICBpZiAoIW5h dF9ibG9jaykKPiArICAgIHJldHVybiAwOwo+ICsKPiArICBibG9ja19vZmYgPSBuaWQgLyBOQVRf RU5UUllfUEVSX0JMT0NLOwo+ICsgIGVudHJ5X29mZiA9IG5pZCAlIE5BVF9FTlRSWV9QRVJfQkxP Q0s7Cj4gKwo+ICsgIHNlZ19vZmYgPSBibG9ja19vZmYgLyBkYXRhLT5ibG9ja3NfcGVyX3NlZzsK PiArICBibG9ja19hZGRyID0gZGF0YS0+bmF0X2Jsa2FkZHIgKwo+ICsJKChzZWdfb2ZmICogZGF0 YS0+YmxvY2tzX3Blcl9zZWcpIDw8IDEpICsKPiArCShibG9ja19vZmYgJiAoZGF0YS0+YmxvY2tz X3Blcl9zZWcgLSAxKSk7Cj4gKwo+ICsgIGlmIChncnViX2YyZnNfdGVzdF9iaXQgKGJsb2NrX29m ZiwgZGF0YS0+bmF0X2JpdG1hcCkpCj4gKyAgICBibG9ja19hZGRyICs9IGRhdGEtPmJsb2Nrc19w ZXJfc2VnOwo+ICsKPiArICBlcnIgPSBncnViX2YyZnNfYmxvY2tfcmVhZCAoZGF0YSwgYmxvY2tf YWRkciwgbmF0X2Jsb2NrKTsKPiArICBpZiAoZXJyKQo+ICsgICAgewo+ICsgICAgICBncnViX2Zy ZWUgKG5hdF9ibG9jayk7Cj4gKyAgICAgIHJldHVybiAwOwo+ICsgICAgfQo+ICsKPiArICBibGth ZGRyID0gZ3J1Yl9sZV90b19jcHUzMiAobmF0X2Jsb2NrLT5uZVtlbnRyeV9vZmZdLmJsb2NrX2Fk ZHIpOwo+ICsKPiArICBncnViX2ZyZWUgKG5hdF9ibG9jayk7Cj4gKwo+ICsgIHJldHVybiBibGth ZGRyOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50Cj4gK2dydWJfZ2V0X25vZGVfcGF0aCAoc3RydWN0 IGdydWJfZjJmc19pbm9kZSAqaW5vZGUsIGdydWJfdWludDMyX3QgYmxvY2ssCj4gKwlncnViX3Vp bnQzMl90IG9mZnNldFs0XSwgZ3J1Yl91aW50MzJfdCBub2Zmc2V0WzRdKQo+ICt7Cj4gKyAgZ3J1 Yl91aW50MzJfdCBkaXJlY3RfYmxrcyA9IEFERFJTX1BFUl9CTE9DSzsKPiArICBncnViX3VpbnQz Ml90IGRwdHJzX3Blcl9ibGsgPSBOSURTX1BFUl9CTE9DSzsKPiArICBncnViX3VpbnQzMl90IGlu ZGlyZWN0X2Jsa3MgPSBBRERSU19QRVJfQkxPQ0sgKiBOSURTX1BFUl9CTE9DSzsKPiArICBncnVi X3VpbnQzMl90IGRpbmRpcmVjdF9ibGtzID0gaW5kaXJlY3RfYmxrcyAqIE5JRFNfUEVSX0JMT0NL Owo+ICsgIGdydWJfdWludDMyX3QgZGlyZWN0X2luZGV4ID0gREVGX0FERFJTX1BFUl9JTk9ERTsK PiArICBpbnQgbiA9IDA7Cj4gKyAgaW50IGxldmVsID0gMDsKPiArCj4gKyAgaWYgKGlub2RlLT5p X2lubGluZSAmIEYyRlNfSU5MSU5FX1hBVFRSKQo+ICsgICAgZGlyZWN0X2luZGV4IC09IEYyRlNf SU5MSU5FX1hBVFRSX0FERFJTOwo+ICsKPiArICBub2Zmc2V0WzBdID0gMDsKPiArCj4gKyAgaWYg KGJsb2NrIDwgZGlyZWN0X2luZGV4KQo+ICsgICAgewo+ICsgICAgICBvZmZzZXRbbl0gPSBibG9j azsKPiArICAgICAgZ290byBnb3Q7Cj4gKyAgICB9Cj4gKwo+ICsgIGJsb2NrIC09IGRpcmVjdF9p bmRleDsKPiArICBpZiAoYmxvY2sgPCBkaXJlY3RfYmxrcykKPiArICAgIHsKPiArICAgICAgb2Zm c2V0W24rK10gPSBOT0RFX0RJUjFfQkxPQ0s7Cj4gKyAgICAgIG5vZmZzZXRbbl0gPSAxOwo+ICsg ICAgICBvZmZzZXRbbl0gPSBibG9jazsKPiArICAgICAgbGV2ZWwgPSAxOwo+ICsgICAgICBnb3Rv IGdvdDsKPiArICAgIH0KPiArCj4gKyAgYmxvY2sgLT0gZGlyZWN0X2Jsa3M7Cj4gKyAgaWYgKGJs b2NrIDwgZGlyZWN0X2Jsa3MpCj4gKyAgICB7Cj4gKyAgICAgIG9mZnNldFtuKytdID0gTk9ERV9E SVIyX0JMT0NLOwo+ICsgICAgICBub2Zmc2V0W25dID0gMjsKPiArICAgICAgb2Zmc2V0W25dID0g YmxvY2s7Cj4gKyAgICAgIGxldmVsID0gMTsKPiArICAgICAgZ290byBnb3Q7Cj4gKyAgICB9Cj4g Kwo+ICsgIGJsb2NrIC09IGRpcmVjdF9ibGtzOwo+ICsgIGlmIChibG9jayA8IGluZGlyZWN0X2Js a3MpCj4gKyAgICB7Cj4gKyAgICAgIG9mZnNldFtuKytdID0gTk9ERV9JTkQxX0JMT0NLOwo+ICsg ICAgICBub2Zmc2V0W25dID0gMzsKPiArICAgICAgb2Zmc2V0W24rK10gPSBibG9jayAvIGRpcmVj dF9ibGtzOwo+ICsgICAgICBub2Zmc2V0W25dID0gNCArIG9mZnNldFtuIC0gMV07Cj4gKyAgICAg IG9mZnNldFtuXSA9IGJsb2NrICUgZGlyZWN0X2Jsa3M7Cj4gKyAgICAgIGxldmVsID0gMjsKPiAr ICAgICAgZ290byBnb3Q7Cj4gKyAgICB9Cj4gKwo+ICsgIGJsb2NrIC09IGluZGlyZWN0X2Jsa3M7 Cj4gKyAgaWYgKGJsb2NrIDwgaW5kaXJlY3RfYmxrcykKPiArICAgIHsKPiArICAgICAgb2Zmc2V0 W24rK10gPSBOT0RFX0lORDJfQkxPQ0s7Cj4gKyAgICAgIG5vZmZzZXRbbl0gPSA0ICsgZHB0cnNf cGVyX2JsazsKPiArICAgICAgb2Zmc2V0W24rK10gPSBibG9jayAvIGRpcmVjdF9ibGtzOwo+ICsg ICAgICBub2Zmc2V0W25dID0gNSArIGRwdHJzX3Blcl9ibGsgKyBvZmZzZXRbbiAtIDFdOwo+ICsg ICAgICBvZmZzZXRbbl0gPSBibG9jayAlIGRpcmVjdF9ibGtzOwo+ICsgICAgICBsZXZlbCA9IDI7 Cj4gKyAgICAgIGdvdG8gZ290Owo+ICsgICAgfQo+ICsKPiArICBibG9jayAtPSBpbmRpcmVjdF9i bGtzOwo+ICsgIGlmIChibG9jayA8IGRpbmRpcmVjdF9ibGtzKQo+ICsgICAgewo+ICsgICAgICBv ZmZzZXRbbisrXSA9IE5PREVfRElORF9CTE9DSzsKPiArICAgICAgbm9mZnNldFtuXSA9IDUgKyAo ZHB0cnNfcGVyX2JsayAqIDIpOwo+ICsgICAgICBvZmZzZXRbbisrXSA9IGJsb2NrIC8gaW5kaXJl Y3RfYmxrczsKPiArICAgICAgbm9mZnNldFtuXSA9IDYgKyAoZHB0cnNfcGVyX2JsayAqIDIpICsK PiArICAgICAgb2Zmc2V0W24gLSAxXSAqIChkcHRyc19wZXJfYmxrICsgMSk7Cj4gKyAgICAgIG9m ZnNldFtuKytdID0gKGJsb2NrIC8gZGlyZWN0X2Jsa3MpICUgZHB0cnNfcGVyX2JsazsKPiArICAg ICAgbm9mZnNldFtuXSA9IDcgKyAoZHB0cnNfcGVyX2JsayAqIDIpICsKPiArCQlvZmZzZXRbbiAt IDJdICogKGRwdHJzX3Blcl9ibGsgKyAxKSArIG9mZnNldFtuIC0gMV07Cj4gKyAgICAgIG9mZnNl dFtuXSA9IGJsb2NrICUgZGlyZWN0X2Jsa3M7Cj4gKyAgICAgIGxldmVsID0gMzsKPiArICAgICAg Z290byBnb3Q7Cj4gKyAgICB9Cj4gK2dvdDoKPiArICByZXR1cm4gbGV2ZWw7Cj4gK30KPiArCj4g K3N0YXRpYyBncnViX2Vycl90Cj4gK2dydWJfZjJmc19yZWFkX25vZGUgKHN0cnVjdCBncnViX2Yy ZnNfZGF0YSAqZGF0YSwKPiArCWdydWJfdWludDMyX3QgbmlkLCBzdHJ1Y3QgZ3J1Yl9mMmZzX25v ZGUgKm5wKQo+ICt7Cj4gKyAgZ3J1Yl91aW50MzJfdCBibGthZGRyOwo+ICsKPiArICBibGthZGRy ID0gZ2V0X25vZGVfYmxrYWRkciAoZGF0YSwgbmlkKTsKPiArICBpZiAoIWJsa2FkZHIpCj4gKyAg ICByZXR1cm4gZ3J1Yl9lcnJubzsKPiArCj4gKyAgcmV0dXJuIGdydWJfZjJmc19ibG9ja19yZWFk IChkYXRhLCBibGthZGRyLCBucCk7Cj4gK30KPiArCj4gK3N0YXRpYyBzdHJ1Y3QgZ3J1Yl9mMmZz X2RhdGEgKgo+ICtncnViX2YyZnNfbW91bnQgKGdydWJfZGlza190IGRpc2spCj4gK3sKPiArICBz dHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGE7Cj4gKyAgZ3J1Yl9lcnJfdCBlcnI7Cj4gKwo+ICsg IGRhdGEgPSBncnViX21hbGxvYyAoc2l6ZW9mICgqZGF0YSkpOwo+ICsgIGlmICghZGF0YSkKPiAr ICAgIHJldHVybiBOVUxMOwo+ICsKPiArICBkYXRhLT5kaXNrID0gZGlzazsKPiArCj4gKyAgaWYg KGdydWJfZjJmc19yZWFkX3NiIChkYXRhLCBGMkZTX1NVUEVSX09GRlNFVDApKQo+ICsgICAgewo+ ICsgICAgICBpZiAoZ3J1Yl9mMmZzX3JlYWRfc2IgKGRhdGEsIEYyRlNfU1VQRVJfT0ZGU0VUMSkp Cj4gKyAgICAgICAgewo+ICsgICAgICAgICAgaWYgKGdydWJfZXJybm8gPT0gR1JVQl9FUlJfTk9O RSkKPiArICAgICAgICAgICAgZ3J1Yl9lcnJvciAoR1JVQl9FUlJfQkFEX0ZTLAo+ICsJCQkibm90 IGEgRjJGUyBmaWxlc3lzdGVtIChubyBzdXBlcmJsb2NrKSIpOwo+ICsgICAgICAgICAgZ290byBm YWlsOwo+ICsgICAgICAgIH0KPiArICAgIH0KPiArCj4gKyAgZGF0YS0+cm9vdF9pbm8gPSBncnVi X2xlX3RvX2NwdTMyIChkYXRhLT5zYmxvY2sucm9vdF9pbm8pOwo+ICsgIGRhdGEtPmNwX2Jsa2Fk ZHIgPSBncnViX2xlX3RvX2NwdTMyIChkYXRhLT5zYmxvY2suY3BfYmxrYWRkcik7Cj4gKyAgZGF0 YS0+bmF0X2Jsa2FkZHIgPSBncnViX2xlX3RvX2NwdTMyIChkYXRhLT5zYmxvY2submF0X2Jsa2Fk ZHIpOwo+ICsgIGRhdGEtPmJsb2Nrc19wZXJfc2VnID0gMSA8PAo+ICsJZ3J1Yl9sZV90b19jcHUz MiAoZGF0YS0+c2Jsb2NrLmxvZ19ibG9ja3NfcGVyX3NlZyk7Cj4gKwo+ICsgIGVyciA9IGdydWJf ZjJmc19yZWFkX2NwIChkYXRhKTsKPiArICBpZiAoZXJyKQo+ICsgICAgZ290byBmYWlsOwo+ICsK PiArICBkYXRhLT5uYXRfYml0bWFwID0gX19uYXRfYml0bWFwX3B0ciAoZGF0YSk7Cj4gKwo+ICsg IGVyciA9IGdldF9uYXRfam91cm5hbCAoZGF0YSk7Cj4gKyAgaWYgKGVycikKPiArICAgIGdvdG8g ZmFpbDsKPiArCj4gKyAgZGF0YS0+ZGlyb3Blbi5kYXRhID0gZGF0YTsKPiArICBkYXRhLT5kaXJv cGVuLmlubyA9IGRhdGEtPnJvb3RfaW5vOwo+ICsgIGRhdGEtPmRpcm9wZW4uaW5vZGVfcmVhZCA9 IDE7Cj4gKyAgZGF0YS0+aW5vZGUgPSAmZGF0YS0+ZGlyb3Blbi5pbm9kZTsKPiArCj4gKyAgZXJy ID0gZ3J1Yl9mMmZzX3JlYWRfbm9kZSAoZGF0YSwgZGF0YS0+cm9vdF9pbm8sIGRhdGEtPmlub2Rl KTsKPiArICBpZiAoZXJyKQo+ICsgICAgZ290byBmYWlsOwo+ICsKPiArICByZXR1cm4gZGF0YTsK PiArCj4gK2ZhaWw6Cj4gKyAgZ3J1Yl9mcmVlIChkYXRhKTsKPiArICByZXR1cm4gTlVMTDsKPiAr fQo+ICsKPiArLyogZ3VhcmFudGVlIGlubGluZV9kYXRhIHdhcyBoYW5kbGVkIGJ5IGNhbGxlciAq Lwo+ICtzdGF0aWMgZ3J1Yl9kaXNrX2FkZHJfdAo+ICtncnViX2YyZnNfZ2V0X2Jsb2NrIChncnVi X2ZzaGVscF9ub2RlX3Qgbm9kZSwgZ3J1Yl9kaXNrX2FkZHJfdCBibG9ja19vZnMpCj4gK3sKPiAr ICBzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGEgPSBub2RlLT5kYXRhOwo+ICsgIHN0cnVjdCBn cnViX2YyZnNfaW5vZGUgKmlub2RlID0gJm5vZGUtPmlub2RlLmk7Cj4gKyAgZ3J1Yl91aW50MzJf dCBvZmZzZXRbNF0sIG5vZmZzZXRbNF0sIG5pZHNbNF07Cj4gKyAgc3RydWN0IGdydWJfZjJmc19u b2RlICpub2RlX2Jsb2NrOwo+ICsgIGdydWJfdWludDMyX3QgYmxvY2tfYWRkciA9IC0xOwo+ICsg IGludCBsZXZlbCwgaTsKPiArCj4gKyAgbGV2ZWwgPSBncnViX2dldF9ub2RlX3BhdGggKGlub2Rl LCBibG9ja19vZnMsIG9mZnNldCwgbm9mZnNldCk7Cj4gKyAgaWYgKGxldmVsID09IDApCj4gKyAg ICByZXR1cm4gZ3J1Yl9sZV90b19jcHUzMiAoaW5vZGUtPmlfYWRkcltvZmZzZXRbMF1dKTsKPiAr Cj4gKyAgbm9kZV9ibG9jayA9IGdydWJfbWFsbG9jIChGMkZTX0JMS1NJWkUpOwo+ICsgIGlmICgh bm9kZV9ibG9jaykKPiArICAgIHJldHVybiAtMTsKPiArCj4gKyAgbmlkc1sxXSA9IF9fZ2V0X25v ZGVfaWQgKCZub2RlLT5pbm9kZSwgb2Zmc2V0WzBdLCAxKTsKPiArCj4gKyAgLyogZ2V0IGluZGly ZWN0IG9yIGRpcmVjdCBub2RlcyAqLwo+ICsgIGZvciAoaSA9IDE7IGkgPD0gbGV2ZWw7IGkrKykK PiArICAgIHsKPiArICAgICAgZ3J1Yl9mMmZzX3JlYWRfbm9kZSAoZGF0YSwgbmlkc1tpXSwgbm9k ZV9ibG9jayk7Cj4gKyAgICAgIGlmIChncnViX2Vycm5vKQo+ICsgICAgICAgIGdvdG8gZmFpbDsK PiArCj4gKyAgICAgIGlmIChpIDwgbGV2ZWwpCj4gKyAgICAgICAgbmlkc1tpICsgMV0gPSBfX2dl dF9ub2RlX2lkIChub2RlX2Jsb2NrLCBvZmZzZXRbaV0sIDApOwo+ICsgICAgfQo+ICsKPiArICBi bG9ja19hZGRyID0gZ3J1Yl9sZV90b19jcHUzMiAobm9kZV9ibG9jay0+ZG4uYWRkcltvZmZzZXRb bGV2ZWxdXSk7Cj4gK2ZhaWw6Cj4gKyAgZ3J1Yl9mcmVlIChub2RlX2Jsb2NrKTsKPiArICByZXR1 cm4gYmxvY2tfYWRkcjsKPiArfQo+ICsKPiArc3RhdGljIGdydWJfc3NpemVfdAo+ICtncnViX2Yy ZnNfcmVhZF9maWxlIChncnViX2ZzaGVscF9ub2RlX3Qgbm9kZSwKPiArCQlncnViX2Rpc2tfcmVh ZF9ob29rX3QgcmVhZF9ob29rLCB2b2lkICpyZWFkX2hvb2tfZGF0YSwKPiArCQlncnViX29mZl90 IHBvcywgZ3J1Yl9zaXplX3QgbGVuLCBjaGFyICpidWYpCj4gK3sKPiArICBzdHJ1Y3QgZ3J1Yl9m MmZzX2lub2RlICppbm9kZSA9ICZub2RlLT5pbm9kZS5pOwo+ICsgIGdydWJfb2ZmX3QgZmlsZXNp emUgPSBncnViX2YyZnNfZmlsZV9zaXplIChpbm9kZSk7Cj4gKyAgY2hhciAqaW5saW5lX2FkZHIg PSBfX2lubGluZV9hZGRyIChpbm9kZSk7Cj4gKwo+ICsgIGlmIChpbm9kZS0+aV9pbmxpbmUgJiBG MkZTX0lOTElORV9EQVRBKQo+ICsgICAgewo+ICsgICAgICBpZiAoZmlsZXNpemUgPiBNQVhfSU5M SU5FX0RBVEEpCj4gKyAgICAgICAgcmV0dXJuIC0xOwo+ICsgICAgICBpZiAobGVuID4gZmlsZXNp emUgLSBwb3MpCj4gKyAgICAgICAgbGVuID0gZmlsZXNpemUgLSBwb3M7Cj4gKwo+ICsgICAgICBn cnViX21lbWNweSAoYnVmICsgcG9zLCBpbmxpbmVfYWRkciArIHBvcywgbGVuKTsKPiArICAgICAg cmV0dXJuIGxlbjsKPiArICAgIH0KPiArCj4gKyAgcmV0dXJuIGdydWJfZnNoZWxwX3JlYWRfZmls ZSAobm9kZS0+ZGF0YS0+ZGlzaywgbm9kZSwKPiArCQkJcmVhZF9ob29rLCByZWFkX2hvb2tfZGF0 YSwKPiArCQkJcG9zLCBsZW4sIGJ1ZiwgZ3J1Yl9mMmZzX2dldF9ibG9jaywKPiArCQkJZmlsZXNp emUsCj4gKwkJCUYyRlNfQkxLX1NFQ19CSVRTLCAwKTsKPiArfQo+ICsKPiArc3RhdGljIGNoYXIg Kgo+ICtncnViX2YyZnNfcmVhZF9zeW1saW5rIChncnViX2ZzaGVscF9ub2RlX3Qgbm9kZSkKPiAr ewo+ICsgIGNoYXIgKnN5bWxpbms7Cj4gKyAgc3RydWN0IGdydWJfZnNoZWxwX25vZGUgKmRpcm8g PSBub2RlOwo+ICsgIGdydWJfdWludDY0X3QgZmlsZXNpemU7Cj4gKwo+ICsgIGlmICghZGlyby0+ aW5vZGVfcmVhZCkKPiArICAgIHsKPiArICAgICAgZ3J1Yl9mMmZzX3JlYWRfbm9kZSAoZGlyby0+ ZGF0YSwgZGlyby0+aW5vLCAmZGlyby0+aW5vZGUpOwo+ICsgICAgICBpZiAoZ3J1Yl9lcnJubykK PiArICAgICAgICByZXR1cm4gMDsKPiArICAgIH0KPiArCj4gKyAgZmlsZXNpemUgPSBncnViX2Yy ZnNfZmlsZV9zaXplKCZkaXJvLT5pbm9kZS5pKTsKPiArCj4gKyAgc3ltbGluayA9IGdydWJfbWFs bG9jIChmaWxlc2l6ZSArIDEpOwo+ICsgIGlmICghc3ltbGluaykKPiArICAgIHJldHVybiAwOwo+ ICsKPiArICBncnViX2YyZnNfcmVhZF9maWxlIChkaXJvLCAwLCAwLCAwLCBmaWxlc2l6ZSwgc3lt bGluayk7Cj4gKyAgaWYgKGdydWJfZXJybm8pCj4gKyAgICB7Cj4gKyAgICAgIGdydWJfZnJlZSAo c3ltbGluayk7Cj4gKyAgICAgIHJldHVybiAwOwo+ICsgICAgfQo+ICsKPiArICBzeW1saW5rW2Zp bGVzaXplXSA9ICdcMCc7Cj4gKyAgcmV0dXJuIHN5bWxpbms7Cj4gK30KPiArCj4gK3N0YXRpYyBp bnQKPiArZ3J1Yl9mMmZzX2NoZWNrX2RlbnRyaWVzIChzdHJ1Y3QgZ3J1Yl9mMmZzX2Rpcl9pdGVy X2N0eCAqY3R4KQo+ICt7Cj4gKyAgc3RydWN0IGdydWJfZnNoZWxwX25vZGUgKmZkaXJvOwo+ICsg IGludCBpOwo+ICsKPiArICBmb3IgKGkgPSAwOyBpIDwgY3R4LT5tYXg7KQo+ICsgICAgewo+ICsg ICAgICBjaGFyICpmaWxlbmFtZTsKPiArICAgICAgZW51bSBncnViX2ZzaGVscF9maWxldHlwZSB0 eXBlID0gR1JVQl9GU0hFTFBfVU5LTk9XTjsKPiArICAgICAgZW51bSBGSUxFX1RZUEUgZnR5cGU7 Cj4gKyAgICAgIGludCBuYW1lX2xlbjsKPiArICAgICAgaW50IHJldDsKPiArCj4gKyAgICAgIGlm IChncnViX2YyZnNfdGVzdF9iaXRfbGUgKGksIGN0eC0+Yml0bWFwKSA9PSAwKQo+ICsgICAgICAg IHsKPiArICAgICAgICAgIGkrKzsKPiArICAgICAgICAgIGNvbnRpbnVlOwo+ICsgICAgICAgIH0K PiArCj4gKyAgICAgIGZ0eXBlID0gY3R4LT5kZW50cnlbaV0uZmlsZV90eXBlOwo+ICsgICAgICBu YW1lX2xlbiA9IGdydWJfbGVfdG9fY3B1MTYgKGN0eC0+ZGVudHJ5W2ldLm5hbWVfbGVuKTsKPiAr ICAgICAgZmlsZW5hbWUgPSBncnViX21hbGxvYyAobmFtZV9sZW4gKyAxKTsKPiArICAgICAgaWYg KCFmaWxlbmFtZSkKPiArICAgICAgICByZXR1cm4gMDsKPiArCj4gKyAgICAgIGdydWJfbWVtY3B5 IChmaWxlbmFtZSwgY3R4LT5maWxlbmFtZVtpXSwgbmFtZV9sZW4pOwo+ICsgICAgICBmaWxlbmFt ZVtuYW1lX2xlbl0gPSAwOwo+ICsKPiArICAgICAgZmRpcm8gPSBncnViX21hbGxvYyAoc2l6ZW9m IChzdHJ1Y3QgZ3J1Yl9mc2hlbHBfbm9kZSkpOwo+ICsgICAgICBpZiAoIWZkaXJvKQo+ICsgICAg ICAgIHsKPiArICAgICAgICAgIGdydWJfZnJlZShmaWxlbmFtZSk7Cj4gKyAgICAgICAgICByZXR1 cm4gMDsKPiArICAgICAgICB9Cj4gKwo+ICsgICAgICBpZiAoZnR5cGUgPT0gRjJGU19GVF9ESVIp Cj4gKyAgICAgICAgdHlwZSA9IEdSVUJfRlNIRUxQX0RJUjsKPiArICAgICAgZWxzZSBpZiAoZnR5 cGUgPT0gRjJGU19GVF9TWU1MSU5LKQo+ICsgICAgICAgIHR5cGUgPSBHUlVCX0ZTSEVMUF9TWU1M SU5LOwo+ICsgICAgICBlbHNlIGlmIChmdHlwZSA9PSBGMkZTX0ZUX1JFR19GSUxFKQo+ICsgICAg ICAgIHR5cGUgPSBHUlVCX0ZTSEVMUF9SRUc7Cj4gKwo+ICsgICAgICBmZGlyby0+ZGF0YSA9IGN0 eC0+ZGF0YTsKPiArICAgICAgZmRpcm8tPmlubyA9IGdydWJfbGVfdG9fY3B1MzIgKGN0eC0+ZGVu dHJ5W2ldLmlubyk7Cj4gKyAgICAgIGZkaXJvLT5pbm9kZV9yZWFkID0gMDsKPiArCj4gKyAgICAg IHJldCA9IGN0eC0+aG9vayAoZmlsZW5hbWUsIHR5cGUsIGZkaXJvLCBjdHgtPmhvb2tfZGF0YSk7 Cj4gKyAgICAgIGdydWJfZnJlZShmaWxlbmFtZSk7Cj4gKyAgICAgIGlmIChyZXQpCj4gKyAgICAg ICAgcmV0dXJuIDE7Cj4gKwo+ICsgICAgICBpICs9IChuYW1lX2xlbiArIEYyRlNfU0xPVF9MRU4g LSAxKSAvIEYyRlNfU0xPVF9MRU47Cj4gKyAgICB9Cj4gKyAgICByZXR1cm4gMDsKPiArfQo+ICsK PiArc3RhdGljIGludAo+ICtncnViX2YyZnNfaXRlcmF0ZV9pbmxpbmVfZGlyIChzdHJ1Y3QgZ3J1 Yl9mMmZzX2lub2RlICpkaXIsCj4gKwlzdHJ1Y3QgZ3J1Yl9mMmZzX2Rpcl9pdGVyX2N0eCAqY3R4 KQo+ICt7Cj4gKyAgc3RydWN0IGdydWJfZjJmc19pbmxpbmVfZGVudHJ5ICpkZV9ibGs7Cj4gKwo+ ICsgIGRlX2JsayA9IChzdHJ1Y3QgZ3J1Yl9mMmZzX2lubGluZV9kZW50cnkgKikgX19pbmxpbmVf YWRkciAoZGlyKTsKPiArCj4gKyAgY3R4LT5iaXRtYXAgPSBkZV9ibGstPmRlbnRyeV9iaXRtYXA7 Cj4gKyAgY3R4LT5kZW50cnkgPSBkZV9ibGstPmRlbnRyeTsKPiArICBjdHgtPmZpbGVuYW1lID0g ZGVfYmxrLT5maWxlbmFtZTsKPiArICBjdHgtPm1heCA9IE5SX0lOTElORV9ERU5UUlk7Cj4gKwo+ ICsgIHJldHVybiBncnViX2YyZnNfY2hlY2tfZGVudHJpZXMgKGN0eCk7Cj4gK30KPiArCj4gK3N0 YXRpYyBpbnQKPiArZ3J1Yl9mMmZzX2l0ZXJhdGVfZGlyIChncnViX2ZzaGVscF9ub2RlX3QgZGly LAo+ICsJZ3J1Yl9mc2hlbHBfaXRlcmF0ZV9kaXJfaG9va190IGhvb2ssIHZvaWQgKmhvb2tfZGF0 YSkKPiArewo+ICsgIHN0cnVjdCBncnViX2ZzaGVscF9ub2RlICpkaXJvID0gKHN0cnVjdCBncnVi X2ZzaGVscF9ub2RlICopIGRpcjsKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2lub2RlICppbm9kZTsK PiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2Rpcl9pdGVyX2N0eCBjdHggPSB7Cj4gKyAgICAuZGF0YSA9 IGRpcm8tPmRhdGEsCj4gKyAgICAuaG9vayA9IGhvb2ssCj4gKyAgICAuaG9va19kYXRhID0gaG9v a19kYXRhCj4gKyAgfTsKPiArICBncnViX29mZl90IGZwb3MgPSAwOwo+ICsKPiArICBpZiAoIWRp cm8tPmlub2RlX3JlYWQpCj4gKyAgICB7Cj4gKyAgICAgIGdydWJfZjJmc19yZWFkX25vZGUgKGRp cm8tPmRhdGEsIGRpcm8tPmlubywgJmRpcm8tPmlub2RlKTsKPiArICAgICAgaWYgKGdydWJfZXJy bm8pCj4gKwlyZXR1cm4gMDsKPiArICAgIH0KPiArCj4gKyAgaW5vZGUgPSAmZGlyby0+aW5vZGUu aTsKPiArCj4gKyAgaWYgKGlub2RlLT5pX2lubGluZSAmIEYyRlNfSU5MSU5FX0RFTlRSWSkKPiAr ICAgIHJldHVybiBncnViX2YyZnNfaXRlcmF0ZV9pbmxpbmVfZGlyIChpbm9kZSwgJmN0eCk7Cj4g Kwo+ICsgIHdoaWxlIChmcG9zIDwgZ3J1Yl9mMmZzX2ZpbGVfc2l6ZSAoaW5vZGUpKQo+ICsgICAg ewo+ICsgICAgICBzdHJ1Y3QgZ3J1Yl9mMmZzX2RlbnRyeV9ibG9jayAqZGVfYmxrOwo+ICsgICAg ICBjaGFyICpidWY7Cj4gKyAgICAgIGludCByZXQ7Cj4gKwo+ICsgICAgICBidWYgPSBncnViX3ph bGxvYyAoRjJGU19CTEtTSVpFKTsKPiArICAgICAgaWYgKCFidWYpCj4gKyAgICAgICAgcmV0dXJu IDA7Cj4gKwo+ICsgICAgICBncnViX2YyZnNfcmVhZF9maWxlIChkaXJvLCAwLCAwLCBmcG9zLCBG MkZTX0JMS1NJWkUsIGJ1Zik7Cj4gKyAgICAgIGlmIChncnViX2Vycm5vKQo+ICsgICAgICAgIHsK PiArICAgICAgICAgIGdydWJfZnJlZSAoYnVmKTsKPiArICAgICAgICAgIHJldHVybiAwOwo+ICsg ICAgICAgIH0KPiArCj4gKyAgICAgIGRlX2JsayA9IChzdHJ1Y3QgZ3J1Yl9mMmZzX2RlbnRyeV9i bG9jayAqKSBidWY7Cj4gKwo+ICsgICAgICBjdHguYml0bWFwID0gZGVfYmxrLT5kZW50cnlfYml0 bWFwOwo+ICsgICAgICBjdHguZGVudHJ5ID0gZGVfYmxrLT5kZW50cnk7Cj4gKyAgICAgIGN0eC5m aWxlbmFtZSA9IGRlX2Jsay0+ZmlsZW5hbWU7Cj4gKyAgICAgIGN0eC5tYXggPSBOUl9ERU5UUllf SU5fQkxPQ0s7Cj4gKwo+ICsgICAgICByZXQgPSBncnViX2YyZnNfY2hlY2tfZGVudHJpZXMgKCZj dHgpOwo+ICsgICAgICBncnViX2ZyZWUgKGJ1Zik7Cj4gKyAgICAgIGlmIChyZXQpCj4gKyAgICAg ICAgcmV0dXJuIDE7Cj4gKwo+ICsgICAgICBmcG9zICs9IEYyRlNfQkxLU0laRTsKPiArICAgIH0K PiArICByZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludAo+ICtncnViX2YyZnNfZGlyX2l0 ZXIgKGNvbnN0IGNoYXIgKmZpbGVuYW1lLCBlbnVtIGdydWJfZnNoZWxwX2ZpbGV0eXBlIGZpbGV0 eXBlLAo+ICsJICAgICAgZ3J1Yl9mc2hlbHBfbm9kZV90IG5vZGUsIHZvaWQgKmRhdGEpCj4gK3sK PiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2Rpcl9jdHggKmN0eCA9IGRhdGE7Cj4gKyAgc3RydWN0IGdy dWJfZGlyaG9va19pbmZvIGluZm87Cj4gKwo+ICsgIGdydWJfbWVtc2V0ICgmaW5mbywgMCwgc2l6 ZW9mIChpbmZvKSk7Cj4gKyAgaWYgKCFub2RlLT5pbm9kZV9yZWFkKQo+ICsgICAgewo+ICsgICAg ICBncnViX2YyZnNfcmVhZF9ub2RlIChjdHgtPmRhdGEsIG5vZGUtPmlubywgJm5vZGUtPmlub2Rl KTsKPiArICAgICAgaWYgKCFncnViX2Vycm5vKQo+ICsgICAgICAgIG5vZGUtPmlub2RlX3JlYWQg PSAxOwo+ICsgICAgICBncnViX2Vycm5vID0gR1JVQl9FUlJfTk9ORTsKPiArICAgIH0KPiArICBp ZiAobm9kZS0+aW5vZGVfcmVhZCkKPiArICAgIHsKPiArICAgICAgaW5mby5tdGltZXNldCA9IDE7 Cj4gKyAgICAgIGluZm8ubXRpbWUgPSBncnViX2xlX3RvX2NwdTY0IChub2RlLT5pbm9kZS5pLmlf bXRpbWUpOwo+ICsgICAgfQo+ICsKPiArICBpbmZvLmRpciA9ICgoZmlsZXR5cGUgJiBHUlVCX0ZT SEVMUF9UWVBFX01BU0spID09IEdSVUJfRlNIRUxQX0RJUik7Cj4gKyAgZ3J1Yl9mcmVlIChub2Rl KTsKPiArICByZXR1cm4gY3R4LT5ob29rIChmaWxlbmFtZSwgJmluZm8sIGN0eC0+aG9va19kYXRh KTsKPiArfQo+ICsKPiArc3RhdGljIGdydWJfZXJyX3QKPiArZ3J1Yl9mMmZzX2RpciAoZ3J1Yl9k ZXZpY2VfdCBkZXZpY2UsIGNvbnN0IGNoYXIgKnBhdGgsCj4gKwlncnViX2ZzX2Rpcl9ob29rX3Qg aG9vaywgdm9pZCAqaG9va19kYXRhKQo+ICt7Cj4gKyAgc3RydWN0IGdydWJfZjJmc19kaXJfY3R4 IGN0eCA9IHsKPiArICAgIC5ob29rID0gaG9vaywKPiArICAgIC5ob29rX2RhdGEgPSBob29rX2Rh dGEKPiArICB9Owo+ICsgIHN0cnVjdCBncnViX2ZzaGVscF9ub2RlICpmZGlybyA9IDA7Cj4gKwo+ ICsgIGdydWJfZGxfcmVmIChteV9tb2QpOwo+ICsKPiArICBjdHguZGF0YSA9IGdydWJfZjJmc19t b3VudCAoZGV2aWNlLT5kaXNrKTsKPiArICBpZiAoIWN0eC5kYXRhKQo+ICsgICAgZ290byBmYWls Owo+ICsKPiArICBncnViX2ZzaGVscF9maW5kX2ZpbGUgKHBhdGgsICZjdHguZGF0YS0+ZGlyb3Bl biwgJmZkaXJvLAo+ICsJCWdydWJfZjJmc19pdGVyYXRlX2RpciwgZ3J1Yl9mMmZzX3JlYWRfc3lt bGluaywKPiArCQlHUlVCX0ZTSEVMUF9ESVIpOwo+ICsgIGlmIChncnViX2Vycm5vKQo+ICsgICAg Z290byBmYWlsOwo+ICsKPiArICBncnViX2YyZnNfaXRlcmF0ZV9kaXIgKGZkaXJvLCBncnViX2Yy ZnNfZGlyX2l0ZXIsICZjdHgpOwo+ICsKPiArZmFpbDoKPiArICBpZiAoZmRpcm8gIT0gJmN0eC5k YXRhLT5kaXJvcGVuKQo+ICsgICAgZ3J1Yl9mcmVlIChmZGlybyk7Cj4gKyBncnViX2ZyZWUgKGN0 eC5kYXRhKTsKPiArIGdydWJfZGxfdW5yZWYgKG15X21vZCk7Cj4gKyByZXR1cm4gZ3J1Yl9lcnJu bzsKPiArfQo+ICsKPiArCj4gKy8qIE9wZW4gYSBmaWxlIG5hbWVkIE5BTUUgYW5kIGluaXRpYWxp emUgRklMRS4gICovCj4gK3N0YXRpYyBncnViX2Vycl90Cj4gK2dydWJfZjJmc19vcGVuIChzdHJ1 Y3QgZ3J1Yl9maWxlICpmaWxlLCBjb25zdCBjaGFyICpuYW1lKQo+ICt7Cj4gKyAgc3RydWN0IGdy dWJfZjJmc19kYXRhICpkYXRhID0gTlVMTDsKPiArICBzdHJ1Y3QgZ3J1Yl9mc2hlbHBfbm9kZSAq ZmRpcm8gPSAwOwo+ICsgIHN0cnVjdCBncnViX2YyZnNfaW5vZGUgKmlub2RlOwo+ICsKPiArICBn cnViX2RsX3JlZiAobXlfbW9kKTsKPiArCj4gKyAgZGF0YSA9IGdydWJfZjJmc19tb3VudCAoZmls ZS0+ZGV2aWNlLT5kaXNrKTsKPiArICBpZiAoIWRhdGEpCj4gKyAgICBnb3RvIGZhaWw7Cj4gKwo+ ICsgIGdydWJfZnNoZWxwX2ZpbmRfZmlsZSAobmFtZSwgJmRhdGEtPmRpcm9wZW4sICZmZGlybywK PiArCQkJZ3J1Yl9mMmZzX2l0ZXJhdGVfZGlyLCBncnViX2YyZnNfcmVhZF9zeW1saW5rLAo+ICsJ CQlHUlVCX0ZTSEVMUF9SRUcpOwo+ICsgIGlmIChncnViX2Vycm5vKQo+ICsgICAgZ290byBmYWls Owo+ICsKPiArICBpZiAoIWZkaXJvLT5pbm9kZV9yZWFkKQo+ICsgICAgewo+ICsgICAgICBncnVi X2YyZnNfcmVhZF9ub2RlIChkYXRhLCBmZGlyby0+aW5vLCAmZmRpcm8tPmlub2RlKTsKPiArICAg ICAgaWYgKGdydWJfZXJybm8pCj4gKwlnb3RvIGZhaWw7Cj4gKyAgICB9Cj4gKwo+ICsgIGdydWJf bWVtY3B5IChkYXRhLT5pbm9kZSwgJmZkaXJvLT5pbm9kZSwgc2l6ZW9mICgqZGF0YS0+aW5vZGUp KTsKPiArICBncnViX2ZyZWUgKGZkaXJvKTsKPiArCj4gKyAgaW5vZGUgPSAmKGRhdGEtPmlub2Rl LT5pKTsKPiArICBmaWxlLT5zaXplID0gZ3J1Yl9mMmZzX2ZpbGVfc2l6ZSAoaW5vZGUpOwo+ICsg IGZpbGUtPmRhdGEgPSBkYXRhOwo+ICsgIGZpbGUtPm9mZnNldCA9IDA7Cj4gKwo+ICsgIGlmIChp bm9kZS0+aV9pbmxpbmUgJiBGMkZTX0lOTElORV9EQVRBICYmIGZpbGUtPnNpemUgPiBNQVhfSU5M SU5FX0RBVEEpCj4gKyAgICBncnViX2Vycm9yIChHUlVCX0VSUl9CQURfRlMsICJjb3JydXB0ZWQg aW5saW5lX2RhdGE6IG5lZWQgZnNjayIpOwo+ICsgIHJldHVybiAwOwo+ICsKPiArZmFpbDoKPiAr ICBpZiAoZmRpcm8gIT0gJmRhdGEtPmRpcm9wZW4pCj4gKyAgICBncnViX2ZyZWUgKGZkaXJvKTsK PiArICBncnViX2ZyZWUgKGRhdGEpOwo+ICsKPiArICBncnViX2RsX3VucmVmIChteV9tb2QpOwo+ ICsKPiArICByZXR1cm4gZ3J1Yl9lcnJubzsKPiArfQo+ICsKPiArc3RhdGljIGdydWJfc3NpemVf dAo+ICtncnViX2YyZnNfcmVhZCAoZ3J1Yl9maWxlX3QgZmlsZSwgY2hhciAqYnVmLCBncnViX3Np emVfdCBsZW4pCj4gK3sKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGEgPSAoc3RydWN0 IGdydWJfZjJmc19kYXRhICopIGZpbGUtPmRhdGE7Cj4gKwo+ICsgIHJldHVybiBncnViX2YyZnNf cmVhZF9maWxlICgmZGF0YS0+ZGlyb3BlbiwKPiArCQlmaWxlLT5yZWFkX2hvb2ssIGZpbGUtPnJl YWRfaG9va19kYXRhLAo+ICsJCWZpbGUtPm9mZnNldCwgbGVuLCBidWYpOwo+ICt9Cj4gKwo+ICtz dGF0aWMgZ3J1Yl9lcnJfdAo+ICtncnViX2YyZnNfY2xvc2UgKGdydWJfZmlsZV90IGZpbGUpCj4g K3sKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGEgPSAoc3RydWN0IGdydWJfZjJmc19k YXRhICopIGZpbGUtPmRhdGE7Cj4gKwo+ICsgIGdydWJfZnJlZSAoZGF0YSk7Cj4gKwo+ICsgIGdy dWJfZGxfdW5yZWYgKG15X21vZCk7Cj4gKwo+ICsgIHJldHVybiBHUlVCX0VSUl9OT05FOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgZ3J1Yl91aW50OF90ICoKPiArZ3J1Yl9mMmZzX3V0ZjE2X3RvX3V0Zjgg KGdydWJfdWludDE2X3QgKmluX2J1Zl9sZSkKPiArewo+ICsgIGdydWJfdWludDE2X3QgaW5fYnVm W01BWF9WT0xVTUVfTkFNRV07Cj4gKyAgZ3J1Yl91aW50OF90ICpvdXRfYnVmOwo+ICsgIGludCBs ZW4gPSAwOwo+ICsKPiArICBvdXRfYnVmID0gZ3J1Yl9tYWxsb2MgKE1BWF9WT0xVTUVfTkFNRSAq IEdSVUJfTUFYX1VURjhfUEVSX1VURjE2ICsgMSk7Cj4gKyAgaWYgKCFvdXRfYnVmKQo+ICsgICAg cmV0dXJuIE5VTEw7Cj4gKwo+ICsgIHdoaWxlICgqaW5fYnVmX2xlICE9IDAgJiYgbGVuIDwgTUFY X1ZPTFVNRV9OQU1FKSB7Cj4gKyAgICBpbl9idWZbbGVuXSA9IGdydWJfbGVfdG9fY3B1MTYgKGlu X2J1Zl9sZVtsZW5dKTsKPiArICAgIGxlbisrOwo+ICsgIH0KPiArCj4gKyAgKmdydWJfdXRmMTZf dG9fdXRmOCAob3V0X2J1ZiwgaW5fYnVmLCBsZW4pID0gJ1wwJzsKPiArICByZXR1cm4gb3V0X2J1 ZjsKPiArfQo+ICsKPiArc3RhdGljIGdydWJfZXJyX3QKPiArZ3J1Yl9mMmZzX2xhYmVsIChncnVi X2RldmljZV90IGRldmljZSwgY2hhciAqKmxhYmVsKQo+ICt7Cj4gKyAgc3RydWN0IGdydWJfZjJm c19kYXRhICpkYXRhOwo+ICsgIGdydWJfZGlza190IGRpc2sgPSBkZXZpY2UtPmRpc2s7Cj4gKwo+ ICsgIGdydWJfZGxfcmVmIChteV9tb2QpOwo+ICsKPiArICBkYXRhID0gZ3J1Yl9mMmZzX21vdW50 IChkaXNrKTsKPiArICBpZiAoZGF0YSkKPiArICAgICpsYWJlbCA9IChjaGFyICopIGdydWJfZjJm c191dGYxNl90b191dGY4IChkYXRhLT5zYmxvY2sudm9sdW1lX25hbWUpOwo+ICsgIGVsc2UKPiAr ICAgICpsYWJlbCA9IE5VTEw7Cj4gKwo+ICsgIGdydWJfZnJlZSAoZGF0YSk7Cj4gKyAgZ3J1Yl9k bF91bnJlZiAobXlfbW9kKTsKPiArICByZXR1cm4gZ3J1Yl9lcnJubzsKPiArfQo+ICsKPiArc3Rh dGljIGdydWJfZXJyX3QKPiArZ3J1Yl9mMmZzX3V1aWQgKGdydWJfZGV2aWNlX3QgZGV2aWNlLCBj aGFyICoqdXVpZCkKPiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0YTsKPiArICBn cnViX2Rpc2tfdCBkaXNrID0gZGV2aWNlLT5kaXNrOwo+ICsKPiArICBncnViX2RsX3JlZiAobXlf bW9kKTsKPiArCj4gKyAgZGF0YSA9IGdydWJfZjJmc19tb3VudCAoZGlzayk7Cj4gKyAgaWYgKGRh dGEpCj4gKyAgICB7Cj4gKyAgICAgICp1dWlkID0KPiArCWdydWJfeGFzcHJpbnRmCj4gKwkoIiUw MnglMDJ4JTAyeCUwMngtJTAyeCUwMngtJTAyeCUwMngtJTAyeCUwMngtJTAyeCUwMnglMDJ4JTAy eCUwMnglMDJ4IiwKPiArCQlkYXRhLT5zYmxvY2sudXVpZFswXSwgZGF0YS0+c2Jsb2NrLnV1aWRb MV0sCj4gKwkJZGF0YS0+c2Jsb2NrLnV1aWRbMl0sIGRhdGEtPnNibG9jay51dWlkWzNdLAo+ICsJ CWRhdGEtPnNibG9jay51dWlkWzRdLCBkYXRhLT5zYmxvY2sudXVpZFs1XSwKPiArCQlkYXRhLT5z YmxvY2sudXVpZFs2XSwgZGF0YS0+c2Jsb2NrLnV1aWRbN10sCj4gKwkJZGF0YS0+c2Jsb2NrLnV1 aWRbOF0sIGRhdGEtPnNibG9jay51dWlkWzldLAo+ICsJCWRhdGEtPnNibG9jay51dWlkWzEwXSwg ZGF0YS0+c2Jsb2NrLnV1aWRbMTFdLAo+ICsJCWRhdGEtPnNibG9jay51dWlkWzEyXSwgZGF0YS0+ c2Jsb2NrLnV1aWRbMTNdLAo+ICsJCWRhdGEtPnNibG9jay51dWlkWzE0XSwgZGF0YS0+c2Jsb2Nr LnV1aWRbMTVdKTsKPiArICAgIH0KPiArICBlbHNlCj4gKyAgICAqdXVpZCA9IE5VTEw7Cj4gKwo+ ICsgIGdydWJfZnJlZSAoZGF0YSk7Cj4gKyAgZ3J1Yl9kbF91bnJlZiAobXlfbW9kKTsKPiArICBy ZXR1cm4gZ3J1Yl9lcnJubzsKPiArfQo+ICsKPiArc3RhdGljIHN0cnVjdCBncnViX2ZzIGdydWJf ZjJmc19mcyA9IHsKPiArICAubmFtZSA9ICJmMmZzIiwKPiArICAuZGlyID0gZ3J1Yl9mMmZzX2Rp ciwKPiArICAub3BlbiA9IGdydWJfZjJmc19vcGVuLAo+ICsgIC5yZWFkID0gZ3J1Yl9mMmZzX3Jl YWQsCj4gKyAgLmNsb3NlID0gZ3J1Yl9mMmZzX2Nsb3NlLAo+ICsgIC5sYWJlbCA9IGdydWJfZjJm c19sYWJlbCwKPiArICAudXVpZCA9IGdydWJfZjJmc191dWlkLAo+ICsjaWZkZWYgR1JVQl9VVElM Cj4gKyAgLnJlc2VydmVkX2ZpcnN0X3NlY3RvciA9IDEsCj4gKyAgLmJsb2NrbGlzdF9pbnN0YWxs ID0gMCwKPiArI2VuZGlmCj4gKyAgLm5leHQgPSAwCj4gK307Cj4gKwo+ICtHUlVCX01PRF9JTklU IChmMmZzKQo+ICt7Cj4gKyAgZ3J1Yl9mc19yZWdpc3RlciAoJmdydWJfZjJmc19mcyk7Cj4gKyAg bXlfbW9kID0gbW9kOwo+ICt9Cj4gKwo+ICtHUlVCX01PRF9GSU5JIChmMmZzKQo+ICt7Cj4gKyAg Z3J1Yl9mc191bnJlZ2lzdGVyICgmZ3J1Yl9mMmZzX2ZzKTsKPiArfQo+IGRpZmYgLS1naXQgYS9w by9leGNsdWRlLnBvdCBiL3BvL2V4Y2x1ZGUucG90Cj4gaW5kZXggMGE5YjIxNS4uODE2MDg5YyAx MDA2NDQKPiAtLS0gYS9wby9leGNsdWRlLnBvdAo+ICsrKyBiL3BvL2V4Y2x1ZGUucG90Cj4gQEAg LTEyMTQsNiArMTIxNCw3IEBAIG1zZ3N0ciAiIgo+ICAKPiAgIzogZ3J1Yi1jb3JlL2NvbW1hbmRz L3hudV91dWlkLmM6NzUgZ3J1Yi1jb3JlL2ZzL2pmcy5jOjkyNAo+ICAjOiBncnViLWNvcmUvZnMv bmlsZnMyLmM6MTEzNQo+ICsjOiBncnViLWNvcmUvZnMvZjJmcy5jOjEyNTkKPiAgIywgYy1mb3Jt YXQKPiAgbXNnaWQgIiUwMnglMDJ4JTAyeCUwMngtJTAyeCUwMngtJTAyeCUwMngtJTAyeCUwMngt JTAyeCUwMnglMDJ4JTAyeCUwMnglMDJ4Igo+ICBtc2dzdHIgIiIKPiBkaWZmIC0tZ2l0IGEvdGVz dHMvZjJmc190ZXN0LmluIGIvdGVzdHMvZjJmc190ZXN0LmluCj4gbmV3IGZpbGUgbW9kZSAxMDA2 NDQKPiBpbmRleCAwMDAwMDAwLi4xZWE3N2M4Cj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL3Rlc3Rz L2YyZnNfdGVzdC5pbgo+IEBAIC0wLDAgKzEsMTkgQEAKPiArIyEvYmluL3NoCj4gKwo+ICtzZXQg LWUKPiArCj4gK2lmIFsgIngkRVVJRCIgPSAieCIgXSA7IHRoZW4KPiArIEVVSUQ9YGlkIC11YAo+ ICtmaQo+ICsKPiAraWYgWyAiJEVVSUQiICE9IDAgXSA7IHRoZW4KPiArIGV4aXQgNzcKPiArZmkK PiArCj4gK2lmICEgd2hpY2ggbWtmcy5mMmZzID4vZGV2L251bGwgMj4mMTsgdGhlbgo+ICsgZWNo byAibWtmcy5mMmZzIG5vdCBpbnN0YWxsZWQ7IGNhbm5vdCB0ZXN0IGYyZnMuIgo+ICsgZXhpdCA3 Nwo+ICtmaQo+ICsKPiArCj4gKyJAYnVpbGRkaXJAL2dydWItZnMtdGVzdGVyIiBmMmZzCj4gZGlm ZiAtLWdpdCBhL3Rlc3RzL3V0aWwvZ3J1Yi1mcy10ZXN0ZXIuaW4gYi90ZXN0cy91dGlsL2dydWIt ZnMtdGVzdGVyLmluCj4gaW5kZXggNDI0ZGUyMi4uZTNlNDEwOSAxMDA2NDQKPiAtLS0gYS90ZXN0 cy91dGlsL2dydWItZnMtdGVzdGVyLmluCj4gKysrIGIvdGVzdHMvdXRpbC9ncnViLWZzLXRlc3Rl ci5pbgo+IEBAIC0xNDIsNyArMTQyLDcgQEAgZm9yICgoTE9HU0VDU0laRT1NSU5MT0dTRUNTSVpF O0xPR1NFQ1NJWkU8PU1BWExPR1NFQ1NJWkU7TE9HU0VDU0laRT1MT0dTRUNTSVpFICsKPiAgCXhz cXVhc2gqKQo+ICAJICAgIE1JTkJMS1NJWkU9NDA5Ngo+ICAJICAgIE1BWEJMS1NJWkU9MTA0ODU3 Njs7Cj4gLQl4eGZzKQo+ICsJeHhmc3x4ZjJmcykKPiAgCSAgICBNSU5CTEtTSVpFPSRTRUNTSVpF Cj4gIAkJIyBPUyBMaW1pdGF0aW9uOiBHTlUvTGludXggZG9lc24ndCBhY2NlcHQgPiA0MDk2Cj4g IAkgICAgTUFYQkxLU0laRT00MDk2OzsKPiBAQCAtMjY1LDYgKzI2NSwxMCBAQCBmb3IgKChMT0dT RUNTSVpFPU1JTkxPR1NFQ1NJWkU7TE9HU0VDU0laRTw9TUFYTE9HU0VDU0laRTtMT0dTRUNTSVpF PUxPR1NFQ1NJWkUgKwo+ICAJCXgiYnRyZnMiKikKPiAgCQkgICAgRlNMQUJFTD0iZ3J1Yl87L3Rl c3TDqfCvppvwr6ad8J+YgdC60LjRgNC40YJpIHVyZXdmY2VuaXVld3J1ZXZyZXdudXVpcmV1cmV2 dWV1cm5pZXZyZXdmbmVyZmNuZXZpcml2aW5yZXd2bmlyZXduaXZyZXdpdXZjcmV3dm51ZXd2cnJy ZXduaXVlcndyZWl1dml1cmV3aXV2aXVyZXdudXZld252cmVudXJudW51dnJldnV1cmVyZWppcmVt dnJlaWpudmNyZWl2aXJlIG52ZXJpdm5yZWl2cmV2bnVyZWlvcmZuZnJ2b2VvaXJvaXJlb2lyZW9p ZnJlZm9pZXJvaWZvaXJlb2lmIjs7Cj4gIAo+ICsJICAgICMgRlMgTElNSVRBVElPTjogZjJmcyBs YWJlbCBpcyBhdCBtb3N0IDUxMiBVVEYtMTYgY2hhcnMKPiArCQl4ImYyZnMiKQo+ICsJCSAgICBG U0xBQkVMPSJncnViXzsvdGVzdMOp5I+M5JCT5I+V0LrQuNGA0LjRgml1cmV3ZmNlbml1ZXdydWV3 bnV1aXJldXJldnVldXJuaWV2cmV3Zm5lcmZjbmV2aXJpdmlucmV3dm5pcmV3bml2cmV3aXV2Y3Jl d3ZudWV3dnJycmV3bml1ZXJ3cmVpdXZpdXJld2l1dml1cmV3bnV2ZXdudnJlbnVybnVudXZyZXZ1 dXJlcmVqaXJlbXZyZWlqbnZ2Y3JlaXZpcmUgbnZlcml2bnJlaXZyZXZudXJlaW9yZm5mcnZvZW9p cm9pcmVvaXJlb2lmcmVmb2llcm9pZm9pcnZjcmVpdmlyZSBudmVyaXZucmVpdnJldm51cmVpb3Jm bmZydm9lb2lyb2lyZW9pcmVvaWZyZWZvaWVyb2lmb2lyY3JlaXZpcmUgbnZlcml2bnJlaXZyZXZu dXJlaW9yZm5mcnZvZW9pcm9pcmVvaXJlb2lmcmVmb2llcm9pZm9pcmVvaWZvaXEiOzsKPiArCj4g IAkgICAgIyBGUyBMSU1JVEFUSU9OOiBleGZhdCBpcyBhdCBtb3N0IDE1IFVURi0xNiBjaGFycwo+ ICAJCXgiZXhmYXQiKQo+ICAJCSAgICBGU0xBQkVMPSJnw6nRgiA7L/Cvppvwr6ad8J+YgdC60LjR gCI7Owo+IEBAIC00NzQsNyArNDc4LDcgQEAgZm9yICgoTE9HU0VDU0laRT1NSU5MT0dTRUNTSVpF O0xPR1NFQ1NJWkU8PU1BWExPR1NFQ1NJWkU7TE9HU0VDU0laRT1MT0dTRUNTSVpFICsKPiAgCSAg ICAjIEZJWE1FOiBOb3Qgc3VyZSBhYm91dCBCdHJGUywgTlRGUywgSkZTLCBBRlMsIFVERiBhbmQg U0ZTLiBDaGVjayBpdC4KPiAgCSMgRlMgTElNSVRBVElPTjogYXMgZmFyIGFzIEkga25vdyB0aG9z ZSBGUyBkb24ndCBzdG9yZSB0aGVpciBsYXN0IG1vZGlmaWNhdGlvbiBkYXRlLgo+ICAJCXgiamZz X2Nhc2VpbnMiIHwgeCJqZnMiIHwgeCJ4ZnMiIHwgeCJ4ZnNfY3JjIiB8IHgiYnRyZnMiKiB8IHgi cmVpc2VyZnNfb2xkIiB8IHgicmVpc2VyZnMiIFwKPiAtCQkgICAgfCB4ImJmcyIgfCB4ImFmcyIg XAo+ICsJCSAgICB8IHgiYmZzIiB8IHgiYWZzIiB8IHgiZjJmcyIgXAo+ICAJCSAgICB8IHgidGFy ZnMiIHwgeCJjcGlvXyIqIHwgeCJtaW5peCIgfCB4Im1pbml4MiIgXAo+ICAJCSAgICB8IHgibWlu aXgzIiB8IHgibnRmcyIqIHwgeCJ1ZGYiIHwgeCJzZnMiKikKPiAgCQkgICAgTk9GU1RJTUU9eTs7 Cj4gQEAgLTc1Myw2ICs3NTcsOCBAQCBmb3IgKChMT0dTRUNTSVpFPU1JTkxPR1NFQ1NJWkU7TE9H U0VDU0laRTw9TUFYTE9HU0VDU0laRTtMT0dTRUNTSVpFPUxPR1NFQ1NJWkUgKwo+ICAJCSAgICBN T1VOVERFVklDRT0iL2Rldi9tYXBwZXIvZ3J1Yl90ZXN0LXRlc3R2b2wiCj4gIAkJICAgIE1PVU5U RlM9ZXh0Mgo+ICAJCSAgICAibWtmcy5leHQyIiAtTCAiJEZTTEFCRUwiIC1xICIke01PVU5UREVW SUNFfSIgIDs7Cj4gKwkJeGYyZnMpCj4gKwkJICAgICJta2ZzLmYyZnMiIC1sICIkRlNMQUJFTCIg LXEgIiR7TE9ERVZJQ0VTWzBdfSIgOzsKPiAgCQl4bmlsZnMyKQo+ICAJCSAgICAibWtmcy5uaWxm czIiIC1MICIkRlNMQUJFTCIgLWIgJEJMS1NJWkUgIC1xICIke0xPREVWSUNFU1swXX0iIDs7Cj4g IAkJeGV4dDJfb2xkKQo+IAoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fCkdydWItZGV2ZWwgbWFpbGluZyBsaXN0CkdydWItZGV2ZWxAZ251Lm9yZwpodHRw czovL2xpc3RzLmdudS5vcmcvbWFpbG1hbi9saXN0aW5mby9ncnViLWRldmVsCg==