Module Name:    src
Committed By:   perseant
Date:           Fri Aug  2 00:23:21 UTC 2024

Modified Files:
        src/sbin/newfs_exfatfs [perseant-exfatfs]: Makefile extern.h
            make_exfatfs.c newfs.c newfs_exfatfs.8
Added Files:
        src/sbin/newfs_exfatfs [perseant-exfatfs]: defaults.c defaults.h

Log Message:
Make the default behavior to load an existing boot block set from the device,
if one exists; if it does not, to apply default values; and finally to
override either of those defaults with command-line arguments.

Add -n flag to ellow the creation of a file system with two FATs and
bitmap allocations, even though our code only ever uses the first.

Add -q (quiet) flag.

Add -w flag to pass over any existing boot block and use base defaults.


To generate a diff of this commit:
cvs rdiff -u -r1.1.2.1 -r1.1.2.2 src/sbin/newfs_exfatfs/Makefile
cvs rdiff -u -r0 -r1.1.2.1 src/sbin/newfs_exfatfs/defaults.c \
    src/sbin/newfs_exfatfs/defaults.h
cvs rdiff -u -r1.1.2.2 -r1.1.2.3 src/sbin/newfs_exfatfs/extern.h \
    src/sbin/newfs_exfatfs/newfs_exfatfs.8
cvs rdiff -u -r1.1.2.5 -r1.1.2.6 src/sbin/newfs_exfatfs/make_exfatfs.c
cvs rdiff -u -r1.1.2.3 -r1.1.2.4 src/sbin/newfs_exfatfs/newfs.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/newfs_exfatfs/Makefile
diff -u src/sbin/newfs_exfatfs/Makefile:1.1.2.1 src/sbin/newfs_exfatfs/Makefile:1.1.2.2
--- src/sbin/newfs_exfatfs/Makefile:1.1.2.1	Sat Jun 29 19:43:25 2024
+++ src/sbin/newfs_exfatfs/Makefile	Fri Aug  2 00:23:20 2024
@@ -1,10 +1,10 @@
-# $NetBSD: Makefile,v 1.1.2.1 2024/06/29 19:43:25 perseant Exp $
+# $NetBSD: Makefile,v 1.1.2.2 2024/08/02 00:23:20 perseant Exp $
 
 .include <bsd.own.mk>
 
 PROG=	newfs_exfatfs
 MAN=	newfs_exfatfs.8
-SRCS=	newfs.c partutil.c make_exfatfs.c bufcache.c exfatfs_cksum.c exfatfs_conv.c exfatfs_tables.c vnode.c kernelops.c
+SRCS=	newfs.c defaults.c partutil.c make_exfatfs.c bufcache.c exfatfs_cksum.c exfatfs_conv.c exfatfs_extern.c exfatfs_tables.c vnode.c kernelops.c
 
 CFLAGS=-g
 

Index: src/sbin/newfs_exfatfs/extern.h
diff -u src/sbin/newfs_exfatfs/extern.h:1.1.2.2 src/sbin/newfs_exfatfs/extern.h:1.1.2.3
--- src/sbin/newfs_exfatfs/extern.h:1.1.2.2	Wed Jul 24 00:46:18 2024
+++ src/sbin/newfs_exfatfs/extern.h	Fri Aug  2 00:23:21 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: extern.h,v 1.1.2.2 2024/07/24 00:46:18 perseant Exp $	*/
+/*	$NetBSD: extern.h,v 1.1.2.3 2024/08/02 00:23:21 perseant Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -31,10 +31,13 @@
  *	@(#)extern.h	8.2 (Berkeley) 5/24/95
  */
 
+#include "vnode.h"
+
 void	fatal(const char *fmt, ...)
      __attribute__((__format__(__printf__,1,2)));
-int	make_exfatfs(int, uint, struct dkwedge_info *, uint,
-		     uint16_t *, int, uint32_t, uint16_t *, size_t, char *);
+int	make_exfatfs(struct uvnode *, struct exfatfs *,
+		     uint16_t *, int, uint16_t *, size_t,
+		     uint32_t, uint32_t);
 
 extern char	*progname;
 extern char	*special;
Index: src/sbin/newfs_exfatfs/newfs_exfatfs.8
diff -u src/sbin/newfs_exfatfs/newfs_exfatfs.8:1.1.2.2 src/sbin/newfs_exfatfs/newfs_exfatfs.8:1.1.2.3
--- src/sbin/newfs_exfatfs/newfs_exfatfs.8:1.1.2.2	Thu Jul 25 23:46:10 2024
+++ src/sbin/newfs_exfatfs/newfs_exfatfs.8	Fri Aug  2 00:23:21 2024
@@ -1,4 +1,4 @@
-.\"	$NetBSD: newfs_exfatfs.8,v 1.1.2.2 2024/07/25 23:46:10 perseant Exp $
+.\"	$NetBSD: newfs_exfatfs.8,v 1.1.2.3 2024/08/02 00:23:21 perseant Exp $
 .\"
 .\" Copyright (c) 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -71,13 +71,13 @@ The alignment of the cluster heap, in by
 If not specified, the FAT alignment will be used.
 .It Fl L Ar label
 Specify the file system label.  The default label is "NONE GIVEN".
-.It Fl l Ar fat-length
-The length of the File Allocation Table, in sectors.
 .It Fl N
 Do not actually create the filesystem.
 .It Fl o Ar partition-offset
 The offset of this partition from the beginning of the disk, in sectors.
 The default value is taken from the disklabel.
+.It Fl q
+Do not print anything on stdout.
 .It Fl S Ar sector-size
 Use this as the size of filesystem sectors, in bytes.  The default is to
 use the sector size from the disk label.
@@ -91,6 +91,11 @@ The default is to use the recommended up
 section 7.2.5.1 of the specification.
 .It Fl v
 Be more verbose about what is being done.
+.It Fl w
+Do not attempt to read the existing superblock, if any.
+By default the existing superblock will be read and the
+existing file system parameters will be used unless
+overridden by command-line arguments.
 .El
 .Sh SEE ALSO
 .Xr disktab 5 ,

Index: src/sbin/newfs_exfatfs/make_exfatfs.c
diff -u src/sbin/newfs_exfatfs/make_exfatfs.c:1.1.2.5 src/sbin/newfs_exfatfs/make_exfatfs.c:1.1.2.6
--- src/sbin/newfs_exfatfs/make_exfatfs.c:1.1.2.5	Thu Jul 25 23:46:10 2024
+++ src/sbin/newfs_exfatfs/make_exfatfs.c	Fri Aug  2 00:23:21 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: make_exfatfs.c,v 1.1.2.5 2024/07/25 23:46:10 perseant Exp $	*/
+/*	$NetBSD: make_exfatfs.c,v 1.1.2.6 2024/08/02 00:23:21 perseant Exp $	*/
 
 /*-
  * Copyright (c) 2022 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
 #if 0
 static char sccsid[] = "@(#)lfs.c	8.5 (Berkeley) 5/24/95";
 #else
-__RCSID("$NetBSD: make_exfatfs.c,v 1.1.2.5 2024/07/25 23:46:10 perseant Exp $");
+__RCSID("$NetBSD: make_exfatfs.c,v 1.1.2.6 2024/08/02 00:23:21 perseant Exp $");
 #endif
 #endif /* not lint */
 
