├── LICENSE ├── Makefile ├── README ├── exfat.c ├── exfat.h ├── exfat_api.c ├── exfat_api.h ├── exfat_blkdev.c ├── exfat_blkdev.h ├── exfat_cache.c ├── exfat_cache.h ├── exfat_config.h ├── exfat_data.c ├── exfat_data.h ├── exfat_global.c ├── exfat_global.h ├── exfat_nls.c ├── exfat_nls.h ├── exfat_oal.c ├── exfat_oal.h ├── exfat_part.h ├── exfat_super.c ├── exfat_super.h ├── exfat_upcase.c └── exfat_version.h /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | obj-m += exfat_core.o exfat_fs.o 2 | 3 | exfat_fs-y := exfat_super.o 4 | 5 | exfat_core-y := exfat.o exfat_api.o exfat_blkdev.o exfat_cache.o \ 6 | exfat_data.o exfat_global.o exfat_nls.o exfat_oal.o exfat_upcase.o 7 | 8 | all: 9 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 10 | 11 | clean: 12 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 13 | 14 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | HOW TO BUILD YOUR KERNEL WITH THE exFAT FILESYSTEM DRIVER 2 | 3 | - get Kernel code of your Samsung Product in OSRC website. (http://opensource.samsung.com/) 4 | 5 | - make "exfat" directory into {Kernel}/drivers/ 6 | 7 | - copy exFAT source code into {Kernel}/drivers/exfat/ 8 | 9 | - edit default kernel configuration file of your device. 10 | $ vi {Kernel}/arch/arm/configs/{your_device_defconfig} 11 | #NLS Setting 12 | CONFIG_NLS_UTF8=y 13 | 14 | - edit a Makefile in Kernel/drivers 15 | $ vi {Kernel}/drivers/Makefile 16 | obj-y += exfat/ 17 | 18 | - execute command to make for your Kernel. (see README_kernel.txt in Kernel) 19 | ex) make arch=arm defconfig 20 | make 21 | 22 | -------------------------------------------------------------------------------- /exfat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef _EXFAT_H 20 | #define _EXFAT_H 21 | 22 | #include "exfat_config.h" 23 | #include "exfat_global.h" 24 | #include "exfat_data.h" 25 | #include "exfat_oal.h" 26 | 27 | #include "exfat_blkdev.h" 28 | #include "exfat_cache.h" 29 | #include "exfat_nls.h" 30 | #include "exfat_api.h" 31 | #include "exfat_cache.h" 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | #if EXFAT_CONFIG_KERNEL_DEBUG 38 | #define EXFAT_IOC_GET_DEBUGFLAGS _IOR('f', 100, long) 39 | #define EXFAT_IOC_SET_DEBUGFLAGS _IOW('f', 101, long) 40 | 41 | #define EXFAT_DEBUGFLAGS_INVALID_UMOUNT 0x01 42 | #define EXFAT_DEBUGFLAGS_ERROR_RW 0x02 43 | #endif 44 | 45 | #define MAX_VOLUME 4 46 | 47 | #define DENTRY_SIZE 32 48 | #define DENTRY_SIZE_BITS 5 49 | 50 | #define PBR_SIGNATURE 0xAA55 51 | #define EXT_SIGNATURE 0xAA550000 52 | #define VOL_LABEL "NO NAME " 53 | #define OEM_NAME "MSWIN4.1" 54 | #define STR_FAT12 "FAT12 " 55 | #define STR_FAT16 "FAT16 " 56 | #define STR_FAT32 "FAT32 " 57 | #define STR_EXFAT "EXFAT " 58 | #define VOL_CLEAN 0x0000 59 | #define VOL_DIRTY 0x0002 60 | 61 | #define FAT12_THRESHOLD 4087 62 | #define FAT16_THRESHOLD 65527 63 | #define FAT32_THRESHOLD 268435457 64 | #define EXFAT_THRESHOLD 268435457 65 | 66 | #define TYPE_UNUSED 0x0000 67 | #define TYPE_DELETED 0x0001 68 | #define TYPE_INVALID 0x0002 69 | #define TYPE_CRITICAL_PRI 0x0100 70 | #define TYPE_BITMAP 0x0101 71 | #define TYPE_UPCASE 0x0102 72 | #define TYPE_VOLUME 0x0103 73 | #define TYPE_DIR 0x0104 74 | #define TYPE_FILE 0x011F 75 | #define TYPE_SYMLINK 0x015F 76 | #define TYPE_CRITICAL_SEC 0x0200 77 | #define TYPE_STREAM 0x0201 78 | #define TYPE_EXTEND 0x0202 79 | #define TYPE_ACL 0x0203 80 | #define TYPE_BENIGN_PRI 0x0400 81 | #define TYPE_GUID 0x0401 82 | #define TYPE_PADDING 0x0402 83 | #define TYPE_ACLTAB 0x0403 84 | #define TYPE_BENIGN_SEC 0x0800 85 | #define TYPE_ALL 0x0FFF 86 | 87 | #define TM_CREATE 0 88 | #define TM_MODIFY 1 89 | #define TM_ACCESS 2 90 | 91 | #define CS_DIR_ENTRY 0 92 | #define CS_PBR_SECTOR 1 93 | #define CS_DEFAULT 2 94 | 95 | #define CLUSTER_16(x) ((UINT16)(x)) 96 | #define CLUSTER_32(x) ((UINT32)(x)) 97 | 98 | #define START_SECTOR(x) \ 99 | ( (((x)-2) << p_fs->sectors_per_clu_bits) + p_fs->data_start_sector ) 100 | 101 | #define IS_LAST_SECTOR_IN_CLUSTER(sec) \ 102 | ( (((sec) - p_fs->data_start_sector + 1) & ((1 << p_fs->sectors_per_clu_bits) -1)) == 0) 103 | 104 | #define GET_CLUSTER_FROM_SECTOR(sec) \ 105 | ((((sec) - p_fs->data_start_sector) >> p_fs->sectors_per_clu_bits) +2) 106 | 107 | #define GET16(p_src) \ 108 | ( ((UINT16)(p_src)[0]) | (((UINT16)(p_src)[1]) << 8) ) 109 | #define GET32(p_src) \ 110 | ( ((UINT32)(p_src)[0]) | (((UINT32)(p_src)[1]) << 8) | \ 111 | (((UINT32)(p_src)[2]) << 16) | (((UINT32)(p_src)[3]) << 24) ) 112 | #define GET64(p_src) \ 113 | ( ((UINT64)(p_src)[0]) | (((UINT64)(p_src)[1]) << 8) | \ 114 | (((UINT64)(p_src)[2]) << 16) | (((UINT64)(p_src)[3]) << 24) | \ 115 | (((UINT64)(p_src)[4]) << 32) | (((UINT64)(p_src)[5]) << 40) | \ 116 | (((UINT64)(p_src)[6]) << 48) | (((UINT64)(p_src)[7]) << 56) ) 117 | 118 | 119 | #define SET16(p_dst,src) \ 120 | do { \ 121 | (p_dst)[0]=(UINT8)(src); \ 122 | (p_dst)[1]=(UINT8)(((UINT16)(src)) >> 8); \ 123 | } while (0) 124 | #define SET32(p_dst,src) \ 125 | do { \ 126 | (p_dst)[0]=(UINT8)(src); \ 127 | (p_dst)[1]=(UINT8)(((UINT32)(src)) >> 8); \ 128 | (p_dst)[2]=(UINT8)(((UINT32)(src)) >> 16); \ 129 | (p_dst)[3]=(UINT8)(((UINT32)(src)) >> 24); \ 130 | } while (0) 131 | #define SET64(p_dst,src) \ 132 | do { \ 133 | (p_dst)[0]=(UINT8)(src); \ 134 | (p_dst)[1]=(UINT8)(((UINT64)(src)) >> 8); \ 135 | (p_dst)[2]=(UINT8)(((UINT64)(src)) >> 16); \ 136 | (p_dst)[3]=(UINT8)(((UINT64)(src)) >> 24); \ 137 | (p_dst)[4]=(UINT8)(((UINT64)(src)) >> 32); \ 138 | (p_dst)[5]=(UINT8)(((UINT64)(src)) >> 40); \ 139 | (p_dst)[6]=(UINT8)(((UINT64)(src)) >> 48); \ 140 | (p_dst)[7]=(UINT8)(((UINT64)(src)) >> 56); \ 141 | } while (0) 142 | 143 | #if (FFS_CONFIG_LITTLE_ENDIAN == 1) 144 | #define GET16_A(p_src) (*((UINT16 *)(p_src))) 145 | #define GET32_A(p_src) (*((UINT32 *)(p_src))) 146 | #define GET64_A(p_src) (*((UINT64 *)(p_src))) 147 | #define SET16_A(p_dst,src) *((UINT16 *)(p_dst)) = (UINT16)(src) 148 | #define SET32_A(p_dst,src) *((UINT32 *)(p_dst)) = (UINT32)(src) 149 | #define SET64_A(p_dst,src) *((UINT64 *)(p_dst)) = (UINT64)(src) 150 | #else 151 | #define GET16_A(p_src) GET16(p_src) 152 | #define GET32_A(p_src) GET32(p_src) 153 | #define GET64_A(p_src) GET64(p_src) 154 | #define SET16_A(p_dst,src) SET16(p_dst, src) 155 | #define SET32_A(p_dst,src) SET32(p_dst, src) 156 | #define SET64_A(p_dst,src) SET64(p_dst, src) 157 | #endif 158 | 159 | #define HIGH_INDEX_BIT (8) 160 | #define HIGH_INDEX_MASK (0xFF00) 161 | #define LOW_INDEX_BIT (16-HIGH_INDEX_BIT) 162 | #define UTBL_ROW_COUNT (1<> LOW_INDEX_BIT; 168 | } 169 | static inline UINT16 get_row_index(UINT16 i) 170 | { 171 | return i & ~HIGH_INDEX_MASK; 172 | } 173 | 174 | typedef struct { 175 | UINT8 jmp_boot[3]; 176 | UINT8 oem_name[8]; 177 | UINT8 bpb[109]; 178 | UINT8 boot_code[390]; 179 | UINT8 signature[2]; 180 | } PBR_SECTOR_T; 181 | 182 | typedef struct { 183 | UINT8 sector_size[2]; 184 | UINT8 sectors_per_clu; 185 | UINT8 num_reserved[2]; 186 | UINT8 num_fats; 187 | UINT8 num_root_entries[2]; 188 | UINT8 num_sectors[2]; 189 | UINT8 media_type; 190 | UINT8 num_fat_sectors[2]; 191 | UINT8 sectors_in_track[2]; 192 | UINT8 num_heads[2]; 193 | UINT8 num_hid_sectors[4]; 194 | UINT8 num_huge_sectors[4]; 195 | 196 | UINT8 phy_drv_no; 197 | UINT8 reserved; 198 | UINT8 ext_signature; 199 | UINT8 vol_serial[4]; 200 | UINT8 vol_label[11]; 201 | UINT8 vol_type[8]; 202 | } BPB16_T; 203 | 204 | typedef struct { 205 | UINT8 sector_size[2]; 206 | UINT8 sectors_per_clu; 207 | UINT8 num_reserved[2]; 208 | UINT8 num_fats; 209 | UINT8 num_root_entries[2]; 210 | UINT8 num_sectors[2]; 211 | UINT8 media_type; 212 | UINT8 num_fat_sectors[2]; 213 | UINT8 sectors_in_track[2]; 214 | UINT8 num_heads[2]; 215 | UINT8 num_hid_sectors[4]; 216 | UINT8 num_huge_sectors[4]; 217 | UINT8 num_fat32_sectors[4]; 218 | UINT8 ext_flags[2]; 219 | UINT8 fs_version[2]; 220 | UINT8 root_cluster[4]; 221 | UINT8 fsinfo_sector[2]; 222 | UINT8 backup_sector[2]; 223 | UINT8 reserved[12]; 224 | 225 | UINT8 phy_drv_no; 226 | UINT8 ext_reserved; 227 | UINT8 ext_signature; 228 | UINT8 vol_serial[4]; 229 | UINT8 vol_label[11]; 230 | UINT8 vol_type[8]; 231 | } BPB32_T; 232 | 233 | typedef struct { 234 | UINT8 reserved1[53]; 235 | UINT8 vol_offset[8]; 236 | UINT8 vol_length[8]; 237 | UINT8 fat_offset[4]; 238 | UINT8 fat_length[4]; 239 | UINT8 clu_offset[4]; 240 | UINT8 clu_count[4]; 241 | UINT8 root_cluster[4]; 242 | UINT8 vol_serial[4]; 243 | UINT8 fs_version[2]; 244 | UINT8 vol_flags[2]; 245 | UINT8 sector_size_bits; 246 | UINT8 sectors_per_clu_bits; 247 | UINT8 num_fats; 248 | UINT8 phy_drv_no; 249 | UINT8 perc_in_use; 250 | UINT8 reserved2[7]; 251 | } BPBEX_T; 252 | 253 | typedef struct { 254 | UINT8 signature1[4]; 255 | UINT8 reserved1[480]; 256 | UINT8 signature2[4]; 257 | UINT8 free_cluster[4]; 258 | UINT8 next_cluster[4]; 259 | UINT8 reserved2[14]; 260 | UINT8 signature3[2]; 261 | } FSI_SECTOR_T; 262 | 263 | typedef struct { 264 | UINT8 dummy[32]; 265 | } DENTRY_T; 266 | 267 | typedef struct { 268 | UINT8 name[DOS_NAME_LENGTH]; 269 | UINT8 attr; 270 | UINT8 lcase; 271 | UINT8 create_time_ms; 272 | UINT8 create_time[2]; 273 | UINT8 create_date[2]; 274 | UINT8 access_date[2]; 275 | UINT8 start_clu_hi[2]; 276 | UINT8 modify_time[2]; 277 | UINT8 modify_date[2]; 278 | UINT8 start_clu_lo[2]; 279 | UINT8 size[4]; 280 | } DOS_DENTRY_T; 281 | 282 | typedef struct { 283 | UINT8 order; 284 | UINT8 unicode_0_4[10]; 285 | UINT8 attr; 286 | UINT8 sysid; 287 | UINT8 checksum; 288 | UINT8 unicode_5_10[12]; 289 | UINT8 start_clu[2]; 290 | UINT8 unicode_11_12[4]; 291 | } EXT_DENTRY_T; 292 | 293 | typedef struct { 294 | UINT8 type; 295 | UINT8 num_ext; 296 | UINT8 checksum[2]; 297 | UINT8 attr[2]; 298 | UINT8 reserved1[2]; 299 | UINT8 create_time[2]; 300 | UINT8 create_date[2]; 301 | UINT8 modify_time[2]; 302 | UINT8 modify_date[2]; 303 | UINT8 access_time[2]; 304 | UINT8 access_date[2]; 305 | UINT8 create_time_ms; 306 | UINT8 modify_time_ms; 307 | UINT8 access_time_ms; 308 | UINT8 reserved2[9]; 309 | } FILE_DENTRY_T; 310 | 311 | typedef struct { 312 | UINT8 type; 313 | UINT8 flags; 314 | UINT8 reserved1; 315 | UINT8 name_len; 316 | UINT8 name_hash[2]; 317 | UINT8 reserved2[2]; 318 | UINT8 valid_size[8]; 319 | UINT8 reserved3[4]; 320 | UINT8 start_clu[4]; 321 | UINT8 size[8]; 322 | } STRM_DENTRY_T; 323 | 324 | typedef struct { 325 | UINT8 type; 326 | UINT8 flags; 327 | UINT8 unicode_0_14[30]; 328 | } NAME_DENTRY_T; 329 | 330 | typedef struct { 331 | UINT8 type; 332 | UINT8 flags; 333 | UINT8 reserved[18]; 334 | UINT8 start_clu[4]; 335 | UINT8 size[8]; 336 | } BMAP_DENTRY_T; 337 | 338 | typedef struct { 339 | UINT8 type; 340 | UINT8 reserved1[3]; 341 | UINT8 checksum[4]; 342 | UINT8 reserved2[12]; 343 | UINT8 start_clu[4]; 344 | UINT8 size[8]; 345 | } CASE_DENTRY_T; 346 | 347 | typedef struct { 348 | UINT8 type; 349 | UINT8 label_len; 350 | UINT8 unicode_0_10[22]; 351 | UINT8 reserved[8]; 352 | } VOLM_DENTRY_T; 353 | 354 | typedef struct { 355 | UINT32 dir; 356 | INT32 entry; 357 | CHAIN_T clu; 358 | } UENTRY_T; 359 | 360 | typedef struct __FS_STRUCT_T { 361 | UINT32 mounted; 362 | struct super_block *sb; 363 | struct semaphore v_sem; 364 | } FS_STRUCT_T; 365 | 366 | typedef struct { 367 | INT32 (*alloc_cluster)(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain); 368 | void (*free_cluster)(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse); 369 | INT32 (*count_used_clusters)(struct super_block *sb); 370 | 371 | INT32 (*init_dir_entry)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, 372 | UINT32 start_clu, UINT64 size); 373 | INT32 (*init_ext_entry)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, 374 | UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname); 375 | INT32 (*find_dir_entry)(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type); 376 | void (*delete_dir_entry)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 offset, INT32 num_entries); 377 | void (*get_uni_name_from_ext_entry)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname); 378 | INT32 (*count_ext_entries)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry); 379 | INT32 (*calc_num_entries)(UNI_NAME_T *p_uniname); 380 | 381 | UINT32 (*get_entry_type)(DENTRY_T *p_entry); 382 | void (*set_entry_type)(DENTRY_T *p_entry, UINT32 type); 383 | UINT32 (*get_entry_attr)(DENTRY_T *p_entry); 384 | void (*set_entry_attr)(DENTRY_T *p_entry, UINT32 attr); 385 | UINT8 (*get_entry_flag)(DENTRY_T *p_entry); 386 | void (*set_entry_flag)(DENTRY_T *p_entry, UINT8 flag); 387 | UINT32 (*get_entry_clu0)(DENTRY_T *p_entry); 388 | void (*set_entry_clu0)(DENTRY_T *p_entry, UINT32 clu0); 389 | UINT64 (*get_entry_size)(DENTRY_T *p_entry); 390 | void (*set_entry_size)(DENTRY_T *p_entry, UINT64 size); 391 | void (*get_entry_time)(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); 392 | void (*set_entry_time)(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); 393 | } FS_FUNC_T; 394 | 395 | typedef struct __FS_INFO_T { 396 | UINT32 drv; 397 | UINT32 vol_type; 398 | UINT32 vol_id; 399 | 400 | UINT32 num_sectors; 401 | UINT32 num_clusters; 402 | UINT32 cluster_size; 403 | UINT32 cluster_size_bits; 404 | UINT32 sectors_per_clu; 405 | UINT32 sectors_per_clu_bits; 406 | 407 | UINT32 PBR_sector; 408 | UINT32 FAT1_start_sector; 409 | UINT32 FAT2_start_sector; 410 | UINT32 root_start_sector; 411 | UINT32 data_start_sector; 412 | UINT32 num_FAT_sectors; 413 | 414 | UINT32 root_dir; 415 | UINT32 dentries_in_root; 416 | UINT32 dentries_per_clu; 417 | 418 | UINT32 vol_flag; 419 | struct buffer_head *pbr_bh; 420 | 421 | UINT32 map_clu; 422 | UINT32 map_sectors; 423 | struct buffer_head **vol_amap; 424 | 425 | UINT16 **vol_utbl; 426 | 427 | UINT32 clu_srch_ptr; 428 | UINT32 used_clusters; 429 | UENTRY_T hint_uentry; 430 | 431 | UINT32 dev_ejected; 432 | 433 | FS_FUNC_T *fs_func; 434 | 435 | BUF_CACHE_T FAT_cache_array[FAT_CACHE_SIZE]; 436 | BUF_CACHE_T FAT_cache_lru_list; 437 | BUF_CACHE_T FAT_cache_hash_list[FAT_CACHE_HASH_SIZE]; 438 | 439 | BUF_CACHE_T buf_cache_array[BUF_CACHE_SIZE]; 440 | BUF_CACHE_T buf_cache_lru_list; 441 | BUF_CACHE_T buf_cache_hash_list[BUF_CACHE_HASH_SIZE]; 442 | } FS_INFO_T; 443 | 444 | #define ES_2_ENTRIES 2 445 | #define ES_3_ENTRIES 3 446 | #define ES_ALL_ENTRIES 0 447 | 448 | typedef struct { 449 | UINT32 sector; 450 | INT32 offset; 451 | INT32 alloc_flag; 452 | UINT32 num_entries; 453 | 454 | void *__buf; 455 | } ENTRY_SET_CACHE_T; 456 | 457 | INT32 ffsInit(void); 458 | INT32 ffsShutdown(void); 459 | 460 | INT32 ffsMountVol(struct super_block *sb, INT32 drv); 461 | INT32 ffsUmountVol(struct super_block *sb); 462 | INT32 ffsCheckVol(struct super_block *sb); 463 | INT32 ffsGetVolInfo(struct super_block *sb, VOL_INFO_T *info); 464 | INT32 ffsSyncVol(struct super_block *sb, INT32 do_sync); 465 | 466 | INT32 ffsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid); 467 | INT32 ffsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid); 468 | INT32 ffsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount); 469 | INT32 ffsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount); 470 | INT32 ffsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size); 471 | INT32 ffsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry); 472 | INT32 ffsRemoveFile(struct inode *inode, FILE_ID_T *fid); 473 | INT32 ffsSetAttr(struct inode *inode, UINT32 attr); 474 | INT32 ffsGetStat(struct inode *inode, DIR_ENTRY_T *info); 475 | INT32 ffsSetStat(struct inode *inode, DIR_ENTRY_T *info); 476 | INT32 ffsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu); 477 | 478 | INT32 ffsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid); 479 | INT32 ffsReadDir(struct inode *inode, DIR_ENTRY_T *dir_ent); 480 | INT32 ffsRemoveDir(struct inode *inode, FILE_ID_T *fid); 481 | 482 | INT32 fs_init(void); 483 | INT32 fs_shutdown(void); 484 | void fs_set_vol_flags(struct super_block *sb, UINT32 new_flag); 485 | void fs_sync(struct super_block *sb, INT32 do_sync); 486 | void fs_error(struct super_block *sb); 487 | 488 | INT32 clear_cluster(struct super_block *sb, UINT32 clu); 489 | INT32 fat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain); 490 | INT32 exfat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain); 491 | void fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse); 492 | void exfat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse); 493 | UINT32 find_last_cluster(struct super_block *sb, CHAIN_T *p_chain); 494 | INT32 count_num_clusters(struct super_block *sb, CHAIN_T *dir); 495 | INT32 fat_count_used_clusters(struct super_block *sb); 496 | INT32 exfat_count_used_clusters(struct super_block *sb); 497 | void exfat_chain_cont_cluster(struct super_block *sb, UINT32 chain, INT32 len); 498 | 499 | INT32 load_alloc_bitmap(struct super_block *sb); 500 | void free_alloc_bitmap(struct super_block *sb); 501 | INT32 set_alloc_bitmap(struct super_block *sb, UINT32 clu); 502 | INT32 clr_alloc_bitmap(struct super_block *sb, UINT32 clu); 503 | UINT32 test_alloc_bitmap(struct super_block *sb, UINT32 clu); 504 | void sync_alloc_bitmap(struct super_block *sb); 505 | 506 | INT32 load_upcase_table(struct super_block *sb); 507 | void free_upcase_table(struct super_block *sb); 508 | 509 | UINT32 fat_get_entry_type(DENTRY_T *p_entry); 510 | UINT32 exfat_get_entry_type(DENTRY_T *p_entry); 511 | void fat_set_entry_type(DENTRY_T *p_entry, UINT32 type); 512 | void exfat_set_entry_type(DENTRY_T *p_entry, UINT32 type); 513 | UINT32 fat_get_entry_attr(DENTRY_T *p_entry); 514 | UINT32 exfat_get_entry_attr(DENTRY_T *p_entry); 515 | void fat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr); 516 | void exfat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr); 517 | UINT8 fat_get_entry_flag(DENTRY_T *p_entry); 518 | UINT8 exfat_get_entry_flag(DENTRY_T *p_entry); 519 | void fat_set_entry_flag(DENTRY_T *p_entry, UINT8 flag); 520 | void exfat_set_entry_flag(DENTRY_T *p_entry, UINT8 flag); 521 | UINT32 fat_get_entry_clu0(DENTRY_T *p_entry); 522 | UINT32 exfat_get_entry_clu0(DENTRY_T *p_entry); 523 | void fat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu); 524 | void exfat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu); 525 | UINT64 fat_get_entry_size(DENTRY_T *p_entry); 526 | UINT64 exfat_get_entry_size(DENTRY_T *p_entry); 527 | void fat_set_entry_size(DENTRY_T *p_entry, UINT64 size); 528 | void exfat_set_entry_size(DENTRY_T *p_entry, UINT64 size); 529 | void fat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); 530 | void exfat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); 531 | void fat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); 532 | void exfat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); 533 | INT32 fat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, UINT32 start_clu, UINT64 size); 534 | INT32 exfat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, UINT32 start_clu, UINT64 size); 535 | INT32 fat_init_ext_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname); 536 | INT32 exfat_init_ext_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname); 537 | void init_dos_entry(DOS_DENTRY_T *ep, UINT32 type, UINT32 start_clu); 538 | void init_ext_entry(EXT_DENTRY_T *ep, INT32 order, UINT8 chksum, UINT16 *uniname); 539 | void init_file_entry(FILE_DENTRY_T *ep, UINT32 type); 540 | void init_strm_entry(STRM_DENTRY_T *ep, UINT8 flags, UINT32 start_clu, UINT64 size); 541 | void init_name_entry(NAME_DENTRY_T *ep, UINT16 *uniname); 542 | void fat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 order, INT32 num_entries); 543 | void exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 order, INT32 num_entries); 544 | 545 | INT32 find_location(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 *sector, INT32 *offset); 546 | DENTRY_T *get_entry_with_sector(struct super_block *sb, UINT32 sector, INT32 offset); 547 | DENTRY_T *get_entry_in_dir(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 *sector); 548 | ENTRY_SET_CACHE_T *get_entry_set_in_dir (struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, DENTRY_T **file_ep); 549 | void release_entry_set (ENTRY_SET_CACHE_T *es); 550 | INT32 write_whole_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es); 551 | INT32 write_partial_entries_in_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es, DENTRY_T *ep, UINT32 count); 552 | INT32 search_deleted_or_unused_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 num_entries); 553 | INT32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, INT32 num_entries); 554 | INT32 fat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type); 555 | INT32 exfat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type); 556 | INT32 fat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry); 557 | INT32 exfat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry); 558 | INT32 count_dos_name_entries(struct super_block *sb, CHAIN_T *p_dir, UINT32 type); 559 | void update_dir_checksum(struct super_block *sb, CHAIN_T *p_dir, INT32 entry); 560 | void update_dir_checksum_with_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es); 561 | BOOL is_dir_empty(struct super_block *sb, CHAIN_T *p_dir); 562 | 563 | INT32 get_num_entries_and_dos_name(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 *entries, DOS_NAME_T *p_dosname); 564 | void get_uni_name_from_dos_entry(struct super_block *sb, DOS_DENTRY_T *ep, UNI_NAME_T *p_uniname, UINT8 mode); 565 | void fat_get_uni_name_from_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname); 566 | void exfat_get_uni_name_from_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname); 567 | INT32 extract_uni_name_from_ext_entry(EXT_DENTRY_T *ep, UINT16 *uniname, INT32 order); 568 | INT32 extract_uni_name_from_name_entry(NAME_DENTRY_T *ep, UINT16 *uniname, INT32 order); 569 | INT32 fat_generate_dos_name(struct super_block *sb, CHAIN_T *p_dir, DOS_NAME_T *p_dosname); 570 | void fat_attach_count_to_dos_name(UINT8 *dosname, INT32 count); 571 | INT32 fat_calc_num_entries(UNI_NAME_T *p_uniname); 572 | INT32 exfat_calc_num_entries(UNI_NAME_T *p_uniname); 573 | UINT8 calc_checksum_1byte(void *data, INT32 len, UINT8 chksum); 574 | UINT16 calc_checksum_2byte(void *data, INT32 len, UINT16 chksum, INT32 type); 575 | UINT32 calc_checksum_4byte(void *data, INT32 len, UINT32 chksum, INT32 type); 576 | 577 | INT32 resolve_path(struct inode *inode, UINT8 *path, CHAIN_T *p_dir, UNI_NAME_T *p_uniname); 578 | INT32 resolve_name(UINT8 *name, UINT8 **arg); 579 | 580 | INT32 fat16_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr); 581 | INT32 fat32_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr); 582 | INT32 exfat_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr); 583 | INT32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, FILE_ID_T *fid); 584 | INT32 create_file(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, UINT8 mode, FILE_ID_T *fid); 585 | void remove_file(struct inode *inode, CHAIN_T *p_dir, INT32 entry); 586 | INT32 rename_file(struct inode *inode, CHAIN_T *p_dir, INT32 old_entry, UNI_NAME_T *p_uniname, FILE_ID_T *fid); 587 | INT32 move_file(struct inode *inode, CHAIN_T *p_olddir, INT32 oldentry, CHAIN_T *p_newdir, UNI_NAME_T *p_uniname, FILE_ID_T *fid); 588 | 589 | INT32 sector_read(struct super_block *sb, UINT32 sec, struct buffer_head **bh, INT32 read); 590 | INT32 sector_write(struct super_block *sb, UINT32 sec, struct buffer_head *bh, INT32 sync); 591 | INT32 multi_sector_read(struct super_block *sb, UINT32 sec, struct buffer_head **bh, INT32 num_secs, INT32 read); 592 | INT32 multi_sector_write(struct super_block *sb, UINT32 sec, struct buffer_head *bh, INT32 num_secs, INT32 sync); 593 | 594 | #ifdef __cplusplus 595 | } 596 | #endif 597 | 598 | #endif 599 | -------------------------------------------------------------------------------- /exfat_api.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "exfat_version.h" 24 | #include "exfat_config.h" 25 | #include "exfat_global.h" 26 | #include "exfat_data.h" 27 | #include "exfat_oal.h" 28 | 29 | #include "exfat_part.h" 30 | #include "exfat_nls.h" 31 | #include "exfat_api.h" 32 | #include "exfat_super.h" 33 | #include "exfat.h" 34 | 35 | extern FS_STRUCT_T fs_struct[]; 36 | 37 | extern struct semaphore z_sem; 38 | 39 | INT32 FsInit(void) 40 | { 41 | INT32 i; 42 | 43 | for (i = 0; i < MAX_DRIVE; i++) { 44 | fs_struct[i].mounted = FALSE; 45 | fs_struct[i].sb = NULL; 46 | sm_init(&(fs_struct[i].v_sem)); 47 | } 48 | 49 | return(ffsInit()); 50 | } 51 | 52 | INT32 FsShutdown(void) 53 | { 54 | INT32 i; 55 | 56 | for (i = 0; i < MAX_DRIVE; i++) { 57 | if (!fs_struct[i].mounted) continue; 58 | 59 | ffsUmountVol(fs_struct[i].sb); 60 | } 61 | 62 | return(ffsShutdown()); 63 | } 64 | 65 | INT32 FsMountVol(struct super_block *sb) 66 | { 67 | INT32 err, drv; 68 | 69 | sm_P(&z_sem); 70 | 71 | for (drv = 0; drv < MAX_DRIVE; drv++) { 72 | if (!fs_struct[drv].mounted) break; 73 | } 74 | 75 | if (drv >= MAX_DRIVE) return(FFS_ERROR); 76 | 77 | sm_P(&(fs_struct[drv].v_sem)); 78 | 79 | err = buf_init(sb); 80 | if (!err) { 81 | err = ffsMountVol(sb, drv); 82 | } 83 | 84 | sm_V(&(fs_struct[drv].v_sem)); 85 | 86 | if (!err) { 87 | fs_struct[drv].mounted = TRUE; 88 | fs_struct[drv].sb = sb; 89 | } else { 90 | buf_shutdown(sb); 91 | } 92 | 93 | sm_V(&z_sem); 94 | 95 | return(err); 96 | } 97 | 98 | INT32 FsUmountVol(struct super_block *sb) 99 | { 100 | INT32 err; 101 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 102 | 103 | sm_P(&z_sem); 104 | 105 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 106 | 107 | err = ffsUmountVol(sb); 108 | buf_shutdown(sb); 109 | 110 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 111 | 112 | fs_struct[p_fs->drv].mounted = FALSE; 113 | fs_struct[p_fs->drv].sb = NULL; 114 | 115 | sm_V(&z_sem); 116 | 117 | return(err); 118 | } 119 | 120 | INT32 FsGetVolInfo(struct super_block *sb, VOL_INFO_T *info) 121 | { 122 | INT32 err; 123 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 124 | 125 | if (info == NULL) return(FFS_ERROR); 126 | 127 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 128 | 129 | err = ffsGetVolInfo(sb, info); 130 | 131 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 132 | 133 | return(err); 134 | } 135 | 136 | INT32 FsSyncVol(struct super_block *sb, INT32 do_sync) 137 | { 138 | INT32 err; 139 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 140 | 141 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 142 | 143 | err = ffsSyncVol(sb, do_sync); 144 | 145 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 146 | 147 | return(err); 148 | } 149 | 150 | INT32 FsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid) 151 | { 152 | INT32 err; 153 | struct super_block *sb = inode->i_sb; 154 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 155 | 156 | if ((fid == NULL) || (path == NULL) || (STRLEN(path) == 0)) 157 | return(FFS_ERROR); 158 | 159 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 160 | 161 | err = ffsLookupFile(inode, path, fid); 162 | 163 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 164 | 165 | return(err); 166 | } 167 | 168 | INT32 FsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid) 169 | { 170 | INT32 err; 171 | struct super_block *sb = inode->i_sb; 172 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 173 | 174 | if ((fid == NULL) || (path == NULL) || (STRLEN(path) == 0)) 175 | return(FFS_ERROR); 176 | 177 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 178 | 179 | err = ffsCreateFile(inode, path, mode, fid); 180 | 181 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 182 | 183 | return(err); 184 | } 185 | 186 | INT32 FsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount) 187 | { 188 | INT32 err; 189 | struct super_block *sb = inode->i_sb; 190 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 191 | 192 | if (fid == NULL) return(FFS_INVALIDFID); 193 | 194 | if (buffer == NULL) return(FFS_ERROR); 195 | 196 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 197 | 198 | err = ffsReadFile(inode, fid, buffer, count, rcount); 199 | 200 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 201 | 202 | return(err); 203 | } 204 | 205 | INT32 FsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount) 206 | { 207 | INT32 err; 208 | struct super_block *sb = inode->i_sb; 209 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 210 | 211 | if (fid == NULL) return(FFS_INVALIDFID); 212 | 213 | if (buffer == NULL) return(FFS_ERROR); 214 | 215 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 216 | 217 | err = ffsWriteFile(inode, fid, buffer, count, wcount); 218 | 219 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 220 | 221 | return(err); 222 | } 223 | 224 | INT32 FsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size) 225 | { 226 | INT32 err; 227 | struct super_block *sb = inode->i_sb; 228 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 229 | 230 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 231 | 232 | PRINTK("FsTruncateFile entered (inode %p size %llu)\n", inode, new_size); 233 | 234 | err = ffsTruncateFile(inode, old_size, new_size); 235 | 236 | PRINTK("FsTruncateFile exitted (%d)\n", err); 237 | 238 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 239 | 240 | return(err); 241 | } 242 | 243 | INT32 FsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry) 244 | { 245 | INT32 err; 246 | struct super_block *sb = old_parent_inode->i_sb; 247 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 248 | 249 | if (fid == NULL) return(FFS_INVALIDFID); 250 | 251 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 252 | 253 | err = ffsMoveFile(old_parent_inode, fid, new_parent_inode, new_dentry); 254 | 255 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 256 | 257 | return(err); 258 | } 259 | 260 | INT32 FsRemoveFile(struct inode *inode, FILE_ID_T *fid) 261 | { 262 | INT32 err; 263 | struct super_block *sb = inode->i_sb; 264 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 265 | 266 | if (fid == NULL) return(FFS_INVALIDFID); 267 | 268 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 269 | 270 | err = ffsRemoveFile(inode, fid); 271 | 272 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 273 | 274 | return(err); 275 | } 276 | 277 | INT32 FsSetAttr(struct inode *inode, UINT32 attr) 278 | { 279 | INT32 err; 280 | struct super_block *sb = inode->i_sb; 281 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 282 | 283 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 284 | 285 | err = ffsSetAttr(inode, attr); 286 | 287 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 288 | 289 | return(err); 290 | } 291 | 292 | INT32 FsReadStat(struct inode *inode, DIR_ENTRY_T *info) 293 | { 294 | INT32 err; 295 | struct super_block *sb = inode->i_sb; 296 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 297 | 298 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 299 | 300 | err = ffsGetStat(inode, info); 301 | 302 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 303 | 304 | return(err); 305 | } 306 | 307 | INT32 FsWriteStat(struct inode *inode, DIR_ENTRY_T *info) 308 | { 309 | INT32 err; 310 | struct super_block *sb = inode->i_sb; 311 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 312 | 313 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 314 | 315 | PRINTK("FsWriteStat entered (inode %p info %p\n", inode, info); 316 | 317 | err = ffsSetStat(inode, info); 318 | 319 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 320 | 321 | PRINTK("FsWriteStat exited (%d)\n", err); 322 | 323 | return(err); 324 | } 325 | 326 | INT32 FsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu) 327 | { 328 | INT32 err; 329 | struct super_block *sb = inode->i_sb; 330 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 331 | 332 | if (clu == NULL) return(FFS_ERROR); 333 | 334 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 335 | 336 | err = ffsMapCluster(inode, clu_offset, clu); 337 | 338 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 339 | 340 | return(err); 341 | } 342 | 343 | INT32 FsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid) 344 | { 345 | INT32 err; 346 | struct super_block *sb = inode->i_sb; 347 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 348 | 349 | if ((fid == NULL) || (path == NULL) || (STRLEN(path) == 0)) 350 | return(FFS_ERROR); 351 | 352 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 353 | 354 | err = ffsCreateDir(inode, path, fid); 355 | 356 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 357 | 358 | return(err); 359 | } 360 | 361 | INT32 FsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry) 362 | { 363 | INT32 err; 364 | struct super_block *sb = inode->i_sb; 365 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 366 | 367 | if (dir_entry == NULL) return(FFS_ERROR); 368 | 369 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 370 | 371 | err = ffsReadDir(inode, dir_entry); 372 | 373 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 374 | 375 | return(err); 376 | } 377 | 378 | INT32 FsRemoveDir(struct inode *inode, FILE_ID_T *fid) 379 | { 380 | INT32 err; 381 | struct super_block *sb = inode->i_sb; 382 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 383 | 384 | if (fid == NULL) return(FFS_INVALIDFID); 385 | 386 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 387 | 388 | err = ffsRemoveDir(inode, fid); 389 | 390 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 391 | 392 | return(err); 393 | } 394 | 395 | EXPORT_SYMBOL(FsMountVol); 396 | EXPORT_SYMBOL(FsUmountVol); 397 | EXPORT_SYMBOL(FsGetVolInfo); 398 | EXPORT_SYMBOL(FsSyncVol); 399 | EXPORT_SYMBOL(FsLookupFile); 400 | EXPORT_SYMBOL(FsCreateFile); 401 | EXPORT_SYMBOL(FsReadFile); 402 | EXPORT_SYMBOL(FsWriteFile); 403 | EXPORT_SYMBOL(FsTruncateFile); 404 | EXPORT_SYMBOL(FsMoveFile); 405 | EXPORT_SYMBOL(FsRemoveFile); 406 | EXPORT_SYMBOL(FsSetAttr); 407 | EXPORT_SYMBOL(FsReadStat); 408 | EXPORT_SYMBOL(FsWriteStat); 409 | EXPORT_SYMBOL(FsMapCluster); 410 | EXPORT_SYMBOL(FsCreateDir); 411 | EXPORT_SYMBOL(FsReadDir); 412 | EXPORT_SYMBOL(FsRemoveDir); 413 | 414 | #if EXFAT_CONFIG_KERNEL_DEBUG 415 | INT32 FsReleaseCache(struct super_block *sb) 416 | { 417 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 418 | 419 | sm_P(&(fs_struct[p_fs->drv].v_sem)); 420 | 421 | FAT_release_all(sb); 422 | buf_release_all(sb); 423 | 424 | sm_V(&(fs_struct[p_fs->drv].v_sem)); 425 | 426 | return 0; 427 | } 428 | 429 | EXPORT_SYMBOL(FsReleaseCache); 430 | #endif 431 | 432 | static int __init init_exfat_core(void) 433 | { 434 | int err; 435 | 436 | printk(KERN_INFO "exFAT: Core Version %s\n", EXFAT_VERSION); 437 | 438 | err = FsInit(); 439 | if (err) { 440 | if (err == FFS_MEMORYERR) 441 | return -ENOMEM; 442 | else 443 | return -EIO; 444 | } 445 | 446 | return 0; 447 | } 448 | 449 | static void __exit exit_exfat_core(void) 450 | { 451 | FsShutdown(); 452 | } 453 | 454 | module_init(init_exfat_core); 455 | module_exit(exit_exfat_core); 456 | 457 | MODULE_LICENSE("GPL"); 458 | -------------------------------------------------------------------------------- /exfat_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef _EXFAT_API_H 20 | #define _EXFAT_API_H 21 | 22 | #include "exfat_config.h" 23 | #include "exfat_global.h" 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | #define EXFAT_SUPER_MAGIC (0x2011BAB0L) 30 | #define EXFAT_ROOT_INO 1 31 | 32 | #define FAT12 0x01 33 | #define FAT16 0x0E 34 | #define FAT32 0x0C 35 | #define EXFAT 0x07 36 | 37 | #define MAX_CHARSET_SIZE 3 38 | #define MAX_PATH_DEPTH 15 39 | #define MAX_NAME_LENGTH 256 40 | #define MAX_PATH_LENGTH 260 41 | #define DOS_NAME_LENGTH 11 42 | #define DOS_PATH_LENGTH 80 43 | 44 | #define ATTR_NORMAL 0x0000 45 | #define ATTR_READONLY 0x0001 46 | #define ATTR_HIDDEN 0x0002 47 | #define ATTR_SYSTEM 0x0004 48 | #define ATTR_VOLUME 0x0008 49 | #define ATTR_SUBDIR 0x0010 50 | #define ATTR_ARCHIVE 0x0020 51 | #define ATTR_SYMLINK 0x0040 52 | #define ATTR_EXTEND 0x000F 53 | #define ATTR_RWMASK 0x007E 54 | 55 | #define FM_REGULAR 0x00 56 | #define FM_SYMLINK 0x40 57 | 58 | #define FFS_SUCCESS 0 59 | #define FFS_MEDIAERR 1 60 | #define FFS_FORMATERR 2 61 | #define FFS_MOUNTED 3 62 | #define FFS_NOTMOUNTED 4 63 | #define FFS_ALIGNMENTERR 5 64 | #define FFS_SEMAPHOREERR 6 65 | #define FFS_INVALIDPATH 7 66 | #define FFS_INVALIDFID 8 67 | #define FFS_NOTFOUND 9 68 | #define FFS_FILEEXIST 10 69 | #define FFS_PERMISSIONERR 11 70 | #define FFS_NOTOPENED 12 71 | #define FFS_MAXOPENED 13 72 | #define FFS_FULL 14 73 | #define FFS_EOF 15 74 | #define FFS_DIRBUSY 16 75 | #define FFS_MEMORYERR 17 76 | #define FFS_NAMETOOLONG 18 77 | #define FFS_ERROR 19 78 | 79 | typedef struct { 80 | UINT16 Year; 81 | UINT16 Month; 82 | UINT16 Day; 83 | UINT16 Hour; 84 | UINT16 Minute; 85 | UINT16 Second; 86 | UINT16 MilliSecond; 87 | } DATE_TIME_T; 88 | 89 | typedef struct { 90 | UINT32 Offset; 91 | UINT32 Size; 92 | } PART_INFO_T; 93 | 94 | typedef struct { 95 | UINT32 SecSize; 96 | UINT32 DevSize; 97 | } DEV_INFO_T; 98 | 99 | typedef struct { 100 | UINT32 FatType; 101 | UINT32 ClusterSize; 102 | UINT32 NumClusters; 103 | UINT32 FreeClusters; 104 | UINT32 UsedClusters; 105 | } VOL_INFO_T; 106 | 107 | typedef struct { 108 | UINT32 dir; 109 | INT32 size; 110 | UINT8 flags; 111 | } CHAIN_T; 112 | 113 | typedef struct { 114 | CHAIN_T dir; 115 | INT32 entry; 116 | UINT32 type; 117 | UINT32 attr; 118 | UINT32 start_clu; 119 | UINT64 size; 120 | UINT8 flags; 121 | INT64 rwoffset; 122 | INT32 hint_last_off; 123 | UINT32 hint_last_clu; 124 | } FILE_ID_T; 125 | 126 | typedef struct { 127 | INT8 Name[MAX_NAME_LENGTH *MAX_CHARSET_SIZE]; 128 | INT8 ShortName[DOS_NAME_LENGTH + 2]; 129 | UINT32 Attr; 130 | UINT64 Size; 131 | UINT32 NumSubdirs; 132 | DATE_TIME_T CreateTimestamp; 133 | DATE_TIME_T ModifyTimestamp; 134 | DATE_TIME_T AccessTimestamp; 135 | } DIR_ENTRY_T; 136 | 137 | INT32 FsInit(void); 138 | INT32 FsShutdown(void); 139 | 140 | INT32 FsMountVol(struct super_block *sb); 141 | INT32 FsUmountVol(struct super_block *sb); 142 | INT32 FsGetVolInfo(struct super_block *sb, VOL_INFO_T *info); 143 | INT32 FsSyncVol(struct super_block *sb, INT32 do_sync); 144 | 145 | INT32 FsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid); 146 | INT32 FsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid); 147 | INT32 FsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount); 148 | INT32 FsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount); 149 | INT32 FsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size); 150 | INT32 FsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry); 151 | INT32 FsRemoveFile(struct inode *inode, FILE_ID_T *fid); 152 | INT32 FsSetAttr(struct inode *inode, UINT32 attr); 153 | INT32 FsReadStat(struct inode *inode, DIR_ENTRY_T *info); 154 | INT32 FsWriteStat(struct inode *inode, DIR_ENTRY_T *info); 155 | INT32 FsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu); 156 | 157 | INT32 FsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid); 158 | INT32 FsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry); 159 | INT32 FsRemoveDir(struct inode *inode, FILE_ID_T *fid); 160 | 161 | INT32 FsReleaseCache(struct super_block *sb); 162 | #ifdef __cplusplus 163 | } 164 | #endif 165 | #endif 166 | -------------------------------------------------------------------------------- /exfat_blkdev.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include 20 | 21 | #include "exfat_config.h" 22 | #include "exfat_global.h" 23 | #include "exfat_blkdev.h" 24 | #include "exfat_data.h" 25 | #include "exfat_api.h" 26 | #include "exfat_super.h" 27 | 28 | INT32 bdev_init(void) 29 | { 30 | return(FFS_SUCCESS); 31 | } 32 | 33 | INT32 bdev_shutdown(void) 34 | { 35 | return(FFS_SUCCESS); 36 | } 37 | 38 | INT32 bdev_open(struct super_block *sb) 39 | { 40 | BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); 41 | 42 | if (p_bd->opened) return(FFS_SUCCESS); 43 | 44 | p_bd->sector_size = bdev_logical_block_size(sb->s_bdev); 45 | p_bd->sector_size_bits = my_log2(p_bd->sector_size); 46 | p_bd->sector_size_mask = p_bd->sector_size - 1; 47 | p_bd->num_sectors = i_size_read(sb->s_bdev->bd_inode) >> p_bd->sector_size_bits; 48 | 49 | p_bd->opened = TRUE; 50 | 51 | return(FFS_SUCCESS); 52 | } 53 | 54 | INT32 bdev_close(struct super_block *sb) 55 | { 56 | BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); 57 | 58 | if (!p_bd->opened) return(FFS_SUCCESS); 59 | 60 | p_bd->opened = FALSE; 61 | return(FFS_SUCCESS); 62 | } 63 | 64 | INT32 bdev_read(struct super_block *sb, UINT32 secno, struct buffer_head **bh, UINT32 num_secs, INT32 read) 65 | { 66 | BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); 67 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 68 | #if EXFAT_CONFIG_KERNEL_DEBUG 69 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 70 | long flags = sbi->debug_flags; 71 | 72 | if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR); 73 | #endif 74 | 75 | if (!p_bd->opened) return(FFS_MEDIAERR); 76 | 77 | if (*bh) __brelse(*bh); 78 | 79 | if (read) 80 | *bh = __bread(sb->s_bdev, secno, num_secs << p_bd->sector_size_bits); 81 | else 82 | *bh = __getblk(sb->s_bdev, secno, num_secs << p_bd->sector_size_bits); 83 | 84 | if (*bh) return(FFS_SUCCESS); 85 | 86 | WARN(!p_fs->dev_ejected, 87 | "[EXFAT] No bh, device seems wrong or to be ejected.\n"); 88 | 89 | return(FFS_MEDIAERR); 90 | } 91 | 92 | INT32 bdev_write(struct super_block *sb, UINT32 secno, struct buffer_head *bh, UINT32 num_secs, INT32 sync) 93 | { 94 | INT32 count; 95 | struct buffer_head *bh2; 96 | BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); 97 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 98 | #if EXFAT_CONFIG_KERNEL_DEBUG 99 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 100 | long flags = sbi->debug_flags; 101 | 102 | if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR); 103 | #endif 104 | 105 | if (!p_bd->opened) return(FFS_MEDIAERR); 106 | 107 | if (secno == bh->b_blocknr) { 108 | lock_buffer(bh); 109 | set_buffer_uptodate(bh); 110 | mark_buffer_dirty(bh); 111 | unlock_buffer(bh); 112 | if (sync && (sync_dirty_buffer(bh) != 0)) 113 | return (FFS_MEDIAERR); 114 | } else { 115 | count = num_secs << p_bd->sector_size_bits; 116 | 117 | bh2 = __getblk(sb->s_bdev, secno, count); 118 | 119 | if (bh2 == NULL) 120 | goto no_bh; 121 | 122 | lock_buffer(bh2); 123 | MEMCPY(bh2->b_data, bh->b_data, count); 124 | set_buffer_uptodate(bh2); 125 | mark_buffer_dirty(bh2); 126 | unlock_buffer(bh2); 127 | if (sync && (sync_dirty_buffer(bh2) != 0)) { 128 | __brelse(bh2); 129 | goto no_bh; 130 | } 131 | __brelse(bh2); 132 | } 133 | 134 | return(FFS_SUCCESS); 135 | 136 | no_bh: 137 | WARN(!p_fs->dev_ejected, 138 | "[EXFAT] No bh, device seems wrong or to be ejected.\n"); 139 | 140 | return (FFS_MEDIAERR); 141 | } 142 | 143 | INT32 bdev_sync(struct super_block *sb) 144 | { 145 | BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); 146 | #if EXFAT_CONFIG_KERNEL_DEBUG 147 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 148 | long flags = sbi->debug_flags; 149 | 150 | if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR); 151 | #endif 152 | 153 | if (!p_bd->opened) return(FFS_MEDIAERR); 154 | 155 | return sync_blockdev(sb->s_bdev); 156 | } 157 | -------------------------------------------------------------------------------- /exfat_blkdev.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef _EXFAT_BLKDEV_H 20 | #define _EXFAT_BLKDEV_H 21 | 22 | #include "exfat_config.h" 23 | #include "exfat_global.h" 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | typedef struct __BD_INFO_T { 29 | INT32 sector_size; 30 | INT32 sector_size_bits; 31 | INT32 sector_size_mask; 32 | INT32 num_sectors; 33 | BOOL opened; 34 | } BD_INFO_T; 35 | 36 | INT32 bdev_init(void); 37 | INT32 bdev_shutdown(void); 38 | INT32 bdev_open(struct super_block *sb); 39 | INT32 bdev_close(struct super_block *sb); 40 | INT32 bdev_read(struct super_block *sb, UINT32 secno, struct buffer_head **bh, UINT32 num_secs, INT32 read); 41 | INT32 bdev_write(struct super_block *sb, UINT32 secno, struct buffer_head *bh, UINT32 num_secs, INT32 sync); 42 | INT32 bdev_sync(struct super_block *sb); 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | #endif 47 | -------------------------------------------------------------------------------- /exfat_cache.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include "exfat_config.h" 20 | #include "exfat_global.h" 21 | #include "exfat_data.h" 22 | 23 | #include "exfat_cache.h" 24 | #include "exfat_super.h" 25 | #include "exfat.h" 26 | 27 | extern FS_STRUCT_T fs_struct[]; 28 | 29 | #define sm_P(s) 30 | #define sm_V(s) 31 | 32 | static INT32 __FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content); 33 | static INT32 __FAT_write(struct super_block *sb, UINT32 loc, UINT32 content); 34 | 35 | static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, UINT32 sec); 36 | static BUF_CACHE_T *FAT_cache_get(struct super_block *sb, UINT32 sec); 37 | static void FAT_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp); 38 | static void FAT_cache_remove_hash(BUF_CACHE_T *bp); 39 | 40 | static UINT8 *__buf_getblk(struct super_block *sb, UINT32 sec); 41 | 42 | static BUF_CACHE_T *buf_cache_find(struct super_block *sb, UINT32 sec); 43 | static BUF_CACHE_T *buf_cache_get(struct super_block *sb, UINT32 sec); 44 | static void buf_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp); 45 | static void buf_cache_remove_hash(BUF_CACHE_T *bp); 46 | 47 | static void push_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list); 48 | static void push_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list); 49 | static void move_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list); 50 | static void move_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list); 51 | 52 | INT32 buf_init(struct super_block *sb) 53 | { 54 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 55 | 56 | INT32 i; 57 | 58 | p_fs->FAT_cache_lru_list.next = p_fs->FAT_cache_lru_list.prev = &p_fs->FAT_cache_lru_list; 59 | 60 | for (i = 0; i < FAT_CACHE_SIZE; i++) { 61 | p_fs->FAT_cache_array[i].drv = -1; 62 | p_fs->FAT_cache_array[i].sec = ~0; 63 | p_fs->FAT_cache_array[i].flag = 0; 64 | p_fs->FAT_cache_array[i].buf_bh = NULL; 65 | p_fs->FAT_cache_array[i].prev = p_fs->FAT_cache_array[i].next = NULL; 66 | push_to_mru(&(p_fs->FAT_cache_array[i]), &p_fs->FAT_cache_lru_list); 67 | } 68 | 69 | p_fs->buf_cache_lru_list.next = p_fs->buf_cache_lru_list.prev = &p_fs->buf_cache_lru_list; 70 | 71 | for (i = 0; i < BUF_CACHE_SIZE; i++) { 72 | p_fs->buf_cache_array[i].drv = -1; 73 | p_fs->buf_cache_array[i].sec = ~0; 74 | p_fs->buf_cache_array[i].flag = 0; 75 | p_fs->buf_cache_array[i].buf_bh = NULL; 76 | p_fs->buf_cache_array[i].prev = p_fs->buf_cache_array[i].next = NULL; 77 | push_to_mru(&(p_fs->buf_cache_array[i]), &p_fs->buf_cache_lru_list); 78 | } 79 | 80 | for (i = 0; i < FAT_CACHE_HASH_SIZE; i++) { 81 | p_fs->FAT_cache_hash_list[i].drv = -1; 82 | p_fs->FAT_cache_hash_list[i].sec = ~0; 83 | p_fs->FAT_cache_hash_list[i].hash_next = p_fs->FAT_cache_hash_list[i].hash_prev = &(p_fs->FAT_cache_hash_list[i]); 84 | } 85 | 86 | for (i = 0; i < FAT_CACHE_SIZE; i++) { 87 | FAT_cache_insert_hash(sb, &(p_fs->FAT_cache_array[i])); 88 | } 89 | 90 | for (i = 0; i < BUF_CACHE_HASH_SIZE; i++) { 91 | p_fs->buf_cache_hash_list[i].drv = -1; 92 | p_fs->buf_cache_hash_list[i].sec = ~0; 93 | p_fs->buf_cache_hash_list[i].hash_next = p_fs->buf_cache_hash_list[i].hash_prev = &(p_fs->buf_cache_hash_list[i]); 94 | } 95 | 96 | for (i = 0; i < BUF_CACHE_SIZE; i++) { 97 | buf_cache_insert_hash(sb, &(p_fs->buf_cache_array[i])); 98 | } 99 | 100 | return(FFS_SUCCESS); 101 | } 102 | 103 | INT32 buf_shutdown(struct super_block *sb) 104 | { 105 | return(FFS_SUCCESS); 106 | } 107 | 108 | INT32 FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content) 109 | { 110 | INT32 ret; 111 | 112 | sm_P(&f_sem); 113 | 114 | ret = __FAT_read(sb, loc, content); 115 | 116 | sm_V(&f_sem); 117 | 118 | return(ret); 119 | } 120 | 121 | INT32 FAT_write(struct super_block *sb, UINT32 loc, UINT32 content) 122 | { 123 | INT32 ret; 124 | 125 | sm_P(&f_sem); 126 | 127 | ret = __FAT_write(sb, loc, content); 128 | 129 | sm_V(&f_sem); 130 | 131 | return(ret); 132 | } 133 | 134 | static INT32 __FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content) 135 | { 136 | INT32 off; 137 | UINT32 sec, _content; 138 | UINT8 *fat_sector, *fat_entry; 139 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 140 | BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); 141 | 142 | if (p_fs->vol_type == FAT12) { 143 | sec = p_fs->FAT1_start_sector + ((loc + (loc >> 1)) >> p_bd->sector_size_bits); 144 | off = (loc + (loc >> 1)) & p_bd->sector_size_mask; 145 | 146 | if (off == (p_bd->sector_size-1)) { 147 | fat_sector = FAT_getblk(sb, sec); 148 | if (!fat_sector) 149 | return -1; 150 | 151 | _content = (UINT32) fat_sector[off]; 152 | 153 | fat_sector = FAT_getblk(sb, ++sec); 154 | if (!fat_sector) 155 | return -1; 156 | 157 | _content |= (UINT32) fat_sector[0] << 8; 158 | } else { 159 | fat_sector = FAT_getblk(sb, sec); 160 | if (!fat_sector) 161 | return -1; 162 | 163 | fat_entry = &(fat_sector[off]); 164 | _content = GET16(fat_entry); 165 | } 166 | 167 | if (loc & 1) _content >>= 4; 168 | 169 | _content &= 0x00000FFF; 170 | 171 | if (_content >= CLUSTER_16(0x0FF8)) { 172 | *content = CLUSTER_32(~0); 173 | return 0; 174 | } else { 175 | *content = CLUSTER_32(_content); 176 | return 0; 177 | } 178 | } else if (p_fs->vol_type == FAT16) { 179 | sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-1)); 180 | off = (loc << 1) & p_bd->sector_size_mask; 181 | 182 | fat_sector = FAT_getblk(sb, sec); 183 | if 184 | (!fat_sector) 185 | return -1; 186 | 187 | fat_entry = &(fat_sector[off]); 188 | 189 | _content = GET16_A(fat_entry); 190 | 191 | _content &= 0x0000FFFF; 192 | 193 | if (_content >= CLUSTER_16(0xFFF8)) { 194 | *content = CLUSTER_32(~0); 195 | return 0; 196 | } else { 197 | *content = CLUSTER_32(_content); 198 | return 0; 199 | } 200 | } else if (p_fs->vol_type == FAT32) { 201 | sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2)); 202 | off = (loc << 2) & p_bd->sector_size_mask; 203 | 204 | fat_sector = FAT_getblk(sb, sec); 205 | if (!fat_sector) 206 | return -1; 207 | 208 | fat_entry = &(fat_sector[off]); 209 | 210 | _content = GET32_A(fat_entry); 211 | 212 | _content &= 0x0FFFFFFF; 213 | 214 | if (_content >= CLUSTER_32(0x0FFFFFF8)) { 215 | *content = CLUSTER_32(~0); 216 | return 0; 217 | } else { 218 | *content = CLUSTER_32(_content); 219 | return 0; 220 | } 221 | } else { 222 | sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2)); 223 | off = (loc << 2) & p_bd->sector_size_mask; 224 | 225 | fat_sector = FAT_getblk(sb, sec); 226 | if (!fat_sector) 227 | return -1; 228 | 229 | fat_entry = &(fat_sector[off]); 230 | _content = GET32_A(fat_entry); 231 | 232 | if (_content >= CLUSTER_32(0xFFFFFFF8)) { 233 | *content = CLUSTER_32(~0); 234 | return 0; 235 | } else { 236 | *content = CLUSTER_32(_content); 237 | return 0; 238 | } 239 | } 240 | 241 | *content = CLUSTER_32(~0); 242 | return 0; 243 | } 244 | 245 | static INT32 __FAT_write(struct super_block *sb, UINT32 loc, UINT32 content) 246 | { 247 | INT32 off; 248 | UINT32 sec; 249 | UINT8 *fat_sector, *fat_entry; 250 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 251 | BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); 252 | 253 | if (p_fs->vol_type == FAT12) { 254 | 255 | content &= 0x00000FFF; 256 | 257 | sec = p_fs->FAT1_start_sector + ((loc + (loc >> 1)) >> p_bd->sector_size_bits); 258 | off = (loc + (loc >> 1)) & p_bd->sector_size_mask; 259 | 260 | fat_sector = FAT_getblk(sb, sec); 261 | if (!fat_sector) 262 | return -1; 263 | 264 | if (loc & 1) { 265 | 266 | content <<= 4; 267 | 268 | if (off == (p_bd->sector_size-1)) { 269 | fat_sector[off] = (UINT8)(content | (fat_sector[off] & 0x0F)); 270 | FAT_modify(sb, sec); 271 | 272 | fat_sector = FAT_getblk(sb, ++sec); 273 | if (!fat_sector) 274 | return -1; 275 | 276 | fat_sector[0] = (UINT8)(content >> 8); 277 | } else { 278 | fat_entry = &(fat_sector[off]); 279 | content |= GET16(fat_entry) & 0x000F; 280 | 281 | SET16(fat_entry, content); 282 | } 283 | } else { 284 | fat_sector[off] = (UINT8)(content); 285 | 286 | if (off == (p_bd->sector_size-1)) { 287 | fat_sector[off] = (UINT8)(content); 288 | FAT_modify(sb, sec); 289 | 290 | fat_sector = FAT_getblk(sb, ++sec); 291 | fat_sector[0] = (UINT8)((fat_sector[0] & 0xF0) | (content >> 8)); 292 | } else { 293 | fat_entry = &(fat_sector[off]); 294 | content |= GET16(fat_entry) & 0xF000; 295 | 296 | SET16(fat_entry, content); 297 | } 298 | } 299 | } 300 | 301 | else if (p_fs->vol_type == FAT16) { 302 | 303 | content &= 0x0000FFFF; 304 | 305 | sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-1)); 306 | off = (loc << 1) & p_bd->sector_size_mask; 307 | 308 | fat_sector = FAT_getblk(sb, sec); 309 | if (!fat_sector) 310 | return -1; 311 | 312 | fat_entry = &(fat_sector[off]); 313 | 314 | SET16_A(fat_entry, content); 315 | } 316 | 317 | else if (p_fs->vol_type == FAT32) { 318 | 319 | content &= 0x0FFFFFFF; 320 | 321 | sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2)); 322 | off = (loc << 2) & p_bd->sector_size_mask; 323 | 324 | fat_sector = FAT_getblk(sb, sec); 325 | if (!fat_sector) 326 | return -1; 327 | 328 | fat_entry = &(fat_sector[off]); 329 | 330 | content |= GET32_A(fat_entry) & 0xF0000000; 331 | 332 | SET32_A(fat_entry, content); 333 | } 334 | 335 | else { 336 | 337 | sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2)); 338 | off = (loc << 2) & p_bd->sector_size_mask; 339 | 340 | fat_sector = FAT_getblk(sb, sec); 341 | if (!fat_sector) 342 | return -1; 343 | 344 | fat_entry = &(fat_sector[off]); 345 | 346 | SET32_A(fat_entry, content); 347 | } 348 | 349 | FAT_modify(sb, sec); 350 | return 0; 351 | } 352 | 353 | UINT8 *FAT_getblk(struct super_block *sb, UINT32 sec) 354 | { 355 | BUF_CACHE_T *bp; 356 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 357 | 358 | bp = FAT_cache_find(sb, sec); 359 | if (bp != NULL) { 360 | move_to_mru(bp, &p_fs->FAT_cache_lru_list); 361 | return(bp->buf_bh->b_data); 362 | } 363 | 364 | bp = FAT_cache_get(sb, sec); 365 | 366 | FAT_cache_remove_hash(bp); 367 | 368 | bp->drv = p_fs->drv; 369 | bp->sec = sec; 370 | bp->flag = 0; 371 | 372 | FAT_cache_insert_hash(sb, bp); 373 | 374 | if (sector_read(sb, sec, &(bp->buf_bh), 1) != FFS_SUCCESS) { 375 | FAT_cache_remove_hash(bp); 376 | bp->drv = -1; 377 | bp->sec = ~0; 378 | bp->flag = 0; 379 | bp->buf_bh = NULL; 380 | 381 | move_to_lru(bp, &p_fs->FAT_cache_lru_list); 382 | return NULL; 383 | } 384 | 385 | return(bp->buf_bh->b_data); 386 | } 387 | 388 | void FAT_modify(struct super_block *sb, UINT32 sec) 389 | { 390 | BUF_CACHE_T *bp; 391 | 392 | bp = FAT_cache_find(sb, sec); 393 | if (bp != NULL) { 394 | sector_write(sb, sec, bp->buf_bh, 0); 395 | } 396 | } 397 | 398 | void FAT_release_all(struct super_block *sb) 399 | { 400 | BUF_CACHE_T *bp; 401 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 402 | 403 | sm_P(&f_sem); 404 | 405 | bp = p_fs->FAT_cache_lru_list.next; 406 | while (bp != &p_fs->FAT_cache_lru_list) { 407 | if (bp->drv == p_fs->drv) { 408 | bp->drv = -1; 409 | bp->sec = ~0; 410 | bp->flag = 0; 411 | 412 | if(bp->buf_bh) { 413 | __brelse(bp->buf_bh); 414 | bp->buf_bh = NULL; 415 | } 416 | } 417 | bp = bp->next; 418 | } 419 | 420 | sm_V(&f_sem); 421 | } 422 | 423 | void FAT_sync(struct super_block *sb) 424 | { 425 | BUF_CACHE_T *bp; 426 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 427 | 428 | sm_P(&f_sem); 429 | 430 | bp = p_fs->FAT_cache_lru_list.next; 431 | while (bp != &p_fs->FAT_cache_lru_list) { 432 | if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) { 433 | sync_dirty_buffer(bp->buf_bh); 434 | bp->flag &= ~(DIRTYBIT); 435 | } 436 | bp = bp->next; 437 | } 438 | 439 | sm_V(&f_sem); 440 | } 441 | 442 | static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, UINT32 sec) 443 | { 444 | INT32 off; 445 | BUF_CACHE_T *bp, *hp; 446 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 447 | 448 | off = (sec + (sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE - 1); 449 | 450 | hp = &(p_fs->FAT_cache_hash_list[off]); 451 | for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) { 452 | if ((bp->drv == p_fs->drv) && (bp->sec == sec)) { 453 | 454 | WARN(!bp->buf_bh, "[EXFAT] FAT_cache has no bh. " 455 | "It will make system panic.\n"); 456 | 457 | touch_buffer(bp->buf_bh); 458 | return(bp); 459 | } 460 | } 461 | return(NULL); 462 | } 463 | 464 | static BUF_CACHE_T *FAT_cache_get(struct super_block *sb, UINT32 sec) 465 | { 466 | BUF_CACHE_T *bp; 467 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 468 | 469 | bp = p_fs->FAT_cache_lru_list.prev; 470 | 471 | 472 | move_to_mru(bp, &p_fs->FAT_cache_lru_list); 473 | return(bp); 474 | } 475 | 476 | static void FAT_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp) 477 | { 478 | INT32 off; 479 | BUF_CACHE_T *hp; 480 | FS_INFO_T *p_fs; 481 | 482 | p_fs = &(EXFAT_SB(sb)->fs_info); 483 | off = (bp->sec + (bp->sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE-1); 484 | 485 | hp = &(p_fs->FAT_cache_hash_list[off]); 486 | bp->hash_next = hp->hash_next; 487 | bp->hash_prev = hp; 488 | hp->hash_next->hash_prev = bp; 489 | hp->hash_next = bp; 490 | } 491 | 492 | static void FAT_cache_remove_hash(BUF_CACHE_T *bp) 493 | { 494 | (bp->hash_prev)->hash_next = bp->hash_next; 495 | (bp->hash_next)->hash_prev = bp->hash_prev; 496 | } 497 | 498 | UINT8 *buf_getblk(struct super_block *sb, UINT32 sec) 499 | { 500 | UINT8 *buf; 501 | 502 | sm_P(&b_sem); 503 | 504 | buf = __buf_getblk(sb, sec); 505 | 506 | sm_V(&b_sem); 507 | 508 | return(buf); 509 | } 510 | 511 | static UINT8 *__buf_getblk(struct super_block *sb, UINT32 sec) 512 | { 513 | BUF_CACHE_T *bp; 514 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 515 | 516 | bp = buf_cache_find(sb, sec); 517 | if (bp != NULL) { 518 | move_to_mru(bp, &p_fs->buf_cache_lru_list); 519 | return(bp->buf_bh->b_data); 520 | } 521 | 522 | bp = buf_cache_get(sb, sec); 523 | 524 | buf_cache_remove_hash(bp); 525 | 526 | bp->drv = p_fs->drv; 527 | bp->sec = sec; 528 | bp->flag = 0; 529 | 530 | buf_cache_insert_hash(sb, bp); 531 | 532 | if (sector_read(sb, sec, &(bp->buf_bh), 1) != FFS_SUCCESS) { 533 | buf_cache_remove_hash(bp); 534 | bp->drv = -1; 535 | bp->sec = ~0; 536 | bp->flag = 0; 537 | bp->buf_bh = NULL; 538 | 539 | move_to_lru(bp, &p_fs->buf_cache_lru_list); 540 | return NULL; 541 | } 542 | 543 | return(bp->buf_bh->b_data); 544 | 545 | } 546 | 547 | void buf_modify(struct super_block *sb, UINT32 sec) 548 | { 549 | BUF_CACHE_T *bp; 550 | 551 | sm_P(&b_sem); 552 | 553 | bp = buf_cache_find(sb, sec); 554 | if (likely(bp != NULL)) { 555 | sector_write(sb, sec, bp->buf_bh, 0); 556 | } 557 | 558 | WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec); 559 | 560 | sm_V(&b_sem); 561 | } 562 | 563 | void buf_lock(struct super_block *sb, UINT32 sec) 564 | { 565 | BUF_CACHE_T *bp; 566 | 567 | sm_P(&b_sem); 568 | 569 | bp = buf_cache_find(sb, sec); 570 | if (likely(bp != NULL)) bp->flag |= LOCKBIT; 571 | 572 | WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec); 573 | 574 | sm_V(&b_sem); 575 | } 576 | 577 | void buf_unlock(struct super_block *sb, UINT32 sec) 578 | { 579 | BUF_CACHE_T *bp; 580 | 581 | sm_P(&b_sem); 582 | 583 | bp = buf_cache_find(sb, sec); 584 | if (likely(bp != NULL)) bp->flag &= ~(LOCKBIT); 585 | 586 | WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec); 587 | 588 | sm_V(&b_sem); 589 | } 590 | 591 | void buf_release(struct super_block *sb, UINT32 sec) 592 | { 593 | BUF_CACHE_T *bp; 594 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 595 | 596 | sm_P(&b_sem); 597 | 598 | bp = buf_cache_find(sb, sec); 599 | if (likely(bp != NULL)) { 600 | bp->drv = -1; 601 | bp->sec = ~0; 602 | bp->flag = 0; 603 | 604 | if(bp->buf_bh) { 605 | __brelse(bp->buf_bh); 606 | bp->buf_bh = NULL; 607 | } 608 | 609 | move_to_lru(bp, &p_fs->buf_cache_lru_list); 610 | } 611 | 612 | sm_V(&b_sem); 613 | } 614 | 615 | void buf_release_all(struct super_block *sb) 616 | { 617 | BUF_CACHE_T *bp; 618 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 619 | 620 | sm_P(&b_sem); 621 | 622 | bp = p_fs->buf_cache_lru_list.next; 623 | while (bp != &p_fs->buf_cache_lru_list) { 624 | if (bp->drv == p_fs->drv) { 625 | bp->drv = -1; 626 | bp->sec = ~0; 627 | bp->flag = 0; 628 | 629 | if(bp->buf_bh) { 630 | __brelse(bp->buf_bh); 631 | bp->buf_bh = NULL; 632 | } 633 | } 634 | bp = bp->next; 635 | } 636 | 637 | sm_V(&b_sem); 638 | } 639 | 640 | void buf_sync(struct super_block *sb) 641 | { 642 | BUF_CACHE_T *bp; 643 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 644 | 645 | sm_P(&b_sem); 646 | 647 | bp = p_fs->buf_cache_lru_list.next; 648 | while (bp != &p_fs->buf_cache_lru_list) { 649 | if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) { 650 | sync_dirty_buffer(bp->buf_bh); 651 | bp->flag &= ~(DIRTYBIT); 652 | } 653 | bp = bp->next; 654 | } 655 | 656 | sm_V(&b_sem); 657 | } 658 | 659 | static BUF_CACHE_T *buf_cache_find(struct super_block *sb, UINT32 sec) 660 | { 661 | INT32 off; 662 | BUF_CACHE_T *bp, *hp; 663 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 664 | 665 | off = (sec + (sec >> p_fs->sectors_per_clu_bits)) & (BUF_CACHE_HASH_SIZE - 1); 666 | 667 | hp = &(p_fs->buf_cache_hash_list[off]); 668 | for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) { 669 | if ((bp->drv == p_fs->drv) && (bp->sec == sec)) { 670 | touch_buffer(bp->buf_bh); 671 | return(bp); 672 | } 673 | } 674 | return(NULL); 675 | } 676 | 677 | static BUF_CACHE_T *buf_cache_get(struct super_block *sb, UINT32 sec) 678 | { 679 | BUF_CACHE_T *bp; 680 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 681 | 682 | bp = p_fs->buf_cache_lru_list.prev; 683 | while (bp->flag & LOCKBIT) bp = bp->prev; 684 | 685 | 686 | move_to_mru(bp, &p_fs->buf_cache_lru_list); 687 | return(bp); 688 | } 689 | 690 | static void buf_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp) 691 | { 692 | INT32 off; 693 | BUF_CACHE_T *hp; 694 | FS_INFO_T *p_fs; 695 | 696 | p_fs = &(EXFAT_SB(sb)->fs_info); 697 | off = (bp->sec + (bp->sec >> p_fs->sectors_per_clu_bits)) & (BUF_CACHE_HASH_SIZE-1); 698 | 699 | hp = &(p_fs->buf_cache_hash_list[off]); 700 | bp->hash_next = hp->hash_next; 701 | bp->hash_prev = hp; 702 | hp->hash_next->hash_prev = bp; 703 | hp->hash_next = bp; 704 | } 705 | 706 | static void buf_cache_remove_hash(BUF_CACHE_T *bp) 707 | { 708 | (bp->hash_prev)->hash_next = bp->hash_next; 709 | (bp->hash_next)->hash_prev = bp->hash_prev; 710 | } 711 | 712 | static void push_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list) 713 | { 714 | bp->next = list->next; 715 | bp->prev = list; 716 | list->next->prev = bp; 717 | list->next = bp; 718 | } 719 | 720 | static void push_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list) 721 | { 722 | bp->prev = list->prev; 723 | bp->next = list; 724 | list->prev->next = bp; 725 | list->prev = bp; 726 | } 727 | 728 | static void move_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list) 729 | { 730 | bp->prev->next = bp->next; 731 | bp->next->prev = bp->prev; 732 | push_to_mru(bp, list); 733 | } 734 | 735 | static void move_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list) 736 | { 737 | bp->prev->next = bp->next; 738 | bp->next->prev = bp->prev; 739 | push_to_lru(bp, list); 740 | } 741 | -------------------------------------------------------------------------------- /exfat_cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef _EXFAT_CACHE_H 20 | #define _EXFAT_CACHE_H 21 | 22 | #include "exfat_config.h" 23 | #include "exfat_global.h" 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | #define LOCKBIT 0x01 30 | #define DIRTYBIT 0x02 31 | 32 | typedef struct __BUF_CACHE_T { 33 | struct __BUF_CACHE_T *next; 34 | struct __BUF_CACHE_T *prev; 35 | struct __BUF_CACHE_T *hash_next; 36 | struct __BUF_CACHE_T *hash_prev; 37 | INT32 drv; 38 | UINT32 sec; 39 | UINT32 flag; 40 | struct buffer_head *buf_bh; 41 | } BUF_CACHE_T; 42 | 43 | INT32 buf_init(struct super_block *sb); 44 | INT32 buf_shutdown(struct super_block *sb); 45 | INT32 FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content); 46 | INT32 FAT_write(struct super_block *sb, UINT32 loc, UINT32 content); 47 | UINT8 *FAT_getblk(struct super_block *sb, UINT32 sec); 48 | void FAT_modify(struct super_block *sb, UINT32 sec); 49 | void FAT_release_all(struct super_block *sb); 50 | void FAT_sync(struct super_block *sb); 51 | UINT8 *buf_getblk(struct super_block *sb, UINT32 sec); 52 | void buf_modify(struct super_block *sb, UINT32 sec); 53 | void buf_lock(struct super_block *sb, UINT32 sec); 54 | void buf_unlock(struct super_block *sb, UINT32 sec); 55 | void buf_release(struct super_block *sb, UINT32 sec); 56 | void buf_release_all(struct super_block *sb); 57 | void buf_sync(struct super_block *sb); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /exfat_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef _EXFAT_CONFIG_H 20 | #define _EXFAT_CONFIG_H 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | #define OS_NONOS 1 27 | #define OS_LINUX 2 28 | 29 | #define FFS_CONFIG_OS OS_LINUX 30 | 31 | #define FFS_CONFIG_LITTLE_ENDIAN 1 32 | #define FFS_CONFIG_LEGACY_32BIT_API 0 33 | #define FFS_CONFIG_LEGACY_32BIT_API 0 34 | #define FFS_CONFIG_SUPPORT_CP1250 1 35 | #define FFS_CONFIG_SUPPORT_CP1251 1 36 | #define FFS_CONFIG_SUPPORT_CP1252 1 37 | #define FFS_CONFIG_SUPPORT_CP1253 1 38 | #define FFS_CONFIG_SUPPORT_CP1254 1 39 | #define FFS_CONFIG_SUPPORT_CP1255 1 40 | #define FFS_CONFIG_SUPPORT_CP1256 1 41 | #define FFS_CONFIG_SUPPORT_CP1257 1 42 | #define FFS_CONFIG_SUPPORT_CP1258 1 43 | #define FFS_CONFIG_SUPPORT_CP874 1 44 | #define FFS_CONFIG_SUPPORT_CP932 1 45 | #define FFS_CONFIG_SUPPORT_CP936 1 46 | #define FFS_CONFIG_SUPPORT_CP949 1 47 | #define FFS_CONFIG_SUPPORT_CP950 1 48 | #define FFS_CONFIG_SUPPORT_UTF8 1 49 | #define EXFAT_CONFIG_DISCARD 1 50 | #define EXFAT_CONFIG_KERNEL_DEBUG 1 51 | #define EXFAT_CONFIG_DEBUG_MSG 0 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /exfat_data.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include "exfat_config.h" 20 | #include "exfat_global.h" 21 | #include "exfat_data.h" 22 | #include "exfat_oal.h" 23 | 24 | #include "exfat_blkdev.h" 25 | #include "exfat_cache.h" 26 | #include "exfat_nls.h" 27 | #include "exfat_super.h" 28 | #include "exfat.h" 29 | 30 | FS_STRUCT_T fs_struct[MAX_DRIVE]; 31 | 32 | DECLARE_MUTEX(f_sem); 33 | BUF_CACHE_T FAT_cache_array[FAT_CACHE_SIZE]; 34 | BUF_CACHE_T FAT_cache_lru_list; 35 | BUF_CACHE_T FAT_cache_hash_list[FAT_CACHE_HASH_SIZE]; 36 | 37 | DECLARE_MUTEX(b_sem); 38 | BUF_CACHE_T buf_cache_array[BUF_CACHE_SIZE]; 39 | BUF_CACHE_T buf_cache_lru_list; 40 | BUF_CACHE_T buf_cache_hash_list[BUF_CACHE_HASH_SIZE]; 41 | -------------------------------------------------------------------------------- /exfat_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef _EXFAT_DATA_H 20 | #define _EXFAT_DATA_H 21 | #include "exfat_config.h" 22 | #include "exfat_global.h" 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | #define MAX_DEVICE 2 27 | #define MAX_DRIVE 2 28 | #define MAX_OPEN 20 29 | #define MAX_DENTRY 512 30 | #define FAT_CACHE_SIZE 128 31 | #define FAT_CACHE_HASH_SIZE 64 32 | #define BUF_CACHE_SIZE 256 33 | #define BUF_CACHE_HASH_SIZE 64 34 | #define DEFAULT_CODEPAGE 437 35 | #define DEFAULT_IOCHARSET "utf8" 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | #endif 40 | -------------------------------------------------------------------------------- /exfat_global.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include "exfat_config.h" 20 | #include "exfat_global.h" 21 | 22 | INT32 __wstrchr(UINT16 *str, UINT16 wchar) 23 | { 24 | while (*str) { 25 | if (*(str++) == wchar) return(1); 26 | } 27 | return(0); 28 | } 29 | 30 | INT32 __wstrlen(UINT16 *str) 31 | { 32 | INT32 length = 0; 33 | 34 | while (*(str++)) length++; 35 | return(length); 36 | } 37 | 38 | #define BITMAP_LOC(v) ((v) >> 3) 39 | #define BITMAP_SHIFT(v) ((v) & 0x07) 40 | 41 | void Bitmap_set_all(UINT8 *bitmap, INT32 mapsize) 42 | { 43 | MEMSET(bitmap, 0xFF, mapsize); 44 | } 45 | 46 | void Bitmap_clear_all(UINT8 *bitmap, INT32 mapsize) 47 | { 48 | MEMSET(bitmap, 0x0, mapsize); 49 | } 50 | 51 | INT32 Bitmap_test(UINT8 *bitmap, INT32 i) 52 | { 53 | UINT8 data; 54 | 55 | data = bitmap[BITMAP_LOC(i)]; 56 | if ((data >> BITMAP_SHIFT(i)) & 0x01) return(1); 57 | return(0); 58 | } 59 | 60 | void Bitmap_set(UINT8 *bitmap, INT32 i) 61 | { 62 | bitmap[BITMAP_LOC(i)] |= (0x01 << BITMAP_SHIFT(i)); 63 | } 64 | 65 | void Bitmap_clear(UINT8 *bitmap, INT32 i) 66 | { 67 | bitmap[BITMAP_LOC(i)] &= ~(0x01 << BITMAP_SHIFT(i)); 68 | } 69 | 70 | void Bitmap_nbits_set(UINT8 *bitmap, INT32 offset, INT32 nbits) 71 | { 72 | INT32 i; 73 | 74 | for (i = 0; i < nbits; i++) { 75 | Bitmap_set(bitmap, offset+i); 76 | } 77 | } 78 | 79 | void Bitmap_nbits_clear(UINT8 *bitmap, INT32 offset, INT32 nbits) 80 | { 81 | INT32 i; 82 | 83 | for (i = 0; i < nbits; i++) { 84 | Bitmap_clear(bitmap, offset+i); 85 | } 86 | } 87 | 88 | void my_itoa(INT8 *buf, INT32 v) 89 | { 90 | INT32 mod[10]; 91 | INT32 i; 92 | 93 | for (i = 0; i < 10; i++) { 94 | mod[i] = (v % 10); 95 | v = v / 10; 96 | if (v == 0) break; 97 | } 98 | 99 | if (i == 10) 100 | i--; 101 | 102 | for (; i >= 0; i--) { 103 | *buf = (UINT8) ('0' + mod[i]); 104 | buf++; 105 | } 106 | *buf = '\0'; 107 | } 108 | 109 | INT32 my_log2(UINT32 v) 110 | { 111 | UINT32 bits = 0; 112 | 113 | while (v > 1) { 114 | if (v & 0x01) return(-1); 115 | v >>= 1; 116 | bits++; 117 | } 118 | return(bits); 119 | } 120 | -------------------------------------------------------------------------------- /exfat_global.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef _EXFAT_GLOBAL_H 20 | #define _EXFAT_GLOBAL_H 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "exfat_config.h" 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | #ifndef TRUE 35 | #define TRUE 1 36 | #endif 37 | #ifndef FALSE 38 | #define FALSE 0 39 | #endif 40 | #ifndef OK 41 | #define OK 0 42 | #endif 43 | #ifndef FAIL 44 | #define FAIL 1 45 | #endif 46 | #ifndef NULL 47 | #define NULL 0 48 | #endif 49 | 50 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 51 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 52 | 53 | typedef char INT8; 54 | typedef short INT16; 55 | typedef int INT32; 56 | typedef long long INT64; 57 | typedef unsigned char UINT8; 58 | typedef unsigned short UINT16; 59 | typedef unsigned int UINT32; 60 | typedef unsigned long long UINT64; 61 | typedef unsigned char BOOL; 62 | 63 | #ifdef MALLOC 64 | #undef MALLOC 65 | #endif 66 | #ifdef FREE 67 | #undef FREE 68 | #endif 69 | #ifdef MEMSET 70 | #undef MEMSET 71 | #endif 72 | #ifdef MEMCPY 73 | #undef MEMCPY 74 | #endif 75 | #ifdef MEMCMP 76 | #undef MEMCMP 77 | #endif 78 | 79 | #define MALLOC(size) kmalloc(size, GFP_KERNEL) 80 | #define FREE(mem) if (mem) kfree(mem) 81 | #define MEMSET(mem, value, size) memset(mem, value, size) 82 | #define MEMCPY(dest, src, size) memcpy(dest, src, size) 83 | #define MEMCMP(mem1, mem2, size) memcmp(mem1, mem2, size) 84 | #define COPY_DENTRY(dest, src) memcpy(dest, src, sizeof(DENTRY_T)) 85 | 86 | #define STRCPY(dest, src) strcpy(dest, src) 87 | #define STRNCPY(dest, src, n) strncpy(dest, src, n) 88 | #define STRCAT(str1, str2) strcat(str1, str2) 89 | #define STRCMP(str1, str2) strcmp(str1, str2) 90 | #define STRNCMP(str1, str2, n) strncmp(str1, str2, n) 91 | #define STRLEN(str) strlen(str) 92 | 93 | INT32 __wstrchr(UINT16 *str, UINT16 wchar); 94 | INT32 __wstrlen(UINT16 *str); 95 | 96 | #define WSTRCHR(str, wchar) __wstrchr(str, wchar) 97 | #define WSTRLEN(str) __wstrlen(str) 98 | 99 | #if EXFAT_CONFIG_DEBUG_MSG 100 | #define PRINTK(...) \ 101 | do { \ 102 | printk("[EXFAT] " __VA_ARGS__); \ 103 | } while(0) 104 | #else 105 | #define PRINTK(...) 106 | #endif 107 | 108 | void Bitmap_set_all(UINT8 *bitmap, INT32 mapsize); 109 | void Bitmap_clear_all(UINT8 *bitmap, INT32 mapsize); 110 | INT32 Bitmap_test(UINT8 *bitmap, INT32 i); 111 | void Bitmap_set(UINT8 *bitmap, INT32 i); 112 | void Bitmap_clear(UINT8 *bitmpa, INT32 i); 113 | void Bitmap_nbits_set(UINT8 *bitmap, INT32 offset, INT32 nbits); 114 | void Bitmap_nbits_clear(UINT8 *bitmap, INT32 offset, INT32 nbits); 115 | 116 | void my_itoa(INT8 *buf, INT32 v); 117 | INT32 my_log2(UINT32 v); 118 | 119 | #ifdef PRINT 120 | #undef PRINT 121 | #endif 122 | 123 | #define PRINT printk 124 | #ifdef __cplusplus 125 | } 126 | #endif 127 | #endif 128 | -------------------------------------------------------------------------------- /exfat_nls.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include "exfat_config.h" 20 | #include "exfat_global.h" 21 | #include "exfat_data.h" 22 | 23 | #include "exfat_nls.h" 24 | #include "exfat_api.h" 25 | #include "exfat_super.h" 26 | #include "exfat.h" 27 | 28 | #include 29 | 30 | static UINT16 bad_dos_chars[] = { 31 | 0x002B, 0x002C, 0x003B, 0x003D, 0x005B, 0x005D, 32 | 0xFF0B, 0xFF0C, 0xFF1B, 0xFF1D, 0xFF3B, 0xFF3D, 33 | 0 34 | }; 35 | 36 | static UINT16 bad_uni_chars[] = { 37 | 0x0022, 0x002A, 0x002F, 0x003A, 38 | 0x003C, 0x003E, 0x003F, 0x005C, 0x007C, 39 | 0 40 | }; 41 | 42 | static INT32 convert_uni_to_ch(struct nls_table *nls, UINT8 *ch, UINT16 uni, INT32 *lossy); 43 | static INT32 convert_ch_to_uni(struct nls_table *nls, UINT16 *uni, UINT8 *ch, INT32 *lossy); 44 | 45 | UINT16 nls_upper(struct super_block *sb, UINT16 a) 46 | { 47 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 48 | 49 | if (EXFAT_SB(sb)->options.casesensitive) 50 | return(a); 51 | if ((p_fs->vol_utbl)[get_col_index(a)] != NULL) 52 | return (p_fs->vol_utbl)[get_col_index(a)][get_row_index(a)]; 53 | else 54 | return a; 55 | } 56 | 57 | INT32 nls_dosname_cmp(struct super_block *sb, UINT8 *a, UINT8 *b) 58 | { 59 | return(STRNCMP((void *) a, (void *) b, DOS_NAME_LENGTH)); 60 | } 61 | 62 | INT32 nls_uniname_cmp(struct super_block *sb, UINT16 *a, UINT16 *b) 63 | { 64 | INT32 i; 65 | 66 | for (i = 0; i < MAX_NAME_LENGTH; i++, a++, b++) { 67 | if (nls_upper(sb, *a) != nls_upper(sb, *b)) return(1); 68 | if (*a == 0x0) return(0); 69 | } 70 | return(0); 71 | } 72 | 73 | void nls_uniname_to_dosname(struct super_block *sb, DOS_NAME_T *p_dosname, UNI_NAME_T *p_uniname, INT32 *p_lossy) 74 | { 75 | INT32 i, j, len, lossy = FALSE; 76 | UINT8 buf[MAX_CHARSET_SIZE]; 77 | UINT8 lower = 0, upper = 0; 78 | UINT8 *dosname = p_dosname->name; 79 | UINT16 *uniname = p_uniname->name; 80 | UINT16 *p, *last_period; 81 | struct nls_table *nls = EXFAT_SB(sb)->nls_disk; 82 | 83 | for (i = 0; i < DOS_NAME_LENGTH; i++) { 84 | *(dosname+i) = ' '; 85 | } 86 | 87 | if (!nls_uniname_cmp(sb, uniname, (UINT16 *) UNI_CUR_DIR_NAME)) { 88 | *(dosname) = '.'; 89 | p_dosname->name_case = 0x0; 90 | if (p_lossy != NULL) *p_lossy = FALSE; 91 | return; 92 | } 93 | 94 | if (!nls_uniname_cmp(sb, uniname, (UINT16 *) UNI_PAR_DIR_NAME)) { 95 | *(dosname) = '.'; 96 | *(dosname+1) = '.'; 97 | p_dosname->name_case = 0x0; 98 | if (p_lossy != NULL) *p_lossy = FALSE; 99 | return; 100 | } 101 | 102 | last_period = NULL; 103 | for (p = uniname; *p; p++) { 104 | if (*p == (UINT16) '.') last_period = p; 105 | } 106 | 107 | i = 0; 108 | while (i < DOS_NAME_LENGTH) { 109 | if (i == 8) { 110 | if (last_period == NULL) break; 111 | 112 | if (uniname <= last_period) { 113 | if (uniname < last_period) lossy = TRUE; 114 | uniname = last_period + 1; 115 | } 116 | } 117 | 118 | if (*uniname == (UINT16) '\0') { 119 | break; 120 | } else if (*uniname == (UINT16) ' ') { 121 | lossy = TRUE; 122 | } else if (*uniname == (UINT16) '.') { 123 | if (uniname < last_period) lossy = TRUE; 124 | else i = 8; 125 | } else if (WSTRCHR(bad_dos_chars, *uniname)) { 126 | lossy = TRUE; 127 | *(dosname+i) = '_'; 128 | i++; 129 | } else { 130 | len = convert_uni_to_ch(nls, buf, *uniname, &lossy); 131 | 132 | if (len > 1) { 133 | if ((i >= 8) && ((i+len) > DOS_NAME_LENGTH)) { 134 | break; 135 | } 136 | if ((i < 8) && ((i+len) > 8)) { 137 | i = 8; 138 | continue; 139 | } 140 | 141 | lower = 0xFF; 142 | 143 | for (j = 0; j < len; j++, i++) { 144 | *(dosname+i) = *(buf+j); 145 | } 146 | } else { 147 | if ((*buf >= 'a') && (*buf <= 'z')) { 148 | *(dosname+i) = *buf - ('a' - 'A'); 149 | 150 | if (i < 8) lower |= 0x08; 151 | else lower |= 0x10; 152 | } else if ((*buf >= 'A') && (*buf <= 'Z')) { 153 | *(dosname+i) = *buf; 154 | 155 | if (i < 8) upper |= 0x08; 156 | else upper |= 0x10; 157 | } else { 158 | *(dosname+i) = *buf; 159 | } 160 | i++; 161 | } 162 | } 163 | 164 | uniname++; 165 | } 166 | 167 | if (*dosname == 0xE5) *dosname = 0x05; 168 | if (*uniname != 0x0) lossy = TRUE; 169 | 170 | if (upper & lower) p_dosname->name_case = 0xFF; 171 | else p_dosname->name_case = lower; 172 | 173 | if (p_lossy != NULL) *p_lossy = lossy; 174 | } 175 | 176 | void nls_dosname_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname) 177 | { 178 | INT32 i = 0, j, n = 0; 179 | UINT8 buf[DOS_NAME_LENGTH+2]; 180 | UINT8 *dosname = p_dosname->name; 181 | UINT16 *uniname = p_uniname->name; 182 | struct nls_table *nls = EXFAT_SB(sb)->nls_disk; 183 | 184 | if (*dosname == 0x05) { 185 | *buf = 0xE5; 186 | i++; 187 | n++; 188 | } 189 | 190 | for ( ; i < 8; i++, n++) { 191 | if (*(dosname+i) == ' ') break; 192 | 193 | if ((*(dosname+i) >= 'A') && (*(dosname+i) <= 'Z') && (p_dosname->name_case & 0x08)) 194 | *(buf+n) = *(dosname+i) + ('a' - 'A'); 195 | else 196 | *(buf+n) = *(dosname+i); 197 | } 198 | if (*(dosname+8) != ' ') { 199 | *(buf+n) = '.'; 200 | n++; 201 | } 202 | 203 | for (i = 8; i < DOS_NAME_LENGTH; i++, n++) { 204 | if (*(dosname+i) == ' ') break; 205 | 206 | if ((*(dosname+i) >= 'A') && (*(dosname+i) <= 'Z') && (p_dosname->name_case & 0x10)) 207 | *(buf+n) = *(dosname+i) + ('a' - 'A'); 208 | else 209 | *(buf+n) = *(dosname+i); 210 | } 211 | *(buf+n) = '\0'; 212 | 213 | i = j = 0; 214 | while (j < (MAX_NAME_LENGTH-1)) { 215 | if (*(buf+i) == '\0') break; 216 | 217 | i += convert_ch_to_uni(nls, uniname, (buf+i), NULL); 218 | 219 | uniname++; 220 | j++; 221 | } 222 | 223 | *uniname = (UINT16) '\0'; 224 | } 225 | 226 | void nls_uniname_to_cstring(struct super_block *sb, UINT8 *p_cstring, UNI_NAME_T *p_uniname) 227 | { 228 | INT32 i, j, len; 229 | UINT8 buf[MAX_CHARSET_SIZE]; 230 | UINT16 *uniname = p_uniname->name; 231 | struct nls_table *nls = EXFAT_SB(sb)->nls_io; 232 | 233 | i = 0; 234 | while (i < (MAX_NAME_LENGTH-1)) { 235 | if (*uniname == (UINT16) '\0') break; 236 | 237 | len = convert_uni_to_ch(nls, buf, *uniname, NULL); 238 | 239 | if (len > 1) { 240 | for (j = 0; j < len; j++) 241 | *p_cstring++ = (INT8) *(buf+j); 242 | } else { 243 | *p_cstring++ = (INT8) *buf; 244 | } 245 | 246 | uniname++; 247 | i++; 248 | } 249 | 250 | *p_cstring = '\0'; 251 | } 252 | 253 | void nls_cstring_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, UINT8 *p_cstring, INT32 *p_lossy) 254 | { 255 | INT32 i, j, lossy = FALSE; 256 | UINT8 *end_of_name; 257 | UINT16 upname[MAX_NAME_LENGTH]; 258 | UINT16 *uniname = p_uniname->name; 259 | struct nls_table *nls = EXFAT_SB(sb)->nls_io; 260 | 261 | end_of_name = p_cstring + STRLEN((INT8 *) p_cstring); 262 | 263 | while (*(--end_of_name) == ' ') { 264 | if (end_of_name < p_cstring) break; 265 | } 266 | *(++end_of_name) = '\0'; 267 | 268 | if (STRCMP((INT8 *) p_cstring, ".") && STRCMP((INT8 *) p_cstring, "..")) { 269 | while (*(--end_of_name) == '.') { 270 | if (end_of_name < p_cstring) break; 271 | } 272 | *(++end_of_name) = '\0'; 273 | } 274 | 275 | if (*p_cstring == '\0') 276 | lossy = TRUE; 277 | 278 | i = j = 0; 279 | while (j < (MAX_NAME_LENGTH-1)) { 280 | if (*(p_cstring+i) == '\0') break; 281 | 282 | i += convert_ch_to_uni(nls, uniname, (UINT8 *)(p_cstring+i), &lossy); 283 | 284 | if ((*uniname < 0x0020) || WSTRCHR(bad_uni_chars, *uniname)) 285 | lossy = TRUE; 286 | 287 | *(upname+j) = nls_upper(sb, *uniname); 288 | 289 | uniname++; 290 | j++; 291 | } 292 | 293 | if (*(p_cstring+i) != '\0') 294 | lossy = TRUE; 295 | *uniname = (UINT16) '\0'; 296 | 297 | p_uniname->name_len = j; 298 | p_uniname->name_hash = calc_checksum_2byte((void *) upname, j<<1, 0, CS_DEFAULT); 299 | 300 | if (p_lossy != NULL) 301 | *p_lossy = lossy; 302 | } 303 | 304 | static INT32 convert_ch_to_uni(struct nls_table *nls, UINT16 *uni, UINT8 *ch, INT32 *lossy) 305 | { 306 | int len; 307 | 308 | *uni = 0x0; 309 | 310 | if (ch[0] < 0x80) { 311 | *uni = (UINT16) ch[0]; 312 | return(1); 313 | } 314 | 315 | if ((len = nls->char2uni(ch, NLS_MAX_CHARSET_SIZE, uni)) < 0) { 316 | printk("%s: fail to use nls \n", __func__); 317 | if (lossy != NULL) 318 | *lossy = TRUE; 319 | *uni = (UINT16) '_'; 320 | if (!strcmp(nls->charset, "utf8")) return(1); 321 | else return(2); 322 | } 323 | 324 | return(len); 325 | } 326 | 327 | static INT32 convert_uni_to_ch(struct nls_table *nls, UINT8 *ch, UINT16 uni, INT32 *lossy) 328 | { 329 | int len; 330 | 331 | ch[0] = 0x0; 332 | 333 | if (uni < 0x0080) { 334 | ch[0] = (UINT8) uni; 335 | return(1); 336 | } 337 | 338 | if ((len = nls->uni2char(uni, ch, NLS_MAX_CHARSET_SIZE)) < 0) { 339 | printk("%s: fail to use nls \n", __func__); 340 | if (lossy != NULL) *lossy = TRUE; 341 | ch[0] = '_'; 342 | return(1); 343 | } 344 | 345 | return(len); 346 | 347 | } 348 | -------------------------------------------------------------------------------- /exfat_nls.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef _EXFAT_NLS_H 20 | #define _EXFAT_NLS_H 21 | 22 | #include 23 | 24 | #include "exfat_config.h" 25 | #include "exfat_global.h" 26 | #include "exfat_api.h" 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | #define NUM_UPCASE 2918 33 | 34 | #define DOS_CUR_DIR_NAME ". " 35 | #define DOS_PAR_DIR_NAME ".. " 36 | 37 | #if (FFS_CONFIG_LITTLE_ENDIAN == 1) 38 | #define UNI_CUR_DIR_NAME ".\0" 39 | #define UNI_PAR_DIR_NAME ".\0.\0" 40 | #else 41 | #define UNI_CUR_DIR_NAME "\0." 42 | #define UNI_PAR_DIR_NAME "\0.\0." 43 | #endif 44 | 45 | 46 | typedef struct { 47 | UINT8 name[DOS_NAME_LENGTH]; 48 | UINT8 name_case; 49 | } DOS_NAME_T; 50 | 51 | typedef struct { 52 | UINT16 name[MAX_NAME_LENGTH]; 53 | UINT16 name_hash; 54 | UINT8 name_len; 55 | } UNI_NAME_T; 56 | 57 | UINT16 nls_upper(struct super_block *sb, UINT16 a); 58 | INT32 nls_dosname_cmp(struct super_block *sb, UINT8 *a, UINT8 *b); 59 | INT32 nls_uniname_cmp(struct super_block *sb, UINT16 *a, UINT16 *b); 60 | void nls_uniname_to_dosname(struct super_block *sb, DOS_NAME_T *p_dosname, UNI_NAME_T *p_uniname, INT32 *p_lossy); 61 | void nls_dosname_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname); 62 | void nls_uniname_to_cstring(struct super_block *sb, UINT8 *p_cstring, UNI_NAME_T *p_uniname); 63 | void nls_cstring_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, UINT8 *p_cstring, INT32 *p_lossy); 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | #endif 69 | -------------------------------------------------------------------------------- /exfat_oal.c: -------------------------------------------------------------------------------- 1 | /* Some of the source code in this file came from "linux/fs/fat/misc.c". */ 2 | /* 3 | * linux/fs/fat/misc.c 4 | * 5 | * Written 1992,1993 by Werner Almesberger 6 | * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 7 | * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) 8 | */ 9 | 10 | /* 11 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU General Public License 15 | * as published by the Free Software Foundation; either version 2 16 | * of the License, or (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program; if not, write to the Free Software 25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | */ 27 | 28 | #include 29 | #include 30 | 31 | #include "exfat_config.h" 32 | #include "exfat_global.h" 33 | #include "exfat_api.h" 34 | #include "exfat_oal.h" 35 | 36 | DECLARE_MUTEX(z_sem); 37 | 38 | INT32 sm_init(struct semaphore *sm) 39 | { 40 | sema_init(sm, 1); 41 | return(0); 42 | } 43 | 44 | INT32 sm_P(struct semaphore *sm) 45 | { 46 | down(sm); 47 | return 0; 48 | } 49 | 50 | void sm_V(struct semaphore *sm) 51 | { 52 | up(sm); 53 | } 54 | 55 | extern struct timezone sys_tz; 56 | 57 | #define UNIX_SECS_1980 315532800L 58 | 59 | #if BITS_PER_LONG == 64 60 | #define UNIX_SECS_2108 4354819200L 61 | #endif 62 | 63 | #define DAYS_DELTA_DECADE (365 * 10 + 2) 64 | #define NO_LEAP_YEAR_2100 (120) 65 | #define IS_LEAP_YEAR(y) (!((y) & 3) && (y) != NO_LEAP_YEAR_2100) 66 | 67 | #define SECS_PER_MIN (60) 68 | #define SECS_PER_HOUR (60 * SECS_PER_MIN) 69 | #define SECS_PER_DAY (24 * SECS_PER_HOUR) 70 | 71 | #define MAKE_LEAP_YEAR(leap_year, year) \ 72 | do { \ 73 | if (unlikely(year > NO_LEAP_YEAR_2100)) \ 74 | leap_year = ((year + 3) / 4) - 1; \ 75 | else \ 76 | leap_year = ((year + 3) / 4); \ 77 | } while(0) 78 | 79 | 80 | 81 | static time_t accum_days_in_year[] = { 82 | 0, 0, 31, 59, 90,120,151,181,212,243,273,304,334, 0, 0, 0, 83 | }; 84 | 85 | 86 | TIMESTAMP_T *tm_current(TIMESTAMP_T *tp) 87 | { 88 | struct timespec ts = CURRENT_TIME_SEC; 89 | time_t second = ts.tv_sec; 90 | time_t day, leap_day, month, year; 91 | 92 | second -= sys_tz.tz_minuteswest * SECS_PER_MIN; 93 | 94 | if (second < UNIX_SECS_1980) { 95 | tp->sec = 0; 96 | tp->min = 0; 97 | tp->hour = 0; 98 | tp->day = 1; 99 | tp->mon = 1; 100 | tp->year = 0; 101 | return(tp); 102 | } 103 | #if BITS_PER_LONG == 64 104 | if (second >= UNIX_SECS_2108) { 105 | tp->sec = 59; 106 | tp->min = 59; 107 | tp->hour = 23; 108 | tp->day = 31; 109 | tp->mon = 12; 110 | tp->year = 127; 111 | return(tp); 112 | } 113 | #endif 114 | 115 | day = second / SECS_PER_DAY - DAYS_DELTA_DECADE; 116 | year = day / 365; 117 | 118 | MAKE_LEAP_YEAR(leap_day, year); 119 | if (year * 365 + leap_day > day) 120 | year--; 121 | 122 | MAKE_LEAP_YEAR(leap_day, year); 123 | 124 | day -= year * 365 + leap_day; 125 | 126 | if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) { 127 | month = 2; 128 | } else { 129 | if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3]) 130 | day--; 131 | for (month = 1; month < 12; month++) { 132 | if (accum_days_in_year[month + 1] > day) 133 | break; 134 | } 135 | } 136 | day -= accum_days_in_year[month]; 137 | 138 | tp->sec = second % SECS_PER_MIN; 139 | tp->min = (second / SECS_PER_MIN) % 60; 140 | tp->hour = (second / SECS_PER_HOUR) % 24; 141 | tp->day = day + 1; 142 | tp->mon = month; 143 | tp->year = year; 144 | 145 | return(tp); 146 | } 147 | -------------------------------------------------------------------------------- /exfat_oal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef _EXFAT_OAL_H 20 | #define _EXFAT_OAL_H 21 | 22 | #include "exfat_config.h" 23 | #include "exfat_global.h" 24 | #include 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | typedef struct { 31 | UINT16 sec; 32 | UINT16 min; 33 | UINT16 hour; 34 | UINT16 day; 35 | UINT16 mon; 36 | UINT16 year; 37 | } TIMESTAMP_T; 38 | 39 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) 40 | #define DECLARE_MUTEX(m) DEFINE_SEMAPHORE(m) 41 | #endif 42 | 43 | INT32 sm_init(struct semaphore *sm); 44 | INT32 sm_P(struct semaphore *sm); 45 | void sm_V(struct semaphore *sm); 46 | 47 | TIMESTAMP_T *tm_current(TIMESTAMP_T *tm); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /exfat_part.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef _EXFAT_PART_H 20 | #define _EXFAT_PART_H 21 | 22 | #include "exfat_config.h" 23 | #include "exfat_global.h" 24 | #include "exfat_api.h" 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #define MBR_SIGNATURE 0xAA55 31 | typedef struct { 32 | UINT8 boot_code[446]; 33 | UINT8 partition[64]; 34 | UINT8 signature[2]; 35 | } MBR_SECTOR_T; 36 | 37 | typedef struct { 38 | UINT8 def_boot; 39 | UINT8 bgn_chs[3]; 40 | UINT8 sys_type; 41 | UINT8 end_chs[3]; 42 | UINT8 start_sector[4]; 43 | UINT8 num_sectors[4]; 44 | } PART_ENTRY_T; 45 | 46 | INT32 ffsSetPartition(INT32 dev, INT32 num_vol, PART_INFO_T *vol_spec); 47 | INT32 ffsGetPartition(INT32 dev, INT32 *num_vol, PART_INFO_T *vol_spec); 48 | INT32 ffsGetDevInfo(INT32 dev, DEV_INFO_T *info); 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /exfat_super.c: -------------------------------------------------------------------------------- 1 | /* Some of the source code in this file came from "linux/fs/fat/file.c","linux/fs/fat/inode.c" and "linux/fs/fat/misc.c". */ 2 | /* 3 | * linux/fs/fat/file.c 4 | * 5 | * Written 1992,1993 by Werner Almesberger 6 | * 7 | * regular file handling primitives for fat-based filesystems 8 | */ 9 | 10 | /* 11 | * linux/fs/fat/inode.c 12 | * 13 | * Written 1992,1993 by Werner Almesberger 14 | * VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner 15 | * Rewritten for the constant inumbers support by Al Viro 16 | * 17 | * Fixes: 18 | * 19 | * Max Cohan: Fixed invalid FSINFO offset when info_sector is 0 20 | */ 21 | 22 | /* 23 | * linux/fs/fat/misc.c 24 | * 25 | * Written 1992,1993 by Werner Almesberger 26 | * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 27 | * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) 28 | */ 29 | 30 | /* 31 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 32 | * 33 | * This program is free software; you can redistribute it and/or 34 | * modify it under the terms of the GNU General Public License 35 | * as published by the Free Software Foundation; either version 2 36 | * of the License, or (at your option) any later version. 37 | * 38 | * This program is distributed in the hope that it will be useful, 39 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 40 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 41 | * GNU General Public License for more details. 42 | * 43 | * You should have received a copy of the GNU General Public License 44 | * along with this program; if not, write to the Free Software 45 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 46 | */ 47 | 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) 54 | #include 55 | #endif 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | 75 | #include "exfat_version.h" 76 | #include "exfat_config.h" 77 | #include "exfat_global.h" 78 | #include "exfat_data.h" 79 | #include "exfat_oal.h" 80 | 81 | #include "exfat_blkdev.h" 82 | #include "exfat_cache.h" 83 | #include "exfat_part.h" 84 | #include "exfat_nls.h" 85 | #include "exfat_api.h" 86 | #include "exfat.h" 87 | 88 | #include "exfat_super.h" 89 | 90 | static struct kmem_cache *exfat_inode_cachep; 91 | 92 | static int exfat_default_codepage = DEFAULT_CODEPAGE; 93 | static char exfat_default_iocharset[] = DEFAULT_IOCHARSET; 94 | 95 | extern struct timezone sys_tz; 96 | 97 | #define CHECK_ERR(x) BUG_ON(x) 98 | #define ELAPSED_TIME 0 99 | 100 | #if (ELAPSED_TIME == 1) 101 | #include 102 | 103 | static UINT32 __t1, __t2; 104 | static UINT32 get_current_msec(void) 105 | { 106 | struct timeval tm; 107 | do_gettimeofday(&tm); 108 | return((UINT32)(tm.tv_sec*1000000 + tm.tv_usec)); 109 | } 110 | #define TIME_START() do {__t1 = get_current_msec();} while (0) 111 | #define TIME_END() do {__t2 = get_current_msec();} while (0) 112 | #define PRINT_TIME(n) do {printk("[EXFAT] Elapsed time %d = %d (usec)\n", n, (__t2 - __t1));} while (0) 113 | #else 114 | #define TIME_START() 115 | #define TIME_END() 116 | #define PRINT_TIME(n) 117 | #endif 118 | 119 | #define UNIX_SECS_1980 315532800L 120 | 121 | #if BITS_PER_LONG == 64 122 | #define UNIX_SECS_2108 4354819200L 123 | #endif 124 | #define DAYS_DELTA_DECADE (365 * 10 + 2) 125 | #define NO_LEAP_YEAR_2100 (120) 126 | #define IS_LEAP_YEAR(y) (!((y) & 0x3) && (y) != NO_LEAP_YEAR_2100) 127 | 128 | #define SECS_PER_MIN (60) 129 | #define SECS_PER_HOUR (60 * SECS_PER_MIN) 130 | #define SECS_PER_DAY (24 * SECS_PER_HOUR) 131 | 132 | #define MAKE_LEAP_YEAR(leap_year, year) \ 133 | do { \ 134 | if (unlikely(year > NO_LEAP_YEAR_2100)) \ 135 | leap_year = ((year + 3) / 4) - 1; \ 136 | else \ 137 | leap_year = ((year + 3) / 4); \ 138 | } while(0) 139 | 140 | static time_t accum_days_in_year[] = { 141 | 0, 0, 31, 59, 90,120,151,181,212,243,273,304,334, 0, 0, 0, 142 | }; 143 | 144 | static void _exfat_truncate(struct inode *inode, loff_t old_size); 145 | 146 | void exfat_time_fat2unix(struct exfat_sb_info *sbi, struct timespec *ts, 147 | DATE_TIME_T *tp) 148 | { 149 | time_t year = tp->Year; 150 | time_t ld; 151 | 152 | MAKE_LEAP_YEAR(ld, year); 153 | 154 | if (IS_LEAP_YEAR(year) && (tp->Month) > 2) 155 | ld++; 156 | 157 | ts->tv_sec = tp->Second + tp->Minute * SECS_PER_MIN 158 | + tp->Hour * SECS_PER_HOUR 159 | + (year * 365 + ld + accum_days_in_year[(tp->Month)] + (tp->Day - 1) + DAYS_DELTA_DECADE) * SECS_PER_DAY 160 | + sys_tz.tz_minuteswest * SECS_PER_MIN; 161 | ts->tv_nsec = 0; 162 | } 163 | 164 | void exfat_time_unix2fat(struct exfat_sb_info *sbi, struct timespec *ts, 165 | DATE_TIME_T *tp) 166 | { 167 | time_t second = ts->tv_sec; 168 | time_t day, month, year; 169 | time_t ld; 170 | 171 | second -= sys_tz.tz_minuteswest * SECS_PER_MIN; 172 | 173 | if (second < UNIX_SECS_1980) { 174 | tp->Second = 0; 175 | tp->Minute = 0; 176 | tp->Hour = 0; 177 | tp->Day = 1; 178 | tp->Month = 1; 179 | tp->Year = 0; 180 | return; 181 | } 182 | #if (BITS_PER_LONG == 64) 183 | if (second >= UNIX_SECS_2108) { 184 | tp->Second = 59; 185 | tp->Minute = 59; 186 | tp->Hour = 23; 187 | tp->Day = 31; 188 | tp->Month = 12; 189 | tp->Year = 127; 190 | return; 191 | } 192 | #endif 193 | day = second / SECS_PER_DAY - DAYS_DELTA_DECADE; 194 | year = day / 365; 195 | MAKE_LEAP_YEAR(ld, year); 196 | if (year * 365 + ld > day) 197 | year--; 198 | 199 | MAKE_LEAP_YEAR(ld, year); 200 | day -= year * 365 + ld; 201 | 202 | if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) { 203 | month = 2; 204 | } else { 205 | if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3]) 206 | day--; 207 | for (month = 1; month < 12; month++) { 208 | if (accum_days_in_year[month + 1] > day) 209 | break; 210 | } 211 | } 212 | day -= accum_days_in_year[month]; 213 | 214 | tp->Second = second % SECS_PER_MIN; 215 | tp->Minute = (second / SECS_PER_MIN) % 60; 216 | tp->Hour = (second / SECS_PER_HOUR) % 24; 217 | tp->Day = day + 1; 218 | tp->Month = month; 219 | tp->Year = year; 220 | } 221 | 222 | static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos); 223 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) 224 | static int exfat_generic_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); 225 | #else 226 | static long exfat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); 227 | #endif 228 | static int exfat_sync_inode(struct inode *inode); 229 | static struct inode *exfat_build_inode(struct super_block *sb, FILE_ID_T *fid, loff_t i_pos); 230 | static void exfat_detach(struct inode *inode); 231 | static void exfat_attach(struct inode *inode, loff_t i_pos); 232 | static inline unsigned long exfat_hash(loff_t i_pos); 233 | static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc); 234 | static void exfat_write_super(struct super_block *sb); 235 | 236 | static void __lock_super(struct super_block *sb) 237 | { 238 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) 239 | lock_super(sb); 240 | #else 241 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 242 | mutex_lock(&sbi->s_lock); 243 | #endif 244 | } 245 | 246 | static void __unlock_super(struct super_block *sb) 247 | { 248 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) 249 | unlock_super(sb); 250 | #else 251 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 252 | mutex_unlock(&sbi->s_lock); 253 | #endif 254 | } 255 | 256 | static int __is_sb_dirty(struct super_block *sb) 257 | { 258 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) 259 | return sb->s_dirt; 260 | #else 261 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 262 | return sbi->s_dirt; 263 | #endif 264 | } 265 | 266 | static void __set_sb_clean(struct super_block *sb) 267 | { 268 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) 269 | sb->s_dirt = 0; 270 | #else 271 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 272 | sbi->s_dirt = 0; 273 | #endif 274 | } 275 | 276 | static int exfat_readdir(struct file *filp, void *dirent, filldir_t filldir) 277 | { 278 | struct inode *inode = filp->f_path.dentry->d_inode; 279 | struct super_block *sb = inode->i_sb; 280 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 281 | FS_INFO_T *p_fs = &(sbi->fs_info); 282 | BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); 283 | DIR_ENTRY_T de; 284 | unsigned long inum; 285 | loff_t cpos; 286 | int err = 0; 287 | 288 | __lock_super(sb); 289 | 290 | cpos = filp->f_pos; 291 | if ((p_fs->vol_type == EXFAT) || (inode->i_ino == EXFAT_ROOT_INO)) { 292 | while (cpos < 2) { 293 | if (inode->i_ino == EXFAT_ROOT_INO) 294 | inum = EXFAT_ROOT_INO; 295 | else if (cpos == 0) 296 | inum = inode->i_ino; 297 | else 298 | inum = parent_ino(filp->f_path.dentry); 299 | 300 | if (filldir(dirent, "..", cpos+1, cpos, inum, DT_DIR) < 0) 301 | goto out; 302 | cpos++; 303 | filp->f_pos++; 304 | } 305 | if (cpos == 2) { 306 | cpos = 0; 307 | } 308 | } 309 | if (cpos & (DENTRY_SIZE - 1)) { 310 | err = -ENOENT; 311 | goto out; 312 | } 313 | 314 | get_new: 315 | EXFAT_I(inode)->fid.size = i_size_read(inode); 316 | EXFAT_I(inode)->fid.rwoffset = cpos >> DENTRY_SIZE_BITS; 317 | 318 | err = FsReadDir(inode, &de); 319 | if (err) { 320 | if (err == FFS_MEDIAERR) { 321 | cpos += 1 << p_bd->sector_size_bits; 322 | cpos &= ~((1 << p_bd->sector_size_bits)-1); 323 | } 324 | 325 | err = -EIO; 326 | goto end_of_dir; 327 | } 328 | 329 | cpos = EXFAT_I(inode)->fid.rwoffset << DENTRY_SIZE_BITS; 330 | 331 | if (!de.Name[0]) 332 | goto end_of_dir; 333 | 334 | if (!memcmp(de.ShortName, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH)) { 335 | inum = inode->i_ino; 336 | } else if (!memcmp(de.ShortName, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH)) { 337 | inum = parent_ino(filp->f_path.dentry); 338 | } else { 339 | loff_t i_pos = ((loff_t) EXFAT_I(inode)->fid.start_clu << 32) | 340 | ((EXFAT_I(inode)->fid.rwoffset-1) & 0xffffffff); 341 | 342 | struct inode *tmp = exfat_iget(sb, i_pos); 343 | if (tmp) { 344 | inum = tmp->i_ino; 345 | iput(tmp); 346 | } else { 347 | inum = iunique(sb, EXFAT_ROOT_INO); 348 | } 349 | } 350 | 351 | if (filldir(dirent, de.Name, strlen(de.Name), cpos-1, inum, 352 | (de.Attr & ATTR_SUBDIR) ? DT_DIR : DT_REG) < 0) 353 | goto out; 354 | 355 | filp->f_pos = cpos; 356 | goto get_new; 357 | 358 | end_of_dir: 359 | filp->f_pos = cpos; 360 | out: 361 | __unlock_super(sb); 362 | return err; 363 | } 364 | 365 | static int exfat_ioctl_volume_id(struct inode *dir) 366 | { 367 | struct super_block *sb = dir->i_sb; 368 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 369 | FS_INFO_T *p_fs = &(sbi->fs_info); 370 | 371 | return p_fs->vol_id; 372 | } 373 | 374 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) 375 | static int exfat_generic_ioctl(struct inode *inode, struct file *filp, 376 | unsigned int cmd, unsigned long arg) 377 | #else 378 | static long exfat_generic_ioctl(struct file *filp, 379 | unsigned int cmd, unsigned long arg) 380 | #endif 381 | { 382 | #if EXFAT_CONFIG_KERNEL_DEBUG 383 | #if !(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) 384 | struct inode *inode = filp->f_dentry->d_inode; 385 | #endif 386 | unsigned int flags; 387 | #endif 388 | 389 | switch (cmd) { 390 | case EXFAT_IOCTL_GET_VOLUME_ID: 391 | return exfat_ioctl_volume_id(inode); 392 | #if EXFAT_CONFIG_KERNEL_DEBUG 393 | case EXFAT_IOC_GET_DEBUGFLAGS: { 394 | struct super_block *sb = inode->i_sb; 395 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 396 | 397 | flags = sbi->debug_flags; 398 | return put_user(flags, (int __user *)arg); 399 | } 400 | case EXFAT_IOC_SET_DEBUGFLAGS: { 401 | struct super_block *sb = inode->i_sb; 402 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 403 | 404 | if (!capable(CAP_SYS_ADMIN)) 405 | return -EPERM; 406 | 407 | if (get_user(flags, (int __user *) arg)) 408 | return -EFAULT; 409 | 410 | __lock_super(sb); 411 | sbi->debug_flags = flags; 412 | __unlock_super(sb); 413 | 414 | return 0; 415 | } 416 | #endif 417 | default: 418 | return -ENOTTY; 419 | } 420 | } 421 | 422 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) 423 | static int exfat_file_fsync(struct file *filp, int datasync) 424 | { 425 | struct inode *inode = filp->f_mapping->host; 426 | struct super_block *sb = inode->i_sb; 427 | int res, err; 428 | 429 | res = generic_file_fsync(filp, datasync); 430 | err = FsSyncVol(sb, 1); 431 | 432 | return res ? res : err; 433 | } 434 | #endif 435 | 436 | const struct file_operations exfat_dir_operations = { 437 | .llseek = generic_file_llseek, 438 | .read = generic_read_dir, 439 | .readdir = exfat_readdir, 440 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) 441 | .ioctl = exfat_generic_ioctl, 442 | .fsync = exfat_file_fsync, 443 | #else 444 | .unlocked_ioctl = exfat_generic_ioctl, 445 | .fsync = generic_file_fsync, 446 | #endif 447 | }; 448 | 449 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00) 450 | static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, 451 | bool excl) 452 | #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) 453 | static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, 454 | struct nameidata *nd) 455 | #else 456 | static int exfat_create(struct inode *dir, struct dentry *dentry, int mode, 457 | struct nameidata *nd) 458 | #endif 459 | { 460 | struct super_block *sb = dir->i_sb; 461 | struct inode *inode; 462 | struct timespec ts; 463 | FILE_ID_T fid; 464 | loff_t i_pos; 465 | int err; 466 | 467 | __lock_super(sb); 468 | 469 | PRINTK("exfat_create entered\n"); 470 | 471 | ts = CURRENT_TIME_SEC; 472 | 473 | err = FsCreateFile(dir, (UINT8 *) dentry->d_name.name, FM_REGULAR, &fid); 474 | if (err) { 475 | if (err == FFS_INVALIDPATH) 476 | err = -EINVAL; 477 | else if (err == FFS_FILEEXIST) 478 | err = -EEXIST; 479 | else if (err == FFS_FULL) 480 | err = -ENOSPC; 481 | else if (err == FFS_NAMETOOLONG) 482 | err = -ENAMETOOLONG; 483 | else 484 | err = -EIO; 485 | goto out; 486 | } 487 | dir->i_version++; 488 | dir->i_ctime = dir->i_mtime = dir->i_atime = ts; 489 | if (IS_DIRSYNC(dir)) 490 | (void) exfat_sync_inode(dir); 491 | else 492 | mark_inode_dirty(dir); 493 | 494 | i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); 495 | 496 | inode = exfat_build_inode(sb, &fid, i_pos); 497 | if (IS_ERR(inode)) { 498 | err = PTR_ERR(inode); 499 | goto out; 500 | } 501 | inode->i_version++; 502 | inode->i_mtime = inode->i_atime = inode->i_ctime = ts; 503 | 504 | dentry->d_time = dentry->d_parent->d_inode->i_version; 505 | d_instantiate(dentry, inode); 506 | 507 | out: 508 | __unlock_super(sb); 509 | PRINTK("exfat_create exited\n"); 510 | return err; 511 | } 512 | 513 | static int exfat_find(struct inode *dir, struct qstr *qname, 514 | FILE_ID_T *fid) 515 | { 516 | int err; 517 | 518 | if (qname->len == 0) 519 | return -ENOENT; 520 | 521 | err = FsLookupFile(dir, (UINT8 *) qname->name, fid); 522 | if (err) 523 | return -ENOENT; 524 | 525 | return 0; 526 | } 527 | 528 | static int exfat_d_anon_disconn(struct dentry *dentry) 529 | { 530 | return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); 531 | } 532 | 533 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00) 534 | static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, 535 | unsigned int flags) 536 | #else 537 | static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, 538 | struct nameidata *nd) 539 | #endif 540 | { 541 | struct super_block *sb = dir->i_sb; 542 | struct inode *inode; 543 | struct dentry *alias; 544 | int err; 545 | FILE_ID_T fid; 546 | loff_t i_pos; 547 | UINT64 ret; 548 | mode_t i_mode; 549 | 550 | __lock_super(sb); 551 | PRINTK("exfat_lookup entered\n"); 552 | err = exfat_find(dir, &dentry->d_name, &fid); 553 | if (err) { 554 | if (err == -ENOENT) { 555 | inode = NULL; 556 | goto out; 557 | } 558 | goto error; 559 | } 560 | 561 | i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); 562 | inode = exfat_build_inode(sb, &fid, i_pos); 563 | if (IS_ERR(inode)) { 564 | err = PTR_ERR(inode); 565 | goto error; 566 | } 567 | 568 | i_mode = inode->i_mode; 569 | if (S_ISLNK(i_mode)) { 570 | EXFAT_I(inode)->target = MALLOC(i_size_read(inode)+1); 571 | if (!EXFAT_I(inode)->target) { 572 | err = -ENOMEM; 573 | goto error; 574 | } 575 | FsReadFile(dir, &fid, EXFAT_I(inode)->target, i_size_read(inode), &ret); 576 | *(EXFAT_I(inode)->target + i_size_read(inode)) = '\0'; 577 | } 578 | 579 | alias = d_find_alias(inode); 580 | if (alias && !exfat_d_anon_disconn(alias)) { 581 | CHECK_ERR(d_unhashed(alias)); 582 | if (!S_ISDIR(i_mode)) 583 | d_move(alias, dentry); 584 | iput(inode); 585 | __unlock_super(sb); 586 | PRINTK("exfat_lookup exited 1\n"); 587 | return alias; 588 | } else { 589 | dput(alias); 590 | } 591 | out: 592 | __unlock_super(sb); 593 | dentry->d_time = dentry->d_parent->d_inode->i_version; 594 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) 595 | dentry->d_op = sb->s_root->d_op; 596 | dentry = d_splice_alias(inode, dentry); 597 | if (dentry) { 598 | dentry->d_op = sb->s_root->d_op; 599 | dentry->d_time = dentry->d_parent->d_inode->i_version; 600 | } 601 | #else 602 | dentry = d_splice_alias(inode, dentry); 603 | if (dentry) 604 | dentry->d_time = dentry->d_parent->d_inode->i_version; 605 | #endif 606 | PRINTK("exfat_lookup exited 2\n"); 607 | return dentry; 608 | 609 | error: 610 | __unlock_super(sb); 611 | PRINTK("exfat_lookup exited 3\n"); 612 | return ERR_PTR(err); 613 | } 614 | 615 | static int exfat_unlink(struct inode *dir, struct dentry *dentry) 616 | { 617 | struct inode *inode = dentry->d_inode; 618 | struct super_block *sb = dir->i_sb; 619 | struct timespec ts; 620 | int err; 621 | 622 | __lock_super(sb); 623 | 624 | PRINTK("exfat_unlink entered\n"); 625 | 626 | ts = CURRENT_TIME_SEC; 627 | 628 | EXFAT_I(inode)->fid.size = i_size_read(inode); 629 | 630 | err = FsRemoveFile(dir, &(EXFAT_I(inode)->fid)); 631 | if (err) { 632 | if (err == FFS_PERMISSIONERR) 633 | err = -EPERM; 634 | else 635 | err = -EIO; 636 | goto out; 637 | } 638 | dir->i_version++; 639 | dir->i_mtime = dir->i_atime = ts; 640 | if (IS_DIRSYNC(dir)) 641 | (void) exfat_sync_inode(dir); 642 | else 643 | mark_inode_dirty(dir); 644 | 645 | clear_nlink(inode); 646 | inode->i_mtime = inode->i_atime = ts; 647 | exfat_detach(inode); 648 | remove_inode_hash(inode); 649 | 650 | out: 651 | __unlock_super(sb); 652 | PRINTK("exfat_unlink exited\n"); 653 | return err; 654 | } 655 | 656 | static int exfat_symlink(struct inode *dir, struct dentry *dentry, const char *target) 657 | { 658 | struct super_block *sb = dir->i_sb; 659 | struct inode *inode; 660 | struct timespec ts; 661 | FILE_ID_T fid; 662 | loff_t i_pos; 663 | int err; 664 | UINT64 len = (UINT64) strlen(target); 665 | UINT64 ret; 666 | 667 | __lock_super(sb); 668 | 669 | PRINTK("exfat_symlink entered\n"); 670 | 671 | ts = CURRENT_TIME_SEC; 672 | 673 | err = FsCreateFile(dir, (UINT8 *) dentry->d_name.name, FM_SYMLINK, &fid); 674 | if (err) { 675 | if (err == FFS_INVALIDPATH) 676 | err = -EINVAL; 677 | else if (err == FFS_FILEEXIST) 678 | err = -EEXIST; 679 | else if (err == FFS_FULL) 680 | err = -ENOSPC; 681 | else 682 | err = -EIO; 683 | goto out; 684 | } 685 | 686 | err = FsWriteFile(dir, &fid, (char *) target, len, &ret); 687 | 688 | if (err) { 689 | FsRemoveFile(dir, &fid); 690 | 691 | if (err == FFS_FULL) 692 | err = -ENOSPC; 693 | else 694 | err = -EIO; 695 | goto out; 696 | } 697 | 698 | dir->i_version++; 699 | dir->i_ctime = dir->i_mtime = dir->i_atime = ts; 700 | if (IS_DIRSYNC(dir)) 701 | (void) exfat_sync_inode(dir); 702 | else 703 | mark_inode_dirty(dir); 704 | 705 | i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); 706 | 707 | inode = exfat_build_inode(sb, &fid, i_pos); 708 | if (IS_ERR(inode)) { 709 | err = PTR_ERR(inode); 710 | goto out; 711 | } 712 | inode->i_version++; 713 | inode->i_mtime = inode->i_atime = inode->i_ctime = ts; 714 | 715 | EXFAT_I(inode)->target = MALLOC(len+1); 716 | if (!EXFAT_I(inode)->target) { 717 | err = -ENOMEM; 718 | goto out; 719 | } 720 | MEMCPY(EXFAT_I(inode)->target, target, len+1); 721 | 722 | dentry->d_time = dentry->d_parent->d_inode->i_version; 723 | d_instantiate(dentry, inode); 724 | 725 | out: 726 | __unlock_super(sb); 727 | PRINTK("exfat_symlink exited\n"); 728 | return err; 729 | } 730 | 731 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) 732 | static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 733 | #else 734 | static int exfat_mkdir(struct inode *dir, struct dentry *dentry, int mode) 735 | #endif 736 | { 737 | struct super_block *sb = dir->i_sb; 738 | struct inode *inode; 739 | struct timespec ts; 740 | FILE_ID_T fid; 741 | loff_t i_pos; 742 | int err; 743 | 744 | __lock_super(sb); 745 | 746 | PRINTK("exfat_mkdir entered\n"); 747 | 748 | ts = CURRENT_TIME_SEC; 749 | 750 | err = FsCreateDir(dir, (UINT8 *) dentry->d_name.name, &fid); 751 | if (err) { 752 | if (err == FFS_INVALIDPATH) 753 | err = -EINVAL; 754 | else if (err == FFS_FILEEXIST) 755 | err = -EEXIST; 756 | else if (err == FFS_FULL) 757 | err = -ENOSPC; 758 | else if (err == FFS_NAMETOOLONG) 759 | err = -ENAMETOOLONG; 760 | else 761 | err = -EIO; 762 | goto out; 763 | } 764 | dir->i_version++; 765 | dir->i_ctime = dir->i_mtime = dir->i_atime = ts; 766 | if (IS_DIRSYNC(dir)) 767 | (void) exfat_sync_inode(dir); 768 | else 769 | mark_inode_dirty(dir); 770 | inc_nlink(dir); 771 | 772 | i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); 773 | 774 | inode = exfat_build_inode(sb, &fid, i_pos); 775 | if (IS_ERR(inode)) { 776 | err = PTR_ERR(inode); 777 | goto out; 778 | } 779 | inode->i_version++; 780 | inode->i_mtime = inode->i_atime = inode->i_ctime = ts; 781 | 782 | dentry->d_time = dentry->d_parent->d_inode->i_version; 783 | d_instantiate(dentry, inode); 784 | 785 | out: 786 | __unlock_super(sb); 787 | PRINTK("exfat_mkdir exited\n"); 788 | return err; 789 | } 790 | 791 | static int exfat_rmdir(struct inode *dir, struct dentry *dentry) 792 | { 793 | struct inode *inode = dentry->d_inode; 794 | struct super_block *sb = dir->i_sb; 795 | struct timespec ts; 796 | int err; 797 | 798 | __lock_super(sb); 799 | 800 | PRINTK("exfat_rmdir entered\n"); 801 | 802 | ts = CURRENT_TIME_SEC; 803 | 804 | EXFAT_I(inode)->fid.size = i_size_read(inode); 805 | 806 | err = FsRemoveDir(dir, &(EXFAT_I(inode)->fid)); 807 | if (err) { 808 | if (err == FFS_INVALIDPATH) 809 | err = -EINVAL; 810 | else if (err == FFS_FILEEXIST) 811 | err = -ENOTEMPTY; 812 | else if (err == FFS_NOTFOUND) 813 | err = -ENOENT; 814 | else if (err == FFS_DIRBUSY) 815 | err = -EBUSY; 816 | else 817 | err = -EIO; 818 | goto out; 819 | } 820 | dir->i_version++; 821 | dir->i_mtime = dir->i_atime = ts; 822 | if (IS_DIRSYNC(dir)) 823 | (void) exfat_sync_inode(dir); 824 | else 825 | mark_inode_dirty(dir); 826 | drop_nlink(dir); 827 | 828 | clear_nlink(inode); 829 | inode->i_mtime = inode->i_atime = ts; 830 | exfat_detach(inode); 831 | remove_inode_hash(inode); 832 | 833 | out: 834 | __unlock_super(sb); 835 | PRINTK("exfat_rmdir exited\n"); 836 | return err; 837 | } 838 | 839 | static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, 840 | struct inode *new_dir, struct dentry *new_dentry) 841 | { 842 | struct inode *old_inode, *new_inode; 843 | struct super_block *sb = old_dir->i_sb; 844 | struct timespec ts; 845 | loff_t i_pos; 846 | int err; 847 | 848 | __lock_super(sb); 849 | 850 | PRINTK("exfat_rename entered\n"); 851 | 852 | old_inode = old_dentry->d_inode; 853 | new_inode = new_dentry->d_inode; 854 | 855 | ts = CURRENT_TIME_SEC; 856 | 857 | EXFAT_I(old_inode)->fid.size = i_size_read(old_inode); 858 | 859 | err = FsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir, new_dentry); 860 | if (err) { 861 | if (err == FFS_PERMISSIONERR) 862 | err = -EPERM; 863 | else if (err == FFS_INVALIDPATH) 864 | err = -EINVAL; 865 | else if (err == FFS_FILEEXIST) 866 | err = -EEXIST; 867 | else if (err == FFS_NOTFOUND) 868 | err = -ENOENT; 869 | else if (err == FFS_FULL) 870 | err = -ENOSPC; 871 | else 872 | err = -EIO; 873 | goto out; 874 | } 875 | new_dir->i_version++; 876 | new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = ts; 877 | if (IS_DIRSYNC(new_dir)) 878 | (void) exfat_sync_inode(new_dir); 879 | else 880 | mark_inode_dirty(new_dir); 881 | 882 | i_pos = ((loff_t) EXFAT_I(old_inode)->fid.dir.dir << 32) | 883 | (EXFAT_I(old_inode)->fid.entry & 0xffffffff); 884 | 885 | exfat_detach(old_inode); 886 | exfat_attach(old_inode, i_pos); 887 | if (IS_DIRSYNC(new_dir)) 888 | (void) exfat_sync_inode(old_inode); 889 | else 890 | mark_inode_dirty(old_inode); 891 | 892 | if ((S_ISDIR(old_inode->i_mode)) && (old_dir != new_dir)) { 893 | drop_nlink(old_dir); 894 | if (!new_inode) inc_nlink(new_dir); 895 | } 896 | 897 | old_dir->i_version++; 898 | old_dir->i_ctime = old_dir->i_mtime = ts; 899 | if (IS_DIRSYNC(old_dir)) 900 | (void) exfat_sync_inode(old_dir); 901 | else 902 | mark_inode_dirty(old_dir); 903 | 904 | if (new_inode) { 905 | exfat_detach(new_inode); 906 | drop_nlink(new_inode); 907 | if (S_ISDIR(new_inode->i_mode)) 908 | drop_nlink(new_inode); 909 | new_inode->i_ctime = ts; 910 | } 911 | 912 | out: 913 | __unlock_super(sb); 914 | PRINTK("exfat_rename exited\n"); 915 | return err; 916 | } 917 | 918 | static int exfat_cont_expand(struct inode *inode, loff_t size) 919 | { 920 | struct address_space *mapping = inode->i_mapping; 921 | loff_t start = i_size_read(inode), count = size - i_size_read(inode); 922 | int err, err2; 923 | 924 | if ((err = generic_cont_expand_simple(inode, size)) != 0) 925 | return err; 926 | 927 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; 928 | mark_inode_dirty(inode); 929 | 930 | if (IS_SYNC(inode)) { 931 | err = filemap_fdatawrite_range(mapping, start, start + count - 1); 932 | err2 = sync_mapping_buffers(mapping); 933 | err = (err)?(err):(err2); 934 | err2 = write_inode_now(inode, 1); 935 | err = (err)?(err):(err2); 936 | if (!err) { 937 | err = filemap_fdatawait_range(mapping, start, start + count - 1); 938 | } 939 | } 940 | return err; 941 | } 942 | 943 | static int exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode) 944 | { 945 | mode_t allow_utime = sbi->options.allow_utime; 946 | 947 | if (current_fsuid() != inode->i_uid) { 948 | if (in_group_p(inode->i_gid)) 949 | allow_utime >>= 3; 950 | if (allow_utime & MAY_WRITE) 951 | return 1; 952 | } 953 | 954 | return 0; 955 | } 956 | 957 | static int exfat_sanitize_mode(const struct exfat_sb_info *sbi, 958 | struct inode *inode, umode_t *mode_ptr) 959 | { 960 | mode_t i_mode, mask, perm; 961 | 962 | i_mode = inode->i_mode; 963 | 964 | if (S_ISREG(i_mode) || S_ISLNK(i_mode)) 965 | mask = sbi->options.fs_fmask; 966 | else 967 | mask = sbi->options.fs_dmask; 968 | 969 | perm = *mode_ptr & ~(S_IFMT | mask); 970 | 971 | if ((perm & (S_IRUGO | S_IXUGO)) != (i_mode & (S_IRUGO|S_IXUGO))) 972 | return -EPERM; 973 | 974 | if (exfat_mode_can_hold_ro(inode)) { 975 | if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask))) 976 | return -EPERM; 977 | } else { 978 | if ((perm & S_IWUGO) != (S_IWUGO & ~mask)) 979 | return -EPERM; 980 | } 981 | 982 | *mode_ptr &= S_IFMT | perm; 983 | 984 | return 0; 985 | } 986 | 987 | static int exfat_setattr(struct dentry *dentry, struct iattr *attr) 988 | { 989 | 990 | struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb); 991 | struct inode *inode = dentry->d_inode; 992 | unsigned int ia_valid; 993 | int error; 994 | loff_t old_size; 995 | 996 | PRINTK("exfat_setattr entered\n"); 997 | 998 | if ((attr->ia_valid & ATTR_SIZE) 999 | && (attr->ia_size > i_size_read(inode))) { 1000 | error = exfat_cont_expand(inode, attr->ia_size); 1001 | if (error || attr->ia_valid == ATTR_SIZE) 1002 | return error; 1003 | attr->ia_valid &= ~ATTR_SIZE; 1004 | } 1005 | 1006 | ia_valid = attr->ia_valid; 1007 | 1008 | if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) 1009 | && exfat_allow_set_time(sbi, inode)) { 1010 | attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET); 1011 | } 1012 | 1013 | error = inode_change_ok(inode, attr); 1014 | attr->ia_valid = ia_valid; 1015 | if (error) { 1016 | return error; 1017 | } 1018 | 1019 | if (((attr->ia_valid & ATTR_UID) && 1020 | (attr->ia_uid != sbi->options.fs_uid)) || 1021 | ((attr->ia_valid & ATTR_GID) && 1022 | (attr->ia_gid != sbi->options.fs_gid)) || 1023 | ((attr->ia_valid & ATTR_MODE) && 1024 | (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | S_IRWXUGO)))) { 1025 | return -EPERM; 1026 | } 1027 | 1028 | if (attr->ia_valid & ATTR_MODE) { 1029 | if (exfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0) 1030 | attr->ia_valid &= ~ATTR_MODE; 1031 | } 1032 | 1033 | EXFAT_I(inode)->fid.size = i_size_read(inode); 1034 | 1035 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) 1036 | if (attr->ia_valid) 1037 | error = inode_setattr(inode, attr); 1038 | #else 1039 | if (attr->ia_valid & ATTR_SIZE) { 1040 | old_size = i_size_read(inode); 1041 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) 1042 | down_write(&EXFAT_I(inode)->truncate_lock); 1043 | truncate_setsize(inode, attr->ia_size); 1044 | _exfat_truncate(inode, old_size); 1045 | up_write(&EXFAT_I(inode)->truncate_lock); 1046 | #else 1047 | truncate_setsize(inode, attr->ia_size); 1048 | _exfat_truncate(inode, old_size); 1049 | #endif 1050 | } 1051 | setattr_copy(inode, attr); 1052 | mark_inode_dirty(inode); 1053 | #endif 1054 | 1055 | 1056 | PRINTK("exfat_setattr exited\n"); 1057 | return error; 1058 | } 1059 | 1060 | static int exfat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 1061 | { 1062 | struct inode *inode = dentry->d_inode; 1063 | 1064 | PRINTK("exfat_getattr entered\n"); 1065 | 1066 | generic_fillattr(inode, stat); 1067 | stat->blksize = EXFAT_SB(inode->i_sb)->fs_info.cluster_size; 1068 | 1069 | PRINTK("exfat_getattr exited\n"); 1070 | return 0; 1071 | } 1072 | 1073 | const struct inode_operations exfat_dir_inode_operations = { 1074 | .create = exfat_create, 1075 | .lookup = exfat_lookup, 1076 | .unlink = exfat_unlink, 1077 | .symlink = exfat_symlink, 1078 | .mkdir = exfat_mkdir, 1079 | .rmdir = exfat_rmdir, 1080 | .rename = exfat_rename, 1081 | .setattr = exfat_setattr, 1082 | .getattr = exfat_getattr, 1083 | }; 1084 | 1085 | static void *exfat_follow_link(struct dentry *dentry, struct nameidata *nd) 1086 | { 1087 | struct exfat_inode_info *ei = EXFAT_I(dentry->d_inode); 1088 | nd_set_link(nd, (char *)(ei->target)); 1089 | return NULL; 1090 | } 1091 | 1092 | const struct inode_operations exfat_symlink_inode_operations = { 1093 | .readlink = generic_readlink, 1094 | .follow_link = exfat_follow_link, 1095 | }; 1096 | 1097 | static int exfat_file_release(struct inode *inode, struct file *filp) 1098 | { 1099 | struct super_block *sb = inode->i_sb; 1100 | 1101 | EXFAT_I(inode)->fid.size = i_size_read(inode); 1102 | FsSyncVol(sb, 0); 1103 | return 0; 1104 | } 1105 | 1106 | const struct file_operations exfat_file_operations = { 1107 | .llseek = generic_file_llseek, 1108 | .read = do_sync_read, 1109 | .write = do_sync_write, 1110 | .aio_read = generic_file_aio_read, 1111 | .aio_write = generic_file_aio_write, 1112 | .mmap = generic_file_mmap, 1113 | .release = exfat_file_release, 1114 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) 1115 | .ioctl = exfat_generic_ioctl, 1116 | .fsync = exfat_file_fsync, 1117 | #else 1118 | .unlocked_ioctl = exfat_generic_ioctl, 1119 | .fsync = generic_file_fsync, 1120 | #endif 1121 | .splice_read = generic_file_splice_read, 1122 | }; 1123 | 1124 | static void _exfat_truncate(struct inode *inode, loff_t old_size) 1125 | { 1126 | struct super_block *sb = inode->i_sb; 1127 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 1128 | FS_INFO_T *p_fs = &(sbi->fs_info); 1129 | int err; 1130 | 1131 | __lock_super(sb); 1132 | 1133 | if (EXFAT_I(inode)->mmu_private > i_size_read(inode)) 1134 | EXFAT_I(inode)->mmu_private = i_size_read(inode); 1135 | 1136 | if (EXFAT_I(inode)->fid.start_clu == 0) goto out; 1137 | 1138 | err = FsTruncateFile(inode, old_size, i_size_read(inode)); 1139 | if (err) goto out; 1140 | 1141 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; 1142 | if (IS_DIRSYNC(inode)) 1143 | (void) exfat_sync_inode(inode); 1144 | else 1145 | mark_inode_dirty(inode); 1146 | 1147 | inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) 1148 | & ~((loff_t)p_fs->cluster_size - 1)) >> 9; 1149 | out: 1150 | __unlock_super(sb); 1151 | } 1152 | 1153 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) 1154 | static void exfat_truncate(struct inode *inode) 1155 | { 1156 | _exfat_truncate(inode, i_size_read(inode)); 1157 | } 1158 | #endif 1159 | 1160 | const struct inode_operations exfat_file_inode_operations = { 1161 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) 1162 | .truncate = exfat_truncate, 1163 | #endif 1164 | .setattr = exfat_setattr, 1165 | .getattr = exfat_getattr, 1166 | }; 1167 | 1168 | static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys, 1169 | unsigned long *mapped_blocks, int *create) 1170 | { 1171 | struct super_block *sb = inode->i_sb; 1172 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 1173 | FS_INFO_T *p_fs = &(sbi->fs_info); 1174 | BD_INFO_T *p_bd = &(sbi->bd_info); 1175 | const unsigned long blocksize = sb->s_blocksize; 1176 | const unsigned char blocksize_bits = sb->s_blocksize_bits; 1177 | sector_t last_block; 1178 | int err, clu_offset, sec_offset; 1179 | unsigned int cluster; 1180 | 1181 | *phys = 0; 1182 | *mapped_blocks = 0; 1183 | 1184 | if ((p_fs->vol_type == FAT12) || (p_fs->vol_type == FAT16)) { 1185 | if (inode->i_ino == EXFAT_ROOT_INO) { 1186 | if (sector < (p_fs->dentries_in_root >> (p_bd->sector_size_bits-DENTRY_SIZE_BITS))) { 1187 | *phys = sector + p_fs->root_start_sector; 1188 | *mapped_blocks = 1; 1189 | } 1190 | return 0; 1191 | } 1192 | } 1193 | 1194 | last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits; 1195 | if (sector >= last_block) { 1196 | if (*create == 0) return 0; 1197 | } else { 1198 | *create = 0; 1199 | } 1200 | 1201 | clu_offset = sector >> p_fs->sectors_per_clu_bits; 1202 | sec_offset = sector & (p_fs->sectors_per_clu - 1); 1203 | 1204 | EXFAT_I(inode)->fid.size = i_size_read(inode); 1205 | 1206 | err = FsMapCluster(inode, clu_offset, &cluster); 1207 | 1208 | if (err) { 1209 | if (err == FFS_FULL) 1210 | return -ENOSPC; 1211 | else 1212 | return -EIO; 1213 | } else if (cluster != CLUSTER_32(~0)) { 1214 | *phys = START_SECTOR(cluster) + sec_offset; 1215 | *mapped_blocks = p_fs->sectors_per_clu - sec_offset; 1216 | } 1217 | 1218 | return 0; 1219 | } 1220 | 1221 | static int exfat_get_block(struct inode *inode, sector_t iblock, 1222 | struct buffer_head *bh_result, int create) 1223 | { 1224 | struct super_block *sb = inode->i_sb; 1225 | unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; 1226 | int err; 1227 | unsigned long mapped_blocks; 1228 | sector_t phys; 1229 | 1230 | __lock_super(sb); 1231 | 1232 | err = exfat_bmap(inode, iblock, &phys, &mapped_blocks, &create); 1233 | if (err) { 1234 | __unlock_super(sb); 1235 | return err; 1236 | } 1237 | 1238 | if (phys) { 1239 | max_blocks = min(mapped_blocks, max_blocks); 1240 | if (create) { 1241 | EXFAT_I(inode)->mmu_private += max_blocks << sb->s_blocksize_bits; 1242 | set_buffer_new(bh_result); 1243 | } 1244 | map_bh(bh_result, sb, phys); 1245 | } 1246 | 1247 | bh_result->b_size = max_blocks << sb->s_blocksize_bits; 1248 | __unlock_super(sb); 1249 | 1250 | return 0; 1251 | } 1252 | 1253 | static int exfat_readpage(struct file *file, struct page *page) 1254 | { 1255 | int ret; 1256 | ret = mpage_readpage(page, exfat_get_block); 1257 | return ret; 1258 | } 1259 | 1260 | static int exfat_readpages(struct file *file, struct address_space *mapping, 1261 | struct list_head *pages, unsigned nr_pages) 1262 | { 1263 | int ret; 1264 | ret = mpage_readpages(mapping, pages, nr_pages, exfat_get_block); 1265 | return ret; 1266 | } 1267 | 1268 | static int exfat_writepage(struct page *page, struct writeback_control *wbc) 1269 | { 1270 | int ret; 1271 | ret = block_write_full_page(page, exfat_get_block, wbc); 1272 | return ret; 1273 | } 1274 | 1275 | static int exfat_writepages(struct address_space *mapping, 1276 | struct writeback_control *wbc) 1277 | { 1278 | int ret; 1279 | ret = mpage_writepages(mapping, wbc, exfat_get_block); 1280 | return ret; 1281 | } 1282 | 1283 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) 1284 | static void exfat_write_failed(struct address_space *mapping, loff_t to) 1285 | { 1286 | struct inode *inode = mapping->host; 1287 | if (to > i_size_read(inode)) { 1288 | truncate_pagecache(inode, to, i_size_read(inode)); 1289 | EXFAT_I(inode)->fid.size = i_size_read(inode); 1290 | _exfat_truncate(inode, i_size_read(inode)); 1291 | } 1292 | } 1293 | #endif 1294 | 1295 | 1296 | static int exfat_write_begin(struct file *file, struct address_space *mapping, 1297 | loff_t pos, unsigned len, unsigned flags, 1298 | struct page **pagep, void **fsdata) 1299 | { 1300 | int ret; 1301 | *pagep = NULL; 1302 | ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, 1303 | exfat_get_block, 1304 | &EXFAT_I(mapping->host)->mmu_private); 1305 | 1306 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) 1307 | if (ret < 0) 1308 | exfat_write_failed(mapping, pos+len); 1309 | #endif 1310 | return ret; 1311 | } 1312 | 1313 | static int exfat_write_end(struct file *file, struct address_space *mapping, 1314 | loff_t pos, unsigned len, unsigned copied, 1315 | struct page *pagep, void *fsdata) 1316 | { 1317 | struct inode *inode = mapping->host; 1318 | FILE_ID_T *fid = &(EXFAT_I(inode)->fid); 1319 | int err; 1320 | 1321 | err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); 1322 | 1323 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) 1324 | if (err < len) 1325 | exfat_write_failed(mapping, pos+len); 1326 | #endif 1327 | 1328 | if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) { 1329 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; 1330 | fid->attr |= ATTR_ARCHIVE; 1331 | mark_inode_dirty(inode); 1332 | } 1333 | return err; 1334 | } 1335 | 1336 | static ssize_t exfat_direct_IO(int rw, struct kiocb *iocb, 1337 | const struct iovec *iov, 1338 | loff_t offset, unsigned long nr_segs) 1339 | { 1340 | struct inode *inode = iocb->ki_filp->f_mapping->host; 1341 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) 1342 | struct address_space *mapping = iocb->ki_filp->f_mapping; 1343 | #endif 1344 | ssize_t ret; 1345 | 1346 | if (rw == WRITE) { 1347 | if (EXFAT_I(inode)->mmu_private < (offset + iov_length(iov, nr_segs))) 1348 | return 0; 1349 | } 1350 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) 1351 | ret = blockdev_direct_IO(rw, iocb, inode, iov, 1352 | offset, nr_segs, exfat_get_block); 1353 | #else 1354 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, 1355 | offset, nr_segs, exfat_get_block, NULL); 1356 | #endif 1357 | 1358 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) 1359 | if ((ret < 0) && (rw & WRITE)) 1360 | exfat_write_failed(mapping, offset+iov_length(iov, nr_segs)); 1361 | #endif 1362 | return ret; 1363 | 1364 | } 1365 | 1366 | static sector_t _exfat_bmap(struct address_space *mapping, sector_t block) 1367 | { 1368 | sector_t blocknr; 1369 | 1370 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) 1371 | down_read(&EXFAT_I(mapping->host)->truncate_lock); 1372 | blocknr = generic_block_bmap(mapping, block, exfat_get_block); 1373 | up_read(&EXFAT_I(mapping->host)->truncate_lock); 1374 | #else 1375 | down_read(&mapping->host->i_alloc_sem); 1376 | blocknr = generic_block_bmap(mapping, block, exfat_get_block); 1377 | up_read(&mapping->host->i_alloc_sem); 1378 | #endif 1379 | 1380 | return blocknr; 1381 | } 1382 | 1383 | const struct address_space_operations exfat_aops = { 1384 | .readpage = exfat_readpage, 1385 | .readpages = exfat_readpages, 1386 | .writepage = exfat_writepage, 1387 | .writepages = exfat_writepages, 1388 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) 1389 | .sync_page = block_sync_page, 1390 | #endif 1391 | .write_begin = exfat_write_begin, 1392 | .write_end = exfat_write_end, 1393 | .direct_IO = exfat_direct_IO, 1394 | .bmap = _exfat_bmap 1395 | }; 1396 | 1397 | static inline unsigned long exfat_hash(loff_t i_pos) 1398 | { 1399 | return hash_32(i_pos, EXFAT_HASH_BITS); 1400 | } 1401 | 1402 | static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos) { 1403 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 1404 | struct exfat_inode_info *info; 1405 | struct hlist_node *node; 1406 | struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); 1407 | struct inode *inode = NULL; 1408 | 1409 | spin_lock(&sbi->inode_hash_lock); 1410 | hlist_for_each_entry(info, node, head, i_hash_fat) { 1411 | CHECK_ERR(info->vfs_inode.i_sb != sb); 1412 | 1413 | if (i_pos != info->i_pos) 1414 | continue; 1415 | inode = igrab(&info->vfs_inode); 1416 | if (inode) 1417 | break; 1418 | } 1419 | spin_unlock(&sbi->inode_hash_lock); 1420 | return inode; 1421 | } 1422 | 1423 | static void exfat_attach(struct inode *inode, loff_t i_pos) 1424 | { 1425 | struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); 1426 | struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); 1427 | 1428 | spin_lock(&sbi->inode_hash_lock); 1429 | EXFAT_I(inode)->i_pos = i_pos; 1430 | hlist_add_head(&EXFAT_I(inode)->i_hash_fat, head); 1431 | spin_unlock(&sbi->inode_hash_lock); 1432 | } 1433 | 1434 | static void exfat_detach(struct inode *inode) 1435 | { 1436 | struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); 1437 | 1438 | spin_lock(&sbi->inode_hash_lock); 1439 | hlist_del_init(&EXFAT_I(inode)->i_hash_fat); 1440 | EXFAT_I(inode)->i_pos = 0; 1441 | spin_unlock(&sbi->inode_hash_lock); 1442 | } 1443 | 1444 | static int exfat_fill_inode(struct inode *inode, FILE_ID_T *fid) 1445 | { 1446 | struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); 1447 | FS_INFO_T *p_fs = &(sbi->fs_info); 1448 | DIR_ENTRY_T info; 1449 | 1450 | memcpy(&(EXFAT_I(inode)->fid), fid, sizeof(FILE_ID_T)); 1451 | 1452 | FsReadStat(inode, &info); 1453 | 1454 | EXFAT_I(inode)->i_pos = 0; 1455 | EXFAT_I(inode)->target = NULL; 1456 | inode->i_uid = sbi->options.fs_uid; 1457 | inode->i_gid = sbi->options.fs_gid; 1458 | inode->i_version++; 1459 | inode->i_generation = get_seconds(); 1460 | 1461 | if (info.Attr & ATTR_SUBDIR) { 1462 | inode->i_generation &= ~1; 1463 | inode->i_mode = exfat_make_mode(sbi, info.Attr, S_IRWXUGO); 1464 | inode->i_op = &exfat_dir_inode_operations; 1465 | inode->i_fop = &exfat_dir_operations; 1466 | 1467 | i_size_write(inode, info.Size); 1468 | EXFAT_I(inode)->mmu_private = i_size_read(inode); 1469 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) 1470 | set_nlink(inode,info.NumSubdirs); 1471 | #else 1472 | inode->i_nlink = info.NumSubdirs; 1473 | #endif 1474 | } else if (info.Attr & ATTR_SYMLINK) { 1475 | inode->i_generation |= 1; 1476 | inode->i_mode = exfat_make_mode(sbi, info.Attr, S_IRWXUGO); 1477 | inode->i_op = &exfat_symlink_inode_operations; 1478 | 1479 | i_size_write(inode, info.Size); 1480 | EXFAT_I(inode)->mmu_private = i_size_read(inode); 1481 | } else { 1482 | inode->i_generation |= 1; 1483 | inode->i_mode = exfat_make_mode(sbi, info.Attr, S_IRWXUGO); 1484 | inode->i_op = &exfat_file_inode_operations; 1485 | inode->i_fop = &exfat_file_operations; 1486 | inode->i_mapping->a_ops = &exfat_aops; 1487 | inode->i_mapping->nrpages = 0; 1488 | 1489 | i_size_write(inode, info.Size); 1490 | EXFAT_I(inode)->mmu_private = i_size_read(inode); 1491 | } 1492 | exfat_save_attr(inode, info.Attr); 1493 | 1494 | inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) 1495 | & ~((loff_t)p_fs->cluster_size - 1)) >> 9; 1496 | 1497 | exfat_time_fat2unix(sbi, &inode->i_mtime, &info.ModifyTimestamp); 1498 | exfat_time_fat2unix(sbi, &inode->i_ctime, &info.CreateTimestamp); 1499 | exfat_time_fat2unix(sbi, &inode->i_atime, &info.AccessTimestamp); 1500 | 1501 | return 0; 1502 | } 1503 | 1504 | static struct inode *exfat_build_inode(struct super_block *sb, 1505 | FILE_ID_T *fid, loff_t i_pos) { 1506 | struct inode *inode; 1507 | int err; 1508 | 1509 | inode = exfat_iget(sb, i_pos); 1510 | if (inode) 1511 | goto out; 1512 | inode = new_inode(sb); 1513 | if (!inode) { 1514 | inode = ERR_PTR(-ENOMEM); 1515 | goto out; 1516 | } 1517 | inode->i_ino = iunique(sb, EXFAT_ROOT_INO); 1518 | inode->i_version = 1; 1519 | err = exfat_fill_inode(inode, fid); 1520 | if (err) { 1521 | iput(inode); 1522 | inode = ERR_PTR(err); 1523 | goto out; 1524 | } 1525 | exfat_attach(inode, i_pos); 1526 | insert_inode_hash(inode); 1527 | out: 1528 | return inode; 1529 | } 1530 | 1531 | static int exfat_sync_inode(struct inode *inode) 1532 | { 1533 | return exfat_write_inode(inode, NULL); 1534 | } 1535 | 1536 | static struct inode *exfat_alloc_inode(struct super_block *sb) { 1537 | struct exfat_inode_info *ei; 1538 | 1539 | ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS); 1540 | if (!ei) 1541 | return NULL; 1542 | 1543 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) 1544 | init_rwsem(&ei->truncate_lock); 1545 | #endif 1546 | 1547 | return &ei->vfs_inode; 1548 | } 1549 | 1550 | static void exfat_destroy_inode(struct inode *inode) 1551 | { 1552 | FREE(EXFAT_I(inode)->target); 1553 | EXFAT_I(inode)->target = NULL; 1554 | 1555 | kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); 1556 | } 1557 | 1558 | static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc) 1559 | { 1560 | struct super_block *sb = inode->i_sb; 1561 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 1562 | DIR_ENTRY_T info; 1563 | 1564 | if (inode->i_ino == EXFAT_ROOT_INO) 1565 | return 0; 1566 | 1567 | info.Attr = exfat_make_attr(inode); 1568 | info.Size = i_size_read(inode); 1569 | 1570 | exfat_time_unix2fat(sbi, &inode->i_mtime, &info.ModifyTimestamp); 1571 | exfat_time_unix2fat(sbi, &inode->i_ctime, &info.CreateTimestamp); 1572 | exfat_time_unix2fat(sbi, &inode->i_atime, &info.AccessTimestamp); 1573 | 1574 | FsWriteStat(inode, &info); 1575 | 1576 | return 0; 1577 | } 1578 | 1579 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) 1580 | static void exfat_delete_inode(struct inode *inode) 1581 | { 1582 | truncate_inode_pages(&inode->i_data, 0); 1583 | clear_inode(inode); 1584 | } 1585 | 1586 | static void exfat_clear_inode(struct inode *inode) 1587 | { 1588 | exfat_detach(inode); 1589 | remove_inode_hash(inode); 1590 | } 1591 | #else 1592 | static void exfat_evict_inode(struct inode *inode) 1593 | { 1594 | truncate_inode_pages(&inode->i_data, 0); 1595 | 1596 | if (!inode->i_nlink) 1597 | i_size_write(inode, 0); 1598 | invalidate_inode_buffers(inode); 1599 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,00) 1600 | end_writeback(inode); 1601 | #else 1602 | clear_inode(inode); 1603 | #endif 1604 | exfat_detach(inode); 1605 | 1606 | remove_inode_hash(inode); 1607 | } 1608 | #endif 1609 | 1610 | 1611 | static void exfat_put_super(struct super_block *sb) 1612 | { 1613 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 1614 | if (__is_sb_dirty(sb)) 1615 | exfat_write_super(sb); 1616 | 1617 | FsUmountVol(sb); 1618 | 1619 | if (sbi->nls_disk) { 1620 | unload_nls(sbi->nls_disk); 1621 | sbi->nls_disk = NULL; 1622 | sbi->options.codepage = exfat_default_codepage; 1623 | } 1624 | if (sbi->nls_io) { 1625 | unload_nls(sbi->nls_io); 1626 | sbi->nls_io = NULL; 1627 | } 1628 | if (sbi->options.iocharset != exfat_default_iocharset) { 1629 | kfree(sbi->options.iocharset); 1630 | sbi->options.iocharset = exfat_default_iocharset; 1631 | } 1632 | 1633 | sb->s_fs_info = NULL; 1634 | kfree(sbi); 1635 | } 1636 | 1637 | static void exfat_write_super(struct super_block *sb) 1638 | { 1639 | __lock_super(sb); 1640 | 1641 | __set_sb_clean(sb); 1642 | 1643 | if (!(sb->s_flags & MS_RDONLY)) 1644 | FsSyncVol(sb, 1); 1645 | 1646 | __unlock_super(sb); 1647 | } 1648 | 1649 | static int exfat_sync_fs(struct super_block *sb, int wait) 1650 | { 1651 | int err = 0; 1652 | 1653 | if (__is_sb_dirty(sb)) { 1654 | __lock_super(sb); 1655 | __set_sb_clean(sb); 1656 | err = FsSyncVol(sb, 1); 1657 | __unlock_super(sb); 1658 | } 1659 | 1660 | return err; 1661 | } 1662 | 1663 | static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) 1664 | { 1665 | struct super_block *sb = dentry->d_sb; 1666 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); 1667 | FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); 1668 | VOL_INFO_T info; 1669 | 1670 | if (p_fs->used_clusters == (UINT32) ~0) { 1671 | if (FFS_MEDIAERR == FsGetVolInfo(sb, &info)) 1672 | return -EIO; 1673 | 1674 | } else { 1675 | info.FatType = p_fs->vol_type; 1676 | info.ClusterSize = p_fs->cluster_size; 1677 | info.NumClusters = p_fs->num_clusters - 2; 1678 | info.UsedClusters = p_fs->used_clusters; 1679 | info.FreeClusters = info.NumClusters - info.UsedClusters; 1680 | 1681 | if (p_fs->dev_ejected) 1682 | return -EIO; 1683 | } 1684 | 1685 | buf->f_type = sb->s_magic; 1686 | buf->f_bsize = info.ClusterSize; 1687 | buf->f_blocks = info.NumClusters; 1688 | buf->f_bfree = info.FreeClusters; 1689 | buf->f_bavail = info.FreeClusters; 1690 | buf->f_fsid.val[0] = (u32)id; 1691 | buf->f_fsid.val[1] = (u32)(id >> 32); 1692 | buf->f_namelen = 260; 1693 | 1694 | return 0; 1695 | } 1696 | 1697 | static int exfat_remount(struct super_block *sb, int *flags, char *data) 1698 | { 1699 | *flags |= MS_NODIRATIME; 1700 | return 0; 1701 | } 1702 | 1703 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) 1704 | static int exfat_show_options(struct seq_file *m, struct dentry *root) 1705 | { 1706 | struct exfat_sb_info *sbi = EXFAT_SB(root->d_sb); 1707 | #else 1708 | static int exfat_show_options(struct seq_file *m, struct vfsmount *mnt) 1709 | { 1710 | struct exfat_sb_info *sbi = EXFAT_SB(mnt->mnt_sb); 1711 | #endif 1712 | struct exfat_mount_options *opts = &sbi->options; 1713 | 1714 | if (opts->fs_uid != 0) 1715 | seq_printf(m, ",uid=%u", opts->fs_uid); 1716 | if (opts->fs_gid != 0) 1717 | seq_printf(m, ",gid=%u", opts->fs_gid); 1718 | seq_printf(m, ",fmask=%04o", opts->fs_fmask); 1719 | seq_printf(m, ",dmask=%04o", opts->fs_dmask); 1720 | if (opts->allow_utime) 1721 | seq_printf(m, ",allow_utime=%04o", opts->allow_utime); 1722 | if (sbi->nls_disk) 1723 | seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); 1724 | if (sbi->nls_io) 1725 | seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); 1726 | seq_printf(m, ",namecase=%u", opts->casesensitive); 1727 | if (opts->errors == EXFAT_ERRORS_CONT) 1728 | seq_puts(m, ",errors=continue"); 1729 | else if (opts->errors == EXFAT_ERRORS_PANIC) 1730 | seq_puts(m, ",errors=panic"); 1731 | else 1732 | seq_puts(m, ",errors=remount-ro"); 1733 | #if EXFAT_CONFIG_DISCARD 1734 | if (opts->discard) 1735 | seq_printf(m, ",discard"); 1736 | #endif 1737 | return 0; 1738 | } 1739 | 1740 | const struct super_operations exfat_sops = { 1741 | .alloc_inode = exfat_alloc_inode, 1742 | .destroy_inode = exfat_destroy_inode, 1743 | .write_inode = exfat_write_inode, 1744 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) 1745 | .delete_inode = exfat_delete_inode, 1746 | .clear_inode = exfat_clear_inode, 1747 | #else 1748 | .evict_inode = exfat_evict_inode, 1749 | #endif 1750 | .put_super = exfat_put_super, 1751 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,00) 1752 | .write_super = exfat_write_super, 1753 | #endif 1754 | .sync_fs = exfat_sync_fs, 1755 | .statfs = exfat_statfs, 1756 | .remount_fs = exfat_remount, 1757 | .show_options = exfat_show_options, 1758 | }; 1759 | 1760 | enum { 1761 | Opt_uid, 1762 | Opt_gid, 1763 | Opt_umask, 1764 | Opt_dmask, 1765 | Opt_fmask, 1766 | Opt_allow_utime, 1767 | Opt_codepage, 1768 | Opt_charset, 1769 | Opt_namecase, 1770 | Opt_debug, 1771 | Opt_err_cont, 1772 | Opt_err_panic, 1773 | Opt_err_ro, 1774 | Opt_err, 1775 | #if EXFAT_CONFIG_DISCARD 1776 | Opt_discard, 1777 | #endif 1778 | }; 1779 | 1780 | static const match_table_t exfat_tokens = { 1781 | {Opt_uid, "uid=%u"}, 1782 | {Opt_gid, "gid=%u"}, 1783 | {Opt_umask, "umask=%o"}, 1784 | {Opt_dmask, "dmask=%o"}, 1785 | {Opt_fmask, "fmask=%o"}, 1786 | {Opt_allow_utime, "allow_utime=%o"}, 1787 | {Opt_codepage, "codepage=%u"}, 1788 | {Opt_charset, "iocharset=%s"}, 1789 | {Opt_namecase, "namecase=%u"}, 1790 | {Opt_debug, "debug"}, 1791 | {Opt_err_cont, "errors=continue"}, 1792 | {Opt_err_panic, "errors=panic"}, 1793 | {Opt_err_ro, "errors=remount-ro"}, 1794 | #if EXFAT_CONFIG_DISCARD 1795 | {Opt_discard, "discard"}, 1796 | #endif 1797 | {Opt_err, NULL} 1798 | }; 1799 | 1800 | static int parse_options(char *options, int silent, int *debug, 1801 | struct exfat_mount_options *opts) 1802 | { 1803 | char *p; 1804 | substring_t args[MAX_OPT_ARGS]; 1805 | int option; 1806 | char *iocharset; 1807 | 1808 | opts->fs_uid = current_uid(); 1809 | opts->fs_gid = current_gid(); 1810 | opts->fs_fmask = opts->fs_dmask = current->fs->umask; 1811 | opts->allow_utime = (unsigned short) -1; 1812 | opts->codepage = exfat_default_codepage; 1813 | opts->iocharset = exfat_default_iocharset; 1814 | opts->casesensitive = 0; 1815 | opts->errors = EXFAT_ERRORS_RO; 1816 | #if EXFAT_CONFIG_DISCARD 1817 | opts->discard = 0; 1818 | #endif 1819 | *debug = 0; 1820 | 1821 | if (!options) 1822 | goto out; 1823 | 1824 | while ((p = strsep(&options, ",")) != NULL) { 1825 | int token; 1826 | if (!*p) 1827 | continue; 1828 | 1829 | token = match_token(p, exfat_tokens, args); 1830 | switch (token) { 1831 | case Opt_uid: 1832 | if (match_int(&args[0], &option)) 1833 | return 0; 1834 | opts->fs_uid = option; 1835 | break; 1836 | case Opt_gid: 1837 | if (match_int(&args[0], &option)) 1838 | return 0; 1839 | opts->fs_gid = option; 1840 | break; 1841 | case Opt_umask: 1842 | case Opt_dmask: 1843 | case Opt_fmask: 1844 | if (match_octal(&args[0], &option)) 1845 | return 0; 1846 | if (token != Opt_dmask) 1847 | opts->fs_fmask = option; 1848 | if (token != Opt_fmask) 1849 | opts->fs_dmask = option; 1850 | break; 1851 | case Opt_allow_utime: 1852 | if (match_octal(&args[0], &option)) 1853 | return 0; 1854 | opts->allow_utime = option & (S_IWGRP | S_IWOTH); 1855 | break; 1856 | case Opt_codepage: 1857 | if (match_int(&args[0], &option)) 1858 | return 0; 1859 | opts->codepage = option; 1860 | break; 1861 | case Opt_charset: 1862 | if (opts->iocharset != exfat_default_iocharset) 1863 | kfree(opts->iocharset); 1864 | iocharset = match_strdup(&args[0]); 1865 | if (!iocharset) 1866 | return -ENOMEM; 1867 | opts->iocharset = iocharset; 1868 | break; 1869 | case Opt_namecase: 1870 | if (match_int(&args[0], &option)) 1871 | return 0; 1872 | opts->casesensitive = option; 1873 | break; 1874 | case Opt_err_cont: 1875 | opts->errors = EXFAT_ERRORS_CONT; 1876 | break; 1877 | case Opt_err_panic: 1878 | opts->errors = EXFAT_ERRORS_PANIC; 1879 | break; 1880 | case Opt_err_ro: 1881 | opts->errors = EXFAT_ERRORS_RO; 1882 | break; 1883 | case Opt_debug: 1884 | *debug = 1; 1885 | break; 1886 | #if EXFAT_CONFIG_DISCARD 1887 | case Opt_discard: 1888 | opts->discard = 1; 1889 | break; 1890 | #endif 1891 | default: 1892 | if (!silent) { 1893 | printk(KERN_ERR "[EXFAT] Unrecognized mount option %s or missing value\n", p); 1894 | } 1895 | return -EINVAL; 1896 | } 1897 | } 1898 | 1899 | out: 1900 | if (opts->allow_utime == (unsigned short) -1) 1901 | opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH); 1902 | 1903 | return 0; 1904 | } 1905 | 1906 | static void exfat_hash_init(struct super_block *sb) 1907 | { 1908 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 1909 | int i; 1910 | 1911 | spin_lock_init(&sbi->inode_hash_lock); 1912 | for (i = 0; i < EXFAT_HASH_SIZE; i++) 1913 | INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); 1914 | } 1915 | 1916 | static int exfat_read_root(struct inode *inode) 1917 | { 1918 | struct super_block *sb = inode->i_sb; 1919 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 1920 | struct timespec ts; 1921 | FS_INFO_T *p_fs = &(sbi->fs_info); 1922 | DIR_ENTRY_T info; 1923 | 1924 | ts = CURRENT_TIME_SEC; 1925 | 1926 | EXFAT_I(inode)->fid.dir.dir = p_fs->root_dir; 1927 | EXFAT_I(inode)->fid.dir.flags = 0x01; 1928 | EXFAT_I(inode)->fid.entry = -1; 1929 | EXFAT_I(inode)->fid.start_clu = p_fs->root_dir; 1930 | EXFAT_I(inode)->fid.flags = 0x01; 1931 | EXFAT_I(inode)->fid.type = TYPE_DIR; 1932 | EXFAT_I(inode)->fid.rwoffset = 0; 1933 | EXFAT_I(inode)->fid.hint_last_off = -1; 1934 | 1935 | EXFAT_I(inode)->target = NULL; 1936 | 1937 | FsReadStat(inode, &info); 1938 | 1939 | inode->i_uid = sbi->options.fs_uid; 1940 | inode->i_gid = sbi->options.fs_gid; 1941 | inode->i_version++; 1942 | inode->i_generation = 0; 1943 | inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, S_IRWXUGO); 1944 | inode->i_op = &exfat_dir_inode_operations; 1945 | inode->i_fop = &exfat_dir_operations; 1946 | 1947 | i_size_write(inode, info.Size); 1948 | inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) 1949 | & ~((loff_t)p_fs->cluster_size - 1)) >> 9; 1950 | EXFAT_I(inode)->i_pos = ((loff_t) p_fs->root_dir << 32) | 0xffffffff; 1951 | EXFAT_I(inode)->mmu_private = i_size_read(inode); 1952 | 1953 | exfat_save_attr(inode, ATTR_SUBDIR); 1954 | inode->i_mtime = inode->i_atime = inode->i_ctime = ts; 1955 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) 1956 | set_nlink(inode,info.NumSubdirs + 2); 1957 | #else 1958 | inode->i_nlink = info.NumSubdirs + 2; 1959 | #endif 1960 | 1961 | return 0; 1962 | } 1963 | 1964 | static int exfat_fill_super(struct super_block *sb, void *data, int silent) 1965 | { 1966 | struct inode *root_inode = NULL; 1967 | struct exfat_sb_info *sbi; 1968 | int debug, ret; 1969 | long error; 1970 | char buf[50]; 1971 | 1972 | sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL); 1973 | if (!sbi) 1974 | return -ENOMEM; 1975 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 1976 | mutex_init(&sbi->s_lock); 1977 | #endif 1978 | sb->s_fs_info = sbi; 1979 | 1980 | sb->s_flags |= MS_NODIRATIME; 1981 | sb->s_magic = EXFAT_SUPER_MAGIC; 1982 | sb->s_op = &exfat_sops; 1983 | 1984 | error = parse_options(data, silent, &debug, &sbi->options); 1985 | if (error) 1986 | goto out_fail; 1987 | 1988 | error = -EIO; 1989 | sb_min_blocksize(sb, 512); 1990 | sb->s_maxbytes = 0x7fffffffffffffffLL; 1991 | 1992 | ret = FsMountVol(sb); 1993 | if (ret) { 1994 | if (!silent) 1995 | printk(KERN_ERR "[EXFAT] FsMountVol failed\n"); 1996 | 1997 | goto out_fail; 1998 | } 1999 | 2000 | exfat_hash_init(sb); 2001 | 2002 | error = -EINVAL; 2003 | sprintf(buf, "cp%d", sbi->options.codepage); 2004 | sbi->nls_disk = load_nls(buf); 2005 | if (!sbi->nls_disk) { 2006 | printk(KERN_ERR "[EXFAT] Codepage %s not found\n", buf); 2007 | goto out_fail2; 2008 | } 2009 | 2010 | sbi->nls_io = load_nls(sbi->options.iocharset); 2011 | if (!sbi->nls_io) { 2012 | printk(KERN_ERR "[EXFAT] IO charset %s not found\n", 2013 | sbi->options.iocharset); 2014 | goto out_fail2; 2015 | } 2016 | 2017 | error = -ENOMEM; 2018 | root_inode = new_inode(sb); 2019 | if (!root_inode) 2020 | goto out_fail2; 2021 | root_inode->i_ino = EXFAT_ROOT_INO; 2022 | root_inode->i_version = 1; 2023 | error = exfat_read_root(root_inode); 2024 | if (error < 0) 2025 | goto out_fail2; 2026 | error = -ENOMEM; 2027 | exfat_attach(root_inode, EXFAT_I(root_inode)->i_pos); 2028 | insert_inode_hash(root_inode); 2029 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) 2030 | sb->s_root = d_make_root(root_inode); 2031 | #else 2032 | sb->s_root = d_alloc_root(root_inode); 2033 | #endif 2034 | if (!sb->s_root) { 2035 | printk(KERN_ERR "[EXFAT] Getting the root inode failed\n"); 2036 | goto out_fail2; 2037 | } 2038 | 2039 | return 0; 2040 | 2041 | out_fail2: 2042 | FsUmountVol(sb); 2043 | out_fail: 2044 | if (root_inode) 2045 | iput(root_inode); 2046 | if (sbi->nls_io) 2047 | unload_nls(sbi->nls_io); 2048 | if (sbi->nls_disk) 2049 | unload_nls(sbi->nls_disk); 2050 | if (sbi->options.iocharset != exfat_default_iocharset) 2051 | kfree(sbi->options.iocharset); 2052 | sb->s_fs_info = NULL; 2053 | kfree(sbi); 2054 | return error; 2055 | } 2056 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) 2057 | static int exfat_get_sb(struct file_system_type *fs_type, 2058 | int flags, const char *dev_name, 2059 | void *data, struct vfsmount *mnt) 2060 | { 2061 | return get_sb_bdev(fs_type, flags, dev_name, data, exfat_fill_super, mnt); 2062 | } 2063 | #else 2064 | static struct dentry *exfat_fs_mount(struct file_system_type *fs_type, 2065 | int flags, const char *dev_name, 2066 | void *data) { 2067 | return mount_bdev(fs_type, flags, dev_name, data, exfat_fill_super); 2068 | } 2069 | #endif 2070 | 2071 | static void init_once(void *foo) 2072 | { 2073 | struct exfat_inode_info *ei = (struct exfat_inode_info *)foo; 2074 | 2075 | INIT_HLIST_NODE(&ei->i_hash_fat); 2076 | inode_init_once(&ei->vfs_inode); 2077 | } 2078 | 2079 | static int __init exfat_init_inodecache(void) 2080 | { 2081 | exfat_inode_cachep = kmem_cache_create("exfat_inode_cache", 2082 | sizeof(struct exfat_inode_info), 2083 | 0, (SLAB_RECLAIM_ACCOUNT| 2084 | SLAB_MEM_SPREAD), 2085 | init_once); 2086 | if (exfat_inode_cachep == NULL) 2087 | return -ENOMEM; 2088 | return 0; 2089 | } 2090 | 2091 | static void __exit exfat_destroy_inodecache(void) 2092 | { 2093 | kmem_cache_destroy(exfat_inode_cachep); 2094 | } 2095 | 2096 | #if EXFAT_CONFIG_KERNEL_DEBUG 2097 | static void exfat_debug_kill_sb(struct super_block *sb) 2098 | { 2099 | struct exfat_sb_info *sbi = EXFAT_SB(sb); 2100 | struct block_device *bdev = sb->s_bdev; 2101 | 2102 | long flags; 2103 | 2104 | if (sbi) { 2105 | flags = sbi->debug_flags; 2106 | 2107 | if (flags & EXFAT_DEBUGFLAGS_INVALID_UMOUNT) { 2108 | FsReleaseCache(sb); 2109 | invalidate_bdev(bdev); 2110 | } 2111 | } 2112 | 2113 | kill_block_super(sb); 2114 | } 2115 | #endif 2116 | 2117 | static struct file_system_type exfat_fs_type = { 2118 | .owner = THIS_MODULE, 2119 | .name = "exfat", 2120 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) 2121 | .get_sb = exfat_get_sb, 2122 | #else 2123 | .mount = exfat_fs_mount, 2124 | #endif 2125 | #if EXFAT_CONFIG_KERNEL_DEBUG 2126 | .kill_sb = exfat_debug_kill_sb, 2127 | #else 2128 | .kill_sb = kill_block_super, 2129 | #endif 2130 | .fs_flags = FS_REQUIRES_DEV, 2131 | }; 2132 | 2133 | static int __init init_exfat_fs(void) 2134 | { 2135 | int err; 2136 | 2137 | printk(KERN_INFO "exFAT: FS Version %s\n", EXFAT_VERSION); 2138 | 2139 | err = exfat_init_inodecache(); 2140 | if (err) return err; 2141 | 2142 | return register_filesystem(&exfat_fs_type); 2143 | } 2144 | 2145 | static void __exit exit_exfat_fs(void) 2146 | { 2147 | exfat_destroy_inodecache(); 2148 | unregister_filesystem(&exfat_fs_type); 2149 | } 2150 | 2151 | module_init(init_exfat_fs); 2152 | module_exit(exit_exfat_fs); 2153 | 2154 | MODULE_LICENSE("GPL"); 2155 | -------------------------------------------------------------------------------- /exfat_super.h: -------------------------------------------------------------------------------- 1 | /* Some of the source code in this file came from "linux/fs/fat/fat.h". */ 2 | 3 | /* 4 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; either version 2 9 | * of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #ifndef _EXFAT_LINUX_H 22 | #define _EXFAT_LINUX_H 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "exfat_config.h" 32 | #include "exfat_global.h" 33 | #include "exfat_data.h" 34 | #include "exfat_oal.h" 35 | 36 | #include "exfat_blkdev.h" 37 | #include "exfat_cache.h" 38 | #include "exfat_part.h" 39 | #include "exfat_nls.h" 40 | #include "exfat_api.h" 41 | #include "exfat.h" 42 | 43 | #define EXFAT_ERRORS_CONT 1 44 | #define EXFAT_ERRORS_PANIC 2 45 | #define EXFAT_ERRORS_RO 3 46 | 47 | #define EXFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32) 48 | 49 | struct exfat_mount_options { 50 | uid_t fs_uid; 51 | gid_t fs_gid; 52 | unsigned short fs_fmask; 53 | unsigned short fs_dmask; 54 | unsigned short allow_utime; 55 | unsigned short codepage; 56 | char *iocharset; 57 | unsigned char casesensitive; 58 | unsigned char errors; 59 | #if EXFAT_CONFIG_DISCARD 60 | unsigned char discard; 61 | #endif 62 | }; 63 | 64 | #define EXFAT_HASH_BITS 8 65 | #define EXFAT_HASH_SIZE (1UL << EXFAT_HASH_BITS) 66 | 67 | struct exfat_sb_info { 68 | FS_INFO_T fs_info; 69 | BD_INFO_T bd_info; 70 | 71 | struct exfat_mount_options options; 72 | 73 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00) 74 | int s_dirt; 75 | struct mutex s_lock; 76 | #endif 77 | struct nls_table *nls_disk; 78 | struct nls_table *nls_io; 79 | 80 | struct inode *fat_inode; 81 | 82 | spinlock_t inode_hash_lock; 83 | struct hlist_head inode_hashtable[EXFAT_HASH_SIZE]; 84 | #if EXFAT_CONFIG_KERNEL_DEBUG 85 | long debug_flags; 86 | #endif 87 | }; 88 | 89 | struct exfat_inode_info { 90 | FILE_ID_T fid; 91 | char *target; 92 | loff_t mmu_private; 93 | loff_t i_pos; 94 | struct hlist_node i_hash_fat; 95 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) 96 | struct rw_semaphore truncate_lock; 97 | #endif 98 | struct inode vfs_inode; 99 | }; 100 | 101 | #define EXFAT_SB(sb) ((struct exfat_sb_info *)((sb)->s_fs_info)) 102 | 103 | static inline struct exfat_inode_info *EXFAT_I(struct inode *inode) { 104 | return container_of(inode, struct exfat_inode_info, vfs_inode); 105 | } 106 | 107 | static inline int exfat_mode_can_hold_ro(struct inode *inode) 108 | { 109 | struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); 110 | 111 | if (S_ISDIR(inode->i_mode)) 112 | return 0; 113 | 114 | if ((~sbi->options.fs_fmask) & S_IWUGO) 115 | return 1; 116 | return 0; 117 | } 118 | 119 | static inline mode_t exfat_make_mode(struct exfat_sb_info *sbi, 120 | u32 attr, mode_t mode) 121 | { 122 | if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR)) 123 | mode &= ~S_IWUGO; 124 | 125 | if (attr & ATTR_SUBDIR) 126 | return (mode & ~sbi->options.fs_dmask) | S_IFDIR; 127 | else if (attr & ATTR_SYMLINK) 128 | return (mode & ~sbi->options.fs_dmask) | S_IFLNK; 129 | else 130 | return (mode & ~sbi->options.fs_fmask) | S_IFREG; 131 | } 132 | 133 | static inline u32 exfat_make_attr(struct inode *inode) 134 | { 135 | if (exfat_mode_can_hold_ro(inode) && !(inode->i_mode & S_IWUGO)) 136 | return ((EXFAT_I(inode)->fid.attr) | ATTR_READONLY); 137 | else 138 | return (EXFAT_I(inode)->fid.attr); 139 | } 140 | 141 | static inline void exfat_save_attr(struct inode *inode, u32 attr) 142 | { 143 | if (exfat_mode_can_hold_ro(inode)) 144 | EXFAT_I(inode)->fid.attr = attr & ATTR_RWMASK; 145 | else 146 | EXFAT_I(inode)->fid.attr = attr & (ATTR_RWMASK | ATTR_READONLY); 147 | } 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /exfat_upcase.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include "exfat_config.h" 20 | #include "exfat_global.h" 21 | 22 | #include "exfat_nls.h" 23 | 24 | UINT8 uni_upcase[NUM_UPCASE<<1] = { 25 | 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 26 | 0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, 27 | 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, 28 | 0x18, 0x00, 0x19, 0x00, 0x1A, 0x00, 0x1B, 0x00, 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x00, 0x1F, 0x00, 29 | 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 30 | 0x28, 0x00, 0x29, 0x00, 0x2A, 0x00, 0x2B, 0x00, 0x2C, 0x00, 0x2D, 0x00, 0x2E, 0x00, 0x2F, 0x00, 31 | 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 32 | 0x38, 0x00, 0x39, 0x00, 0x3A, 0x00, 0x3B, 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, 33 | 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 34 | 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, 35 | 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, 36 | 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x5B, 0x00, 0x5C, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00, 37 | 0x60, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 38 | 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, 39 | 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, 40 | 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x7B, 0x00, 0x7C, 0x00, 0x7D, 0x00, 0x7E, 0x00, 0x7F, 0x00, 41 | 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, 42 | 0x88, 0x00, 0x89, 0x00, 0x8A, 0x00, 0x8B, 0x00, 0x8C, 0x00, 0x8D, 0x00, 0x8E, 0x00, 0x8F, 0x00, 43 | 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 44 | 0x98, 0x00, 0x99, 0x00, 0x9A, 0x00, 0x9B, 0x00, 0x9C, 0x00, 0x9D, 0x00, 0x9E, 0x00, 0x9F, 0x00, 45 | 0xA0, 0x00, 0xA1, 0x00, 0xA2, 0x00, 0xA3, 0x00, 0xA4, 0x00, 0xA5, 0x00, 0xA6, 0x00, 0xA7, 0x00, 46 | 0xA8, 0x00, 0xA9, 0x00, 0xAA, 0x00, 0xAB, 0x00, 0xAC, 0x00, 0xAD, 0x00, 0xAE, 0x00, 0xAF, 0x00, 47 | 0xB0, 0x00, 0xB1, 0x00, 0xB2, 0x00, 0xB3, 0x00, 0xB4, 0x00, 0xB5, 0x00, 0xB6, 0x00, 0xB7, 0x00, 48 | 0xB8, 0x00, 0xB9, 0x00, 0xBA, 0x00, 0xBB, 0x00, 0xBC, 0x00, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0x00, 49 | 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, 50 | 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, 51 | 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xD7, 0x00, 52 | 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0xDF, 0x00, 53 | 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, 54 | 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, 55 | 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xF7, 0x00, 56 | 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0x78, 0x01, 57 | 0x00, 0x01, 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x04, 0x01, 0x04, 0x01, 0x06, 0x01, 0x06, 0x01, 58 | 0x08, 0x01, 0x08, 0x01, 0x0A, 0x01, 0x0A, 0x01, 0x0C, 0x01, 0x0C, 0x01, 0x0E, 0x01, 0x0E, 0x01, 59 | 0x10, 0x01, 0x10, 0x01, 0x12, 0x01, 0x12, 0x01, 0x14, 0x01, 0x14, 0x01, 0x16, 0x01, 0x16, 0x01, 60 | 0x18, 0x01, 0x18, 0x01, 0x1A, 0x01, 0x1A, 0x01, 0x1C, 0x01, 0x1C, 0x01, 0x1E, 0x01, 0x1E, 0x01, 61 | 0x20, 0x01, 0x20, 0x01, 0x22, 0x01, 0x22, 0x01, 0x24, 0x01, 0x24, 0x01, 0x26, 0x01, 0x26, 0x01, 62 | 0x28, 0x01, 0x28, 0x01, 0x2A, 0x01, 0x2A, 0x01, 0x2C, 0x01, 0x2C, 0x01, 0x2E, 0x01, 0x2E, 0x01, 63 | 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x32, 0x01, 0x34, 0x01, 0x34, 0x01, 0x36, 0x01, 0x36, 0x01, 64 | 0x38, 0x01, 0x39, 0x01, 0x39, 0x01, 0x3B, 0x01, 0x3B, 0x01, 0x3D, 0x01, 0x3D, 0x01, 0x3F, 0x01, 65 | 0x3F, 0x01, 0x41, 0x01, 0x41, 0x01, 0x43, 0x01, 0x43, 0x01, 0x45, 0x01, 0x45, 0x01, 0x47, 0x01, 66 | 0x47, 0x01, 0x49, 0x01, 0x4A, 0x01, 0x4A, 0x01, 0x4C, 0x01, 0x4C, 0x01, 0x4E, 0x01, 0x4E, 0x01, 67 | 0x50, 0x01, 0x50, 0x01, 0x52, 0x01, 0x52, 0x01, 0x54, 0x01, 0x54, 0x01, 0x56, 0x01, 0x56, 0x01, 68 | 0x58, 0x01, 0x58, 0x01, 0x5A, 0x01, 0x5A, 0x01, 0x5C, 0x01, 0x5C, 0x01, 0x5E, 0x01, 0x5E, 0x01, 69 | 0x60, 0x01, 0x60, 0x01, 0x62, 0x01, 0x62, 0x01, 0x64, 0x01, 0x64, 0x01, 0x66, 0x01, 0x66, 0x01, 70 | 0x68, 0x01, 0x68, 0x01, 0x6A, 0x01, 0x6A, 0x01, 0x6C, 0x01, 0x6C, 0x01, 0x6E, 0x01, 0x6E, 0x01, 71 | 0x70, 0x01, 0x70, 0x01, 0x72, 0x01, 0x72, 0x01, 0x74, 0x01, 0x74, 0x01, 0x76, 0x01, 0x76, 0x01, 72 | 0x78, 0x01, 0x79, 0x01, 0x79, 0x01, 0x7B, 0x01, 0x7B, 0x01, 0x7D, 0x01, 0x7D, 0x01, 0x7F, 0x01, 73 | 0x43, 0x02, 0x81, 0x01, 0x82, 0x01, 0x82, 0x01, 0x84, 0x01, 0x84, 0x01, 0x86, 0x01, 0x87, 0x01, 74 | 0x87, 0x01, 0x89, 0x01, 0x8A, 0x01, 0x8B, 0x01, 0x8B, 0x01, 0x8D, 0x01, 0x8E, 0x01, 0x8F, 0x01, 75 | 0x90, 0x01, 0x91, 0x01, 0x91, 0x01, 0x93, 0x01, 0x94, 0x01, 0xF6, 0x01, 0x96, 0x01, 0x97, 0x01, 76 | 0x98, 0x01, 0x98, 0x01, 0x3D, 0x02, 0x9B, 0x01, 0x9C, 0x01, 0x9D, 0x01, 0x20, 0x02, 0x9F, 0x01, 77 | 0xA0, 0x01, 0xA0, 0x01, 0xA2, 0x01, 0xA2, 0x01, 0xA4, 0x01, 0xA4, 0x01, 0xA6, 0x01, 0xA7, 0x01, 78 | 0xA7, 0x01, 0xA9, 0x01, 0xAA, 0x01, 0xAB, 0x01, 0xAC, 0x01, 0xAC, 0x01, 0xAE, 0x01, 0xAF, 0x01, 79 | 0xAF, 0x01, 0xB1, 0x01, 0xB2, 0x01, 0xB3, 0x01, 0xB3, 0x01, 0xB5, 0x01, 0xB5, 0x01, 0xB7, 0x01, 80 | 0xB8, 0x01, 0xB8, 0x01, 0xBA, 0x01, 0xBB, 0x01, 0xBC, 0x01, 0xBC, 0x01, 0xBE, 0x01, 0xF7, 0x01, 81 | 0xC0, 0x01, 0xC1, 0x01, 0xC2, 0x01, 0xC3, 0x01, 0xC4, 0x01, 0xC5, 0x01, 0xC4, 0x01, 0xC7, 0x01, 82 | 0xC8, 0x01, 0xC7, 0x01, 0xCA, 0x01, 0xCB, 0x01, 0xCA, 0x01, 0xCD, 0x01, 0xCD, 0x01, 0xCF, 0x01, 83 | 0xCF, 0x01, 0xD1, 0x01, 0xD1, 0x01, 0xD3, 0x01, 0xD3, 0x01, 0xD5, 0x01, 0xD5, 0x01, 0xD7, 0x01, 84 | 0xD7, 0x01, 0xD9, 0x01, 0xD9, 0x01, 0xDB, 0x01, 0xDB, 0x01, 0x8E, 0x01, 0xDE, 0x01, 0xDE, 0x01, 85 | 0xE0, 0x01, 0xE0, 0x01, 0xE2, 0x01, 0xE2, 0x01, 0xE4, 0x01, 0xE4, 0x01, 0xE6, 0x01, 0xE6, 0x01, 86 | 0xE8, 0x01, 0xE8, 0x01, 0xEA, 0x01, 0xEA, 0x01, 0xEC, 0x01, 0xEC, 0x01, 0xEE, 0x01, 0xEE, 0x01, 87 | 0xF0, 0x01, 0xF1, 0x01, 0xF2, 0x01, 0xF1, 0x01, 0xF4, 0x01, 0xF4, 0x01, 0xF6, 0x01, 0xF7, 0x01, 88 | 0xF8, 0x01, 0xF8, 0x01, 0xFA, 0x01, 0xFA, 0x01, 0xFC, 0x01, 0xFC, 0x01, 0xFE, 0x01, 0xFE, 0x01, 89 | 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x02, 90 | 0x08, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x0A, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0E, 0x02, 0x0E, 0x02, 91 | 0x10, 0x02, 0x10, 0x02, 0x12, 0x02, 0x12, 0x02, 0x14, 0x02, 0x14, 0x02, 0x16, 0x02, 0x16, 0x02, 92 | 0x18, 0x02, 0x18, 0x02, 0x1A, 0x02, 0x1A, 0x02, 0x1C, 0x02, 0x1C, 0x02, 0x1E, 0x02, 0x1E, 0x02, 93 | 0x20, 0x02, 0x21, 0x02, 0x22, 0x02, 0x22, 0x02, 0x24, 0x02, 0x24, 0x02, 0x26, 0x02, 0x26, 0x02, 94 | 0x28, 0x02, 0x28, 0x02, 0x2A, 0x02, 0x2A, 0x02, 0x2C, 0x02, 0x2C, 0x02, 0x2E, 0x02, 0x2E, 0x02, 95 | 0x30, 0x02, 0x30, 0x02, 0x32, 0x02, 0x32, 0x02, 0x34, 0x02, 0x35, 0x02, 0x36, 0x02, 0x37, 0x02, 96 | 0x38, 0x02, 0x39, 0x02, 0x65, 0x2C, 0x3B, 0x02, 0x3B, 0x02, 0x3D, 0x02, 0x66, 0x2C, 0x3F, 0x02, 97 | 0x40, 0x02, 0x41, 0x02, 0x41, 0x02, 0x43, 0x02, 0x44, 0x02, 0x45, 0x02, 0x46, 0x02, 0x46, 0x02, 98 | 0x48, 0x02, 0x48, 0x02, 0x4A, 0x02, 0x4A, 0x02, 0x4C, 0x02, 0x4C, 0x02, 0x4E, 0x02, 0x4E, 0x02, 99 | 0x50, 0x02, 0x51, 0x02, 0x52, 0x02, 0x81, 0x01, 0x86, 0x01, 0x55, 0x02, 0x89, 0x01, 0x8A, 0x01, 100 | 0x58, 0x02, 0x8F, 0x01, 0x5A, 0x02, 0x90, 0x01, 0x5C, 0x02, 0x5D, 0x02, 0x5E, 0x02, 0x5F, 0x02, 101 | 0x93, 0x01, 0x61, 0x02, 0x62, 0x02, 0x94, 0x01, 0x64, 0x02, 0x65, 0x02, 0x66, 0x02, 0x67, 0x02, 102 | 0x97, 0x01, 0x96, 0x01, 0x6A, 0x02, 0x62, 0x2C, 0x6C, 0x02, 0x6D, 0x02, 0x6E, 0x02, 0x9C, 0x01, 103 | 0x70, 0x02, 0x71, 0x02, 0x9D, 0x01, 0x73, 0x02, 0x74, 0x02, 0x9F, 0x01, 0x76, 0x02, 0x77, 0x02, 104 | 0x78, 0x02, 0x79, 0x02, 0x7A, 0x02, 0x7B, 0x02, 0x7C, 0x02, 0x64, 0x2C, 0x7E, 0x02, 0x7F, 0x02, 105 | 0xA6, 0x01, 0x81, 0x02, 0x82, 0x02, 0xA9, 0x01, 0x84, 0x02, 0x85, 0x02, 0x86, 0x02, 0x87, 0x02, 106 | 0xAE, 0x01, 0x44, 0x02, 0xB1, 0x01, 0xB2, 0x01, 0x45, 0x02, 0x8D, 0x02, 0x8E, 0x02, 0x8F, 0x02, 107 | 0x90, 0x02, 0x91, 0x02, 0xB7, 0x01, 0x93, 0x02, 0x94, 0x02, 0x95, 0x02, 0x96, 0x02, 0x97, 0x02, 108 | 0x98, 0x02, 0x99, 0x02, 0x9A, 0x02, 0x9B, 0x02, 0x9C, 0x02, 0x9D, 0x02, 0x9E, 0x02, 0x9F, 0x02, 109 | 0xA0, 0x02, 0xA1, 0x02, 0xA2, 0x02, 0xA3, 0x02, 0xA4, 0x02, 0xA5, 0x02, 0xA6, 0x02, 0xA7, 0x02, 110 | 0xA8, 0x02, 0xA9, 0x02, 0xAA, 0x02, 0xAB, 0x02, 0xAC, 0x02, 0xAD, 0x02, 0xAE, 0x02, 0xAF, 0x02, 111 | 0xB0, 0x02, 0xB1, 0x02, 0xB2, 0x02, 0xB3, 0x02, 0xB4, 0x02, 0xB5, 0x02, 0xB6, 0x02, 0xB7, 0x02, 112 | 0xB8, 0x02, 0xB9, 0x02, 0xBA, 0x02, 0xBB, 0x02, 0xBC, 0x02, 0xBD, 0x02, 0xBE, 0x02, 0xBF, 0x02, 113 | 0xC0, 0x02, 0xC1, 0x02, 0xC2, 0x02, 0xC3, 0x02, 0xC4, 0x02, 0xC5, 0x02, 0xC6, 0x02, 0xC7, 0x02, 114 | 0xC8, 0x02, 0xC9, 0x02, 0xCA, 0x02, 0xCB, 0x02, 0xCC, 0x02, 0xCD, 0x02, 0xCE, 0x02, 0xCF, 0x02, 115 | 0xD0, 0x02, 0xD1, 0x02, 0xD2, 0x02, 0xD3, 0x02, 0xD4, 0x02, 0xD5, 0x02, 0xD6, 0x02, 0xD7, 0x02, 116 | 0xD8, 0x02, 0xD9, 0x02, 0xDA, 0x02, 0xDB, 0x02, 0xDC, 0x02, 0xDD, 0x02, 0xDE, 0x02, 0xDF, 0x02, 117 | 0xE0, 0x02, 0xE1, 0x02, 0xE2, 0x02, 0xE3, 0x02, 0xE4, 0x02, 0xE5, 0x02, 0xE6, 0x02, 0xE7, 0x02, 118 | 0xE8, 0x02, 0xE9, 0x02, 0xEA, 0x02, 0xEB, 0x02, 0xEC, 0x02, 0xED, 0x02, 0xEE, 0x02, 0xEF, 0x02, 119 | 0xF0, 0x02, 0xF1, 0x02, 0xF2, 0x02, 0xF3, 0x02, 0xF4, 0x02, 0xF5, 0x02, 0xF6, 0x02, 0xF7, 0x02, 120 | 0xF8, 0x02, 0xF9, 0x02, 0xFA, 0x02, 0xFB, 0x02, 0xFC, 0x02, 0xFD, 0x02, 0xFE, 0x02, 0xFF, 0x02, 121 | 0x00, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x03, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x07, 0x03, 122 | 0x08, 0x03, 0x09, 0x03, 0x0A, 0x03, 0x0B, 0x03, 0x0C, 0x03, 0x0D, 0x03, 0x0E, 0x03, 0x0F, 0x03, 123 | 0x10, 0x03, 0x11, 0x03, 0x12, 0x03, 0x13, 0x03, 0x14, 0x03, 0x15, 0x03, 0x16, 0x03, 0x17, 0x03, 124 | 0x18, 0x03, 0x19, 0x03, 0x1A, 0x03, 0x1B, 0x03, 0x1C, 0x03, 0x1D, 0x03, 0x1E, 0x03, 0x1F, 0x03, 125 | 0x20, 0x03, 0x21, 0x03, 0x22, 0x03, 0x23, 0x03, 0x24, 0x03, 0x25, 0x03, 0x26, 0x03, 0x27, 0x03, 126 | 0x28, 0x03, 0x29, 0x03, 0x2A, 0x03, 0x2B, 0x03, 0x2C, 0x03, 0x2D, 0x03, 0x2E, 0x03, 0x2F, 0x03, 127 | 0x30, 0x03, 0x31, 0x03, 0x32, 0x03, 0x33, 0x03, 0x34, 0x03, 0x35, 0x03, 0x36, 0x03, 0x37, 0x03, 128 | 0x38, 0x03, 0x39, 0x03, 0x3A, 0x03, 0x3B, 0x03, 0x3C, 0x03, 0x3D, 0x03, 0x3E, 0x03, 0x3F, 0x03, 129 | 0x40, 0x03, 0x41, 0x03, 0x42, 0x03, 0x43, 0x03, 0x44, 0x03, 0x45, 0x03, 0x46, 0x03, 0x47, 0x03, 130 | 0x48, 0x03, 0x49, 0x03, 0x4A, 0x03, 0x4B, 0x03, 0x4C, 0x03, 0x4D, 0x03, 0x4E, 0x03, 0x4F, 0x03, 131 | 0x50, 0x03, 0x51, 0x03, 0x52, 0x03, 0x53, 0x03, 0x54, 0x03, 0x55, 0x03, 0x56, 0x03, 0x57, 0x03, 132 | 0x58, 0x03, 0x59, 0x03, 0x5A, 0x03, 0x5B, 0x03, 0x5C, 0x03, 0x5D, 0x03, 0x5E, 0x03, 0x5F, 0x03, 133 | 0x60, 0x03, 0x61, 0x03, 0x62, 0x03, 0x63, 0x03, 0x64, 0x03, 0x65, 0x03, 0x66, 0x03, 0x67, 0x03, 134 | 0x68, 0x03, 0x69, 0x03, 0x6A, 0x03, 0x6B, 0x03, 0x6C, 0x03, 0x6D, 0x03, 0x6E, 0x03, 0x6F, 0x03, 135 | 0x70, 0x03, 0x71, 0x03, 0x72, 0x03, 0x73, 0x03, 0x74, 0x03, 0x75, 0x03, 0x76, 0x03, 0x77, 0x03, 136 | 0x78, 0x03, 0x79, 0x03, 0x7A, 0x03, 0xFD, 0x03, 0xFE, 0x03, 0xFF, 0x03, 0x7E, 0x03, 0x7F, 0x03, 137 | 0x80, 0x03, 0x81, 0x03, 0x82, 0x03, 0x83, 0x03, 0x84, 0x03, 0x85, 0x03, 0x86, 0x03, 0x87, 0x03, 138 | 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, 0x8B, 0x03, 0x8C, 0x03, 0x8D, 0x03, 0x8E, 0x03, 0x8F, 0x03, 139 | 0x90, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, 140 | 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, 141 | 0xA0, 0x03, 0xA1, 0x03, 0xA2, 0x03, 0xA3, 0x03, 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, 142 | 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, 0x86, 0x03, 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, 143 | 0xB0, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, 144 | 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, 145 | 0xA0, 0x03, 0xA1, 0x03, 0xA3, 0x03, 0xA3, 0x03, 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, 146 | 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, 0x8C, 0x03, 0x8E, 0x03, 0x8F, 0x03, 0xCF, 0x03, 147 | 0xD0, 0x03, 0xD1, 0x03, 0xD2, 0x03, 0xD3, 0x03, 0xD4, 0x03, 0xD5, 0x03, 0xD6, 0x03, 0xD7, 0x03, 148 | 0xD8, 0x03, 0xD8, 0x03, 0xDA, 0x03, 0xDA, 0x03, 0xDC, 0x03, 0xDC, 0x03, 0xDE, 0x03, 0xDE, 0x03, 149 | 0xE0, 0x03, 0xE0, 0x03, 0xE2, 0x03, 0xE2, 0x03, 0xE4, 0x03, 0xE4, 0x03, 0xE6, 0x03, 0xE6, 0x03, 150 | 0xE8, 0x03, 0xE8, 0x03, 0xEA, 0x03, 0xEA, 0x03, 0xEC, 0x03, 0xEC, 0x03, 0xEE, 0x03, 0xEE, 0x03, 151 | 0xF0, 0x03, 0xF1, 0x03, 0xF9, 0x03, 0xF3, 0x03, 0xF4, 0x03, 0xF5, 0x03, 0xF6, 0x03, 0xF7, 0x03, 152 | 0xF7, 0x03, 0xF9, 0x03, 0xFA, 0x03, 0xFA, 0x03, 0xFC, 0x03, 0xFD, 0x03, 0xFE, 0x03, 0xFF, 0x03, 153 | 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, 154 | 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, 155 | 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, 156 | 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, 157 | 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, 158 | 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, 159 | 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, 160 | 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, 161 | 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, 162 | 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, 163 | 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, 164 | 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, 165 | 0x60, 0x04, 0x60, 0x04, 0x62, 0x04, 0x62, 0x04, 0x64, 0x04, 0x64, 0x04, 0x66, 0x04, 0x66, 0x04, 166 | 0x68, 0x04, 0x68, 0x04, 0x6A, 0x04, 0x6A, 0x04, 0x6C, 0x04, 0x6C, 0x04, 0x6E, 0x04, 0x6E, 0x04, 167 | 0x70, 0x04, 0x70, 0x04, 0x72, 0x04, 0x72, 0x04, 0x74, 0x04, 0x74, 0x04, 0x76, 0x04, 0x76, 0x04, 168 | 0x78, 0x04, 0x78, 0x04, 0x7A, 0x04, 0x7A, 0x04, 0x7C, 0x04, 0x7C, 0x04, 0x7E, 0x04, 0x7E, 0x04, 169 | 0x80, 0x04, 0x80, 0x04, 0x82, 0x04, 0x83, 0x04, 0x84, 0x04, 0x85, 0x04, 0x86, 0x04, 0x87, 0x04, 170 | 0x88, 0x04, 0x89, 0x04, 0x8A, 0x04, 0x8A, 0x04, 0x8C, 0x04, 0x8C, 0x04, 0x8E, 0x04, 0x8E, 0x04, 171 | 0x90, 0x04, 0x90, 0x04, 0x92, 0x04, 0x92, 0x04, 0x94, 0x04, 0x94, 0x04, 0x96, 0x04, 0x96, 0x04, 172 | 0x98, 0x04, 0x98, 0x04, 0x9A, 0x04, 0x9A, 0x04, 0x9C, 0x04, 0x9C, 0x04, 0x9E, 0x04, 0x9E, 0x04, 173 | 0xA0, 0x04, 0xA0, 0x04, 0xA2, 0x04, 0xA2, 0x04, 0xA4, 0x04, 0xA4, 0x04, 0xA6, 0x04, 0xA6, 0x04, 174 | 0xA8, 0x04, 0xA8, 0x04, 0xAA, 0x04, 0xAA, 0x04, 0xAC, 0x04, 0xAC, 0x04, 0xAE, 0x04, 0xAE, 0x04, 175 | 0xB0, 0x04, 0xB0, 0x04, 0xB2, 0x04, 0xB2, 0x04, 0xB4, 0x04, 0xB4, 0x04, 0xB6, 0x04, 0xB6, 0x04, 176 | 0xB8, 0x04, 0xB8, 0x04, 0xBA, 0x04, 0xBA, 0x04, 0xBC, 0x04, 0xBC, 0x04, 0xBE, 0x04, 0xBE, 0x04, 177 | 0xC0, 0x04, 0xC1, 0x04, 0xC1, 0x04, 0xC3, 0x04, 0xC3, 0x04, 0xC5, 0x04, 0xC5, 0x04, 0xC7, 0x04, 178 | 0xC7, 0x04, 0xC9, 0x04, 0xC9, 0x04, 0xCB, 0x04, 0xCB, 0x04, 0xCD, 0x04, 0xCD, 0x04, 0xC0, 0x04, 179 | 0xD0, 0x04, 0xD0, 0x04, 0xD2, 0x04, 0xD2, 0x04, 0xD4, 0x04, 0xD4, 0x04, 0xD6, 0x04, 0xD6, 0x04, 180 | 0xD8, 0x04, 0xD8, 0x04, 0xDA, 0x04, 0xDA, 0x04, 0xDC, 0x04, 0xDC, 0x04, 0xDE, 0x04, 0xDE, 0x04, 181 | 0xE0, 0x04, 0xE0, 0x04, 0xE2, 0x04, 0xE2, 0x04, 0xE4, 0x04, 0xE4, 0x04, 0xE6, 0x04, 0xE6, 0x04, 182 | 0xE8, 0x04, 0xE8, 0x04, 0xEA, 0x04, 0xEA, 0x04, 0xEC, 0x04, 0xEC, 0x04, 0xEE, 0x04, 0xEE, 0x04, 183 | 0xF0, 0x04, 0xF0, 0x04, 0xF2, 0x04, 0xF2, 0x04, 0xF4, 0x04, 0xF4, 0x04, 0xF6, 0x04, 0xF6, 0x04, 184 | 0xF8, 0x04, 0xF8, 0x04, 0xFA, 0x04, 0xFA, 0x04, 0xFC, 0x04, 0xFC, 0x04, 0xFE, 0x04, 0xFE, 0x04, 185 | 0x00, 0x05, 0x00, 0x05, 0x02, 0x05, 0x02, 0x05, 0x04, 0x05, 0x04, 0x05, 0x06, 0x05, 0x06, 0x05, 186 | 0x08, 0x05, 0x08, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0C, 0x05, 0x0C, 0x05, 0x0E, 0x05, 0x0E, 0x05, 187 | 0x10, 0x05, 0x10, 0x05, 0x12, 0x05, 0x12, 0x05, 0x14, 0x05, 0x15, 0x05, 0x16, 0x05, 0x17, 0x05, 188 | 0x18, 0x05, 0x19, 0x05, 0x1A, 0x05, 0x1B, 0x05, 0x1C, 0x05, 0x1D, 0x05, 0x1E, 0x05, 0x1F, 0x05, 189 | 0x20, 0x05, 0x21, 0x05, 0x22, 0x05, 0x23, 0x05, 0x24, 0x05, 0x25, 0x05, 0x26, 0x05, 0x27, 0x05, 190 | 0x28, 0x05, 0x29, 0x05, 0x2A, 0x05, 0x2B, 0x05, 0x2C, 0x05, 0x2D, 0x05, 0x2E, 0x05, 0x2F, 0x05, 191 | 0x30, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, 192 | 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, 193 | 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, 194 | 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, 195 | 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0x57, 0x05, 196 | 0x58, 0x05, 0x59, 0x05, 0x5A, 0x05, 0x5B, 0x05, 0x5C, 0x05, 0x5D, 0x05, 0x5E, 0x05, 0x5F, 0x05, 197 | 0x60, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, 198 | 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, 199 | 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, 200 | 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, 201 | 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0xFF, 0xFF, 202 | 0xF6, 0x17, 0x63, 0x2C, 0x7E, 0x1D, 0x7F, 0x1D, 0x80, 0x1D, 0x81, 0x1D, 0x82, 0x1D, 0x83, 0x1D, 203 | 0x84, 0x1D, 0x85, 0x1D, 0x86, 0x1D, 0x87, 0x1D, 0x88, 0x1D, 0x89, 0x1D, 0x8A, 0x1D, 0x8B, 0x1D, 204 | 0x8C, 0x1D, 0x8D, 0x1D, 0x8E, 0x1D, 0x8F, 0x1D, 0x90, 0x1D, 0x91, 0x1D, 0x92, 0x1D, 0x93, 0x1D, 205 | 0x94, 0x1D, 0x95, 0x1D, 0x96, 0x1D, 0x97, 0x1D, 0x98, 0x1D, 0x99, 0x1D, 0x9A, 0x1D, 0x9B, 0x1D, 206 | 0x9C, 0x1D, 0x9D, 0x1D, 0x9E, 0x1D, 0x9F, 0x1D, 0xA0, 0x1D, 0xA1, 0x1D, 0xA2, 0x1D, 0xA3, 0x1D, 207 | 0xA4, 0x1D, 0xA5, 0x1D, 0xA6, 0x1D, 0xA7, 0x1D, 0xA8, 0x1D, 0xA9, 0x1D, 0xAA, 0x1D, 0xAB, 0x1D, 208 | 0xAC, 0x1D, 0xAD, 0x1D, 0xAE, 0x1D, 0xAF, 0x1D, 0xB0, 0x1D, 0xB1, 0x1D, 0xB2, 0x1D, 0xB3, 0x1D, 209 | 0xB4, 0x1D, 0xB5, 0x1D, 0xB6, 0x1D, 0xB7, 0x1D, 0xB8, 0x1D, 0xB9, 0x1D, 0xBA, 0x1D, 0xBB, 0x1D, 210 | 0xBC, 0x1D, 0xBD, 0x1D, 0xBE, 0x1D, 0xBF, 0x1D, 0xC0, 0x1D, 0xC1, 0x1D, 0xC2, 0x1D, 0xC3, 0x1D, 211 | 0xC4, 0x1D, 0xC5, 0x1D, 0xC6, 0x1D, 0xC7, 0x1D, 0xC8, 0x1D, 0xC9, 0x1D, 0xCA, 0x1D, 0xCB, 0x1D, 212 | 0xCC, 0x1D, 0xCD, 0x1D, 0xCE, 0x1D, 0xCF, 0x1D, 0xD0, 0x1D, 0xD1, 0x1D, 0xD2, 0x1D, 0xD3, 0x1D, 213 | 0xD4, 0x1D, 0xD5, 0x1D, 0xD6, 0x1D, 0xD7, 0x1D, 0xD8, 0x1D, 0xD9, 0x1D, 0xDA, 0x1D, 0xDB, 0x1D, 214 | 0xDC, 0x1D, 0xDD, 0x1D, 0xDE, 0x1D, 0xDF, 0x1D, 0xE0, 0x1D, 0xE1, 0x1D, 0xE2, 0x1D, 0xE3, 0x1D, 215 | 0xE4, 0x1D, 0xE5, 0x1D, 0xE6, 0x1D, 0xE7, 0x1D, 0xE8, 0x1D, 0xE9, 0x1D, 0xEA, 0x1D, 0xEB, 0x1D, 216 | 0xEC, 0x1D, 0xED, 0x1D, 0xEE, 0x1D, 0xEF, 0x1D, 0xF0, 0x1D, 0xF1, 0x1D, 0xF2, 0x1D, 0xF3, 0x1D, 217 | 0xF4, 0x1D, 0xF5, 0x1D, 0xF6, 0x1D, 0xF7, 0x1D, 0xF8, 0x1D, 0xF9, 0x1D, 0xFA, 0x1D, 0xFB, 0x1D, 218 | 0xFC, 0x1D, 0xFD, 0x1D, 0xFE, 0x1D, 0xFF, 0x1D, 0x00, 0x1E, 0x00, 0x1E, 0x02, 0x1E, 0x02, 0x1E, 219 | 0x04, 0x1E, 0x04, 0x1E, 0x06, 0x1E, 0x06, 0x1E, 0x08, 0x1E, 0x08, 0x1E, 0x0A, 0x1E, 0x0A, 0x1E, 220 | 0x0C, 0x1E, 0x0C, 0x1E, 0x0E, 0x1E, 0x0E, 0x1E, 0x10, 0x1E, 0x10, 0x1E, 0x12, 0x1E, 0x12, 0x1E, 221 | 0x14, 0x1E, 0x14, 0x1E, 0x16, 0x1E, 0x16, 0x1E, 0x18, 0x1E, 0x18, 0x1E, 0x1A, 0x1E, 0x1A, 0x1E, 222 | 0x1C, 0x1E, 0x1C, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x20, 0x1E, 0x20, 0x1E, 0x22, 0x1E, 0x22, 0x1E, 223 | 0x24, 0x1E, 0x24, 0x1E, 0x26, 0x1E, 0x26, 0x1E, 0x28, 0x1E, 0x28, 0x1E, 0x2A, 0x1E, 0x2A, 0x1E, 224 | 0x2C, 0x1E, 0x2C, 0x1E, 0x2E, 0x1E, 0x2E, 0x1E, 0x30, 0x1E, 0x30, 0x1E, 0x32, 0x1E, 0x32, 0x1E, 225 | 0x34, 0x1E, 0x34, 0x1E, 0x36, 0x1E, 0x36, 0x1E, 0x38, 0x1E, 0x38, 0x1E, 0x3A, 0x1E, 0x3A, 0x1E, 226 | 0x3C, 0x1E, 0x3C, 0x1E, 0x3E, 0x1E, 0x3E, 0x1E, 0x40, 0x1E, 0x40, 0x1E, 0x42, 0x1E, 0x42, 0x1E, 227 | 0x44, 0x1E, 0x44, 0x1E, 0x46, 0x1E, 0x46, 0x1E, 0x48, 0x1E, 0x48, 0x1E, 0x4A, 0x1E, 0x4A, 0x1E, 228 | 0x4C, 0x1E, 0x4C, 0x1E, 0x4E, 0x1E, 0x4E, 0x1E, 0x50, 0x1E, 0x50, 0x1E, 0x52, 0x1E, 0x52, 0x1E, 229 | 0x54, 0x1E, 0x54, 0x1E, 0x56, 0x1E, 0x56, 0x1E, 0x58, 0x1E, 0x58, 0x1E, 0x5A, 0x1E, 0x5A, 0x1E, 230 | 0x5C, 0x1E, 0x5C, 0x1E, 0x5E, 0x1E, 0x5E, 0x1E, 0x60, 0x1E, 0x60, 0x1E, 0x62, 0x1E, 0x62, 0x1E, 231 | 0x64, 0x1E, 0x64, 0x1E, 0x66, 0x1E, 0x66, 0x1E, 0x68, 0x1E, 0x68, 0x1E, 0x6A, 0x1E, 0x6A, 0x1E, 232 | 0x6C, 0x1E, 0x6C, 0x1E, 0x6E, 0x1E, 0x6E, 0x1E, 0x70, 0x1E, 0x70, 0x1E, 0x72, 0x1E, 0x72, 0x1E, 233 | 0x74, 0x1E, 0x74, 0x1E, 0x76, 0x1E, 0x76, 0x1E, 0x78, 0x1E, 0x78, 0x1E, 0x7A, 0x1E, 0x7A, 0x1E, 234 | 0x7C, 0x1E, 0x7C, 0x1E, 0x7E, 0x1E, 0x7E, 0x1E, 0x80, 0x1E, 0x80, 0x1E, 0x82, 0x1E, 0x82, 0x1E, 235 | 0x84, 0x1E, 0x84, 0x1E, 0x86, 0x1E, 0x86, 0x1E, 0x88, 0x1E, 0x88, 0x1E, 0x8A, 0x1E, 0x8A, 0x1E, 236 | 0x8C, 0x1E, 0x8C, 0x1E, 0x8E, 0x1E, 0x8E, 0x1E, 0x90, 0x1E, 0x90, 0x1E, 0x92, 0x1E, 0x92, 0x1E, 237 | 0x94, 0x1E, 0x94, 0x1E, 0x96, 0x1E, 0x97, 0x1E, 0x98, 0x1E, 0x99, 0x1E, 0x9A, 0x1E, 0x9B, 0x1E, 238 | 0x9C, 0x1E, 0x9D, 0x1E, 0x9E, 0x1E, 0x9F, 0x1E, 0xA0, 0x1E, 0xA0, 0x1E, 0xA2, 0x1E, 0xA2, 0x1E, 239 | 0xA4, 0x1E, 0xA4, 0x1E, 0xA6, 0x1E, 0xA6, 0x1E, 0xA8, 0x1E, 0xA8, 0x1E, 0xAA, 0x1E, 0xAA, 0x1E, 240 | 0xAC, 0x1E, 0xAC, 0x1E, 0xAE, 0x1E, 0xAE, 0x1E, 0xB0, 0x1E, 0xB0, 0x1E, 0xB2, 0x1E, 0xB2, 0x1E, 241 | 0xB4, 0x1E, 0xB4, 0x1E, 0xB6, 0x1E, 0xB6, 0x1E, 0xB8, 0x1E, 0xB8, 0x1E, 0xBA, 0x1E, 0xBA, 0x1E, 242 | 0xBC, 0x1E, 0xBC, 0x1E, 0xBE, 0x1E, 0xBE, 0x1E, 0xC0, 0x1E, 0xC0, 0x1E, 0xC2, 0x1E, 0xC2, 0x1E, 243 | 0xC4, 0x1E, 0xC4, 0x1E, 0xC6, 0x1E, 0xC6, 0x1E, 0xC8, 0x1E, 0xC8, 0x1E, 0xCA, 0x1E, 0xCA, 0x1E, 244 | 0xCC, 0x1E, 0xCC, 0x1E, 0xCE, 0x1E, 0xCE, 0x1E, 0xD0, 0x1E, 0xD0, 0x1E, 0xD2, 0x1E, 0xD2, 0x1E, 245 | 0xD4, 0x1E, 0xD4, 0x1E, 0xD6, 0x1E, 0xD6, 0x1E, 0xD8, 0x1E, 0xD8, 0x1E, 0xDA, 0x1E, 0xDA, 0x1E, 246 | 0xDC, 0x1E, 0xDC, 0x1E, 0xDE, 0x1E, 0xDE, 0x1E, 0xE0, 0x1E, 0xE0, 0x1E, 0xE2, 0x1E, 0xE2, 0x1E, 247 | 0xE4, 0x1E, 0xE4, 0x1E, 0xE6, 0x1E, 0xE6, 0x1E, 0xE8, 0x1E, 0xE8, 0x1E, 0xEA, 0x1E, 0xEA, 0x1E, 248 | 0xEC, 0x1E, 0xEC, 0x1E, 0xEE, 0x1E, 0xEE, 0x1E, 0xF0, 0x1E, 0xF0, 0x1E, 0xF2, 0x1E, 0xF2, 0x1E, 249 | 0xF4, 0x1E, 0xF4, 0x1E, 0xF6, 0x1E, 0xF6, 0x1E, 0xF8, 0x1E, 0xF8, 0x1E, 0xFA, 0x1E, 0xFB, 0x1E, 250 | 0xFC, 0x1E, 0xFD, 0x1E, 0xFE, 0x1E, 0xFF, 0x1E, 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, 251 | 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, 252 | 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, 253 | 0x1C, 0x1F, 0x1D, 0x1F, 0x16, 0x1F, 0x17, 0x1F, 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, 254 | 0x1C, 0x1F, 0x1D, 0x1F, 0x1E, 0x1F, 0x1F, 0x1F, 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, 255 | 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, 256 | 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, 257 | 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, 258 | 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, 259 | 0x4C, 0x1F, 0x4D, 0x1F, 0x46, 0x1F, 0x47, 0x1F, 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, 260 | 0x4C, 0x1F, 0x4D, 0x1F, 0x4E, 0x1F, 0x4F, 0x1F, 0x50, 0x1F, 0x59, 0x1F, 0x52, 0x1F, 0x5B, 0x1F, 261 | 0x54, 0x1F, 0x5D, 0x1F, 0x56, 0x1F, 0x5F, 0x1F, 0x58, 0x1F, 0x59, 0x1F, 0x5A, 0x1F, 0x5B, 0x1F, 262 | 0x5C, 0x1F, 0x5D, 0x1F, 0x5E, 0x1F, 0x5F, 0x1F, 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, 263 | 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, 264 | 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, 0xBA, 0x1F, 0xBB, 0x1F, 0xC8, 0x1F, 0xC9, 0x1F, 265 | 0xCA, 0x1F, 0xCB, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, 0xF8, 0x1F, 0xF9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, 266 | 0xFA, 0x1F, 0xFB, 0x1F, 0x7E, 0x1F, 0x7F, 0x1F, 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, 267 | 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, 268 | 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, 269 | 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, 270 | 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, 271 | 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, 272 | 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, 0xB8, 0x1F, 0xB9, 0x1F, 0xB2, 0x1F, 0xBC, 0x1F, 273 | 0xB4, 0x1F, 0xB5, 0x1F, 0xB6, 0x1F, 0xB7, 0x1F, 0xB8, 0x1F, 0xB9, 0x1F, 0xBA, 0x1F, 0xBB, 0x1F, 274 | 0xBC, 0x1F, 0xBD, 0x1F, 0xBE, 0x1F, 0xBF, 0x1F, 0xC0, 0x1F, 0xC1, 0x1F, 0xC2, 0x1F, 0xC3, 0x1F, 275 | 0xC4, 0x1F, 0xC5, 0x1F, 0xC6, 0x1F, 0xC7, 0x1F, 0xC8, 0x1F, 0xC9, 0x1F, 0xCA, 0x1F, 0xCB, 0x1F, 276 | 0xC3, 0x1F, 0xCD, 0x1F, 0xCE, 0x1F, 0xCF, 0x1F, 0xD8, 0x1F, 0xD9, 0x1F, 0xD2, 0x1F, 0xD3, 0x1F, 277 | 0xD4, 0x1F, 0xD5, 0x1F, 0xD6, 0x1F, 0xD7, 0x1F, 0xD8, 0x1F, 0xD9, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, 278 | 0xDC, 0x1F, 0xDD, 0x1F, 0xDE, 0x1F, 0xDF, 0x1F, 0xE8, 0x1F, 0xE9, 0x1F, 0xE2, 0x1F, 0xE3, 0x1F, 279 | 0xE4, 0x1F, 0xEC, 0x1F, 0xE6, 0x1F, 0xE7, 0x1F, 0xE8, 0x1F, 0xE9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, 280 | 0xEC, 0x1F, 0xED, 0x1F, 0xEE, 0x1F, 0xEF, 0x1F, 0xF0, 0x1F, 0xF1, 0x1F, 0xF2, 0x1F, 0xF3, 0x1F, 281 | 0xF4, 0x1F, 0xF5, 0x1F, 0xF6, 0x1F, 0xF7, 0x1F, 0xF8, 0x1F, 0xF9, 0x1F, 0xFA, 0x1F, 0xFB, 0x1F, 282 | 0xF3, 0x1F, 0xFD, 0x1F, 0xFE, 0x1F, 0xFF, 0x1F, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x20, 283 | 0x04, 0x20, 0x05, 0x20, 0x06, 0x20, 0x07, 0x20, 0x08, 0x20, 0x09, 0x20, 0x0A, 0x20, 0x0B, 0x20, 284 | 0x0C, 0x20, 0x0D, 0x20, 0x0E, 0x20, 0x0F, 0x20, 0x10, 0x20, 0x11, 0x20, 0x12, 0x20, 0x13, 0x20, 285 | 0x14, 0x20, 0x15, 0x20, 0x16, 0x20, 0x17, 0x20, 0x18, 0x20, 0x19, 0x20, 0x1A, 0x20, 0x1B, 0x20, 286 | 0x1C, 0x20, 0x1D, 0x20, 0x1E, 0x20, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x20, 0x22, 0x20, 0x23, 0x20, 287 | 0x24, 0x20, 0x25, 0x20, 0x26, 0x20, 0x27, 0x20, 0x28, 0x20, 0x29, 0x20, 0x2A, 0x20, 0x2B, 0x20, 288 | 0x2C, 0x20, 0x2D, 0x20, 0x2E, 0x20, 0x2F, 0x20, 0x30, 0x20, 0x31, 0x20, 0x32, 0x20, 0x33, 0x20, 289 | 0x34, 0x20, 0x35, 0x20, 0x36, 0x20, 0x37, 0x20, 0x38, 0x20, 0x39, 0x20, 0x3A, 0x20, 0x3B, 0x20, 290 | 0x3C, 0x20, 0x3D, 0x20, 0x3E, 0x20, 0x3F, 0x20, 0x40, 0x20, 0x41, 0x20, 0x42, 0x20, 0x43, 0x20, 291 | 0x44, 0x20, 0x45, 0x20, 0x46, 0x20, 0x47, 0x20, 0x48, 0x20, 0x49, 0x20, 0x4A, 0x20, 0x4B, 0x20, 292 | 0x4C, 0x20, 0x4D, 0x20, 0x4E, 0x20, 0x4F, 0x20, 0x50, 0x20, 0x51, 0x20, 0x52, 0x20, 0x53, 0x20, 293 | 0x54, 0x20, 0x55, 0x20, 0x56, 0x20, 0x57, 0x20, 0x58, 0x20, 0x59, 0x20, 0x5A, 0x20, 0x5B, 0x20, 294 | 0x5C, 0x20, 0x5D, 0x20, 0x5E, 0x20, 0x5F, 0x20, 0x60, 0x20, 0x61, 0x20, 0x62, 0x20, 0x63, 0x20, 295 | 0x64, 0x20, 0x65, 0x20, 0x66, 0x20, 0x67, 0x20, 0x68, 0x20, 0x69, 0x20, 0x6A, 0x20, 0x6B, 0x20, 296 | 0x6C, 0x20, 0x6D, 0x20, 0x6E, 0x20, 0x6F, 0x20, 0x70, 0x20, 0x71, 0x20, 0x72, 0x20, 0x73, 0x20, 297 | 0x74, 0x20, 0x75, 0x20, 0x76, 0x20, 0x77, 0x20, 0x78, 0x20, 0x79, 0x20, 0x7A, 0x20, 0x7B, 0x20, 298 | 0x7C, 0x20, 0x7D, 0x20, 0x7E, 0x20, 0x7F, 0x20, 0x80, 0x20, 0x81, 0x20, 0x82, 0x20, 0x83, 0x20, 299 | 0x84, 0x20, 0x85, 0x20, 0x86, 0x20, 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x8A, 0x20, 0x8B, 0x20, 300 | 0x8C, 0x20, 0x8D, 0x20, 0x8E, 0x20, 0x8F, 0x20, 0x90, 0x20, 0x91, 0x20, 0x92, 0x20, 0x93, 0x20, 301 | 0x94, 0x20, 0x95, 0x20, 0x96, 0x20, 0x97, 0x20, 0x98, 0x20, 0x99, 0x20, 0x9A, 0x20, 0x9B, 0x20, 302 | 0x9C, 0x20, 0x9D, 0x20, 0x9E, 0x20, 0x9F, 0x20, 0xA0, 0x20, 0xA1, 0x20, 0xA2, 0x20, 0xA3, 0x20, 303 | 0xA4, 0x20, 0xA5, 0x20, 0xA6, 0x20, 0xA7, 0x20, 0xA8, 0x20, 0xA9, 0x20, 0xAA, 0x20, 0xAB, 0x20, 304 | 0xAC, 0x20, 0xAD, 0x20, 0xAE, 0x20, 0xAF, 0x20, 0xB0, 0x20, 0xB1, 0x20, 0xB2, 0x20, 0xB3, 0x20, 305 | 0xB4, 0x20, 0xB5, 0x20, 0xB6, 0x20, 0xB7, 0x20, 0xB8, 0x20, 0xB9, 0x20, 0xBA, 0x20, 0xBB, 0x20, 306 | 0xBC, 0x20, 0xBD, 0x20, 0xBE, 0x20, 0xBF, 0x20, 0xC0, 0x20, 0xC1, 0x20, 0xC2, 0x20, 0xC3, 0x20, 307 | 0xC4, 0x20, 0xC5, 0x20, 0xC6, 0x20, 0xC7, 0x20, 0xC8, 0x20, 0xC9, 0x20, 0xCA, 0x20, 0xCB, 0x20, 308 | 0xCC, 0x20, 0xCD, 0x20, 0xCE, 0x20, 0xCF, 0x20, 0xD0, 0x20, 0xD1, 0x20, 0xD2, 0x20, 0xD3, 0x20, 309 | 0xD4, 0x20, 0xD5, 0x20, 0xD6, 0x20, 0xD7, 0x20, 0xD8, 0x20, 0xD9, 0x20, 0xDA, 0x20, 0xDB, 0x20, 310 | 0xDC, 0x20, 0xDD, 0x20, 0xDE, 0x20, 0xDF, 0x20, 0xE0, 0x20, 0xE1, 0x20, 0xE2, 0x20, 0xE3, 0x20, 311 | 0xE4, 0x20, 0xE5, 0x20, 0xE6, 0x20, 0xE7, 0x20, 0xE8, 0x20, 0xE9, 0x20, 0xEA, 0x20, 0xEB, 0x20, 312 | 0xEC, 0x20, 0xED, 0x20, 0xEE, 0x20, 0xEF, 0x20, 0xF0, 0x20, 0xF1, 0x20, 0xF2, 0x20, 0xF3, 0x20, 313 | 0xF4, 0x20, 0xF5, 0x20, 0xF6, 0x20, 0xF7, 0x20, 0xF8, 0x20, 0xF9, 0x20, 0xFA, 0x20, 0xFB, 0x20, 314 | 0xFC, 0x20, 0xFD, 0x20, 0xFE, 0x20, 0xFF, 0x20, 0x00, 0x21, 0x01, 0x21, 0x02, 0x21, 0x03, 0x21, 315 | 0x04, 0x21, 0x05, 0x21, 0x06, 0x21, 0x07, 0x21, 0x08, 0x21, 0x09, 0x21, 0x0A, 0x21, 0x0B, 0x21, 316 | 0x0C, 0x21, 0x0D, 0x21, 0x0E, 0x21, 0x0F, 0x21, 0x10, 0x21, 0x11, 0x21, 0x12, 0x21, 0x13, 0x21, 317 | 0x14, 0x21, 0x15, 0x21, 0x16, 0x21, 0x17, 0x21, 0x18, 0x21, 0x19, 0x21, 0x1A, 0x21, 0x1B, 0x21, 318 | 0x1C, 0x21, 0x1D, 0x21, 0x1E, 0x21, 0x1F, 0x21, 0x20, 0x21, 0x21, 0x21, 0x22, 0x21, 0x23, 0x21, 319 | 0x24, 0x21, 0x25, 0x21, 0x26, 0x21, 0x27, 0x21, 0x28, 0x21, 0x29, 0x21, 0x2A, 0x21, 0x2B, 0x21, 320 | 0x2C, 0x21, 0x2D, 0x21, 0x2E, 0x21, 0x2F, 0x21, 0x30, 0x21, 0x31, 0x21, 0x32, 0x21, 0x33, 0x21, 321 | 0x34, 0x21, 0x35, 0x21, 0x36, 0x21, 0x37, 0x21, 0x38, 0x21, 0x39, 0x21, 0x3A, 0x21, 0x3B, 0x21, 322 | 0x3C, 0x21, 0x3D, 0x21, 0x3E, 0x21, 0x3F, 0x21, 0x40, 0x21, 0x41, 0x21, 0x42, 0x21, 0x43, 0x21, 323 | 0x44, 0x21, 0x45, 0x21, 0x46, 0x21, 0x47, 0x21, 0x48, 0x21, 0x49, 0x21, 0x4A, 0x21, 0x4B, 0x21, 324 | 0x4C, 0x21, 0x4D, 0x21, 0x32, 0x21, 0x4F, 0x21, 0x50, 0x21, 0x51, 0x21, 0x52, 0x21, 0x53, 0x21, 325 | 0x54, 0x21, 0x55, 0x21, 0x56, 0x21, 0x57, 0x21, 0x58, 0x21, 0x59, 0x21, 0x5A, 0x21, 0x5B, 0x21, 326 | 0x5C, 0x21, 0x5D, 0x21, 0x5E, 0x21, 0x5F, 0x21, 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, 327 | 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, 328 | 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, 329 | 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, 330 | 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, 0x80, 0x21, 0x81, 0x21, 0x82, 0x21, 0x83, 0x21, 331 | 0x83, 0x21, 0xFF, 0xFF, 0x4B, 0x03, 0xB6, 0x24, 0xB7, 0x24, 0xB8, 0x24, 0xB9, 0x24, 0xBA, 0x24, 332 | 0xBB, 0x24, 0xBC, 0x24, 0xBD, 0x24, 0xBE, 0x24, 0xBF, 0x24, 0xC0, 0x24, 0xC1, 0x24, 0xC2, 0x24, 333 | 0xC3, 0x24, 0xC4, 0x24, 0xC5, 0x24, 0xC6, 0x24, 0xC7, 0x24, 0xC8, 0x24, 0xC9, 0x24, 0xCA, 0x24, 334 | 0xCB, 0x24, 0xCC, 0x24, 0xCD, 0x24, 0xCE, 0x24, 0xCF, 0x24, 0xFF, 0xFF, 0x46, 0x07, 0x00, 0x2C, 335 | 0x01, 0x2C, 0x02, 0x2C, 0x03, 0x2C, 0x04, 0x2C, 0x05, 0x2C, 0x06, 0x2C, 0x07, 0x2C, 0x08, 0x2C, 336 | 0x09, 0x2C, 0x0A, 0x2C, 0x0B, 0x2C, 0x0C, 0x2C, 0x0D, 0x2C, 0x0E, 0x2C, 0x0F, 0x2C, 0x10, 0x2C, 337 | 0x11, 0x2C, 0x12, 0x2C, 0x13, 0x2C, 0x14, 0x2C, 0x15, 0x2C, 0x16, 0x2C, 0x17, 0x2C, 0x18, 0x2C, 338 | 0x19, 0x2C, 0x1A, 0x2C, 0x1B, 0x2C, 0x1C, 0x2C, 0x1D, 0x2C, 0x1E, 0x2C, 0x1F, 0x2C, 0x20, 0x2C, 339 | 0x21, 0x2C, 0x22, 0x2C, 0x23, 0x2C, 0x24, 0x2C, 0x25, 0x2C, 0x26, 0x2C, 0x27, 0x2C, 0x28, 0x2C, 340 | 0x29, 0x2C, 0x2A, 0x2C, 0x2B, 0x2C, 0x2C, 0x2C, 0x2D, 0x2C, 0x2E, 0x2C, 0x5F, 0x2C, 0x60, 0x2C, 341 | 0x60, 0x2C, 0x62, 0x2C, 0x63, 0x2C, 0x64, 0x2C, 0x65, 0x2C, 0x66, 0x2C, 0x67, 0x2C, 0x67, 0x2C, 342 | 0x69, 0x2C, 0x69, 0x2C, 0x6B, 0x2C, 0x6B, 0x2C, 0x6D, 0x2C, 0x6E, 0x2C, 0x6F, 0x2C, 0x70, 0x2C, 343 | 0x71, 0x2C, 0x72, 0x2C, 0x73, 0x2C, 0x74, 0x2C, 0x75, 0x2C, 0x75, 0x2C, 0x77, 0x2C, 0x78, 0x2C, 344 | 0x79, 0x2C, 0x7A, 0x2C, 0x7B, 0x2C, 0x7C, 0x2C, 0x7D, 0x2C, 0x7E, 0x2C, 0x7F, 0x2C, 0x80, 0x2C, 345 | 0x80, 0x2C, 0x82, 0x2C, 0x82, 0x2C, 0x84, 0x2C, 0x84, 0x2C, 0x86, 0x2C, 0x86, 0x2C, 0x88, 0x2C, 346 | 0x88, 0x2C, 0x8A, 0x2C, 0x8A, 0x2C, 0x8C, 0x2C, 0x8C, 0x2C, 0x8E, 0x2C, 0x8E, 0x2C, 0x90, 0x2C, 347 | 0x90, 0x2C, 0x92, 0x2C, 0x92, 0x2C, 0x94, 0x2C, 0x94, 0x2C, 0x96, 0x2C, 0x96, 0x2C, 0x98, 0x2C, 348 | 0x98, 0x2C, 0x9A, 0x2C, 0x9A, 0x2C, 0x9C, 0x2C, 0x9C, 0x2C, 0x9E, 0x2C, 0x9E, 0x2C, 0xA0, 0x2C, 349 | 0xA0, 0x2C, 0xA2, 0x2C, 0xA2, 0x2C, 0xA4, 0x2C, 0xA4, 0x2C, 0xA6, 0x2C, 0xA6, 0x2C, 0xA8, 0x2C, 350 | 0xA8, 0x2C, 0xAA, 0x2C, 0xAA, 0x2C, 0xAC, 0x2C, 0xAC, 0x2C, 0xAE, 0x2C, 0xAE, 0x2C, 0xB0, 0x2C, 351 | 0xB0, 0x2C, 0xB2, 0x2C, 0xB2, 0x2C, 0xB4, 0x2C, 0xB4, 0x2C, 0xB6, 0x2C, 0xB6, 0x2C, 0xB8, 0x2C, 352 | 0xB8, 0x2C, 0xBA, 0x2C, 0xBA, 0x2C, 0xBC, 0x2C, 0xBC, 0x2C, 0xBE, 0x2C, 0xBE, 0x2C, 0xC0, 0x2C, 353 | 0xC0, 0x2C, 0xC2, 0x2C, 0xC2, 0x2C, 0xC4, 0x2C, 0xC4, 0x2C, 0xC6, 0x2C, 0xC6, 0x2C, 0xC8, 0x2C, 354 | 0xC8, 0x2C, 0xCA, 0x2C, 0xCA, 0x2C, 0xCC, 0x2C, 0xCC, 0x2C, 0xCE, 0x2C, 0xCE, 0x2C, 0xD0, 0x2C, 355 | 0xD0, 0x2C, 0xD2, 0x2C, 0xD2, 0x2C, 0xD4, 0x2C, 0xD4, 0x2C, 0xD6, 0x2C, 0xD6, 0x2C, 0xD8, 0x2C, 356 | 0xD8, 0x2C, 0xDA, 0x2C, 0xDA, 0x2C, 0xDC, 0x2C, 0xDC, 0x2C, 0xDE, 0x2C, 0xDE, 0x2C, 0xE0, 0x2C, 357 | 0xE0, 0x2C, 0xE2, 0x2C, 0xE2, 0x2C, 0xE4, 0x2C, 0xE5, 0x2C, 0xE6, 0x2C, 0xE7, 0x2C, 0xE8, 0x2C, 358 | 0xE9, 0x2C, 0xEA, 0x2C, 0xEB, 0x2C, 0xEC, 0x2C, 0xED, 0x2C, 0xEE, 0x2C, 0xEF, 0x2C, 0xF0, 0x2C, 359 | 0xF1, 0x2C, 0xF2, 0x2C, 0xF3, 0x2C, 0xF4, 0x2C, 0xF5, 0x2C, 0xF6, 0x2C, 0xF7, 0x2C, 0xF8, 0x2C, 360 | 0xF9, 0x2C, 0xFA, 0x2C, 0xFB, 0x2C, 0xFC, 0x2C, 0xFD, 0x2C, 0xFE, 0x2C, 0xFF, 0x2C, 0xA0, 0x10, 361 | 0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10, 0xA5, 0x10, 0xA6, 0x10, 0xA7, 0x10, 0xA8, 0x10, 362 | 0xA9, 0x10, 0xAA, 0x10, 0xAB, 0x10, 0xAC, 0x10, 0xAD, 0x10, 0xAE, 0x10, 0xAF, 0x10, 0xB0, 0x10, 363 | 0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 0xB4, 0x10, 0xB5, 0x10, 0xB6, 0x10, 0xB7, 0x10, 0xB8, 0x10, 364 | 0xB9, 0x10, 0xBA, 0x10, 0xBB, 0x10, 0xBC, 0x10, 0xBD, 0x10, 0xBE, 0x10, 0xBF, 0x10, 0xC0, 0x10, 365 | 0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xC5, 0x10, 0xFF, 0xFF, 0x1B, 0xD2, 0x21, 0xFF, 366 | 0x22, 0xFF, 0x23, 0xFF, 0x24, 0xFF, 0x25, 0xFF, 0x26, 0xFF, 0x27, 0xFF, 0x28, 0xFF, 0x29, 0xFF, 367 | 0x2A, 0xFF, 0x2B, 0xFF, 0x2C, 0xFF, 0x2D, 0xFF, 0x2E, 0xFF, 0x2F, 0xFF, 0x30, 0xFF, 0x31, 0xFF, 368 | 0x32, 0xFF, 0x33, 0xFF, 0x34, 0xFF, 0x35, 0xFF, 0x36, 0xFF, 0x37, 0xFF, 0x38, 0xFF, 0x39, 0xFF, 369 | 0x3A, 0xFF, 0x5B, 0xFF, 0x5C, 0xFF, 0x5D, 0xFF, 0x5E, 0xFF, 0x5F, 0xFF, 0x60, 0xFF, 0x61, 0xFF, 370 | 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, 0x66, 0xFF, 0x67, 0xFF, 0x68, 0xFF, 0x69, 0xFF, 371 | 0x6A, 0xFF, 0x6B, 0xFF, 0x6C, 0xFF, 0x6D, 0xFF, 0x6E, 0xFF, 0x6F, 0xFF, 0x70, 0xFF, 0x71, 0xFF, 372 | 0x72, 0xFF, 0x73, 0xFF, 0x74, 0xFF, 0x75, 0xFF, 0x76, 0xFF, 0x77, 0xFF, 0x78, 0xFF, 0x79, 0xFF, 373 | 0x7A, 0xFF, 0x7B, 0xFF, 0x7C, 0xFF, 0x7D, 0xFF, 0x7E, 0xFF, 0x7F, 0xFF, 0x80, 0xFF, 0x81, 0xFF, 374 | 0x82, 0xFF, 0x83, 0xFF, 0x84, 0xFF, 0x85, 0xFF, 0x86, 0xFF, 0x87, 0xFF, 0x88, 0xFF, 0x89, 0xFF, 375 | 0x8A, 0xFF, 0x8B, 0xFF, 0x8C, 0xFF, 0x8D, 0xFF, 0x8E, 0xFF, 0x8F, 0xFF, 0x90, 0xFF, 0x91, 0xFF, 376 | 0x92, 0xFF, 0x93, 0xFF, 0x94, 0xFF, 0x95, 0xFF, 0x96, 0xFF, 0x97, 0xFF, 0x98, 0xFF, 0x99, 0xFF, 377 | 0x9A, 0xFF, 0x9B, 0xFF, 0x9C, 0xFF, 0x9D, 0xFF, 0x9E, 0xFF, 0x9F, 0xFF, 0xA0, 0xFF, 0xA1, 0xFF, 378 | 0xA2, 0xFF, 0xA3, 0xFF, 0xA4, 0xFF, 0xA5, 0xFF, 0xA6, 0xFF, 0xA7, 0xFF, 0xA8, 0xFF, 0xA9, 0xFF, 379 | 0xAA, 0xFF, 0xAB, 0xFF, 0xAC, 0xFF, 0xAD, 0xFF, 0xAE, 0xFF, 0xAF, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, 380 | 0xB2, 0xFF, 0xB3, 0xFF, 0xB4, 0xFF, 0xB5, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB8, 0xFF, 0xB9, 0xFF, 381 | 0xBA, 0xFF, 0xBB, 0xFF, 0xBC, 0xFF, 0xBD, 0xFF, 0xBE, 0xFF, 0xBF, 0xFF, 0xC0, 0xFF, 0xC1, 0xFF, 382 | 0xC2, 0xFF, 0xC3, 0xFF, 0xC4, 0xFF, 0xC5, 0xFF, 0xC6, 0xFF, 0xC7, 0xFF, 0xC8, 0xFF, 0xC9, 0xFF, 383 | 0xCA, 0xFF, 0xCB, 0xFF, 0xCC, 0xFF, 0xCD, 0xFF, 0xCE, 0xFF, 0xCF, 0xFF, 0xD0, 0xFF, 0xD1, 0xFF, 384 | 0xD2, 0xFF, 0xD3, 0xFF, 0xD4, 0xFF, 0xD5, 0xFF, 0xD6, 0xFF, 0xD7, 0xFF, 0xD8, 0xFF, 0xD9, 0xFF, 385 | 0xDA, 0xFF, 0xDB, 0xFF, 0xDC, 0xFF, 0xDD, 0xFF, 0xDE, 0xFF, 0xDF, 0xFF, 0xE0, 0xFF, 0xE1, 0xFF, 386 | 0xE2, 0xFF, 0xE3, 0xFF, 0xE4, 0xFF, 0xE5, 0xFF, 0xE6, 0xFF, 0xE7, 0xFF, 0xE8, 0xFF, 0xE9, 0xFF, 387 | 0xEA, 0xFF, 0xEB, 0xFF, 0xEC, 0xFF, 0xED, 0xFF, 0xEE, 0xFF, 0xEF, 0xFF, 0xF0, 0xFF, 0xF1, 0xFF, 388 | 0xF2, 0xFF, 0xF3, 0xFF, 0xF4, 0xFF, 0xF5, 0xFF, 0xF6, 0xFF, 0xF7, 0xFF, 0xF8, 0xFF, 0xF9, 0xFF, 389 | 0xFA, 0xFF, 0xFB, 0xFF, 0xFC, 0xFF, 0xFD, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF 390 | }; 391 | -------------------------------------------------------------------------------- /exfat_version.h: -------------------------------------------------------------------------------- 1 | #define EXFAT_VERSION "1.2.4" 2 | --------------------------------------------------------------------------------