From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1bVM6C-0000xS-Oj for mharc-grub-devel@gnu.org; Thu, 04 Aug 2016 13:06:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60519) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bVM66-0000wy-JI for grub-devel@gnu.org; Thu, 04 Aug 2016 13:06:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bVM62-000184-65 for grub-devel@gnu.org; Thu, 04 Aug 2016 13:06:18 -0400 Received: from mail.kernel.org ([198.145.29.136]:38732) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bVM61-00017p-LU for grub-devel@gnu.org; Thu, 04 Aug 2016 13:06:14 -0400 Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D6CED201EF; Thu, 4 Aug 2016 17:06:08 +0000 (UTC) Received: from localhost (107-1-141-74-ip-static.hfc.comcastbusiness.net [107.1.141.74]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 51D3420396; Thu, 4 Aug 2016 17:06:05 +0000 (UTC) Date: Thu, 4 Aug 2016 10:06:05 -0700 From: Jaegeuk Kim To: Andrei Borzenkov Cc: The development of GNU GRUB , linux-f2fs-devel@lists.sourceforge.net Subject: Re: [f2fs-dev] [2.02] Re: [PATCH v8] F2FS support Message-ID: <20160804170605.GA12013@jaegeuk> 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> <56D5F2E9.1070501@gmail.com> <20160303213653.GB15612@jaegeuk.hsd1.ca.comcast.net> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <20160303213653.GB15612@jaegeuk.hsd1.ca.comcast.net> User-Agent: Mutt/1.6.0 (2016-04-01) X-Virus-Scanned: ClamAV using ClamSMTP Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 198.145.29.136 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 04 Aug 2016 17:06:22 -0000 Hi Andrei, It's been sitting for a long long time. May I ask whether or not there is any merging plan of this? Thanks, On Thu, Mar 03, 2016 at 01:36:53PM -0800, Jaegeuk Kim wrote: > Change log from v7: > - fix an offset bug in read_file >=20 > -- >8 -- > From d774cdecc2fee18ed44098c88d2a54d358bc04d3 Mon Sep 17 00:00:00 2001 > From: Jaegeuk Kim > Date: Tue, 17 Nov 2015 12:45:13 -0800 > Subject: [PATCH] F2FS support >=20 > "F2FS (Flash-Friendly File System) is flash-friendly file system which = was merged > into Linux kernel v3.8 in 2013. >=20 > The motive for F2FS was to build a file system that from the start, tak= es into > account the characteristics of NAND flash memory-based storage devices = (such as > solid-state disks, eMMC, and SD cards). >=20 > 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, su= ch as > the snowball effect of wandering trees and high cleaning overhead. In a= ddition, > since a NAND-based storage device shows different characteristics accor= ding to > its internal geometry or flash memory management scheme (such as the Fl= ash > Translation Layer or FTL), it supports various parameters not only for > configuring on-disk layout, but also for selecting allocation and clean= ing > algorithm.", quote by https://en.wikipedia.org/wiki/F2FS. >=20 > The source codes for F2FS are available from: >=20 > http://git.kernel.org/cgit/linux/kernel/git/jaegeuk/f2fs.git > http://git.kernel.org/cgit/linux/kernel/git/jaegeuk/f2fs-tools.git >=20 > 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 >=20 > 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 =3D { > common =3D grub-core/fs/ext2.c; > common =3D grub-core/fs/fat.c; > common =3D grub-core/fs/exfat.c; > + common =3D grub-core/fs/f2fs.c; > common =3D grub-core/fs/fshelp.c; > common =3D grub-core/fs/hfs.c; > common =3D grub-core/fs/hfsplus.c; > @@ -766,6 +767,12 @@ script =3D { > =20 > script =3D { > testcase; > + name =3D f2fs_test; > + common =3D tests/f2fs_test.in; > +}; > + > +script =3D { > + testcase; > name =3D nilfs2_test; > common =3D 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 filesys= tem 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-chun= k 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 FA= T, Joliet part of > ISO9660 are treated as UTF-16 as per specification. AFS and BFS are re= ad > as UTF-8, again according to specification. BtrFS, cpio, tar, squash4,= minix, > minix2, minix3, ROMFS, ReiserFS, XFS, ext2, ext3, ext4, FAT (short nam= es), > -RockRidge part of ISO9660, nilfs2, UFS1, UFS2 and ZFS are assumed > +f2fs, RockRidge part of ISO9660, nilfs2, UFS1, UFS2 and ZFS are assume= d > to be UTF-8. This might be false on systems configured with legacy cha= rset > but as long as the charset used is superset of ASCII you should be abl= e to > access ASCII-named files. And it's recommended to configure your syste= m 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 =3D { > }; > =20 > module =3D { > + name =3D f2fs; > + common =3D fs/f2fs.c; > +}; > + > +module =3D { > name =3D fshelp; > common =3D fs/fshelp.c; > }; > diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c > new file mode 100644 > index 0000000..7fb256f > --- /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 =3D 1, > + F2FS_FT_DIR =3D 2, > + F2FS_FT_SYMLINK =3D 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 =3D &data->ckpt; > + grub_uint32_t start_addr =3D 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 =3D &data->ckpt; > + > + return __start_cp_addr (data) + grub_le_to_cpu32 (ckpt->cp_pack_star= t_sum); > +} > + > +static inline grub_uint32_t > +__sum_blk_addr (struct grub_f2fs_data *data, int base, int type) > +{ > + struct grub_f2fs_checkpoint *ckpt =3D &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 =3D &data->ckpt; > + grub_uint32_t offset; > + > + if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0) > + return ckpt->sit_nat_version_bitmap; > + > + offset =3D 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 blkad= dr, 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 =3D F2FS_SUPER_MAGIC; > + unsigned char *p =3D (unsigned char *)buf; > + grub_uint32_t tmp =3D len; > + int i; > + > + while (tmp--) > + { > + crc ^=3D *p++; > + for (i =3D 0; i < 8; i++) > + crc =3D (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_uint= 32_t len) > +{ > + grub_uint32_t cal_crc =3D 0; > + > + cal_crc =3D grub_f2fs_cal_crc32 (buf, len); > + > + return (cal_crc =3D=3D blk_crc) ? 1 : 0; > +} > + > +static inline int > +grub_f2fs_test_bit (grub_uint32_t nr, const char *p) > +{ > + int mask; > + > + p +=3D (nr >> 3); > + mask =3D 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 !=3D grub_cpu_to_le32_compile_time (F2FS_SUPER_MAGIC)) > + return -1; > + > + if (sb->log_blocksize !=3D grub_cpu_to_le32_compile_time (F2FS_BLK_B= ITS)) > + return -1; > + > + log_sectorsize =3D grub_le_to_cpu32 (sb->log_sectorsize); > + log_sectors_per_block =3D grub_le_to_cpu32 (sb->log_sectors_per_bloc= k); > + > + 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 !=3D F2FS_BLK_BITS) > + return -1; > + > + return 0; > +} > + > +static int > +grub_f2fs_read_sb (struct grub_f2fs_data *data, grub_disk_addr_t offse= t) > +{ > + grub_disk_t disk =3D data->disk; > + grub_err_t err; > + > + /* Read first super block. */ > + err =3D grub_disk_read (disk, offset, 0, sizeof (data->sblock), &dat= a->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_add= r, > + grub_uint64_t *version) > +{ > + grub_uint32_t *cp_page_1, *cp_page_2; > + struct grub_f2fs_checkpoint *cp_block; > + grub_uint64_t cur_version =3D 0, pre_version =3D 0; > + grub_uint32_t crc =3D 0; > + grub_uint32_t crc_offset; > + grub_err_t err; > + > + /* Read the 1st cp block in this CP pack */ > + cp_page_1 =3D grub_malloc (F2FS_BLKSIZE); > + if (!cp_page_1) > + return NULL; > + > + err =3D grub_f2fs_block_read (data, cp_addr, cp_page_1); > + if (err) > + goto invalid_cp1; > + > + cp_block =3D (struct grub_f2fs_checkpoint *)cp_page_1; > + crc_offset =3D grub_le_to_cpu32 (cp_block->checksum_offset); > + if (crc_offset !=3D CHECKSUM_OFFSET) > + goto invalid_cp1; > + > + crc =3D 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 =3D grub_le_to_cpu64 (cp_block->checkpoint_ver); > + > + /* Read the 2nd cp block in this CP pack */ > + cp_page_2 =3D grub_malloc (F2FS_BLKSIZE); > + if (!cp_page_2) > + goto invalid_cp1; > + > + cp_addr +=3D grub_le_to_cpu32 (cp_block->cp_pack_total_block_count) = - 1; > + > + err =3D grub_f2fs_block_read (data, cp_addr, cp_page_2); > + if (err) > + goto invalid_cp2; > + > + cp_block =3D (struct grub_f2fs_checkpoint *)cp_page_2; > + crc_offset =3D grub_le_to_cpu32 (cp_block->checksum_offset); > + if (crc_offset !=3D CHECKSUM_OFFSET) > + goto invalid_cp2; > + > + crc =3D 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 =3D grub_le_to_cpu64 (cp_block->checkpoint_ver); > + if (cur_version =3D=3D pre_version) > + { > + *version =3D 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 =3D 0, cp2_version =3D 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 =3D data->cp_blkaddr; > + cp1 =3D 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 +=3D data->blocks_per_seg; > + cp2 =3D validate_checkpoint (data, cp_start_blk_no, &cp2_version); > + if (!cp2 && grub_errno) > + { > + grub_free (cp1); > + return grub_errno; > + } > + > + if (cp1 && cp2) > + cur_page =3D (cp2_version > cp1_version) ? cp2 : cp1; > + else if (cp1) > + cur_page =3D cp1; > + else if (cp2) > + cur_page =3D 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 =3D grub_malloc (F2FS_BLKSIZE); > + if (!buf) > + return grub_errno; > + > + if (CKPT_FLAG_SET(&data->ckpt, CP_COMPACT_SUM_FLAG)) > + block =3D __start_sum_block (data); > + else if (CKPT_FLAG_SET (&data->ckpt, CP_UMOUNT_FLAG)) > + block =3D __sum_blk_addr (data, NR_CURSEG_TYPE, CURSEG_HOT_DATA); > + else > + block =3D __sum_blk_addr (data, NR_CURSEG_DATA_TYPE, CURSEG_HOT_DA= TA); > + > + err =3D 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_SIZ= E); > + > +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 =3D grub_le_to_cpu16 (data->nat_j.n_nats); > + grub_uint32_t blkaddr =3D 0; > + grub_uint16_t i; > + > + for (i =3D 0; i < n; i++) > + { > + if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) =3D=3D nid) > + { > + blkaddr =3D grub_le_to_cpu32 (data->nat_j.entries[i].ne.bloc= k_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 =3D get_blkaddr_from_nat_journal (data, nid); > + if (blkaddr) > + return blkaddr; > + > + nat_block =3D grub_malloc (F2FS_BLKSIZE); > + if (!nat_block) > + return 0; > + > + block_off =3D nid / NAT_ENTRY_PER_BLOCK; > + entry_off =3D nid % NAT_ENTRY_PER_BLOCK; > + > + seg_off =3D block_off / data->blocks_per_seg; > + block_addr =3D 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 +=3D data->blocks_per_seg; > + > + err =3D grub_f2fs_block_read (data, block_addr, nat_block); > + if (err) > + { > + grub_free (nat_block); > + return 0; > + } > + > + blkaddr =3D 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 =3D ADDRS_PER_BLOCK; > + grub_uint32_t dptrs_per_blk =3D NIDS_PER_BLOCK; > + grub_uint32_t indirect_blks =3D ADDRS_PER_BLOCK * NIDS_PER_BLOCK; > + grub_uint32_t dindirect_blks =3D indirect_blks * NIDS_PER_BLOCK; > + grub_uint32_t direct_index =3D DEF_ADDRS_PER_INODE; > + int n =3D 0; > + int level =3D 0; > + > + if (inode->i_inline & F2FS_INLINE_XATTR) > + direct_index -=3D F2FS_INLINE_XATTR_ADDRS; > + > + noffset[0] =3D 0; > + > + if (block < direct_index) > + { > + offset[n] =3D block; > + goto got; > + } > + > + block -=3D direct_index; > + if (block < direct_blks) > + { > + offset[n++] =3D NODE_DIR1_BLOCK; > + noffset[n] =3D 1; > + offset[n] =3D block; > + level =3D 1; > + goto got; > + } > + > + block -=3D direct_blks; > + if (block < direct_blks) > + { > + offset[n++] =3D NODE_DIR2_BLOCK; > + noffset[n] =3D 2; > + offset[n] =3D block; > + level =3D 1; > + goto got; > + } > + > + block -=3D direct_blks; > + if (block < indirect_blks) > + { > + offset[n++] =3D NODE_IND1_BLOCK; > + noffset[n] =3D 3; > + offset[n++] =3D block / direct_blks; > + noffset[n] =3D 4 + offset[n - 1]; > + offset[n] =3D block % direct_blks; > + level =3D 2; > + goto got; > + } > + > + block -=3D indirect_blks; > + if (block < indirect_blks) > + { > + offset[n++] =3D NODE_IND2_BLOCK; > + noffset[n] =3D 4 + dptrs_per_blk; > + offset[n++] =3D block / direct_blks; > + noffset[n] =3D 5 + dptrs_per_blk + offset[n - 1]; > + offset[n] =3D block % direct_blks; > + level =3D 2; > + goto got; > + } > + > + block -=3D indirect_blks; > + if (block < dindirect_blks) > + { > + offset[n++] =3D NODE_DIND_BLOCK; > + noffset[n] =3D 5 + (dptrs_per_blk * 2); > + offset[n++] =3D block / indirect_blks; > + noffset[n] =3D 6 + (dptrs_per_blk * 2) + > + offset[n - 1] * (dptrs_per_blk + 1); > + offset[n++] =3D (block / direct_blks) % dptrs_per_blk; > + noffset[n] =3D 7 + (dptrs_per_blk * 2) + > + offset[n - 2] * (dptrs_per_blk + 1) + offset[n - 1]; > + offset[n] =3D block % direct_blks; > + level =3D 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 =3D 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 =3D grub_malloc (sizeof (*data)); > + if (!data) > + return NULL; > + > + data->disk =3D disk; > + > + if (grub_f2fs_read_sb (data, F2FS_SUPER_OFFSET0)) > + { > + if (grub_f2fs_read_sb (data, F2FS_SUPER_OFFSET1)) > + { > + if (grub_errno =3D=3D GRUB_ERR_NONE) > + grub_error (GRUB_ERR_BAD_FS, > + "not a F2FS filesystem (no superblock)"); > + goto fail; > + } > + } > + > + data->root_ino =3D grub_le_to_cpu32 (data->sblock.root_ino); > + data->cp_blkaddr =3D grub_le_to_cpu32 (data->sblock.cp_blkaddr); > + data->nat_blkaddr =3D grub_le_to_cpu32 (data->sblock.nat_blkaddr); > + data->blocks_per_seg =3D 1 << > + grub_le_to_cpu32 (data->sblock.log_blocks_per_seg); > + > + err =3D grub_f2fs_read_cp (data); > + if (err) > + goto fail; > + > + data->nat_bitmap =3D __nat_bitmap_ptr (data); > + > + err =3D get_nat_journal (data); > + if (err) > + goto fail; > + > + data->diropen.data =3D data; > + data->diropen.ino =3D data->root_ino; > + data->diropen.inode_read =3D 1; > + data->inode =3D &data->diropen.inode; > + > + err =3D 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_o= fs) > +{ > + struct grub_f2fs_data *data =3D node->data; > + struct grub_f2fs_inode *inode =3D &node->inode.i; > + grub_uint32_t offset[4], noffset[4], nids[4]; > + struct grub_f2fs_node *node_block; > + grub_uint32_t block_addr =3D -1; > + int level, i; > + > + level =3D grub_get_node_path (inode, block_ofs, offset, noffset); > + if (level =3D=3D 0) > + return grub_le_to_cpu32 (inode->i_addr[offset[0]]); > + > + node_block =3D grub_malloc (F2FS_BLKSIZE); > + if (!node_block) > + return -1; > + > + nids[1] =3D __get_node_id (&node->inode, offset[0], 1); > + > + /* get indirect or direct nodes */ > + for (i =3D 1; i <=3D level; i++) > + { > + grub_f2fs_read_node (data, nids[i], node_block); > + if (grub_errno) > + goto fail; > + > + if (i < level) > + nids[i + 1] =3D __get_node_id (node_block, offset[i], 0); > + } > + > + block_addr =3D 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 =3D &node->inode.i; > + grub_off_t filesize =3D grub_f2fs_file_size (inode); > + char *inline_addr =3D __inline_addr (inode); > + > + if (inode->i_inline & F2FS_INLINE_DATA) > + { > + if (filesize > MAX_INLINE_DATA) > + return -1; > + if (len > filesize - pos) > + len =3D filesize - pos; > + > + grub_memcpy (buf, 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 =3D 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 =3D grub_f2fs_file_size(&diro->inode.i); > + > + symlink =3D 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] =3D '\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 =3D 0; i < ctx->max;) > + { > + char *filename; > + enum grub_fshelp_filetype type =3D GRUB_FSHELP_UNKNOWN; > + enum FILE_TYPE ftype; > + int name_len; > + int ret; > + > + if (grub_f2fs_test_bit_le (i, ctx->bitmap) =3D=3D 0) > + { > + i++; > + continue; > + } > + > + ftype =3D ctx->dentry[i].file_type; > + name_len =3D grub_le_to_cpu16 (ctx->dentry[i].name_len); > + filename =3D grub_malloc (name_len + 1); > + if (!filename) > + return 0; > + > + grub_memcpy (filename, ctx->filename[i], name_len); > + filename[name_len] =3D 0; > + > + fdiro =3D grub_malloc (sizeof (struct grub_fshelp_node)); > + if (!fdiro) > + { > + grub_free(filename); > + return 0; > + } > + > + if (ftype =3D=3D F2FS_FT_DIR) > + type =3D GRUB_FSHELP_DIR; > + else if (ftype =3D=3D F2FS_FT_SYMLINK) > + type =3D GRUB_FSHELP_SYMLINK; > + else if (ftype =3D=3D F2FS_FT_REG_FILE) > + type =3D GRUB_FSHELP_REG; > + > + fdiro->data =3D ctx->data; > + fdiro->ino =3D grub_le_to_cpu32 (ctx->dentry[i].ino); > + fdiro->inode_read =3D 0; > + > + ret =3D ctx->hook (filename, type, fdiro, ctx->hook_data); > + grub_free(filename); > + if (ret) > + return 1; > + > + i +=3D (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 =3D (struct grub_f2fs_inline_dentry *) __inline_addr (dir); > + > + ctx->bitmap =3D de_blk->dentry_bitmap; > + ctx->dentry =3D de_blk->dentry; > + ctx->filename =3D de_blk->filename; > + ctx->max =3D 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 =3D (struct grub_fshelp_node *) dir; > + struct grub_f2fs_inode *inode; > + struct grub_f2fs_dir_iter_ctx ctx =3D { > + .data =3D diro->data, > + .hook =3D hook, > + .hook_data =3D hook_data > + }; > + grub_off_t fpos =3D 0; > + > + if (!diro->inode_read) > + { > + grub_f2fs_read_node (diro->data, diro->ino, &diro->inode); > + if (grub_errno) > + return 0; > + } > + > + inode =3D &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 =3D 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 =3D (struct grub_f2fs_dentry_block *) buf; > + > + ctx.bitmap =3D de_blk->dentry_bitmap; > + ctx.dentry =3D de_blk->dentry; > + ctx.filename =3D de_blk->filename; > + ctx.max =3D NR_DENTRY_IN_BLOCK; > + > + ret =3D grub_f2fs_check_dentries (&ctx); > + grub_free (buf); > + if (ret) > + return 1; > + > + fpos +=3D F2FS_BLKSIZE; > + } > + return 0; > +} > + > +static int > +grub_f2fs_dir_iter (const char *filename, enum grub_fshelp_filetype fi= letype, > + grub_fshelp_node_t node, void *data) > +{ > + struct grub_f2fs_dir_ctx *ctx =3D 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 =3D 1; > + grub_errno =3D GRUB_ERR_NONE; > + } > + if (node->inode_read) > + { > + info.mtimeset =3D 1; > + info.mtime =3D grub_le_to_cpu64 (node->inode.i.i_mtime); > + } > + > + info.dir =3D ((filetype & GRUB_FSHELP_TYPE_MASK) =3D=3D 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 =3D { > + .hook =3D hook, > + .hook_data =3D hook_data > + }; > + struct grub_fshelp_node *fdiro =3D 0; > + > + grub_dl_ref (my_mod); > + > + ctx.data =3D 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 !=3D &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 =3D NULL; > + struct grub_fshelp_node *fdiro =3D 0; > + struct grub_f2fs_inode *inode; > + > + grub_dl_ref (my_mod); > + > + data =3D 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 =3D &(data->inode->i); > + file->size =3D grub_f2fs_file_size (inode); > + file->data =3D data; > + file->offset =3D 0; > + > + if (inode->i_inline & F2FS_INLINE_DATA && file->size > MAX_INLINE_DA= TA) > + grub_error (GRUB_ERR_BAD_FS, "corrupted inline_data: need fsck"); > + return 0; > + > +fail: > + if (fdiro !=3D &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 =3D (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 =3D (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 =3D 0; > + > + out_buf =3D grub_malloc (MAX_VOLUME_NAME * GRUB_MAX_UTF8_PER_UTF16 += 1); > + if (!out_buf) > + return NULL; > + > + while (*in_buf_le !=3D 0 && len < MAX_VOLUME_NAME) { > + in_buf[len] =3D grub_le_to_cpu16 (in_buf_le[len]); > + len++; > + } > + > + *grub_utf16_to_utf8 (out_buf, in_buf, len) =3D '\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 =3D device->disk; > + > + grub_dl_ref (my_mod); > + > + data =3D grub_f2fs_mount (disk); > + if (data) > + *label =3D (char *) grub_f2fs_utf16_to_utf8 (data->sblock.volume_n= ame); > + else > + *label =3D 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 =3D device->disk; > + > + grub_dl_ref (my_mod); > + > + data =3D grub_f2fs_mount (disk); > + if (data) > + { > + *uuid =3D > + grub_xasprintf > + ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02= x", > + 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 =3D NULL; > + > + grub_free (data); > + grub_dl_unref (my_mod); > + return grub_errno; > +} > + > +static struct grub_fs grub_f2fs_fs =3D { > + .name =3D "f2fs", > + .dir =3D grub_f2fs_dir, > + .open =3D grub_f2fs_open, > + .read =3D grub_f2fs_read, > + .close =3D grub_f2fs_close, > + .label =3D grub_f2fs_label, > + .uuid =3D grub_f2fs_uuid, > +#ifdef GRUB_UTIL > + .reserved_first_sector =3D 1, > + .blocklist_install =3D 0, > +#endif > + .next =3D 0 > +}; > + > +GRUB_MOD_INIT (f2fs) > +{ > + grub_fs_register (&grub_f2fs_fs); > + my_mod =3D 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 "" > =20 > #: 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%02= x%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" =3D "x" ] ; then > + EUID=3D`id -u` > +fi > + > +if [ "$EUID" !=3D 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.i= n > index 424de22..e3e4109 100644 > --- a/tests/util/grub-fs-tester.in > +++ b/tests/util/grub-fs-tester.in > @@ -142,7 +142,7 @@ for ((LOGSECSIZE=3DMINLOGSECSIZE;LOGSECSIZE<=3DMAXL= OGSECSIZE;LOGSECSIZE=3DLOGSECSIZE + > xsquash*) > MINBLKSIZE=3D4096 > MAXBLKSIZE=3D1048576;; > - xxfs) > + xxfs|xf2fs) > MINBLKSIZE=3D$SECSIZE > # OS Limitation: GNU/Linux doesn't accept > 4096 > MAXBLKSIZE=3D4096;; > @@ -265,6 +265,10 @@ for ((LOGSECSIZE=3DMINLOGSECSIZE;LOGSECSIZE<=3DMAX= LOGSECSIZE;LOGSECSIZE=3DLOGSECSIZE + > x"btrfs"*) > FSLABEL=3D"grub_;/test=C3=A9=F0=AF=A6=9B=F0=AF=A6=9D=F0=9F=98=81= =D0=BA=D0=B8=D1=80=D0=B8=D1=82i urewfceniuewruevrewnuuireurevueurnievrewf= nerfcnevirivinrewvnirewnivrewiuvcrewvnuewvrrrewniuerwreiuviurewiuviurewnu= vewnvrenurnunuvrevuurerejiremvreijnvcreivire nverivnreivrevnureiorfnfrvoe= oiroireoireoifrefoieroifoireoif";; > =20 > + # FS LIMITATION: f2fs label is at most 512 UTF-16 chars > + x"f2fs") > + FSLABEL=3D"grub_;/test=C3=A9=E4=8F=8C=E4=90=93=E4=8F=95=D0=BA=D0= =B8=D1=80=D0=B8=D1=82iurewfceniuewruewnuuireurevueurnievrewfnerfcnevirivi= nrewvnirewnivrewiuvcrewvnuewvrrrewniuerwreiuviurewiuviurewnuvewnvrenurnun= uvrevuurerejiremvreijnvvcreivire nverivnreivrevnureiorfnfrvoeoiroireoireo= ifrefoieroifoirvcreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoie= roifoircreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoireo= ifoiq";; > + > # FS LIMITATION: exfat is at most 15 UTF-16 chars > x"exfat") > FSLABEL=3D"g=C3=A9=D1=82 ;/=F0=AF=A6=9B=F0=AF=A6=9D=F0=9F=98=81=D0= =BA=D0=B8=D1=80";; > @@ -474,7 +478,7 @@ for ((LOGSECSIZE=3DMINLOGSECSIZE;LOGSECSIZE<=3DMAXL= OGSECSIZE;LOGSECSIZE=3DLOGSECSIZE + > # 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 mod= ification date. > x"jfs_caseins" | x"jfs" | x"xfs" | x"xfs_crc" | x"btrfs"* | x"reiser= fs_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=3Dy;; > @@ -753,6 +757,8 @@ for ((LOGSECSIZE=3DMINLOGSECSIZE;LOGSECSIZE<=3DMAXL= OGSECSIZE;LOGSECSIZE=3DLOGSECSIZE + > MOUNTDEVICE=3D"/dev/mapper/grub_test-testvol" > MOUNTFS=3Dext2 > "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) > --=20 > 2.6.3 >=20 >=20 > -----------------------------------------------------------------------= ------- > Site24x7 APM Insight: Get Deep Visibility into Application Performance > APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month > Monitor end-to-end web transactions and take corrective actions now > Troubleshoot faster and improve end-user experience. Signup Now! > http://pubads.g.doubleclick.net/gampad/clk?id=3D272487151&iu=3D/4140 > _______________________________________________ > Linux-f2fs-devel mailing list > Linux-f2fs-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jaegeuk Kim Subject: Re: [2.02] Re: [PATCH v8] F2FS support Date: Thu, 4 Aug 2016 10:06:05 -0700 Message-ID: <20160804170605.GA12013@jaegeuk> 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> <56D5F2E9.1070501@gmail.com> <20160303213653.GB15612@jaegeuk.hsd1.ca.comcast.net> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from sog-mx-2.v43.ch3.sourceforge.com ([172.29.43.192] helo=mx.sourceforge.net) by sfs-ml-4.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1bVM69-0003Z6-7R for linux-f2fs-devel@lists.sourceforge.net; Thu, 04 Aug 2016 17:06:21 +0000 Received: from mail.kernel.org ([198.145.29.136]) by sog-mx-2.v43.ch3.sourceforge.com with esmtps (TLSv1:AES256-SHA:256) (Exim 4.76) id 1bVM65-0005pF-OZ for linux-f2fs-devel@lists.sourceforge.net; Thu, 04 Aug 2016 17:06:21 +0000 Content-Disposition: inline In-Reply-To: <20160303213653.GB15612@jaegeuk.hsd1.ca.comcast.net> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linux-f2fs-devel-bounces@lists.sourceforge.net To: Andrei Borzenkov Cc: The development of GNU GRUB , linux-f2fs-devel@lists.sourceforge.net SGkgQW5kcmVpLAoKSXQncyBiZWVuIHNpdHRpbmcgZm9yIGEgbG9uZyBsb25nIHRpbWUuCk1heSBJ IGFzayB3aGV0aGVyIG9yIG5vdCB0aGVyZSBpcyBhbnkgbWVyZ2luZyBwbGFuIG9mIHRoaXM/CgpU aGFua3MsCgpPbiBUaHUsIE1hciAwMywgMjAxNiBhdCAwMTozNjo1M1BNIC0wODAwLCBKYWVnZXVr IEtpbSB3cm90ZToKPiBDaGFuZ2UgbG9nIGZyb20gdjc6Cj4gIC0gZml4IGFuIG9mZnNldCBidWcg aW4gcmVhZF9maWxlCj4gCj4gLS0gPjggLS0KPiBGcm9tIGQ3NzRjZGVjYzJmZWUxOGVkNDQwOThj ODhkMmE1NGQzNThiYzA0ZDMgTW9uIFNlcCAxNyAwMDowMDowMCAyMDAxCj4gRnJvbTogSmFlZ2V1 ayBLaW0gPGphZWdldWtAa2VybmVsLm9yZz4KPiBEYXRlOiBUdWUsIDE3IE5vdiAyMDE1IDEyOjQ1 OjEzIC0wODAwCj4gU3ViamVjdDogW1BBVENIXSBGMkZTIHN1cHBvcnQKPiAKPiAiRjJGUyAoRmxh c2gtRnJpZW5kbHkgRmlsZSBTeXN0ZW0pIGlzIGZsYXNoLWZyaWVuZGx5IGZpbGUgc3lzdGVtIHdo aWNoIHdhcyBtZXJnZWQKPiBpbnRvIExpbnV4IGtlcm5lbCB2My44IGluIDIwMTMuCj4gCj4gVGhl IG1vdGl2ZSBmb3IgRjJGUyB3YXMgdG8gYnVpbGQgYSBmaWxlIHN5c3RlbSB0aGF0IGZyb20gdGhl IHN0YXJ0LCB0YWtlcyBpbnRvCj4gYWNjb3VudCB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIE5BTkQg Zmxhc2ggbWVtb3J5LWJhc2VkIHN0b3JhZ2UgZGV2aWNlcyAoc3VjaCBhcwo+IHNvbGlkLXN0YXRl IGRpc2tzLCBlTU1DLCBhbmQgU0QgY2FyZHMpLgo+IAo+IEYyRlMgd2FzIGRlc2lnbmVkIG9uIGEg YmFzaXMgb2YgYSBsb2ctc3RydWN0dXJlZCBmaWxlIHN5c3RlbSBhcHByb2FjaCwgd2hpY2gKPiBy ZW1lZGllcyBzb21lIGtub3duIGlzc3VlcyBvZiB0aGUgb2xkZXIgbG9nIHN0cnVjdHVyZWQgZmls ZSBzeXN0ZW1zLCBzdWNoIGFzCj4gdGhlIHNub3diYWxsIGVmZmVjdCBvZiB3YW5kZXJpbmcgdHJl ZXMgYW5kIGhpZ2ggY2xlYW5pbmcgb3ZlcmhlYWQuIEluIGFkZGl0aW9uLAo+IHNpbmNlIGEgTkFO RC1iYXNlZCBzdG9yYWdlIGRldmljZSBzaG93cyBkaWZmZXJlbnQgY2hhcmFjdGVyaXN0aWNzIGFj Y29yZGluZyB0bwo+IGl0cyBpbnRlcm5hbCBnZW9tZXRyeSBvciBmbGFzaCBtZW1vcnkgbWFuYWdl bWVudCBzY2hlbWUgKHN1Y2ggYXMgdGhlIEZsYXNoCj4gVHJhbnNsYXRpb24gTGF5ZXIgb3IgRlRM KSwgaXQgc3VwcG9ydHMgdmFyaW91cyBwYXJhbWV0ZXJzIG5vdCBvbmx5IGZvcgo+IGNvbmZpZ3Vy aW5nIG9uLWRpc2sgbGF5b3V0LCBidXQgYWxzbyBmb3Igc2VsZWN0aW5nIGFsbG9jYXRpb24gYW5k IGNsZWFuaW5nCj4gYWxnb3JpdGhtLiIsIHF1b3RlIGJ5IGh0dHBzOi8vZW4ud2lraXBlZGlhLm9y Zy93aWtpL0YyRlMuCj4gCj4gVGhlIHNvdXJjZSBjb2RlcyBmb3IgRjJGUyBhcmUgYXZhaWxhYmxl IGZyb206Cj4gCj4gaHR0cDovL2dpdC5rZXJuZWwub3JnL2NnaXQvbGludXgva2VybmVsL2dpdC9q YWVnZXVrL2YyZnMuZ2l0Cj4gaHR0cDovL2dpdC5rZXJuZWwub3JnL2NnaXQvbGludXgva2VybmVs L2dpdC9qYWVnZXVrL2YyZnMtdG9vbHMuZ2l0Cj4gCj4gU2lnbmVkLW9mZi1ieTogSmFlZ2V1ayBL aW0gPGphZWdldWtAa2VybmVsLm9yZz4KPiAtLS0KPiAgTWFrZWZpbGUudXRpbC5kZWYgICAgICAg ICAgICB8ICAgIDcgKwo+ICBkb2NzL2dydWIudGV4aSAgICAgICAgICAgICAgIHwgICAgNSArLQo+ ICBncnViLWNvcmUvTWFrZWZpbGUuY29yZS5kZWYgIHwgICAgNSArCj4gIGdydWItY29yZS9mcy9m MmZzLmMgICAgICAgICAgfCAxMjg5ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKwo+ICBwby9leGNsdWRlLnBvdCAgICAgICAgICAgICAgIHwgICAgMSArCj4gIHRlc3Rz L2YyZnNfdGVzdC5pbiAgICAgICAgICAgfCAgIDE5ICsKPiAgdGVzdHMvdXRpbC9ncnViLWZzLXRl c3Rlci5pbiB8ICAgMTAgKy0KPiAgNyBmaWxlcyBjaGFuZ2VkLCAxMzMyIGluc2VydGlvbnMoKyks IDQgZGVsZXRpb25zKC0pCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBncnViLWNvcmUvZnMvZjJmcy5j Cj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCB0ZXN0cy9mMmZzX3Rlc3QuaW4KPiAKPiBkaWZmIC0tZ2l0 IGEvTWFrZWZpbGUudXRpbC5kZWYgYi9NYWtlZmlsZS51dGlsLmRlZgo+IGluZGV4IGRiN2U4ZWMu Ljg0NjI3YmIgMTAwNjQ0Cj4gLS0tIGEvTWFrZWZpbGUudXRpbC5kZWYKPiArKysgYi9NYWtlZmls ZS51dGlsLmRlZgo+IEBAIC05OSw2ICs5OSw3IEBAIGxpYnJhcnkgPSB7Cj4gICAgY29tbW9uID0g Z3J1Yi1jb3JlL2ZzL2V4dDIuYzsKPiAgICBjb21tb24gPSBncnViLWNvcmUvZnMvZmF0LmM7Cj4g ICAgY29tbW9uID0gZ3J1Yi1jb3JlL2ZzL2V4ZmF0LmM7Cj4gKyAgY29tbW9uID0gZ3J1Yi1jb3Jl L2ZzL2YyZnMuYzsKPiAgICBjb21tb24gPSBncnViLWNvcmUvZnMvZnNoZWxwLmM7Cj4gICAgY29t bW9uID0gZ3J1Yi1jb3JlL2ZzL2hmcy5jOwo+ICAgIGNvbW1vbiA9IGdydWItY29yZS9mcy9oZnNw bHVzLmM7Cj4gQEAgLTc2Niw2ICs3NjcsMTIgQEAgc2NyaXB0ID0gewo+ICAKPiAgc2NyaXB0ID0g ewo+ICAgIHRlc3RjYXNlOwo+ICsgIG5hbWUgPSBmMmZzX3Rlc3Q7Cj4gKyAgY29tbW9uID0gdGVz dHMvZjJmc190ZXN0LmluOwo+ICt9Owo+ICsKPiArc2NyaXB0ID0gewo+ICsgIHRlc3RjYXNlOwo+ ICAgIG5hbWUgPSBuaWxmczJfdGVzdDsKPiAgICBjb21tb24gPSB0ZXN0cy9uaWxmczJfdGVzdC5p bjsKPiAgfTsKPiBkaWZmIC0tZ2l0IGEvZG9jcy9ncnViLnRleGkgYi9kb2NzL2dydWIudGV4aQo+ IGluZGV4IDFkZjNkYjIuLmU1YTgwZjMgMTAwNjQ0Cj4gLS0tIGEvZG9jcy9ncnViLnRleGkKPiAr KysgYi9kb2NzL2dydWIudGV4aQo+IEBAIC0zNjAsNyArMzYwLDggQEAgYmxvY2tsaXN0IG5vdGF0 aW9uLiBUaGUgY3VycmVudGx5IHN1cHBvcnRlZCBmaWxlc3lzdGVtIHR5cGVzIGFyZSBAZGZue0Ft aWdhCj4gIEZhc3QgRmlsZVN5c3RlbSAoQUZGUyl9LCBAZGZue0F0aGVPUyBmc30sIEBkZm57QmVG U30sCj4gIEBkZm57QnRyRlN9IChpbmNsdWRpbmcgcmFpZDAsIHJhaWQxLCByYWlkMTAsIGd6aXAg YW5kIGx6byksCj4gIEBkZm57Y3Bpb30gKGxpdHRsZS0gYW5kIGJpZy1lbmRpYW4gYmluLCBvZGMg YW5kIG5ld2MgdmFyaWFudHMpLAo+IC1AZGZue0xpbnV4IGV4dDIvZXh0My9leHQ0fSwgQGRmbntE T1MgRkFUMTIvRkFUMTYvRkFUMzJ9LCBAZGZue2V4RkFUfSwgQGRmbntIRlN9LAo+ICtAZGZue0xp bnV4IGV4dDIvZXh0My9leHQ0fSwgQGRmbntET1MgRkFUMTIvRkFUMTYvRkFUMzJ9LCBAZGZue2V4 RkFUfSwKPiArQGRmbntmMmZzfSwgQGRmbntIRlN9LAo+ICBAZGZue0hGUyt9LCBAZGZue0lTTzk2 NjB9IChpbmNsdWRpbmcgSm9saWV0LCBSb2NrLXJpZGdlIGFuZCBtdWx0aS1jaHVuayBmaWxlcyks Cj4gIEBkZm57SkZTfSwgQGRmbntNaW5peCBmc30gKHZlcnNpb25zIDEsIDIgYW5kIDMpLCBAZGZu e25pbGZzMn0sCj4gIEBkZm57TlRGU30gKGluY2x1ZGluZyBjb21wcmVzc2lvbiksIEBkZm57UmVp c2VyRlN9LCBAZGZue1JPTUZTfSwKPiBAQCAtNTM0Nyw3ICs1MzQ4LDcgQEAgTlRGUywgSkZTLCBV REYsIEhGUyssIGV4RkFULCBsb25nIGZpbGVuYW1lcyBpbiBGQVQsIEpvbGlldCBwYXJ0IG9mCj4g IElTTzk2NjAgYXJlIHRyZWF0ZWQgYXMgVVRGLTE2IGFzIHBlciBzcGVjaWZpY2F0aW9uLiBBRlMg YW5kIEJGUyBhcmUgcmVhZAo+ICBhcyBVVEYtOCwgYWdhaW4gYWNjb3JkaW5nIHRvIHNwZWNpZmlj YXRpb24uIEJ0ckZTLCBjcGlvLCB0YXIsIHNxdWFzaDQsIG1pbml4LAo+ICBtaW5peDIsIG1pbml4 MywgUk9NRlMsIFJlaXNlckZTLCBYRlMsIGV4dDIsIGV4dDMsIGV4dDQsIEZBVCAoc2hvcnQgbmFt ZXMpLAo+IC1Sb2NrUmlkZ2UgcGFydCBvZiBJU085NjYwLCBuaWxmczIsIFVGUzEsIFVGUzIgYW5k IFpGUyBhcmUgYXNzdW1lZAo+ICtmMmZzLCBSb2NrUmlkZ2UgcGFydCBvZiBJU085NjYwLCBuaWxm czIsIFVGUzEsIFVGUzIgYW5kIFpGUyBhcmUgYXNzdW1lZAo+ICB0byBiZSBVVEYtOC4gVGhpcyBt aWdodCBiZSBmYWxzZSBvbiBzeXN0ZW1zIGNvbmZpZ3VyZWQgd2l0aCBsZWdhY3kgY2hhcnNldAo+ ICBidXQgYXMgbG9uZyBhcyB0aGUgY2hhcnNldCB1c2VkIGlzIHN1cGVyc2V0IG9mIEFTQ0lJIHlv dSBzaG91bGQgYmUgYWJsZSB0bwo+ICBhY2Nlc3MgQVNDSUktbmFtZWQgZmlsZXMuIEFuZCBpdCdz IHJlY29tbWVuZGVkIHRvIGNvbmZpZ3VyZSB5b3VyIHN5c3RlbSB0byB1c2UKPiBkaWZmIC0tZ2l0 IGEvZ3J1Yi1jb3JlL01ha2VmaWxlLmNvcmUuZGVmIGIvZ3J1Yi1jb3JlL01ha2VmaWxlLmNvcmUu ZGVmCj4gaW5kZXggZDlmYTBlMy4uYjU4NWFkZSAxMDA2NDQKPiAtLS0gYS9ncnViLWNvcmUvTWFr ZWZpbGUuY29yZS5kZWYKPiArKysgYi9ncnViLWNvcmUvTWFrZWZpbGUuY29yZS5kZWYKPiBAQCAt MTI3OCw2ICsxMjc4LDExIEBAIG1vZHVsZSA9IHsKPiAgfTsKPiAgCj4gIG1vZHVsZSA9IHsKPiAr ICBuYW1lID0gZjJmczsKPiArICBjb21tb24gPSBmcy9mMmZzLmM7Cj4gK307Cj4gKwo+ICttb2R1 bGUgPSB7Cj4gICAgbmFtZSA9IGZzaGVscDsKPiAgICBjb21tb24gPSBmcy9mc2hlbHAuYzsKPiAg fTsKPiBkaWZmIC0tZ2l0IGEvZ3J1Yi1jb3JlL2ZzL2YyZnMuYyBiL2dydWItY29yZS9mcy9mMmZz LmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLjdmYjI1NmYKPiAtLS0g L2Rldi9udWxsCj4gKysrIGIvZ3J1Yi1jb3JlL2ZzL2YyZnMuYwo+IEBAIC0wLDAgKzEsMTI4OSBA QAo+ICsvKgo+ICsgKiAgZjJmcy5jIC0gRmxhc2gtRnJpZW5kbHkgRmlsZSBTeXN0ZW0KPiArICoK PiArICogIFdyaXR0ZW4gYnkgSmFlZ2V1ayBLaW0gPGphZWdldWtAa2VybmVsLm9yZz4KPiArICoK PiArICogIENvcHlyaWdodCAoQykgMjAxNSAgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBJbmMu Cj4gKyAqCj4gKyAqICBHUlVCIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRl IGl0IGFuZC9vciBtb2RpZnkKPiArICogIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdl bmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5Cj4gKyAqICB0aGUgRnJlZSBTb2Z0 d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvcgo+ICsg KiAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KPiArICoKPiArICogIEdSVUIg aXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKPiArICog IGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJh bnR5IG9mCj4gKyAqICBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFS IFBVUlBPU0UuICBTZWUgdGhlCj4gKyAqICBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3Ig bW9yZSBkZXRhaWxzLgo+ICsgKgo+ICsgKiAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29w eSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKPiArICogIGFsb25nIHdpdGggR1JV Qi4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi4KPiArICovCj4g KyNpbmNsdWRlIDxncnViL2Vyci5oPgo+ICsjaW5jbHVkZSA8Z3J1Yi9maWxlLmg+Cj4gKyNpbmNs dWRlIDxncnViL21tLmg+Cj4gKyNpbmNsdWRlIDxncnViL21pc2MuaD4KPiArI2luY2x1ZGUgPGdy dWIvZGlzay5oPgo+ICsjaW5jbHVkZSA8Z3J1Yi9kbC5oPgo+ICsjaW5jbHVkZSA8Z3J1Yi90eXBl cy5oPgo+ICsjaW5jbHVkZSA8Z3J1Yi9jaGFyc2V0Lmg+Cj4gKyNpbmNsdWRlIDxncnViL2ZzaGVs cC5oPgo+ICsKPiArR1JVQl9NT0RfTElDRU5TRSAoIkdQTHYzKyIpOwo+ICsKPiArLyogRjJGUyBN YWdpYyBOdW1iZXIgKi8KPiArI2RlZmluZSBGMkZTX1NVUEVSX01BR0lDCTB4RjJGNTIwMTAKPiAr I2RlZmluZSBDSEVDS1NVTV9PRkZTRVQJCTQwOTIJCS8qIG11c3QgYmUgYWxpZ25lZCA0IGJ5dGVz ICovCj4gKyNkZWZpbmUgVTMyX0NIRUNLU1VNX09GRlNFVAkoQ0hFQ0tTVU1fT0ZGU0VUID4+IDIp Cj4gKwo+ICsvKiBieXRlLXNpemUgb2Zmc2V0ICovCj4gKyNkZWZpbmUgRjJGU19TVVBFUl9PRkZT RVQJKChncnViX2Rpc2tfYWRkcl90KTEwMjQpCj4gKyNkZWZpbmUgRjJGU19TVVBFUl9PRkZTRVQw CShGMkZTX1NVUEVSX09GRlNFVCA+PiBHUlVCX0RJU0tfU0VDVE9SX0JJVFMpCj4gKyNkZWZpbmUg RjJGU19TVVBFUl9PRkZTRVQxCSgoRjJGU19TVVBFUl9PRkZTRVQgKyBGMkZTX0JMS1NJWkUpID4+ CVwKPiArCQkJCQkJR1JVQl9ESVNLX1NFQ1RPUl9CSVRTKQo+ICsKPiArLyogOSBiaXRzIGZvciA1 MTIgYnl0ZXMgKi8KPiArI2RlZmluZSBGMkZTX01JTl9MT0dfU0VDVE9SX1NJWkUJOQo+ICsKPiAr Lyogc3VwcG9ydCBvbmx5IDRLQiBibG9jayAqLwo+ICsjZGVmaW5lIEYyRlNfQkxLX0JJVFMJMTIK PiArI2RlZmluZSBGMkZTX0JMS1NJWkUJKDEgPDwgRjJGU19CTEtfQklUUykKPiArI2RlZmluZSBG MkZTX0JMS19TRUNfQklUUwkoRjJGU19CTEtfQklUUyAtIEdSVUJfRElTS19TRUNUT1JfQklUUykK PiArCj4gKyNkZWZpbmUgVkVSU0lPTl9MRU4JMjU2Cj4gKyNkZWZpbmUgRjJGU19NQVhfRVhURU5T SU9OCTY0Cj4gKwo+ICsjZGVmaW5lIENQX0NPTVBBQ1RfU1VNX0ZMQUcJMHgwMDAwMDAwNAo+ICsj ZGVmaW5lIENQX1VNT1VOVF9GTEFHCTB4MDAwMDAwMDEKPiArCj4gKyNkZWZpbmUgTUFYX0FDVElW RV9MT0dTCTE2Cj4gKyNkZWZpbmUgTUFYX0FDVElWRV9OT0RFX0xPR1MJOAo+ICsjZGVmaW5lIE1B WF9BQ1RJVkVfREFUQV9MT0dTCTgKPiArI2RlZmluZQlOUl9DVVJTRUdfREFUQV9UWVBFCTMKPiAr I2RlZmluZSBOUl9DVVJTRUdfTk9ERV9UWVBFCTMKPiArI2RlZmluZSBOUl9DVVJTRUdfVFlQRQko TlJfQ1VSU0VHX0RBVEFfVFlQRSArIE5SX0NVUlNFR19OT0RFX1RZUEUpCj4gKwo+ICsjZGVmaW5l IEVOVFJJRVNfSU5fU1VNCTUxMgo+ICsjZGVmaW5lCVNVTU1BUllfU0laRQk3Cj4gKyNkZWZpbmUJ U1VNX0ZPT1RFUl9TSVpFCTUKPiArI2RlZmluZSBKRU5UUllfU0laRQkoc2l6ZW9mKHN0cnVjdCBn cnViX2YyZnNfbmF0X2plbnQpKQo+ICsjZGVmaW5lIFNVTV9FTlRSSUVTX1NJWkUJKFNVTU1BUllf U0laRSAqIEVOVFJJRVNfSU5fU1VNKQo+ICsjZGVmaW5lIFNVTV9KT1VSTkFMX1NJWkUJKEYyRlNf QkxLU0laRSAtIFNVTV9GT09URVJfU0laRSAtXAo+ICsJCQkJU1VNX0VOVFJJRVNfU0laRSkKPiAr I2RlZmluZSBOQVRfSk9VUk5BTF9FTlRSSUVTCSgoU1VNX0pPVVJOQUxfU0laRSAtIDIpIC8gSkVO VFJZX1NJWkUpCj4gKyNkZWZpbmUgTkFUX0pPVVJOQUxfUkVTRVJWRUQJKChTVU1fSk9VUk5BTF9T SVpFIC0gMikgJSBKRU5UUllfU0laRSkKPiArCj4gKyNkZWZpbmUgTkFUX0VOVFJZX1NJWkUgKHNp emVvZihzdHJ1Y3QgZ3J1Yl9mMmZzX25hdF9lbnRyeSkpCj4gKyNkZWZpbmUgTkFUX0VOVFJZX1BF Ul9CTE9DSyAoRjJGU19CTEtTSVpFIC8gTkFUX0VOVFJZX1NJWkUpCj4gKwo+ICsjZGVmaW5lIEYy RlNfTkFNRV9MRU4JMjU1Cj4gKyNkZWZpbmUgRjJGU19TTE9UX0xFTgk4Cj4gKyNkZWZpbmUgTlJf REVOVFJZX0lOX0JMT0NLCTIxNAo+ICsjZGVmaW5lIFNJWkVfT0ZfRElSX0VOVFJZCTExCS8qIGJ5 IGJ5dGUgKi8KPiArI2RlZmluZSBCSVRTX1BFUl9CWVRFCTgKPiArI2RlZmluZSBTSVpFX09GX0RF TlRSWV9CSVRNQVAJKChOUl9ERU5UUllfSU5fQkxPQ0sgKyBCSVRTX1BFUl9CWVRFIC0gMSkgLyBc Cj4gKwkJCQlCSVRTX1BFUl9CWVRFKQo+ICsjZGVmaW5lIFNJWkVfT0ZfUkVTRVJWRUQJKEYyRlNf QkxLU0laRSAtICgoU0laRV9PRl9ESVJfRU5UUlkgKyBcCj4gKwkJCQlGMkZTX1NMT1RfTEVOKSAq IFwKPiArCQkJCU5SX0RFTlRSWV9JTl9CTE9DSyArIFNJWkVfT0ZfREVOVFJZX0JJVE1BUCkpCj4g Kwo+ICsjZGVmaW5lIEYyRlNfSU5MSU5FX1hBVFRSX0FERFJTCTUwCS8qIDIwMCBieXRlcyBmb3Ig aW5saW5lIHhhdHRycyAqLwo+ICsjZGVmaW5lIERFRl9BRERSU19QRVJfSU5PREUJOTIzCS8qIEFk ZHJlc3MgUG9pbnRlcnMgaW4gYW4gSW5vZGUgKi8KPiArCj4gKyNkZWZpbmUgQUREUlNfUEVSX0JM T0NLCTEwMTgJLyogQWRkcmVzcyBQb2ludGVycyBpbiBhIERpcmVjdCBCbG9jayAqLwo+ICsjZGVm aW5lIE5JRFNfUEVSX0JMT0NLCTEwMTgJLyogTm9kZSBJRHMgaW4gYW4gSW5kaXJlY3QgQmxvY2sg Ki8KPiArI2RlZmluZQlOT0RFX0RJUjFfQkxPQ0sJKERFRl9BRERSU19QRVJfSU5PREUgKyAxKQo+ ICsjZGVmaW5lCU5PREVfRElSMl9CTE9DSwkoREVGX0FERFJTX1BFUl9JTk9ERSArIDIpCj4gKyNk ZWZpbmUJTk9ERV9JTkQxX0JMT0NLCShERUZfQUREUlNfUEVSX0lOT0RFICsgMykKPiArI2RlZmlu ZQlOT0RFX0lORDJfQkxPQ0sJKERFRl9BRERSU19QRVJfSU5PREUgKyA0KQo+ICsjZGVmaW5lCU5P REVfRElORF9CTE9DSwkoREVGX0FERFJTX1BFUl9JTk9ERSArIDUpCj4gKwo+ICsjZGVmaW5lIE1B WF9JTkxJTkVfREFUQQkoNCAqIChERUZfQUREUlNfUEVSX0lOT0RFIC0gXAo+ICsJCQlGMkZTX0lO TElORV9YQVRUUl9BRERSUyAtIDEpKQo+ICsjZGVmaW5lIE5SX0lOTElORV9ERU5UUlkJKE1BWF9J TkxJTkVfREFUQSAqIEJJVFNfUEVSX0JZVEUgLyBcCj4gKwkJCSgoU0laRV9PRl9ESVJfRU5UUlkg KyBGMkZTX1NMT1RfTEVOKSAqIFwKPiArCQkJIEJJVFNfUEVSX0JZVEUgKyAxKSkKPiArI2RlZmlu ZSBJTkxJTkVfREVOVFJZX0JJVE1BUF9TSVpFCSgoTlJfSU5MSU5FX0RFTlRSWSArIFwKPiArCQkJ QklUU19QRVJfQllURSAtIDEpIC8gQklUU19QRVJfQllURSkKPiArI2RlZmluZSBJTkxJTkVfUkVT RVJWRURfU0laRQkoTUFYX0lOTElORV9EQVRBIC0gXAo+ICsJCQkoKFNJWkVfT0ZfRElSX0VOVFJZ ICsgRjJGU19TTE9UX0xFTikgKiBcCj4gKwkJCSBOUl9JTkxJTkVfREVOVFJZICsgSU5MSU5FX0RF TlRSWV9CSVRNQVBfU0laRSkpCj4gKyNkZWZpbmUgQ1VSU0VHX0hPVF9EQVRBCTAKPiArCj4gKyNk ZWZpbmUgQ0tQVF9GTEFHX1NFVChja3B0LCBmKQlcCj4gKwkJKGNrcHQpLT5ja3B0X2ZsYWdzICYg Z3J1Yl9jcHVfdG9fbGUzMl9jb21waWxlX3RpbWUgKGYpCj4gKwo+ICsjZGVmaW5lIEYyRlNfSU5M SU5FX1hBVFRSCTB4MDEJLyogZmlsZSBpbmxpbmUgeGF0dHIgZmxhZyAqLwo+ICsjZGVmaW5lIEYy RlNfSU5MSU5FX0RBVEEJMHgwMgkvKiBmaWxlIGlubGluZSBkYXRhIGZsYWcgKi8KPiArI2RlZmlu ZSBGMkZTX0lOTElORV9ERU5UUlkJMHgwNAkvKiBmaWxlIGlubGluZSBkZW50cnkgZmxhZyAqLwo+ ICsjZGVmaW5lIEYyRlNfREFUQV9FWElTVAkJMHgwOAkvKiBmaWxlIGlubGluZSBkYXRhIGV4aXN0 IGZsYWcgKi8KPiArI2RlZmluZSBGMkZTX0lOTElORV9ET1RTCTB4MTAJLyogZmlsZSBoYXZpbmcg aW1wbGljaXQgZG90IGRlbnRyaWVzICovCj4gKwo+ICtlbnVtIEZJTEVfVFlQRQo+ICt7Cj4gKyAg RjJGU19GVF9VTktOT1dOLAo+ICsgIEYyRlNfRlRfUkVHX0ZJTEUgPSAxLAo+ICsgIEYyRlNfRlRf RElSID0gMiwKPiArICBGMkZTX0ZUX1NZTUxJTksgPSA3LAo+ICt9Owo+ICsKPiArI2RlZmluZSBN QVhfVk9MVU1FX05BTUUJCTUxMgo+ICsKPiArc3RydWN0IGdydWJfZjJmc19zdXBlcmJsb2NrCj4g K3sKPiArICBncnViX3VpbnQzMl90IG1hZ2ljOwo+ICsgIGdydWJfdWludDE2X3QgZHVtbXkxWzJd Owo+ICsgIGdydWJfdWludDMyX3QgbG9nX3NlY3RvcnNpemU7Cj4gKyAgZ3J1Yl91aW50MzJfdCBs b2dfc2VjdG9yc19wZXJfYmxvY2s7Cj4gKyAgZ3J1Yl91aW50MzJfdCBsb2dfYmxvY2tzaXplOwo+ ICsgIGdydWJfdWludDMyX3QgbG9nX2Jsb2Nrc19wZXJfc2VnOwo+ICsgIGdydWJfdWludDMyX3Qg c2Vnc19wZXJfc2VjOwo+ICsgIGdydWJfdWludDMyX3Qgc2Vjc19wZXJfem9uZTsKPiArICBncnVi X3VpbnQzMl90IGNoZWNrc3VtX29mZnNldDsKPiArICBncnViX3VpbnQ4X3QgZHVtbXkyWzQwXTsK PiArICBncnViX3VpbnQzMl90IGNwX2Jsa2FkZHI7Cj4gKyAgZ3J1Yl91aW50MzJfdCBzaXRfYmxr YWRkcjsKPiArICBncnViX3VpbnQzMl90IG5hdF9ibGthZGRyOwo+ICsgIGdydWJfdWludDMyX3Qg c3NhX2Jsa2FkZHI7Cj4gKyAgZ3J1Yl91aW50MzJfdCBtYWluX2Jsa2FkZHI7Cj4gKyAgZ3J1Yl91 aW50MzJfdCByb290X2lubzsKPiArICBncnViX3VpbnQzMl90IG5vZGVfaW5vOwo+ICsgIGdydWJf dWludDMyX3QgbWV0YV9pbm87Cj4gKyAgZ3J1Yl91aW50OF90IHV1aWRbMTZdOwo+ICsgIGdydWJf dWludDE2X3Qgdm9sdW1lX25hbWVbTUFYX1ZPTFVNRV9OQU1FXTsKPiArICBncnViX3VpbnQzMl90 IGV4dGVuc2lvbl9jb3VudDsKPiArICBncnViX3VpbnQ4X3QgZXh0ZW5zaW9uX2xpc3RbRjJGU19N QVhfRVhURU5TSU9OXVs4XTsKPiArICBncnViX3VpbnQzMl90IGNwX3BheWxvYWQ7Cj4gKyAgZ3J1 Yl91aW50OF90IHZlcnNpb25bVkVSU0lPTl9MRU5dOwo+ICsgIGdydWJfdWludDhfdCBpbml0X3Zl cnNpb25bVkVSU0lPTl9MRU5dOwo+ICt9IEdSVUJfUEFDS0VEOwo+ICsKPiArc3RydWN0IGdydWJf ZjJmc19jaGVja3BvaW50Cj4gK3sKPiArICBncnViX3VpbnQ2NF90IGNoZWNrcG9pbnRfdmVyOwo+ ICsgIGdydWJfdWludDY0X3QgdXNlcl9ibG9ja19jb3VudDsKPiArICBncnViX3VpbnQ2NF90IHZh bGlkX2Jsb2NrX2NvdW50Owo+ICsgIGdydWJfdWludDMyX3QgcnN2ZF9zZWdtZW50X2NvdW50Owo+ ICsgIGdydWJfdWludDMyX3Qgb3ZlcnByb3Zfc2VnbWVudF9jb3VudDsKPiArICBncnViX3VpbnQz Ml90IGZyZWVfc2VnbWVudF9jb3VudDsKPiArICBncnViX3VpbnQzMl90IGN1cl9ub2RlX3NlZ25v W01BWF9BQ1RJVkVfTk9ERV9MT0dTXTsKPiArICBncnViX3VpbnQxNl90IGN1cl9ub2RlX2Jsa29m ZltNQVhfQUNUSVZFX05PREVfTE9HU107Cj4gKyAgZ3J1Yl91aW50MzJfdCBjdXJfZGF0YV9zZWdu b1tNQVhfQUNUSVZFX0RBVEFfTE9HU107Cj4gKyAgZ3J1Yl91aW50MTZfdCBjdXJfZGF0YV9ibGtv ZmZbTUFYX0FDVElWRV9EQVRBX0xPR1NdOwo+ICsgIGdydWJfdWludDMyX3QgY2twdF9mbGFnczsK PiArICBncnViX3VpbnQzMl90IGNwX3BhY2tfdG90YWxfYmxvY2tfY291bnQ7Cj4gKyAgZ3J1Yl91 aW50MzJfdCBjcF9wYWNrX3N0YXJ0X3N1bTsKPiArICBncnViX3VpbnQzMl90IHZhbGlkX25vZGVf Y291bnQ7Cj4gKyAgZ3J1Yl91aW50MzJfdCB2YWxpZF9pbm9kZV9jb3VudDsKPiArICBncnViX3Vp bnQzMl90IG5leHRfZnJlZV9uaWQ7Cj4gKyAgZ3J1Yl91aW50MzJfdCBzaXRfdmVyX2JpdG1hcF9i eXRlc2l6ZTsKPiArICBncnViX3VpbnQzMl90IG5hdF92ZXJfYml0bWFwX2J5dGVzaXplOwo+ICsg IGdydWJfdWludDMyX3QgY2hlY2tzdW1fb2Zmc2V0Owo+ICsgIGdydWJfdWludDY0X3QgZWxhcHNl ZF90aW1lOwo+ICsgIGdydWJfdWludDhfdCBhbGxvY190eXBlW01BWF9BQ1RJVkVfTE9HU107Cj4g KyAgZ3J1Yl91aW50OF90IHNpdF9uYXRfdmVyc2lvbl9iaXRtYXBbMzkwMF07Cj4gKyAgZ3J1Yl91 aW50MzJfdCBjaGVja3N1bTsKPiArfSBHUlVCX1BBQ0tFRDsKPiArCj4gK3N0cnVjdCBncnViX2Yy ZnNfbmF0X2VudHJ5IHsKPiArICBncnViX3VpbnQ4X3QgdmVyc2lvbjsKPiArICBncnViX3VpbnQz Ml90IGlubzsKPiArICBncnViX3VpbnQzMl90IGJsb2NrX2FkZHI7Cj4gK30gR1JVQl9QQUNLRUQ7 Cj4gKwo+ICtzdHJ1Y3QgZ3J1Yl9mMmZzX25hdF9qZW50Cj4gK3sKPiArICBncnViX3VpbnQzMl90 IG5pZDsKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX25hdF9lbnRyeSBuZTsKPiArfSBHUlVCX1BBQ0tF RDsKPiArCj4gK3N0cnVjdCBncnViX2YyZnNfbmF0X2pvdXJuYWwgewo+ICsgIGdydWJfdWludDE2 X3Qgbl9uYXRzOwo+ICsgIHN0cnVjdCBncnViX2YyZnNfbmF0X2plbnQgZW50cmllc1tOQVRfSk9V Uk5BTF9FTlRSSUVTXTsKPiArICBncnViX3VpbnQ4X3QgcmVzZXJ2ZWRbTkFUX0pPVVJOQUxfUkVT RVJWRURdOwo+ICt9IEdSVUJfUEFDS0VEOwo+ICsKPiArc3RydWN0IGdydWJfZjJmc19uYXRfYmxv Y2sgewo+ICsgIHN0cnVjdCBncnViX2YyZnNfbmF0X2VudHJ5IG5lW05BVF9FTlRSWV9QRVJfQkxP Q0tdOwo+ICt9IEdSVUJfUEFDS0VEOwo+ICsKPiArc3RydWN0IGdydWJfZjJmc19kaXJfZW50cnkK PiArewo+ICsgIGdydWJfdWludDMyX3QgaGFzaF9jb2RlOwo+ICsgIGdydWJfdWludDMyX3QgaW5v Owo+ICsgIGdydWJfdWludDE2X3QgbmFtZV9sZW47Cj4gKyAgZ3J1Yl91aW50OF90IGZpbGVfdHlw ZTsKPiArfSBHUlVCX1BBQ0tFRDsKPiArCj4gK3N0cnVjdCBncnViX2YyZnNfaW5saW5lX2RlbnRy eQo+ICt7Cj4gKyAgZ3J1Yl91aW50OF90IGRlbnRyeV9iaXRtYXBbSU5MSU5FX0RFTlRSWV9CSVRN QVBfU0laRV07Cj4gKyAgZ3J1Yl91aW50OF90IHJlc2VydmVkW0lOTElORV9SRVNFUlZFRF9TSVpF XTsKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2Rpcl9lbnRyeSBkZW50cnlbTlJfSU5MSU5FX0RFTlRS WV07Cj4gKyAgZ3J1Yl91aW50OF90IGZpbGVuYW1lW05SX0lOTElORV9ERU5UUlldW0YyRlNfU0xP VF9MRU5dOwo+ICt9IEdSVUJfUEFDS0VEOwo+ICsKPiArc3RydWN0IGdydWJfZjJmc19kZW50cnlf YmxvY2sgewo+ICsgIGdydWJfdWludDhfdCBkZW50cnlfYml0bWFwW1NJWkVfT0ZfREVOVFJZX0JJ VE1BUF07Cj4gKyAgZ3J1Yl91aW50OF90IHJlc2VydmVkW1NJWkVfT0ZfUkVTRVJWRURdOwo+ICsg IHN0cnVjdCBncnViX2YyZnNfZGlyX2VudHJ5IGRlbnRyeVtOUl9ERU5UUllfSU5fQkxPQ0tdOwo+ ICsgIGdydWJfdWludDhfdCBmaWxlbmFtZVtOUl9ERU5UUllfSU5fQkxPQ0tdW0YyRlNfU0xPVF9M RU5dOwo+ICt9IEdSVUJfUEFDS0VEOwo+ICsKPiArc3RydWN0IGdydWJfZjJmc19pbm9kZQo+ICt7 Cj4gKyAgZ3J1Yl91aW50MTZfdCBpX21vZGU7Cj4gKyAgZ3J1Yl91aW50OF90IGlfYWR2aXNlOwo+ ICsgIGdydWJfdWludDhfdCBpX2lubGluZTsKPiArICBncnViX3VpbnQzMl90IGlfdWlkOwo+ICsg IGdydWJfdWludDMyX3QgaV9naWQ7Cj4gKyAgZ3J1Yl91aW50MzJfdCBpX2xpbmtzOwo+ICsgIGdy dWJfdWludDY0X3QgaV9zaXplOwo+ICsgIGdydWJfdWludDY0X3QgaV9ibG9ja3M7Cj4gKyAgZ3J1 Yl91aW50NjRfdCBpX2F0aW1lOwo+ICsgIGdydWJfdWludDY0X3QgaV9jdGltZTsKPiArICBncnVi X3VpbnQ2NF90IGlfbXRpbWU7Cj4gKyAgZ3J1Yl91aW50MzJfdCBpX2F0aW1lX25zZWM7Cj4gKyAg Z3J1Yl91aW50MzJfdCBpX2N0aW1lX25zZWM7Cj4gKyAgZ3J1Yl91aW50MzJfdCBpX210aW1lX25z ZWM7Cj4gKyAgZ3J1Yl91aW50MzJfdCBpX2dlbmVyYXRpb247Cj4gKyAgZ3J1Yl91aW50MzJfdCBp X2N1cnJlbnRfZGVwdGg7Cj4gKyAgZ3J1Yl91aW50MzJfdCBpX3hhdHRyX25pZDsKPiArICBncnVi X3VpbnQzMl90IGlfZmxhZ3M7Cj4gKyAgZ3J1Yl91aW50MzJfdCBpX3Bpbm87Cj4gKyAgZ3J1Yl91 aW50MzJfdCBpX25hbWVsZW47Cj4gKyAgZ3J1Yl91aW50OF90IGlfbmFtZVtGMkZTX05BTUVfTEVO XTsKPiArICBncnViX3VpbnQ4X3QgaV9kaXJfbGV2ZWw7Cj4gKyAgZ3J1Yl91aW50OF90IGlfZXh0 WzEyXTsKPiArICBncnViX3VpbnQzMl90IGlfYWRkcltERUZfQUREUlNfUEVSX0lOT0RFXTsKPiAr ICBncnViX3VpbnQzMl90IGlfbmlkWzVdOwo+ICt9IEdSVUJfUEFDS0VEOwo+ICsKPiArc3RydWN0 IGdydWJfZGlyZWN0X25vZGUgewo+ICsgIGdydWJfdWludDMyX3QgYWRkcltBRERSU19QRVJfQkxP Q0tdOwo+ICt9IEdSVUJfUEFDS0VEOwo+ICsKPiArc3RydWN0IGdydWJfaW5kaXJlY3Rfbm9kZSB7 Cj4gKyAgZ3J1Yl91aW50MzJfdCBuaWRbTklEU19QRVJfQkxPQ0tdOwo+ICt9IEdSVUJfUEFDS0VE Owo+ICsKPiArc3RydWN0IGdydWJfZjJmc19ub2RlCj4gK3sKPiArICB1bmlvbgo+ICsgIHsKPiAr ICAgIHN0cnVjdCBncnViX2YyZnNfaW5vZGUgaTsKPiArICAgIHN0cnVjdCBncnViX2RpcmVjdF9u b2RlIGRuOwo+ICsgICAgc3RydWN0IGdydWJfaW5kaXJlY3Rfbm9kZSBpbjsKPiArICAgIGNoYXIg YnVmW0YyRlNfQkxLU0laRSAtIDQwXTsJLyogU2hvdWxkIG9jY3VweSBGMkZTX0JMS1NJWkUgdG90 YWxseSAqLwo+ICsgIH07Cj4gKyAgZ3J1Yl91aW50OF90IGR1bW15WzQwXTsKPiArfSBHUlVCX1BB Q0tFRDsKPiArCj4gK3N0cnVjdCBncnViX2ZzaGVscF9ub2RlCj4gK3sKPiArICBzdHJ1Y3QgZ3J1 Yl9mMmZzX2RhdGEgKmRhdGE7Cj4gKyAgc3RydWN0IGdydWJfZjJmc19ub2RlIGlub2RlOwo+ICsg IGdydWJfdWludDMyX3QgaW5vOwo+ICsgIGludCBpbm9kZV9yZWFkOwo+ICt9Owo+ICsKPiArc3Ry dWN0IGdydWJfZjJmc19kYXRhCj4gK3sKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX3N1cGVyYmxvY2sg c2Jsb2NrOwo+ICsgIHN0cnVjdCBncnViX2YyZnNfY2hlY2twb2ludCBja3B0Owo+ICsKPiArICBn cnViX3VpbnQzMl90IHJvb3RfaW5vOwo+ICsgIGdydWJfdWludDMyX3QgYmxvY2tzX3Blcl9zZWc7 Cj4gKyAgZ3J1Yl91aW50MzJfdCBjcF9ibGthZGRyOwo+ICsgIGdydWJfdWludDMyX3QgbmF0X2Js a2FkZHI7Cj4gKwo+ICsgIHN0cnVjdCBncnViX2YyZnNfbmF0X2pvdXJuYWwgbmF0X2o7Cj4gKyAg Y2hhciAqbmF0X2JpdG1hcDsKPiArCj4gKyAgZ3J1Yl9kaXNrX3QgZGlzazsKPiArICBzdHJ1Y3Qg Z3J1Yl9mMmZzX25vZGUgKmlub2RlOwo+ICsgIHN0cnVjdCBncnViX2ZzaGVscF9ub2RlIGRpcm9w ZW47Cj4gK307Cj4gKwo+ICtzdHJ1Y3QgZ3J1Yl9mMmZzX2Rpcl9pdGVyX2N0eAo+ICt7Cj4gKyAg c3RydWN0IGdydWJfZjJmc19kYXRhICpkYXRhOwo+ICsgIGdydWJfZnNoZWxwX2l0ZXJhdGVfZGly X2hvb2tfdCBob29rOwo+ICsgIHZvaWQgKmhvb2tfZGF0YTsKPiArICBncnViX3VpbnQ4X3QgKmJp dG1hcDsKPiArICBncnViX3VpbnQ4X3QgKCpmaWxlbmFtZSlbRjJGU19TTE9UX0xFTl07Cj4gKyAg c3RydWN0IGdydWJfZjJmc19kaXJfZW50cnkgKmRlbnRyeTsKPiArICBpbnQgbWF4Owo+ICt9Owo+ ICsKPiArc3RydWN0IGdydWJfZjJmc19kaXJfY3R4Cj4gK3sKPiArICBncnViX2ZzX2Rpcl9ob29r X3QgaG9vazsKPiArICB2b2lkICpob29rX2RhdGE7Cj4gKyAgc3RydWN0IGdydWJfZjJmc19kYXRh ICpkYXRhOwo+ICt9Owo+ICsKPiArc3RhdGljIGdydWJfZGxfdCBteV9tb2Q7Cj4gKwo+ICtzdGF0 aWMgaW5saW5lIGludAo+ICtncnViX2YyZnNfdGVzdF9iaXRfbGUgKGludCBuciwgY29uc3QgZ3J1 Yl91aW50OF90ICphZGRyKQo+ICt7Cj4gKyAgcmV0dXJuIGFkZHJbbnIgPj4gM10gJiAoMSA8PCAo bnIgJiA3KSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgY2hhciAqCj4gK19faW5saW5lX2Fk ZHIgKHN0cnVjdCBncnViX2YyZnNfaW5vZGUgKmlub2RlKQo+ICt7Cj4gKyAgcmV0dXJuIChjaGFy ICopJmlub2RlLT5pX2FkZHJbMV07Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgZ3J1Yl91aW50 NjRfdAo+ICtncnViX2YyZnNfZmlsZV9zaXplIChzdHJ1Y3QgZ3J1Yl9mMmZzX2lub2RlICppbm9k ZSkKPiArewo+ICsgIHJldHVybiBncnViX2xlX3RvX2NwdTY0IChpbm9kZS0+aV9zaXplKTsKPiAr fQo+ICsKPiArc3RhdGljIGlubGluZSBncnViX3VpbnQzMl90Cj4gK19fc3RhcnRfY3BfYWRkciAo c3RydWN0IGdydWJfZjJmc19kYXRhICpkYXRhKQo+ICt7Cj4gKyAgc3RydWN0IGdydWJfZjJmc19j aGVja3BvaW50ICpja3B0ID0gJmRhdGEtPmNrcHQ7Cj4gKyAgZ3J1Yl91aW50MzJfdCBzdGFydF9h ZGRyID0gZGF0YS0+Y3BfYmxrYWRkcjsKPiArCj4gKyAgaWYgKCEoY2twdC0+Y2hlY2twb2ludF92 ZXIgJiBncnViX2NwdV90b19sZTY0X2NvbXBpbGVfdGltZSgxKSkpCj4gKyAgICByZXR1cm4gc3Rh cnRfYWRkciArIGRhdGEtPmJsb2Nrc19wZXJfc2VnOwo+ICsgIHJldHVybiBzdGFydF9hZGRyOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGdydWJfdWludDMyX3QKPiArX19zdGFydF9zdW1fYmxv Y2sgKHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0YSkKPiArewo+ICsgIHN0cnVjdCBncnViX2Yy ZnNfY2hlY2twb2ludCAqY2twdCA9ICZkYXRhLT5ja3B0Owo+ICsKPiArICByZXR1cm4gX19zdGFy dF9jcF9hZGRyIChkYXRhKSArIGdydWJfbGVfdG9fY3B1MzIgKGNrcHQtPmNwX3BhY2tfc3RhcnRf c3VtKTsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBncnViX3VpbnQzMl90Cj4gK19fc3VtX2Js a19hZGRyIChzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGEsIGludCBiYXNlLCBpbnQgdHlwZSkK PiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfY2hlY2twb2ludCAqY2twdCA9ICZkYXRhLT5ja3B0 Owo+ICsKPiArICByZXR1cm4gX19zdGFydF9jcF9hZGRyIChkYXRhKSArCj4gKwlncnViX2xlX3Rv X2NwdTMyIChja3B0LT5jcF9wYWNrX3RvdGFsX2Jsb2NrX2NvdW50KQo+ICsJLSAoYmFzZSArIDEp ICsgdHlwZTsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSB2b2lkICoKPiArX19uYXRfYml0bWFw X3B0ciAoc3RydWN0IGdydWJfZjJmc19kYXRhICpkYXRhKQo+ICt7Cj4gKyAgc3RydWN0IGdydWJf ZjJmc19jaGVja3BvaW50ICpja3B0ID0gJmRhdGEtPmNrcHQ7Cj4gKyAgZ3J1Yl91aW50MzJfdCBv ZmZzZXQ7Cj4gKwo+ICsgIGlmIChncnViX2xlX3RvX2NwdTMyIChkYXRhLT5zYmxvY2suY3BfcGF5 bG9hZCkgPiAwKQo+ICsgICAgcmV0dXJuIGNrcHQtPnNpdF9uYXRfdmVyc2lvbl9iaXRtYXA7Cj4g Kwo+ICsgIG9mZnNldCA9IGdydWJfbGVfdG9fY3B1MzIgKGNrcHQtPnNpdF92ZXJfYml0bWFwX2J5 dGVzaXplKTsKPiArICByZXR1cm4gY2twdC0+c2l0X25hdF92ZXJzaW9uX2JpdG1hcCArIG9mZnNl dDsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBncnViX3VpbnQzMl90Cj4gK19fZ2V0X25vZGVf aWQgKHN0cnVjdCBncnViX2YyZnNfbm9kZSAqcm4sIGludCBvZmYsIGludCBpbm9kZV9ibG9jaykK PiArewo+ICsgIGlmIChpbm9kZV9ibG9jaykKPiArICAgIHJldHVybiBncnViX2xlX3RvX2NwdTMy IChybi0+aS5pX25pZFtvZmYgLSBOT0RFX0RJUjFfQkxPQ0tdKTsKPiArICByZXR1cm4gZ3J1Yl9s ZV90b19jcHUzMiAocm4tPmluLm5pZFtvZmZdKTsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBn cnViX2Vycl90Cj4gK2dydWJfZjJmc19ibG9ja19yZWFkIChzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEg KmRhdGEsIGdydWJfdWludDMyX3QgYmxrYWRkciwgdm9pZCAqYnVmKQo+ICt7Cj4gKyAgcmV0dXJu IGdydWJfZGlza19yZWFkIChkYXRhLT5kaXNrLAo+ICsJCSgoZ3J1Yl9kaXNrX2FkZHJfdClibGth ZGRyKSA8PCBGMkZTX0JMS19TRUNfQklUUywKPiArCQkwLCBGMkZTX0JMS1NJWkUsIGJ1Zik7Cj4g K30KPiArCj4gKy8qCj4gKyAqIENSQzMyCj4gKyovCj4gKyNkZWZpbmUgQ1JDUE9MWV9MRSAweGVk Yjg4MzIwCj4gKwo+ICtzdGF0aWMgaW5saW5lIGdydWJfdWludDMyX3QKPiArZ3J1Yl9mMmZzX2Nh bF9jcmMzMiAoY29uc3Qgdm9pZCAqYnVmLCBjb25zdCBncnViX3VpbnQzMl90IGxlbikKPiArewo+ ICsgIGdydWJfdWludDMyX3QgY3JjID0gRjJGU19TVVBFUl9NQUdJQzsKPiArICB1bnNpZ25lZCBj aGFyICpwID0gKHVuc2lnbmVkIGNoYXIgKilidWY7Cj4gKyAgZ3J1Yl91aW50MzJfdCB0bXAgPSBs ZW47Cj4gKyAgaW50IGk7Cj4gKwo+ICsgIHdoaWxlICh0bXAtLSkKPiArICAgIHsKPiArICAgICAg Y3JjIF49ICpwKys7Cj4gKyAgICAgIGZvciAoaSA9IDA7IGkgPCA4OyBpKyspCj4gKyAgICAgICAg Y3JjID0gKGNyYyA+PiAxKSBeICgoY3JjICYgMSkgPyBDUkNQT0xZX0xFIDogMCk7Cj4gKyAgICB9 Cj4gKyAgcmV0dXJuIGNyYzsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBpbnQKPiArZ3J1Yl9m MmZzX2NyY192YWxpZCAoZ3J1Yl91aW50MzJfdCBibGtfY3JjLCB2b2lkICpidWYsIGNvbnN0IGdy dWJfdWludDMyX3QgbGVuKQo+ICt7Cj4gKyAgZ3J1Yl91aW50MzJfdCBjYWxfY3JjID0gMDsKPiAr Cj4gKyAgY2FsX2NyYyA9IGdydWJfZjJmc19jYWxfY3JjMzIgKGJ1ZiwgbGVuKTsKPiArCj4gKyAg cmV0dXJuIChjYWxfY3JjID09IGJsa19jcmMpID8gMSA6IDA7Cj4gK30KPiArCj4gK3N0YXRpYyBp bmxpbmUgaW50Cj4gK2dydWJfZjJmc190ZXN0X2JpdCAoZ3J1Yl91aW50MzJfdCBuciwgY29uc3Qg Y2hhciAqcCkKPiArewo+ICsgIGludCBtYXNrOwo+ICsKPiArICBwICs9IChuciA+PiAzKTsKPiAr ICBtYXNrID0gMSA8PCAoNyAtIChuciAmIDB4MDcpKTsKPiArICByZXR1cm4gbWFzayAmICpwOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgaW50Cj4gK2dydWJfZjJmc19zYW5pdHlfY2hlY2tfc2IgKHN0cnVj dCBncnViX2YyZnNfc3VwZXJibG9jayAqc2IpCj4gK3sKPiArICBncnViX3VpbnQzMl90IGxvZ19z ZWN0b3JzaXplLCBsb2dfc2VjdG9yc19wZXJfYmxvY2s7Cj4gKwo+ICsgIGlmIChzYi0+bWFnaWMg IT0gZ3J1Yl9jcHVfdG9fbGUzMl9jb21waWxlX3RpbWUgKEYyRlNfU1VQRVJfTUFHSUMpKQo+ICsg ICAgcmV0dXJuIC0xOwo+ICsKPiArICBpZiAoc2ItPmxvZ19ibG9ja3NpemUgIT0gZ3J1Yl9jcHVf dG9fbGUzMl9jb21waWxlX3RpbWUgKEYyRlNfQkxLX0JJVFMpKQo+ICsgICAgcmV0dXJuIC0xOwo+ ICsKPiArICBsb2dfc2VjdG9yc2l6ZSA9IGdydWJfbGVfdG9fY3B1MzIgKHNiLT5sb2dfc2VjdG9y c2l6ZSk7Cj4gKyAgbG9nX3NlY3RvcnNfcGVyX2Jsb2NrID0gZ3J1Yl9sZV90b19jcHUzMiAoc2It PmxvZ19zZWN0b3JzX3Blcl9ibG9jayk7Cj4gKwo+ICsgIGlmIChsb2dfc2VjdG9yc2l6ZSA+IEYy RlNfQkxLX0JJVFMpCj4gKyAgICByZXR1cm4gLTE7Cj4gKwo+ICsgIGlmIChsb2dfc2VjdG9yc2l6 ZSA8IEYyRlNfTUlOX0xPR19TRUNUT1JfU0laRSkKPiArICAgIHJldHVybiAtMTsKPiArCj4gKyAg aWYgKGxvZ19zZWN0b3JzX3Blcl9ibG9jayArIGxvZ19zZWN0b3JzaXplICE9IEYyRlNfQkxLX0JJ VFMpCj4gKyAgICByZXR1cm4gLTE7Cj4gKwo+ICsgIHJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgaW50Cj4gK2dydWJfZjJmc19yZWFkX3NiIChzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGEs IGdydWJfZGlza19hZGRyX3Qgb2Zmc2V0KQo+ICt7Cj4gKyAgZ3J1Yl9kaXNrX3QgZGlzayA9IGRh dGEtPmRpc2s7Cj4gKyAgZ3J1Yl9lcnJfdCBlcnI7Cj4gKwo+ICsgIC8qIFJlYWQgZmlyc3Qgc3Vw ZXIgYmxvY2suICovCj4gKyAgZXJyID0gZ3J1Yl9kaXNrX3JlYWQgKGRpc2ssIG9mZnNldCwgMCwg c2l6ZW9mIChkYXRhLT5zYmxvY2spLCAmZGF0YS0+c2Jsb2NrKTsKPiArICBpZiAoZXJyKQo+ICsg ICAgcmV0dXJuIC0xOwo+ICsKPiArICByZXR1cm4gZ3J1Yl9mMmZzX3Nhbml0eV9jaGVja19zYiAo JmRhdGEtPnNibG9jayk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkICoKPiArdmFsaWRhdGVfY2hl Y2twb2ludCAoc3RydWN0IGdydWJfZjJmc19kYXRhICpkYXRhLCBncnViX3VpbnQzMl90IGNwX2Fk ZHIsCj4gKwlncnViX3VpbnQ2NF90ICp2ZXJzaW9uKQo+ICt7Cj4gKyAgZ3J1Yl91aW50MzJfdCAq Y3BfcGFnZV8xLCAqY3BfcGFnZV8yOwo+ICsgIHN0cnVjdCBncnViX2YyZnNfY2hlY2twb2ludCAq Y3BfYmxvY2s7Cj4gKyAgZ3J1Yl91aW50NjRfdCBjdXJfdmVyc2lvbiA9IDAsIHByZV92ZXJzaW9u ID0gMDsKPiArICBncnViX3VpbnQzMl90IGNyYyA9IDA7Cj4gKyAgZ3J1Yl91aW50MzJfdCBjcmNf b2Zmc2V0Owo+ICsgIGdydWJfZXJyX3QgZXJyOwo+ICsKPiArICAvKiBSZWFkIHRoZSAxc3QgY3Ag YmxvY2sgaW4gdGhpcyBDUCBwYWNrICovCj4gKyAgY3BfcGFnZV8xID0gZ3J1Yl9tYWxsb2MgKEYy RlNfQkxLU0laRSk7Cj4gKyAgaWYgKCFjcF9wYWdlXzEpCj4gKyAgICByZXR1cm4gTlVMTDsKPiAr Cj4gKyAgZXJyID0gZ3J1Yl9mMmZzX2Jsb2NrX3JlYWQgKGRhdGEsIGNwX2FkZHIsIGNwX3BhZ2Vf MSk7Cj4gKyAgaWYgKGVycikKPiArICAgIGdvdG8gaW52YWxpZF9jcDE7Cj4gKwo+ICsgIGNwX2Js b2NrID0gKHN0cnVjdCBncnViX2YyZnNfY2hlY2twb2ludCAqKWNwX3BhZ2VfMTsKPiArICBjcmNf b2Zmc2V0ID0gZ3J1Yl9sZV90b19jcHUzMiAoY3BfYmxvY2stPmNoZWNrc3VtX29mZnNldCk7Cj4g KyAgaWYgKGNyY19vZmZzZXQgIT0gQ0hFQ0tTVU1fT0ZGU0VUKQo+ICsgICAgZ290byBpbnZhbGlk X2NwMTsKPiArCj4gKyAgY3JjID0gZ3J1Yl9sZV90b19jcHUzMiAoKihjcF9wYWdlXzEgKyBVMzJf Q0hFQ0tTVU1fT0ZGU0VUKSk7Cj4gKyAgaWYgKCFncnViX2YyZnNfY3JjX3ZhbGlkIChjcmMsIGNw X2Jsb2NrLCBjcmNfb2Zmc2V0KSkKPiArICAgIGdvdG8gaW52YWxpZF9jcDE7Cj4gKwo+ICsgIHBy ZV92ZXJzaW9uID0gZ3J1Yl9sZV90b19jcHU2NCAoY3BfYmxvY2stPmNoZWNrcG9pbnRfdmVyKTsK PiArCj4gKyAgLyogUmVhZCB0aGUgMm5kIGNwIGJsb2NrIGluIHRoaXMgQ1AgcGFjayAqLwo+ICsg IGNwX3BhZ2VfMiA9IGdydWJfbWFsbG9jIChGMkZTX0JMS1NJWkUpOwo+ICsgIGlmICghY3BfcGFn ZV8yKQo+ICsgICAgZ290byBpbnZhbGlkX2NwMTsKPiArCj4gKyAgY3BfYWRkciArPSBncnViX2xl X3RvX2NwdTMyIChjcF9ibG9jay0+Y3BfcGFja190b3RhbF9ibG9ja19jb3VudCkgLSAxOwo+ICsK PiArICBlcnIgPSBncnViX2YyZnNfYmxvY2tfcmVhZCAoZGF0YSwgY3BfYWRkciwgY3BfcGFnZV8y KTsKPiArICBpZiAoZXJyKQo+ICsgICAgZ290byBpbnZhbGlkX2NwMjsKPiArCj4gKyAgY3BfYmxv Y2sgPSAoc3RydWN0IGdydWJfZjJmc19jaGVja3BvaW50ICopY3BfcGFnZV8yOwo+ICsgIGNyY19v ZmZzZXQgPSBncnViX2xlX3RvX2NwdTMyIChjcF9ibG9jay0+Y2hlY2tzdW1fb2Zmc2V0KTsKPiAr ICBpZiAoY3JjX29mZnNldCAhPSBDSEVDS1NVTV9PRkZTRVQpCj4gKyAgICBnb3RvIGludmFsaWRf Y3AyOwo+ICsKPiArICBjcmMgPSBncnViX2xlX3RvX2NwdTMyICgqKGNwX3BhZ2VfMiArIFUzMl9D SEVDS1NVTV9PRkZTRVQpKTsKPiArICBpZiAoIWdydWJfZjJmc19jcmNfdmFsaWQgKGNyYywgY3Bf YmxvY2ssIGNyY19vZmZzZXQpKQo+ICsgICAgZ290byBpbnZhbGlkX2NwMjsKPiArCj4gKyAgY3Vy X3ZlcnNpb24gPSBncnViX2xlX3RvX2NwdTY0IChjcF9ibG9jay0+Y2hlY2twb2ludF92ZXIpOwo+ ICsgIGlmIChjdXJfdmVyc2lvbiA9PSBwcmVfdmVyc2lvbikKPiArICAgIHsKPiArICAgICAgKnZl cnNpb24gPSBjdXJfdmVyc2lvbjsKPiArICAgICAgZ3J1Yl9mcmVlIChjcF9wYWdlXzIpOwo+ICsg ICAgICByZXR1cm4gY3BfcGFnZV8xOwo+ICsgICAgfQo+ICsKPiAraW52YWxpZF9jcDI6Cj4gKyAg Z3J1Yl9mcmVlIChjcF9wYWdlXzIpOwo+ICtpbnZhbGlkX2NwMToKPiArICBncnViX2ZyZWUgKGNw X3BhZ2VfMSk7Cj4gKyAgcmV0dXJuIE5VTEw7Cj4gK30KPiArCj4gK3N0YXRpYyBncnViX2Vycl90 Cj4gK2dydWJfZjJmc19yZWFkX2NwIChzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGEpCj4gK3sK PiArICB2b2lkICpjcDEsICpjcDIsICpjdXJfcGFnZTsKPiArICBncnViX3VpbnQ2NF90IGNwMV92 ZXJzaW9uID0gMCwgY3AyX3ZlcnNpb24gPSAwOwo+ICsgIGdydWJfdWludDY0X3QgY3Bfc3RhcnRf YmxrX25vOwo+ICsKPiArICAvKgo+ICsgICAqIEZpbmRpbmcgb3V0IHZhbGlkIGNwIGJsb2NrIGlu dm9sdmVzIHJlYWQgYm90aAo+ICsgICAqIHNldHMgKGNwIHBhY2sxIGFuZCBjcCBwYWNrIDIpCj4g KyAgICovCj4gKyAgY3Bfc3RhcnRfYmxrX25vID0gZGF0YS0+Y3BfYmxrYWRkcjsKPiArICBjcDEg PSB2YWxpZGF0ZV9jaGVja3BvaW50IChkYXRhLCBjcF9zdGFydF9ibGtfbm8sICZjcDFfdmVyc2lv bik7Cj4gKyAgaWYgKCFjcDEgJiYgZ3J1Yl9lcnJubykKPiArICAgIHJldHVybiBncnViX2Vycm5v Owo+ICsKPiArICAvKiBUaGUgc2Vjb25kIGNoZWNrcG9pbnQgcGFjayBzaG91bGQgc3RhcnQgYXQg dGhlIG5leHQgc2VnbWVudCAqLwo+ICsgIGNwX3N0YXJ0X2Jsa19ubyArPSBkYXRhLT5ibG9ja3Nf cGVyX3NlZzsKPiArICBjcDIgPSB2YWxpZGF0ZV9jaGVja3BvaW50IChkYXRhLCBjcF9zdGFydF9i bGtfbm8sICZjcDJfdmVyc2lvbik7Cj4gKyAgaWYgKCFjcDIgJiYgZ3J1Yl9lcnJubykKPiArICAg IHsKPiArICAgICAgZ3J1Yl9mcmVlIChjcDEpOwo+ICsgICAgICByZXR1cm4gZ3J1Yl9lcnJubzsK PiArICAgIH0KPiArCj4gKyAgaWYgKGNwMSAmJiBjcDIpCj4gKyAgICBjdXJfcGFnZSA9IChjcDJf dmVyc2lvbiA+IGNwMV92ZXJzaW9uKSA/IGNwMiA6IGNwMTsKPiArICBlbHNlIGlmIChjcDEpCj4g KyAgICBjdXJfcGFnZSA9IGNwMTsKPiArICBlbHNlIGlmIChjcDIpCj4gKyAgICBjdXJfcGFnZSA9 IGNwMjsKPiArICBlbHNlCj4gKyAgICByZXR1cm4gZ3J1Yl9lcnJvciAoR1JVQl9FUlJfQkFEX0ZT LCAibm8gY2hlY2twb2ludHMiKTsKPiArCj4gKyAgZ3J1Yl9tZW1jcHkgKCZkYXRhLT5ja3B0LCBj dXJfcGFnZSwgRjJGU19CTEtTSVpFKTsKPiArCj4gKyAgZ3J1Yl9mcmVlIChjcDEpOwo+ICsgIGdy dWJfZnJlZSAoY3AyKTsKPiArICByZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGdydWJfZXJy X3QKPiArZ2V0X25hdF9qb3VybmFsIChzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGEpCj4gK3sK PiArICBncnViX3VpbnQzMl90IGJsb2NrOwo+ICsgIGNoYXIgKmJ1ZjsKPiArICBncnViX2Vycl90 IGVycjsKPiArCj4gKyAgYnVmID0gZ3J1Yl9tYWxsb2MgKEYyRlNfQkxLU0laRSk7Cj4gKyAgaWYg KCFidWYpCj4gKyAgICByZXR1cm4gZ3J1Yl9lcnJubzsKPiArCj4gKyAgaWYgKENLUFRfRkxBR19T RVQoJmRhdGEtPmNrcHQsIENQX0NPTVBBQ1RfU1VNX0ZMQUcpKQo+ICsgICAgYmxvY2sgPSBfX3N0 YXJ0X3N1bV9ibG9jayAoZGF0YSk7Cj4gKyAgZWxzZSBpZiAoQ0tQVF9GTEFHX1NFVCAoJmRhdGEt PmNrcHQsIENQX1VNT1VOVF9GTEFHKSkKPiArICAgIGJsb2NrID0gX19zdW1fYmxrX2FkZHIgKGRh dGEsIE5SX0NVUlNFR19UWVBFLCBDVVJTRUdfSE9UX0RBVEEpOwo+ICsgIGVsc2UKPiArICAgIGJs b2NrID0gX19zdW1fYmxrX2FkZHIgKGRhdGEsIE5SX0NVUlNFR19EQVRBX1RZUEUsIENVUlNFR19I T1RfREFUQSk7Cj4gKwo+ICsgIGVyciA9IGdydWJfZjJmc19ibG9ja19yZWFkIChkYXRhLCBibG9j aywgYnVmKTsKPiArICBpZiAoZXJyKQo+ICsgICAgZ290byBmYWlsOwo+ICsKPiArICBpZiAoQ0tQ VF9GTEFHX1NFVCAoJmRhdGEtPmNrcHQsIENQX0NPTVBBQ1RfU1VNX0ZMQUcpKQo+ICsgICAgZ3J1 Yl9tZW1jcHkgKCZkYXRhLT5uYXRfaiwgYnVmLCBTVU1fSk9VUk5BTF9TSVpFKTsKPiArICBlbHNl Cj4gKyAgICBncnViX21lbWNweSAoJmRhdGEtPm5hdF9qLCBidWYgKyBTVU1fRU5UUklFU19TSVpF LCBTVU1fSk9VUk5BTF9TSVpFKTsKPiArCj4gK2ZhaWw6Cj4gKyAgZ3J1Yl9mcmVlIChidWYpOwo+ ICsgIHJldHVybiBlcnI7Cj4gK30KPiArCj4gK3N0YXRpYyBncnViX3VpbnQzMl90Cj4gK2dldF9i bGthZGRyX2Zyb21fbmF0X2pvdXJuYWwgKHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0YSwgZ3J1 Yl91aW50MzJfdCBuaWQpCj4gK3sKPiArICBncnViX3VpbnQxNl90IG4gPSBncnViX2xlX3RvX2Nw dTE2IChkYXRhLT5uYXRfai5uX25hdHMpOwo+ICsgIGdydWJfdWludDMyX3QgYmxrYWRkciA9IDA7 Cj4gKyAgZ3J1Yl91aW50MTZfdCBpOwo+ICsKPiArICBmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKQo+ ICsgICAgewo+ICsgICAgICBpZiAoZ3J1Yl9sZV90b19jcHUzMiAoZGF0YS0+bmF0X2ouZW50cmll c1tpXS5uaWQpID09IG5pZCkKPiArICAgICAgICB7Cj4gKyAgICAgICAgICBibGthZGRyID0gZ3J1 Yl9sZV90b19jcHUzMiAoZGF0YS0+bmF0X2ouZW50cmllc1tpXS5uZS5ibG9ja19hZGRyKTsKPiAr ICAgICAgICAgIGJyZWFrOwo+ICsgICAgICAgIH0KPiArICAgIH0KPiArICByZXR1cm4gYmxrYWRk cjsKPiArfQo+ICsKPiArc3RhdGljIGdydWJfdWludDMyX3QKPiArZ2V0X25vZGVfYmxrYWRkciAo c3RydWN0IGdydWJfZjJmc19kYXRhICpkYXRhLCBncnViX3VpbnQzMl90IG5pZCkKPiArewo+ICsg IHN0cnVjdCBncnViX2YyZnNfbmF0X2Jsb2NrICpuYXRfYmxvY2s7Cj4gKyAgZ3J1Yl91aW50MzJf dCBzZWdfb2ZmLCBibG9ja19vZmYsIGVudHJ5X29mZiwgYmxvY2tfYWRkcjsKPiArICBncnViX3Vp bnQzMl90IGJsa2FkZHI7Cj4gKyAgZ3J1Yl9lcnJfdCBlcnI7Cj4gKwo+ICsgIGJsa2FkZHIgPSBn ZXRfYmxrYWRkcl9mcm9tX25hdF9qb3VybmFsIChkYXRhLCBuaWQpOwo+ICsgIGlmIChibGthZGRy KQo+ICsgICAgcmV0dXJuIGJsa2FkZHI7Cj4gKwo+ICsgIG5hdF9ibG9jayA9IGdydWJfbWFsbG9j IChGMkZTX0JMS1NJWkUpOwo+ICsgIGlmICghbmF0X2Jsb2NrKQo+ICsgICAgcmV0dXJuIDA7Cj4g Kwo+ICsgIGJsb2NrX29mZiA9IG5pZCAvIE5BVF9FTlRSWV9QRVJfQkxPQ0s7Cj4gKyAgZW50cnlf b2ZmID0gbmlkICUgTkFUX0VOVFJZX1BFUl9CTE9DSzsKPiArCj4gKyAgc2VnX29mZiA9IGJsb2Nr X29mZiAvIGRhdGEtPmJsb2Nrc19wZXJfc2VnOwo+ICsgIGJsb2NrX2FkZHIgPSBkYXRhLT5uYXRf YmxrYWRkciArCj4gKwkoKHNlZ19vZmYgKiBkYXRhLT5ibG9ja3NfcGVyX3NlZykgPDwgMSkgKwo+ ICsJKGJsb2NrX29mZiAmIChkYXRhLT5ibG9ja3NfcGVyX3NlZyAtIDEpKTsKPiArCj4gKyAgaWYg KGdydWJfZjJmc190ZXN0X2JpdCAoYmxvY2tfb2ZmLCBkYXRhLT5uYXRfYml0bWFwKSkKPiArICAg IGJsb2NrX2FkZHIgKz0gZGF0YS0+YmxvY2tzX3Blcl9zZWc7Cj4gKwo+ICsgIGVyciA9IGdydWJf ZjJmc19ibG9ja19yZWFkIChkYXRhLCBibG9ja19hZGRyLCBuYXRfYmxvY2spOwo+ICsgIGlmIChl cnIpCj4gKyAgICB7Cj4gKyAgICAgIGdydWJfZnJlZSAobmF0X2Jsb2NrKTsKPiArICAgICAgcmV0 dXJuIDA7Cj4gKyAgICB9Cj4gKwo+ICsgIGJsa2FkZHIgPSBncnViX2xlX3RvX2NwdTMyIChuYXRf YmxvY2stPm5lW2VudHJ5X29mZl0uYmxvY2tfYWRkcik7Cj4gKwo+ICsgIGdydWJfZnJlZSAobmF0 X2Jsb2NrKTsKPiArCj4gKyAgcmV0dXJuIGJsa2FkZHI7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQK PiArZ3J1Yl9nZXRfbm9kZV9wYXRoIChzdHJ1Y3QgZ3J1Yl9mMmZzX2lub2RlICppbm9kZSwgZ3J1 Yl91aW50MzJfdCBibG9jaywKPiArCWdydWJfdWludDMyX3Qgb2Zmc2V0WzRdLCBncnViX3VpbnQz Ml90IG5vZmZzZXRbNF0pCj4gK3sKPiArICBncnViX3VpbnQzMl90IGRpcmVjdF9ibGtzID0gQURE UlNfUEVSX0JMT0NLOwo+ICsgIGdydWJfdWludDMyX3QgZHB0cnNfcGVyX2JsayA9IE5JRFNfUEVS X0JMT0NLOwo+ICsgIGdydWJfdWludDMyX3QgaW5kaXJlY3RfYmxrcyA9IEFERFJTX1BFUl9CTE9D SyAqIE5JRFNfUEVSX0JMT0NLOwo+ICsgIGdydWJfdWludDMyX3QgZGluZGlyZWN0X2Jsa3MgPSBp bmRpcmVjdF9ibGtzICogTklEU19QRVJfQkxPQ0s7Cj4gKyAgZ3J1Yl91aW50MzJfdCBkaXJlY3Rf aW5kZXggPSBERUZfQUREUlNfUEVSX0lOT0RFOwo+ICsgIGludCBuID0gMDsKPiArICBpbnQgbGV2 ZWwgPSAwOwo+ICsKPiArICBpZiAoaW5vZGUtPmlfaW5saW5lICYgRjJGU19JTkxJTkVfWEFUVFIp Cj4gKyAgICBkaXJlY3RfaW5kZXggLT0gRjJGU19JTkxJTkVfWEFUVFJfQUREUlM7Cj4gKwo+ICsg IG5vZmZzZXRbMF0gPSAwOwo+ICsKPiArICBpZiAoYmxvY2sgPCBkaXJlY3RfaW5kZXgpCj4gKyAg ICB7Cj4gKyAgICAgIG9mZnNldFtuXSA9IGJsb2NrOwo+ICsgICAgICBnb3RvIGdvdDsKPiArICAg IH0KPiArCj4gKyAgYmxvY2sgLT0gZGlyZWN0X2luZGV4Owo+ICsgIGlmIChibG9jayA8IGRpcmVj dF9ibGtzKQo+ICsgICAgewo+ICsgICAgICBvZmZzZXRbbisrXSA9IE5PREVfRElSMV9CTE9DSzsK PiArICAgICAgbm9mZnNldFtuXSA9IDE7Cj4gKyAgICAgIG9mZnNldFtuXSA9IGJsb2NrOwo+ICsg ICAgICBsZXZlbCA9IDE7Cj4gKyAgICAgIGdvdG8gZ290Owo+ICsgICAgfQo+ICsKPiArICBibG9j ayAtPSBkaXJlY3RfYmxrczsKPiArICBpZiAoYmxvY2sgPCBkaXJlY3RfYmxrcykKPiArICAgIHsK PiArICAgICAgb2Zmc2V0W24rK10gPSBOT0RFX0RJUjJfQkxPQ0s7Cj4gKyAgICAgIG5vZmZzZXRb bl0gPSAyOwo+ICsgICAgICBvZmZzZXRbbl0gPSBibG9jazsKPiArICAgICAgbGV2ZWwgPSAxOwo+ ICsgICAgICBnb3RvIGdvdDsKPiArICAgIH0KPiArCj4gKyAgYmxvY2sgLT0gZGlyZWN0X2Jsa3M7 Cj4gKyAgaWYgKGJsb2NrIDwgaW5kaXJlY3RfYmxrcykKPiArICAgIHsKPiArICAgICAgb2Zmc2V0 W24rK10gPSBOT0RFX0lORDFfQkxPQ0s7Cj4gKyAgICAgIG5vZmZzZXRbbl0gPSAzOwo+ICsgICAg ICBvZmZzZXRbbisrXSA9IGJsb2NrIC8gZGlyZWN0X2Jsa3M7Cj4gKyAgICAgIG5vZmZzZXRbbl0g PSA0ICsgb2Zmc2V0W24gLSAxXTsKPiArICAgICAgb2Zmc2V0W25dID0gYmxvY2sgJSBkaXJlY3Rf YmxrczsKPiArICAgICAgbGV2ZWwgPSAyOwo+ICsgICAgICBnb3RvIGdvdDsKPiArICAgIH0KPiAr Cj4gKyAgYmxvY2sgLT0gaW5kaXJlY3RfYmxrczsKPiArICBpZiAoYmxvY2sgPCBpbmRpcmVjdF9i bGtzKQo+ICsgICAgewo+ICsgICAgICBvZmZzZXRbbisrXSA9IE5PREVfSU5EMl9CTE9DSzsKPiAr ICAgICAgbm9mZnNldFtuXSA9IDQgKyBkcHRyc19wZXJfYmxrOwo+ICsgICAgICBvZmZzZXRbbisr XSA9IGJsb2NrIC8gZGlyZWN0X2Jsa3M7Cj4gKyAgICAgIG5vZmZzZXRbbl0gPSA1ICsgZHB0cnNf cGVyX2JsayArIG9mZnNldFtuIC0gMV07Cj4gKyAgICAgIG9mZnNldFtuXSA9IGJsb2NrICUgZGly ZWN0X2Jsa3M7Cj4gKyAgICAgIGxldmVsID0gMjsKPiArICAgICAgZ290byBnb3Q7Cj4gKyAgICB9 Cj4gKwo+ICsgIGJsb2NrIC09IGluZGlyZWN0X2Jsa3M7Cj4gKyAgaWYgKGJsb2NrIDwgZGluZGly ZWN0X2Jsa3MpCj4gKyAgICB7Cj4gKyAgICAgIG9mZnNldFtuKytdID0gTk9ERV9ESU5EX0JMT0NL Owo+ICsgICAgICBub2Zmc2V0W25dID0gNSArIChkcHRyc19wZXJfYmxrICogMik7Cj4gKyAgICAg IG9mZnNldFtuKytdID0gYmxvY2sgLyBpbmRpcmVjdF9ibGtzOwo+ICsgICAgICBub2Zmc2V0W25d ID0gNiArIChkcHRyc19wZXJfYmxrICogMikgKwo+ICsgICAgICBvZmZzZXRbbiAtIDFdICogKGRw dHJzX3Blcl9ibGsgKyAxKTsKPiArICAgICAgb2Zmc2V0W24rK10gPSAoYmxvY2sgLyBkaXJlY3Rf YmxrcykgJSBkcHRyc19wZXJfYmxrOwo+ICsgICAgICBub2Zmc2V0W25dID0gNyArIChkcHRyc19w ZXJfYmxrICogMikgKwo+ICsJCW9mZnNldFtuIC0gMl0gKiAoZHB0cnNfcGVyX2JsayArIDEpICsg b2Zmc2V0W24gLSAxXTsKPiArICAgICAgb2Zmc2V0W25dID0gYmxvY2sgJSBkaXJlY3RfYmxrczsK PiArICAgICAgbGV2ZWwgPSAzOwo+ICsgICAgICBnb3RvIGdvdDsKPiArICAgIH0KPiArZ290Ogo+ ICsgIHJldHVybiBsZXZlbDsKPiArfQo+ICsKPiArc3RhdGljIGdydWJfZXJyX3QKPiArZ3J1Yl9m MmZzX3JlYWRfbm9kZSAoc3RydWN0IGdydWJfZjJmc19kYXRhICpkYXRhLAo+ICsJZ3J1Yl91aW50 MzJfdCBuaWQsIHN0cnVjdCBncnViX2YyZnNfbm9kZSAqbnApCj4gK3sKPiArICBncnViX3VpbnQz Ml90IGJsa2FkZHI7Cj4gKwo+ICsgIGJsa2FkZHIgPSBnZXRfbm9kZV9ibGthZGRyIChkYXRhLCBu aWQpOwo+ICsgIGlmICghYmxrYWRkcikKPiArICAgIHJldHVybiBncnViX2Vycm5vOwo+ICsKPiAr ICByZXR1cm4gZ3J1Yl9mMmZzX2Jsb2NrX3JlYWQgKGRhdGEsIGJsa2FkZHIsIG5wKTsKPiArfQo+ ICsKPiArc3RhdGljIHN0cnVjdCBncnViX2YyZnNfZGF0YSAqCj4gK2dydWJfZjJmc19tb3VudCAo Z3J1Yl9kaXNrX3QgZGlzaykKPiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0YTsK PiArICBncnViX2Vycl90IGVycjsKPiArCj4gKyAgZGF0YSA9IGdydWJfbWFsbG9jIChzaXplb2Yg KCpkYXRhKSk7Cj4gKyAgaWYgKCFkYXRhKQo+ICsgICAgcmV0dXJuIE5VTEw7Cj4gKwo+ICsgIGRh dGEtPmRpc2sgPSBkaXNrOwo+ICsKPiArICBpZiAoZ3J1Yl9mMmZzX3JlYWRfc2IgKGRhdGEsIEYy RlNfU1VQRVJfT0ZGU0VUMCkpCj4gKyAgICB7Cj4gKyAgICAgIGlmIChncnViX2YyZnNfcmVhZF9z YiAoZGF0YSwgRjJGU19TVVBFUl9PRkZTRVQxKSkKPiArICAgICAgICB7Cj4gKyAgICAgICAgICBp ZiAoZ3J1Yl9lcnJubyA9PSBHUlVCX0VSUl9OT05FKQo+ICsgICAgICAgICAgICBncnViX2Vycm9y IChHUlVCX0VSUl9CQURfRlMsCj4gKwkJCSJub3QgYSBGMkZTIGZpbGVzeXN0ZW0gKG5vIHN1cGVy YmxvY2spIik7Cj4gKyAgICAgICAgICBnb3RvIGZhaWw7Cj4gKyAgICAgICAgfQo+ICsgICAgfQo+ ICsKPiArICBkYXRhLT5yb290X2lubyA9IGdydWJfbGVfdG9fY3B1MzIgKGRhdGEtPnNibG9jay5y b290X2lubyk7Cj4gKyAgZGF0YS0+Y3BfYmxrYWRkciA9IGdydWJfbGVfdG9fY3B1MzIgKGRhdGEt PnNibG9jay5jcF9ibGthZGRyKTsKPiArICBkYXRhLT5uYXRfYmxrYWRkciA9IGdydWJfbGVfdG9f Y3B1MzIgKGRhdGEtPnNibG9jay5uYXRfYmxrYWRkcik7Cj4gKyAgZGF0YS0+YmxvY2tzX3Blcl9z ZWcgPSAxIDw8Cj4gKwlncnViX2xlX3RvX2NwdTMyIChkYXRhLT5zYmxvY2subG9nX2Jsb2Nrc19w ZXJfc2VnKTsKPiArCj4gKyAgZXJyID0gZ3J1Yl9mMmZzX3JlYWRfY3AgKGRhdGEpOwo+ICsgIGlm IChlcnIpCj4gKyAgICBnb3RvIGZhaWw7Cj4gKwo+ICsgIGRhdGEtPm5hdF9iaXRtYXAgPSBfX25h dF9iaXRtYXBfcHRyIChkYXRhKTsKPiArCj4gKyAgZXJyID0gZ2V0X25hdF9qb3VybmFsIChkYXRh KTsKPiArICBpZiAoZXJyKQo+ICsgICAgZ290byBmYWlsOwo+ICsKPiArICBkYXRhLT5kaXJvcGVu LmRhdGEgPSBkYXRhOwo+ICsgIGRhdGEtPmRpcm9wZW4uaW5vID0gZGF0YS0+cm9vdF9pbm87Cj4g KyAgZGF0YS0+ZGlyb3Blbi5pbm9kZV9yZWFkID0gMTsKPiArICBkYXRhLT5pbm9kZSA9ICZkYXRh LT5kaXJvcGVuLmlub2RlOwo+ICsKPiArICBlcnIgPSBncnViX2YyZnNfcmVhZF9ub2RlIChkYXRh LCBkYXRhLT5yb290X2lubywgZGF0YS0+aW5vZGUpOwo+ICsgIGlmIChlcnIpCj4gKyAgICBnb3Rv IGZhaWw7Cj4gKwo+ICsgIHJldHVybiBkYXRhOwo+ICsKPiArZmFpbDoKPiArICBncnViX2ZyZWUg KGRhdGEpOwo+ICsgIHJldHVybiBOVUxMOwo+ICt9Cj4gKwo+ICsvKiBndWFyYW50ZWUgaW5saW5l X2RhdGEgd2FzIGhhbmRsZWQgYnkgY2FsbGVyICovCj4gK3N0YXRpYyBncnViX2Rpc2tfYWRkcl90 Cj4gK2dydWJfZjJmc19nZXRfYmxvY2sgKGdydWJfZnNoZWxwX25vZGVfdCBub2RlLCBncnViX2Rp c2tfYWRkcl90IGJsb2NrX29mcykKPiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0 YSA9IG5vZGUtPmRhdGE7Cj4gKyAgc3RydWN0IGdydWJfZjJmc19pbm9kZSAqaW5vZGUgPSAmbm9k ZS0+aW5vZGUuaTsKPiArICBncnViX3VpbnQzMl90IG9mZnNldFs0XSwgbm9mZnNldFs0XSwgbmlk c1s0XTsKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX25vZGUgKm5vZGVfYmxvY2s7Cj4gKyAgZ3J1Yl91 aW50MzJfdCBibG9ja19hZGRyID0gLTE7Cj4gKyAgaW50IGxldmVsLCBpOwo+ICsKPiArICBsZXZl bCA9IGdydWJfZ2V0X25vZGVfcGF0aCAoaW5vZGUsIGJsb2NrX29mcywgb2Zmc2V0LCBub2Zmc2V0 KTsKPiArICBpZiAobGV2ZWwgPT0gMCkKPiArICAgIHJldHVybiBncnViX2xlX3RvX2NwdTMyIChp bm9kZS0+aV9hZGRyW29mZnNldFswXV0pOwo+ICsKPiArICBub2RlX2Jsb2NrID0gZ3J1Yl9tYWxs b2MgKEYyRlNfQkxLU0laRSk7Cj4gKyAgaWYgKCFub2RlX2Jsb2NrKQo+ICsgICAgcmV0dXJuIC0x Owo+ICsKPiArICBuaWRzWzFdID0gX19nZXRfbm9kZV9pZCAoJm5vZGUtPmlub2RlLCBvZmZzZXRb MF0sIDEpOwo+ICsKPiArICAvKiBnZXQgaW5kaXJlY3Qgb3IgZGlyZWN0IG5vZGVzICovCj4gKyAg Zm9yIChpID0gMTsgaSA8PSBsZXZlbDsgaSsrKQo+ICsgICAgewo+ICsgICAgICBncnViX2YyZnNf cmVhZF9ub2RlIChkYXRhLCBuaWRzW2ldLCBub2RlX2Jsb2NrKTsKPiArICAgICAgaWYgKGdydWJf ZXJybm8pCj4gKyAgICAgICAgZ290byBmYWlsOwo+ICsKPiArICAgICAgaWYgKGkgPCBsZXZlbCkK PiArICAgICAgICBuaWRzW2kgKyAxXSA9IF9fZ2V0X25vZGVfaWQgKG5vZGVfYmxvY2ssIG9mZnNl dFtpXSwgMCk7Cj4gKyAgICB9Cj4gKwo+ICsgIGJsb2NrX2FkZHIgPSBncnViX2xlX3RvX2NwdTMy IChub2RlX2Jsb2NrLT5kbi5hZGRyW29mZnNldFtsZXZlbF1dKTsKPiArZmFpbDoKPiArICBncnVi X2ZyZWUgKG5vZGVfYmxvY2spOwo+ICsgIHJldHVybiBibG9ja19hZGRyOwo+ICt9Cj4gKwo+ICtz dGF0aWMgZ3J1Yl9zc2l6ZV90Cj4gK2dydWJfZjJmc19yZWFkX2ZpbGUgKGdydWJfZnNoZWxwX25v ZGVfdCBub2RlLAo+ICsJCWdydWJfZGlza19yZWFkX2hvb2tfdCByZWFkX2hvb2ssIHZvaWQgKnJl YWRfaG9va19kYXRhLAo+ICsJCWdydWJfb2ZmX3QgcG9zLCBncnViX3NpemVfdCBsZW4sIGNoYXIg KmJ1ZikKPiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfaW5vZGUgKmlub2RlID0gJm5vZGUtPmlu b2RlLmk7Cj4gKyAgZ3J1Yl9vZmZfdCBmaWxlc2l6ZSA9IGdydWJfZjJmc19maWxlX3NpemUgKGlu b2RlKTsKPiArICBjaGFyICppbmxpbmVfYWRkciA9IF9faW5saW5lX2FkZHIgKGlub2RlKTsKPiAr Cj4gKyAgaWYgKGlub2RlLT5pX2lubGluZSAmIEYyRlNfSU5MSU5FX0RBVEEpCj4gKyAgICB7Cj4g KyAgICAgIGlmIChmaWxlc2l6ZSA+IE1BWF9JTkxJTkVfREFUQSkKPiArICAgICAgICByZXR1cm4g LTE7Cj4gKyAgICAgIGlmIChsZW4gPiBmaWxlc2l6ZSAtIHBvcykKPiArICAgICAgICBsZW4gPSBm aWxlc2l6ZSAtIHBvczsKPiArCj4gKyAgICAgIGdydWJfbWVtY3B5IChidWYsIGlubGluZV9hZGRy ICsgcG9zLCBsZW4pOwo+ICsgICAgICByZXR1cm4gbGVuOwo+ICsgICAgfQo+ICsKPiArICByZXR1 cm4gZ3J1Yl9mc2hlbHBfcmVhZF9maWxlIChub2RlLT5kYXRhLT5kaXNrLCBub2RlLAo+ICsJCQly ZWFkX2hvb2ssIHJlYWRfaG9va19kYXRhLAo+ICsJCQlwb3MsIGxlbiwgYnVmLCBncnViX2YyZnNf Z2V0X2Jsb2NrLAo+ICsJCQlmaWxlc2l6ZSwKPiArCQkJRjJGU19CTEtfU0VDX0JJVFMsIDApOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgY2hhciAqCj4gK2dydWJfZjJmc19yZWFkX3N5bWxpbmsgKGdydWJf ZnNoZWxwX25vZGVfdCBub2RlKQo+ICt7Cj4gKyAgY2hhciAqc3ltbGluazsKPiArICBzdHJ1Y3Qg Z3J1Yl9mc2hlbHBfbm9kZSAqZGlybyA9IG5vZGU7Cj4gKyAgZ3J1Yl91aW50NjRfdCBmaWxlc2l6 ZTsKPiArCj4gKyAgaWYgKCFkaXJvLT5pbm9kZV9yZWFkKQo+ICsgICAgewo+ICsgICAgICBncnVi X2YyZnNfcmVhZF9ub2RlIChkaXJvLT5kYXRhLCBkaXJvLT5pbm8sICZkaXJvLT5pbm9kZSk7Cj4g KyAgICAgIGlmIChncnViX2Vycm5vKQo+ICsgICAgICAgIHJldHVybiAwOwo+ICsgICAgfQo+ICsK PiArICBmaWxlc2l6ZSA9IGdydWJfZjJmc19maWxlX3NpemUoJmRpcm8tPmlub2RlLmkpOwo+ICsK PiArICBzeW1saW5rID0gZ3J1Yl9tYWxsb2MgKGZpbGVzaXplICsgMSk7Cj4gKyAgaWYgKCFzeW1s aW5rKQo+ICsgICAgcmV0dXJuIDA7Cj4gKwo+ICsgIGdydWJfZjJmc19yZWFkX2ZpbGUgKGRpcm8s IDAsIDAsIDAsIGZpbGVzaXplLCBzeW1saW5rKTsKPiArICBpZiAoZ3J1Yl9lcnJubykKPiArICAg IHsKPiArICAgICAgZ3J1Yl9mcmVlIChzeW1saW5rKTsKPiArICAgICAgcmV0dXJuIDA7Cj4gKyAg ICB9Cj4gKwo+ICsgIHN5bWxpbmtbZmlsZXNpemVdID0gJ1wwJzsKPiArICByZXR1cm4gc3ltbGlu azsKPiArfQo+ICsKPiArc3RhdGljIGludAo+ICtncnViX2YyZnNfY2hlY2tfZGVudHJpZXMgKHN0 cnVjdCBncnViX2YyZnNfZGlyX2l0ZXJfY3R4ICpjdHgpCj4gK3sKPiArICBzdHJ1Y3QgZ3J1Yl9m c2hlbHBfbm9kZSAqZmRpcm87Cj4gKyAgaW50IGk7Cj4gKwo+ICsgIGZvciAoaSA9IDA7IGkgPCBj dHgtPm1heDspCj4gKyAgICB7Cj4gKyAgICAgIGNoYXIgKmZpbGVuYW1lOwo+ICsgICAgICBlbnVt IGdydWJfZnNoZWxwX2ZpbGV0eXBlIHR5cGUgPSBHUlVCX0ZTSEVMUF9VTktOT1dOOwo+ICsgICAg ICBlbnVtIEZJTEVfVFlQRSBmdHlwZTsKPiArICAgICAgaW50IG5hbWVfbGVuOwo+ICsgICAgICBp bnQgcmV0Owo+ICsKPiArICAgICAgaWYgKGdydWJfZjJmc190ZXN0X2JpdF9sZSAoaSwgY3R4LT5i aXRtYXApID09IDApCj4gKyAgICAgICAgewo+ICsgICAgICAgICAgaSsrOwo+ICsgICAgICAgICAg Y29udGludWU7Cj4gKyAgICAgICAgfQo+ICsKPiArICAgICAgZnR5cGUgPSBjdHgtPmRlbnRyeVtp XS5maWxlX3R5cGU7Cj4gKyAgICAgIG5hbWVfbGVuID0gZ3J1Yl9sZV90b19jcHUxNiAoY3R4LT5k ZW50cnlbaV0ubmFtZV9sZW4pOwo+ICsgICAgICBmaWxlbmFtZSA9IGdydWJfbWFsbG9jIChuYW1l X2xlbiArIDEpOwo+ICsgICAgICBpZiAoIWZpbGVuYW1lKQo+ICsgICAgICAgIHJldHVybiAwOwo+ ICsKPiArICAgICAgZ3J1Yl9tZW1jcHkgKGZpbGVuYW1lLCBjdHgtPmZpbGVuYW1lW2ldLCBuYW1l X2xlbik7Cj4gKyAgICAgIGZpbGVuYW1lW25hbWVfbGVuXSA9IDA7Cj4gKwo+ICsgICAgICBmZGly byA9IGdydWJfbWFsbG9jIChzaXplb2YgKHN0cnVjdCBncnViX2ZzaGVscF9ub2RlKSk7Cj4gKyAg ICAgIGlmICghZmRpcm8pCj4gKyAgICAgICAgewo+ICsgICAgICAgICAgZ3J1Yl9mcmVlKGZpbGVu YW1lKTsKPiArICAgICAgICAgIHJldHVybiAwOwo+ICsgICAgICAgIH0KPiArCj4gKyAgICAgIGlm IChmdHlwZSA9PSBGMkZTX0ZUX0RJUikKPiArICAgICAgICB0eXBlID0gR1JVQl9GU0hFTFBfRElS Owo+ICsgICAgICBlbHNlIGlmIChmdHlwZSA9PSBGMkZTX0ZUX1NZTUxJTkspCj4gKyAgICAgICAg dHlwZSA9IEdSVUJfRlNIRUxQX1NZTUxJTks7Cj4gKyAgICAgIGVsc2UgaWYgKGZ0eXBlID09IEYy RlNfRlRfUkVHX0ZJTEUpCj4gKyAgICAgICAgdHlwZSA9IEdSVUJfRlNIRUxQX1JFRzsKPiArCj4g KyAgICAgIGZkaXJvLT5kYXRhID0gY3R4LT5kYXRhOwo+ICsgICAgICBmZGlyby0+aW5vID0gZ3J1 Yl9sZV90b19jcHUzMiAoY3R4LT5kZW50cnlbaV0uaW5vKTsKPiArICAgICAgZmRpcm8tPmlub2Rl X3JlYWQgPSAwOwo+ICsKPiArICAgICAgcmV0ID0gY3R4LT5ob29rIChmaWxlbmFtZSwgdHlwZSwg ZmRpcm8sIGN0eC0+aG9va19kYXRhKTsKPiArICAgICAgZ3J1Yl9mcmVlKGZpbGVuYW1lKTsKPiAr ICAgICAgaWYgKHJldCkKPiArICAgICAgICByZXR1cm4gMTsKPiArCj4gKyAgICAgIGkgKz0gKG5h bWVfbGVuICsgRjJGU19TTE9UX0xFTiAtIDEpIC8gRjJGU19TTE9UX0xFTjsKPiArICAgIH0KPiAr ICAgIHJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50Cj4gK2dydWJfZjJmc19pdGVyYXRl X2lubGluZV9kaXIgKHN0cnVjdCBncnViX2YyZnNfaW5vZGUgKmRpciwKPiArCXN0cnVjdCBncnVi X2YyZnNfZGlyX2l0ZXJfY3R4ICpjdHgpCj4gK3sKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2lubGlu ZV9kZW50cnkgKmRlX2JsazsKPiArCj4gKyAgZGVfYmxrID0gKHN0cnVjdCBncnViX2YyZnNfaW5s aW5lX2RlbnRyeSAqKSBfX2lubGluZV9hZGRyIChkaXIpOwo+ICsKPiArICBjdHgtPmJpdG1hcCA9 IGRlX2Jsay0+ZGVudHJ5X2JpdG1hcDsKPiArICBjdHgtPmRlbnRyeSA9IGRlX2Jsay0+ZGVudHJ5 Owo+ICsgIGN0eC0+ZmlsZW5hbWUgPSBkZV9ibGstPmZpbGVuYW1lOwo+ICsgIGN0eC0+bWF4ID0g TlJfSU5MSU5FX0RFTlRSWTsKPiArCj4gKyAgcmV0dXJuIGdydWJfZjJmc19jaGVja19kZW50cmll cyAoY3R4KTsKPiArfQo+ICsKPiArc3RhdGljIGludAo+ICtncnViX2YyZnNfaXRlcmF0ZV9kaXIg KGdydWJfZnNoZWxwX25vZGVfdCBkaXIsCj4gKwlncnViX2ZzaGVscF9pdGVyYXRlX2Rpcl9ob29r X3QgaG9vaywgdm9pZCAqaG9va19kYXRhKQo+ICt7Cj4gKyAgc3RydWN0IGdydWJfZnNoZWxwX25v ZGUgKmRpcm8gPSAoc3RydWN0IGdydWJfZnNoZWxwX25vZGUgKikgZGlyOwo+ICsgIHN0cnVjdCBn cnViX2YyZnNfaW5vZGUgKmlub2RlOwo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGlyX2l0ZXJfY3R4 IGN0eCA9IHsKPiArICAgIC5kYXRhID0gZGlyby0+ZGF0YSwKPiArICAgIC5ob29rID0gaG9vaywK PiArICAgIC5ob29rX2RhdGEgPSBob29rX2RhdGEKPiArICB9Owo+ICsgIGdydWJfb2ZmX3QgZnBv cyA9IDA7Cj4gKwo+ICsgIGlmICghZGlyby0+aW5vZGVfcmVhZCkKPiArICAgIHsKPiArICAgICAg Z3J1Yl9mMmZzX3JlYWRfbm9kZSAoZGlyby0+ZGF0YSwgZGlyby0+aW5vLCAmZGlyby0+aW5vZGUp Owo+ICsgICAgICBpZiAoZ3J1Yl9lcnJubykKPiArCXJldHVybiAwOwo+ICsgICAgfQo+ICsKPiAr ICBpbm9kZSA9ICZkaXJvLT5pbm9kZS5pOwo+ICsKPiArICBpZiAoaW5vZGUtPmlfaW5saW5lICYg RjJGU19JTkxJTkVfREVOVFJZKQo+ICsgICAgcmV0dXJuIGdydWJfZjJmc19pdGVyYXRlX2lubGlu ZV9kaXIgKGlub2RlLCAmY3R4KTsKPiArCj4gKyAgd2hpbGUgKGZwb3MgPCBncnViX2YyZnNfZmls ZV9zaXplIChpbm9kZSkpCj4gKyAgICB7Cj4gKyAgICAgIHN0cnVjdCBncnViX2YyZnNfZGVudHJ5 X2Jsb2NrICpkZV9ibGs7Cj4gKyAgICAgIGNoYXIgKmJ1ZjsKPiArICAgICAgaW50IHJldDsKPiAr Cj4gKyAgICAgIGJ1ZiA9IGdydWJfemFsbG9jIChGMkZTX0JMS1NJWkUpOwo+ICsgICAgICBpZiAo IWJ1ZikKPiArICAgICAgICByZXR1cm4gMDsKPiArCj4gKyAgICAgIGdydWJfZjJmc19yZWFkX2Zp bGUgKGRpcm8sIDAsIDAsIGZwb3MsIEYyRlNfQkxLU0laRSwgYnVmKTsKPiArICAgICAgaWYgKGdy dWJfZXJybm8pCj4gKyAgICAgICAgewo+ICsgICAgICAgICAgZ3J1Yl9mcmVlIChidWYpOwo+ICsg ICAgICAgICAgcmV0dXJuIDA7Cj4gKyAgICAgICAgfQo+ICsKPiArICAgICAgZGVfYmxrID0gKHN0 cnVjdCBncnViX2YyZnNfZGVudHJ5X2Jsb2NrICopIGJ1ZjsKPiArCj4gKyAgICAgIGN0eC5iaXRt YXAgPSBkZV9ibGstPmRlbnRyeV9iaXRtYXA7Cj4gKyAgICAgIGN0eC5kZW50cnkgPSBkZV9ibGst PmRlbnRyeTsKPiArICAgICAgY3R4LmZpbGVuYW1lID0gZGVfYmxrLT5maWxlbmFtZTsKPiArICAg ICAgY3R4Lm1heCA9IE5SX0RFTlRSWV9JTl9CTE9DSzsKPiArCj4gKyAgICAgIHJldCA9IGdydWJf ZjJmc19jaGVja19kZW50cmllcyAoJmN0eCk7Cj4gKyAgICAgIGdydWJfZnJlZSAoYnVmKTsKPiAr ICAgICAgaWYgKHJldCkKPiArICAgICAgICByZXR1cm4gMTsKPiArCj4gKyAgICAgIGZwb3MgKz0g RjJGU19CTEtTSVpFOwo+ICsgICAgfQo+ICsgIHJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMg aW50Cj4gK2dydWJfZjJmc19kaXJfaXRlciAoY29uc3QgY2hhciAqZmlsZW5hbWUsIGVudW0gZ3J1 Yl9mc2hlbHBfZmlsZXR5cGUgZmlsZXR5cGUsCj4gKwkgICAgICBncnViX2ZzaGVscF9ub2RlX3Qg bm9kZSwgdm9pZCAqZGF0YSkKPiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGlyX2N0eCAqY3R4 ID0gZGF0YTsKPiArICBzdHJ1Y3QgZ3J1Yl9kaXJob29rX2luZm8gaW5mbzsKPiArCj4gKyAgZ3J1 Yl9tZW1zZXQgKCZpbmZvLCAwLCBzaXplb2YgKGluZm8pKTsKPiArICBpZiAoIW5vZGUtPmlub2Rl X3JlYWQpCj4gKyAgICB7Cj4gKyAgICAgIGdydWJfZjJmc19yZWFkX25vZGUgKGN0eC0+ZGF0YSwg bm9kZS0+aW5vLCAmbm9kZS0+aW5vZGUpOwo+ICsgICAgICBpZiAoIWdydWJfZXJybm8pCj4gKyAg ICAgICAgbm9kZS0+aW5vZGVfcmVhZCA9IDE7Cj4gKyAgICAgIGdydWJfZXJybm8gPSBHUlVCX0VS Ul9OT05FOwo+ICsgICAgfQo+ICsgIGlmIChub2RlLT5pbm9kZV9yZWFkKQo+ICsgICAgewo+ICsg ICAgICBpbmZvLm10aW1lc2V0ID0gMTsKPiArICAgICAgaW5mby5tdGltZSA9IGdydWJfbGVfdG9f Y3B1NjQgKG5vZGUtPmlub2RlLmkuaV9tdGltZSk7Cj4gKyAgICB9Cj4gKwo+ICsgIGluZm8uZGly ID0gKChmaWxldHlwZSAmIEdSVUJfRlNIRUxQX1RZUEVfTUFTSykgPT0gR1JVQl9GU0hFTFBfRElS KTsKPiArICBncnViX2ZyZWUgKG5vZGUpOwo+ICsgIHJldHVybiBjdHgtPmhvb2sgKGZpbGVuYW1l LCAmaW5mbywgY3R4LT5ob29rX2RhdGEpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgZ3J1Yl9lcnJfdAo+ ICtncnViX2YyZnNfZGlyIChncnViX2RldmljZV90IGRldmljZSwgY29uc3QgY2hhciAqcGF0aCwK PiArCWdydWJfZnNfZGlyX2hvb2tfdCBob29rLCB2b2lkICpob29rX2RhdGEpCj4gK3sKPiArICBz dHJ1Y3QgZ3J1Yl9mMmZzX2Rpcl9jdHggY3R4ID0gewo+ICsgICAgLmhvb2sgPSBob29rLAo+ICsg ICAgLmhvb2tfZGF0YSA9IGhvb2tfZGF0YQo+ICsgIH07Cj4gKyAgc3RydWN0IGdydWJfZnNoZWxw X25vZGUgKmZkaXJvID0gMDsKPiArCj4gKyAgZ3J1Yl9kbF9yZWYgKG15X21vZCk7Cj4gKwo+ICsg IGN0eC5kYXRhID0gZ3J1Yl9mMmZzX21vdW50IChkZXZpY2UtPmRpc2spOwo+ICsgIGlmICghY3R4 LmRhdGEpCj4gKyAgICBnb3RvIGZhaWw7Cj4gKwo+ICsgIGdydWJfZnNoZWxwX2ZpbmRfZmlsZSAo cGF0aCwgJmN0eC5kYXRhLT5kaXJvcGVuLCAmZmRpcm8sCj4gKwkJZ3J1Yl9mMmZzX2l0ZXJhdGVf ZGlyLCBncnViX2YyZnNfcmVhZF9zeW1saW5rLAo+ICsJCUdSVUJfRlNIRUxQX0RJUik7Cj4gKyAg aWYgKGdydWJfZXJybm8pCj4gKyAgICBnb3RvIGZhaWw7Cj4gKwo+ICsgIGdydWJfZjJmc19pdGVy YXRlX2RpciAoZmRpcm8sIGdydWJfZjJmc19kaXJfaXRlciwgJmN0eCk7Cj4gKwo+ICtmYWlsOgo+ ICsgIGlmIChmZGlybyAhPSAmY3R4LmRhdGEtPmRpcm9wZW4pCj4gKyAgICBncnViX2ZyZWUgKGZk aXJvKTsKPiArIGdydWJfZnJlZSAoY3R4LmRhdGEpOwo+ICsgZ3J1Yl9kbF91bnJlZiAobXlfbW9k KTsKPiArIHJldHVybiBncnViX2Vycm5vOwo+ICt9Cj4gKwo+ICsKPiArLyogT3BlbiBhIGZpbGUg bmFtZWQgTkFNRSBhbmQgaW5pdGlhbGl6ZSBGSUxFLiAgKi8KPiArc3RhdGljIGdydWJfZXJyX3QK PiArZ3J1Yl9mMmZzX29wZW4gKHN0cnVjdCBncnViX2ZpbGUgKmZpbGUsIGNvbnN0IGNoYXIgKm5h bWUpCj4gK3sKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGEgPSBOVUxMOwo+ICsgIHN0 cnVjdCBncnViX2ZzaGVscF9ub2RlICpmZGlybyA9IDA7Cj4gKyAgc3RydWN0IGdydWJfZjJmc19p bm9kZSAqaW5vZGU7Cj4gKwo+ICsgIGdydWJfZGxfcmVmIChteV9tb2QpOwo+ICsKPiArICBkYXRh ID0gZ3J1Yl9mMmZzX21vdW50IChmaWxlLT5kZXZpY2UtPmRpc2spOwo+ICsgIGlmICghZGF0YSkK PiArICAgIGdvdG8gZmFpbDsKPiArCj4gKyAgZ3J1Yl9mc2hlbHBfZmluZF9maWxlIChuYW1lLCAm ZGF0YS0+ZGlyb3BlbiwgJmZkaXJvLAo+ICsJCQlncnViX2YyZnNfaXRlcmF0ZV9kaXIsIGdydWJf ZjJmc19yZWFkX3N5bWxpbmssCj4gKwkJCUdSVUJfRlNIRUxQX1JFRyk7Cj4gKyAgaWYgKGdydWJf ZXJybm8pCj4gKyAgICBnb3RvIGZhaWw7Cj4gKwo+ICsgIGlmICghZmRpcm8tPmlub2RlX3JlYWQp Cj4gKyAgICB7Cj4gKyAgICAgIGdydWJfZjJmc19yZWFkX25vZGUgKGRhdGEsIGZkaXJvLT5pbm8s ICZmZGlyby0+aW5vZGUpOwo+ICsgICAgICBpZiAoZ3J1Yl9lcnJubykKPiArCWdvdG8gZmFpbDsK PiArICAgIH0KPiArCj4gKyAgZ3J1Yl9tZW1jcHkgKGRhdGEtPmlub2RlLCAmZmRpcm8tPmlub2Rl LCBzaXplb2YgKCpkYXRhLT5pbm9kZSkpOwo+ICsgIGdydWJfZnJlZSAoZmRpcm8pOwo+ICsKPiAr ICBpbm9kZSA9ICYoZGF0YS0+aW5vZGUtPmkpOwo+ICsgIGZpbGUtPnNpemUgPSBncnViX2YyZnNf ZmlsZV9zaXplIChpbm9kZSk7Cj4gKyAgZmlsZS0+ZGF0YSA9IGRhdGE7Cj4gKyAgZmlsZS0+b2Zm c2V0ID0gMDsKPiArCj4gKyAgaWYgKGlub2RlLT5pX2lubGluZSAmIEYyRlNfSU5MSU5FX0RBVEEg JiYgZmlsZS0+c2l6ZSA+IE1BWF9JTkxJTkVfREFUQSkKPiArICAgIGdydWJfZXJyb3IgKEdSVUJf RVJSX0JBRF9GUywgImNvcnJ1cHRlZCBpbmxpbmVfZGF0YTogbmVlZCBmc2NrIik7Cj4gKyAgcmV0 dXJuIDA7Cj4gKwo+ICtmYWlsOgo+ICsgIGlmIChmZGlybyAhPSAmZGF0YS0+ZGlyb3BlbikKPiAr ICAgIGdydWJfZnJlZSAoZmRpcm8pOwo+ICsgIGdydWJfZnJlZSAoZGF0YSk7Cj4gKwo+ICsgIGdy dWJfZGxfdW5yZWYgKG15X21vZCk7Cj4gKwo+ICsgIHJldHVybiBncnViX2Vycm5vOwo+ICt9Cj4g Kwo+ICtzdGF0aWMgZ3J1Yl9zc2l6ZV90Cj4gK2dydWJfZjJmc19yZWFkIChncnViX2ZpbGVfdCBm aWxlLCBjaGFyICpidWYsIGdydWJfc2l6ZV90IGxlbikKPiArewo+ICsgIHN0cnVjdCBncnViX2Yy ZnNfZGF0YSAqZGF0YSA9IChzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKikgZmlsZS0+ZGF0YTsKPiAr Cj4gKyAgcmV0dXJuIGdydWJfZjJmc19yZWFkX2ZpbGUgKCZkYXRhLT5kaXJvcGVuLAo+ICsJCWZp bGUtPnJlYWRfaG9vaywgZmlsZS0+cmVhZF9ob29rX2RhdGEsCj4gKwkJZmlsZS0+b2Zmc2V0LCBs ZW4sIGJ1Zik7Cj4gK30KPiArCj4gK3N0YXRpYyBncnViX2Vycl90Cj4gK2dydWJfZjJmc19jbG9z ZSAoZ3J1Yl9maWxlX3QgZmlsZSkKPiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0 YSA9IChzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKikgZmlsZS0+ZGF0YTsKPiArCj4gKyAgZ3J1Yl9m cmVlIChkYXRhKTsKPiArCj4gKyAgZ3J1Yl9kbF91bnJlZiAobXlfbW9kKTsKPiArCj4gKyAgcmV0 dXJuIEdSVUJfRVJSX05PTkU7Cj4gK30KPiArCj4gK3N0YXRpYyBncnViX3VpbnQ4X3QgKgo+ICtn cnViX2YyZnNfdXRmMTZfdG9fdXRmOCAoZ3J1Yl91aW50MTZfdCAqaW5fYnVmX2xlKQo+ICt7Cj4g KyAgZ3J1Yl91aW50MTZfdCBpbl9idWZbTUFYX1ZPTFVNRV9OQU1FXTsKPiArICBncnViX3VpbnQ4 X3QgKm91dF9idWY7Cj4gKyAgaW50IGxlbiA9IDA7Cj4gKwo+ICsgIG91dF9idWYgPSBncnViX21h bGxvYyAoTUFYX1ZPTFVNRV9OQU1FICogR1JVQl9NQVhfVVRGOF9QRVJfVVRGMTYgKyAxKTsKPiAr ICBpZiAoIW91dF9idWYpCj4gKyAgICByZXR1cm4gTlVMTDsKPiArCj4gKyAgd2hpbGUgKCppbl9i dWZfbGUgIT0gMCAmJiBsZW4gPCBNQVhfVk9MVU1FX05BTUUpIHsKPiArICAgIGluX2J1ZltsZW5d ID0gZ3J1Yl9sZV90b19jcHUxNiAoaW5fYnVmX2xlW2xlbl0pOwo+ICsgICAgbGVuKys7Cj4gKyAg fQo+ICsKPiArICAqZ3J1Yl91dGYxNl90b191dGY4IChvdXRfYnVmLCBpbl9idWYsIGxlbikgPSAn XDAnOwo+ICsgIHJldHVybiBvdXRfYnVmOwo+ICt9Cj4gKwo+ICtzdGF0aWMgZ3J1Yl9lcnJfdAo+ ICtncnViX2YyZnNfbGFiZWwgKGdydWJfZGV2aWNlX3QgZGV2aWNlLCBjaGFyICoqbGFiZWwpCj4g K3sKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGE7Cj4gKyAgZ3J1Yl9kaXNrX3QgZGlz ayA9IGRldmljZS0+ZGlzazsKPiArCj4gKyAgZ3J1Yl9kbF9yZWYgKG15X21vZCk7Cj4gKwo+ICsg IGRhdGEgPSBncnViX2YyZnNfbW91bnQgKGRpc2spOwo+ICsgIGlmIChkYXRhKQo+ICsgICAgKmxh YmVsID0gKGNoYXIgKikgZ3J1Yl9mMmZzX3V0ZjE2X3RvX3V0ZjggKGRhdGEtPnNibG9jay52b2x1 bWVfbmFtZSk7Cj4gKyAgZWxzZQo+ICsgICAgKmxhYmVsID0gTlVMTDsKPiArCj4gKyAgZ3J1Yl9m cmVlIChkYXRhKTsKPiArICBncnViX2RsX3VucmVmIChteV9tb2QpOwo+ICsgIHJldHVybiBncnVi X2Vycm5vOwo+ICt9Cj4gKwo+ICtzdGF0aWMgZ3J1Yl9lcnJfdAo+ICtncnViX2YyZnNfdXVpZCAo Z3J1Yl9kZXZpY2VfdCBkZXZpY2UsIGNoYXIgKip1dWlkKQo+ICt7Cj4gKyAgc3RydWN0IGdydWJf ZjJmc19kYXRhICpkYXRhOwo+ICsgIGdydWJfZGlza190IGRpc2sgPSBkZXZpY2UtPmRpc2s7Cj4g Kwo+ICsgIGdydWJfZGxfcmVmIChteV9tb2QpOwo+ICsKPiArICBkYXRhID0gZ3J1Yl9mMmZzX21v dW50IChkaXNrKTsKPiArICBpZiAoZGF0YSkKPiArICAgIHsKPiArICAgICAgKnV1aWQgPQo+ICsJ Z3J1Yl94YXNwcmludGYKPiArCSgiJTAyeCUwMnglMDJ4JTAyeC0lMDJ4JTAyeC0lMDJ4JTAyeC0l MDJ4JTAyeC0lMDJ4JTAyeCUwMnglMDJ4JTAyeCUwMngiLAo+ICsJCWRhdGEtPnNibG9jay51dWlk WzBdLCBkYXRhLT5zYmxvY2sudXVpZFsxXSwKPiArCQlkYXRhLT5zYmxvY2sudXVpZFsyXSwgZGF0 YS0+c2Jsb2NrLnV1aWRbM10sCj4gKwkJZGF0YS0+c2Jsb2NrLnV1aWRbNF0sIGRhdGEtPnNibG9j ay51dWlkWzVdLAo+ICsJCWRhdGEtPnNibG9jay51dWlkWzZdLCBkYXRhLT5zYmxvY2sudXVpZFs3 XSwKPiArCQlkYXRhLT5zYmxvY2sudXVpZFs4XSwgZGF0YS0+c2Jsb2NrLnV1aWRbOV0sCj4gKwkJ ZGF0YS0+c2Jsb2NrLnV1aWRbMTBdLCBkYXRhLT5zYmxvY2sudXVpZFsxMV0sCj4gKwkJZGF0YS0+ c2Jsb2NrLnV1aWRbMTJdLCBkYXRhLT5zYmxvY2sudXVpZFsxM10sCj4gKwkJZGF0YS0+c2Jsb2Nr LnV1aWRbMTRdLCBkYXRhLT5zYmxvY2sudXVpZFsxNV0pOwo+ICsgICAgfQo+ICsgIGVsc2UKPiAr ICAgICp1dWlkID0gTlVMTDsKPiArCj4gKyAgZ3J1Yl9mcmVlIChkYXRhKTsKPiArICBncnViX2Rs X3VucmVmIChteV9tb2QpOwo+ICsgIHJldHVybiBncnViX2Vycm5vOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgc3RydWN0IGdydWJfZnMgZ3J1Yl9mMmZzX2ZzID0gewo+ICsgIC5uYW1lID0gImYyZnMiLAo+ ICsgIC5kaXIgPSBncnViX2YyZnNfZGlyLAo+ICsgIC5vcGVuID0gZ3J1Yl9mMmZzX29wZW4sCj4g KyAgLnJlYWQgPSBncnViX2YyZnNfcmVhZCwKPiArICAuY2xvc2UgPSBncnViX2YyZnNfY2xvc2Us Cj4gKyAgLmxhYmVsID0gZ3J1Yl9mMmZzX2xhYmVsLAo+ICsgIC51dWlkID0gZ3J1Yl9mMmZzX3V1 aWQsCj4gKyNpZmRlZiBHUlVCX1VUSUwKPiArICAucmVzZXJ2ZWRfZmlyc3Rfc2VjdG9yID0gMSwK PiArICAuYmxvY2tsaXN0X2luc3RhbGwgPSAwLAo+ICsjZW5kaWYKPiArICAubmV4dCA9IDAKPiAr fTsKPiArCj4gK0dSVUJfTU9EX0lOSVQgKGYyZnMpCj4gK3sKPiArICBncnViX2ZzX3JlZ2lzdGVy ICgmZ3J1Yl9mMmZzX2ZzKTsKPiArICBteV9tb2QgPSBtb2Q7Cj4gK30KPiArCj4gK0dSVUJfTU9E X0ZJTkkgKGYyZnMpCj4gK3sKPiArICBncnViX2ZzX3VucmVnaXN0ZXIgKCZncnViX2YyZnNfZnMp Owo+ICt9Cj4gZGlmZiAtLWdpdCBhL3BvL2V4Y2x1ZGUucG90IGIvcG8vZXhjbHVkZS5wb3QKPiBp bmRleCAwYTliMjE1Li44MTYwODljIDEwMDY0NAo+IC0tLSBhL3BvL2V4Y2x1ZGUucG90Cj4gKysr IGIvcG8vZXhjbHVkZS5wb3QKPiBAQCAtMTIxNCw2ICsxMjE0LDcgQEAgbXNnc3RyICIiCj4gIAo+ ICAjOiBncnViLWNvcmUvY29tbWFuZHMveG51X3V1aWQuYzo3NSBncnViLWNvcmUvZnMvamZzLmM6 OTI0Cj4gICM6IGdydWItY29yZS9mcy9uaWxmczIuYzoxMTM1Cj4gKyM6IGdydWItY29yZS9mcy9m MmZzLmM6MTI1OQo+ICAjLCBjLWZvcm1hdAo+ICBtc2dpZCAiJTAyeCUwMnglMDJ4JTAyeC0lMDJ4 JTAyeC0lMDJ4JTAyeC0lMDJ4JTAyeC0lMDJ4JTAyeCUwMnglMDJ4JTAyeCUwMngiCj4gIG1zZ3N0 ciAiIgo+IGRpZmYgLS1naXQgYS90ZXN0cy9mMmZzX3Rlc3QuaW4gYi90ZXN0cy9mMmZzX3Rlc3Qu aW4KPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLjFlYTc3YzgKPiAtLS0g L2Rldi9udWxsCj4gKysrIGIvdGVzdHMvZjJmc190ZXN0LmluCj4gQEAgLTAsMCArMSwxOSBAQAo+ ICsjIS9iaW4vc2gKPiArCj4gK3NldCAtZQo+ICsKPiAraWYgWyAieCRFVUlEIiA9ICJ4IiBdIDsg dGhlbgo+ICsgRVVJRD1gaWQgLXVgCj4gK2ZpCj4gKwo+ICtpZiBbICIkRVVJRCIgIT0gMCBdIDsg dGhlbgo+ICsgZXhpdCA3Nwo+ICtmaQo+ICsKPiAraWYgISB3aGljaCBta2ZzLmYyZnMgPi9kZXYv bnVsbCAyPiYxOyB0aGVuCj4gKyBlY2hvICJta2ZzLmYyZnMgbm90IGluc3RhbGxlZDsgY2Fubm90 IHRlc3QgZjJmcy4iCj4gKyBleGl0IDc3Cj4gK2ZpCj4gKwo+ICsKPiArIkBidWlsZGRpckAvZ3J1 Yi1mcy10ZXN0ZXIiIGYyZnMKPiBkaWZmIC0tZ2l0IGEvdGVzdHMvdXRpbC9ncnViLWZzLXRlc3Rl ci5pbiBiL3Rlc3RzL3V0aWwvZ3J1Yi1mcy10ZXN0ZXIuaW4KPiBpbmRleCA0MjRkZTIyLi5lM2U0 MTA5IDEwMDY0NAo+IC0tLSBhL3Rlc3RzL3V0aWwvZ3J1Yi1mcy10ZXN0ZXIuaW4KPiArKysgYi90 ZXN0cy91dGlsL2dydWItZnMtdGVzdGVyLmluCj4gQEAgLTE0Miw3ICsxNDIsNyBAQCBmb3IgKChM T0dTRUNTSVpFPU1JTkxPR1NFQ1NJWkU7TE9HU0VDU0laRTw9TUFYTE9HU0VDU0laRTtMT0dTRUNT SVpFPUxPR1NFQ1NJWkUgKwo+ICAJeHNxdWFzaCopCj4gIAkgICAgTUlOQkxLU0laRT00MDk2Cj4g IAkgICAgTUFYQkxLU0laRT0xMDQ4NTc2OzsKPiAtCXh4ZnMpCj4gKwl4eGZzfHhmMmZzKQo+ICAJ ICAgIE1JTkJMS1NJWkU9JFNFQ1NJWkUKPiAgCQkjIE9TIExpbWl0YXRpb246IEdOVS9MaW51eCBk b2Vzbid0IGFjY2VwdCA+IDQwOTYKPiAgCSAgICBNQVhCTEtTSVpFPTQwOTY7Owo+IEBAIC0yNjUs NiArMjY1LDEwIEBAIGZvciAoKExPR1NFQ1NJWkU9TUlOTE9HU0VDU0laRTtMT0dTRUNTSVpFPD1N QVhMT0dTRUNTSVpFO0xPR1NFQ1NJWkU9TE9HU0VDU0laRSArCj4gIAkJeCJidHJmcyIqKQo+ICAJ CSAgICBGU0xBQkVMPSJncnViXzsvdGVzdMOp8K+mm/Cvpp3wn5iB0LrQuNGA0LjRgmkgdXJld2Zj ZW5pdWV3cnVldnJld251dWlyZXVyZXZ1ZXVybmlldnJld2ZuZXJmY25ldmlyaXZpbnJld3ZuaXJl d25pdnJld2l1dmNyZXd2bnVld3ZycnJld25pdWVyd3JlaXV2aXVyZXdpdXZpdXJld251dmV3bnZy ZW51cm51bnV2cmV2dXVyZXJlamlyZW12cmVpam52Y3JlaXZpcmUgbnZlcml2bnJlaXZyZXZudXJl aW9yZm5mcnZvZW9pcm9pcmVvaXJlb2lmcmVmb2llcm9pZm9pcmVvaWYiOzsKPiAgCj4gKwkgICAg IyBGUyBMSU1JVEFUSU9OOiBmMmZzIGxhYmVsIGlzIGF0IG1vc3QgNTEyIFVURi0xNiBjaGFycwo+ ICsJCXgiZjJmcyIpCj4gKwkJICAgIEZTTEFCRUw9ImdydWJfOy90ZXN0w6nkj4zkkJPkj5XQutC4 0YDQuNGCaXVyZXdmY2VuaXVld3J1ZXdudXVpcmV1cmV2dWV1cm5pZXZyZXdmbmVyZmNuZXZpcml2 aW5yZXd2bmlyZXduaXZyZXdpdXZjcmV3dm51ZXd2cnJyZXduaXVlcndyZWl1dml1cmV3aXV2aXVy ZXdudXZld252cmVudXJudW51dnJldnV1cmVyZWppcmVtdnJlaWpudnZjcmVpdmlyZSBudmVyaXZu cmVpdnJldm51cmVpb3JmbmZydm9lb2lyb2lyZW9pcmVvaWZyZWZvaWVyb2lmb2lydmNyZWl2aXJl IG52ZXJpdm5yZWl2cmV2bnVyZWlvcmZuZnJ2b2VvaXJvaXJlb2lyZW9pZnJlZm9pZXJvaWZvaXJj cmVpdmlyZSBudmVyaXZucmVpdnJldm51cmVpb3JmbmZydm9lb2lyb2lyZW9pcmVvaWZyZWZvaWVy b2lmb2lyZW9pZm9pcSI7Owo+ICsKPiAgCSAgICAjIEZTIExJTUlUQVRJT046IGV4ZmF0IGlzIGF0 IG1vc3QgMTUgVVRGLTE2IGNoYXJzCj4gIAkJeCJleGZhdCIpCj4gIAkJICAgIEZTTEFCRUw9ImfD qdGCIDsv8K+mm/Cvpp3wn5iB0LrQuNGAIjs7Cj4gQEAgLTQ3NCw3ICs0NzgsNyBAQCBmb3IgKChM T0dTRUNTSVpFPU1JTkxPR1NFQ1NJWkU7TE9HU0VDU0laRTw9TUFYTE9HU0VDU0laRTtMT0dTRUNT SVpFPUxPR1NFQ1NJWkUgKwo+ICAJICAgICMgRklYTUU6IE5vdCBzdXJlIGFib3V0IEJ0ckZTLCBO VEZTLCBKRlMsIEFGUywgVURGIGFuZCBTRlMuIENoZWNrIGl0Lgo+ICAJIyBGUyBMSU1JVEFUSU9O OiBhcyBmYXIgYXMgSSBrbm93IHRob3NlIEZTIGRvbid0IHN0b3JlIHRoZWlyIGxhc3QgbW9kaWZp Y2F0aW9uIGRhdGUuCj4gIAkJeCJqZnNfY2FzZWlucyIgfCB4ImpmcyIgfCB4InhmcyIgfCB4Inhm c19jcmMiIHwgeCJidHJmcyIqIHwgeCJyZWlzZXJmc19vbGQiIHwgeCJyZWlzZXJmcyIgXAo+IC0J CSAgICB8IHgiYmZzIiB8IHgiYWZzIiBcCj4gKwkJICAgIHwgeCJiZnMiIHwgeCJhZnMiIHwgeCJm MmZzIiBcCj4gIAkJICAgIHwgeCJ0YXJmcyIgfCB4ImNwaW9fIiogfCB4Im1pbml4IiB8IHgibWlu aXgyIiBcCj4gIAkJICAgIHwgeCJtaW5peDMiIHwgeCJudGZzIiogfCB4InVkZiIgfCB4InNmcyIq KQo+ICAJCSAgICBOT0ZTVElNRT15OzsKPiBAQCAtNzUzLDYgKzc1Nyw4IEBAIGZvciAoKExPR1NF Q1NJWkU9TUlOTE9HU0VDU0laRTtMT0dTRUNTSVpFPD1NQVhMT0dTRUNTSVpFO0xPR1NFQ1NJWkU9 TE9HU0VDU0laRSArCj4gIAkJICAgIE1PVU5UREVWSUNFPSIvZGV2L21hcHBlci9ncnViX3Rlc3Qt dGVzdHZvbCIKPiAgCQkgICAgTU9VTlRGUz1leHQyCj4gIAkJICAgICJta2ZzLmV4dDIiIC1MICIk RlNMQUJFTCIgLXEgIiR7TU9VTlRERVZJQ0V9IiAgOzsKPiArCQl4ZjJmcykKPiArCQkgICAgIm1r ZnMuZjJmcyIgLWwgIiRGU0xBQkVMIiAtcSAiJHtMT0RFVklDRVNbMF19IiA7Owo+ICAJCXhuaWxm czIpCj4gIAkJICAgICJta2ZzLm5pbGZzMiIgLUwgIiRGU0xBQkVMIiAtYiAkQkxLU0laRSAgLXEg IiR7TE9ERVZJQ0VTWzBdfSIgOzsKPiAgCQl4ZXh0Ml9vbGQpCj4gLS0gCj4gMi42LjMKPiAKPiAK PiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPiBTaXRlMjR4NyBBUE0gSW5zaWdodDogR2V0IERlZXAg VmlzaWJpbGl0eSBpbnRvIEFwcGxpY2F0aW9uIFBlcmZvcm1hbmNlCj4gQVBNICsgTW9iaWxlIEFQ TSArIFJVTTogTW9uaXRvciAzIEFwcCBpbnN0YW5jZXMgYXQganVzdCAkMzUvTW9udGgKPiBNb25p dG9yIGVuZC10by1lbmQgd2ViIHRyYW5zYWN0aW9ucyBhbmQgdGFrZSBjb3JyZWN0aXZlIGFjdGlv bnMgbm93Cj4gVHJvdWJsZXNob290IGZhc3RlciBhbmQgaW1wcm92ZSBlbmQtdXNlciBleHBlcmll bmNlLiBTaWdudXAgTm93IQo+IGh0dHA6Ly9wdWJhZHMuZy5kb3VibGVjbGljay5uZXQvZ2FtcGFk L2Nsaz9pZD0yNzI0ODcxNTEmaXU9LzQxNDAKPiBfX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fXwo+IExpbnV4LWYyZnMtZGV2ZWwgbWFpbGluZyBsaXN0Cj4gTGlu dXgtZjJmcy1kZXZlbEBsaXN0cy5zb3VyY2Vmb3JnZS5uZXQKPiBodHRwczovL2xpc3RzLnNvdXJj ZWZvcmdlLm5ldC9saXN0cy9saXN0aW5mby9saW51eC1mMmZzLWRldmVsCgotLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0KX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18K TGludXgtZjJmcy1kZXZlbCBtYWlsaW5nIGxpc3QKTGludXgtZjJmcy1kZXZlbEBsaXN0cy5zb3Vy Y2Vmb3JnZS5uZXQKaHR0cHM6Ly9saXN0cy5zb3VyY2Vmb3JnZS5uZXQvbGlzdHMvbGlzdGluZm8v bGludXgtZjJmcy1kZXZlbAo=