@@ -83,6 +83,7 @@ __RCSID("$NetBSD: make_exfatfs.c,v 1.1.2
 #include <fs/exfatfs/exfatfs.h>
 #include <fs/exfatfs/exfatfs_cksum.h>
 #include <fs/exfatfs/exfatfs_dirent.h>
+#include <fs/exfatfs/exfatfs_extern.h>
 #include <fs/exfatfs/exfatfs_tables.h>
 
 #include <assert.h>
@@ -100,518 +101,94 @@ __RCSID("$NetBSD: make_exfatfs.c,v 1.1.2
 #include "bufcache.h"
 #include "vnode.h"
 
-#if 0
-static uint8_t PRIMARY_IGNORE[2] = { 2, 3 };
-static uint8_t PRIMARY_IGNORE_LEN = 2;
-#endif
-
-uint16_t exfatfs_recommended_upcase_table_compressed[] = {
-	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
-	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
-	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
-	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
-	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
-	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
-	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
-	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
-	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
-	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
-	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
-	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
-	0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
-	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
-	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
-	0x0058, 0x0059, 0x005A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
-	0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
-	0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
-	0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
-	0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
-	0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
-	0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
-	0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
-	0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
-	0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
-	0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
-	0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
-	0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
-	0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
-	0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
-	0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00F7,
-	0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x0178,
-	0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106,
-	0x0108, 0x0108, 0x010A, 0x010A, 0x010C, 0x010C, 0x010E, 0x010E,
-	0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116,
-	0x0118, 0x0118, 0x011A, 0x011A, 0x011C, 0x011C, 0x011E, 0x011E,
-	0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126,
-	0x0128, 0x0128, 0x012A, 0x012A, 0x012C, 0x012C, 0x012E, 0x012E,
-	0x0130, 0x0131, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136,
-	0x0138, 0x0139, 0x0139, 0x013B, 0x013B, 0x013D, 0x013D, 0x013F,
-	0x013F, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147,
-	0x0147, 0x0149, 0x014A, 0x014A, 0x014C, 0x014C, 0x014E, 0x014E,
-	0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156,
-	0x0158, 0x0158, 0x015A, 0x015A, 0x015C, 0x015C, 0x015E, 0x015E,
-	0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166,
-	0x0168, 0x0168, 0x016A, 0x016A, 0x016C, 0x016C, 0x016E, 0x016E,
-	0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176,
-	0x0178, 0x0179, 0x0179, 0x017B, 0x017B, 0x017D, 0x017D, 0x017F,
-	0x0243, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
-	0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,
-	0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197,
-	0x0198, 0x0198, 0x023D, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F,
-	0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,
-	0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,
-	0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,
-	0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7,
-	0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C5, 0x01C4, 0x01C7,
-	0x01C8, 0x01C7, 0x01CA, 0x01CB, 0x01CA, 0x01CD, 0x01CD, 0x01CF,
-	0x01CF, 0x01D1, 0x01D1, 0x01D3, 0x01D3, 0x01D5, 0x01D5, 0x01D7,
-	0x01D7, 0x01D9, 0x01D9, 0x01DB, 0x01DB, 0x018E, 0x01DE, 0x01DE,
-	0x01E0, 0x01E0, 0x01E2, 0x01E2, 0x01E4, 0x01E4, 0x01E6, 0x01E6,
-	0x01E8, 0x01E8, 0x01EA, 0x01EA, 0x01EC, 0x01EC, 0x01EE, 0x01EE,
-	0x01F0, 0x01F1, 0x01F2, 0x01F1, 0x01F4, 0x01F4, 0x01F6, 0x01F7,
-	0x01F8, 0x01F8, 0x01FA, 0x01FA, 0x01FC, 0x01FC, 0x01FE, 0x01FE,
-	0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206,
-	0x0208, 0x0208, 0x020A, 0x020A, 0x020C, 0x020C, 0x020E, 0x020E,
-	0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216,
-	0x0218, 0x0218, 0x021A, 0x021A, 0x021C, 0x021C, 0x021E, 0x021E,
-	0x0220, 0x0221, 0x0222, 0x0222, 0x0224, 0x0224, 0x0226, 0x0226,
-	0x0228, 0x0228, 0x022A, 0x022A, 0x022C, 0x022C, 0x022E, 0x022E,
-	0x0230, 0x0230, 0x0232, 0x0232, 0x0234, 0x0235, 0x0236, 0x0237,
-	0x0238, 0x0239, 0x2C65, 0x023B, 0x023B, 0x023D, 0x2C66, 0x023F,
-	0x0240, 0x0241, 0x0241, 0x0243, 0x0244, 0x0245, 0x0246, 0x0246,
-	0x0248, 0x0248, 0x024A, 0x024A, 0x024C, 0x024C, 0x024E, 0x024E,
-	0x0250, 0x0251, 0x0252, 0x0181, 0x0186, 0x0255, 0x0189, 0x018A,
-	0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,
-	0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
-	0x0197, 0x0196, 0x026A, 0x2C62, 0x026C, 0x026D, 0x026E, 0x019C,
-	0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277,
-	0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x2C64, 0x027E, 0x027F,
-	0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,
-	0x01AE, 0x0244, 0x01B1, 0x01B2, 0x0245, 0x028D, 0x028E, 0x028F,
-	0x0290, 0x0291, 0x01B7, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297,
-	0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F,
-	0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7,
-	0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, 0x02AD, 0x02AE, 0x02AF,
-	0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6, 0x02B7,
-	0x02B8, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF,
-	0x02C0, 0x02C1, 0x02C2, 0x02C3, 0x02C4, 0x02C5, 0x02C6, 0x02C7,
-	0x02C8, 0x02C9, 0x02CA, 0x02CB, 0x02CC, 0x02CD, 0x02CE, 0x02CF,
-	0x02D0, 0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7,
-	0x02D8, 0x02D9, 0x02DA, 0x02DB, 0x02DC, 0x02DD, 0x02DE, 0x02DF,
-	0x02E0, 0x02E1, 0x02E2, 0x02E3, 0x02E4, 0x02E5, 0x02E6, 0x02E7,
-	0x02E8, 0x02E9, 0x02EA, 0x02EB, 0x02EC, 0x02ED, 0x02EE, 0x02EF,
-	0x02F0, 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, 0x02F7,
-	0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, 0x02FD, 0x02FE, 0x02FF,
-	0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
-	0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
-	0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
-	0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F,
-	0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
-	0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F,
-	0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
-	0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F,
-	0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
-	0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F,
-	0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
-	0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F,
-	0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
-	0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F,
-	0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
-	0x0378, 0x0379, 0x037A, 0x03FD, 0x03FE, 0x03FF, 0x037E, 0x037F,
-	0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,
-	0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,
-	0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
-	0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
-	0x03A0, 0x03A1, 0x03A2, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
-	0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,
-	0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
-	0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
-	0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
-	0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x03CF,
-	0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
-	0x03D8, 0x03D8, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE,
-	0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6,
-	0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,
-	0x03F0, 0x03F1, 0x03F9, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,
-	0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x03FC, 0x03FD, 0x03FE, 0x03FF,
-	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
-	0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F,
-	0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
-	0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
-	0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
-	0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
-	0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
-	0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
-	0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
-	0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
-	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
-	0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F,
-	0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466,
-	0x0468, 0x0468, 0x046A, 0x046A, 0x046C, 0x046C, 0x046E, 0x046E,
-	0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476,
-	0x0478, 0x0478, 0x047A, 0x047A, 0x047C, 0x047C, 0x047E, 0x047E,
-	0x0480, 0x0480, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
-	0x0488, 0x0489, 0x048A, 0x048A, 0x048C, 0x048C, 0x048E, 0x048E,
-	0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496,
-	0x0498, 0x0498, 0x049A, 0x049A, 0x049C, 0x049C, 0x049E, 0x049E,
-	0x04A0, 0x04A0, 0x04A2, 0x04A2, 0x04A4, 0x04A4, 0x04A6, 0x04A6,
-	0x04A8, 0x04A8, 0x04AA, 0x04AA, 0x04AC, 0x04AC, 0x04AE, 0x04AE,
-	0x04B0, 0x04B0, 0x04B2, 0x04B2, 0x04B4, 0x04B4, 0x04B6, 0x04B6,
-	0x04B8, 0x04B8, 0x04BA, 0x04BA, 0x04BC, 0x04BC, 0x04BE, 0x04BE,
-	0x04C0, 0x04C1, 0x04C1, 0x04C3, 0x04C3, 0x04C5, 0x04C5, 0x04C7,
-	0x04C7, 0x04C9, 0x04C9, 0x04CB, 0x04CB, 0x04CD, 0x04CD, 0x04C0,
-	0x04D0, 0x04D0, 0x04D2, 0x04D2, 0x04D4, 0x04D4, 0x04D6, 0x04D6,
-	0x04D8, 0x04D8, 0x04DA, 0x04DA, 0x04DC, 0x04DC, 0x04DE, 0x04DE,
-	0x04E0, 0x04E0, 0x04E2, 0x04E2, 0x04E4, 0x04E4, 0x04E6, 0x04E6,
-	0x04E8, 0x04E8, 0x04EA, 0x04EA, 0x04EC, 0x04EC, 0x04EE, 0x04EE,
-	0x04F0, 0x04F0, 0x04F2, 0x04F2, 0x04F4, 0x04F4, 0x04F6, 0x04F6,
-	0x04F8, 0x04F8, 0x04FA, 0x04FA, 0x04FC, 0x04FC, 0x04FE, 0x04FE,
-	0x0500, 0x0500, 0x0502, 0x0502, 0x0504, 0x0504, 0x0506, 0x0506,
-	0x0508, 0x0508, 0x050A, 0x050A, 0x050C, 0x050C, 0x050E, 0x050E,
-	0x0510, 0x0510, 0x0512, 0x0512, 0x0514, 0x0515, 0x0516, 0x0517,
-	0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,
-	0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
-	0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,
-	0x0530, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
-	0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F,
-	0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
-	0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F,
-	0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0557,
-	0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,
-	0x0560, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
-	0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F,
-	0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
-	0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F,
-	0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0xFFFF,
-	0x17F6, 0x2C63, 0x1D7E, 0x1D7F, 0x1D80, 0x1D81, 0x1D82, 0x1D83,
-	0x1D84, 0x1D85, 0x1D86, 0x1D87, 0x1D88, 0x1D89, 0x1D8A, 0x1D8B,
-	0x1D8C, 0x1D8D, 0x1D8E, 0x1D8F, 0x1D90, 0x1D91, 0x1D92, 0x1D93,
-	0x1D94, 0x1D95, 0x1D96, 0x1D97, 0x1D98, 0x1D99, 0x1D9A, 0x1D9B,
-	0x1D9C, 0x1D9D, 0x1D9E, 0x1D9F, 0x1DA0, 0x1DA1, 0x1DA2, 0x1DA3,
-	0x1DA4, 0x1DA5, 0x1DA6, 0x1DA7, 0x1DA8, 0x1DA9, 0x1DAA, 0x1DAB,
-	0x1DAC, 0x1DAD, 0x1DAE, 0x1DAF, 0x1DB0, 0x1DB1, 0x1DB2, 0x1DB3,
-	0x1DB4, 0x1DB5, 0x1DB6, 0x1DB7, 0x1DB8, 0x1DB9, 0x1DBA, 0x1DBB,
-	0x1DBC, 0x1DBD, 0x1DBE, 0x1DBF, 0x1DC0, 0x1DC1, 0x1DC2, 0x1DC3,
-	0x1DC4, 0x1DC5, 0x1DC6, 0x1DC7, 0x1DC8, 0x1DC9, 0x1DCA, 0x1DCB,
-	0x1DCC, 0x1DCD, 0x1DCE, 0x1DCF, 0x1DD0, 0x1DD1, 0x1DD2, 0x1DD3,
-	0x1DD4, 0x1DD5, 0x1DD6, 0x1DD7, 0x1DD8, 0x1DD9, 0x1DDA, 0x1DDB,
-	0x1DDC, 0x1DDD, 0x1DDE, 0x1DDF, 0x1DE0, 0x1DE1, 0x1DE2, 0x1DE3,
-	0x1DE4, 0x1DE5, 0x1DE6, 0x1DE7, 0x1DE8, 0x1DE9, 0x1DEA, 0x1DEB,
-	0x1DEC, 0x1DED, 0x1DEE, 0x1DEF, 0x1DF0, 0x1DF1, 0x1DF2, 0x1DF3,
-	0x1DF4, 0x1DF5, 0x1DF6, 0x1DF7, 0x1DF8, 0x1DF9, 0x1DFA, 0x1DFB,
-	0x1DFC, 0x1DFD, 0x1DFE, 0x1DFF, 0x1E00, 0x1E00, 0x1E02, 0x1E02,
-	0x1E04, 0x1E04, 0x1E06, 0x1E06, 0x1E08, 0x1E08, 0x1E0A, 0x1E0A,
-	0x1E0C, 0x1E0C, 0x1E0E, 0x1E0E, 0x1E10, 0x1E10, 0x1E12, 0x1E12,
-	0x1E14, 0x1E14, 0x1E16, 0x1E16, 0x1E18, 0x1E18, 0x1E1A, 0x1E1A,
-	0x1E1C, 0x1E1C, 0x1E1E, 0x1E1E, 0x1E20, 0x1E20, 0x1E22, 0x1E22,
-	0x1E24, 0x1E24, 0x1E26, 0x1E26, 0x1E28, 0x1E28, 0x1E2A, 0x1E2A,
-	0x1E2C, 0x1E2C, 0x1E2E, 0x1E2E, 0x1E30, 0x1E30, 0x1E32, 0x1E32,
-	0x1E34, 0x1E34, 0x1E36, 0x1E36, 0x1E38, 0x1E38, 0x1E3A, 0x1E3A,
-	0x1E3C, 0x1E3C, 0x1E3E, 0x1E3E, 0x1E40, 0x1E40, 0x1E42, 0x1E42,
-	0x1E44, 0x1E44, 0x1E46, 0x1E46, 0x1E48, 0x1E48, 0x1E4A, 0x1E4A,
-	0x1E4C, 0x1E4C, 0x1E4E, 0x1E4E, 0x1E50, 0x1E50, 0x1E52, 0x1E52,
-	0x1E54, 0x1E54, 0x1E56, 0x1E56, 0x1E58, 0x1E58, 0x1E5A, 0x1E5A,
-	0x1E5C, 0x1E5C, 0x1E5E, 0x1E5E, 0x1E60, 0x1E60, 0x1E62, 0x1E62,
-	0x1E64, 0x1E64, 0x1E66, 0x1E66, 0x1E68, 0x1E68, 0x1E6A, 0x1E6A,
-	0x1E6C, 0x1E6C, 0x1E6E, 0x1E6E, 0x1E70, 0x1E70, 0x1E72, 0x1E72,
-	0x1E74, 0x1E74, 0x1E76, 0x1E76, 0x1E78, 0x1E78, 0x1E7A, 0x1E7A,
-	0x1E7C, 0x1E7C, 0x1E7E, 0x1E7E, 0x1E80, 0x1E80, 0x1E82, 0x1E82,
-	0x1E84, 0x1E84, 0x1E86, 0x1E86, 0x1E88, 0x1E88, 0x1E8A, 0x1E8A,
-	0x1E8C, 0x1E8C, 0x1E8E, 0x1E8E, 0x1E90, 0x1E90, 0x1E92, 0x1E92,
-	0x1E94, 0x1E94, 0x1E96, 0x1E97, 0x1E98, 0x1E99, 0x1E9A, 0x1E9B,
-	0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F, 0x1EA0, 0x1EA0, 0x1EA2, 0x1EA2,
-	0x1EA4, 0x1EA4, 0x1EA6, 0x1EA6, 0x1EA8, 0x1EA8, 0x1EAA, 0x1EAA,
-	0x1EAC, 0x1EAC, 0x1EAE, 0x1EAE, 0x1EB0, 0x1EB0, 0x1EB2, 0x1EB2,
-	0x1EB4, 0x1EB4, 0x1EB6, 0x1EB6, 0x1EB8, 0x1EB8, 0x1EBA, 0x1EBA,
-	0x1EBC, 0x1EBC, 0x1EBE, 0x1EBE, 0x1EC0, 0x1EC0, 0x1EC2, 0x1EC2,
-	0x1EC4, 0x1EC4, 0x1EC6, 0x1EC6, 0x1EC8, 0x1EC8, 0x1ECA, 0x1ECA,
-	0x1ECC, 0x1ECC, 0x1ECE, 0x1ECE, 0x1ED0, 0x1ED0, 0x1ED2, 0x1ED2,
-	0x1ED4, 0x1ED4, 0x1ED6, 0x1ED6, 0x1ED8, 0x1ED8, 0x1EDA, 0x1EDA,
-	0x1EDC, 0x1EDC, 0x1EDE, 0x1EDE, 0x1EE0, 0x1EE0, 0x1EE2, 0x1EE2,
-	0x1EE4, 0x1EE4, 0x1EE6, 0x1EE6, 0x1EE8, 0x1EE8, 0x1EEA, 0x1EEA,
-	0x1EEC, 0x1EEC, 0x1EEE, 0x1EEE, 0x1EF0, 0x1EF0, 0x1EF2, 0x1EF2,
-	0x1EF4, 0x1EF4, 0x1EF6, 0x1EF6, 0x1EF8, 0x1EF8, 0x1EFA, 0x1EFB,
-	0x1EFC, 0x1EFD, 0x1EFE, 0x1EFF, 0x1F08, 0x1F09, 0x1F0A, 0x1F0B,
-	0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, 0x1F08, 0x1F09, 0x1F0A, 0x1F0B,
-	0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, 0x1F18, 0x1F19, 0x1F1A, 0x1F1B,
-	0x1F1C, 0x1F1D, 0x1F16, 0x1F17, 0x1F18, 0x1F19, 0x1F1A, 0x1F1B,
-	0x1F1C, 0x1F1D, 0x1F1E, 0x1F1F, 0x1F28, 0x1F29, 0x1F2A, 0x1F2B,
-	0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 0x1F28, 0x1F29, 0x1F2A, 0x1F2B,
-	0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 0x1F38, 0x1F39, 0x1F3A, 0x1F3B,
-	0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, 0x1F38, 0x1F39, 0x1F3A, 0x1F3B,
-	0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, 0x1F48, 0x1F49, 0x1F4A, 0x1F4B,
-	0x1F4C, 0x1F4D, 0x1F46, 0x1F47, 0x1F48, 0x1F49, 0x1F4A, 0x1F4B,
-	0x1F4C, 0x1F4D, 0x1F4E, 0x1F4F, 0x1F50, 0x1F59, 0x1F52, 0x1F5B,
-	0x1F54, 0x1F5D, 0x1F56, 0x1F5F, 0x1F58, 0x1F59, 0x1F5A, 0x1F5B,
-	0x1F5C, 0x1F5D, 0x1F5E, 0x1F5F, 0x1F68, 0x1F69, 0x1F6A, 0x1F6B,
-	0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, 0x1F68, 0x1F69, 0x1F6A, 0x1F6B,
-	0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9,
-	0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB, 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB,
-	0x1FFA, 0x1FFB, 0x1F7E, 0x1F7F, 0x1F88, 0x1F89, 0x1F8A, 0x1F8B,
-	0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, 0x1F88, 0x1F89, 0x1F8A, 0x1F8B,
-	0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, 0x1F98, 0x1F99, 0x1F9A, 0x1F9B,
-	0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, 0x1F98, 0x1F99, 0x1F9A, 0x1F9B,
-	0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB,
-	0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB,
-	0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, 0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC,
-	0x1FB4, 0x1FB5, 0x1FB6, 0x1FB7, 0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB,
-	0x1FBC, 0x1FBD, 0x1FBE, 0x1FBF, 0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3,
-	0x1FC4, 0x1FC5, 0x1FC6, 0x1FC7, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB,
-	0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF, 0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3,
-	0x1FD4, 0x1FD5, 0x1FD6, 0x1FD7, 0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB,
-	0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF, 0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3,
-	0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7, 0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB,
-	0x1FEC, 0x1FED, 0x1FEE, 0x1FEF, 0x1FF0, 0x1FF1, 0x1FF2, 0x1FF3,
-	0x1FF4, 0x1FF5, 0x1FF6, 0x1FF7, 0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB,
-	0x1FF3, 0x1FFD, 0x1FFE, 0x1FFF, 0x2000, 0x2001, 0x2002, 0x2003,
-	0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B,
-	0x200C, 0x200D, 0x200E, 0x200F, 0x2010, 0x2011, 0x2012, 0x2013,
-	0x2014, 0x2015, 0x2016, 0x2017, 0x2018, 0x2019, 0x201A, 0x201B,
-	0x201C, 0x201D, 0x201E, 0x201F, 0x2020, 0x2021, 0x2022, 0x2023,
-	0x2024, 0x2025, 0x2026, 0x2027, 0x2028, 0x2029, 0x202A, 0x202B,
-	0x202C, 0x202D, 0x202E, 0x202F, 0x2030, 0x2031, 0x2032, 0x2033,
-	0x2034, 0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203A, 0x203B,
-	0x203C, 0x203D, 0x203E, 0x203F, 0x2040, 0x2041, 0x2042, 0x2043,
-	0x2044, 0x2045, 0x2046, 0x2047, 0x2048, 0x2049, 0x204A, 0x204B,
-	0x204C, 0x204D, 0x204E, 0x204F, 0x2050, 0x2051, 0x2052, 0x2053,
-	0x2054, 0x2055, 0x2056, 0x2057, 0x2058, 0x2059, 0x205A, 0x205B,
-	0x205C, 0x205D, 0x205E, 0x205F, 0x2060, 0x2061, 0x2062, 0x2063,
-	0x2064, 0x2065, 0x2066, 0x2067, 0x2068, 0x2069, 0x206A, 0x206B,
-	0x206C, 0x206D, 0x206E, 0x206F, 0x2070, 0x2071, 0x2072, 0x2073,
-	0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079, 0x207A, 0x207B,
-	0x207C, 0x207D, 0x207E, 0x207F, 0x2080, 0x2081, 0x2082, 0x2083,
-	0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208A, 0x208B,
-	0x208C, 0x208D, 0x208E, 0x208F, 0x2090, 0x2091, 0x2092, 0x2093,
-	0x2094, 0x2095, 0x2096, 0x2097, 0x2098, 0x2099, 0x209A, 0x209B,
-	0x209C, 0x209D, 0x209E, 0x209F, 0x20A0, 0x20A1, 0x20A2, 0x20A3,
-	0x20A4, 0x20A5, 0x20A6, 0x20A7, 0x20A8, 0x20A9, 0x20AA, 0x20AB,
-	0x20AC, 0x20AD, 0x20AE, 0x20AF, 0x20B0, 0x20B1, 0x20B2, 0x20B3,
-	0x20B4, 0x20B5, 0x20B6, 0x20B7, 0x20B8, 0x20B9, 0x20BA, 0x20BB,
-	0x20BC, 0x20BD, 0x20BE, 0x20BF, 0x20C0, 0x20C1, 0x20C2, 0x20C3,
-	0x20C4, 0x20C5, 0x20C6, 0x20C7, 0x20C8, 0x20C9, 0x20CA, 0x20CB,
-	0x20CC, 0x20CD, 0x20CE, 0x20CF, 0x20D0, 0x20D1, 0x20D2, 0x20D3,
-	0x20D4, 0x20D5, 0x20D6, 0x20D7, 0x20D8, 0x20D9, 0x20DA, 0x20DB,
-	0x20DC, 0x20DD, 0x20DE, 0x20DF, 0x20E0, 0x20E1, 0x20E2, 0x20E3,
-	0x20E4, 0x20E5, 0x20E6, 0x20E7, 0x20E8, 0x20E9, 0x20EA, 0x20EB,
-	0x20EC, 0x20ED, 0x20EE, 0x20EF, 0x20F0, 0x20F1, 0x20F2, 0x20F3,
-	0x20F4, 0x20F5, 0x20F6, 0x20F7, 0x20F8, 0x20F9, 0x20FA, 0x20FB,
-	0x20FC, 0x20FD, 0x20FE, 0x20FF, 0x2100, 0x2101, 0x2102, 0x2103,
-	0x2104, 0x2105, 0x2106, 0x2107, 0x2108, 0x2109, 0x210A, 0x210B,
-	0x210C, 0x210D, 0x210E, 0x210F, 0x2110, 0x2111, 0x2112, 0x2113,
-	0x2114, 0x2115, 0x2116, 0x2117, 0x2118, 0x2119, 0x211A, 0x211B,
-	0x211C, 0x211D, 0x211E, 0x211F, 0x2120, 0x2121, 0x2122, 0x2123,
-	0x2124, 0x2125, 0x2126, 0x2127, 0x2128, 0x2129, 0x212A, 0x212B,
-	0x212C, 0x212D, 0x212E, 0x212F, 0x2130, 0x2131, 0x2132, 0x2133,
-	0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213A, 0x213B,
-	0x213C, 0x213D, 0x213E, 0x213F, 0x2140, 0x2141, 0x2142, 0x2143,
-	0x2144, 0x2145, 0x2146, 0x2147, 0x2148, 0x2149, 0x214A, 0x214B,
-	0x214C, 0x214D, 0x2132, 0x214F, 0x2150, 0x2151, 0x2152, 0x2153,
-	0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215A, 0x215B,
-	0x215C, 0x215D, 0x215E, 0x215F, 0x2160, 0x2161, 0x2162, 0x2163,
-	0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B,
-	0x216C, 0x216D, 0x216E, 0x216F, 0x2160, 0x2161, 0x2162, 0x2163,
-	0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B,
-	0x216C, 0x216D, 0x216E, 0x216F, 0x2180, 0x2181, 0x2182, 0x2183,
-	0x2183, 0xFFFF, 0x034B, 0x24B6, 0x24B7, 0x24B8, 0x24B9, 0x24BA,
-	0x24BB, 0x24BC, 0x24BD, 0x24BE, 0x24BF, 0x24C0, 0x24C1, 0x24C2,
-	0x24C3, 0x24C4, 0x24C5, 0x24C6, 0x24C7, 0x24C8, 0x24C9, 0x24CA,
-	0x24CB, 0x24CC, 0x24CD, 0x24CE, 0x24CF, 0xFFFF, 0x0746, 0x2C00,
-	0x2C01, 0x2C02, 0x2C03, 0x2C04, 0x2C05, 0x2C06, 0x2C07, 0x2C08,
-	0x2C09, 0x2C0A, 0x2C0B, 0x2C0C, 0x2C0D, 0x2C0E, 0x2C0F, 0x2C10,
-	0x2C11, 0x2C12, 0x2C13, 0x2C14, 0x2C15, 0x2C16, 0x2C17, 0x2C18,
-	0x2C19, 0x2C1A, 0x2C1B, 0x2C1C, 0x2C1D, 0x2C1E, 0x2C1F, 0x2C20,
-	0x2C21, 0x2C22, 0x2C23, 0x2C24, 0x2C25, 0x2C26, 0x2C27, 0x2C28,
-	0x2C29, 0x2C2A, 0x2C2B, 0x2C2C, 0x2C2D, 0x2C2E, 0x2C5F, 0x2C60,
-	0x2C60, 0x2C62, 0x2C63, 0x2C64, 0x2C65, 0x2C66, 0x2C67, 0x2C67,
-	0x2C69, 0x2C69, 0x2C6B, 0x2C6B, 0x2C6D, 0x2C6E, 0x2C6F, 0x2C70,
-	0x2C71, 0x2C72, 0x2C73, 0x2C74, 0x2C75, 0x2C75, 0x2C77, 0x2C78,
-	0x2C79, 0x2C7A, 0x2C7B, 0x2C7C, 0x2C7D, 0x2C7E, 0x2C7F, 0x2C80,
-	0x2C80, 0x2C82, 0x2C82, 0x2C84, 0x2C84, 0x2C86, 0x2C86, 0x2C88,
-	0x2C88, 0x2C8A, 0x2C8A, 0x2C8C, 0x2C8C, 0x2C8E, 0x2C8E, 0x2C90,
-	0x2C90, 0x2C92, 0x2C92, 0x2C94, 0x2C94, 0x2C96, 0x2C96, 0x2C98,
-	0x2C98, 0x2C9A, 0x2C9A, 0x2C9C, 0x2C9C, 0x2C9E, 0x2C9E, 0x2CA0,
-	0x2CA0, 0x2CA2, 0x2CA2, 0x2CA4, 0x2CA4, 0x2CA6, 0x2CA6, 0x2CA8,
-	0x2CA8, 0x2CAA, 0x2CAA, 0x2CAC, 0x2CAC, 0x2CAE, 0x2CAE, 0x2CB0,
-	0x2CB0, 0x2CB2, 0x2CB2, 0x2CB4, 0x2CB4, 0x2CB6, 0x2CB6, 0x2CB8,
-	0x2CB8, 0x2CBA, 0x2CBA, 0x2CBC, 0x2CBC, 0x2CBE, 0x2CBE, 0x2CC0,
-	0x2CC0, 0x2CC2, 0x2CC2, 0x2CC4, 0x2CC4, 0x2CC6, 0x2CC6, 0x2CC8,
-	0x2CC8, 0x2CCA, 0x2CCA, 0x2CCC, 0x2CCC, 0x2CCE, 0x2CCE, 0x2CD0,
-	0x2CD0, 0x2CD2, 0x2CD2, 0x2CD4, 0x2CD4, 0x2CD6, 0x2CD6, 0x2CD8,
-	0x2CD8, 0x2CDA, 0x2CDA, 0x2CDC, 0x2CDC, 0x2CDE, 0x2CDE, 0x2CE0,
-	0x2CE0, 0x2CE2, 0x2CE2, 0x2CE4, 0x2CE5, 0x2CE6, 0x2CE7, 0x2CE8,
-	0x2CE9, 0x2CEA, 0x2CEB, 0x2CEC, 0x2CED, 0x2CEE, 0x2CEF, 0x2CF0,
-	0x2CF1, 0x2CF2, 0x2CF3, 0x2CF4, 0x2CF5, 0x2CF6, 0x2CF7, 0x2CF8,
-	0x2CF9, 0x2CFA, 0x2CFB, 0x2CFC, 0x2CFD, 0x2CFE, 0x2CFF, 0x10A0,
-	0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x10A7, 0x10A8,
-	0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x10AF, 0x10B0,
-	0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x10B7, 0x10B8,
-	0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x10BE, 0x10BF, 0x10C0,
-	0x10C1, 0x10C2, 0x10C3, 0x10C4, 0x10C5, 0xFFFF, 0xD21B, 0xFF21,
-	0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29,
-	0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31,
-	0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39,
-	0xFF3A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F, 0xFF60, 0xFF61,
-	0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, 0xFF68, 0xFF69,
-	0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, 0xFF70, 0xFF71,
-	0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, 0xFF78, 0xFF79,
-	0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, 0xFF80, 0xFF81,
-	0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88, 0xFF89,
-	0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, 0xFF90, 0xFF91,
-	0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, 0xFF98, 0xFF99,
-	0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, 0xFFA0, 0xFFA1,
-	0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, 0xFFA8, 0xFFA9,
-	0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF, 0xFFB0, 0xFFB1,
-	0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7, 0xFFB8, 0xFFB9,
-	0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF, 0xFFC0, 0xFFC1,
-	0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, 0xFFC8, 0xFFC9,
-	0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF, 0xFFD0, 0xFFD1,
-	0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, 0xFFD8, 0xFFD9,
-	0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF, 0xFFE0, 0xFFE1,
-	0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7, 0xFFE8, 0xFFE9,
-	0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, 0xFFF0, 0xFFF1,
-	0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, 0xFFF8, 0xFFF9,
-	0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF
-};
 
 extern int Nflag; /* Don't write anything */
+extern int Qflag; /* Quiet */
 extern int Vflag; /* Verbose */
-extern uint32_t fatalign;
-extern uint32_t heapalign;
-extern uint32_t fatlength;
-extern uint32_t partition_offset;
 
 void pwarn(const char *, ...);
 
-static void
-efun(int eval, const char *fmt, ...)
-{
-        va_list ap;
-        va_start(ap, fmt);
-        verr(1, fmt, ap);
-        va_end(ap);
-}
-
 int
-make_exfatfs(int devfd, uint secsize, struct dkwedge_info *dkw, uint bsize,
-	     uint16_t *uclabel, int uclabellen, uint32_t serial,
-	     uint16_t *uctable, size_t uctablesize, char *bootcode)
+make_exfatfs(struct uvnode *devvp, struct exfatfs *fs,
+	     uint16_t *uclabel, int uclabellen,
+	     uint16_t *uctable, size_t uctablesize,
+	     uint32_t fatalign, uint32_t heapalign)
 {
-	struct exfatfs *fs;
-	struct uvnode *devvp;
-	uint32_t nclust;
-	struct exfatfs_dirent_allocation_bitmap dirent_bitmap;
+	uint32_t clust, nclust;
+	struct exfatfs_dirent_allocation_bitmap dirent_bitmap[2];
 	struct exfatfs_dirent_upcase_table dirent_upcase;
 	struct exfatfs_dirent_volume_label dirent_label;
-	daddr_t daddr, base;
+	daddr_t daddr;
 	char *data;
-	uint8_t boot_ignore[3] = { 106, 107, 112 };
 	struct buf *bp;
-	uint32_t bsshift, scshift, cksum, fatspersec;
-	uint32_t bitmap_cluster_size, upcase_cluster_size;
-	unsigned int i, j, bit, byte;
+	uint32_t fatspersec;
+	unsigned int i, j, bi, bit, byte;
 	off_t resid;
 	off_t end, start, progress, oprogress;
+	uint32_t secsize = (1 << fs->xf_BytesPerSectorShift);
 
-	/* Calculate shifts */
-	bsshift = 0;
-	while ((1U << bsshift) < secsize)
-		++bsshift;
-	scshift = 0;
-	while ((secsize << scshift) < bsize)
-		++scshift;
-
-	/* Convert align and heapalign into sectors */
-	fatalign /= secsize;
-	heapalign /= secsize;
-	if (heapalign == 0)
-		heapalign = fatalign;
-
-	/* If no table given, use recommendation */
-	if (uctable == NULL || uctablesize == 0) {
-		uctable = exfatfs_recommended_upcase_table_compressed;
-		uctablesize = sizeof (exfatfs_recommended_upcase_table_compressed);
+	if (Vflag) {
+		printf("VolumeLength: %lu\n",
+			(unsigned long)fs->xf_VolumeLength);
+		printf("Serial Number: 0x%lx (%lu)\n",
+			(unsigned long)fs->xf_VolumeSerialNumber,
+               		(unsigned long)fs->xf_VolumeSerialNumber);
+		printf("Sector shift: %u (size %u)\n",
+			(unsigned)fs->xf_BytesPerSectorShift,
+			(unsigned)secsize);
+		printf("Cluster shift: %u (size %u)\n",
+			(unsigned)fs->xf_SectorsPerClusterShift,
+			(unsigned)(1 << (fs->xf_SectorsPerClusterShift + fs->xf_BytesPerSectorShift)));
 	}
 
-	/* Use random serial number if not given */
-	if (serial == 0)
-		serial = (uint32_t)random();
-	
 	/*
-	 * Initialize buffer cache.
+	 * Apply alignments and compute the number of clusters
+	 * to fill in the remaining fields of the superblock.
 	 */
-	vfs_init();
-	bufinit(17); /* XXX arbitrary magic 17 */
-	esetfunc(efun);
-	devvp = ecalloc(1, sizeof(*devvp));
-        devvp->v_fs = NULL;
-        devvp->v_fd = devfd;
-        devvp->v_strategy_op = raw_vop_strategy;
-        devvp->v_bwrite_op = raw_vop_bwrite;
-        devvp->v_bmap_op = raw_vop_bmap;
-        LIST_INIT(&devvp->v_cleanblkhd);
-        LIST_INIT(&devvp->v_dirtyblkhd);
-
-	fs = ecalloc(1, sizeof(*fs));
-
-	/* Fill in boot block fields */
-	memcpy(fs->xf_JumpBoot, EXFAT_JUMPBOOT, sizeof(EXFAT_JUMPBOOT));
-	memcpy(fs->xf_FileSystemName, EXFAT_FSNAME, sizeof(EXFAT_FSNAME));
-	/* memset(fs->xf_MustBeZero, 0, sizeof(fs->xf_MustBeZero); */
-	fs->xf_PartitionOffset = partition_offset;
-	fs->xf_VolumeLength = dkw->dkw_size;
-
+	
  	/* The FAT immediately follows the boot blocks */
 	fs->xf_FatOffset = 24;
 	/* and some optional alignment padding */
 	if (fatalign) {
-		uint32_t falignoff = partition_offset % fatalign;
+		uint32_t falignoff = fs->xf_PartitionOffset % fatalign;
 		fs->xf_FatOffset = roundup(fs->xf_FatOffset + falignoff, fatalign);
 	}
+	if (Vflag)
+		printf("FatOffset: 0x%lx (byte 0x%llx)\n",
+		       (unsigned long)fs->xf_FatOffset,
+		       (unsigned long long)fs->xf_FatOffset << fs->xf_BytesPerSectorShift);
 
 	/* Find the total number of "blocks" (clusters) on this volume */
 	/* This is an overestimate, not accounting for the FAT itself */
-	nclust = (dkw->dkw_size - fs->xf_FatOffset) / (bsize / secsize);
+	nclust = (fs->xf_VolumeLength - fs->xf_FatOffset) >> fs->xf_SectorsPerClusterShift;
 
-	if (fatlength == 0)
-		fatlength = howmany((nclust + 2) * sizeof(uint32_t), secsize);
-	else if (nclust > fatlength * secsize / sizeof(uint32_t) - 2)
-		nclust = fatlength * secsize / sizeof(uint32_t) - 2;
-	fs->xf_FatLength = fatlength;
-	fs->xf_ClusterHeapOffset = fs->xf_FatOffset + fs->xf_FatLength;
+	if (fs->xf_FatLength == 0)
+		fs->xf_FatLength = howmany((nclust + 2) * sizeof(uint32_t), secsize);
+	else if (nclust > fs->xf_FatLength * secsize / sizeof(uint32_t) - 2)
+		nclust = fs->xf_FatLength * secsize / sizeof(uint32_t) - 2;
+	fs->xf_ClusterHeapOffset = fs->xf_FatOffset + fs->xf_NumberOfFats * fs->xf_FatLength;
 	if (heapalign) {
-		uint32_t halignoff = partition_offset % heapalign;
+		uint32_t halignoff = fs->xf_PartitionOffset % heapalign;
 		fs->xf_ClusterHeapOffset = roundup(fs->xf_ClusterHeapOffset
 						   + halignoff, heapalign);
 	}
+	if (Vflag) {
+		printf("FatLength: %lx\n",
+			(unsigned long)fs->xf_FatLength);
+		printf("ClusterHeapOffset: 0x%lx (byte 0x%llx)\n",
+		       (unsigned long)fs->xf_ClusterHeapOffset,
+		       (unsigned long long)fs->xf_ClusterHeapOffset << fs->xf_BytesPerSectorShift);
+	}
 
 	/* Recalculate to take FATs into account */
-	nclust = (dkw->dkw_size - fs->xf_ClusterHeapOffset)
-		/ (bsize / secsize);
+	nclust = (fs->xf_VolumeLength - fs->xf_ClusterHeapOffset) >> fs->xf_SectorsPerClusterShift;
 	/* Make sure it fits in our given FAT */
-	if (nclust > fatlength * secsize / sizeof(uint32_t) - 2)
-		nclust = fatlength * secsize / sizeof(uint32_t) - 2;
+	if (nclust > fs->xf_FatLength * secsize / sizeof(uint32_t) - 2)
+		nclust = fs->xf_FatLength * secsize / sizeof(uint32_t) - 2;
 	fs->xf_ClusterCount = nclust;
 	if (Vflag)
 		printf("File system contains %d clusters\n",
 		       (int)fs->xf_ClusterCount);
-	fs->xf_VolumeSerialNumber = serial;
-	fs->xf_FileSystemRevision = EXFAT_GREATEST_VERSION << 8;
-	/* fs->xf_VolumeFlags = 0; */
-	fs->xf_BytesPerSectorShift = bsshift;
-	fs->xf_SectorsPerClusterShift = scshift;
-	fs->xf_NumberOfFats = 1; /* XXX maybe two? */
-	fs->xf_DriveSelect = 0x80; /* An arbitrary value, from the spec */
-	fs->xf_PercentInUse = 0;
-	if (bootcode == NULL)
-		memset(fs->xf_BootCode, 0xf4, sizeof(fs->xf_BootCode));
-	else
-		memcpy(fs->xf_BootCode, bootcode, sizeof(fs->xf_BootCode));
-	fs->xf_BootSignature = EXFAT_BOOT_SIGNATURE;
-
-	if (Vflag)
-		printf("ClusterHeapOffset: 0x%lx (byte 0x%llx)\n",
-		       (unsigned long)fs->xf_ClusterHeapOffset,
-		       (unsigned long long)fs->xf_ClusterHeapOffset << fs->xf_BytesPerSectorShift);
 	
 	/*
 	 * Prepare root directory entries.
@@ -621,6 +198,9 @@ make_exfatfs(int devfd, uint secsize, st
 	 * They will even all fit into a single sector.
 	 */
 
+	/* Keep track of clusters as we allocate them */
+	clust = 2; /* XXX symbol pls */
+
 	/* First root directory entry: Volume Label */
 	memset(&dirent_label, 0, sizeof(dirent_label));
 	dirent_label.xd_entryType = XD_ENTRYTYPE_VOLUME_LABEL
@@ -630,27 +210,26 @@ make_exfatfs(int devfd, uint secsize, st
 
 	/* Second root directory entry: Allocation Bitmap */
 	/* This has cluster data, like a file */
-	memset(&dirent_bitmap, 0, sizeof(dirent_bitmap));
-	dirent_bitmap.xd_entryType = XD_ENTRYTYPE_ALLOC_BITMAP
-		| XD_ENTRYTYPE_INUSE_MASK;
-	dirent_bitmap.xd_bitmapFlags = 0; /* Primary bitmap */
-	dirent_bitmap.xd_firstCluster = 2; /* XXX symbol pls */
-	dirent_bitmap.xd_dataLength = howmany(nclust, NBBY);
-	if (Vflag)
-		printf("First cluster of bitmap region: 0x%lx\n",
-		       (unsigned long)dirent_bitmap.xd_firstCluster);
+	for (bi = 0; bi < fs->xf_NumberOfFats; ++bi) {
+		memset(&dirent_bitmap[bi], 0, sizeof(dirent_bitmap));
+		dirent_bitmap[bi].xd_entryType = XD_ENTRYTYPE_ALLOC_BITMAP
+			| XD_ENTRYTYPE_INUSE_MASK;
+		dirent_bitmap[bi].xd_bitmapFlags = bi; /* Primary bitmap */
+		dirent_bitmap[bi].xd_firstCluster = clust;
+		dirent_bitmap[bi].xd_dataLength = howmany(nclust, NBBY);
+		if (Vflag)
+			printf("First cluster of bitmap region #%d: 0x%lx\n", bi,
+			       (unsigned long)dirent_bitmap[bi].xd_firstCluster);
+		clust += howmany(howmany(nclust, NBBY),
+				 EXFATFS_CSIZE(fs));
+	}
 
-	/* Size of bitmap data, in clusters */
-	bitmap_cluster_size = howmany(dirent_bitmap.xd_dataLength,
-				      EXFATFS_CSIZE(fs));
-	
 	/* Third root directory entry: Up-case Table */
 	/* This too has cluster data, like a file */
 	memset(&dirent_upcase, 0, sizeof(dirent_upcase));
 	dirent_upcase.xd_entryType = XD_ENTRYTYPE_UPCASE_TABLE
 		| XD_ENTRYTYPE_INUSE_MASK;
-	dirent_upcase.xd_firstCluster = dirent_bitmap.xd_firstCluster
-		+ bitmap_cluster_size;
+	dirent_upcase.xd_firstCluster = clust;
 	dirent_upcase.xd_dataLength = uctablesize;
 	dirent_upcase.xd_tableChecksum = 
 		exfatfs_cksum32(0, (uint8_t *)uctable, uctablesize,
@@ -659,8 +238,7 @@ make_exfatfs(int devfd, uint secsize, st
 		printf("First cluster of upcase map: 0x%lx\n",
 		       (unsigned long)dirent_upcase.xd_firstCluster);
 	/* Size of upcase table, in clusters */
-	upcase_cluster_size = howmany(dirent_upcase.xd_dataLength,
-				      EXFATFS_CSIZE(fs));
+	clust += howmany(dirent_upcase.xd_dataLength, EXFATFS_CSIZE(fs));
 
 	/*
 	 * Write the upcase table to disk.
@@ -681,8 +259,7 @@ make_exfatfs(int devfd, uint secsize, st
 		}
 	}
 
-	fs->xf_FirstClusterOfRootDirectory = dirent_upcase.xd_firstCluster
-		+ upcase_cluster_size;
+	fs->xf_FirstClusterOfRootDirectory = clust;
 	if (Vflag)
 		printf("First cluster of root directory: 0x%lx (byte 0x%llx)\n",
 		       (unsigned long)fs->xf_FirstClusterOfRootDirectory,
@@ -693,69 +270,74 @@ make_exfatfs(int devfd, uint secsize, st
 	 * Write the first bitmap sector.
 	 */
 	if (!Nflag) {
-		start = dirent_bitmap.xd_firstCluster;
-		daddr = EXFATFS_LC2D(fs, start);
-		bp = getblk(devvp, daddr, EXFATFS_LSIZE(fs));
-		memset(bp->b_data, 0, EXFATFS_LSIZE(fs));
+		for (bi = 0; bi < fs->xf_NumberOfFats; ++bi) {
+			daddr = EXFATFS_LC2D(fs, dirent_bitmap[bi].xd_firstCluster);
+			bp = getblk(devvp, daddr, EXFATFS_LSIZE(fs));
+			memset(bp->b_data, 0, EXFATFS_LSIZE(fs));
 
-		/* Mark off the clusters we've allocated */
-		for (i = start; i <= fs->xf_FirstClusterOfRootDirectory; i++) {
-			/* It might take more than one bitmap cluster */
-			if ((i - start) == NBBY * EXFATFS_LSIZE(fs)) {
-				if (Vflag)
-					printf(" write used bitmap sector size %d at bn 0x%lx\n",
-			       			EXFATFS_LSIZE(fs), (unsigned long)bp->b_blkno);
-				bwrite(bp);
-				start = i;
-				daddr += EXFATFS_L2D(fs, 1);
-				bp = getblk(devvp, daddr, EXFATFS_LSIZE(fs));
-				memset(bp->b_data, 0, EXFATFS_LSIZE(fs));
+			/* Mark off the clusters we've allocated */
+			start = 2;
+			for (i = start; i <= fs->xf_FirstClusterOfRootDirectory; i++) {
+				/* It might take more than one bitmap cluster */
+				if ((i - start) == NBBY * EXFATFS_LSIZE(fs)) {
+					if (Vflag)
+						printf(" write used bitmap sector size %d at bn 0x%lx\n",
+			       				EXFATFS_LSIZE(fs), (unsigned long)bp->b_blkno);
+					bwrite(bp);
+					start = i;
+					daddr += EXFATFS_L2D(fs, 1);
+					bp = getblk(devvp, daddr, EXFATFS_LSIZE(fs));
+					memset(bp->b_data, 0, EXFATFS_LSIZE(fs));
+				}
+				bit = ((i - start) & (NBBY - 1));
+				byte = (i - start) / NBBY;
+				if (Vflag > 1)
+					printf("  set bit %d byte %d bn 0x%lx for cluster %lld\n", bit, byte, (unsigned long)bp->b_blkno, (long long)i);
+				((char *)bp->b_data)[byte] |= (1 << bit);
 			}
-			bit = ((i - start) & (NBBY - 1));
-			byte = (i - start) / NBBY;
 			if (Vflag)
-				printf("  set bit %d byte %d bn 0x%lx for cluster %lld\n", bit, byte, (unsigned long)bp->b_blkno, (long long)i);
-			((char *)bp->b_data)[byte] |= (1 << bit);
-		}
-		if (Vflag)
-			printf(" write used bitmap sector size %d at bn 0x%lx\n",
-			       EXFATFS_LSIZE(fs), (unsigned long)bp->b_blkno);
-		bwrite(bp);
-	}
+				printf(" write used bitmap sector size %d at bn 0x%lx\n",
+					EXFATFS_LSIZE(fs), (unsigned long)bp->b_blkno);
+			bwrite(bp);
 
-	/* Now write blank pages for the rest of the bitmap */
-	progress = oprogress = 0;
-	start = daddr + EXFATFS_L2D(fs, 1);
-	end = EXFATFS_LC2D(fs, dirent_upcase.xd_firstCluster);
-	for (daddr = start; daddr < end; ++daddr) {
-		if (!Nflag) {
-			size_t size = EXFATFS_LSIZE(fs);
-			if (daddr < EXFATFS_LC2D(fs, fs->xf_FirstClusterOfRootDirectory) - MAXPHYS / EXFATFS_LSIZE(fs))
-				size = MAXPHYS;
-			bp = getblk(devvp, daddr, size);
-			memset(bp->b_data, 0, size);
-			if (Vflag)
-				printf(" write zero bitmap block size %zd at bn 0x%lx\n",
-				       size, (unsigned long)bp->b_blkno);
-			else {
-				progress = 80 * (daddr - start) / (end - start);
-				for (i = oprogress; i < progress; i++) {
-					printf(".");
-					fflush(stdout);
+			/* Now write blank pages for the rest of the bitmap */
+			progress = oprogress = 0;
+			start = daddr + EXFATFS_L2D(fs, 1);
+			if (bi == 0 && fs->xf_NumberOfFats > 0)
+				end = EXFATFS_LC2D(fs, dirent_bitmap[1].xd_firstCluster);
+			else
+				end = EXFATFS_LC2D(fs, dirent_upcase.xd_firstCluster);
+			for (daddr = start; daddr < end; ++daddr) {
+				if (!Nflag) {
+					size_t size = EXFATFS_LSIZE(fs);
+					if (daddr < EXFATFS_LC2D(fs, end) - MAXPHYS / EXFATFS_LSIZE(fs))
+						size = MAXPHYS;
+					bp = getblk(devvp, daddr, size);
+					memset(bp->b_data, 0, size);
+					if (Vflag)
+						printf(" write zero bitmap block size %zd at bn 0x%lx\n",
+				       		size, (unsigned long)bp->b_blkno);
+					else if (!Qflag) {
+						progress = 80 * (daddr - start) / (end - start);
+						for (i = oprogress; i < progress; i++) {
+							printf(".");
+							fflush(stdout);
+						}
+						oprogress = progress;
+					}
+					bwrite(bp);
+					if (size > (size_t)EXFATFS_LSIZE(fs))
+						daddr += size / EXFATFS_LSIZE(fs) - 1;
 				}
-				oprogress = progress;
 			}
-			bwrite(bp);
-			if (size > (size_t)EXFATFS_LSIZE(fs))
-				daddr += size / EXFATFS_LSIZE(fs) - 1;
+			if (!Vflag && !Qflag) {
+				for (i = progress; i < 80; i++)
+					printf(".");
+				fflush(stdout);
+				printf("\n");
+			}
 		}
 	}
-	if (!Vflag) {
-		for (i = progress; i < 80; i++)
-			printf(".");
-		fflush(stdout);
-		printf("\n");
-	}
 
 	/* Write the root directory following the bitmap */
 	daddr = EXFATFS_LC2D(fs, fs->xf_FirstClusterOfRootDirectory);
@@ -767,8 +349,10 @@ make_exfatfs(int devfd, uint secsize, st
 		memcpy(data, &dirent_label, sizeof(dirent_label));
 		data += sizeof(dirent_label);
 
-		memcpy(data, &dirent_bitmap, sizeof(dirent_bitmap));
-		data += sizeof(dirent_bitmap);
+		for (bi = 0; bi < fs->xf_NumberOfFats; ++bi) {
+			memcpy(data, &dirent_bitmap[bi], sizeof(dirent_bitmap[bi]));
+			data += sizeof(dirent_bitmap[bi]);
+		}
 
 		memcpy(data, &dirent_upcase, sizeof(dirent_upcase));
 		
@@ -794,130 +378,81 @@ make_exfatfs(int devfd, uint secsize, st
 	}
 
 	/*
-	 * Write the FAT.
+	 * Write the FAT(s).
 	 */
-	progress = oprogress = 0;
-	end = howmany(fs->xf_ClusterCount, FATBSIZE(fs) / sizeof(uint32_t));
-	for (i = 0; i < end; ++i) {
-		if (!Nflag) {
+	for (bi = 0; bi < fs->xf_NumberOfFats; ++bi) {
+		progress = oprogress = 0;
+		end = howmany(fs->xf_ClusterCount, FATBSIZE(fs) / sizeof(uint32_t));
+		for (i = 0; i < end; ++i) {
+			if (!Nflag) {
 #if 1
-			size_t size = MAXPHYS;
-			if (size > (size_t)(end - i) * FATBSIZE(fs)) {
-				size = (end - i) * FATBSIZE(fs);
-				/* printf(" reset size to %zd for i=%lld\n",
-					size, (long long)i); */
-			}
+				size_t size = MAXPHYS;
+				if (size > (size_t)(end - i) * FATBSIZE(fs)) {
+					size = (end - i) * FATBSIZE(fs);
+					/* printf(" reset size to %zd for i=%lld\n",
+						size, (long long)i); */
+				}
 #else
-			size_t size = FATBSIZE(fs);
-			if (i >= (MAXPHYS / size) && howmany(fs->xf_ClusterCount, FATBSIZE(fs) / sizeof(uint32_t)) - i > (MAXPHYS / size))
-				size = MAXPHYS;
+				size_t size = FATBSIZE(fs);
+				if (i >= (MAXPHYS / size) && howmany(fs->xf_ClusterCount, FATBSIZE(fs) / sizeof(uint32_t)) - i > (MAXPHYS / size))
+					size = MAXPHYS;
 #endif
-			fatspersec = size / sizeof(uint32_t);
-			daddr = (i + fs->xf_FatOffset) * (FATBSIZE(fs) / DEV_BSIZE);
-			bp = getblk(devvp, daddr, size);
-			memset(bp->b_data, 0, size);
-			for (j = 0; j < fatspersec; j++) {
-				uint32_t sec = i * (FATBSIZE(fs) / sizeof(uint32_t)) + j;
-				uint32_t v;
-				
-				if (sec == 0) {
-					v = 0xFFFFFFF8;
-				} else if (sec == dirent_bitmap.xd_firstCluster - 1
-					   || sec == dirent_upcase.xd_firstCluster - 1
-					   || sec == fs->xf_FirstClusterOfRootDirectory - 1
-					   || sec >= fs->xf_FirstClusterOfRootDirectory) {
-					/* No file or end of file */
-					v = 0xFFFFFFFF;
-				} else {
-					v = sec + 1;
+				fatspersec = size / sizeof(uint32_t);
+				daddr = (fs->xf_FatOffset + bi * fs->xf_FatLength + i)
+					* (FATBSIZE(fs) / DEV_BSIZE);
+				bp = getblk(devvp, daddr, size);
+				memset(bp->b_data, 0, size);
+				for (j = 0; j < fatspersec; j++) {
+					uint32_t sec = i * (FATBSIZE(fs) / sizeof(uint32_t)) + j;
+					uint32_t v;
+					
+					if (sec == 0) {
+						v = 0xFFFFFFF8;
+					} else if (sec == dirent_bitmap[0].xd_firstCluster - 1
+						|| sec == dirent_bitmap[fs->xf_NumberOfFats - 1].xd_firstCluster - 1
+					   	|| sec == dirent_upcase.xd_firstCluster - 1
+					   	|| sec == fs->xf_FirstClusterOfRootDirectory - 1
+					   	|| sec >= fs->xf_FirstClusterOfRootDirectory) {
+						/* No file or end of file */
+						v = 0xFFFFFFFF;
+					} else {
+						v = sec + 1;
+					}
+	
+					((uint32_t *)bp->b_data)[j] = v;
 				}
-
-				((uint32_t *)bp->b_data)[j] = v;
-			}
-			if (Vflag) {
-				printf(" write fat sector size %zd at bn 0x%lx\n",
-				       size, (unsigned long)bp->b_blkno);
-			} else {
-				progress = 80 * i / end;
-				for (j = oprogress; j < progress; j++) {
-					printf(".");
-					fflush(stdout);
+				if (Vflag) {
+					printf(" write fat sector size %zd at bn 0x%lx\n",
+				       	size, (unsigned long)bp->b_blkno);
+				} else if (!Qflag) {
+					progress = 80 * i / end;
+					for (j = oprogress; j < progress; j++) {
+						printf(".");
+						fflush(stdout);
+					}
+					oprogress = progress;
 				}
-				oprogress = progress;
+				bwrite(bp);
+				if (size > (size_t)FATBSIZE(fs))
+					i += (size / FATBSIZE(fs)) - 1;
 			}
-			bwrite(bp);
-			if (size > (size_t)FATBSIZE(fs))
-				i += (size / FATBSIZE(fs)) - 1;
 		}
-	}
-	if (!Vflag) {
-		for (i = progress; i < 80; i++)
-			printf(".");
-		fflush(stdout);
-		printf("\n");
+		if (!Vflag && !Qflag) {
+			for (i = progress; i < 80; i++)
+				printf(".");
+			fflush(stdout);
+			printf("\n");
+		}
 	}
 
+	fs->xf_PercentInUse = 100 * (fs->xf_FirstClusterOfRootDirectory - 1)
+		/ (fs->xf_ClusterCount);
+	
 	/*
 	 * Finally, write the boot sector.
 	 */
-	fs->xf_PercentInUse = 100 * (fs->xf_FirstClusterOfRootDirectory - 1)
-		/ (fs->xf_ClusterCount);
-	if (!Nflag) {
-		for (base = 0; base < 24; base += 12) {
-			/* Write superblock to disk */
-			bp = getblk(devvp, base + 0, BSSIZE(fs));
-			memcpy(bp->b_data, &fs->xf_exfatdfs, sizeof(fs->xf_exfatdfs));
-			cksum = exfatfs_cksum32(0, (uint8_t *)bp->b_data,
-						BSSIZE(fs), boot_ignore,
-						sizeof(boot_ignore));
-			if (Vflag)
-				printf(" write boot sector size %d at bn 0x%lx\n",
-		       			BSSIZE(fs), (unsigned long)bp->b_blkno);
-			bwrite(bp);
-			
-			/* Write extended boot sectors */
-			for (i = 1; i < 9; i++) {
-				bp = getblk(devvp, base + i, BSSIZE(fs));
-				memset(bp->b_data, 0, BSSIZE(fs));
-				*(uint32_t *)((char *)bp->b_data
-					      + BSSIZE(fs)
-					      - sizeof(uint32_t))
-					= htole32(0xAA550000);
-				cksum = exfatfs_cksum32(cksum,
-							(uint8_t *)bp->b_data,
-							BSSIZE(fs),
-							NULL, 0);
-				if (Vflag)
-					printf(" write extended boot sector size %d at bn 0x%lx\n",
-		       				BSSIZE(fs), (unsigned long)bp->b_blkno);
-				bwrite(bp);
-			}
-			
-			/* Checksum but do not write OEM and Reserved */
-			for (i = 9; i < 11; i++) {
-				bread(devvp, base + i, BSSIZE(fs), 0, &bp);
-				cksum = exfatfs_cksum32(cksum,
-							(uint8_t *)bp->b_data,
-							BSSIZE(fs),
-							NULL, 0);
-				if (Vflag)
-					printf(" write oem/reserved block size %d at bn 0x%lx\n",
-		       				BSSIZE(fs), (unsigned long)bp->b_blkno);
-				brelse(bp, 0);
-			}
-
-			if (Vflag)
-				printf("Write checksum 0x%lx to sector 0x%.2lx\n",
-				       (unsigned long)cksum,
-				       (unsigned long)(base + i));
-
-			/* Populate checksum block and write it */
-			bp = getblk(devvp, base + i, BSSIZE(fs));
-			for (j = 0; j < BSSIZE(fs) / sizeof(uint32_t); j++)
-				((uint32_t *)bp->b_data)[j] = cksum;
-			bwrite(bp);
-		}
-	}
+	if (!Nflag)
+		exfatfs_write_sb(fs, 1);
 
 	return 0;
 }
@@ -948,3 +483,34 @@ fatal(const char *fmt, ...)
 }
 
 long dev_bsize = DEV_BSIZE;
+
+/*
+ * Compatibility with exfatfs_extern.c
+ */
+int exfatfs_getnewvnode(struct exfatfs *, struct uvnode *,
+                        uint32_t, uint32_t, unsigned,
+                        void *, struct uvnode **);
+
+int
+exfatfs_getnewvnode(struct exfatfs *fs, struct uvnode *dvp,
+		    uint32_t clust, uint32_t off, unsigned type,
+		    void *extra, struct uvnode **vpp)
+{
+        return 0;
+}
+
+int exfatfs_finish_mountfs(struct exfatfs *unused);
+
+int
+exfatfs_finish_mountfs(struct exfatfs *unused)
+{
+	return 0;
+}
+
+int exfatfs_bitmap_init(struct exfatfs *);
+
+int
+exfatfs_bitmap_init(struct exfatfs *unused)
+{
+	return 0;
+}

Index: src/sbin/newfs_exfatfs/newfs.c
diff -u src/sbin/newfs_exfatfs/newfs.c:1.1.2.3 src/sbin/newfs_exfatfs/newfs.c:1.1.2.4
--- src/sbin/newfs_exfatfs/newfs.c:1.1.2.3	Thu Jul 25 23:46:10 2024
+++ src/sbin/newfs_exfatfs/newfs.c	Fri Aug  2 00:23:21 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: newfs.c,v 1.1.2.3 2024/07/25 23:46:10 perseant Exp $	*/
+/*	$NetBSD: newfs.c,v 1.1.2.4 2024/08/02 00:23:21 perseant Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1992, 1993
@@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 19
 #if 0
 static char sccsid[] = "@(#)newfs.c	8.5 (Berkeley) 5/24/95";
 #else
-__RCSID("$NetBSD: newfs.c,v 1.1.2.3 2024/07/25 23:46:10 perseant Exp $");
+__RCSID("$NetBSD: newfs.c,v 1.1.2.4 2024/08/02 00:23:21 perseant Exp $");
 #endif
 #endif /* not lint */
 
@@ -56,8 +56,14 @@ __RCSID("$NetBSD: newfs.c,v 1.1.2.3 2024
 #include <sys/time.h>
 #include <sys/disk.h>
 
+#include "vnode.h"
+#include "bufcache.h"
+
+# define vnode uvnode
+# define buf ubuf
 #include <fs/exfatfs/exfatfs.h>
 #include <fs/exfatfs/exfatfs_conv.h>
+#include <fs/exfatfs/exfatfs_extern.h>
 
 #include <err.h>
 #include <errno.h>
@@ -68,8 +74,8 @@ __RCSID("$NetBSD: newfs.c,v 1.1.2.3 2024
 #include <string.h>
 #include <paths.h>
 #include <util.h>
+#include "defaults.h"
 #include "extern.h"
-#include "bufcache.h"
 #include "partutil.h"
 
 #define MINBLOCKSIZE 4096
@@ -77,7 +83,9 @@ __RCSID("$NetBSD: newfs.c,v 1.1.2.3 2024
 const char lmsg[] = "%s: can't read disk label";
 
 int	Nflag = 0;		/* run without writing file system */
+int	Qflag = 0;		/* quiet */
 int	Vflag = 0;		/* verbose */
+int	Wflag = 0;		/* overwrite */
 uint64_t fssize;		/* file system size */
 uint32_t sectorsize;		/* bytes/sector */
 uint32_t fatalign = 0;		/* fat alignment (sectors) */
@@ -85,7 +93,6 @@ uint32_t csize = 0;		/* block size */
 uint32_t heapalign = 0;		/* cluster heap alignment (sectors) */
 uint32_t serial = 0;
 uint32_t partition_offset = 0;
-uint32_t fatlength = 0;
 
 char	device[MAXPATHLEN];
 char	*progname, *special, *disktype = NULL;
@@ -94,6 +101,7 @@ extern long	dev_bsize;		/* device block 
 
 static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *);
 static void usage(void);
+static struct uvnode *bufcache_init(int);
 
 /* CHUNKSIZE should be larger than MAXPHYS */
 #define CHUNKSIZE (1024 * 1024)
@@ -109,15 +117,17 @@ main(int argc, char **argv)
 	struct disk_geom geo;
 	struct dkwedge_info dkw;
 	struct stat st;
-	int debug, force, fsi, fso, maxpartitions;
-	uint secsize = 0;
+	struct uvnode *devvp;
+	struct exfatfs *fs;
+	int debug, force, fsi, fso, maxpartitions, nfats = 0;
+	uint secsize = 0, secshift = 0;
 	int byte_sized = 0;
 	const char *label = "NONE GIVEN";
 	uint16_t uclabel[11];
 	uint16_t uclabellen;
-	uint64_t diskbytes;
-	char *bootcodefile = NULL, *bootcode = NULL;
-	char *uctablefile = NULL, *uctable = NULL;
+	char *bootcodefile = NULL;
+	char *uctablefile = NULL;
+	uint16_t *uctable = NULL;
 	size_t uctablesize = 0;
 	int r;
 
@@ -132,7 +142,7 @@ main(int argc, char **argv)
 
 	debug = force = 0;
 	memset(&dkw, 0, sizeof(dkw));
-	while ((ch = getopt(argc, argv, "a:b:c:Dh:FL:l:No:S:s:T:u:v#:")) != -1)
+	while ((ch = getopt(argc, argv, "a:b:c:Dh:FL:l:Nn:o:qS:s:T:u:vw#:")) != -1)
 		switch(ch) {
 		case 'D': /* debug */
 			debug = 1;
@@ -146,11 +156,12 @@ main(int argc, char **argv)
 		case 'N': /* dry run */
 			Nflag++;
 			break;
-		case 'S': /* size in sectors */
+		case 'S': /* sector size in bytes */
 		  	secsize = strsuftoi64("sector size", optarg, 1,
 					      INT64_MAX, NULL);
 			if (secsize <= 0 || (secsize & (secsize - 1)))
 				fatal("%s: bad sector size", optarg);
+			secshift = ffs(secsize) - 1;
 			break;
 		case 'T': /* specify disk type XXX */
 			disktype = optarg;
@@ -170,12 +181,18 @@ main(int argc, char **argv)
 		  	heapalign = strsuftoi64("heap alignment", optarg,
 						MINBLOCKSIZE, INT64_MAX, NULL);
 			break;
-		case 'l': /* FAT length in sectors */
-			fatlength = strtoul(optarg, NULL, 10);
+		case 'n': /* number of FATs */
+			nfats = strtol(optarg, NULL, 10);
 			break;
 		case 'o': /* partition offset */
 			partition_offset = strtoul(optarg, NULL, 10);
 			break;
+		case 'q': /* quiet */
+			++Qflag;
+			break;
+		case 'w': /* Overwrite existing superblocks without reading */
+			Wflag = 1;
+			break;
 		case 's': /* size in DEV_BSIZE units */
 		        fssize = strsuftoi64("file system size", optarg,
 					     0, INT64_MAX, &byte_sized);
@@ -187,7 +204,7 @@ main(int argc, char **argv)
 			Vflag++;
 			break;
 		case '#': /* specify serial number */
-			serial = strtoul(optarg, NULL, 10);
+			serial = strtoul(optarg, NULL, 0);
 			break;
 		case '?':
 		default:
@@ -278,81 +295,82 @@ main(int argc, char **argv)
 	/* If force, make the partition look like EXFAT */
 	if (force) {
 		(void)strcpy(dkw.dkw_ptype, DKW_PTYPE_EXFAT); 
-		if (fssize) {
+		if (fssize)
 			dkw.dkw_size = fssize;
+	} else {
+		if (fssize > dkw.dkw_size) {
+			fprintf(stderr, "Requested filesystem size"
+				" %lld does not fit in partition size %lld\n",
+				(long long)fssize, (long long)dkw.dkw_size);
+			exit(1);
 		}
-	} else
-		if (fssize != 0 && fssize < dkw.dkw_size)
+		if (fssize > 0)
 			dkw.dkw_size = fssize;
+	}
 
-	/* If csize not specified, switch based on the partition size */
-	/* This table is based on Windows defaults */
-	diskbytes = dkw.dkw_size * (off_t)dev_bsize;
-	if (csize <= 0) {
-#define KILOBYTE (off_t)1024
-#define MEGABYTE (1024 * KILOBYTE)
-#define GIGABYTE (1024 * MEGABYTE)
-#define TERABYTE (1024 * GIGABYTE)
-#ifdef USE_WINDOWS_DEFAULTS
-		if (diskbytes < 256 * MEGABYTE)
-			csize = 4 * KILOBYTE;
-		else if (diskbytes < 32 * GIGABYTE)
-			csize = 32 * KILOBYTE;
-		else
-			csize = 128 * KILOBYTE;
-		if (Vflag)
-			printf("Using Windows default cluster size %d"
-				" for filesystem size %lld\n",
-				(int)csize, (unsigned long long)diskbytes);
-#else /* SD Association recommendations */
-		if (diskbytes <= 8 * MEGABYTE)
-			csize = 8 * KILOBYTE;
-		else if (diskbytes <= 1 * GIGABYTE)
-			csize = 16 * KILOBYTE;
-		else if (diskbytes <= 128 * GIGABYTE)
-			csize = 32 * KILOBYTE;
-		else if (diskbytes <= 512 * GIGABYTE)
-			csize = 128 * KILOBYTE;
-		else if (diskbytes <= 2 * TERABYTE)
-			csize = 256 * KILOBYTE;
-		else
-			csize = 512 * KILOBYTE;
-		if (Vflag)
-			printf("Using SD Association recommended"
-				" cluster size %d"
-				" for filesystem size %lld\n",
-				(int)csize, (unsigned long long)diskbytes);
-#endif
-	} else {
-		if (Vflag)
-			printf("Using specified cluster size %d", (int)csize);
+	/*
+	 * Read default values from an existing exFAT superblock,
+	 * if there is one; unless we were asked not to.
+	 */
+	devvp = bufcache_init(fso);
+	if (!Wflag) {
+		exfatfs_locate_valid_superblock(devvp, secshift ? secshift : DEV_BSHIFT, &fs);
+		if (Vflag && fs != NULL)
+			printf("Read default values from existing valid boot block\n");
+		/*
+		 * These alignments are not stored directly in the boot sector,
+		 * so if we are copying from an existing filesystem we can't
+		 * be sure what was intended.  Assume that both alignments should
+		 * be powers of two and choose the smallest such alignment.
+		 */
+		if (fatalign == 0 && fs != NULL && fs->xf_FatOffset > 24) {
+			fatalign = 1 << (ffs(fs->xf_FatOffset) - 1);
+		}
+		if (heapalign > 0 && fs != NULL && fs->xf_ClusterHeapOffset > 0) {
+			heapalign = 1 << (ffs(fs->xf_ClusterHeapOffset) - 1);
+		}
 	}
+	/* If there is none, or we were asked to ignore it, start with default values */
+	if (fs == NULL) {
+		fs = default_exfat_sb(&dkw);
+		fatalign = default_fatalign(fs->xf_VolumeLength);
+		heapalign = default_heapalign(fs->xf_VolumeLength);
+	}
+	fs->xf_devvp = devvp;
 
-	if (fatalign <= 0) {
-#ifdef USE_WINDOWS_DEFAULTS
-		fatalign = 0;
-#else /* SD Association recommendations */
-		if (diskbytes <= 8 * MEGABYTE)
-			fatalign = 8 * KILOBYTE;
-		else if (diskbytes <= 64 * MEGABYTE)
-			fatalign = 16 * KILOBYTE;
-		else if (diskbytes <= 256 * MEGABYTE)
-			fatalign = 32 * KILOBYTE;
-		else if (diskbytes <= 2 * GIGABYTE)
-			fatalign = 64 * KILOBYTE;
-		else if (diskbytes <= 32 * GIGABYTE)
-			fatalign = 4 * MEGABYTE;
-		else if (diskbytes <= 128 * GIGABYTE)
-			fatalign = 16 * MEGABYTE;
-		else if (diskbytes <= 512 * GIGABYTE)
-			fatalign = 32 * MEGABYTE;
-		else
-			fatalign = 64 * MEGABYTE;
-#endif
+	/*
+	 * Apply values from arguments
+	 */
+	if (sectorsize > 0) {
+		if (secshift < 9 || secshift > 12) {
+			fprintf(stderr, "Sector size %d is out of range\n",
+				(int)sectorsize);
+			exit(1);
+		}
+		if (secshift != fs->xf_BytesPerSectorShift) {
+			int shiftdiff = secshift - fs->xf_BytesPerSectorShift;
+			fs->xf_BytesPerSectorShift = secshift;
+			fs->xf_SectorsPerClusterShift -= shiftdiff;
+			fs->xf_PartitionOffset >>= shiftdiff;
+			fs->xf_FatOffset >>= shiftdiff;
+			fs->xf_ClusterHeapOffset >>= shiftdiff;
+		}
+	}
+	if (csize > 0) {
+		int cshift = ffs(csize) - 1 - fs->xf_BytesPerSectorShift;
+		if (cshift < 0 || cshift > 25 - fs->xf_BytesPerSectorShift) {
+			fprintf(stderr, "Cluster size %d is out of range\n",
+				(int)csize);
+			exit(1);
+		}
+		fs->xf_SectorsPerClusterShift = cshift;
 	}
-	/* Convert to sectors */
-	fatalign /= secsize;
-	heapalign /= secsize;
+	if (partition_offset > 0)
+		fs->xf_PartitionOffset = partition_offset;
+	if (nfats > 0)
+		fs->xf_NumberOfFats = nfats;
+	if (serial != 0)
+		fs->xf_VolumeSerialNumber = serial;
 
 	/* Convert given label from UTF8 into UCS2 */
 	uclabellen = exfatfs_utf8ucs2str((const uint8_t *)label,
@@ -361,9 +379,8 @@ main(int argc, char **argv)
 
 	/* Load bootcode from file if requested */
 	if (bootcodefile != NULL) {
-		bootcode = (char *)malloc(390);
 		FILE *fp = fopen(bootcodefile, "rb");
-		if (fp == NULL || fread(bootcode, 390, 1, fp) != 1) {
+		if (fp == NULL || fread(fs->xf_BootCode, EXFATFS_BOOTCODE_SIZE, 1, fp) != 1) {
 			perror(bootcodefile);
 			exit(1);
 		}
@@ -378,24 +395,67 @@ main(int argc, char **argv)
 			exit(1);
 		}
 		uctablesize = st.st_size;
-		uctable = malloc(uctablesize);
+		uctable = (uint16_t *)malloc(uctablesize);
 		fp = fopen(uctablefile, "rb");
 		if (fp == NULL || fread(uctable, uctablesize, 1, fp) != 1) {
 			perror(uctablefile);
 			exit(1);
 		}
 		fclose(fp);
+		if (uctablesize < 28 * sizeof(uint16_t)) {
+			fprintf(stderr, "Upcase table size %d too small\n",
+				(int)uctablesize);
+			exit(1);
+		}
+	} else {
+		default_upcase_table(&uctable, &uctablesize);
 	}
-
+	
 	/* Make the filesystem */
-	r = make_exfatfs(fso, secsize, &dkw, csize,
-			 uclabel, uclabellen, serial,
-			 (uint16_t *)uctable, uctablesize, bootcode);
+	r = make_exfatfs(devvp, fs, uclabel, uclabellen,
+			 uctable, uctablesize,
+			 fatalign, heapalign);
+
 	if (debug)
 		bufstats();
 	exit(r);
 }
 
+/*
+ * Error function for buffer cache errors
+ */
+static void
+efun(int eval, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	verr(1, fmt, ap);
+	va_end(ap);
+}
+
+/*
+ * Initialize buffer cache.
+ */
+static struct uvnode *
+bufcache_init(int devfd)
+{
+	struct uvnode *devvp;
+
+	vfs_init();
+	bufinit(17); /* XXX arbitrary magic 17 */
+	esetfunc(efun);
+	devvp = ecalloc(1, sizeof(*devvp));
+	devvp->v_fs = NULL;
+	devvp->v_fd = devfd;
+	devvp->v_strategy_op = raw_vop_strategy;
+	devvp->v_bwrite_op = raw_vop_bwrite;
+	devvp->v_bmap_op = raw_vop_bmap;
+	LIST_INIT(&devvp->v_cleanblkhd);
+	LIST_INIT(&devvp->v_dirtyblkhd);
+
+	return devvp;
+}
+
 static int64_t
 strsuftoi64(const char *desc, const char *arg, int64_t min, int64_t max, int *num_suffix)
 {
@@ -403,6 +463,13 @@ strsuftoi64(const char *desc, const char
 	int shift = 0;
 	char	*ep;
 
+	/* Allow input in hex, without suffix, as well */
+	if (arg[0] == '0' && arg[1] == 'x') {
+		if (num_suffix != NULL)
+			*num_suffix = 0;
+		return strtoll(arg, &ep, 0);
+	}
+
 	errno = 0;
 	r1 = strtoll(arg, &ep, 10);
 	if (ep[0] != '\0' && ep[1] != '\0')
@@ -441,7 +508,7 @@ strsuftoi64(const char *desc, const char
 	return result;
 }
 
-void
+static void
 usage(void)
 {
 	fprintf(stderr, "usage: newfs_exfatfs [ -fsoptions ] special-device\n");
@@ -450,15 +517,14 @@ usage(void)
 	fprintf(stderr, "\t-D (debug)\n");
 	fprintf(stderr, "\t-F (force)\n");
 	fprintf(stderr, "\t-L label\n");
-	fprintf(stderr,
-	    "\t-N (do not create file system, just print out parameters)\n");
+	fprintf(stderr, "\t-N (do not create file system)\n");
 	fprintf(stderr, "\t-S sector size\n");
 	fprintf(stderr, "\t-T disk type\n");
 	fprintf(stderr, "\t-a FAT alignment in bytes\n");
 	fprintf(stderr, "\t-b bootcode file\n");
 	fprintf(stderr, "\t-c cluster size in bytes\n");
 	fprintf(stderr, "\t-h cluster heap alignment in bytes\n");
-	fprintf(stderr, "\t-l FAT length in sectors\n");
+	fprintf(stderr, "\t-n number of FATs (1 or 2)\n");
 	fprintf(stderr, "\t-o partition offset in sectors\n");
 	fprintf(stderr, "\t-s file system size in sectors\n");
 	fprintf(stderr, "\t-u upcase table file\n");

Added files:

Index: src/sbin/newfs_exfatfs/defaults.c
diff -u /dev/null src/sbin/newfs_exfatfs/defaults.c:1.1.2.1
--- /dev/null	Fri Aug  2 00:23:21 2024
+++ src/sbin/newfs_exfatfs/defaults.c	Fri Aug  2 00:23:20 2024
@@ -0,0 +1,543 @@
+/* $NetBSD: defaults.c,v 1.1.2.1 2024/08/02 00:23:20 perseant Exp $ */
+
+/*-
+ * Copyright (c) 2022, 2024 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#ifndef lint
+__RCSID("$NetBSD: defaults.c,v 1.1.2.1 2024/08/02 00:23:20 perseant Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/disk.h>
+
+#include <fs/exfatfs/exfatfs.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <util.h>
+
+#include "defaults.h"
+
+static uint16_t exfatfs_recommended_upcase_table_compressed[] = {
+	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+	0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+	0x0058, 0x0059, 0x005A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+	0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+	0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+	0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+	0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+	0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+	0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+	0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+	0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+	0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+	0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+	0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+	0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+	0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
+	0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+	0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00F7,
+	0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x0178,
+	0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106,
+	0x0108, 0x0108, 0x010A, 0x010A, 0x010C, 0x010C, 0x010E, 0x010E,
+	0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116,
+	0x0118, 0x0118, 0x011A, 0x011A, 0x011C, 0x011C, 0x011E, 0x011E,
+	0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126,
+	0x0128, 0x0128, 0x012A, 0x012A, 0x012C, 0x012C, 0x012E, 0x012E,
+	0x0130, 0x0131, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136,
+	0x0138, 0x0139, 0x0139, 0x013B, 0x013B, 0x013D, 0x013D, 0x013F,
+	0x013F, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147,
+	0x0147, 0x0149, 0x014A, 0x014A, 0x014C, 0x014C, 0x014E, 0x014E,
+	0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156,
+	0x0158, 0x0158, 0x015A, 0x015A, 0x015C, 0x015C, 0x015E, 0x015E,
+	0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166,
+	0x0168, 0x0168, 0x016A, 0x016A, 0x016C, 0x016C, 0x016E, 0x016E,
+	0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176,
+	0x0178, 0x0179, 0x0179, 0x017B, 0x017B, 0x017D, 0x017D, 0x017F,
+	0x0243, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
+	0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,
+	0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197,
+	0x0198, 0x0198, 0x023D, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F,
+	0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,
+	0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,
+	0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,
+	0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7,
+	0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C5, 0x01C4, 0x01C7,
+	0x01C8, 0x01C7, 0x01CA, 0x01CB, 0x01CA, 0x01CD, 0x01CD, 0x01CF,
+	0x01CF, 0x01D1, 0x01D1, 0x01D3, 0x01D3, 0x01D5, 0x01D5, 0x01D7,
+	0x01D7, 0x01D9, 0x01D9, 0x01DB, 0x01DB, 0x018E, 0x01DE, 0x01DE,
+	0x01E0, 0x01E0, 0x01E2, 0x01E2, 0x01E4, 0x01E4, 0x01E6, 0x01E6,
+	0x01E8, 0x01E8, 0x01EA, 0x01EA, 0x01EC, 0x01EC, 0x01EE, 0x01EE,
+	0x01F0, 0x01F1, 0x01F2, 0x01F1, 0x01F4, 0x01F4, 0x01F6, 0x01F7,
+	0x01F8, 0x01F8, 0x01FA, 0x01FA, 0x01FC, 0x01FC, 0x01FE, 0x01FE,
+	0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206,
+	0x0208, 0x0208, 0x020A, 0x020A, 0x020C, 0x020C, 0x020E, 0x020E,
+	0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216,
+	0x0218, 0x0218, 0x021A, 0x021A, 0x021C, 0x021C, 0x021E, 0x021E,
+	0x0220, 0x0221, 0x0222, 0x0222, 0x0224, 0x0224, 0x0226, 0x0226,
+	0x0228, 0x0228, 0x022A, 0x022A, 0x022C, 0x022C, 0x022E, 0x022E,
+	0x0230, 0x0230, 0x0232, 0x0232, 0x0234, 0x0235, 0x0236, 0x0237,
+	0x0238, 0x0239, 0x2C65, 0x023B, 0x023B, 0x023D, 0x2C66, 0x023F,
+	0x0240, 0x0241, 0x0241, 0x0243, 0x0244, 0x0245, 0x0246, 0x0246,
+	0x0248, 0x0248, 0x024A, 0x024A, 0x024C, 0x024C, 0x024E, 0x024E,
+	0x0250, 0x0251, 0x0252, 0x0181, 0x0186, 0x0255, 0x0189, 0x018A,
+	0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,
+	0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
+	0x0197, 0x0196, 0x026A, 0x2C62, 0x026C, 0x026D, 0x026E, 0x019C,
+	0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277,
+	0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x2C64, 0x027E, 0x027F,
+	0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,
+	0x01AE, 0x0244, 0x01B1, 0x01B2, 0x0245, 0x028D, 0x028E, 0x028F,
+	0x0290, 0x0291, 0x01B7, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297,
+	0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F,
+	0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7,
+	0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, 0x02AD, 0x02AE, 0x02AF,
+	0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6, 0x02B7,
+	0x02B8, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF,
+	0x02C0, 0x02C1, 0x02C2, 0x02C3, 0x02C4, 0x02C5, 0x02C6, 0x02C7,
+	0x02C8, 0x02C9, 0x02CA, 0x02CB, 0x02CC, 0x02CD, 0x02CE, 0x02CF,
+	0x02D0, 0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7,
+	0x02D8, 0x02D9, 0x02DA, 0x02DB, 0x02DC, 0x02DD, 0x02DE, 0x02DF,
+	0x02E0, 0x02E1, 0x02E2, 0x02E3, 0x02E4, 0x02E5, 0x02E6, 0x02E7,
+	0x02E8, 0x02E9, 0x02EA, 0x02EB, 0x02EC, 0x02ED, 0x02EE, 0x02EF,
+	0x02F0, 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, 0x02F7,
+	0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, 0x02FD, 0x02FE, 0x02FF,
+	0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
+	0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
+	0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
+	0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F,
+	0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
+	0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F,
+	0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
+	0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F,
+	0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
+	0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F,
+	0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
+	0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F,
+	0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
+	0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F,
+	0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
+	0x0378, 0x0379, 0x037A, 0x03FD, 0x03FE, 0x03FF, 0x037E, 0x037F,
+	0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,
+	0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,
+	0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+	0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+	0x03A0, 0x03A1, 0x03A2, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
+	0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,
+	0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+	0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+	0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
+	0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x03CF,
+	0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
+	0x03D8, 0x03D8, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE,
+	0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6,
+	0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,
+	0x03F0, 0x03F1, 0x03F9, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,
+	0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x03FC, 0x03FD, 0x03FE, 0x03FF,
+	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+	0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F,
+	0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+	0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+	0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+	0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+	0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+	0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
+	0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+	0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+	0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F,
+	0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466,
+	0x0468, 0x0468, 0x046A, 0x046A, 0x046C, 0x046C, 0x046E, 0x046E,
+	0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476,
+	0x0478, 0x0478, 0x047A, 0x047A, 0x047C, 0x047C, 0x047E, 0x047E,
+	0x0480, 0x0480, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
+	0x0488, 0x0489, 0x048A, 0x048A, 0x048C, 0x048C, 0x048E, 0x048E,
+	0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496,
+	0x0498, 0x0498, 0x049A, 0x049A, 0x049C, 0x049C, 0x049E, 0x049E,
+	0x04A0, 0x04A0, 0x04A2, 0x04A2, 0x04A4, 0x04A4, 0x04A6, 0x04A6,
+	0x04A8, 0x04A8, 0x04AA, 0x04AA, 0x04AC, 0x04AC, 0x04AE, 0x04AE,
+	0x04B0, 0x04B0, 0x04B2, 0x04B2, 0x04B4, 0x04B4, 0x04B6, 0x04B6,
+	0x04B8, 0x04B8, 0x04BA, 0x04BA, 0x04BC, 0x04BC, 0x04BE, 0x04BE,
+	0x04C0, 0x04C1, 0x04C1, 0x04C3, 0x04C3, 0x04C5, 0x04C5, 0x04C7,
+	0x04C7, 0x04C9, 0x04C9, 0x04CB, 0x04CB, 0x04CD, 0x04CD, 0x04C0,
+	0x04D0, 0x04D0, 0x04D2, 0x04D2, 0x04D4, 0x04D4, 0x04D6, 0x04D6,
+	0x04D8, 0x04D8, 0x04DA, 0x04DA, 0x04DC, 0x04DC, 0x04DE, 0x04DE,
+	0x04E0, 0x04E0, 0x04E2, 0x04E2, 0x04E4, 0x04E4, 0x04E6, 0x04E6,
+	0x04E8, 0x04E8, 0x04EA, 0x04EA, 0x04EC, 0x04EC, 0x04EE, 0x04EE,
+	0x04F0, 0x04F0, 0x04F2, 0x04F2, 0x04F4, 0x04F4, 0x04F6, 0x04F6,
+	0x04F8, 0x04F8, 0x04FA, 0x04FA, 0x04FC, 0x04FC, 0x04FE, 0x04FE,
+	0x0500, 0x0500, 0x0502, 0x0502, 0x0504, 0x0504, 0x0506, 0x0506,
+	0x0508, 0x0508, 0x050A, 0x050A, 0x050C, 0x050C, 0x050E, 0x050E,
+	0x0510, 0x0510, 0x0512, 0x0512, 0x0514, 0x0515, 0x0516, 0x0517,
+	0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,
+	0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
+	0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,
+	0x0530, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
+	0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F,
+	0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
+	0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F,
+	0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0557,
+	0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,
+	0x0560, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
+	0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F,
+	0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
+	0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F,
+	0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0xFFFF,
+	0x17F6, 0x2C63, 0x1D7E, 0x1D7F, 0x1D80, 0x1D81, 0x1D82, 0x1D83,
+	0x1D84, 0x1D85, 0x1D86, 0x1D87, 0x1D88, 0x1D89, 0x1D8A, 0x1D8B,
+	0x1D8C, 0x1D8D, 0x1D8E, 0x1D8F, 0x1D90, 0x1D91, 0x1D92, 0x1D93,
+	0x1D94, 0x1D95, 0x1D96, 0x1D97, 0x1D98, 0x1D99, 0x1D9A, 0x1D9B,
+	0x1D9C, 0x1D9D, 0x1D9E, 0x1D9F, 0x1DA0, 0x1DA1, 0x1DA2, 0x1DA3,
+	0x1DA4, 0x1DA5, 0x1DA6, 0x1DA7, 0x1DA8, 0x1DA9, 0x1DAA, 0x1DAB,
+	0x1DAC, 0x1DAD, 0x1DAE, 0x1DAF, 0x1DB0, 0x1DB1, 0x1DB2, 0x1DB3,
+	0x1DB4, 0x1DB5, 0x1DB6, 0x1DB7, 0x1DB8, 0x1DB9, 0x1DBA, 0x1DBB,
+	0x1DBC, 0x1DBD, 0x1DBE, 0x1DBF, 0x1DC0, 0x1DC1, 0x1DC2, 0x1DC3,
+	0x1DC4, 0x1DC5, 0x1DC6, 0x1DC7, 0x1DC8, 0x1DC9, 0x1DCA, 0x1DCB,
+	0x1DCC, 0x1DCD, 0x1DCE, 0x1DCF, 0x1DD0, 0x1DD1, 0x1DD2, 0x1DD3,
+	0x1DD4, 0x1DD5, 0x1DD6, 0x1DD7, 0x1DD8, 0x1DD9, 0x1DDA, 0x1DDB,
+	0x1DDC, 0x1DDD, 0x1DDE, 0x1DDF, 0x1DE0, 0x1DE1, 0x1DE2, 0x1DE3,
+	0x1DE4, 0x1DE5, 0x1DE6, 0x1DE7, 0x1DE8, 0x1DE9, 0x1DEA, 0x1DEB,
+	0x1DEC, 0x1DED, 0x1DEE, 0x1DEF, 0x1DF0, 0x1DF1, 0x1DF2, 0x1DF3,
+	0x1DF4, 0x1DF5, 0x1DF6, 0x1DF7, 0x1DF8, 0x1DF9, 0x1DFA, 0x1DFB,
+	0x1DFC, 0x1DFD, 0x1DFE, 0x1DFF, 0x1E00, 0x1E00, 0x1E02, 0x1E02,
+	0x1E04, 0x1E04, 0x1E06, 0x1E06, 0x1E08, 0x1E08, 0x1E0A, 0x1E0A,
+	0x1E0C, 0x1E0C, 0x1E0E, 0x1E0E, 0x1E10, 0x1E10, 0x1E12, 0x1E12,
+	0x1E14, 0x1E14, 0x1E16, 0x1E16, 0x1E18, 0x1E18, 0x1E1A, 0x1E1A,
+	0x1E1C, 0x1E1C, 0x1E1E, 0x1E1E, 0x1E20, 0x1E20, 0x1E22, 0x1E22,
+	0x1E24, 0x1E24, 0x1E26, 0x1E26, 0x1E28, 0x1E28, 0x1E2A, 0x1E2A,
+	0x1E2C, 0x1E2C, 0x1E2E, 0x1E2E, 0x1E30, 0x1E30, 0x1E32, 0x1E32,
+	0x1E34, 0x1E34, 0x1E36, 0x1E36, 0x1E38, 0x1E38, 0x1E3A, 0x1E3A,
+	0x1E3C, 0x1E3C, 0x1E3E, 0x1E3E, 0x1E40, 0x1E40, 0x1E42, 0x1E42,
+	0x1E44, 0x1E44, 0x1E46, 0x1E46, 0x1E48, 0x1E48, 0x1E4A, 0x1E4A,
+	0x1E4C, 0x1E4C, 0x1E4E, 0x1E4E, 0x1E50, 0x1E50, 0x1E52, 0x1E52,
+	0x1E54, 0x1E54, 0x1E56, 0x1E56, 0x1E58, 0x1E58, 0x1E5A, 0x1E5A,
+	0x1E5C, 0x1E5C, 0x1E5E, 0x1E5E, 0x1E60, 0x1E60, 0x1E62, 0x1E62,
+	0x1E64, 0x1E64, 0x1E66, 0x1E66, 0x1E68, 0x1E68, 0x1E6A, 0x1E6A,
+	0x1E6C, 0x1E6C, 0x1E6E, 0x1E6E, 0x1E70, 0x1E70, 0x1E72, 0x1E72,
+	0x1E74, 0x1E74, 0x1E76, 0x1E76, 0x1E78, 0x1E78, 0x1E7A, 0x1E7A,
+	0x1E7C, 0x1E7C, 0x1E7E, 0x1E7E, 0x1E80, 0x1E80, 0x1E82, 0x1E82,
+	0x1E84, 0x1E84, 0x1E86, 0x1E86, 0x1E88, 0x1E88, 0x1E8A, 0x1E8A,
+	0x1E8C, 0x1E8C, 0x1E8E, 0x1E8E, 0x1E90, 0x1E90, 0x1E92, 0x1E92,
+	0x1E94, 0x1E94, 0x1E96, 0x1E97, 0x1E98, 0x1E99, 0x1E9A, 0x1E9B,
+	0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F, 0x1EA0, 0x1EA0, 0x1EA2, 0x1EA2,
+	0x1EA4, 0x1EA4, 0x1EA6, 0x1EA6, 0x1EA8, 0x1EA8, 0x1EAA, 0x1EAA,
+	0x1EAC, 0x1EAC, 0x1EAE, 0x1EAE, 0x1EB0, 0x1EB0, 0x1EB2, 0x1EB2,
+	0x1EB4, 0x1EB4, 0x1EB6, 0x1EB6, 0x1EB8, 0x1EB8, 0x1EBA, 0x1EBA,
+	0x1EBC, 0x1EBC, 0x1EBE, 0x1EBE, 0x1EC0, 0x1EC0, 0x1EC2, 0x1EC2,
+	0x1EC4, 0x1EC4, 0x1EC6, 0x1EC6, 0x1EC8, 0x1EC8, 0x1ECA, 0x1ECA,
+	0x1ECC, 0x1ECC, 0x1ECE, 0x1ECE, 0x1ED0, 0x1ED0, 0x1ED2, 0x1ED2,
+	0x1ED4, 0x1ED4, 0x1ED6, 0x1ED6, 0x1ED8, 0x1ED8, 0x1EDA, 0x1EDA,
+	0x1EDC, 0x1EDC, 0x1EDE, 0x1EDE, 0x1EE0, 0x1EE0, 0x1EE2, 0x1EE2,
+	0x1EE4, 0x1EE4, 0x1EE6, 0x1EE6, 0x1EE8, 0x1EE8, 0x1EEA, 0x1EEA,
+	0x1EEC, 0x1EEC, 0x1EEE, 0x1EEE, 0x1EF0, 0x1EF0, 0x1EF2, 0x1EF2,
+	0x1EF4, 0x1EF4, 0x1EF6, 0x1EF6, 0x1EF8, 0x1EF8, 0x1EFA, 0x1EFB,
+	0x1EFC, 0x1EFD, 0x1EFE, 0x1EFF, 0x1F08, 0x1F09, 0x1F0A, 0x1F0B,
+	0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, 0x1F08, 0x1F09, 0x1F0A, 0x1F0B,
+	0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, 0x1F18, 0x1F19, 0x1F1A, 0x1F1B,
+	0x1F1C, 0x1F1D, 0x1F16, 0x1F17, 0x1F18, 0x1F19, 0x1F1A, 0x1F1B,
+	0x1F1C, 0x1F1D, 0x1F1E, 0x1F1F, 0x1F28, 0x1F29, 0x1F2A, 0x1F2B,
+	0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 0x1F28, 0x1F29, 0x1F2A, 0x1F2B,
+	0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 0x1F38, 0x1F39, 0x1F3A, 0x1F3B,
+	0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, 0x1F38, 0x1F39, 0x1F3A, 0x1F3B,
+	0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, 0x1F48, 0x1F49, 0x1F4A, 0x1F4B,
+	0x1F4C, 0x1F4D, 0x1F46, 0x1F47, 0x1F48, 0x1F49, 0x1F4A, 0x1F4B,
+	0x1F4C, 0x1F4D, 0x1F4E, 0x1F4F, 0x1F50, 0x1F59, 0x1F52, 0x1F5B,
+	0x1F54, 0x1F5D, 0x1F56, 0x1F5F, 0x1F58, 0x1F59, 0x1F5A, 0x1F5B,
+	0x1F5C, 0x1F5D, 0x1F5E, 0x1F5F, 0x1F68, 0x1F69, 0x1F6A, 0x1F6B,
+	0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, 0x1F68, 0x1F69, 0x1F6A, 0x1F6B,
+	0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9,
+	0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB, 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB,
+	0x1FFA, 0x1FFB, 0x1F7E, 0x1F7F, 0x1F88, 0x1F89, 0x1F8A, 0x1F8B,
+	0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, 0x1F88, 0x1F89, 0x1F8A, 0x1F8B,
+	0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, 0x1F98, 0x1F99, 0x1F9A, 0x1F9B,
+	0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, 0x1F98, 0x1F99, 0x1F9A, 0x1F9B,
+	0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB,
+	0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB,
+	0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, 0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC,
+	0x1FB4, 0x1FB5, 0x1FB6, 0x1FB7, 0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB,
+	0x1FBC, 0x1FBD, 0x1FBE, 0x1FBF, 0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3,
+	0x1FC4, 0x1FC5, 0x1FC6, 0x1FC7, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB,
+	0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF, 0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3,
+	0x1FD4, 0x1FD5, 0x1FD6, 0x1FD7, 0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB,
+	0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF, 0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3,
+	0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7, 0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB,
+	0x1FEC, 0x1FED, 0x1FEE, 0x1FEF, 0x1FF0, 0x1FF1, 0x1FF2, 0x1FF3,
+	0x1FF4, 0x1FF5, 0x1FF6, 0x1FF7, 0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB,
+	0x1FF3, 0x1FFD, 0x1FFE, 0x1FFF, 0x2000, 0x2001, 0x2002, 0x2003,
+	0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B,
+	0x200C, 0x200D, 0x200E, 0x200F, 0x2010, 0x2011, 0x2012, 0x2013,
+	0x2014, 0x2015, 0x2016, 0x2017, 0x2018, 0x2019, 0x201A, 0x201B,
+	0x201C, 0x201D, 0x201E, 0x201F, 0x2020, 0x2021, 0x2022, 0x2023,
+	0x2024, 0x2025, 0x2026, 0x2027, 0x2028, 0x2029, 0x202A, 0x202B,
+	0x202C, 0x202D, 0x202E, 0x202F, 0x2030, 0x2031, 0x2032, 0x2033,
+	0x2034, 0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203A, 0x203B,
+	0x203C, 0x203D, 0x203E, 0x203F, 0x2040, 0x2041, 0x2042, 0x2043,
+	0x2044, 0x2045, 0x2046, 0x2047, 0x2048, 0x2049, 0x204A, 0x204B,
+	0x204C, 0x204D, 0x204E, 0x204F, 0x2050, 0x2051, 0x2052, 0x2053,
+	0x2054, 0x2055, 0x2056, 0x2057, 0x2058, 0x2059, 0x205A, 0x205B,
+	0x205C, 0x205D, 0x205E, 0x205F, 0x2060, 0x2061, 0x2062, 0x2063,
+	0x2064, 0x2065, 0x2066, 0x2067, 0x2068, 0x2069, 0x206A, 0x206B,
+	0x206C, 0x206D, 0x206E, 0x206F, 0x2070, 0x2071, 0x2072, 0x2073,
+	0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079, 0x207A, 0x207B,
+	0x207C, 0x207D, 0x207E, 0x207F, 0x2080, 0x2081, 0x2082, 0x2083,
+	0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208A, 0x208B,
+	0x208C, 0x208D, 0x208E, 0x208F, 0x2090, 0x2091, 0x2092, 0x2093,
+	0x2094, 0x2095, 0x2096, 0x2097, 0x2098, 0x2099, 0x209A, 0x209B,
+	0x209C, 0x209D, 0x209E, 0x209F, 0x20A0, 0x20A1, 0x20A2, 0x20A3,
+	0x20A4, 0x20A5, 0x20A6, 0x20A7, 0x20A8, 0x20A9, 0x20AA, 0x20AB,
+	0x20AC, 0x20AD, 0x20AE, 0x20AF, 0x20B0, 0x20B1, 0x20B2, 0x20B3,
+	0x20B4, 0x20B5, 0x20B6, 0x20B7, 0x20B8, 0x20B9, 0x20BA, 0x20BB,
+	0x20BC, 0x20BD, 0x20BE, 0x20BF, 0x20C0, 0x20C1, 0x20C2, 0x20C3,
+	0x20C4, 0x20C5, 0x20C6, 0x20C7, 0x20C8, 0x20C9, 0x20CA, 0x20CB,
+	0x20CC, 0x20CD, 0x20CE, 0x20CF, 0x20D0, 0x20D1, 0x20D2, 0x20D3,
+	0x20D4, 0x20D5, 0x20D6, 0x20D7, 0x20D8, 0x20D9, 0x20DA, 0x20DB,
+	0x20DC, 0x20DD, 0x20DE, 0x20DF, 0x20E0, 0x20E1, 0x20E2, 0x20E3,
+	0x20E4, 0x20E5, 0x20E6, 0x20E7, 0x20E8, 0x20E9, 0x20EA, 0x20EB,
+	0x20EC, 0x20ED, 0x20EE, 0x20EF, 0x20F0, 0x20F1, 0x20F2, 0x20F3,
+	0x20F4, 0x20F5, 0x20F6, 0x20F7, 0x20F8, 0x20F9, 0x20FA, 0x20FB,
+	0x20FC, 0x20FD, 0x20FE, 0x20FF, 0x2100, 0x2101, 0x2102, 0x2103,
+	0x2104, 0x2105, 0x2106, 0x2107, 0x2108, 0x2109, 0x210A, 0x210B,
+	0x210C, 0x210D, 0x210E, 0x210F, 0x2110, 0x2111, 0x2112, 0x2113,
+	0x2114, 0x2115, 0x2116, 0x2117, 0x2118, 0x2119, 0x211A, 0x211B,
+	0x211C, 0x211D, 0x211E, 0x211F, 0x2120, 0x2121, 0x2122, 0x2123,
+	0x2124, 0x2125, 0x2126, 0x2127, 0x2128, 0x2129, 0x212A, 0x212B,
+	0x212C, 0x212D, 0x212E, 0x212F, 0x2130, 0x2131, 0x2132, 0x2133,
+	0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213A, 0x213B,
+	0x213C, 0x213D, 0x213E, 0x213F, 0x2140, 0x2141, 0x2142, 0x2143,
+	0x2144, 0x2145, 0x2146, 0x2147, 0x2148, 0x2149, 0x214A, 0x214B,
+	0x214C, 0x214D, 0x2132, 0x214F, 0x2150, 0x2151, 0x2152, 0x2153,
+	0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215A, 0x215B,
+	0x215C, 0x215D, 0x215E, 0x215F, 0x2160, 0x2161, 0x2162, 0x2163,
+	0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B,
+	0x216C, 0x216D, 0x216E, 0x216F, 0x2160, 0x2161, 0x2162, 0x2163,
+	0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B,
+	0x216C, 0x216D, 0x216E, 0x216F, 0x2180, 0x2181, 0x2182, 0x2183,
+	0x2183, 0xFFFF, 0x034B, 0x24B6, 0x24B7, 0x24B8, 0x24B9, 0x24BA,
+	0x24BB, 0x24BC, 0x24BD, 0x24BE, 0x24BF, 0x24C0, 0x24C1, 0x24C2,
+	0x24C3, 0x24C4, 0x24C5, 0x24C6, 0x24C7, 0x24C8, 0x24C9, 0x24CA,
+	0x24CB, 0x24CC, 0x24CD, 0x24CE, 0x24CF, 0xFFFF, 0x0746, 0x2C00,
+	0x2C01, 0x2C02, 0x2C03, 0x2C04, 0x2C05, 0x2C06, 0x2C07, 0x2C08,
+	0x2C09, 0x2C0A, 0x2C0B, 0x2C0C, 0x2C0D, 0x2C0E, 0x2C0F, 0x2C10,
+	0x2C11, 0x2C12, 0x2C13, 0x2C14, 0x2C15, 0x2C16, 0x2C17, 0x2C18,
+	0x2C19, 0x2C1A, 0x2C1B, 0x2C1C, 0x2C1D, 0x2C1E, 0x2C1F, 0x2C20,
+	0x2C21, 0x2C22, 0x2C23, 0x2C24, 0x2C25, 0x2C26, 0x2C27, 0x2C28,
+	0x2C29, 0x2C2A, 0x2C2B, 0x2C2C, 0x2C2D, 0x2C2E, 0x2C5F, 0x2C60,
+	0x2C60, 0x2C62, 0x2C63, 0x2C64, 0x2C65, 0x2C66, 0x2C67, 0x2C67,
+	0x2C69, 0x2C69, 0x2C6B, 0x2C6B, 0x2C6D, 0x2C6E, 0x2C6F, 0x2C70,
+	0x2C71, 0x2C72, 0x2C73, 0x2C74, 0x2C75, 0x2C75, 0x2C77, 0x2C78,
+	0x2C79, 0x2C7A, 0x2C7B, 0x2C7C, 0x2C7D, 0x2C7E, 0x2C7F, 0x2C80,
+	0x2C80, 0x2C82, 0x2C82, 0x2C84, 0x2C84, 0x2C86, 0x2C86, 0x2C88,
+	0x2C88, 0x2C8A, 0x2C8A, 0x2C8C, 0x2C8C, 0x2C8E, 0x2C8E, 0x2C90,
+	0x2C90, 0x2C92, 0x2C92, 0x2C94, 0x2C94, 0x2C96, 0x2C96, 0x2C98,
+	0x2C98, 0x2C9A, 0x2C9A, 0x2C9C, 0x2C9C, 0x2C9E, 0x2C9E, 0x2CA0,
+	0x2CA0, 0x2CA2, 0x2CA2, 0x2CA4, 0x2CA4, 0x2CA6, 0x2CA6, 0x2CA8,
+	0x2CA8, 0x2CAA, 0x2CAA, 0x2CAC, 0x2CAC, 0x2CAE, 0x2CAE, 0x2CB0,
+	0x2CB0, 0x2CB2, 0x2CB2, 0x2CB4, 0x2CB4, 0x2CB6, 0x2CB6, 0x2CB8,
+	0x2CB8, 0x2CBA, 0x2CBA, 0x2CBC, 0x2CBC, 0x2CBE, 0x2CBE, 0x2CC0,
+	0x2CC0, 0x2CC2, 0x2CC2, 0x2CC4, 0x2CC4, 0x2CC6, 0x2CC6, 0x2CC8,
+	0x2CC8, 0x2CCA, 0x2CCA, 0x2CCC, 0x2CCC, 0x2CCE, 0x2CCE, 0x2CD0,
+	0x2CD0, 0x2CD2, 0x2CD2, 0x2CD4, 0x2CD4, 0x2CD6, 0x2CD6, 0x2CD8,
+	0x2CD8, 0x2CDA, 0x2CDA, 0x2CDC, 0x2CDC, 0x2CDE, 0x2CDE, 0x2CE0,
+	0x2CE0, 0x2CE2, 0x2CE2, 0x2CE4, 0x2CE5, 0x2CE6, 0x2CE7, 0x2CE8,
+	0x2CE9, 0x2CEA, 0x2CEB, 0x2CEC, 0x2CED, 0x2CEE, 0x2CEF, 0x2CF0,
+	0x2CF1, 0x2CF2, 0x2CF3, 0x2CF4, 0x2CF5, 0x2CF6, 0x2CF7, 0x2CF8,
+	0x2CF9, 0x2CFA, 0x2CFB, 0x2CFC, 0x2CFD, 0x2CFE, 0x2CFF, 0x10A0,
+	0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x10A7, 0x10A8,
+	0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x10AF, 0x10B0,
+	0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x10B7, 0x10B8,
+	0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x10BE, 0x10BF, 0x10C0,
+	0x10C1, 0x10C2, 0x10C3, 0x10C4, 0x10C5, 0xFFFF, 0xD21B, 0xFF21,
+	0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29,
+	0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31,
+	0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39,
+	0xFF3A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F, 0xFF60, 0xFF61,
+	0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, 0xFF68, 0xFF69,
+	0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, 0xFF70, 0xFF71,
+	0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, 0xFF78, 0xFF79,
+	0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, 0xFF80, 0xFF81,
+	0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88, 0xFF89,
+	0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, 0xFF90, 0xFF91,
+	0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, 0xFF98, 0xFF99,
+	0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, 0xFFA0, 0xFFA1,
+	0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, 0xFFA8, 0xFFA9,
+	0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF, 0xFFB0, 0xFFB1,
+	0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7, 0xFFB8, 0xFFB9,
+	0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF, 0xFFC0, 0xFFC1,
+	0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, 0xFFC8, 0xFFC9,
+	0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF, 0xFFD0, 0xFFD1,
+	0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, 0xFFD8, 0xFFD9,
+	0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF, 0xFFE0, 0xFFE1,
+	0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7, 0xFFE8, 0xFFE9,
+	0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, 0xFFF0, 0xFFF1,
+	0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, 0xFFF8, 0xFFF9,
+	0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF
+};
+
+int default_upcase_table(uint16_t **tablep, size_t *sizep) {
+	*tablep = exfatfs_recommended_upcase_table_compressed;
+	*sizep = sizeof(exfatfs_recommended_upcase_table_compressed);
+	return 0;
+}
+
+#define KB_SHIFT 10
+#define MB_SHIFT (10 + KB_SHIFT)
+#define GB_SHIFT (10 + MB_SHIFT)
+#define TB_SHIFT (10 + GB_SHIFT)
+
+#define KILOBYTE (1LL << KB_SHIFT)
+#define MEGABYTE (1LL << MB_SHIFT)
+#define GIGABYTE (1LL << GB_SHIFT)
+#define TERABYTE (1LL << TB_SHIFT)
+
+/* #define USE_WINDOWS_DEFAULTS */
+
+off_t
+default_heapalign(off_t diskbytes)
+{
+#ifdef USE_WINDOWS_DEFAULTS
+	if (diskbytes >= 0x80000000)
+		return 0x100000; /* 1 MiB */
+	return 0x10000; /* 64 KiB */
+#else
+	return default_fatalign(diskbytes);
+#endif
+}
+
+off_t
+default_fatalign(off_t diskbytes)
+{
+#ifdef USE_WINDOWS_DEFAULTS
+	if (diskbytes >= 0x100000000)
+		return 0x100000; /* 1 MiB */
+	return 0x10000; /* 64 KiB */
+#else /* SD Association recommendations */
+	off_t fatalign;
+
+	if (diskbytes <= 8 * MEGABYTE)
+		fatalign = 8 * KILOBYTE;
+	else if (diskbytes <= 64 * MEGABYTE)
+		fatalign = 16 * KILOBYTE;
+	else if (diskbytes <= 256 * MEGABYTE)
+		fatalign = 32 * KILOBYTE;
+	else if (diskbytes <= 2 * GIGABYTE)
+		fatalign = 64 * KILOBYTE;
+	else if (diskbytes <= 32 * GIGABYTE)
+		fatalign = 4 * MEGABYTE;
+	else if (diskbytes <= 128 * GIGABYTE)
+		fatalign = 16 * MEGABYTE;
+	else if (diskbytes <= 512 * GIGABYTE)
+		fatalign = 32 * MEGABYTE;
+	else
+		fatalign = 64 * MEGABYTE;
+
+	return fatalign;
+#endif
+}
+
+/*
+ * Produce the default cluster shift
+ * for the given filesystem size (in bytes).
+ */
+off_t
+default_cluster_shift(off_t diskbytes)
+{
+	off_t cshift;
+	
+#ifdef USE_WINDOWS_DEFAULTS
+	if (diskbytes < 256 * MEGABYTE)
+		cshift = 2 + KB_SHIFT;
+	else if (diskbytes < 32 * GIGABYTE)
+		cshift = 5 + KB_SHIFT;
+	else
+		cshift = 7 + KB_SHIFT;
+#else /* SD Association recommendations */
+	if (diskbytes <= 8 * MEGABYTE)
+		cshift = 3 + KB_SHIFT;
+	else if (diskbytes <= 1 * GIGABYTE)
+		cshift = 4 + KB_SHIFT;
+	else if (diskbytes <= 128 * GIGABYTE)
+		cshift = 5 + KB_SHIFT;
+	else if (diskbytes <= 512 * GIGABYTE)
+		cshift = 7 + KB_SHIFT;
+	else if (diskbytes <= 2 * TERABYTE)
+		cshift = 8 + KB_SHIFT;
+	else
+		cshift = 9 + KB_SHIFT;
+#endif
+	return cshift;
+}
+
+struct exfatfs *
+default_exfat_sb(struct dkwedge_info *dkw)
+{
+	struct exfatfs *fs;
+	off_t cshift;
+	
+	fs = ecalloc(1, sizeof(*fs));
+	cshift = default_cluster_shift(dkw->dkw_size << (off_t)DEV_BSHIFT);
+	
+	/*
+	 * Default values
+	 */
+	memcpy(fs->xf_JumpBoot, EXFAT_JUMPBOOT, sizeof(EXFAT_JUMPBOOT));
+	memcpy(fs->xf_FileSystemName, EXFAT_FSNAME, sizeof(EXFAT_FSNAME));
+	/* memset(fs->xf_MustBeZero, 0, sizeof(fs->xf_MustBeZero); */
+	fs->xf_PartitionOffset = 0;
+	fs->xf_VolumeLength = dkw->dkw_size;
+	/* The FAT can begin as early as sector 24 */
+	fs->xf_FatOffset = 24;
+	/* FatLength: computed later */
+	/* ClusterHeapOffset: computed later */
+	/* ClusterCount: computed later */
+	/* FirstClusterOfRootDirectory: computed later */
+	fs->xf_VolumeSerialNumber = (uint32_t)random();
+	fs->xf_FileSystemRevision = EXFAT_GREATEST_VERSION << 8;
+	/* fs->xf_VolumeFlags = 0; */
+	fs->xf_BytesPerSectorShift = DEV_BSHIFT;
+	fs->xf_SectorsPerClusterShift = cshift - DEV_BSHIFT;
+	fs->xf_NumberOfFats = 1; /* XXX maybe two? */
+	fs->xf_DriveSelect = 0x80; /* An arbitrary value, from the spec */
+	fs->xf_PercentInUse = 0;
+	memset(fs->xf_BootCode, 0xf4, sizeof(fs->xf_BootCode));
+	fs->xf_BootSignature = EXFAT_BOOT_SIGNATURE;
+
+	return fs;
+}
Index: src/sbin/newfs_exfatfs/defaults.h
diff -u /dev/null src/sbin/newfs_exfatfs/defaults.h:1.1.2.1
--- /dev/null	Fri Aug  2 00:23:21 2024
+++ src/sbin/newfs_exfatfs/defaults.h	Fri Aug  2 00:23:21 2024
@@ -0,0 +1,12 @@
+#ifndef _NEWFS_EXFATFS_DEFAULTS_H
+#define _NEWFS_EXFATFS_DEFAULTS_H
+
+#include <sys/types.h>
+
+off_t default_cluster_shift(off_t);
+off_t default_fatalign(off_t);
+off_t default_heapalign(off_t);
+struct exfatfs *default_exfat_sb(struct dkwedge_info *);
+int default_upcase_table(uint16_t **, size_t *);
+
+#endif /* _NEWFS_EXFATFS_DEFAULTS_H */

Reply via email to