From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1YblE3-0004XD-7L for mharc-grub-devel@gnu.org; Sat, 28 Mar 2015 03:32:11 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54456) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YblDy-0004MH-8g for grub-devel@gnu.org; Sat, 28 Mar 2015 03:32:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YblDt-0006Sg-6T for grub-devel@gnu.org; Sat, 28 Mar 2015 03:32:06 -0400 Received: from mail-la0-x22a.google.com ([2a00:1450:4010:c03::22a]:36348) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YblDs-0006SI-KN for grub-devel@gnu.org; Sat, 28 Mar 2015 03:32:01 -0400 Received: by labe2 with SMTP id e2so85456213lab.3 for ; Sat, 28 Mar 2015 00:31:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:cc:subject:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=xlZG40t7AqHHIFBrjuRDbzyCOwEXVwCAgK0RTqplKds=; b=ifeUYQJ2ACrVx/eXvBQqV9ZE1nPWJnWN8cJsSxZMRMQ98lcQnrbw4wEUfPQboi4eFf XDFVcMPas0glgbNBskl/BwQ81/2xOnOL7ciEQSgLZmgWkYmCkjbQqbY7etXeOhOGg1fI KEnAO4zl2fnyswD9A0NIUOVGCeUcCazwcnAV/s6Rc1wF50iGykbzA9QevbxMMGBzr41A OcMOou9vaaFYsu+Hj+UPU9GXE3t34yVmPQIAHxd0mHEp0NzZjSJh00xjKqyBqfuq2RGu +xXG47Em4C+EEfUeQKvEg/vR+kZu29y/yUbqsOkHyHVBhuQSKCAAjM48c1cWEh8xhj3E Hiqw== X-Received: by 10.112.132.35 with SMTP id or3mr8992283lbb.85.1427527919677; Sat, 28 Mar 2015 00:31:59 -0700 (PDT) Received: from opensuse.site (ppp91-76-14-38.pppoe.mtu-net.ru. [91.76.14.38]) by mx.google.com with ESMTPSA id o8sm750897lal.24.2015.03.28.00.31.57 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 28 Mar 2015 00:31:58 -0700 (PDT) Date: Sat, 28 Mar 2015 10:31:55 +0300 From: Andrei Borzenkov To: Jaegeuk Kim Subject: Re: [PATCH] F2FS support Message-ID: <20150328103155.5c961fec@opensuse.site> In-Reply-To: <1427185140-41120-1-git-send-email-jaegeuk@kernel.org> References: <1427185140-41120-1-git-send-email-jaegeuk@kernel.org> X-Mailer: Claws Mail 3.11.0 (GTK+ 2.24.25; x86_64-suse-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:4010:c03::22a Cc: grub-devel@gnu.org, linux-f2fs-devel@lists.sourceforge.net X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 28 Mar 2015 07:32:09 -0000 =D0=92 Tue, 24 Mar 2015 01:19:00 -0700 Jaegeuk Kim =D0=BF=D0=B8=D1=88=D0=B5=D1=82: > * Makefile.util.def: Add f2fs.c. > * doc/grub.texi: Add f2fs description. > * grub-core/Makefile.core.def: Add f2fs module. > * grub-core/fs/f2fs.c: New file. > * tests/f2fs_test.in: New file. > * tests/util/grub-fs-tester.in: Add f2fs requirements. >=20 It's not the most useful commit message. Better would be short explanation of use cases and intended platforms. I'm curious here - F2FS is intended for raw flash access, on which platform(s) grub has access to such devices?=20 >=20 > diff --git a/ChangeLog-2015 b/ChangeLog-2015 We do not use ChangeLog any more, it is autogenerated from commits. This file is legacy before this change, do not change it. > diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c > new file mode 100644 > index 0000000..40360d5 > --- /dev/null > +++ b/grub-core/fs/f2fs.c > @@ -0,0 +1,1321 @@ > +/* > + * 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 > + > +/* byte-size offset */ > +#define F2FS_SUPER_OFFSET 1024 > + > +/* 12 bits for 4096 bytes */ > +#define F2FS_MAX_LOG_SECTOR_SIZE 12 > + > +/* 9 bits for 512 bytes */ > +#define F2FS_MIN_LOG_SECTOR_SIZE 9 > + > +/* support only 4KB block */ > +#define F2FS_BLKSIZE 4096 (2 << F2FS_BLK_BITS)? > +#define F2FS_BLK_BITS 12 > +#define F2FS_BLK_SEC_BITS (3) It is confusing to have some defines parenthesized and some not. Could it be unified somehow? Also this can be computed from F2FS_BLK_BITS and GRUB_DISK_SECTOR_BITS - one magic number less. ... > +struct grub_f2fs_inline_dentry > +{ > + grub_uint8_t dentry_bitmap[INLINE_DENTRY_BITMAP_SIZE]; This is cast to grub_uint32_t everywhere. Can it be non-multiple of 4 bytes? If not, may be just define as such?=20 > + 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]; ditto > + 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; > + ... > + > +#define ver_after (a, b) (typecheck (unsigned long long, a) && \ > + typecheck (unsigned long long, b) && \ > + ((long long)((a) - (b)) > 0)) > + Where typecheck definition comes from? ... > + > +static inline int > +__test_bit (int nr, grub_uint32_t *addr) > +{ > + return 1UL & (addr[nr / 32] >> (nr & (31))); Extra parenthesis (31) > +} > + It is used for dentry_bitmap which is kept in LE format and not converted as far as I can tell. This needs fixing for BE systems. Linux kernel is explicitly using test_bit_le here. This will also work for inode flags (just skip explicit conversion). There are two functions with more or less identical names. May be make them grub_f2fs_test_bit_le32 grub_f2fs_test_bit As a general comment - marking non-modified arguments as const everywhere would be good. > +static inline char * > +__inline_addr (struct grub_f2fs_inode *inode) > +{ > + return (char *)&(inode->i_addr[1]); Redundant parens around inode-> > +} > + > +static inline grub_uint64_t > +__i_size (struct grub_f2fs_inode *inode) Could we make it grub_f2fs_file_size or similar? i_size really does not tell much outside of linux kernel. > +{ > + 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_uint64_t ckpt_version =3D grub_le_to_cpu64 (ckpt->checkpoint_ver); > + grub_uint32_t start_addr =3D data->cp_blkaddr; > + > + if (!(ckpt_version & 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_start_= 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 int > +__ckpt_flag_set (struct grub_f2fs_checkpoint *ckpt, unsigned int f) > +{ > + grub_uint32_t ckpt_flags =3D grub_le_to_cpu32 (ckpt->ckpt_flags); > + return ckpt_flags & f; All flags are constant so you can simply do=20 ckpt->ckpt_flags & grub_cpu_to_le32_compile_time (FLAG) in place to avoid extra calls. This makes function redundant. > +} > + > +static inline int > +__inode_flag_set (struct grub_f2fs_inode *inode, int flag) > +{ > + grub_uint32_t i_flags =3D grub_le_to_cpu32 (inode->i_flags); > + return __test_bit (flag, &i_flags); > +} grub_f2fs_test_bit_le32? > + > +/* > + * CRC32 > + */ > +#define CRCPOLY_LE 0xedb88320 > + > +static inline grub_uint32_t > +grub_f2fs_cal_crc32 (grub_uint32_t crc, void *buf, int len) Why crc is parameter here? This function is used exactly once with fixed value for initial crc. > +{ > + int i; > + unsigned char *p =3D (unsigned char *)buf; > + > + while (len--) > + { > + 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, int len) > +{ > + grub_uint32_t cal_crc =3D 0; > + > + cal_crc =3D grub_f2fs_cal_crc32 (F2FS_SUPER_MAGIC, 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; > + char *addr =3D (char *)p; Why cast? We are not going to modify it, right? > + > + addr +=3D (nr >> 3); > + mask =3D 1 << (7 - (nr & 0x07)); > + return (mask & *addr) !=3D 0; > +} > + > +static int > +grub_f2fs_sanity_check_sb (struct grub_f2fs_superblock *sb) > +{ > + unsigned int blocksize; > + > + if (F2FS_SUPER_MAGIC !=3D grub_le_to_cpu32 (sb->magic)) sb->magic !=3D grub_cpu_to_le32_compile_time (F2FS_SUPER_MAGIC) > + return -1; > + > + blocksize =3D 1 << grub_le_to_cpu32 (sb->log_blocksize); > + if (blocksize !=3D F2FS_BLKSIZE) sb->log_blksize !=3D grub_cpu_to_le32_compile_time (F2FS_BLK_BITS) > + return -1; > + > + if (grub_le_to_cpu32 (sb->log_sectorsize) > F2FS_MAX_LOG_SECTOR_SIZE) > + return -1; > + > + if (grub_le_to_cpu32 (sb->log_sectorsize) < F2FS_MIN_LOG_SECTOR_SIZE) > + return -1; > + > + if (grub_le_to_cpu32 (sb->log_sectors_per_block) + > + grub_le_to_cpu32 (sb->log_sectorsize) !=3D F2FS_MAX_LOG_SECTOR_SIZ= E) Should not it be F2FS_BLKSIZE? At least it sounds logical. Also please convert log_sectorsize just once. > + return -1; > + > + return 0; > +} > + > +static grub_err_t > +grub_f2fs_read_sb (struct grub_f2fs_data *data, int block) > +{ > + grub_disk_t disk =3D data->disk; > + grub_uint64_t offset; > + grub_err_t err; > + > + if (block =3D=3D 0) > + offset =3D F2FS_SUPER_OFFSET; > + else > + offset =3D F2FS_BLKSIZE + F2FS_SUPER_OFFSET; > + Please name it "secondary" or similar instead of "block" to avoid confusion. You do not really want to read arbitrary block, right? offset =3D F2FS_SUPER_OFFEST; if (secondary) offset +=3D F2FS_BLKSIZE; > + /* Read first super block. */ > + err =3D grub_disk_read (disk, offset >> GRUB_DISK_SECTOR_BITS, 0, > + sizeof (data->sblock), &data->sblock); > + if (err) > + return err; > + > + if (grub_f2fs_sanity_check_sb (&data->sblock)) > + err =3D GRUB_ERR_BAD_FS; > + > + return err; > +} > + > +static void * > +validate_checkpoint (struct grub_f2fs_data *data, grub_uint32_t cp_addr, > + grub_uint64_t *version) > +{ > + void *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 F2FS_BLKSIZE) > + goto invalid_cp1; > + > + crc =3D *(grub_uint32_t *)((char *)cp_block + crc_offset); Is unaligned access possible here? If yes, it probably should be grub_get_unaligned32. > + if (!grub_f2fs_crc_valid (crc, cp_block, crc_offset)) > + goto invalid_cp1; > + Should not CRC be converted from LE? > + 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 F2FS_BLKSIZE) > + goto invalid_cp2; > + > + crc =3D *(grub_uint32_t *)((char *)cp_block + crc_offset); Ditto alignment. > + if (!grub_f2fs_crc_valid (crc, cp_block, crc_offset)) Ditto endianness. > + 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\n"); > + > + grub_memcpy (&data->ckpt, cur_page, F2FS_BLKSIZE); > + > + grub_free (cp1); > + grub_free (cp2); > + return 0; > +} > + > +static int static grub_error_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)) As mentioned, use grub_cpu_to_leXX_compile_time to avoid run time conversion. > + 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_DATA= ); > + > + 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_SIZE); > + > +fail: > + grub_free (buf); > + return err; > +} > + ... > +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_flag_set (inode, FI_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]; That does not fit. You declared offset and noffset as arrays of four elements and pass arrays of four elements; here is out of bound access already. > + 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 > +load_nat_info (struct grub_f2fs_data *data) > +{ > + void *version_bitmap; > + grub_err_t err; > + > + data->nat_bitmap =3D grub_malloc (__nat_bitmap_size (data)); > + if (!data->nat_bitmap) > + return grub_errno; > + > + version_bitmap =3D __nat_bitmap_ptr (data); > + > + /* copy version bitmap */ > + grub_memcpy (data->nat_bitmap, version_bitmap, __nat_bitmap_size (data= )); > + Any reason to actually copy it? Why is it not possible to just set pointer to source, which is available all the time anyway? > + err =3D get_nat_journal (data); > + if (err) > + grub_free (data->nat_bitmap); > + > + return err; > +} > + > +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); Is struct grub_f2fs_node guaranteed to always have the same size as F2FS block? Then adding char [F2FS_BLKSIZE] to union to make it obvious is better and ensures that it will always be at least this size. > +} > + > +static struct grub_f2fs_data * > +grub_f2fs_mount (grub_disk_t disk) > +{ > + struct grub_f2fs_data *data; > + grub_err_t err; > + > + data =3D grub_zalloc (sizeof (*data)); > + if (!data) > + return NULL; > + > + data->disk =3D disk; > + > + err =3D grub_f2fs_read_sb (data, 0); > + if (err) > + { > + err =3D grub_f2fs_read_sb (data, 1); > + if (err) > + { > + grub_error (GRUB_ERR_BAD_FS, "not a F2FS filesystem"); May be mentioning that superblock could not be read? In another place you already tell that checkpoints could not be found. It helps to troubleshoot issues. > + 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; > + > + err =3D load_nat_info (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: > + if (data) > + grub_free (data->nat_bitmap); Double free after load_nat_info failure. Assuming that we do need to allocate anything at all (see above). > + grub_free (data); > + return NULL; > +} > + > +/* guarantee inline_data was handled by caller */ > +static grub_disk_addr_t > +grub_f2fs_read_block (grub_fshelp_node_t node, grub_disk_addr_t block_of= s) You have grub_f2fs_read_block and grub_f2fs_block_read. Could we make them more different and self-explaining? In particular, this one does not read anything, it returns disk address. grub_f2fs_map_file_block? > +{ > + 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]; See above about overflow in grub_get_inode_path. > + 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 char * > +grub_f2fs_read_symlink (grub_fshelp_node_t node) > +{ > + char *symlink; > + struct grub_fshelp_node *diro =3D node; > + > + if (!diro->inode_read) > + { > + grub_f2fs_read_node (diro->data, diro->ino, &diro->inode); > + if (grub_errno) > + return 0; > + } > + > + symlink =3D grub_malloc (__i_size (&diro->inode.i) + 1); > + if (!symlink) > + return 0; > + > + grub_f2fs_read_file (diro, 0, 0, 0, __i_size (&diro->inode.i), symlink= ); > + if (grub_errno) > + { > + grub_free (symlink); > + return 0; > + } > + What about short read? Is this an error or not? > + symlink[__i_size (&diro->inode.i)] =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[F2FS_NAME_LEN + 1]; Could we avoid large stack allocations? > + enum grub_fshelp_filetype type =3D GRUB_FSHELP_UNKNOWN; > + enum FILE_TYPE ftype; > + int name_len; > + > + if (__test_bit (i, ctx->bitmap) =3D=3D 0) grub_f2fs_test_bit_le32? > + { > + i++; > + continue; > + } > + > + ftype =3D ctx->dentry[i].file_type; > + name_len =3D grub_le_to_cpu16 (ctx->dentry[i].name_len); > + grub_memcpy (filename, ctx->filename[i], name_len); > + filename[name_len] =3D '\0'; > + > + fdiro =3D grub_malloc (sizeof (struct grub_fshelp_node)); > + if (!fdiro) > + 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; > + > + if (ctx->hook (filename, type, fdiro, ctx->hook_data)) > + return 1; > + > + i +=3D (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN; > + } > + return 0; > +} > + ... > + > +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_flag_set (inode, FI_INLINE_DENTRY)) > + return grub_f2fs_iterate_inline_dir (inode, &ctx); > + > + while (fpos < __i_size (inode)) > + { > + struct grub_f2fs_dentry_block *de_blk; > + char *buf; > + > + 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 (grub_uint32_t *) de_blk->dentry_bitmap; > + ctx.dentry =3D de_blk->dentry; > + ctx.filename =3D de_blk->filename; > + ctx.max =3D NR_DENTRY_IN_BLOCK; > + > + if (grub_f2fs_check_dentries (&ctx)) > + return 1; memory leak > + > + grub_free (buf); > + > + fpos +=3D F2FS_BLKSIZE; > + } > + return 0; > +} > + ... > +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); > + if (ctx.data) > + grub_free (ctx.data->nat_bitmap); Triple free :) > + 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; > + > + 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, F2FS_BLKSIZE); sizeof (*data->inode)? Or they can be different? > + grub_free (fdiro); > + > + file->size =3D __i_size (&(data->inode->i)); > + file->data =3D data; > + file->offset =3D 0; > + > + return 0; > + > +fail: > + if (fdiro !=3D &data->diropen) > + grub_free (fdiro); > + if (data) > + grub_free (data->nat_bitmap); Again. > + 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; > + > + if (data) > + grub_free (data->nat_bitmap); Again. > + grub_free (data); > + > + grub_dl_unref (my_mod); > + > + return GRUB_ERR_NONE; > +} > + > +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 grub_zalloc (sizeof (data->sblock.volume_name)); > + grub_utf16_to_utf8 ((grub_uint8_t *) (*label), malloc failure check? > + data->sblock.volume_name, 512); Where 512 comes from? Should it not be sizeof (data->sblock.volume_name) as well? > + } > + else > + *label =3D NULL; > + > + if (data) > + grub_free (data->nat_bitmap); Again. > + grub_free (data); > + grub_dl_unref (my_mod); > + return grub_errno; > +} > + ... > diff --git a/tests/util/grub-fs-tester.in b/tests/util/grub-fs-tester.in > index e9e85c2..acc35cc 100644 > --- a/tests/util/grub-fs-tester.in > +++ b/tests/util/grub-fs-tester.in > @@ -36,7 +36,7 @@ case x"$fs" in > MINLOGSECSIZE=3D8 > # OS LIMITATION: It could go up to 32768 but Linux rejects sector = sizes > 4096 > MAXLOGSECSIZE=3D12;; > - xxfs) > + xxfs|xf2fs) > MINLOGSECSIZE=3D9 > # OS LIMITATION: GNU/Linux doesn't accept > 4096 > MAXLOGSECSIZE=3D12;; > @@ -135,6 +135,10 @@ for ((LOGSECSIZE=3DMINLOGSECSIZE;LOGSECSIZE<=3DMAXLO= GSECSIZE;LOGSECSIZE=3DLOGSECSIZE + > fi > MAXBLKSIZE=3D4096 > ;; > + xf2fs) > + MINBLKSIZE=3D$SECSIZE > + # OS Limitation: GNU/Linux doesn't accept > 4096 > + MAXBLKSIZE=3D4096;; > xsquash*) > MINBLKSIZE=3D4096 > MAXBLKSIZE=3D1048576;; > @@ -256,7 +260,9 @@ for ((LOGSECSIZE=3DMINLOGSECSIZE;LOGSECSIZE<=3DMAXLOG= SECSIZE;LOGSECSIZE=3DLOGSECSIZE + > # FS LIMITATION: btrfs label is at most 255 UTF-8 chars > 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 urewfceniuewruevrewnuuireurevueurnievrewfne= rfcnevirivinrewvnirewnivrewiuvcrewvnuewvrrrewniuerwreiuviurewiuviurewnuvewn= vrenurnunuvrevuurerejiremvreijnvcreivire nverivnreivrevnureiorfnfrvoeoiroir= eoireoifrefoieroifoireoif";; > - > + # FS LIMITATION: btrfs label is at most 512 UTF-16 chars F2FS, not btrfs > + x"f2fs") > + FSLABEL=3D"grub_;/testjaegeuk kim=20 Could you leave initial part in place? This includes some funny UNICODE characters for a reason, actually. Unless this is not possible with f2fs? f2fsaskdfjkasdlfajskdfjaksdjfkjaskjkjkzjkjckzjvkcjkjkjekqjkwejkqwrlkasdfjks= adjflaskdhzxhvjzxchvjzkxchvjkhakjsdhfjkhqjkwehrjkhasjkdfhjkashdfjkhjzkxhcjk= vzhxcjkvhzxjchvkzhxckjvhjzkxchvjkhzjkxchvjkzhxckjvhzkxjchvkjzxhckjvzxcjkvhj= zxkchkvjhzxkjcvhjkhjkahsjkdhkjqhwekrjhakjsdfhkjashdkjzhxcvjkhzxcvzxcvgggggg= ggggf";; > # 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";; > @@ -466,7 +472,7 @@ for ((LOGSECSIZE=3DMINLOGSECSIZE;LOGSECSIZE<=3DMAXLOG= SECSIZE;LOGSECSIZE=3DLOGSECSIZE + > # FIXME: Not sure about BtrFS, NTFS, JFS, AFS, UDF and SFS. Check i= t. > # FS LIMITATION: as far as I know those FS don't store their last modif= ication date. > x"jfs_caseins" | x"jfs" | x"xfs"| x"btrfs"* | x"reiserfs_old" | x"reis= erfs" \ > - | 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;; > @@ -745,6 +751,8 @@ for ((LOGSECSIZE=3DMINLOGSECSIZE;LOGSECSIZE<=3DMAXLOG= SECSIZE;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) From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrei Borzenkov Subject: Re: [PATCH] F2FS support Date: Sat, 28 Mar 2015 10:31:55 +0300 Message-ID: <20150328103155.5c961fec@opensuse.site> References: <1427185140-41120-1-git-send-email-jaegeuk@kernel.org> Reply-To: The development of GNU GRUB Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <1427185140-41120-1-git-send-email-jaegeuk@kernel.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: grub-devel-bounces+gcbgd-grub-devel=m.gmane.org@gnu.org Sender: grub-devel-bounces+gcbgd-grub-devel=m.gmane.org@gnu.org To: Jaegeuk Kim Cc: grub-devel@gnu.org, linux-f2fs-devel@lists.sourceforge.net List-Id: linux-f2fs-devel.lists.sourceforge.net 0JIgVHVlLCAyNCBNYXIgMjAxNSAwMToxOTowMCAtMDcwMApKYWVnZXVrIEtpbSA8amFlZ2V1a0Br ZXJuZWwub3JnPiDQv9C40YjQtdGCOgoKPiAgKiBNYWtlZmlsZS51dGlsLmRlZjogQWRkIGYyZnMu Yy4KPiAgKiBkb2MvZ3J1Yi50ZXhpOiBBZGQgZjJmcyBkZXNjcmlwdGlvbi4KPiAgKiBncnViLWNv cmUvTWFrZWZpbGUuY29yZS5kZWY6IEFkZCBmMmZzIG1vZHVsZS4KPiAgKiBncnViLWNvcmUvZnMv ZjJmcy5jOiBOZXcgZmlsZS4KPiAgKiB0ZXN0cy9mMmZzX3Rlc3QuaW46IE5ldyBmaWxlLgo+ICAq IHRlc3RzL3V0aWwvZ3J1Yi1mcy10ZXN0ZXIuaW46IEFkZCBmMmZzIHJlcXVpcmVtZW50cy4KPiAK Ckl0J3Mgbm90IHRoZSBtb3N0IHVzZWZ1bCBjb21taXQgbWVzc2FnZS4gQmV0dGVyIHdvdWxkIGJl IHNob3J0CmV4cGxhbmF0aW9uIG9mIHVzZSBjYXNlcyBhbmQgaW50ZW5kZWQgcGxhdGZvcm1zLiBJ J20gY3VyaW91cyBoZXJlIC0KRjJGUyBpcyBpbnRlbmRlZCBmb3IgcmF3IGZsYXNoIGFjY2Vzcywg b24gd2hpY2ggcGxhdGZvcm0ocykgZ3J1YiBoYXMKYWNjZXNzIHRvIHN1Y2ggZGV2aWNlcz8gCgo+ IAo+IGRpZmYgLS1naXQgYS9DaGFuZ2VMb2ctMjAxNSBiL0NoYW5nZUxvZy0yMDE1CgpXZSBkbyBu b3QgdXNlIENoYW5nZUxvZyBhbnkgbW9yZSwgaXQgaXMgYXV0b2dlbmVyYXRlZCBmcm9tIGNvbW1p dHMuClRoaXMgZmlsZSBpcyBsZWdhY3kgYmVmb3JlIHRoaXMgY2hhbmdlLCBkbyBub3QgY2hhbmdl IGl0LgoKPiBkaWZmIC0tZ2l0IGEvZ3J1Yi1jb3JlL2ZzL2YyZnMuYyBiL2dydWItY29yZS9mcy9m MmZzLmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLjQwMzYwZDUKPiAt LS0gL2Rldi9udWxsCj4gKysrIGIvZ3J1Yi1jb3JlL2ZzL2YyZnMuYwo+IEBAIC0wLDAgKzEsMTMy MSBAQAo+ICsvKgo+ICsgKiAgZjJmcy5jIC0gRmxhc2gtRnJpZW5kbHkgRmlsZSBTeXN0ZW0KPiAr ICoKPiArICogIFdyaXR0ZW4gYnkgSmFlZ2V1ayBLaW0gPGphZWdldWtAa2VybmVsLm9yZz4KPiAr ICoKPiArICogIENvcHlyaWdodCAoQykgMjAxNSAgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBJ bmMuCj4gKyAqCj4gKyAqICBHUlVCIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmli dXRlIGl0IGFuZC9vciBtb2RpZnkKPiArICogIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05V IEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5Cj4gKyAqICB0aGUgRnJlZSBT b2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvcgo+ ICsgKiAgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KPiArICoKPiArICogIEdS VUIgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKPiAr ICogIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdh cnJhbnR5IG9mCj4gKyAqICBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNV TEFSIFBVUlBPU0UuICBTZWUgdGhlCj4gKyAqICBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBm b3IgbW9yZSBkZXRhaWxzLgo+ICsgKgo+ICsgKiAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEg Y29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKPiArICogIGFsb25nIHdpdGgg R1JVQi4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi4KPiArICov Cj4gKyNpbmNsdWRlIDxncnViL2Vyci5oPgo+ICsjaW5jbHVkZSA8Z3J1Yi9maWxlLmg+Cj4gKyNp bmNsdWRlIDxncnViL21tLmg+Cj4gKyNpbmNsdWRlIDxncnViL21pc2MuaD4KPiArI2luY2x1ZGUg PGdydWIvZGlzay5oPgo+ICsjaW5jbHVkZSA8Z3J1Yi9kbC5oPgo+ICsjaW5jbHVkZSA8Z3J1Yi90 eXBlcy5oPgo+ICsjaW5jbHVkZSA8Z3J1Yi9jaGFyc2V0Lmg+Cj4gKyNpbmNsdWRlIDxncnViL2Zz aGVscC5oPgo+ICsKPiArR1JVQl9NT0RfTElDRU5TRSAoIkdQTHYzKyIpOwo+ICsKPiArLyogRjJG UyBNYWdpYyBOdW1iZXIgKi8KPiArI2RlZmluZSBGMkZTX1NVUEVSX01BR0lDCTB4RjJGNTIwMTAK PiArCj4gKy8qIGJ5dGUtc2l6ZSBvZmZzZXQgKi8KPiArI2RlZmluZSBGMkZTX1NVUEVSX09GRlNF VAkJMTAyNAo+ICsKPiArLyogMTIgYml0cyBmb3IgNDA5NiBieXRlcyAqLwo+ICsjZGVmaW5lIEYy RlNfTUFYX0xPR19TRUNUT1JfU0laRQkxMgo+ICsKPiArLyogOSBiaXRzIGZvciA1MTIgYnl0ZXMg Ki8KPiArI2RlZmluZSBGMkZTX01JTl9MT0dfU0VDVE9SX1NJWkUJOQo+ICsKPiArLyogc3VwcG9y dCBvbmx5IDRLQiBibG9jayAqLwo+ICsjZGVmaW5lIEYyRlNfQkxLU0laRQkJCTQwOTYKCigyIDw8 IEYyRlNfQkxLX0JJVFMpPwoKPiArI2RlZmluZSBGMkZTX0JMS19CSVRTCQkJMTIKPiArI2RlZmlu ZSBGMkZTX0JMS19TRUNfQklUUwkJKDMpCgoKSXQgaXMgY29uZnVzaW5nIHRvIGhhdmUgc29tZSBk ZWZpbmVzIHBhcmVudGhlc2l6ZWQgYW5kIHNvbWUgbm90LiBDb3VsZAppdCBiZSB1bmlmaWVkIHNv bWVob3c/CgpBbHNvIHRoaXMgY2FuIGJlIGNvbXB1dGVkIGZyb20gRjJGU19CTEtfQklUUyBhbmQg R1JVQl9ESVNLX1NFQ1RPUl9CSVRTCi0gb25lIG1hZ2ljIG51bWJlciBsZXNzLgoKLi4uCj4gK3N0 cnVjdCBncnViX2YyZnNfaW5saW5lX2RlbnRyeQo+ICt7Cj4gKyAgZ3J1Yl91aW50OF90IGRlbnRy eV9iaXRtYXBbSU5MSU5FX0RFTlRSWV9CSVRNQVBfU0laRV07CgpUaGlzIGlzIGNhc3QgdG8gZ3J1 Yl91aW50MzJfdCBldmVyeXdoZXJlLiBDYW4gaXQgYmUgbm9uLW11bHRpcGxlIG9mIDQKYnl0ZXM/ IElmIG5vdCwgbWF5IGJlIGp1c3QgZGVmaW5lIGFzIHN1Y2g/IAoKPiArICBncnViX3VpbnQ4X3Qg cmVzZXJ2ZWRbSU5MSU5FX1JFU0VSVkVEX1NJWkVdOwo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGly X2VudHJ5IGRlbnRyeVtOUl9JTkxJTkVfREVOVFJZXTsKPiArICBncnViX3VpbnQ4X3QgZmlsZW5h bWVbTlJfSU5MSU5FX0RFTlRSWV1bRjJGU19TTE9UX0xFTl07Cj4gK30gR1JVQl9QQUNLRUQ7Cj4g Kwo+ICtzdHJ1Y3QgZ3J1Yl9mMmZzX2RlbnRyeV9ibG9jayB7Cj4gKyAgZ3J1Yl91aW50OF90IGRl bnRyeV9iaXRtYXBbU0laRV9PRl9ERU5UUllfQklUTUFQXTsKCmRpdHRvCgo+ICsgIGdydWJfdWlu dDhfdCByZXNlcnZlZFtTSVpFX09GX1JFU0VSVkVEXTsKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2Rp cl9lbnRyeSBkZW50cnlbTlJfREVOVFJZX0lOX0JMT0NLXTsKPiArICBncnViX3VpbnQ4X3QgZmls ZW5hbWVbTlJfREVOVFJZX0lOX0JMT0NLXVtGMkZTX1NMT1RfTEVOXTsKPiArfSBHUlVCX1BBQ0tF RDsKPiArCgoKLi4uCj4gKwo+ICsjZGVmaW5lIHZlcl9hZnRlciAoYSwgYikgKHR5cGVjaGVjayAo dW5zaWduZWQgbG9uZyBsb25nLCBhKSAmJiAgICAgICAgICBcCj4gKwkJdHlwZWNoZWNrICh1bnNp Z25lZCBsb25nIGxvbmcsIGIpICYmICAgICAgICAgICAgICAgICAgICBcCj4gKwkJKChsb25nIGxv bmcpKChhKSAtIChiKSkgPiAwKSkKPiArCgpXaGVyZSB0eXBlY2hlY2sgZGVmaW5pdGlvbiBjb21l cyBmcm9tPwoKLi4uCj4gKwo+ICtzdGF0aWMgaW5saW5lIGludAo+ICtfX3Rlc3RfYml0IChpbnQg bnIsIGdydWJfdWludDMyX3QgKmFkZHIpCj4gK3sKPiArICByZXR1cm4gMVVMICYgKGFkZHJbbnIg LyAzMl0gPj4gKG5yICYgKDMxKSkpOwpFeHRyYSBwYXJlbnRoZXNpcyAoMzEpCgo+ICt9Cj4gKwoK SXQgaXMgdXNlZCBmb3IgZGVudHJ5X2JpdG1hcCB3aGljaCBpcyBrZXB0IGluIExFIGZvcm1hdCBh bmQgbm90CmNvbnZlcnRlZCBhcyBmYXIgYXMgSSBjYW4gdGVsbC4gVGhpcyBuZWVkcyBmaXhpbmcg Zm9yIEJFIHN5c3RlbXMuIExpbnV4Cmtlcm5lbCBpcyBleHBsaWNpdGx5IHVzaW5nIHRlc3RfYml0 X2xlIGhlcmUuIFRoaXMgd2lsbCBhbHNvIHdvcmsgZm9yCmlub2RlIGZsYWdzIChqdXN0IHNraXAg ZXhwbGljaXQgY29udmVyc2lvbikuCgpUaGVyZSBhcmUgdHdvIGZ1bmN0aW9ucyB3aXRoIG1vcmUg b3IgbGVzcyBpZGVudGljYWwgbmFtZXMuIE1heSBiZSBtYWtlCnRoZW0KCmdydWJfZjJmc190ZXN0 X2JpdF9sZTMyCmdydWJfZjJmc190ZXN0X2JpdAoKQXMgYSBnZW5lcmFsIGNvbW1lbnQgLSBtYXJr aW5nIG5vbi1tb2RpZmllZCBhcmd1bWVudHMgYXMgY29uc3QKZXZlcnl3aGVyZSB3b3VsZCBiZSBn b29kLgoKPiArc3RhdGljIGlubGluZSBjaGFyICoKPiArX19pbmxpbmVfYWRkciAoc3RydWN0IGdy dWJfZjJmc19pbm9kZSAqaW5vZGUpCj4gK3sKPiArICByZXR1cm4gKGNoYXIgKikmKGlub2RlLT5p X2FkZHJbMV0pOwpSZWR1bmRhbnQgcGFyZW5zIGFyb3VuZCBpbm9kZS0+Cgo+ICt9Cj4gKwo+ICtz dGF0aWMgaW5saW5lIGdydWJfdWludDY0X3QKPiArX19pX3NpemUgKHN0cnVjdCBncnViX2YyZnNf aW5vZGUgKmlub2RlKQoKQ291bGQgd2UgbWFrZSBpdCBncnViX2YyZnNfZmlsZV9zaXplIG9yIHNp bWlsYXI/IGlfc2l6ZSByZWFsbHkgZG9lcyBub3QKdGVsbCBtdWNoIG91dHNpZGUgb2YgbGludXgg a2VybmVsLgoKPiArewo+ICsgIHJldHVybiBncnViX2xlX3RvX2NwdTY0IChpbm9kZS0+aV9zaXpl KTsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBncnViX3VpbnQzMl90Cj4gK19fc3RhcnRfY3Bf YWRkciAoc3RydWN0IGdydWJfZjJmc19kYXRhICpkYXRhKQo+ICt7Cj4gKyAgc3RydWN0IGdydWJf ZjJmc19jaGVja3BvaW50ICpja3B0ID0gJmRhdGEtPmNrcHQ7Cj4gKyAgZ3J1Yl91aW50NjRfdCBj a3B0X3ZlcnNpb24gPSBncnViX2xlX3RvX2NwdTY0IChja3B0LT5jaGVja3BvaW50X3Zlcik7Cj4g KyAgZ3J1Yl91aW50MzJfdCBzdGFydF9hZGRyID0gZGF0YS0+Y3BfYmxrYWRkcjsKPiArCj4gKyAg aWYgKCEoY2twdF92ZXJzaW9uICYgMSkpCj4gKyAgICByZXR1cm4gc3RhcnRfYWRkciArIGRhdGEt PmJsb2Nrc19wZXJfc2VnOwo+ICsgIHJldHVybiBzdGFydF9hZGRyOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgaW5saW5lIGdydWJfdWludDMyX3QKPiArX19zdGFydF9zdW1fYmxvY2sgKHN0cnVjdCBncnVi X2YyZnNfZGF0YSAqZGF0YSkKPiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfY2hlY2twb2ludCAq Y2twdCA9ICZkYXRhLT5ja3B0Owo+ICsKPiArICByZXR1cm4gX19zdGFydF9jcF9hZGRyIChkYXRh KSArIGdydWJfbGVfdG9fY3B1MzIgKGNrcHQtPmNwX3BhY2tfc3RhcnRfc3VtKTsKPiArfQo+ICsK PiArc3RhdGljIGlubGluZSBncnViX3VpbnQzMl90Cj4gK19fc3VtX2Jsa19hZGRyIChzdHJ1Y3Qg Z3J1Yl9mMmZzX2RhdGEgKmRhdGEsIGludCBiYXNlLCBpbnQgdHlwZSkKPiArewo+ICsgIHN0cnVj dCBncnViX2YyZnNfY2hlY2twb2ludCAqY2twdCA9ICZkYXRhLT5ja3B0Owo+ICsKPiArICByZXR1 cm4gX19zdGFydF9jcF9hZGRyIChkYXRhKSArCj4gKwkJZ3J1Yl9sZV90b19jcHUzMiAoY2twdC0+ Y3BfcGFja190b3RhbF9ibG9ja19jb3VudCkKPiArCQktIChiYXNlICsgMSkgKyB0eXBlOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGludAo+ICtfX2NrcHRfZmxhZ19zZXQgKHN0cnVjdCBncnVi X2YyZnNfY2hlY2twb2ludCAqY2twdCwgdW5zaWduZWQgaW50IGYpCj4gK3sKPiArICBncnViX3Vp bnQzMl90IGNrcHRfZmxhZ3MgPSBncnViX2xlX3RvX2NwdTMyIChja3B0LT5ja3B0X2ZsYWdzKTsK PiArICByZXR1cm4gY2twdF9mbGFncyAmIGY7CgpBbGwgZmxhZ3MgYXJlIGNvbnN0YW50IHNvIHlv dSBjYW4gc2ltcGx5IGRvIAoKY2twdC0+Y2twdF9mbGFncyAmIGdydWJfY3B1X3RvX2xlMzJfY29t cGlsZV90aW1lIChGTEFHKQoKaW4gcGxhY2UgdG8gYXZvaWQgZXh0cmEgY2FsbHMuIFRoaXMgbWFr ZXMgZnVuY3Rpb24gcmVkdW5kYW50LgoKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBpbnQKPiAr X19pbm9kZV9mbGFnX3NldCAoc3RydWN0IGdydWJfZjJmc19pbm9kZSAqaW5vZGUsIGludCBmbGFn KQo+ICt7Cj4gKyAgZ3J1Yl91aW50MzJfdCBpX2ZsYWdzID0gZ3J1Yl9sZV90b19jcHUzMiAoaW5v ZGUtPmlfZmxhZ3MpOwo+ICsgIHJldHVybiBfX3Rlc3RfYml0IChmbGFnLCAmaV9mbGFncyk7Cj4g K30KCmdydWJfZjJmc190ZXN0X2JpdF9sZTMyPwoKPiArCj4gKy8qCj4gKyAqIENSQzMyCj4gKyAq Lwo+ICsjZGVmaW5lIENSQ1BPTFlfTEUgMHhlZGI4ODMyMAo+ICsKPiArc3RhdGljIGlubGluZSBn cnViX3VpbnQzMl90Cj4gK2dydWJfZjJmc19jYWxfY3JjMzIgKGdydWJfdWludDMyX3QgY3JjLCB2 b2lkICpidWYsIGludCBsZW4pCgpXaHkgY3JjIGlzIHBhcmFtZXRlciBoZXJlPyBUaGlzIGZ1bmN0 aW9uIGlzIHVzZWQgZXhhY3RseSBvbmNlIHdpdGgKZml4ZWQgdmFsdWUgZm9yIGluaXRpYWwgY3Jj LgoKPiArewo+ICsgIGludCBpOwo+ICsgIHVuc2lnbmVkIGNoYXIgKnAgPSAodW5zaWduZWQgY2hh ciAqKWJ1ZjsKPiArCj4gKyAgd2hpbGUgKGxlbi0tKQo+ICsgICAgewo+ICsgICAgICBjcmMgXj0g KnArKzsKPiArICAgICAgZm9yIChpID0gMDsgaSA8IDg7IGkrKykKPiArICAgICAgICBjcmMgPSAo Y3JjID4+IDEpIF4gKChjcmMgJiAxKSA/IENSQ1BPTFlfTEUgOiAwKTsKPiArICAgIH0KPiArICBy ZXR1cm4gY3JjOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGludAo+ICtncnViX2YyZnNfY3Jj X3ZhbGlkIChncnViX3VpbnQzMl90IGJsa19jcmMsIHZvaWQgKmJ1ZiwgaW50IGxlbikKPiArewo+ ICsgIGdydWJfdWludDMyX3QgY2FsX2NyYyA9IDA7Cj4gKwo+ICsgIGNhbF9jcmMgPSBncnViX2Yy ZnNfY2FsX2NyYzMyIChGMkZTX1NVUEVSX01BR0lDLCBidWYsIGxlbik7Cj4gKwo+ICsgIHJldHVy biAoY2FsX2NyYyA9PSBibGtfY3JjKSA/IDEgOiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5l IGludAo+ICtncnViX2YyZnNfdGVzdF9iaXQgKGdydWJfdWludDMyX3QgbnIsIGNvbnN0IGNoYXIg KnApCj4gK3sKPiArICBpbnQgbWFzazsKPiArICBjaGFyICphZGRyID0gKGNoYXIgKilwOwoKV2h5 IGNhc3Q/IFdlIGFyZSBub3QgZ29pbmcgdG8gbW9kaWZ5IGl0LCByaWdodD8KCj4gKwo+ICsgIGFk ZHIgKz0gKG5yID4+IDMpOwo+ICsgIG1hc2sgPSAxIDw8ICg3IC0gKG5yICYgMHgwNykpOwo+ICsg IHJldHVybiAobWFzayAmICphZGRyKSAhPSAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50Cj4gK2dy dWJfZjJmc19zYW5pdHlfY2hlY2tfc2IgKHN0cnVjdCBncnViX2YyZnNfc3VwZXJibG9jayAqc2Ip Cj4gK3sKPiArICB1bnNpZ25lZCBpbnQgYmxvY2tzaXplOwo+ICsKPiArICBpZiAoRjJGU19TVVBF Ul9NQUdJQyAhPSBncnViX2xlX3RvX2NwdTMyIChzYi0+bWFnaWMpKQoKc2ItPm1hZ2ljICE9IGdy dWJfY3B1X3RvX2xlMzJfY29tcGlsZV90aW1lIChGMkZTX1NVUEVSX01BR0lDKQoKPiArICAgIHJl dHVybiAtMTsKPiArCj4gKyAgYmxvY2tzaXplID0gMSA8PCBncnViX2xlX3RvX2NwdTMyIChzYi0+ bG9nX2Jsb2Nrc2l6ZSk7Cj4gKyAgaWYgKGJsb2Nrc2l6ZSAhPSBGMkZTX0JMS1NJWkUpCgpzYi0+ bG9nX2Jsa3NpemUgIT0gZ3J1Yl9jcHVfdG9fbGUzMl9jb21waWxlX3RpbWUgKEYyRlNfQkxLX0JJ VFMpCgo+ICsgICAgcmV0dXJuIC0xOwo+ICsKPiArICBpZiAoZ3J1Yl9sZV90b19jcHUzMiAoc2It PmxvZ19zZWN0b3JzaXplKSA+IEYyRlNfTUFYX0xPR19TRUNUT1JfU0laRSkKPiArICAgIHJldHVy biAtMTsKPiArCj4gKyAgaWYgKGdydWJfbGVfdG9fY3B1MzIgKHNiLT5sb2dfc2VjdG9yc2l6ZSkg PCBGMkZTX01JTl9MT0dfU0VDVE9SX1NJWkUpCj4gKyAgICByZXR1cm4gLTE7Cj4gKwo+ICsgIGlm IChncnViX2xlX3RvX2NwdTMyIChzYi0+bG9nX3NlY3RvcnNfcGVyX2Jsb2NrKSArCj4gKyAgICAg IGdydWJfbGVfdG9fY3B1MzIgKHNiLT5sb2dfc2VjdG9yc2l6ZSkgIT0gRjJGU19NQVhfTE9HX1NF Q1RPUl9TSVpFKQoKU2hvdWxkIG5vdCBpdCBiZSBGMkZTX0JMS1NJWkU/IEF0IGxlYXN0IGl0IHNv dW5kcyBsb2dpY2FsLiBBbHNvIHBsZWFzZQpjb252ZXJ0IGxvZ19zZWN0b3JzaXplIGp1c3Qgb25j ZS4KCj4gKyAgICByZXR1cm4gLTE7Cj4gKwo+ICsgIHJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgZ3J1Yl9lcnJfdAo+ICtncnViX2YyZnNfcmVhZF9zYiAoc3RydWN0IGdydWJfZjJmc19kYXRh ICpkYXRhLCBpbnQgYmxvY2spCj4gK3sKPiArICBncnViX2Rpc2tfdCBkaXNrID0gZGF0YS0+ZGlz azsKPiArICBncnViX3VpbnQ2NF90IG9mZnNldDsKPiArICBncnViX2Vycl90IGVycjsKPiArCj4g KyAgaWYgKGJsb2NrID09IDApCj4gKyAgICBvZmZzZXQgPSBGMkZTX1NVUEVSX09GRlNFVDsKPiAr ICBlbHNlCj4gKyAgICBvZmZzZXQgPSBGMkZTX0JMS1NJWkUgKyBGMkZTX1NVUEVSX09GRlNFVDsK PiArCgpQbGVhc2UgbmFtZSBpdCAic2Vjb25kYXJ5IiBvciBzaW1pbGFyIGluc3RlYWQgb2YgImJs b2NrIiB0byBhdm9pZApjb25mdXNpb24uIFlvdSBkbyBub3QgcmVhbGx5IHdhbnQgdG8gcmVhZCBh cmJpdHJhcnkgYmxvY2ssIHJpZ2h0PwoKb2Zmc2V0ID0gRjJGU19TVVBFUl9PRkZFU1Q7CmlmIChz ZWNvbmRhcnkpCiAgb2Zmc2V0ICs9IEYyRlNfQkxLU0laRTsKCj4gKyAgLyogUmVhZCBmaXJzdCBz dXBlciBibG9jay4gKi8KPiArICBlcnIgPSBncnViX2Rpc2tfcmVhZCAoZGlzaywgb2Zmc2V0ID4+ IEdSVUJfRElTS19TRUNUT1JfQklUUywgMCwKPiArCQkJc2l6ZW9mIChkYXRhLT5zYmxvY2spLCAm ZGF0YS0+c2Jsb2NrKTsKPiArICBpZiAoZXJyKQo+ICsgICAgcmV0dXJuIGVycjsKPiArCj4gKyAg aWYgKGdydWJfZjJmc19zYW5pdHlfY2hlY2tfc2IgKCZkYXRhLT5zYmxvY2spKQo+ICsgICAgZXJy ID0gR1JVQl9FUlJfQkFEX0ZTOwo+ICsKPiArICByZXR1cm4gZXJyOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgdm9pZCAqCj4gK3ZhbGlkYXRlX2NoZWNrcG9pbnQgKHN0cnVjdCBncnViX2YyZnNfZGF0YSAq ZGF0YSwgZ3J1Yl91aW50MzJfdCBjcF9hZGRyLAo+ICsJCQkJCQlncnViX3VpbnQ2NF90ICp2ZXJz aW9uKQo+ICt7Cj4gKyAgdm9pZCAqY3BfcGFnZV8xLCAqY3BfcGFnZV8yOwo+ICsgIHN0cnVjdCBn cnViX2YyZnNfY2hlY2twb2ludCAqY3BfYmxvY2s7Cj4gKyAgZ3J1Yl91aW50NjRfdCBjdXJfdmVy c2lvbiA9IDAsIHByZV92ZXJzaW9uID0gMDsKPiArICBncnViX3VpbnQzMl90IGNyYyA9IDA7Cj4g KyAgZ3J1Yl91aW50MzJfdCBjcmNfb2Zmc2V0Owo+ICsgIGdydWJfZXJyX3QgZXJyOwo+ICsKPiAr ICAvKiBSZWFkIHRoZSAxc3QgY3AgYmxvY2sgaW4gdGhpcyBDUCBwYWNrICovCj4gKyAgY3BfcGFn ZV8xID0gZ3J1Yl9tYWxsb2MgKEYyRlNfQkxLU0laRSk7Cj4gKyAgaWYgKCFjcF9wYWdlXzEpCj4g KyAgICByZXR1cm4gTlVMTDsKPiArCj4gKyAgZXJyID0gZ3J1Yl9mMmZzX2Jsb2NrX3JlYWQgKGRh dGEsIGNwX2FkZHIsIGNwX3BhZ2VfMSk7Cj4gKyAgaWYgKGVycikKPiArICAgIGdvdG8gaW52YWxp ZF9jcDE7Cj4gKwo+ICsgIGNwX2Jsb2NrID0gKHN0cnVjdCBncnViX2YyZnNfY2hlY2twb2ludCAq KWNwX3BhZ2VfMTsKPiArICBjcmNfb2Zmc2V0ID0gZ3J1Yl9sZV90b19jcHUzMiAoY3BfYmxvY2st PmNoZWNrc3VtX29mZnNldCk7Cj4gKyAgaWYgKGNyY19vZmZzZXQgPj0gRjJGU19CTEtTSVpFKQo+ ICsgICAgZ290byBpbnZhbGlkX2NwMTsKPiArCj4gKyAgY3JjID0gKihncnViX3VpbnQzMl90ICop KChjaGFyICopY3BfYmxvY2sgKyBjcmNfb2Zmc2V0KTsKCklzIHVuYWxpZ25lZCBhY2Nlc3MgcG9z c2libGUgaGVyZT8gSWYgeWVzLCBpdCBwcm9iYWJseSBzaG91bGQgYmUKZ3J1Yl9nZXRfdW5hbGln bmVkMzIuCgo+ICsgIGlmICghZ3J1Yl9mMmZzX2NyY192YWxpZCAoY3JjLCBjcF9ibG9jaywgY3Jj X29mZnNldCkpCj4gKyAgICBnb3RvIGludmFsaWRfY3AxOwo+ICsKClNob3VsZCBub3QgQ1JDIGJl IGNvbnZlcnRlZCBmcm9tIExFPwoKPiArICBwcmVfdmVyc2lvbiA9IGdydWJfbGVfdG9fY3B1NjQg KGNwX2Jsb2NrLT5jaGVja3BvaW50X3Zlcik7Cj4gKwo+ICsgIC8qIFJlYWQgdGhlIDJuZCBjcCBi bG9jayBpbiB0aGlzIENQIHBhY2sgKi8KPiArICBjcF9wYWdlXzIgPSBncnViX21hbGxvYyAoRjJG U19CTEtTSVpFKTsKPiArICBpZiAoIWNwX3BhZ2VfMikKPiArICAgIGdvdG8gaW52YWxpZF9jcDE7 Cj4gKwo+ICsgIGNwX2FkZHIgKz0gZ3J1Yl9sZV90b19jcHUzMiAoY3BfYmxvY2stPmNwX3BhY2tf dG90YWxfYmxvY2tfY291bnQpIC0gMTsKPiArCj4gKyAgZXJyID0gZ3J1Yl9mMmZzX2Jsb2NrX3Jl YWQgKGRhdGEsIGNwX2FkZHIsIGNwX3BhZ2VfMik7Cj4gKyAgaWYgKGVycikKPiArICAgIGdvdG8g aW52YWxpZF9jcDI7Cj4gKwo+ICsgIGNwX2Jsb2NrID0gKHN0cnVjdCBncnViX2YyZnNfY2hlY2tw b2ludCAqKWNwX3BhZ2VfMjsKPiArICBjcmNfb2Zmc2V0ID0gZ3J1Yl9sZV90b19jcHUzMiAoY3Bf YmxvY2stPmNoZWNrc3VtX29mZnNldCk7Cj4gKyAgaWYgKGNyY19vZmZzZXQgPj0gRjJGU19CTEtT SVpFKQo+ICsgICAgZ290byBpbnZhbGlkX2NwMjsKPiArCj4gKyAgY3JjID0gKihncnViX3VpbnQz Ml90ICopKChjaGFyICopY3BfYmxvY2sgKyBjcmNfb2Zmc2V0KTsKCkRpdHRvIGFsaWdubWVudC4K Cj4gKyAgaWYgKCFncnViX2YyZnNfY3JjX3ZhbGlkIChjcmMsIGNwX2Jsb2NrLCBjcmNfb2Zmc2V0 KSkKRGl0dG8gZW5kaWFubmVzcy4KCj4gKyAgICBnb3RvIGludmFsaWRfY3AyOwo+ICsKPiArICBj dXJfdmVyc2lvbiA9IGdydWJfbGVfdG9fY3B1NjQgKGNwX2Jsb2NrLT5jaGVja3BvaW50X3Zlcik7 Cj4gKyAgaWYgKGN1cl92ZXJzaW9uID09IHByZV92ZXJzaW9uKQo+ICsgICAgewo+ICsgICAgICAq dmVyc2lvbiA9IGN1cl92ZXJzaW9uOwo+ICsgICAgICBncnViX2ZyZWUgKGNwX3BhZ2VfMik7Cj4g KyAgICAgIHJldHVybiBjcF9wYWdlXzE7Cj4gKyAgICB9Cj4gKwo+ICtpbnZhbGlkX2NwMjoKPiAr ICBncnViX2ZyZWUgKGNwX3BhZ2VfMik7Cj4gK2ludmFsaWRfY3AxOgo+ICsgIGdydWJfZnJlZSAo Y3BfcGFnZV8xKTsKPiArICByZXR1cm4gTlVMTDsKPiArfQo+ICsKPiArc3RhdGljIGdydWJfZXJy X3QKPiArZ3J1Yl9mMmZzX3JlYWRfY3AgKHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0YSkKPiAr ewo+ICsgIHZvaWQgKmNwMSwgKmNwMiwgKmN1cl9wYWdlOwo+ICsgIGdydWJfdWludDY0X3QgY3Ax X3ZlcnNpb24gPSAwLCBjcDJfdmVyc2lvbiA9IDA7Cj4gKyAgZ3J1Yl91aW50NjRfdCBjcF9zdGFy dF9ibGtfbm87Cj4gKwo+ICsgIC8qCj4gKyAgICogRmluZGluZyBvdXQgdmFsaWQgY3AgYmxvY2sg aW52b2x2ZXMgcmVhZCBib3RoCj4gKyAgICogc2V0cyAoY3AgcGFjazEgYW5kIGNwIHBhY2sgMikK PiArICAgKi8KPiArICBjcF9zdGFydF9ibGtfbm8gPSBkYXRhLT5jcF9ibGthZGRyOwo+ICsgIGNw MSA9IHZhbGlkYXRlX2NoZWNrcG9pbnQgKGRhdGEsIGNwX3N0YXJ0X2Jsa19ubywgJmNwMV92ZXJz aW9uKTsKPiArICBpZiAoIWNwMSAmJiBncnViX2Vycm5vKQo+ICsgICAgICByZXR1cm4gZ3J1Yl9l cnJubzsKPiArCj4gKyAgLyogVGhlIHNlY29uZCBjaGVja3BvaW50IHBhY2sgc2hvdWxkIHN0YXJ0 IGF0IHRoZSBuZXh0IHNlZ21lbnQgKi8KPiArICBjcF9zdGFydF9ibGtfbm8gKz0gZGF0YS0+Ymxv Y2tzX3Blcl9zZWc7Cj4gKyAgY3AyID0gdmFsaWRhdGVfY2hlY2twb2ludCAoZGF0YSwgY3Bfc3Rh cnRfYmxrX25vLCAmY3AyX3ZlcnNpb24pOwo+ICsgIGlmICghY3AyICYmIGdydWJfZXJybm8pCj4g KyAgICB7Cj4gKyAgICAgIGdydWJfZnJlZSAoY3AxKTsKPiArICAgICAgcmV0dXJuIGdydWJfZXJy bm87Cj4gKyAgICB9Cj4gKwo+ICsgIGlmIChjcDEgJiYgY3AyKQo+ICsgICAgY3VyX3BhZ2UgPSAo Y3AyX3ZlcnNpb24gPiBjcDFfdmVyc2lvbikgPyBjcDIgOiBjcDE7Cj4gKyAgZWxzZSBpZiAoY3Ax KQo+ICsgICAgY3VyX3BhZ2UgPSBjcDE7Cj4gKyAgZWxzZSBpZiAoY3AyKQo+ICsgICAgY3VyX3Bh Z2UgPSBjcDI7Cj4gKyAgZWxzZQo+ICsgICAgcmV0dXJuIGdydWJfZXJyb3IgKEdSVUJfRVJSX0JB RF9GUywgIm5vIGNoZWNrcG9pbnRzXG4iKTsKPiArCj4gKyAgZ3J1Yl9tZW1jcHkgKCZkYXRhLT5j a3B0LCBjdXJfcGFnZSwgRjJGU19CTEtTSVpFKTsKPiArCj4gKyAgZ3J1Yl9mcmVlIChjcDEpOwo+ ICsgIGdydWJfZnJlZSAoY3AyKTsKPiArICByZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGlu dAoKc3RhdGljIGdydWJfZXJyb3JfdAoKPiArZ2V0X25hdF9qb3VybmFsIChzdHJ1Y3QgZ3J1Yl9m MmZzX2RhdGEgKmRhdGEpCj4gK3sKPiArICBncnViX3VpbnQzMl90IGJsb2NrOwo+ICsgIGNoYXIg KmJ1ZjsKPiArICBncnViX2Vycl90IGVycjsKPiArCj4gKyAgYnVmID0gZ3J1Yl9tYWxsb2MgKEYy RlNfQkxLU0laRSk7Cj4gKyAgaWYgKCFidWYpCj4gKyAgICByZXR1cm4gZ3J1Yl9lcnJubzsKPiAr Cj4gKyAgaWYgKF9fY2twdF9mbGFnX3NldCAoJmRhdGEtPmNrcHQsIENQX0NPTVBBQ1RfU1VNX0ZM QUcpKQo+ICsgICAgYmxvY2sgPSBfX3N0YXJ0X3N1bV9ibG9jayAoZGF0YSk7Cj4gKyAgZWxzZSBp ZiAoX19ja3B0X2ZsYWdfc2V0ICgmZGF0YS0+Y2twdCwgQ1BfVU1PVU5UX0ZMQUcpKQoKQXMgbWVu dGlvbmVkLCB1c2UgZ3J1Yl9jcHVfdG9fbGVYWF9jb21waWxlX3RpbWUgdG8gYXZvaWQgcnVuIHRp bWUKY29udmVyc2lvbi4KCj4gKyAgICBibG9jayA9IF9fc3VtX2Jsa19hZGRyIChkYXRhLCBOUl9D VVJTRUdfVFlQRSwgQ1VSU0VHX0hPVF9EQVRBKTsKPiArICBlbHNlCj4gKyAgICBibG9jayA9IF9f c3VtX2Jsa19hZGRyIChkYXRhLCBOUl9DVVJTRUdfREFUQV9UWVBFLCBDVVJTRUdfSE9UX0RBVEEp Owo+ICsKPiArICBlcnIgPSBncnViX2YyZnNfYmxvY2tfcmVhZCAoZGF0YSwgYmxvY2ssIGJ1Zik7 Cj4gKyAgaWYgKGVycikKPiArICAgIGdvdG8gZmFpbDsKPiArCj4gKyAgaWYgKF9fY2twdF9mbGFn X3NldCAoJmRhdGEtPmNrcHQsIENQX0NPTVBBQ1RfU1VNX0ZMQUcpKQo+ICsgICAgZ3J1Yl9tZW1j cHkgKCZkYXRhLT5uYXRfaiwgYnVmLCBTVU1fSk9VUk5BTF9TSVpFKTsKPiArICBlbHNlCj4gKyAg ICBncnViX21lbWNweSAoJmRhdGEtPm5hdF9qLCBidWYgKyBTVU1fRU5UUklFU19TSVpFLCBTVU1f Sk9VUk5BTF9TSVpFKTsKPiArCj4gK2ZhaWw6Cj4gKyAgZ3J1Yl9mcmVlIChidWYpOwo+ICsgIHJl dHVybiBlcnI7Cj4gK30KPiArCi4uLgo+ICtzdGF0aWMgaW50Cj4gK2dydWJfZ2V0X25vZGVfcGF0 aCAoc3RydWN0IGdydWJfZjJmc19pbm9kZSAqaW5vZGUsIGdydWJfdWludDMyX3QgYmxvY2ssCj4g KwkJCWdydWJfdWludDMyX3Qgb2Zmc2V0WzRdLCBncnViX3VpbnQzMl90IG5vZmZzZXRbNF0pCj4g K3sKPiArICBncnViX3VpbnQzMl90IGRpcmVjdF9ibGtzID0gQUREUlNfUEVSX0JMT0NLOwo+ICsg IGdydWJfdWludDMyX3QgZHB0cnNfcGVyX2JsayA9IE5JRFNfUEVSX0JMT0NLOwo+ICsgIGdydWJf dWludDMyX3QgaW5kaXJlY3RfYmxrcyA9IEFERFJTX1BFUl9CTE9DSyAqIE5JRFNfUEVSX0JMT0NL Owo+ICsgIGdydWJfdWludDMyX3QgZGluZGlyZWN0X2Jsa3MgPSBpbmRpcmVjdF9ibGtzICogTklE U19QRVJfQkxPQ0s7Cj4gKyAgZ3J1Yl91aW50MzJfdCBkaXJlY3RfaW5kZXggPSBERUZfQUREUlNf UEVSX0lOT0RFOwo+ICsgIGludCBuID0gMDsKPiArICBpbnQgbGV2ZWwgPSAwOwo+ICsKPiArICBp ZiAoX19pbm9kZV9mbGFnX3NldCAoaW5vZGUsIEZJX0lOTElORV9YQVRUUikpCj4gKyAgICBkaXJl Y3RfaW5kZXggLT0gRjJGU19JTkxJTkVfWEFUVFJfQUREUlM7Cj4gKwo+ICsgIG5vZmZzZXRbMF0g PSAwOwo+ICsKPiArICBpZiAoYmxvY2sgPCBkaXJlY3RfaW5kZXgpCj4gKyAgICB7Cj4gKyAgICAg IG9mZnNldFtuXSA9IGJsb2NrOwo+ICsgICAgICBnb3RvIGdvdDsKPiArICAgIH0KPiArCj4gKyAg YmxvY2sgLT0gZGlyZWN0X2luZGV4Owo+ICsgIGlmIChibG9jayA8IGRpcmVjdF9ibGtzKQo+ICsg ICAgewo+ICsgICAgICBvZmZzZXRbbisrXSA9IE5PREVfRElSMV9CTE9DSzsKPiArICAgICAgbm9m ZnNldFtuXSA9IDE7Cj4gKyAgICAgIG9mZnNldFtuXSA9IGJsb2NrOwo+ICsgICAgICBsZXZlbCA9 IDE7Cj4gKyAgICAgIGdvdG8gZ290Owo+ICsgICAgfQo+ICsKPiArICBibG9jayAtPSBkaXJlY3Rf YmxrczsKPiArICBpZiAoYmxvY2sgPCBkaXJlY3RfYmxrcykKPiArICAgIHsKPiArICAgICAgb2Zm c2V0W24rK10gPSBOT0RFX0RJUjJfQkxPQ0s7Cj4gKyAgICAgIG5vZmZzZXRbbl0gPSAyOwo+ICsg ICAgICBvZmZzZXRbbl0gPSBibG9jazsKPiArICAgICAgbGV2ZWwgPSAxOwo+ICsgICAgICBnb3Rv IGdvdDsKPiArICAgIH0KPiArCj4gKyAgYmxvY2sgLT0gZGlyZWN0X2Jsa3M7Cj4gKyAgaWYgKGJs b2NrIDwgaW5kaXJlY3RfYmxrcykKPiArICAgIHsKPiArICAgICAgb2Zmc2V0W24rK10gPSBOT0RF X0lORDFfQkxPQ0s7Cj4gKyAgICAgIG5vZmZzZXRbbl0gPSAzOwo+ICsgICAgICBvZmZzZXRbbisr XSA9IGJsb2NrIC8gZGlyZWN0X2Jsa3M7Cj4gKyAgICAgIG5vZmZzZXRbbl0gPSA0ICsgb2Zmc2V0 W24gLSAxXTsKClRoYXQgZG9lcyBub3QgZml0LiBZb3UgZGVjbGFyZWQgb2Zmc2V0IGFuZCBub2Zm c2V0IGFzIGFycmF5cyBvZiBmb3VyCmVsZW1lbnRzIGFuZCBwYXNzIGFycmF5cyBvZiBmb3VyIGVs ZW1lbnRzOyBoZXJlIGlzIG91dCBvZiBib3VuZAphY2Nlc3MgYWxyZWFkeS4KCj4gKyAgICAgIG9m ZnNldFtuXSA9IGJsb2NrICUgZGlyZWN0X2Jsa3M7Cj4gKyAgICAgIGxldmVsID0gMjsKPiArICAg ICAgZ290byBnb3Q7Cj4gKyAgICB9Cj4gKwo+ICsgIGJsb2NrIC09IGluZGlyZWN0X2Jsa3M7Cj4g KyAgaWYgKGJsb2NrIDwgaW5kaXJlY3RfYmxrcykKPiArICAgIHsKPiArICAgICAgb2Zmc2V0W24r K10gPSBOT0RFX0lORDJfQkxPQ0s7Cj4gKyAgICAgIG5vZmZzZXRbbl0gPSA0ICsgZHB0cnNfcGVy X2JsazsKPiArICAgICAgb2Zmc2V0W24rK10gPSBibG9jayAvIGRpcmVjdF9ibGtzOwo+ICsgICAg ICBub2Zmc2V0W25dID0gNSArIGRwdHJzX3Blcl9ibGsgKyBvZmZzZXRbbiAtIDFdOwo+ICsgICAg ICBvZmZzZXRbbl0gPSBibG9jayAlIGRpcmVjdF9ibGtzOwo+ICsgICAgICBsZXZlbCA9IDI7Cj4g KyAgICAgIGdvdG8gZ290Owo+ICsgICAgfQo+ICsKPiArICBibG9jayAtPSBpbmRpcmVjdF9ibGtz Owo+ICsgIGlmIChibG9jayA8IGRpbmRpcmVjdF9ibGtzKQo+ICsgICAgewo+ICsgICAgICBvZmZz ZXRbbisrXSA9IE5PREVfRElORF9CTE9DSzsKPiArICAgICAgbm9mZnNldFtuXSA9IDUgKyAoZHB0 cnNfcGVyX2JsayAqIDIpOwo+ICsgICAgICBvZmZzZXRbbisrXSA9IGJsb2NrIC8gaW5kaXJlY3Rf YmxrczsKPiArICAgICAgbm9mZnNldFtuXSA9IDYgKyAoZHB0cnNfcGVyX2JsayAqIDIpICsKPiAr CQlvZmZzZXRbbiAtIDFdICogKGRwdHJzX3Blcl9ibGsgKyAxKTsKPiArICAgICAgb2Zmc2V0W24r K10gPSAoYmxvY2sgLyBkaXJlY3RfYmxrcykgJSBkcHRyc19wZXJfYmxrOwo+ICsgICAgICBub2Zm c2V0W25dID0gNyArIChkcHRyc19wZXJfYmxrICogMikgKwo+ICsJCW9mZnNldFtuIC0gMl0gKiAo ZHB0cnNfcGVyX2JsayArIDEpICsKPiArCQlvZmZzZXRbbiAtIDFdOwo+ICsgICAgICBvZmZzZXRb bl0gPSBibG9jayAlIGRpcmVjdF9ibGtzOwo+ICsgICAgICBsZXZlbCA9IDM7Cj4gKyAgICAgIGdv dG8gZ290Owo+ICsgICAgfQo+ICtnb3Q6Cj4gKyAgcmV0dXJuIGxldmVsOwo+ICt9Cj4gKwo+ICsK PiArc3RhdGljIGdydWJfZXJyX3QKPiArbG9hZF9uYXRfaW5mbyAoc3RydWN0IGdydWJfZjJmc19k YXRhICpkYXRhKQo+ICt7Cj4gKyAgdm9pZCAqdmVyc2lvbl9iaXRtYXA7Cj4gKyAgZ3J1Yl9lcnJf dCBlcnI7Cj4gKwo+ICsgIGRhdGEtPm5hdF9iaXRtYXAgPSBncnViX21hbGxvYyAoX19uYXRfYml0 bWFwX3NpemUgKGRhdGEpKTsKPiArICBpZiAoIWRhdGEtPm5hdF9iaXRtYXApCj4gKyAgICByZXR1 cm4gZ3J1Yl9lcnJubzsKPiArCj4gKyAgdmVyc2lvbl9iaXRtYXAgPSBfX25hdF9iaXRtYXBfcHRy IChkYXRhKTsKPiArCj4gKyAgLyogY29weSB2ZXJzaW9uIGJpdG1hcCAqLwo+ICsgIGdydWJfbWVt Y3B5IChkYXRhLT5uYXRfYml0bWFwLCB2ZXJzaW9uX2JpdG1hcCwgX19uYXRfYml0bWFwX3NpemUg KGRhdGEpKTsKPiArCgpBbnkgcmVhc29uIHRvIGFjdHVhbGx5IGNvcHkgaXQ/IFdoeSBpcyBpdCBu b3QgcG9zc2libGUgdG8ganVzdCBzZXQKcG9pbnRlciB0byBzb3VyY2UsIHdoaWNoIGlzIGF2YWls YWJsZSBhbGwgdGhlIHRpbWUgYW55d2F5PwoKPiArICBlcnIgPSBnZXRfbmF0X2pvdXJuYWwgKGRh dGEpOwo+ICsgIGlmIChlcnIpCj4gKyAgICBncnViX2ZyZWUgKGRhdGEtPm5hdF9iaXRtYXApOwo+ ICsKPiArICByZXR1cm4gZXJyOwo+ICt9Cj4gKwo+ICtzdGF0aWMgZ3J1Yl9lcnJfdAo+ICtncnVi X2YyZnNfcmVhZF9ub2RlIChzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGEsCj4gKwkJCWdydWJf dWludDMyX3QgbmlkLCBzdHJ1Y3QgZ3J1Yl9mMmZzX25vZGUgKm5wKQo+ICt7Cj4gKyAgZ3J1Yl91 aW50MzJfdCBibGthZGRyOwo+ICsKPiArICBibGthZGRyID0gZ2V0X25vZGVfYmxrYWRkciAoZGF0 YSwgbmlkKTsKPiArICBpZiAoIWJsa2FkZHIpCj4gKyAgICByZXR1cm4gZ3J1Yl9lcnJubzsKPiAr Cj4gKyAgcmV0dXJuIGdydWJfZjJmc19ibG9ja19yZWFkIChkYXRhLCBibGthZGRyLCBucCk7CgpJ cyBzdHJ1Y3QgZ3J1Yl9mMmZzX25vZGUgZ3VhcmFudGVlZCB0byBhbHdheXMgaGF2ZSB0aGUgc2Ft ZSBzaXplIGFzIEYyRlMKYmxvY2s/IFRoZW4gYWRkaW5nIGNoYXIgW0YyRlNfQkxLU0laRV0gdG8g dW5pb24gdG8gbWFrZSBpdCBvYnZpb3VzIGlzCmJldHRlciBhbmQgZW5zdXJlcyB0aGF0IGl0IHdp bGwgYWx3YXlzIGJlIGF0IGxlYXN0IHRoaXMgc2l6ZS4KCj4gK30KPiArCj4gK3N0YXRpYyBzdHJ1 Y3QgZ3J1Yl9mMmZzX2RhdGEgKgo+ICtncnViX2YyZnNfbW91bnQgKGdydWJfZGlza190IGRpc2sp Cj4gK3sKPiArICBzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKmRhdGE7Cj4gKyAgZ3J1Yl9lcnJfdCBl cnI7Cj4gKwo+ICsgIGRhdGEgPSBncnViX3phbGxvYyAoc2l6ZW9mICgqZGF0YSkpOwo+ICsgIGlm ICghZGF0YSkKPiArICAgIHJldHVybiBOVUxMOwo+ICsKPiArICBkYXRhLT5kaXNrID0gZGlzazsK PiArCj4gKyAgZXJyID0gZ3J1Yl9mMmZzX3JlYWRfc2IgKGRhdGEsIDApOwo+ICsgIGlmIChlcnIp Cj4gKyAgICB7Cj4gKyAgICAgIGVyciA9IGdydWJfZjJmc19yZWFkX3NiIChkYXRhLCAxKTsKPiAr ICAgICAgaWYgKGVycikKPiArICAgICAgICB7Cj4gKyAgICAgICAgICBncnViX2Vycm9yIChHUlVC X0VSUl9CQURfRlMsICJub3QgYSBGMkZTIGZpbGVzeXN0ZW0iKTsKCk1heSBiZSBtZW50aW9uaW5n IHRoYXQgc3VwZXJibG9jayBjb3VsZCBub3QgYmUgcmVhZD8gSW4gYW5vdGhlciBwbGFjZQp5b3Ug YWxyZWFkeSB0ZWxsIHRoYXQgY2hlY2twb2ludHMgY291bGQgbm90IGJlIGZvdW5kLiBJdCBoZWxw cyB0bwp0cm91Ymxlc2hvb3QgaXNzdWVzLgoKPiArICAgICAgICAgIGdvdG8gZmFpbDsKPiArCX0K PiArICAgIH0KPiArCj4gKyAgZGF0YS0+cm9vdF9pbm8gPSBncnViX2xlX3RvX2NwdTMyIChkYXRh LT5zYmxvY2sucm9vdF9pbm8pOwo+ICsgIGRhdGEtPmNwX2Jsa2FkZHIgPSBncnViX2xlX3RvX2Nw dTMyIChkYXRhLT5zYmxvY2suY3BfYmxrYWRkcik7Cj4gKyAgZGF0YS0+bmF0X2Jsa2FkZHIgPSBn cnViX2xlX3RvX2NwdTMyIChkYXRhLT5zYmxvY2submF0X2Jsa2FkZHIpOwo+ICsgIGRhdGEtPmJs b2Nrc19wZXJfc2VnID0gMSA8PAo+ICsJCWdydWJfbGVfdG9fY3B1MzIgKGRhdGEtPnNibG9jay5s b2dfYmxvY2tzX3Blcl9zZWcpOwo+ICsKPiArICBlcnIgPSBncnViX2YyZnNfcmVhZF9jcCAoZGF0 YSk7Cj4gKyAgaWYgKGVycikKPiArICAgIGdvdG8gZmFpbDsKPiArCj4gKyAgZXJyID0gbG9hZF9u YXRfaW5mbyAoZGF0YSk7Cj4gKyAgaWYgKGVycikKPiArICAgIGdvdG8gZmFpbDsKPiArCj4gKyAg ZGF0YS0+ZGlyb3Blbi5kYXRhID0gZGF0YTsKPiArICBkYXRhLT5kaXJvcGVuLmlubyA9IGRhdGEt PnJvb3RfaW5vOwo+ICsgIGRhdGEtPmRpcm9wZW4uaW5vZGVfcmVhZCA9IDE7Cj4gKyAgZGF0YS0+ aW5vZGUgPSAmZGF0YS0+ZGlyb3Blbi5pbm9kZTsKPiArCj4gKyAgZXJyID0gZ3J1Yl9mMmZzX3Jl YWRfbm9kZSAoZGF0YSwgZGF0YS0+cm9vdF9pbm8sIGRhdGEtPmlub2RlKTsKPiArICBpZiAoZXJy KQo+ICsgICAgZ290byBmYWlsOwo+ICsKPiArICByZXR1cm4gZGF0YTsKPiArCj4gK2ZhaWw6Cj4g KyAgaWYgKGRhdGEpCj4gKyAgICBncnViX2ZyZWUgKGRhdGEtPm5hdF9iaXRtYXApOwoKRG91Ymxl IGZyZWUgYWZ0ZXIgbG9hZF9uYXRfaW5mbyBmYWlsdXJlLiBBc3N1bWluZyB0aGF0IHdlIGRvIG5l ZWQgdG8KYWxsb2NhdGUgYW55dGhpbmcgYXQgYWxsIChzZWUgYWJvdmUpLgoKPiArICBncnViX2Zy ZWUgKGRhdGEpOwo+ICsgIHJldHVybiBOVUxMOwo+ICt9Cj4gKwo+ICsvKiBndWFyYW50ZWUgaW5s aW5lX2RhdGEgd2FzIGhhbmRsZWQgYnkgY2FsbGVyICovCj4gK3N0YXRpYyBncnViX2Rpc2tfYWRk cl90Cj4gK2dydWJfZjJmc19yZWFkX2Jsb2NrIChncnViX2ZzaGVscF9ub2RlX3Qgbm9kZSwgZ3J1 Yl9kaXNrX2FkZHJfdCBibG9ja19vZnMpCgpZb3UgaGF2ZSBncnViX2YyZnNfcmVhZF9ibG9jayBh bmQgZ3J1Yl9mMmZzX2Jsb2NrX3JlYWQuIENvdWxkIHdlIG1ha2UKdGhlbSBtb3JlIGRpZmZlcmVu dCBhbmQgc2VsZi1leHBsYWluaW5nPyBJbiBwYXJ0aWN1bGFyLCB0aGlzIG9uZSBkb2VzCm5vdCBy ZWFkIGFueXRoaW5nLCBpdCByZXR1cm5zIGRpc2sgYWRkcmVzcy4gZ3J1Yl9mMmZzX21hcF9maWxl X2Jsb2NrPwoKPiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0YSA9IG5vZGUtPmRh dGE7Cj4gKyAgc3RydWN0IGdydWJfZjJmc19pbm9kZSAqaW5vZGUgPSAmbm9kZS0+aW5vZGUuaTsK PiArICBncnViX3VpbnQzMl90IG9mZnNldFs0XSwgbm9mZnNldFs0XSwgbmlkc1s0XTsKClNlZSBh Ym92ZSBhYm91dCBvdmVyZmxvdyBpbiBncnViX2dldF9pbm9kZV9wYXRoLgoKPiArICBzdHJ1Y3Qg Z3J1Yl9mMmZzX25vZGUgKm5vZGVfYmxvY2s7Cj4gKyAgZ3J1Yl91aW50MzJfdCBibG9ja19hZGRy ID0gLTE7Cj4gKyAgaW50IGxldmVsLCBpOwo+ICsKPiArICBsZXZlbCA9IGdydWJfZ2V0X25vZGVf cGF0aCAoaW5vZGUsIGJsb2NrX29mcywgb2Zmc2V0LCBub2Zmc2V0KTsKPiArICBpZiAobGV2ZWwg PT0gMCkKPiArICAgICAgcmV0dXJuIGdydWJfbGVfdG9fY3B1MzIgKGlub2RlLT5pX2FkZHJbb2Zm c2V0WzBdXSk7Cj4gKwo+ICsgIG5vZGVfYmxvY2sgPSBncnViX21hbGxvYyAoRjJGU19CTEtTSVpF KTsKPiArICBpZiAoIW5vZGVfYmxvY2spCj4gKyAgICByZXR1cm4gLTE7Cj4gKwo+ICsgIG5pZHNb MV0gPSBfX2dldF9ub2RlX2lkICgmbm9kZS0+aW5vZGUsIG9mZnNldFswXSwgMSk7Cj4gKwo+ICsg IC8qIGdldCBpbmRpcmVjdCBvciBkaXJlY3Qgbm9kZXMgKi8KPiArICBmb3IgKGkgPSAxOyBpIDw9 IGxldmVsOyBpKyspCj4gKyAgICB7Cj4gKyAgICAgIGdydWJfZjJmc19yZWFkX25vZGUgKGRhdGEs IG5pZHNbaV0sIG5vZGVfYmxvY2spOwo+ICsgICAgICBpZiAoZ3J1Yl9lcnJubykKPiArICAgICAg ICBnb3RvIGZhaWw7Cj4gKwo+ICsgICAgICBpZiAoaSA8IGxldmVsKQo+ICsgICAgICAgIG5pZHNb aSArIDFdID0gX19nZXRfbm9kZV9pZCAobm9kZV9ibG9jaywgb2Zmc2V0W2ldLCAwKTsKPiArICAg IH0KPiArCj4gKyAgYmxvY2tfYWRkciA9IGdydWJfbGVfdG9fY3B1MzIgKG5vZGVfYmxvY2stPmRu LmFkZHJbb2Zmc2V0W2xldmVsXV0pOwo+ICtmYWlsOgo+ICsgIGdydWJfZnJlZSAobm9kZV9ibG9j ayk7Cj4gKyAgcmV0dXJuIGJsb2NrX2FkZHI7Cj4gK30KPiArCi4uLgo+ICsKPiArc3RhdGljIGNo YXIgKgo+ICtncnViX2YyZnNfcmVhZF9zeW1saW5rIChncnViX2ZzaGVscF9ub2RlX3Qgbm9kZSkK PiArewo+ICsgIGNoYXIgKnN5bWxpbms7Cj4gKyAgc3RydWN0IGdydWJfZnNoZWxwX25vZGUgKmRp cm8gPSBub2RlOwo+ICsKPiArICBpZiAoIWRpcm8tPmlub2RlX3JlYWQpCj4gKyAgICB7Cj4gKyAg ICAgIGdydWJfZjJmc19yZWFkX25vZGUgKGRpcm8tPmRhdGEsIGRpcm8tPmlubywgJmRpcm8tPmlu b2RlKTsKPiArICAgICAgaWYgKGdydWJfZXJybm8pCj4gKwlyZXR1cm4gMDsKPiArICAgIH0KPiAr Cj4gKyAgc3ltbGluayA9IGdydWJfbWFsbG9jIChfX2lfc2l6ZSAoJmRpcm8tPmlub2RlLmkpICsg MSk7Cj4gKyAgaWYgKCFzeW1saW5rKQo+ICsgICAgcmV0dXJuIDA7Cj4gKwo+ICsgIGdydWJfZjJm c19yZWFkX2ZpbGUgKGRpcm8sIDAsIDAsIDAsIF9faV9zaXplICgmZGlyby0+aW5vZGUuaSksIHN5 bWxpbmspOwo+ICsgIGlmIChncnViX2Vycm5vKQo+ICsgICAgewo+ICsgICAgICBncnViX2ZyZWUg KHN5bWxpbmspOwo+ICsgICAgICByZXR1cm4gMDsKPiArICAgIH0KPiArCgpXaGF0IGFib3V0IHNo b3J0IHJlYWQ/IElzIHRoaXMgYW4gZXJyb3Igb3Igbm90PwoKPiArICBzeW1saW5rW19faV9zaXpl ICgmZGlyby0+aW5vZGUuaSldID0gJ1wwJzsKPiArICByZXR1cm4gc3ltbGluazsKPiArfQo+ICsK PiArc3RhdGljIGludAo+ICtncnViX2YyZnNfY2hlY2tfZGVudHJpZXMgKHN0cnVjdCBncnViX2Yy ZnNfZGlyX2l0ZXJfY3R4ICpjdHgpCj4gK3sKPiArICBzdHJ1Y3QgZ3J1Yl9mc2hlbHBfbm9kZSAq ZmRpcm87Cj4gKyAgaW50IGk7Cj4gKwo+ICsgIGZvciAoaSA9IDA7IGkgPCBjdHgtPm1heDspCj4g KyAgICB7Cj4gKyAgICAgIGNoYXIgZmlsZW5hbWVbRjJGU19OQU1FX0xFTiArIDFdOwoKQ291bGQg d2UgYXZvaWQgbGFyZ2Ugc3RhY2sgYWxsb2NhdGlvbnM/Cgo+ICsgICAgICBlbnVtIGdydWJfZnNo ZWxwX2ZpbGV0eXBlIHR5cGUgPSBHUlVCX0ZTSEVMUF9VTktOT1dOOwo+ICsgICAgICBlbnVtIEZJ TEVfVFlQRSBmdHlwZTsKPiArICAgICAgaW50IG5hbWVfbGVuOwo+ICsKPiArICAgICAgaWYgKF9f dGVzdF9iaXQgKGksIGN0eC0+Yml0bWFwKSA9PSAwKQoKZ3J1Yl9mMmZzX3Rlc3RfYml0X2xlMzI/ Cgo+ICsgICAgICAgIHsKPiArICAgICAgICAgIGkrKzsKPiArICAgICAgICAgIGNvbnRpbnVlOwo+ ICsgICAgICAgIH0KPiArCj4gKyAgICAgIGZ0eXBlID0gY3R4LT5kZW50cnlbaV0uZmlsZV90eXBl Owo+ICsgICAgICBuYW1lX2xlbiA9IGdydWJfbGVfdG9fY3B1MTYgKGN0eC0+ZGVudHJ5W2ldLm5h bWVfbGVuKTsKPiArICAgICAgZ3J1Yl9tZW1jcHkgKGZpbGVuYW1lLCBjdHgtPmZpbGVuYW1lW2ld LCBuYW1lX2xlbik7Cj4gKyAgICAgIGZpbGVuYW1lW25hbWVfbGVuXSA9ICdcMCc7Cj4gKwo+ICsg ICAgICBmZGlybyA9IGdydWJfbWFsbG9jIChzaXplb2YgKHN0cnVjdCBncnViX2ZzaGVscF9ub2Rl KSk7Cj4gKyAgICAgIGlmICghZmRpcm8pCj4gKyAgICAgICAgcmV0dXJuIDA7Cj4gKwo+ICsgICAg ICBpZiAoZnR5cGUgPT0gRjJGU19GVF9ESVIpCj4gKyAgICAgICAgdHlwZSA9IEdSVUJfRlNIRUxQ X0RJUjsKPiArICAgICAgZWxzZSBpZiAoZnR5cGUgPT0gRjJGU19GVF9TWU1MSU5LKQo+ICsgICAg ICAgIHR5cGUgPSBHUlVCX0ZTSEVMUF9TWU1MSU5LOwo+ICsgICAgICBlbHNlIGlmIChmdHlwZSA9 PSBGMkZTX0ZUX1JFR19GSUxFKQo+ICsgICAgICAgIHR5cGUgPSBHUlVCX0ZTSEVMUF9SRUc7Cj4g Kwo+ICsgICAgICBmZGlyby0+ZGF0YSA9IGN0eC0+ZGF0YTsKPiArICAgICAgZmRpcm8tPmlubyA9 IGdydWJfbGVfdG9fY3B1MzIgKGN0eC0+ZGVudHJ5W2ldLmlubyk7Cj4gKyAgICAgIGZkaXJvLT5p bm9kZV9yZWFkID0gMDsKPiArCj4gKyAgICAgIGlmIChjdHgtPmhvb2sgKGZpbGVuYW1lLCB0eXBl LCBmZGlybywgY3R4LT5ob29rX2RhdGEpKQo+ICsgICAgICAgIHJldHVybiAxOwo+ICsKPiArICAg ICAgaSArPSAobmFtZV9sZW4gKyBGMkZTX1NMT1RfTEVOIC0gMSkgLyBGMkZTX1NMT1RfTEVOOwo+ ICsgICAgfQo+ICsgICAgcmV0dXJuIDA7Cj4gK30KPiArCi4uLgo+ICsKPiArc3RhdGljIGludAo+ ICtncnViX2YyZnNfaXRlcmF0ZV9kaXIgKGdydWJfZnNoZWxwX25vZGVfdCBkaXIsCj4gKwkJCSBn cnViX2ZzaGVscF9pdGVyYXRlX2Rpcl9ob29rX3QgaG9vaywgdm9pZCAqaG9va19kYXRhKQo+ICt7 Cj4gKyAgc3RydWN0IGdydWJfZnNoZWxwX25vZGUgKmRpcm8gPSAoc3RydWN0IGdydWJfZnNoZWxw X25vZGUgKikgZGlyOwo+ICsgIHN0cnVjdCBncnViX2YyZnNfaW5vZGUgKmlub2RlOwo+ICsgIHN0 cnVjdCBncnViX2YyZnNfZGlyX2l0ZXJfY3R4IGN0eCA9IHsKPiArICAgIC5kYXRhID0gZGlyby0+ ZGF0YSwKPiArICAgIC5ob29rID0gaG9vaywKPiArICAgIC5ob29rX2RhdGEgPSBob29rX2RhdGEK PiArICB9Owo+ICsgIGdydWJfb2ZmX3QgZnBvcyA9IDA7Cj4gKwo+ICsgIGlmICghZGlyby0+aW5v ZGVfcmVhZCkKPiArICAgIHsKPiArICAgICAgZ3J1Yl9mMmZzX3JlYWRfbm9kZSAoZGlyby0+ZGF0 YSwgZGlyby0+aW5vLCAmZGlyby0+aW5vZGUpOwo+ICsgICAgICBpZiAoZ3J1Yl9lcnJubykKPiAr CXJldHVybiAwOwo+ICsgICAgfQo+ICsKPiArICBpbm9kZSA9ICZkaXJvLT5pbm9kZS5pOwo+ICsK PiArICBpZiAoX19pbm9kZV9mbGFnX3NldCAoaW5vZGUsIEZJX0lOTElORV9ERU5UUlkpKQo+ICsg ICAgcmV0dXJuIGdydWJfZjJmc19pdGVyYXRlX2lubGluZV9kaXIgKGlub2RlLCAmY3R4KTsKPiAr Cj4gKyAgd2hpbGUgKGZwb3MgPCBfX2lfc2l6ZSAoaW5vZGUpKQo+ICsgICAgewo+ICsgICAgICBz dHJ1Y3QgZ3J1Yl9mMmZzX2RlbnRyeV9ibG9jayAqZGVfYmxrOwo+ICsgICAgICBjaGFyICpidWY7 Cj4gKwo+ICsgICAgICBidWYgPSBncnViX3phbGxvYyAoRjJGU19CTEtTSVpFKTsKPiArICAgICAg aWYgKCFidWYpCj4gKyAgICAgICAgcmV0dXJuIDA7Cj4gKwo+ICsgICAgICBncnViX2YyZnNfcmVh ZF9maWxlIChkaXJvLCAwLCAwLCBmcG9zLCBGMkZTX0JMS1NJWkUsIGJ1Zik7Cj4gKyAgICAgIGlm IChncnViX2Vycm5vKQo+ICsgICAgICAgIHsKPiArICAgICAgICAgIGdydWJfZnJlZSAoYnVmKTsK PiArICAgICAgICAgIHJldHVybiAwOwo+ICsgICAgICAgIH0KPiArCj4gKyAgICAgIGRlX2JsayA9 IChzdHJ1Y3QgZ3J1Yl9mMmZzX2RlbnRyeV9ibG9jayAqKSBidWY7Cj4gKwo+ICsgICAgICBjdHgu Yml0bWFwID0gKGdydWJfdWludDMyX3QgKikgZGVfYmxrLT5kZW50cnlfYml0bWFwOwo+ICsgICAg ICBjdHguZGVudHJ5ID0gZGVfYmxrLT5kZW50cnk7Cj4gKyAgICAgIGN0eC5maWxlbmFtZSA9IGRl X2Jsay0+ZmlsZW5hbWU7Cj4gKyAgICAgIGN0eC5tYXggPSBOUl9ERU5UUllfSU5fQkxPQ0s7Cj4g Kwo+ICsgICAgICBpZiAoZ3J1Yl9mMmZzX2NoZWNrX2RlbnRyaWVzICgmY3R4KSkKPiArICAgICAg ICByZXR1cm4gMTsKCm1lbW9yeSBsZWFrCgo+ICsKPiArICAgICAgZ3J1Yl9mcmVlIChidWYpOwo+ ICsKPiArICAgICAgZnBvcyArPSBGMkZTX0JMS1NJWkU7Cj4gKyAgICB9Cj4gKyAgcmV0dXJuIDA7 Cj4gK30KPiArCi4uLgo+ICtzdGF0aWMgZ3J1Yl9lcnJfdAo+ICtncnViX2YyZnNfZGlyIChncnVi X2RldmljZV90IGRldmljZSwgY29uc3QgY2hhciAqcGF0aCwKPiArCQkgZ3J1Yl9mc19kaXJfaG9v a190IGhvb2ssIHZvaWQgKmhvb2tfZGF0YSkKPiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGly X2N0eCBjdHggPSB7Cj4gKyAgICAuaG9vayA9IGhvb2ssCj4gKyAgICAuaG9va19kYXRhID0gaG9v a19kYXRhCj4gKyAgfTsKPiArICBzdHJ1Y3QgZ3J1Yl9mc2hlbHBfbm9kZSAqZmRpcm8gPSAwOwo+ ICsKPiArICBncnViX2RsX3JlZiAobXlfbW9kKTsKPiArCj4gKyAgY3R4LmRhdGEgPSBncnViX2Yy ZnNfbW91bnQgKGRldmljZS0+ZGlzayk7Cj4gKyAgaWYgKCFjdHguZGF0YSkKPiArICAgIGdvdG8g ZmFpbDsKPiArCj4gKyAgZ3J1Yl9mc2hlbHBfZmluZF9maWxlIChwYXRoLCAmY3R4LmRhdGEtPmRp cm9wZW4sICZmZGlybywKPiArCQkJIGdydWJfZjJmc19pdGVyYXRlX2RpciwgZ3J1Yl9mMmZzX3Jl YWRfc3ltbGluaywKPiArCQkJIEdSVUJfRlNIRUxQX0RJUik7Cj4gKyAgaWYgKGdydWJfZXJybm8p Cj4gKyAgICBnb3RvIGZhaWw7Cj4gKwo+ICsgIGdydWJfZjJmc19pdGVyYXRlX2RpciAoZmRpcm8s IGdydWJfZjJmc19kaXJfaXRlciwgJmN0eCk7Cj4gKwo+ICtmYWlsOgo+ICsgIGlmIChmZGlybyAh PSAmY3R4LmRhdGEtPmRpcm9wZW4pCj4gKyAgICBncnViX2ZyZWUgKGZkaXJvKTsKPiArICBpZiAo Y3R4LmRhdGEpCj4gKyAgICBncnViX2ZyZWUgKGN0eC5kYXRhLT5uYXRfYml0bWFwKTsKClRyaXBs ZSBmcmVlIDopCgo+ICsgIGdydWJfZnJlZSAoY3R4LmRhdGEpOwo+ICsgIGdydWJfZGxfdW5yZWYg KG15X21vZCk7Cj4gKyAgcmV0dXJuIGdydWJfZXJybm87Cj4gK30KPiArCj4gKwo+ICsvKiBPcGVu IGEgZmlsZSBuYW1lZCBOQU1FIGFuZCBpbml0aWFsaXplIEZJTEUuICAqLwo+ICtzdGF0aWMgZ3J1 Yl9lcnJfdAo+ICtncnViX2YyZnNfb3BlbiAoc3RydWN0IGdydWJfZmlsZSAqZmlsZSwgY29uc3Qg Y2hhciAqbmFtZSkKPiArewo+ICsgIHN0cnVjdCBncnViX2YyZnNfZGF0YSAqZGF0YSA9IE5VTEw7 Cj4gKyAgc3RydWN0IGdydWJfZnNoZWxwX25vZGUgKmZkaXJvID0gMDsKPiArCj4gKyAgZ3J1Yl9k bF9yZWYgKG15X21vZCk7Cj4gKwo+ICsgIGRhdGEgPSBncnViX2YyZnNfbW91bnQgKGZpbGUtPmRl dmljZS0+ZGlzayk7Cj4gKyAgaWYgKCFkYXRhKQo+ICsgICAgZ290byBmYWlsOwo+ICsKPiArICBn cnViX2ZzaGVscF9maW5kX2ZpbGUgKG5hbWUsICZkYXRhLT5kaXJvcGVuLCAmZmRpcm8sCj4gKwkJ CSBncnViX2YyZnNfaXRlcmF0ZV9kaXIsIGdydWJfZjJmc19yZWFkX3N5bWxpbmssCj4gKwkJCSBH UlVCX0ZTSEVMUF9SRUcpOwo+ICsgIGlmIChncnViX2Vycm5vKQo+ICsgICAgZ290byBmYWlsOwo+ ICsKPiArICBpZiAoIWZkaXJvLT5pbm9kZV9yZWFkKQo+ICsgICAgewo+ICsgICAgICBncnViX2Yy ZnNfcmVhZF9ub2RlIChkYXRhLCBmZGlyby0+aW5vLCAmZmRpcm8tPmlub2RlKTsKPiArICAgICAg aWYgKGdydWJfZXJybm8pCj4gKwlnb3RvIGZhaWw7Cj4gKyAgICB9Cj4gKwo+ICsgIGdydWJfbWVt Y3B5IChkYXRhLT5pbm9kZSwgJmZkaXJvLT5pbm9kZSwgRjJGU19CTEtTSVpFKTsKc2l6ZW9mICgq ZGF0YS0+aW5vZGUpPyBPciB0aGV5IGNhbiBiZSBkaWZmZXJlbnQ/Cgo+ICsgIGdydWJfZnJlZSAo ZmRpcm8pOwo+ICsKPiArICBmaWxlLT5zaXplID0gX19pX3NpemUgKCYoZGF0YS0+aW5vZGUtPmkp KTsKPiArICBmaWxlLT5kYXRhID0gZGF0YTsKPiArICBmaWxlLT5vZmZzZXQgPSAwOwo+ICsKPiAr ICByZXR1cm4gMDsKPiArCj4gK2ZhaWw6Cj4gKyAgaWYgKGZkaXJvICE9ICZkYXRhLT5kaXJvcGVu KQo+ICsgICAgZ3J1Yl9mcmVlIChmZGlybyk7Cj4gKyAgaWYgKGRhdGEpCj4gKyAgICBncnViX2Zy ZWUgKGRhdGEtPm5hdF9iaXRtYXApOwoKQWdhaW4uCgo+ICsgIGdydWJfZnJlZSAoZGF0YSk7Cj4g Kwo+ICsgIGdydWJfZGxfdW5yZWYgKG15X21vZCk7Cj4gKwo+ICsgIHJldHVybiBncnViX2Vycm5v Owo+ICt9Cj4gKwo+ICtzdGF0aWMgZ3J1Yl9zc2l6ZV90Cj4gK2dydWJfZjJmc19yZWFkIChncnVi X2ZpbGVfdCBmaWxlLCBjaGFyICpidWYsIGdydWJfc2l6ZV90IGxlbikKPiArewo+ICsgIHN0cnVj dCBncnViX2YyZnNfZGF0YSAqZGF0YSA9IChzdHJ1Y3QgZ3J1Yl9mMmZzX2RhdGEgKikgZmlsZS0+ ZGF0YTsKPiArCj4gKyAgcmV0dXJuIGdydWJfZjJmc19yZWFkX2ZpbGUgKCZkYXRhLT5kaXJvcGVu LAo+ICsJCQkJZmlsZS0+cmVhZF9ob29rLCBmaWxlLT5yZWFkX2hvb2tfZGF0YSwKPiArCQkJCWZp bGUtPm9mZnNldCwgbGVuLCBidWYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgZ3J1Yl9lcnJfdAo+ICtn cnViX2YyZnNfY2xvc2UgKGdydWJfZmlsZV90IGZpbGUpCj4gK3sKPiArICBzdHJ1Y3QgZ3J1Yl9m MmZzX2RhdGEgKmRhdGEgPSAoc3RydWN0IGdydWJfZjJmc19kYXRhICopIGZpbGUtPmRhdGE7Cj4g Kwo+ICsgIGlmIChkYXRhKQo+ICsgICAgZ3J1Yl9mcmVlIChkYXRhLT5uYXRfYml0bWFwKTsKCkFn YWluLgoKPiArICBncnViX2ZyZWUgKGRhdGEpOwo+ICsKPiArICBncnViX2RsX3VucmVmIChteV9t b2QpOwo+ICsKPiArICByZXR1cm4gR1JVQl9FUlJfTk9ORTsKPiArfQo+ICsKPiArc3RhdGljIGdy dWJfZXJyX3QKPiArZ3J1Yl9mMmZzX2xhYmVsIChncnViX2RldmljZV90IGRldmljZSwgY2hhciAq KmxhYmVsKQo+ICt7Cj4gKyAgc3RydWN0IGdydWJfZjJmc19kYXRhICpkYXRhOwo+ICsgIGdydWJf ZGlza190IGRpc2sgPSBkZXZpY2UtPmRpc2s7Cj4gKwo+ICsgIGdydWJfZGxfcmVmIChteV9tb2Qp Owo+ICsKPiArICBkYXRhID0gZ3J1Yl9mMmZzX21vdW50IChkaXNrKTsKPiArICBpZiAoZGF0YSkK PiArICAgIHsKPiArICAgICAgKmxhYmVsID0gZ3J1Yl96YWxsb2MgKHNpemVvZiAoZGF0YS0+c2Js b2NrLnZvbHVtZV9uYW1lKSk7Cj4gKyAgICAgIGdydWJfdXRmMTZfdG9fdXRmOCAoKGdydWJfdWlu dDhfdCAqKSAoKmxhYmVsKSwKCm1hbGxvYyBmYWlsdXJlIGNoZWNrPwoKPiArCQkJCWRhdGEtPnNi bG9jay52b2x1bWVfbmFtZSwgNTEyKTsKCldoZXJlIDUxMiBjb21lcyBmcm9tPyBTaG91bGQgaXQg bm90IGJlIHNpemVvZgooZGF0YS0+c2Jsb2NrLnZvbHVtZV9uYW1lKSBhcyB3ZWxsPwoKPiArICAg IH0KPiArICBlbHNlCj4gKyAgICAqbGFiZWwgPSBOVUxMOwo+ICsKPiArICBpZiAoZGF0YSkKPiAr ICAgIGdydWJfZnJlZSAoZGF0YS0+bmF0X2JpdG1hcCk7CgpBZ2Fpbi4KCj4gKyAgZ3J1Yl9mcmVl IChkYXRhKTsKPiArICBncnViX2RsX3VucmVmIChteV9tb2QpOwo+ICsgIHJldHVybiBncnViX2Vy cm5vOwo+ICt9Cj4gKwouLi4KPiBkaWZmIC0tZ2l0IGEvdGVzdHMvdXRpbC9ncnViLWZzLXRlc3Rl ci5pbiBiL3Rlc3RzL3V0aWwvZ3J1Yi1mcy10ZXN0ZXIuaW4KPiBpbmRleCBlOWU4NWMyLi5hY2Mz NWNjIDEwMDY0NAo+IC0tLSBhL3Rlc3RzL3V0aWwvZ3J1Yi1mcy10ZXN0ZXIuaW4KPiArKysgYi90 ZXN0cy91dGlsL2dydWItZnMtdGVzdGVyLmluCj4gQEAgLTM2LDcgKzM2LDcgQEAgY2FzZSB4IiRm cyIgaW4KPiAgCU1JTkxPR1NFQ1NJWkU9OAo+ICAJICAgICMgIE9TIExJTUlUQVRJT046IEl0IGNv dWxkIGdvIHVwIHRvIDMyNzY4IGJ1dCBMaW51eCByZWplY3RzIHNlY3RvciBzaXplcyA+IDQwOTYK PiAgCU1BWExPR1NFQ1NJWkU9MTI7Owo+IC0gICAgeHhmcykKPiArICAgIHh4ZnN8eGYyZnMpCj4g IAlNSU5MT0dTRUNTSVpFPTkKPiAgICAJICAgICMgT1MgTElNSVRBVElPTjogR05VL0xpbnV4IGRv ZXNuJ3QgYWNjZXB0ID4gNDA5Ngo+ICAJTUFYTE9HU0VDU0laRT0xMjs7Cj4gQEAgLTEzNSw2ICsx MzUsMTAgQEAgZm9yICgoTE9HU0VDU0laRT1NSU5MT0dTRUNTSVpFO0xPR1NFQ1NJWkU8PU1BWExP R1NFQ1NJWkU7TE9HU0VDU0laRT1MT0dTRUNTSVpFICsKPiAgCSAgICBmaQo+ICAJICAgIE1BWEJM S1NJWkU9NDA5Ngo+ICAJICAgIDs7Cj4gKwl4ZjJmcykKPiArCSAgICBNSU5CTEtTSVpFPSRTRUNT SVpFCj4gKwkJIyBPUyBMaW1pdGF0aW9uOiBHTlUvTGludXggZG9lc24ndCBhY2NlcHQgPiA0MDk2 Cj4gKwkgICAgTUFYQkxLU0laRT00MDk2OzsKPiAgCXhzcXVhc2gqKQo+ICAJICAgIE1JTkJMS1NJ WkU9NDA5Ngo+ICAJICAgIE1BWEJMS1NJWkU9MTA0ODU3Njs7Cj4gQEAgLTI1Niw3ICsyNjAsOSBA QCBmb3IgKChMT0dTRUNTSVpFPU1JTkxPR1NFQ1NJWkU7TE9HU0VDU0laRTw9TUFYTE9HU0VDU0la RTtMT0dTRUNTSVpFPUxPR1NFQ1NJWkUgKwo+ICAJICAgICMgRlMgTElNSVRBVElPTjogYnRyZnMg bGFiZWwgaXMgYXQgbW9zdCAyNTUgVVRGLTggY2hhcnMKPiAgCQl4ImJ0cmZzIiopCj4gIAkJICAg IEZTTEFCRUw9ImdydWJfOy90ZXN0w6nwr6ab8K+mnfCfmIHQutC40YDQuNGCaSB1cmV3ZmNlbml1 ZXdydWV2cmV3bnV1aXJldXJldnVldXJuaWV2cmV3Zm5lcmZjbmV2aXJpdmlucmV3dm5pcmV3bml2 cmV3aXV2Y3Jld3ZudWV3dnJycmV3bml1ZXJ3cmVpdXZpdXJld2l1dml1cmV3bnV2ZXdudnJlbnVy bnVudXZyZXZ1dXJlcmVqaXJlbXZyZWlqbnZjcmVpdmlyZSBudmVyaXZucmVpdnJldm51cmVpb3Jm bmZydm9lb2lyb2lyZW9pcmVvaWZyZWZvaWVyb2lmb2lyZW9pZiI7Owo+IC0KPiArCSAgICAjIEZT IExJTUlUQVRJT046IGJ0cmZzIGxhYmVsIGlzIGF0IG1vc3QgNTEyIFVURi0xNiBjaGFycwoKRjJG Uywgbm90IGJ0cmZzCgo+ICsJCXgiZjJmcyIpCj4gKwkJICAgIEZTTEFCRUw9ImdydWJfOy90ZXN0 amFlZ2V1ayBraW0gCgpDb3VsZCB5b3UgbGVhdmUgaW5pdGlhbCBwYXJ0IGluIHBsYWNlPyBUaGlz IGluY2x1ZGVzIHNvbWUgZnVubnkgVU5JQ09ERQpjaGFyYWN0ZXJzIGZvciBhIHJlYXNvbiwgYWN0 dWFsbHkuIFVubGVzcyB0aGlzIGlzIG5vdCBwb3NzaWJsZSB3aXRoCmYyZnM/CgpmMmZzYXNrZGZq a2FzZGxmYWpza2RmamFrc2RqZmtqYXNramtqa3pqa2pja3pqdmtjamtqa2pla3Fqa3dlamtxd3Js a2FzZGZqa3NhZGpmbGFza2Roenhodmp6eGNodmp6a3hjaHZqa2hha2pzZGhmamtocWprd2Vocmpr aGFzamtkZmhqa2FzaGRmamtoanpreGhjamt2emh4Y2prdmh6eGpjaHZremh4Y2tqdmhqemt4Y2h2 amtoempreGNodmpremh4Y2tqdmh6a3hqY2h2a2p6eGhja2p2enhjamt2aGp6eGtjaGt2amh6eGtq Y3ZoamtoamthaHNqa2Roa2pxaHdla3JqaGFranNkZmhramFzaGRranpoeGN2amtoenhjdnp4Y3Zn Z2dnZ2dnZ2dnZiI7Owo+ICAJICAgICMgRlMgTElNSVRBVElPTjogZXhmYXQgaXMgYXQgbW9zdCAx NSBVVEYtMTYgY2hhcnMKPiAgCQl4ImV4ZmF0IikKPiAgCQkgICAgRlNMQUJFTD0iZ8Op0YIgOy/w r6ab8K+mnfCfmIHQutC40YAiOzsKPiBAQCAtNDY2LDcgKzQ3Miw3IEBAIGZvciAoKExPR1NFQ1NJ WkU9TUlOTE9HU0VDU0laRTtMT0dTRUNTSVpFPD1NQVhMT0dTRUNTSVpFO0xPR1NFQ1NJWkU9TE9H U0VDU0laRSArCj4gIAkgICAgIyBGSVhNRTogTm90IHN1cmUgYWJvdXQgQnRyRlMsIE5URlMsIEpG UywgQUZTLCBVREYgYW5kIFNGUy4gQ2hlY2sgaXQuCj4gIAkjIEZTIExJTUlUQVRJT046IGFzIGZh ciBhcyBJIGtub3cgdGhvc2UgRlMgZG9uJ3Qgc3RvcmUgdGhlaXIgbGFzdCBtb2RpZmljYXRpb24g ZGF0ZS4KPiAgCQl4Impmc19jYXNlaW5zIiB8IHgiamZzIiB8IHgieGZzInwgeCJidHJmcyIqIHwg eCJyZWlzZXJmc19vbGQiIHwgeCJyZWlzZXJmcyIgXAo+IC0JCSAgICB8IHgiYmZzIiB8IHgiYWZz IiBcCj4gKwkJICAgIHwgeCJiZnMiIHwgeCJhZnMiIHwgeCJmMmZzIiBcCj4gIAkJICAgIHwgeCJ0 YXJmcyIgfCB4ImNwaW9fIiogfCB4Im1pbml4IiB8IHgibWluaXgyIiBcCj4gIAkJICAgIHwgeCJt aW5peDMiIHwgeCJudGZzIiogfCB4InVkZiIgfCB4InNmcyIqKQo+ICAJCSAgICBOT0ZTVElNRT15 OzsKPiBAQCAtNzQ1LDYgKzc1MSw4IEBAIGZvciAoKExPR1NFQ1NJWkU9TUlOTE9HU0VDU0laRTtM T0dTRUNTSVpFPD1NQVhMT0dTRUNTSVpFO0xPR1NFQ1NJWkU9TE9HU0VDU0laRSArCj4gIAkJICAg IE1PVU5UREVWSUNFPSIvZGV2L21hcHBlci9ncnViX3Rlc3QtdGVzdHZvbCIKPiAgCQkgICAgTU9V TlRGUz1leHQyCj4gIAkJICAgICJta2ZzLmV4dDIiIC1MICIkRlNMQUJFTCIgLXEgIiR7TU9VTlRE RVZJQ0V9IiAgOzsKPiArCQl4ZjJmcykKPiArCQkgICAgIm1rZnMuZjJmcyIgLWwgIiRGU0xBQkVM IiAtcSAiJHtMT0RFVklDRVNbMF19IiA7Owo+ICAJCXhuaWxmczIpCj4gIAkJICAgICJta2ZzLm5p bGZzMiIgLUwgIiRGU0xBQkVMIiAtYiAkQkxLU0laRSAgLXEgIiR7TE9ERVZJQ0VTWzBdfSIgOzsK PiAgCQl4ZXh0Ml9vbGQpCgoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX18KR3J1Yi1kZXZlbCBtYWlsaW5nIGxpc3QKR3J1Yi1kZXZlbEBnbnUub3JnCmh0dHBz Oi8vbGlzdHMuZ251Lm9yZy9tYWlsbWFuL2xpc3RpbmZvL2dydWItZGV2ZWwK