From e3cb5e74b98b704afdee3762dd13f92154a89abc Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 23 Mar 2022 09:20:31 -0700 Subject: [PATCH] emummc: temp delete --- emummc/.gitignore | 9 - emummc/.gitrepo | 12 - emummc/.vscode/c_cpp_properties.json | 35 - emummc/LICENSE | 339 - emummc/Makefile | 118 - emummc/README.md | 36 - emummc/build.sh | 9 - emummc/emummc.json | 137 - emummc/emummc.ld | 201 - emummc/emummc.specs | 8 - emummc/source/FS/FS.h | 51 - emummc/source/FS/FS_offsets.c | 232 - emummc/source/FS/FS_offsets.h | 59 - emummc/source/FS/FS_structs.h | 61 - emummc/source/FS/FS_versions.h | 95 - emummc/source/FS/offsets/100.h | 57 - emummc/source/FS/offsets/1000.h | 59 - emummc/source/FS/offsets/1000_exfat.h | 59 - emummc/source/FS/offsets/1020.h | 59 - emummc/source/FS/offsets/1020_exfat.h | 59 - emummc/source/FS/offsets/1100.h | 59 - emummc/source/FS/offsets/1100_exfat.h | 59 - emummc/source/FS/offsets/1200.h | 59 - emummc/source/FS/offsets/1200_exfat.h | 59 - emummc/source/FS/offsets/1203.h | 60 - emummc/source/FS/offsets/1203_exfat.h | 60 - emummc/source/FS/offsets/1300.h | 59 - emummc/source/FS/offsets/1300_exfat.h | 59 - emummc/source/FS/offsets/1310.h | 59 - emummc/source/FS/offsets/1310_exfat.h | 59 - emummc/source/FS/offsets/1400.h | 59 - emummc/source/FS/offsets/1400_exfat.h | 59 - emummc/source/FS/offsets/200.h | 58 - emummc/source/FS/offsets/200_exfat.h | 58 - emummc/source/FS/offsets/210.h | 58 - emummc/source/FS/offsets/210_exfat.h | 58 - emummc/source/FS/offsets/300.h | 58 - emummc/source/FS/offsets/300_exfat.h | 58 - emummc/source/FS/offsets/301.h | 58 - emummc/source/FS/offsets/301_exfat.h | 58 - emummc/source/FS/offsets/400.h | 58 - emummc/source/FS/offsets/400_exfat.h | 58 - emummc/source/FS/offsets/410.h | 58 - emummc/source/FS/offsets/410_exfat.h | 58 - emummc/source/FS/offsets/500.h | 58 - emummc/source/FS/offsets/500_exfat.h | 58 - emummc/source/FS/offsets/510.h | 58 - emummc/source/FS/offsets/510_exfat.h | 58 - emummc/source/FS/offsets/600.h | 59 - emummc/source/FS/offsets/600_exfat.h | 59 - emummc/source/FS/offsets/700.h | 60 - emummc/source/FS/offsets/700_exfat.h | 60 - emummc/source/FS/offsets/800.h | 60 - emummc/source/FS/offsets/800_exfat.h | 60 - emummc/source/FS/offsets/810.h | 60 - emummc/source/FS/offsets/810_exfat.h | 60 - emummc/source/FS/offsets/900.h | 60 - emummc/source/FS/offsets/900_exfat.h | 60 - emummc/source/FS/offsets/910.h | 60 - emummc/source/FS/offsets/910_exfat.h | 60 - emummc/source/emmc/mmc.h | 432 -- emummc/source/emmc/nx_emmc.c | 35 - emummc/source/emmc/nx_emmc.h | 67 - emummc/source/emmc/nx_sd.c | 91 - emummc/source/emmc/nx_sd.h | 36 - emummc/source/emmc/sd.h | 129 - emummc/source/emmc/sdmmc.c | 1480 ---- emummc/source/emmc/sdmmc.h | 123 - emummc/source/emmc/sdmmc_driver.c | 1429 ---- emummc/source/emmc/sdmmc_driver.h | 266 - emummc/source/emmc/sdmmc_t210.h | 109 - emummc/source/emuMMC/emummc.c | 573 -- emummc/source/emuMMC/emummc.h | 81 - emummc/source/emuMMC/emummc_ctx.h | 56 - emummc/source/libs/fatfs/diskio.c | 72 - emummc/source/libs/fatfs/diskio.h | 79 - emummc/source/libs/fatfs/ff.c | 6883 ----------------- emummc/source/libs/fatfs/ff.h | 391 - emummc/source/libs/fatfs/ffconf.h | 292 - emummc/source/libs/fatfs/ffsystem.c | 39 - emummc/source/libs/fatfs/ffunicode.c | 625 -- emummc/source/main.c | 436 -- emummc/source/nx/cache.h | 41 - emummc/source/nx/cache.s | 100 - emummc/source/nx/counter.h | 46 - emummc/source/nx/dynamic.c | 45 - emummc/source/nx/smc.c | 217 - emummc/source/nx/smc.h | 105 - emummc/source/nx/start.s | 131 - emummc/source/nx/svc.h | 220 - emummc/source/nx/svc.s | 136 - emummc/source/power/max77620.h | 340 - emummc/source/power/max7762x.c | 159 - emummc/source/power/max7762x.h | 117 - emummc/source/soc/clock.c | 446 -- emummc/source/soc/clock.h | 173 - emummc/source/soc/gpio.c | 168 - emummc/source/soc/gpio.h | 95 - emummc/source/soc/i2c.c | 233 - emummc/source/soc/i2c.h | 36 - emummc/source/soc/pinmux.c | 24 - emummc/source/soc/pinmux.h | 101 - emummc/source/soc/pmc.h | 75 - emummc/source/soc/pmc_lp0_t210.h | 564 -- emummc/source/soc/t210.h | 123 - emummc/source/utils/fatal.c | 40 - emummc/source/utils/fatal.h | 83 - emummc/source/utils/types.h | 100 - emummc/source/utils/util.c | 119 - emummc/source/utils/util.h | 49 - .../fs_ida_nintendo_folder_xref_formatter.au3 | 52 - emummc/tools/kip1converter.py | 53 - 112 files changed, 21966 deletions(-) delete mode 100644 emummc/.gitignore delete mode 100644 emummc/.gitrepo delete mode 100644 emummc/.vscode/c_cpp_properties.json delete mode 100644 emummc/LICENSE delete mode 100644 emummc/Makefile delete mode 100644 emummc/README.md delete mode 100644 emummc/build.sh delete mode 100644 emummc/emummc.json delete mode 100644 emummc/emummc.ld delete mode 100644 emummc/emummc.specs delete mode 100644 emummc/source/FS/FS.h delete mode 100644 emummc/source/FS/FS_offsets.c delete mode 100644 emummc/source/FS/FS_offsets.h delete mode 100644 emummc/source/FS/FS_structs.h delete mode 100644 emummc/source/FS/FS_versions.h delete mode 100644 emummc/source/FS/offsets/100.h delete mode 100644 emummc/source/FS/offsets/1000.h delete mode 100644 emummc/source/FS/offsets/1000_exfat.h delete mode 100644 emummc/source/FS/offsets/1020.h delete mode 100644 emummc/source/FS/offsets/1020_exfat.h delete mode 100644 emummc/source/FS/offsets/1100.h delete mode 100644 emummc/source/FS/offsets/1100_exfat.h delete mode 100644 emummc/source/FS/offsets/1200.h delete mode 100644 emummc/source/FS/offsets/1200_exfat.h delete mode 100644 emummc/source/FS/offsets/1203.h delete mode 100644 emummc/source/FS/offsets/1203_exfat.h delete mode 100644 emummc/source/FS/offsets/1300.h delete mode 100644 emummc/source/FS/offsets/1300_exfat.h delete mode 100644 emummc/source/FS/offsets/1310.h delete mode 100644 emummc/source/FS/offsets/1310_exfat.h delete mode 100644 emummc/source/FS/offsets/1400.h delete mode 100644 emummc/source/FS/offsets/1400_exfat.h delete mode 100644 emummc/source/FS/offsets/200.h delete mode 100644 emummc/source/FS/offsets/200_exfat.h delete mode 100644 emummc/source/FS/offsets/210.h delete mode 100644 emummc/source/FS/offsets/210_exfat.h delete mode 100644 emummc/source/FS/offsets/300.h delete mode 100644 emummc/source/FS/offsets/300_exfat.h delete mode 100644 emummc/source/FS/offsets/301.h delete mode 100644 emummc/source/FS/offsets/301_exfat.h delete mode 100644 emummc/source/FS/offsets/400.h delete mode 100644 emummc/source/FS/offsets/400_exfat.h delete mode 100644 emummc/source/FS/offsets/410.h delete mode 100644 emummc/source/FS/offsets/410_exfat.h delete mode 100644 emummc/source/FS/offsets/500.h delete mode 100644 emummc/source/FS/offsets/500_exfat.h delete mode 100644 emummc/source/FS/offsets/510.h delete mode 100644 emummc/source/FS/offsets/510_exfat.h delete mode 100644 emummc/source/FS/offsets/600.h delete mode 100644 emummc/source/FS/offsets/600_exfat.h delete mode 100644 emummc/source/FS/offsets/700.h delete mode 100644 emummc/source/FS/offsets/700_exfat.h delete mode 100644 emummc/source/FS/offsets/800.h delete mode 100644 emummc/source/FS/offsets/800_exfat.h delete mode 100644 emummc/source/FS/offsets/810.h delete mode 100644 emummc/source/FS/offsets/810_exfat.h delete mode 100644 emummc/source/FS/offsets/900.h delete mode 100644 emummc/source/FS/offsets/900_exfat.h delete mode 100644 emummc/source/FS/offsets/910.h delete mode 100644 emummc/source/FS/offsets/910_exfat.h delete mode 100644 emummc/source/emmc/mmc.h delete mode 100644 emummc/source/emmc/nx_emmc.c delete mode 100644 emummc/source/emmc/nx_emmc.h delete mode 100644 emummc/source/emmc/nx_sd.c delete mode 100644 emummc/source/emmc/nx_sd.h delete mode 100644 emummc/source/emmc/sd.h delete mode 100644 emummc/source/emmc/sdmmc.c delete mode 100644 emummc/source/emmc/sdmmc.h delete mode 100644 emummc/source/emmc/sdmmc_driver.c delete mode 100644 emummc/source/emmc/sdmmc_driver.h delete mode 100644 emummc/source/emmc/sdmmc_t210.h delete mode 100644 emummc/source/emuMMC/emummc.c delete mode 100644 emummc/source/emuMMC/emummc.h delete mode 100644 emummc/source/emuMMC/emummc_ctx.h delete mode 100644 emummc/source/libs/fatfs/diskio.c delete mode 100644 emummc/source/libs/fatfs/diskio.h delete mode 100644 emummc/source/libs/fatfs/ff.c delete mode 100644 emummc/source/libs/fatfs/ff.h delete mode 100644 emummc/source/libs/fatfs/ffconf.h delete mode 100644 emummc/source/libs/fatfs/ffsystem.c delete mode 100644 emummc/source/libs/fatfs/ffunicode.c delete mode 100644 emummc/source/main.c delete mode 100644 emummc/source/nx/cache.h delete mode 100644 emummc/source/nx/cache.s delete mode 100644 emummc/source/nx/counter.h delete mode 100644 emummc/source/nx/dynamic.c delete mode 100644 emummc/source/nx/smc.c delete mode 100644 emummc/source/nx/smc.h delete mode 100644 emummc/source/nx/start.s delete mode 100644 emummc/source/nx/svc.h delete mode 100644 emummc/source/nx/svc.s delete mode 100644 emummc/source/power/max77620.h delete mode 100644 emummc/source/power/max7762x.c delete mode 100644 emummc/source/power/max7762x.h delete mode 100644 emummc/source/soc/clock.c delete mode 100644 emummc/source/soc/clock.h delete mode 100644 emummc/source/soc/gpio.c delete mode 100644 emummc/source/soc/gpio.h delete mode 100644 emummc/source/soc/i2c.c delete mode 100644 emummc/source/soc/i2c.h delete mode 100644 emummc/source/soc/pinmux.c delete mode 100644 emummc/source/soc/pinmux.h delete mode 100644 emummc/source/soc/pmc.h delete mode 100644 emummc/source/soc/pmc_lp0_t210.h delete mode 100644 emummc/source/soc/t210.h delete mode 100644 emummc/source/utils/fatal.c delete mode 100644 emummc/source/utils/fatal.h delete mode 100644 emummc/source/utils/types.h delete mode 100644 emummc/source/utils/util.c delete mode 100644 emummc/source/utils/util.h delete mode 100644 emummc/tools/fs_ida_nintendo_folder_xref_formatter.au3 delete mode 100644 emummc/tools/kip1converter.py diff --git a/emummc/.gitignore b/emummc/.gitignore deleted file mode 100644 index 3c00ac63a0..0000000000 --- a/emummc/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.kip -*.data -*.elf -build -.vscode/ipch -.vscode/settings.json -*.exe -*.kip* -emummc.caps diff --git a/emummc/.gitrepo b/emummc/.gitrepo deleted file mode 100644 index d3b4fd24aa..0000000000 --- a/emummc/.gitrepo +++ /dev/null @@ -1,12 +0,0 @@ -; DO NOT EDIT (unless you know what you are doing) -; -; This subdirectory is a git "subrepo", and this file is maintained by the -; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme -; -[subrepo] - remote = https://github.com/m4xw/emuMMC - branch = develop - commit = a9d56959460fc794ce2cb6405402c25a3e89c47f - parent = ff719641396c635b735873fb2b020c910f768a04 - method = merge - cmdver = 0.4.1 diff --git a/emummc/.vscode/c_cpp_properties.json b/emummc/.vscode/c_cpp_properties.json deleted file mode 100644 index 91df1079b7..0000000000 --- a/emummc/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "configurations": [ - { - "name": "Switch", - "includePath": [ - "/opt/devkitpro/devkitA64/aarch64-none-elf/include", - "/opt/devkitpro/devkitA64/lib/gcc/aarch64-none-elf/8.3.0/include", - "${workspaceFolder}/libnx-patched/nx/include", - "/opt/devkitpro/portlibs/switch/include", - "/opt/devkitpro/portlibs/switch/include/freetype2", - "${workspaceFolder}/source", - "${workspaceFolder}/source/emmc", - "${workspaceFolder}/source/libs/fatfs", - "${workspaceFolder}/source/power", - "${workspaceFolder}/source/soc", - "${workspaceFolder}/source/utils", - "${workspaceFolder}/**" - ], - "defines": [ - "_DEBUG", - "UNICODE", - "_UNICODE", - "__aarch64__", - "__SWITCH__", - "INNER_HEAP_SIZE=0x80000" - ], - "windowsSdkVersion": "10.0.17763.0", - "compilerPath": "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-gcc", - "cStandard": "c11", - "cppStandard": "c++11", - "intelliSenseMode": "gcc-x64" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/emummc/LICENSE b/emummc/LICENSE deleted file mode 100644 index d159169d10..0000000000 --- a/emummc/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/emummc/Makefile b/emummc/Makefile deleted file mode 100644 index 7af45eaac1..0000000000 --- a/emummc/Makefile +++ /dev/null @@ -1,118 +0,0 @@ -.SUFFIXES: - -ifeq ($(strip $(DEVKITPRO)),) -$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") -endif - -TARGET := emummc -BUILD := build -SOURCES := source/nx source source/utils source/emmc source/soc source/power source/emuMMC source/FS source/libs/fatfs -DATA := data -INCLUDES := include -EXEFS_SRC := exefs_src - -ifneq ($(BUILD),$(notdir $(CURDIR))) -EMUMMCDIR ?= $(CURDIR) -else -EMUMMCDIR ?= $(CURDIR)/../ -endif - -include $(DEVKITPRO)/libnx/switch_rules - -ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE - -# Current max usage is 0x4600. (512 * 34 FatFS file objects + 1 fsync buffer). -DEFINES := -DINNER_HEAP_SIZE=0x8000 - -CFLAGS := -Wall -O2 -ffunction-sections -fdata-sections -Wno-unused-function \ - $(ARCH) $(DEFINES) - -CFLAGS += $(INCLUDE) -D__SWITCH__ - -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 - -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=$(EMUMMCDIR)/emummc.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) - -ifneq ($(BUILD),$(notdir $(CURDIR))) - -export OUTPUT := $(CURDIR)/$(TARGET) -export TOPDIR := $(EMUMMCDIR) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -ifeq ($(strip $(CPPFILES)),) - export LD := $(CC) -else - export LD := $(CXX) -endif - -export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export OFILES := $(OFILES_BIN) $(OFILES_SRC) -export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) - -export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC) - -ifeq ($(strip $(CONFIG_JSON)),) - jsons := $(wildcard *.json) - ifneq (,$(findstring $(TARGET).json,$(jsons))) - export APP_JSON := $(TOPDIR)/$(TARGET).json - else - ifneq (,$(findstring config.json,$(jsons))) - export APP_JSON := $(TOPDIR)/config.json - endif - endif -else - export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) -endif - -.PHONY: $(BUILD) clean all - -all: $(BUILD) - -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - -clean: - @echo clean ... - @rm -fr $(BUILD) $(TARGET).elf $(TARGET).kip - -else -.PHONY: all - -DEPENDS := $(OFILES:.o=.d) - -all : $(OUTPUT)_unpacked.kip - -$(OUTPUT)_unpacked.kip : $(OUTPUT).kip - @hactool -t kip --uncompressed=$(OUTPUT)_unpacked.kip $(OUTPUT).kip - -$(OUTPUT).kip : $(OUTPUT).elf - -$(OUTPUT).elf : $(OFILES) - -$(OFILES_SRC) : $(HFILES_BIN) - -%.bin.o %_bin.h : %.bin - @echo $(notdir $<) - @$(bin2o) - --include $(DEPENDS) - -endif diff --git a/emummc/README.md b/emummc/README.md deleted file mode 100644 index af22061a08..0000000000 --- a/emummc/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# emuMMC -*A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw*** - -### Supported Horizon Versions -**1.0.0 - 13.1.0** - -## Features -* Arbitrary SDMMC backend selection - **This allows loading eMMC from SD or even SD from eMMC** -* On the fly hooking / patching, fully self-infesting - **Only one payload required for all versions!** -* File-based SDMMC backend support (from SD) - **This allows loading eMMC images from hekate-backups (split or not)** -* SDMMC device based sector offset (*currently eMMC only*) - **Raw partition support for eMMC from SD with less performance overhead** -* Full support for `/Nintendo` folder redirection to a arbitrary path - **No 8 char length restriction!** -* exosphere based context configuration - **This includes full support for multiple emuMMC images** - -## Compiling -### hekate -Run `./build.sh` and copy the produced kipm (Kernel Initial Process Modification) file to `/bootloader/sys/` - -### Atmosphere -Run `make`, the resulting kip can be used for code injection via fusee (place at `/atmosphere/emummc.kip`) - -## License -**emuMMC is released as GPLv2** - -## Credits -* **CTCaer** - The CTCaer hekate fork, file-based emuMMC support, SDMMC driver fixes among other things -* **SciresM, hexkyz** - The Atmosphere project, FS offsets, additional research related to newer FS versions -* **naehrwert** - The hekate project, its SDMMC driver and being very helpful in the early research phase -* **jakibaki** - KIP Inject PoC, used in the early dev phase -* **switchbrew/devkitPro** - devkitA64 and libnx sources diff --git a/emummc/build.sh b/emummc/build.sh deleted file mode 100644 index b33895374d..0000000000 --- a/emummc/build.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -set -e - -make clean -make -j -./hactool.exe -t kip emummc.kip --uncompressed emummc_unpacked.kip -python2.7 tools/kip1converter.py emummc_unpacked.kip emummc.data -cat emummc.caps emummc.data > emummc.kipm diff --git a/emummc/emummc.json b/emummc/emummc.json deleted file mode 100644 index 19471c53df..0000000000 --- a/emummc/emummc.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "name": "FS", - "title_id": "0x0100000000000000", - "main_thread_stack_size": "0x00008000", - "main_thread_priority": 45, - "default_cpu_id": 3, - "process_category": 1, - "kernel_capabilities": [ - { - "type": "map_page", - "value": "0x60006000" - }, - { - "type": "map", - "value": { - "address": "0x6000D000", - "size": "0x1000", - "is_ro": false, - "is_io": true - } - }, - { - "type": "map", - "value": { - "address": "0x700b0000", - "is_ro": false, - "size": "0x00005000", - "is_io": true - } - }, - { - "type": "map", - "value": { - "address": "0x7000C000", - "is_ro": false, - "size": "0x00002000", - "is_io": true - } - }, - { - "type": "map", - "value": { - "address": "0x70000000", - "is_ro": false, - "size": "0x00004000", - "is_io": true - } - }, - { - "type": "handle_table_size", - "value": 256 - }, - { - "type": "irq_pair", - "value": [ - 46, - 47 - ] - }, - { - "type": "irq_pair", - "value": [ - 51, - 63 - ] - }, - { - "type": "syscalls", - "value": { - "svcSetHeapSize": "0x01", - "svcSetMemoryPermission": "0x02", - "svcSetMemoryAttribute": "0x03", - "svcMapMemory": "0x04", - "svcUnmapMemory": "0x05", - "svcQueryMemory": "0x06", - "svcExitProcess": "0x07", - "svcCreateThread": "0x08", - "svcStartThread": "0x09", - "svcExitThread": "0x0a", - "svcSleepThread": "0x0b", - "svcGetThreadPriority": "0x0c", - "svcSetThreadPriority": "0x0d", - "svcGetThreadCoreMask": "0x0e", - "svcSetThreadCoreMask": "0x0f", - "svcGetCurrentProcessorNumber": "0x10", - "svcSignalEvent": "0x11", - "svcClearEvent": "0x12", - "svcMapSharedMemory": "0x13", - "svcUnmapSharedMemory": "0x14", - "svcCreateTransferMemory": "0x15", - "svcCloseHandle": "0x16", - "svcResetSignal": "0x17", - "svcWaitSynchronization": "0x18", - "svcCancelSynchronization": "0x19", - "svcArbitrateLock": "0x1a", - "svcArbitrateUnlock": "0x1b", - "svcWaitProcessWideKeyAtomic": "0x1c", - "svcSignalProcessWideKey": "0x1d", - "svcGetSystemTick": "0x1e", - "svcConnectToNamedPort": "0x1f", - "svcSendSyncRequestLight": "0x20", - "svcSendSyncRequest": "0x21", - "svcSendSyncRequestWithUserBuffer": "0x22", - "svcSendAsyncRequestWithUserBuffer": "0x23", - "svcGetProcessId": "0x24", - "svcGetThreadId": "0x25", - "svcBreak": "0x26", - "svcOutputDebugString": "0x27", - "svcReturnFromException": "0x28", - "svcGetInfo": "0x29", - "svcWaitForAddress": "0x34", - "svcSignalToAddress": "0x35", - "svcCreateSession": "0x40", - "svcAcceptSession": "0x41", - "svcReplyAndReceiveLight": "0x42", - "svcReplyAndReceive": "0x43", - "svcReplyAndReceiveWithUserBuffer": "0x44", - "svcCreateEvent": "0x45", - "svcReadWriteRegister": "0x4E", - "svcMapTransferMemory": "0x51", - "svcUnmapTransferMemory": "0x52", - "svcCreateInterruptEvent": "0x53", - "svcQueryIoMapping": "0x55", - "svcCreateDeviceAddressSpace": "0x56", - "svcAttachDeviceAddressSpace": "0x57", - "svcDetachDeviceAddressSpace": "0x58", - "svcMapDeviceAddressSpaceAligned": "0x5a", - "svcUnmapDeviceAddressSpace": "0x5c", - "svcGetSystemInfo": "0x6f", - "svcSetProcessMemoryPermission": "0x73", - "svcMapProcessMemory": "0x74", - "svcUnmapProcessMemory": "0x75", - "svcCallSecureMonitor": "0x7f" - } - } - ] -} \ No newline at end of file diff --git a/emummc/emummc.ld b/emummc/emummc.ld deleted file mode 100644 index 48bf24b94f..0000000000 --- a/emummc/emummc.ld +++ /dev/null @@ -1,201 +0,0 @@ -OUTPUT_ARCH(aarch64) -ENTRY(_start) - -PHDRS -{ - code PT_LOAD FLAGS(5) /* Read | Execute */; - rodata PT_LOAD FLAGS(4) /* Read */; - data PT_LOAD FLAGS(6) /* Read | Write */; - dyn PT_DYNAMIC; -} - -SECTIONS -{ - /* =========== CODE section =========== */ - PROVIDE(__start__ = 0x0); - . = __start__; - __code_start = . ; - - .crt0 : - { - KEEP (*(.crt0)) - . = ALIGN(8); - } :code - - .init : - { - KEEP( *(.init) ) - . = ALIGN(8); - } :code - - .plt : - { - *(.plt) - *(.iplt) - . = ALIGN(8); - } :code - - .text : - { - *(.text.unlikely .text.*_unlikely .text.unlikely.*) - *(.text.exit .text.exit.*) - *(.text.startup .text.startup.*) - *(.text.hot .text.hot.*) - *(.text .stub .text.* .gnu.linkonce.t.*) - . = ALIGN(8); - } :code - - .fini : - { - KEEP( *(.fini) ) - . = ALIGN(8); - } :code - - /* =========== RODATA section =========== */ - . = ALIGN(0x1000); - __rodata_start = . ; - - .nx-module-name : { KEEP (*(.nx-module-name)) } :rodata - - .rodata : - { - *(.rodata .rodata.* .gnu.linkonce.r.*) - . = ALIGN(8); - } :rodata - - .eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } :rodata - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } :rodata - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } :rodata - .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } : rodata - - .dynamic : { *(.dynamic) } :rodata :dyn - .dynsym : { *(.dynsym) } :rodata - .dynstr : { *(.dynstr) } :rodata - .rela.dyn : { *(.rela.*) } :rodata - .interp : { *(.interp) } :rodata - .hash : { *(.hash) } :rodata - .gnu.hash : { *(.gnu.hash) } :rodata - .gnu.version : { *(.gnu.version) } :rodata - .gnu.version_d : { *(.gnu.version_d) } :rodata - .gnu.version_r : { *(.gnu.version_r) } :rodata - .note.gnu.build-id : { *(.note.gnu.build-id) } :rodata - - /* =========== DATA section =========== */ - . = ALIGN(0x1000); - __data_start = . ; - - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } :data - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } :data - .gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } : data - .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } :data - - .tdata ALIGN(8) : - { - __tdata_lma = .; - *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(8); - __tdata_lma_end = .; - } :data - - .tbss ALIGN(8) : - { - *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) - . = ALIGN(8); - } :data - - .preinit_array ALIGN(8) : - { - PROVIDE (__preinit_array_start = .); - KEEP (*(.preinit_array)) - PROVIDE (__preinit_array_end = .); - } :data - - .init_array ALIGN(8) : - { - PROVIDE (__init_array_start = .); - KEEP( *(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)) ) - KEEP( *(.init_array .ctors) ) - PROVIDE (__init_array_end = .); - } :data - - .fini_array ALIGN(8) : - { - PROVIDE (__fini_array_start = .); - KEEP( *(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)) ) - KEEP( *(.fini_array .dtors) ) - PROVIDE (__fini_array_end = .); - } :data - - __got_start__ = .; - - .got : { *(.got) *(.igot) } :data - .got.plt : { *(.got.plt) *(.igot.plt) } :data - - __got_end__ = .; - - .data ALIGN(8) : - { - *(.data .data.* .gnu.linkonce.d.*) - SORT(CONSTRUCTORS) - } :data - - __bss_start__ = .; - .bss ALIGN(8) : - { - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - . = ALIGN(8); - - /* Reserve space for the TLS segment of the main thread */ - __tls_start = .; - . += + SIZEOF(.tdata) + SIZEOF(.tbss); - __tls_end = .; - } : data - __bss_end__ = .; - - __end__ = ABSOLUTE(.) ; - - . = ALIGN(0x1000); - __argdata__ = ABSOLUTE(.) ; - - /* ================== - ==== Metadata ==== - ================== */ - - /* Discard sections that difficult post-processing */ - /DISCARD/ : { *(.group .comment .note) } - - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } -} diff --git a/emummc/emummc.specs b/emummc/emummc.specs deleted file mode 100644 index 828da3d28c..0000000000 --- a/emummc/emummc.specs +++ /dev/null @@ -1,8 +0,0 @@ -%rename link old_link - -*link: -%(old_link) -T %:getenv(TOPDIR /emummc.ld) -pie --no-dynamic-linker --spare-dynamic-tags=0 --gc-sections -z text -z nodynamic-undefined-weak --build-id=sha1 --nx-module-name - -*startfile: -crti%O%s crtbegin%O%s - diff --git a/emummc/source/FS/FS.h b/emummc/source/FS/FS.h deleted file mode 100644 index 2d92a98ac7..0000000000 --- a/emummc/source/FS/FS.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __FS_H__ -#define __FS_H__ - -// TODO -#include "../emmc/sdmmc_t210.h" - -#include "FS_versions.h" -#include "FS_offsets.h" -#include "FS_structs.h" - -#define FS_SDMMC_EMMC 0 -#define FS_SDMMC_SD 1 -#define FS_SDMMC_GC 2 - -#define FS_EMMC_PARTITION_GPP 0 -#define FS_EMMC_PARTITION_BOOT0 1 -#define FS_EMMC_PARTITION_BOOT1 2 -#define FS_EMMC_PARTITION_INVALID 3 - -#define BOOT_PARTITION_SIZE 0x2000 -#define FS_READ_WRITE_ERROR 1048 - -#define NAND_PATROL_SECTOR 0xC20 -#define NAND_PATROL_OFFSET 0x184000 - -typedef struct _fs_nand_patrol_t -{ - uint8_t hmac[0x20]; - unsigned int offset; - unsigned int count; - uint8_t rsvd[0x1D8]; -} fs_nand_patrol_t; - -#endif /* __FS_H__ */ diff --git a/emummc/source/FS/FS_offsets.c b/emummc/source/FS/FS_offsets.c deleted file mode 100644 index 627590c389..0000000000 --- a/emummc/source/FS/FS_offsets.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "FS_offsets.h" -#include "offsets/100.h" -#include "offsets/200.h" -#include "offsets/200_exfat.h" -#include "offsets/210.h" -#include "offsets/210_exfat.h" -#include "offsets/300.h" -#include "offsets/300_exfat.h" -#include "offsets/301.h" -#include "offsets/301_exfat.h" -#include "offsets/400.h" -#include "offsets/400_exfat.h" -#include "offsets/410.h" -#include "offsets/410_exfat.h" -#include "offsets/500.h" -#include "offsets/500_exfat.h" -#include "offsets/510.h" -#include "offsets/510_exfat.h" -#include "offsets/600.h" -#include "offsets/600_exfat.h" -#include "offsets/700.h" -#include "offsets/700_exfat.h" -#include "offsets/800.h" -#include "offsets/800_exfat.h" -#include "offsets/810.h" -#include "offsets/810_exfat.h" -#include "offsets/900.h" -#include "offsets/900_exfat.h" -#include "offsets/910.h" -#include "offsets/910_exfat.h" -#include "offsets/1000.h" -#include "offsets/1000_exfat.h" -#include "offsets/1020.h" -#include "offsets/1020_exfat.h" -#include "offsets/1100.h" -#include "offsets/1100_exfat.h" -#include "offsets/1200.h" -#include "offsets/1200_exfat.h" -#include "offsets/1203.h" -#include "offsets/1203_exfat.h" -#include "offsets/1300.h" -#include "offsets/1300_exfat.h" -#include "offsets/1310.h" -#include "offsets/1310_exfat.h" -#include "offsets/1400.h" -#include "offsets/1400_exfat.h" -#include "../utils/fatal.h" - -#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers - -#define DEFINE_OFFSET_STRUCT(vers) \ -static const fs_offsets_t GET_OFFSET_STRUCT_NAME(vers) = { \ - .sdmmc_accessor_gc = FS_OFFSET##vers##_SDMMC_ACCESSOR_GC, \ - .sdmmc_accessor_sd = FS_OFFSET##vers##_SDMMC_ACCESSOR_SD, \ - .sdmmc_accessor_nand = FS_OFFSET##vers##_SDMMC_ACCESSOR_NAND, \ - .sdmmc_wrapper_read = FS_OFFSET##vers##_SDMMC_WRAPPER_READ, \ - .sdmmc_wrapper_write = FS_OFFSET##vers##_SDMMC_WRAPPER_WRITE, \ - .clkrst_set_min_v_clock_rate = FS_OFFSET##vers##_CLKRST_SET_MIN_V_CLK_RATE, \ - .rtld = FS_OFFSET##vers##_RTLD, \ - .rtld_destination = FS_OFFSET##vers##_RTLD_DESTINATION, \ - .lock_mutex = FS_OFFSET##vers##_LOCK_MUTEX, \ - .unlock_mutex = FS_OFFSET##vers##_UNLOCK_MUTEX, \ - .sd_mutex = FS_OFFSET##vers##_SD_MUTEX, \ - .nand_mutex = FS_OFFSET##vers##_NAND_MUTEX, \ - .active_partition = FS_OFFSET##vers##_ACTIVE_PARTITION, \ - .sdmmc_das_handle = FS_OFFSET##vers##_SDMMC_DAS_HANDLE, \ - .sdmmc_accessor_controller_open = FS_OFFSET##vers##_SDMMC_WRAPPER_CONTROLLER_OPEN, \ - .sdmmc_accessor_controller_close = FS_OFFSET##vers##_SDMMC_WRAPPER_CONTROLLER_CLOSE, \ - .sd_das_init = FS_OFFSET##vers##_SD_DAS_INIT, \ - .nintendo_paths = FS_OFFSET##vers##_NINTENDO_PATHS, \ -} - -// Actually define offset structs -DEFINE_OFFSET_STRUCT(_100); -DEFINE_OFFSET_STRUCT(_200); -DEFINE_OFFSET_STRUCT(_200_EXFAT); -DEFINE_OFFSET_STRUCT(_210); -DEFINE_OFFSET_STRUCT(_210_EXFAT); -DEFINE_OFFSET_STRUCT(_300); -DEFINE_OFFSET_STRUCT(_300_EXFAT); -DEFINE_OFFSET_STRUCT(_301); -DEFINE_OFFSET_STRUCT(_301_EXFAT); -DEFINE_OFFSET_STRUCT(_400); -DEFINE_OFFSET_STRUCT(_400_EXFAT); -DEFINE_OFFSET_STRUCT(_410); -DEFINE_OFFSET_STRUCT(_410_EXFAT); -DEFINE_OFFSET_STRUCT(_500); -DEFINE_OFFSET_STRUCT(_500_EXFAT); -DEFINE_OFFSET_STRUCT(_510); -DEFINE_OFFSET_STRUCT(_510_EXFAT); -DEFINE_OFFSET_STRUCT(_600); -DEFINE_OFFSET_STRUCT(_600_EXFAT); -DEFINE_OFFSET_STRUCT(_700); -DEFINE_OFFSET_STRUCT(_700_EXFAT); -DEFINE_OFFSET_STRUCT(_800); -DEFINE_OFFSET_STRUCT(_800_EXFAT); -DEFINE_OFFSET_STRUCT(_810); -DEFINE_OFFSET_STRUCT(_810_EXFAT); -DEFINE_OFFSET_STRUCT(_900); -DEFINE_OFFSET_STRUCT(_900_EXFAT); -DEFINE_OFFSET_STRUCT(_910); -DEFINE_OFFSET_STRUCT(_910_EXFAT); -DEFINE_OFFSET_STRUCT(_1000); -DEFINE_OFFSET_STRUCT(_1000_EXFAT); -DEFINE_OFFSET_STRUCT(_1020); -DEFINE_OFFSET_STRUCT(_1020_EXFAT); -DEFINE_OFFSET_STRUCT(_1100); -DEFINE_OFFSET_STRUCT(_1100_EXFAT); -DEFINE_OFFSET_STRUCT(_1200); -DEFINE_OFFSET_STRUCT(_1200_EXFAT); -DEFINE_OFFSET_STRUCT(_1203); -DEFINE_OFFSET_STRUCT(_1203_EXFAT); -DEFINE_OFFSET_STRUCT(_1300); -DEFINE_OFFSET_STRUCT(_1300_EXFAT); -DEFINE_OFFSET_STRUCT(_1310); -DEFINE_OFFSET_STRUCT(_1310_EXFAT); -DEFINE_OFFSET_STRUCT(_1400); -DEFINE_OFFSET_STRUCT(_1400_EXFAT); - -const fs_offsets_t *get_fs_offsets(enum FS_VER version) { - switch (version) { - case FS_VER_1_0_0: - return &(GET_OFFSET_STRUCT_NAME(_100)); - case FS_VER_2_0_0: - return &(GET_OFFSET_STRUCT_NAME(_200)); - case FS_VER_2_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_200_EXFAT)); - case FS_VER_2_1_0: - return &(GET_OFFSET_STRUCT_NAME(_210)); - case FS_VER_2_1_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_210_EXFAT)); - case FS_VER_3_0_0: - return &(GET_OFFSET_STRUCT_NAME(_300)); - case FS_VER_3_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_300_EXFAT)); - case FS_VER_3_0_1: - return &(GET_OFFSET_STRUCT_NAME(_301)); - case FS_VER_3_0_1_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_301_EXFAT)); - case FS_VER_4_0_0: - return &(GET_OFFSET_STRUCT_NAME(_400)); - case FS_VER_4_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_400_EXFAT)); - case FS_VER_4_1_0: - return &(GET_OFFSET_STRUCT_NAME(_410)); - case FS_VER_4_1_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_410_EXFAT)); - case FS_VER_5_0_0: - return &(GET_OFFSET_STRUCT_NAME(_500)); - case FS_VER_5_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_500_EXFAT)); - case FS_VER_5_1_0: - return &(GET_OFFSET_STRUCT_NAME(_510)); - case FS_VER_5_1_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_510_EXFAT)); - case FS_VER_6_0_0: - return &(GET_OFFSET_STRUCT_NAME(_600)); - case FS_VER_6_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_600_EXFAT)); - case FS_VER_7_0_0: - return &(GET_OFFSET_STRUCT_NAME(_700)); - case FS_VER_7_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_700_EXFAT)); - case FS_VER_8_0_0: - return &(GET_OFFSET_STRUCT_NAME(_800)); - case FS_VER_8_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_800_EXFAT)); - case FS_VER_8_1_0: - return &(GET_OFFSET_STRUCT_NAME(_810)); - case FS_VER_8_1_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_810_EXFAT)); - case FS_VER_9_0_0: - return &(GET_OFFSET_STRUCT_NAME(_900)); - case FS_VER_9_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_900_EXFAT)); - case FS_VER_9_1_0: - return &(GET_OFFSET_STRUCT_NAME(_910)); - case FS_VER_9_1_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_910_EXFAT)); - case FS_VER_10_0_0: - return &(GET_OFFSET_STRUCT_NAME(_1000)); - case FS_VER_10_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_1000_EXFAT)); - case FS_VER_10_2_0: - return &(GET_OFFSET_STRUCT_NAME(_1020)); - case FS_VER_10_2_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_1020_EXFAT)); - case FS_VER_11_0_0: - return &(GET_OFFSET_STRUCT_NAME(_1100)); - case FS_VER_11_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_1100_EXFAT)); - case FS_VER_12_0_0: - return &(GET_OFFSET_STRUCT_NAME(_1200)); - case FS_VER_12_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_1200_EXFAT)); - case FS_VER_12_0_3: - return &(GET_OFFSET_STRUCT_NAME(_1203)); - case FS_VER_12_0_3_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_1203_EXFAT)); - case FS_VER_13_0_0: - return &(GET_OFFSET_STRUCT_NAME(_1300)); - case FS_VER_13_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_1300_EXFAT)); - case FS_VER_13_1_0: - return &(GET_OFFSET_STRUCT_NAME(_1310)); - case FS_VER_13_1_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_1310_EXFAT)); - case FS_VER_14_0_0: - return &(GET_OFFSET_STRUCT_NAME(_1400)); - case FS_VER_14_0_0_EXFAT: - return &(GET_OFFSET_STRUCT_NAME(_1400_EXFAT)); - default: - fatal_abort(Fatal_UnknownVersion); - } -} \ No newline at end of file diff --git a/emummc/source/FS/FS_offsets.h b/emummc/source/FS/FS_offsets.h deleted file mode 100644 index 8507d85d37..0000000000 --- a/emummc/source/FS/FS_offsets.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __FS_OFFSETS_H__ -#define __FS_OFFSETS_H__ - -#include -#include "FS_versions.h" - -typedef struct { - int opcode_reg; - uint32_t adrp_offset; - uint32_t add_rel_offset; -} fs_offsets_nintendo_path_t; - -typedef struct { - // Accessor vtable getters - uintptr_t sdmmc_accessor_gc; - uintptr_t sdmmc_accessor_sd; - uintptr_t sdmmc_accessor_nand; - // Hooks - uintptr_t sdmmc_wrapper_read; - uintptr_t sdmmc_wrapper_write; - uintptr_t rtld; - uintptr_t rtld_destination; - uintptr_t clkrst_set_min_v_clock_rate; - // Misc funcs - uintptr_t lock_mutex; - uintptr_t unlock_mutex; - uintptr_t sdmmc_accessor_controller_open; - uintptr_t sdmmc_accessor_controller_close; - // Misc data - uintptr_t sd_mutex; - uintptr_t nand_mutex; - uintptr_t active_partition; - uintptr_t sdmmc_das_handle; - // NOPs - uintptr_t sd_das_init; - // Nintendo Paths - fs_offsets_nintendo_path_t nintendo_paths[]; -} fs_offsets_t; - -const fs_offsets_t *get_fs_offsets(enum FS_VER version); - -#endif // __FS_OFFSETS_H__ diff --git a/emummc/source/FS/FS_structs.h b/emummc/source/FS/FS_structs.h deleted file mode 100644 index 81db84f85f..0000000000 --- a/emummc/source/FS/FS_structs.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __FS_STRUCTS_H__ -#define __FS_STRUCTS_H__ - -#include "../utils/types.h" - -typedef struct -{ - char *device_addr_buffer; - uint64_t device_addr_buffer_size; - char *device_addr_buffer_masked; -} sdmmc_dma_buffer_t; - -_Static_assert(__alignof(sdmmc_dma_buffer_t) == 8, "sdmmc_dma_buffer_t definition"); - -typedef struct sdmmc_accessor_vt -{ - void *ctor; - void *dtor; - void *map_device_addr_space; - void *unmap_device_addr_space; - uint64_t (*sdmmc_accessor_controller_open)(void *); - uint64_t (*sdmmc_accessor_controller_close)(void *); - uint64_t (*read_write)(void *, uint64_t, uint64_t, void *, uint64_t, uint64_t); - // More not included because we don't use it. -} sdmmc_accessor_vt_t; - -_Static_assert(__alignof(sdmmc_accessor_vt_t) == 8, "sdmmc_accessor_vt_t definition"); - -typedef struct -{ - void *vtab; - t210_sdmmc_t *io_map; - sdmmc_dma_buffer_t dmaBuffers[3]; - // More not included because we don't use it. -} mmc_obj_t; - -typedef struct -{ - sdmmc_accessor_vt_t *vtab; - mmc_obj_t *parent; - // More not included because we don't use it. -} sdmmc_accessor_t; - -#endif // __FS_STRUCTS_H__ diff --git a/emummc/source/FS/FS_versions.h b/emummc/source/FS/FS_versions.h deleted file mode 100644 index 70e1f105a1..0000000000 --- a/emummc/source/FS/FS_versions.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __FS_VERSIONS_H__ -#define __FS_VERSIONS_H__ - -// FS Version enum -enum FS_VER -{ - FS_VER_1_0_0 = 0, - - FS_VER_2_0_0, - FS_VER_2_0_0_EXFAT, - - FS_VER_2_1_0, - FS_VER_2_1_0_EXFAT, - - FS_VER_3_0_0, - FS_VER_3_0_0_EXFAT, - - FS_VER_3_0_1, - FS_VER_3_0_1_EXFAT, - - FS_VER_4_0_0, - FS_VER_4_0_0_EXFAT, - - FS_VER_4_1_0, - FS_VER_4_1_0_EXFAT, - - FS_VER_5_0_0, - FS_VER_5_0_0_EXFAT, - - FS_VER_5_1_0, - FS_VER_5_1_0_EXFAT, - - FS_VER_6_0_0, - FS_VER_6_0_0_EXFAT, - - FS_VER_7_0_0, - FS_VER_7_0_0_EXFAT, - - FS_VER_8_0_0, - FS_VER_8_0_0_EXFAT, - - FS_VER_8_1_0, - FS_VER_8_1_0_EXFAT, - - FS_VER_9_0_0, - FS_VER_9_0_0_EXFAT, - - FS_VER_9_1_0, - FS_VER_9_1_0_EXFAT, - - FS_VER_10_0_0, - FS_VER_10_0_0_EXFAT, - - FS_VER_10_2_0, - FS_VER_10_2_0_EXFAT, - - FS_VER_11_0_0, - FS_VER_11_0_0_EXFAT, - - FS_VER_12_0_0, - FS_VER_12_0_0_EXFAT, - - FS_VER_12_0_3, - FS_VER_12_0_3_EXFAT, - - FS_VER_13_0_0, - FS_VER_13_0_0_EXFAT, - - FS_VER_13_1_0, - FS_VER_13_1_0_EXFAT, - - FS_VER_14_0_0, - FS_VER_14_0_0_EXFAT, - - FS_VER_MAX, -}; - -#endif // __FS_VERSIONS_H__ diff --git a/emummc/source/FS/offsets/100.h b/emummc/source/FS/offsets/100.h deleted file mode 100644 index 0f94f19f42..0000000000 --- a/emummc/source/FS/offsets/100.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_100_H__ -#define __FS_100_H__ - -// Accessor vtable getters -#define FS_OFFSET_100_SDMMC_ACCESSOR_GC 0x6F850 -#define FS_OFFSET_100_SDMMC_ACCESSOR_SD 0x6F65C -#define FS_OFFSET_100_SDMMC_ACCESSOR_NAND 0x6F230 - -// Hooks -#define FS_OFFSET_100_SDMMC_WRAPPER_READ 0x6A930 -#define FS_OFFSET_100_SDMMC_WRAPPER_WRITE 0x6A9F0 -#define FS_OFFSET_100_RTLD 0x534 -#define FS_OFFSET_100_RTLD_DESTINATION 0xA0 - -#define FS_OFFSET_100_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_100_LOCK_MUTEX 0x2884 -#define FS_OFFSET_100_UNLOCK_MUTEX 0x28F0 - -#define FS_OFFSET_100_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x6A8AC - -// Misc Data -#define FS_OFFSET_100_SD_MUTEX 0xE36058 -#define FS_OFFSET_100_NAND_MUTEX 0xE30610 -#define FS_OFFSET_100_ACTIVE_PARTITION 0xE30650 -#define FS_OFFSET_100_SDMMC_DAS_HANDLE 0xE2F730 - -// NOPs -#define FS_OFFSET_100_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_100_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 8, .adrp_offset = 0x00032C58, .add_rel_offset = 8}, \ - {.opcode_reg = 9, .adrp_offset = 0x00032F40, .add_rel_offset = 8}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_100_H__ diff --git a/emummc/source/FS/offsets/1000.h b/emummc/source/FS/offsets/1000.h deleted file mode 100644 index 1471eb9382..0000000000 --- a/emummc/source/FS/offsets/1000.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1000_H__ -#define __FS_1000_H__ - -// Accessor vtable getters -#define FS_OFFSET_1000_SDMMC_ACCESSOR_GC 0x14DC90 -#define FS_OFFSET_1000_SDMMC_ACCESSOR_SD 0x14BDA0 -#define FS_OFFSET_1000_SDMMC_ACCESSOR_NAND 0x146C20 - -// Hooks -#define FS_OFFSET_1000_SDMMC_WRAPPER_READ 0x142380 -#define FS_OFFSET_1000_SDMMC_WRAPPER_WRITE 0x142460 -#define FS_OFFSET_1000_RTLD 0x634 -#define FS_OFFSET_1000_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_1000_CLKRST_SET_MIN_V_CLK_RATE 0x1415A0 - -// Misc funcs -#define FS_OFFSET_1000_LOCK_MUTEX 0x28910 -#define FS_OFFSET_1000_UNLOCK_MUTEX 0x28960 - -#define FS_OFFSET_1000_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_1000_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0 - -// Misc Data -#define FS_OFFSET_1000_SD_MUTEX 0xE273E8 -#define FS_OFFSET_1000_NAND_MUTEX 0xE22DA0 -#define FS_OFFSET_1000_ACTIVE_PARTITION 0xE22DE0 -#define FS_OFFSET_1000_SDMMC_DAS_HANDLE 0xE0AB90 - -// NOPs -#define FS_OFFSET_1000_SD_DAS_INIT 0x151CEC - -// Nintendo Paths -#define FS_OFFSET_1000_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006BBA4, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00078520, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007ED0C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0009115C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1000_H__ diff --git a/emummc/source/FS/offsets/1000_exfat.h b/emummc/source/FS/offsets/1000_exfat.h deleted file mode 100644 index 6dcfe6a028..0000000000 --- a/emummc/source/FS/offsets/1000_exfat.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1000_EXFAT_H__ -#define __FS_1000_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_1000_EXFAT_SDMMC_ACCESSOR_GC 0x14DC90 -#define FS_OFFSET_1000_EXFAT_SDMMC_ACCESSOR_SD 0x14BDA0 -#define FS_OFFSET_1000_EXFAT_SDMMC_ACCESSOR_NAND 0x146C20 - -// Hooks -#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_READ 0x142380 -#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_WRITE 0x142460 -#define FS_OFFSET_1000_EXFAT_RTLD 0x634 -#define FS_OFFSET_1000_EXFAT_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_1000_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1415A0 - -// Misc funcs -#define FS_OFFSET_1000_EXFAT_LOCK_MUTEX 0x28910 -#define FS_OFFSET_1000_EXFAT_UNLOCK_MUTEX 0x28960 - -#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0 - -// Misc Data -#define FS_OFFSET_1000_EXFAT_SD_MUTEX 0xE353E8 -#define FS_OFFSET_1000_EXFAT_NAND_MUTEX 0xE30DA0 -#define FS_OFFSET_1000_EXFAT_ACTIVE_PARTITION 0xE30DE0 -#define FS_OFFSET_1000_EXFAT_SDMMC_DAS_HANDLE 0xE18B90 - -// NOPs -#define FS_OFFSET_1000_EXFAT_SD_DAS_INIT 0x151CEC - -// Nintendo Paths -#define FS_OFFSET_1000_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006BBA4, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00078520, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007ED0C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0009115C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1000_EXFAT_H__ diff --git a/emummc/source/FS/offsets/1020.h b/emummc/source/FS/offsets/1020.h deleted file mode 100644 index 65d5b48c80..0000000000 --- a/emummc/source/FS/offsets/1020.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1020_H__ -#define __FS_1020_H__ - -// Accessor vtable getters -#define FS_OFFSET_1020_SDMMC_ACCESSOR_GC 0x14E0F0 -#define FS_OFFSET_1020_SDMMC_ACCESSOR_SD 0x14C200 -#define FS_OFFSET_1020_SDMMC_ACCESSOR_NAND 0x147080 - -// Hooks -#define FS_OFFSET_1020_SDMMC_WRAPPER_READ 0x1427E0 -#define FS_OFFSET_1020_SDMMC_WRAPPER_WRITE 0x1428C0 -#define FS_OFFSET_1020_RTLD 0x634 -#define FS_OFFSET_1020_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_1020_CLKRST_SET_MIN_V_CLK_RATE 0x141A00 - -// Misc funcs -#define FS_OFFSET_1020_LOCK_MUTEX 0x28910 -#define FS_OFFSET_1020_UNLOCK_MUTEX 0x28960 - -#define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740 - -// Misc Data -#define FS_OFFSET_1020_SD_MUTEX 0xE273E8 -#define FS_OFFSET_1020_NAND_MUTEX 0xE22DA0 -#define FS_OFFSET_1020_ACTIVE_PARTITION 0xE22DE0 -#define FS_OFFSET_1020_SDMMC_DAS_HANDLE 0xE0AB90 - -// NOPs -#define FS_OFFSET_1020_SD_DAS_INIT 0x15214C - -// Nintendo Paths -#define FS_OFFSET_1020_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006BBA4, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00078520, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007ED0C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0009115C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1020_H__ diff --git a/emummc/source/FS/offsets/1020_exfat.h b/emummc/source/FS/offsets/1020_exfat.h deleted file mode 100644 index 34c03d9a47..0000000000 --- a/emummc/source/FS/offsets/1020_exfat.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1020_EXFAT_H__ -#define __FS_1020_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_1020_EXFAT_SDMMC_ACCESSOR_GC 0x14E0F0 -#define FS_OFFSET_1020_EXFAT_SDMMC_ACCESSOR_SD 0x14C200 -#define FS_OFFSET_1020_EXFAT_SDMMC_ACCESSOR_NAND 0x147080 - -// Hooks -#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_READ 0x1427E0 -#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_WRITE 0x1428C0 -#define FS_OFFSET_1020_EXFAT_RTLD 0x634 -#define FS_OFFSET_1020_EXFAT_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_1020_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x141A00 - -// Misc funcs -#define FS_OFFSET_1020_EXFAT_LOCK_MUTEX 0x28910 -#define FS_OFFSET_1020_EXFAT_UNLOCK_MUTEX 0x28960 - -#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740 - -// Misc Data -#define FS_OFFSET_1020_EXFAT_SD_MUTEX 0xE353E8 -#define FS_OFFSET_1020_EXFAT_NAND_MUTEX 0xE30DA0 -#define FS_OFFSET_1020_EXFAT_ACTIVE_PARTITION 0xE30DE0 -#define FS_OFFSET_1020_EXFAT_SDMMC_DAS_HANDLE 0xE18B90 - -// NOPs -#define FS_OFFSET_1020_EXFAT_SD_DAS_INIT 0x15214C - -// Nintendo Paths -#define FS_OFFSET_1020_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006BBA4, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00078520, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007ED0C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0009115C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1020_EXFAT_H__ diff --git a/emummc/source/FS/offsets/1100.h b/emummc/source/FS/offsets/1100.h deleted file mode 100644 index 164ec37d61..0000000000 --- a/emummc/source/FS/offsets/1100.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1100_H__ -#define __FS_1100_H__ - -// Accessor vtable getters -#define FS_OFFSET_1100_SDMMC_ACCESSOR_GC 0x156D90 -#define FS_OFFSET_1100_SDMMC_ACCESSOR_SD 0x154F40 -#define FS_OFFSET_1100_SDMMC_ACCESSOR_NAND 0x1500F0 - -// Hooks -#define FS_OFFSET_1100_SDMMC_WRAPPER_READ 0x14B990 -#define FS_OFFSET_1100_SDMMC_WRAPPER_WRITE 0x14BA70 -#define FS_OFFSET_1100_RTLD 0x688 -#define FS_OFFSET_1100_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C))) - -#define FS_OFFSET_1100_CLKRST_SET_MIN_V_CLK_RATE 0x14AC40 - -// Misc funcs -#define FS_OFFSET_1100_LOCK_MUTEX 0x28FF0 -#define FS_OFFSET_1100_UNLOCK_MUTEX 0x29040 - -#define FS_OFFSET_1100_SDMMC_WRAPPER_CONTROLLER_OPEN 0x14B840 -#define FS_OFFSET_1100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14B8F0 - -// Misc Data -#define FS_OFFSET_1100_SD_MUTEX 0xE323E8 -#define FS_OFFSET_1100_NAND_MUTEX 0xE2D338 -#define FS_OFFSET_1100_ACTIVE_PARTITION 0xE2D378 -#define FS_OFFSET_1100_SDMMC_DAS_HANDLE 0xE15D40 - -// NOPs -#define FS_OFFSET_1100_SD_DAS_INIT 0x273B4 - -// Nintendo Paths -#define FS_OFFSET_1100_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006D944, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007A3C0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00080708, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00092198, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1100_H__ diff --git a/emummc/source/FS/offsets/1100_exfat.h b/emummc/source/FS/offsets/1100_exfat.h deleted file mode 100644 index ecc7056607..0000000000 --- a/emummc/source/FS/offsets/1100_exfat.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1100_EXFAT_H__ -#define __FS_1100_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_1100_EXFAT_SDMMC_ACCESSOR_GC 0x156D90 -#define FS_OFFSET_1100_EXFAT_SDMMC_ACCESSOR_SD 0x154F40 -#define FS_OFFSET_1100_EXFAT_SDMMC_ACCESSOR_NAND 0x1500F0 - -// Hooks -#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_READ 0x14B990 -#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_WRITE 0x14BA70 -#define FS_OFFSET_1100_EXFAT_RTLD 0x688 -#define FS_OFFSET_1100_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C))) - -#define FS_OFFSET_1100_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x14AC40 - -// Misc funcs -#define FS_OFFSET_1100_EXFAT_LOCK_MUTEX 0x28FF0 -#define FS_OFFSET_1100_EXFAT_UNLOCK_MUTEX 0x29040 - -#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x14B840 -#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14B8F0 - -// Misc Data -#define FS_OFFSET_1100_EXFAT_SD_MUTEX 0xE403E8 -#define FS_OFFSET_1100_EXFAT_NAND_MUTEX 0xE3B338 -#define FS_OFFSET_1100_EXFAT_ACTIVE_PARTITION 0xE3B378 -#define FS_OFFSET_1100_EXFAT_SDMMC_DAS_HANDLE 0xE23D40 - -// NOPs -#define FS_OFFSET_1100_EXFAT_SD_DAS_INIT 0x273B4 - -// Nintendo Paths -#define FS_OFFSET_1100_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006D944, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007A3C0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00080708, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00092198, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1100_EXFAT_H__ diff --git a/emummc/source/FS/offsets/1200.h b/emummc/source/FS/offsets/1200.h deleted file mode 100644 index c18d4340de..0000000000 --- a/emummc/source/FS/offsets/1200.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1200_H__ -#define __FS_1200_H__ - -// Accessor vtable getters -#define FS_OFFSET_1200_SDMMC_ACCESSOR_GC 0x154FD0 -#define FS_OFFSET_1200_SDMMC_ACCESSOR_SD 0x156DE0 -#define FS_OFFSET_1200_SDMMC_ACCESSOR_NAND 0x155500 - -// Hooks -#define FS_OFFSET_1200_SDMMC_WRAPPER_READ 0x150970 -#define FS_OFFSET_1200_SDMMC_WRAPPER_WRITE 0x150A30 -#define FS_OFFSET_1200_RTLD 0x688 -#define FS_OFFSET_1200_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C))) - -#define FS_OFFSET_1200_CLKRST_SET_MIN_V_CLK_RATE 0x14FCC0 - -// Misc funcs -#define FS_OFFSET_1200_LOCK_MUTEX 0x29350 -#define FS_OFFSET_1200_UNLOCK_MUTEX 0x293A0 - -#define FS_OFFSET_1200_SDMMC_WRAPPER_CONTROLLER_OPEN 0x150850 -#define FS_OFFSET_1200_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1508E0 - -// Misc Data -#define FS_OFFSET_1200_SD_MUTEX 0xE3D3E8 -#define FS_OFFSET_1200_NAND_MUTEX 0xE38768 -#define FS_OFFSET_1200_ACTIVE_PARTITION 0xE387A8 -#define FS_OFFSET_1200_SDMMC_DAS_HANDLE 0xE20DB0 - -// NOPs -#define FS_OFFSET_1200_SD_DAS_INIT 0x27244 - -// Nintendo Paths -#define FS_OFFSET_1200_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006E810, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007AEC0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00081254, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00092850, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1200_H__ diff --git a/emummc/source/FS/offsets/1200_exfat.h b/emummc/source/FS/offsets/1200_exfat.h deleted file mode 100644 index b6fb7ef93b..0000000000 --- a/emummc/source/FS/offsets/1200_exfat.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1200_EXFAT_H__ -#define __FS_1200_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_1200_EXFAT_SDMMC_ACCESSOR_GC 0x154FD0 -#define FS_OFFSET_1200_EXFAT_SDMMC_ACCESSOR_SD 0x156DE0 -#define FS_OFFSET_1200_EXFAT_SDMMC_ACCESSOR_NAND 0x155500 - -// Hooks -#define FS_OFFSET_1200_EXFAT_SDMMC_WRAPPER_READ 0x150970 -#define FS_OFFSET_1200_EXFAT_SDMMC_WRAPPER_WRITE 0x150A30 -#define FS_OFFSET_1200_EXFAT_RTLD 0x688 -#define FS_OFFSET_1200_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C))) - -#define FS_OFFSET_1200_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x14FCC0 - -// Misc funcs -#define FS_OFFSET_1200_EXFAT_LOCK_MUTEX 0x29350 -#define FS_OFFSET_1200_EXFAT_UNLOCK_MUTEX 0x293A0 - -#define FS_OFFSET_1200_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x150850 -#define FS_OFFSET_1200_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1508E0 - -// Misc Data -#define FS_OFFSET_1200_EXFAT_SD_MUTEX 0xE4B3E8 -#define FS_OFFSET_1200_EXFAT_NAND_MUTEX 0xE46768 -#define FS_OFFSET_1200_EXFAT_ACTIVE_PARTITION 0xE467A8 -#define FS_OFFSET_1200_EXFAT_SDMMC_DAS_HANDLE 0xE2EDB0 - -// NOPs -#define FS_OFFSET_1200_EXFAT_SD_DAS_INIT 0x27244 - -// Nintendo Paths -#define FS_OFFSET_1200_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006E810, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007AEC0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00081254, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00092850, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1200_EXFAT_H__ diff --git a/emummc/source/FS/offsets/1203.h b/emummc/source/FS/offsets/1203.h deleted file mode 100644 index 13aafa642b..0000000000 --- a/emummc/source/FS/offsets/1203.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * Copyright (c) 2021 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1203_H__ -#define __FS_1203_H__ - -// Accessor vtable getters -#define FS_OFFSET_1203_SDMMC_ACCESSOR_GC 0x1550E0 -#define FS_OFFSET_1203_SDMMC_ACCESSOR_SD 0x156EF0 -#define FS_OFFSET_1203_SDMMC_ACCESSOR_NAND 0x155610 - -// Hooks -#define FS_OFFSET_1203_SDMMC_WRAPPER_READ 0x150A80 -#define FS_OFFSET_1203_SDMMC_WRAPPER_WRITE 0x150B40 -#define FS_OFFSET_1203_RTLD 0x688 -#define FS_OFFSET_1203_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C))) - -#define FS_OFFSET_1203_CLKRST_SET_MIN_V_CLK_RATE 0x14FDD0 - -// Misc funcs -#define FS_OFFSET_1203_LOCK_MUTEX 0x29350 -#define FS_OFFSET_1203_UNLOCK_MUTEX 0x293A0 - -#define FS_OFFSET_1203_SDMMC_WRAPPER_CONTROLLER_OPEN 0x150960 -#define FS_OFFSET_1203_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1509F0 - -// Misc Data -#define FS_OFFSET_1203_SD_MUTEX 0xE3D3E8 -#define FS_OFFSET_1203_NAND_MUTEX 0xE38768 -#define FS_OFFSET_1203_ACTIVE_PARTITION 0xE387A8 -#define FS_OFFSET_1203_SDMMC_DAS_HANDLE 0xE20DB0 - -// NOPs -#define FS_OFFSET_1203_SD_DAS_INIT 0x27244 - -// Nintendo Paths -#define FS_OFFSET_1203_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006E920, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007AFD0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00081364, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00092960, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1203_H__ diff --git a/emummc/source/FS/offsets/1203_exfat.h b/emummc/source/FS/offsets/1203_exfat.h deleted file mode 100644 index 016a1c4e06..0000000000 --- a/emummc/source/FS/offsets/1203_exfat.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * Copyright (c) 2021 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1203_EXFAT_H__ -#define __FS_1203_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_1203_EXFAT_SDMMC_ACCESSOR_GC 0x1550E0 -#define FS_OFFSET_1203_EXFAT_SDMMC_ACCESSOR_SD 0x156EF0 -#define FS_OFFSET_1203_EXFAT_SDMMC_ACCESSOR_NAND 0x155610 - -// Hooks -#define FS_OFFSET_1203_EXFAT_SDMMC_WRAPPER_READ 0x150A80 -#define FS_OFFSET_1203_EXFAT_SDMMC_WRAPPER_WRITE 0x150B40 -#define FS_OFFSET_1203_EXFAT_RTLD 0x688 -#define FS_OFFSET_1203_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C))) - -#define FS_OFFSET_1203_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x14FDD0 - -// Misc funcs -#define FS_OFFSET_1203_EXFAT_LOCK_MUTEX 0x29350 -#define FS_OFFSET_1203_EXFAT_UNLOCK_MUTEX 0x293A0 - -#define FS_OFFSET_1203_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x150960 -#define FS_OFFSET_1203_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1509F0 - -// Misc Data -#define FS_OFFSET_1203_EXFAT_SD_MUTEX 0xE4B3E8 -#define FS_OFFSET_1203_EXFAT_NAND_MUTEX 0xE46768 -#define FS_OFFSET_1203_EXFAT_ACTIVE_PARTITION 0xE467A8 -#define FS_OFFSET_1203_EXFAT_SDMMC_DAS_HANDLE 0xE2EDB0 - -// NOPs -#define FS_OFFSET_1203_EXFAT_SD_DAS_INIT 0x27244 - -// Nintendo Paths -#define FS_OFFSET_1203_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006E920, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007AFD0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00081364, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00092960, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1203_EXFAT_H__ diff --git a/emummc/source/FS/offsets/1300.h b/emummc/source/FS/offsets/1300.h deleted file mode 100644 index 2503527aed..0000000000 --- a/emummc/source/FS/offsets/1300.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1300_H__ -#define __FS_1300_H__ - -// Accessor vtable getters -#define FS_OFFSET_1300_SDMMC_ACCESSOR_GC 0x158C80 -#define FS_OFFSET_1300_SDMMC_ACCESSOR_SD 0x15AA90 -#define FS_OFFSET_1300_SDMMC_ACCESSOR_NAND 0x1591B0 - -// Hooks -#define FS_OFFSET_1300_SDMMC_WRAPPER_READ 0x154620 -#define FS_OFFSET_1300_SDMMC_WRAPPER_WRITE 0x1546E0 -#define FS_OFFSET_1300_RTLD 0x688 -#define FS_OFFSET_1300_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C))) - -#define FS_OFFSET_1300_CLKRST_SET_MIN_V_CLK_RATE 0x153820 - -// Misc funcs -#define FS_OFFSET_1300_LOCK_MUTEX 0x29690 -#define FS_OFFSET_1300_UNLOCK_MUTEX 0x296E0 - -#define FS_OFFSET_1300_SDMMC_WRAPPER_CONTROLLER_OPEN 0x154500 -#define FS_OFFSET_1300_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x154590 - -// Misc Data -#define FS_OFFSET_1300_SD_MUTEX 0xE133E8 -#define FS_OFFSET_1300_NAND_MUTEX 0xE0E768 -#define FS_OFFSET_1300_ACTIVE_PARTITION 0xE0E7A8 -#define FS_OFFSET_1300_SDMMC_DAS_HANDLE 0xDF6E18 - -// NOPs -#define FS_OFFSET_1300_SD_DAS_INIT 0x27744 - -// Nintendo Paths -#define FS_OFFSET_1300_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006EBE0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007BEEC, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00082294, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0009422C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1300_H__ diff --git a/emummc/source/FS/offsets/1300_exfat.h b/emummc/source/FS/offsets/1300_exfat.h deleted file mode 100644 index 08dfc39656..0000000000 --- a/emummc/source/FS/offsets/1300_exfat.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1300_EXFAT_H__ -#define __FS_1300_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_1300_EXFAT_SDMMC_ACCESSOR_GC 0x158C80 -#define FS_OFFSET_1300_EXFAT_SDMMC_ACCESSOR_SD 0x15AA90 -#define FS_OFFSET_1300_EXFAT_SDMMC_ACCESSOR_NAND 0x1591B0 - -// Hooks -#define FS_OFFSET_1300_EXFAT_SDMMC_WRAPPER_READ 0x154620 -#define FS_OFFSET_1300_EXFAT_SDMMC_WRAPPER_WRITE 0x1546E0 -#define FS_OFFSET_1300_EXFAT_RTLD 0x688 -#define FS_OFFSET_1300_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C))) - -#define FS_OFFSET_1300_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x153820 - -// Misc funcs -#define FS_OFFSET_1300_EXFAT_LOCK_MUTEX 0x29690 -#define FS_OFFSET_1300_EXFAT_UNLOCK_MUTEX 0x296E0 - -#define FS_OFFSET_1300_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x154500 -#define FS_OFFSET_1300_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x154590 - -// Misc Data -#define FS_OFFSET_1300_EXFAT_SD_MUTEX 0xE203E8 -#define FS_OFFSET_1300_EXFAT_NAND_MUTEX 0xE1B768 -#define FS_OFFSET_1300_EXFAT_ACTIVE_PARTITION 0xE1B7A8 -#define FS_OFFSET_1300_EXFAT_SDMMC_DAS_HANDLE 0xE03E18 - -// NOPs -#define FS_OFFSET_1300_EXFAT_SD_DAS_INIT 0x27744 - -// Nintendo Paths -#define FS_OFFSET_1300_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006EBE0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007BEEC, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00082294, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0009422C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1300_EXFAT_H__ diff --git a/emummc/source/FS/offsets/1310.h b/emummc/source/FS/offsets/1310.h deleted file mode 100644 index 5d4e052262..0000000000 --- a/emummc/source/FS/offsets/1310.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1310_H__ -#define __FS_1310_H__ - -// Accessor vtable getters -#define FS_OFFSET_1310_SDMMC_ACCESSOR_GC 0x158C20 -#define FS_OFFSET_1310_SDMMC_ACCESSOR_SD 0x15AA30 -#define FS_OFFSET_1310_SDMMC_ACCESSOR_NAND 0x159150 - -// Hooks -#define FS_OFFSET_1310_SDMMC_WRAPPER_READ 0x1545C0 -#define FS_OFFSET_1310_SDMMC_WRAPPER_WRITE 0x154680 -#define FS_OFFSET_1310_RTLD 0x688 -#define FS_OFFSET_1310_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C))) - -#define FS_OFFSET_1310_CLKRST_SET_MIN_V_CLK_RATE 0x1537C0 - -// Misc funcs -#define FS_OFFSET_1310_LOCK_MUTEX 0x29690 -#define FS_OFFSET_1310_UNLOCK_MUTEX 0x296E0 - -#define FS_OFFSET_1310_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1544A0 -#define FS_OFFSET_1310_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x154530 - -// Misc Data -#define FS_OFFSET_1310_SD_MUTEX 0xE133E8 -#define FS_OFFSET_1310_NAND_MUTEX 0xE0E768 -#define FS_OFFSET_1310_ACTIVE_PARTITION 0xE0E7A8 -#define FS_OFFSET_1310_SDMMC_DAS_HANDLE 0xDF6E18 - -// NOPs -#define FS_OFFSET_1310_SD_DAS_INIT 0x27744 - -// Nintendo Paths -#define FS_OFFSET_1310_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006EBE0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007BEEC, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00082294, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0009422C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1310_H__ diff --git a/emummc/source/FS/offsets/1310_exfat.h b/emummc/source/FS/offsets/1310_exfat.h deleted file mode 100644 index 33bdc24b88..0000000000 --- a/emummc/source/FS/offsets/1310_exfat.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1310_EXFAT_H__ -#define __FS_1310_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_1310_EXFAT_SDMMC_ACCESSOR_GC 0x158C20 -#define FS_OFFSET_1310_EXFAT_SDMMC_ACCESSOR_SD 0x15AA30 -#define FS_OFFSET_1310_EXFAT_SDMMC_ACCESSOR_NAND 0x159150 - -// Hooks -#define FS_OFFSET_1310_EXFAT_SDMMC_WRAPPER_READ 0x1545C0 -#define FS_OFFSET_1310_EXFAT_SDMMC_WRAPPER_WRITE 0x154680 -#define FS_OFFSET_1310_EXFAT_RTLD 0x688 -#define FS_OFFSET_1310_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C))) - -#define FS_OFFSET_1310_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1537C0 - -// Misc funcs -#define FS_OFFSET_1310_EXFAT_LOCK_MUTEX 0x29690 -#define FS_OFFSET_1310_EXFAT_UNLOCK_MUTEX 0x296E0 - -#define FS_OFFSET_1310_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x1544A0 -#define FS_OFFSET_1310_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x154530 - -// Misc Data -#define FS_OFFSET_1310_EXFAT_SD_MUTEX 0xE203E8 -#define FS_OFFSET_1310_EXFAT_NAND_MUTEX 0xE1B768 -#define FS_OFFSET_1310_EXFAT_ACTIVE_PARTITION 0xE1B7A8 -#define FS_OFFSET_1310_EXFAT_SDMMC_DAS_HANDLE 0xE03E18 - -// NOPs -#define FS_OFFSET_1310_EXFAT_SD_DAS_INIT 0x27744 - -// Nintendo Paths -#define FS_OFFSET_1310_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006EBE0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007BEEC, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x00082294, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0009422C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1310_EXFAT_H__ diff --git a/emummc/source/FS/offsets/1400.h b/emummc/source/FS/offsets/1400.h deleted file mode 100644 index c6e1acaeec..0000000000 --- a/emummc/source/FS/offsets/1400.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1400_H__ -#define __FS_1400_H__ - -// Accessor vtable getters -#define FS_OFFSET_1400_SDMMC_ACCESSOR_GC 0x189F50 -#define FS_OFFSET_1400_SDMMC_ACCESSOR_SD 0x18BD60 -#define FS_OFFSET_1400_SDMMC_ACCESSOR_NAND 0x18A480 - -// Hooks -#define FS_OFFSET_1400_SDMMC_WRAPPER_READ 0x185AF0 -#define FS_OFFSET_1400_SDMMC_WRAPPER_WRITE 0x185B50 -#define FS_OFFSET_1400_RTLD 0x282B8 -#define FS_OFFSET_1400_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C))) - -#define FS_OFFSET_1400_CLKRST_SET_MIN_V_CLK_RATE 0x1A5D90 - -// Misc funcs -#define FS_OFFSET_1400_LOCK_MUTEX 0x17E9F0 -#define FS_OFFSET_1400_UNLOCK_MUTEX 0x17EA40 - -#define FS_OFFSET_1400_SDMMC_WRAPPER_CONTROLLER_OPEN 0x185AA0 -#define FS_OFFSET_1400_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x185AD0 - -// Misc Data -#define FS_OFFSET_1400_SD_MUTEX 0xF2E3F0 -#define FS_OFFSET_1400_NAND_MUTEX 0xF292F8 -#define FS_OFFSET_1400_ACTIVE_PARTITION 0xF29338 -#define FS_OFFSET_1400_SDMMC_DAS_HANDLE 0xDFE9C8 - -// NOPs -#define FS_OFFSET_1400_SD_DAS_INIT 0x27004 - -// Nintendo Paths -#define FS_OFFSET_1400_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006D9C0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007AC24, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x000813E8, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0009387C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1400_H__ diff --git a/emummc/source/FS/offsets/1400_exfat.h b/emummc/source/FS/offsets/1400_exfat.h deleted file mode 100644 index 3ce63e5bc0..0000000000 --- a/emummc/source/FS/offsets/1400_exfat.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_1400_EXFAT_H__ -#define __FS_1400_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_1400_EXFAT_SDMMC_ACCESSOR_GC 0x1952D0 -#define FS_OFFSET_1400_EXFAT_SDMMC_ACCESSOR_SD 0x1970E0 -#define FS_OFFSET_1400_EXFAT_SDMMC_ACCESSOR_NAND 0x195800 - -// Hooks -#define FS_OFFSET_1400_EXFAT_SDMMC_WRAPPER_READ 0x190E70 -#define FS_OFFSET_1400_EXFAT_SDMMC_WRAPPER_WRITE 0x190ED0 -#define FS_OFFSET_1400_EXFAT_RTLD 0x282B8 -#define FS_OFFSET_1400_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C))) - -#define FS_OFFSET_1400_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1B1110 - -// Misc funcs -#define FS_OFFSET_1400_EXFAT_LOCK_MUTEX 0x189D70 -#define FS_OFFSET_1400_EXFAT_UNLOCK_MUTEX 0x189DC0 - -#define FS_OFFSET_1400_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x190E20 -#define FS_OFFSET_1400_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x190E50 - -// Misc Data -#define FS_OFFSET_1400_EXFAT_SD_MUTEX 0x10123F0 -#define FS_OFFSET_1400_EXFAT_NAND_MUTEX 0x100D2F8 -#define FS_OFFSET_1400_EXFAT_ACTIVE_PARTITION 0x100D338 -#define FS_OFFSET_1400_EXFAT_SDMMC_DAS_HANDLE 0xE0B9C8 - -// NOPs -#define FS_OFFSET_1400_EXFAT_SD_DAS_INIT 0x27004 - -// Nintendo Paths -#define FS_OFFSET_1400_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0006D9C0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007AC24, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x000813E8, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0009387C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_1400_EXFAT_H__ diff --git a/emummc/source/FS/offsets/200.h b/emummc/source/FS/offsets/200.h deleted file mode 100644 index 589e25c331..0000000000 --- a/emummc/source/FS/offsets/200.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_200_H__ -#define __FS_200_H__ - -// Accessor vtable getters -#define FS_OFFSET_200_SDMMC_ACCESSOR_GC 0x78BAC -#define FS_OFFSET_200_SDMMC_ACCESSOR_SD 0x7894C -#define FS_OFFSET_200_SDMMC_ACCESSOR_NAND 0x784BC - -// Hooks -#define FS_OFFSET_200_SDMMC_WRAPPER_READ 0x73478 -#define FS_OFFSET_200_SDMMC_WRAPPER_WRITE 0x73538 -#define FS_OFFSET_200_RTLD 0x500 -#define FS_OFFSET_200_RTLD_DESTINATION 0x98 - -#define FS_OFFSET_200_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_200_LOCK_MUTEX 0x3264 -#define FS_OFFSET_200_UNLOCK_MUTEX 0x32D0 - -#define FS_OFFSET_200_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_200_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4 - -// Misc Data -#define FS_OFFSET_200_SD_MUTEX 0xE42268 -#define FS_OFFSET_200_NAND_MUTEX 0xE3CED0 -#define FS_OFFSET_200_ACTIVE_PARTITION 0xE3CF10 -#define FS_OFFSET_200_SDMMC_DAS_HANDLE 0xE3BDD0 - -// NOPs -#define FS_OFFSET_200_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_200_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x00033F08, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00035084, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 3, .adrp_offset = 0x0003537C, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_200_H__ diff --git a/emummc/source/FS/offsets/200_exfat.h b/emummc/source/FS/offsets/200_exfat.h deleted file mode 100644 index 946d4fbd90..0000000000 --- a/emummc/source/FS/offsets/200_exfat.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_200_EXFAT_H__ -#define __FS_200_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_200_EXFAT_SDMMC_ACCESSOR_GC 0x78BAC -#define FS_OFFSET_200_EXFAT_SDMMC_ACCESSOR_SD 0x7894C -#define FS_OFFSET_200_EXFAT_SDMMC_ACCESSOR_NAND 0x784BC - -// Hooks -#define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_READ 0x73478 -#define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_WRITE 0x73538 -#define FS_OFFSET_200_EXFAT_RTLD 0x500 -#define FS_OFFSET_200_EXFAT_RTLD_DESTINATION 0x98 - -#define FS_OFFSET_200_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_200_EXFAT_LOCK_MUTEX 0x3264 -#define FS_OFFSET_200_EXFAT_UNLOCK_MUTEX 0x32D0 - -#define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4 - -// Misc Data -#define FS_OFFSET_200_EXFAT_SD_MUTEX 0xF22268 -#define FS_OFFSET_200_EXFAT_NAND_MUTEX 0xF1CED0 -#define FS_OFFSET_200_EXFAT_ACTIVE_PARTITION 0xF1CF10 -#define FS_OFFSET_200_EXFAT_SDMMC_DAS_HANDLE 0xF1BDD0 - -// NOPs -#define FS_OFFSET_200_EXFAT_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_200_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x00033F08, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00035084, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 3, .adrp_offset = 0x0003537C, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_200_EXFAT_H__ diff --git a/emummc/source/FS/offsets/210.h b/emummc/source/FS/offsets/210.h deleted file mode 100644 index 20369f11c2..0000000000 --- a/emummc/source/FS/offsets/210.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_210_H__ -#define __FS_210_H__ - -// Accessor vtable getters -#define FS_OFFSET_210_SDMMC_ACCESSOR_GC 0x78F8C -#define FS_OFFSET_210_SDMMC_ACCESSOR_SD 0x78D2C -#define FS_OFFSET_210_SDMMC_ACCESSOR_NAND 0x7889C - -// Hooks -#define FS_OFFSET_210_SDMMC_WRAPPER_READ 0x73858 -#define FS_OFFSET_210_SDMMC_WRAPPER_WRITE 0x73918 -#define FS_OFFSET_210_RTLD 0x500 -#define FS_OFFSET_210_RTLD_DESTINATION 0x98 - -#define FS_OFFSET_210_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_210_LOCK_MUTEX 0x3264 -#define FS_OFFSET_210_UNLOCK_MUTEX 0x32D0 - -#define FS_OFFSET_210_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_210_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4 - -// Misc Data -#define FS_OFFSET_210_SD_MUTEX 0xE43268 -#define FS_OFFSET_210_NAND_MUTEX 0xE3DED0 -#define FS_OFFSET_210_ACTIVE_PARTITION 0xE3DF10 -#define FS_OFFSET_210_SDMMC_DAS_HANDLE 0xE3CDD0 - -// NOPs -#define FS_OFFSET_210_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_210_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x000342E0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0003545C, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 3, .adrp_offset = 0x00035754, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_210_H__ diff --git a/emummc/source/FS/offsets/210_exfat.h b/emummc/source/FS/offsets/210_exfat.h deleted file mode 100644 index 844338bc3e..0000000000 --- a/emummc/source/FS/offsets/210_exfat.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_210_EXFAT_H__ -#define __FS_210_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_210_EXFAT_SDMMC_ACCESSOR_GC 0x78F8C -#define FS_OFFSET_210_EXFAT_SDMMC_ACCESSOR_SD 0x78D2C -#define FS_OFFSET_210_EXFAT_SDMMC_ACCESSOR_NAND 0x7889C - -// Hooks -#define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_READ 0x73858 -#define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_WRITE 0x73918 -#define FS_OFFSET_210_EXFAT_RTLD 0x500 -#define FS_OFFSET_210_EXFAT_RTLD_DESTINATION 0x98 - -#define FS_OFFSET_210_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_210_EXFAT_LOCK_MUTEX 0x3264 -#define FS_OFFSET_210_EXFAT_UNLOCK_MUTEX 0x32D0 - -#define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4 - -// Misc Data -#define FS_OFFSET_210_EXFAT_SD_MUTEX 0xF22268 -#define FS_OFFSET_210_EXFAT_NAND_MUTEX 0xF1CED0 -#define FS_OFFSET_210_EXFAT_ACTIVE_PARTITION 0xF1CF10 -#define FS_OFFSET_210_EXFAT_SDMMC_DAS_HANDLE 0xF1BDD0 - -// NOPs -#define FS_OFFSET_210_EXFAT_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_210_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x000342E0, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0003545C, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 3, .adrp_offset = 0x00035754, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_210_EXFAT_H__ diff --git a/emummc/source/FS/offsets/300.h b/emummc/source/FS/offsets/300.h deleted file mode 100644 index 9908a215b3..0000000000 --- a/emummc/source/FS/offsets/300.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_300_H__ -#define __FS_300_H__ - -// Accessor vtable getters -#define FS_OFFSET_300_SDMMC_ACCESSOR_GC 0x8FAAC -#define FS_OFFSET_300_SDMMC_ACCESSOR_SD 0x8F84C -#define FS_OFFSET_300_SDMMC_ACCESSOR_NAND 0x8F3B8 - -// Hooks -#define FS_OFFSET_300_SDMMC_WRAPPER_READ 0x8A2F4 -#define FS_OFFSET_300_SDMMC_WRAPPER_WRITE 0x8A3B4 -#define FS_OFFSET_300_RTLD 0x4E8 -#define FS_OFFSET_300_RTLD_DESTINATION 0x8C - -#define FS_OFFSET_300_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_300_LOCK_MUTEX 0x35CC -#define FS_OFFSET_300_UNLOCK_MUTEX 0x3638 - -#define FS_OFFSET_300_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_300_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270 - -// Misc Data -#define FS_OFFSET_300_SD_MUTEX 0xE69268 -#define FS_OFFSET_300_NAND_MUTEX 0xE646F0 -#define FS_OFFSET_300_ACTIVE_PARTITION 0xE64730 -#define FS_OFFSET_300_SDMMC_DAS_HANDLE 0xE635A0 - -// NOPs -#define FS_OFFSET_300_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_300_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x000391F4, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0003A480, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 3, .adrp_offset = 0x0003A778, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_300_H__ diff --git a/emummc/source/FS/offsets/300_exfat.h b/emummc/source/FS/offsets/300_exfat.h deleted file mode 100644 index d230f52b64..0000000000 --- a/emummc/source/FS/offsets/300_exfat.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_300_EXFAT_H__ -#define __FS_300_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_300_EXFAT_SDMMC_ACCESSOR_GC 0x8FAAC -#define FS_OFFSET_300_EXFAT_SDMMC_ACCESSOR_SD 0x8F84C -#define FS_OFFSET_300_EXFAT_SDMMC_ACCESSOR_NAND 0x8F3B8 - -// Hooks -#define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_READ 0x8A2F4 -#define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_WRITE 0x8A3B4 -#define FS_OFFSET_300_EXFAT_RTLD 0x4E8 -#define FS_OFFSET_300_EXFAT_RTLD_DESTINATION 0x8C - -#define FS_OFFSET_300_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_300_EXFAT_LOCK_MUTEX 0x35CC -#define FS_OFFSET_300_EXFAT_UNLOCK_MUTEX 0x3638 - -#define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270 - -// Misc Data -#define FS_OFFSET_300_EXFAT_SD_MUTEX 0xF4C268 -#define FS_OFFSET_300_EXFAT_NAND_MUTEX 0xF476F0 -#define FS_OFFSET_300_EXFAT_ACTIVE_PARTITION 0xF47730 -#define FS_OFFSET_300_EXFAT_SDMMC_DAS_HANDLE 0xF465A0 - -// NOPs -#define FS_OFFSET_300_EXFAT_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_300_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x000391F4, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0003A480, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 3, .adrp_offset = 0x0003A778, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_300_EXFAT_H__ diff --git a/emummc/source/FS/offsets/301.h b/emummc/source/FS/offsets/301.h deleted file mode 100644 index 8dca17315f..0000000000 --- a/emummc/source/FS/offsets/301.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_301_H__ -#define __FS_301_H__ - -// Accessor vtable getters -#define FS_OFFSET_301_SDMMC_ACCESSOR_GC 0x8FB68 -#define FS_OFFSET_301_SDMMC_ACCESSOR_SD 0x8F908 -#define FS_OFFSET_301_SDMMC_ACCESSOR_NAND 0x8F474 - -// Hooks -#define FS_OFFSET_301_SDMMC_WRAPPER_READ 0x8A3B0 -#define FS_OFFSET_301_SDMMC_WRAPPER_WRITE 0x8A470 -#define FS_OFFSET_301_RTLD 0x4E8 -#define FS_OFFSET_301_RTLD_DESTINATION 0x8C - -#define FS_OFFSET_301_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_301_LOCK_MUTEX 0x3638 -#define FS_OFFSET_301_UNLOCK_MUTEX 0x36A4 - -#define FS_OFFSET_301_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_301_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C - -// Misc Data -#define FS_OFFSET_301_SD_MUTEX 0xE69268 -#define FS_OFFSET_301_NAND_MUTEX 0xE646F0 -#define FS_OFFSET_301_ACTIVE_PARTITION 0xE64730 -#define FS_OFFSET_301_SDMMC_DAS_HANDLE 0xE635A0 - -// NOPs -#define FS_OFFSET_301_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_301_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x00039260, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0003A4EC, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 3, .adrp_offset = 0x0003A7E4, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_301_H__ diff --git a/emummc/source/FS/offsets/301_exfat.h b/emummc/source/FS/offsets/301_exfat.h deleted file mode 100644 index 72f0f44992..0000000000 --- a/emummc/source/FS/offsets/301_exfat.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_301_EXFAT_H__ -#define __FS_301_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_301_EXFAT_SDMMC_ACCESSOR_GC 0x8FB68 -#define FS_OFFSET_301_EXFAT_SDMMC_ACCESSOR_SD 0x8F908 -#define FS_OFFSET_301_EXFAT_SDMMC_ACCESSOR_NAND 0x8F474 - -// Hooks -#define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_READ 0x8A3B0 -#define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_WRITE 0x8A470 -#define FS_OFFSET_301_EXFAT_RTLD 0x4E8 -#define FS_OFFSET_301_EXFAT_RTLD_DESTINATION 0x8C - -#define FS_OFFSET_301_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_301_EXFAT_LOCK_MUTEX 0x3638 -#define FS_OFFSET_301_EXFAT_UNLOCK_MUTEX 0x36A4 - -#define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C - -// Misc Data -#define FS_OFFSET_301_EXFAT_SD_MUTEX 0xF4C268 -#define FS_OFFSET_301_EXFAT_NAND_MUTEX 0xF476F0 -#define FS_OFFSET_301_EXFAT_ACTIVE_PARTITION 0xF47730 -#define FS_OFFSET_301_EXFAT_SDMMC_DAS_HANDLE 0xF465A0 - -// NOPs -#define FS_OFFSET_301_EXFAT_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_301_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x00039260, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x0003A4EC, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 3, .adrp_offset = 0x0003A7E4, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_301_EXFAT_H__ diff --git a/emummc/source/FS/offsets/400.h b/emummc/source/FS/offsets/400.h deleted file mode 100644 index fcd5ca927d..0000000000 --- a/emummc/source/FS/offsets/400.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_400_H__ -#define __FS_400_H__ - -// Accessor vtable getters -#define FS_OFFSET_400_SDMMC_ACCESSOR_GC 0xA3374 -#define FS_OFFSET_400_SDMMC_ACCESSOR_SD 0xA3114 -#define FS_OFFSET_400_SDMMC_ACCESSOR_NAND 0xA2C80 - -// Hooks -#define FS_OFFSET_400_SDMMC_WRAPPER_READ 0x9DBCC -#define FS_OFFSET_400_SDMMC_WRAPPER_WRITE 0x9DC8C -#define FS_OFFSET_400_RTLD 0x4DC -#define FS_OFFSET_400_RTLD_DESTINATION 0x98 - -#define FS_OFFSET_400_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_400_LOCK_MUTEX 0x39A0 -#define FS_OFFSET_400_UNLOCK_MUTEX 0x3A0C - -#define FS_OFFSET_400_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_400_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48 - -// Misc Data -#define FS_OFFSET_400_SD_MUTEX 0xE80268 -#define FS_OFFSET_400_NAND_MUTEX 0xE7BC60 -#define FS_OFFSET_400_ACTIVE_PARTITION 0xE7BCA0 -#define FS_OFFSET_400_SDMMC_DAS_HANDLE 0xE7ABF0 - -// NOPs -#define FS_OFFSET_400_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_400_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0002023C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00021BE8, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 3, .adrp_offset = 0x00021EC4, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_400_H__ diff --git a/emummc/source/FS/offsets/400_exfat.h b/emummc/source/FS/offsets/400_exfat.h deleted file mode 100644 index da1ac97dd0..0000000000 --- a/emummc/source/FS/offsets/400_exfat.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_400_EXFAT_H__ -#define __FS_400_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_400_EXFAT_SDMMC_ACCESSOR_GC 0xA3374 -#define FS_OFFSET_400_EXFAT_SDMMC_ACCESSOR_SD 0xA3114 -#define FS_OFFSET_400_EXFAT_SDMMC_ACCESSOR_NAND 0xA2C80 - -// Hooks -#define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_READ 0x9DBCC -#define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_WRITE 0x9DC8C -#define FS_OFFSET_400_EXFAT_RTLD 0x4DC -#define FS_OFFSET_400_EXFAT_RTLD_DESTINATION 0x98 - -#define FS_OFFSET_400_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_400_EXFAT_LOCK_MUTEX 0x39A0 -#define FS_OFFSET_400_EXFAT_UNLOCK_MUTEX 0x3A0C - -#define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48 - -// Misc Data -#define FS_OFFSET_400_EXFAT_SD_MUTEX 0xF63268 -#define FS_OFFSET_400_EXFAT_NAND_MUTEX 0xF5EC60 -#define FS_OFFSET_400_EXFAT_ACTIVE_PARTITION 0xF5ECA0 -#define FS_OFFSET_400_EXFAT_SDMMC_DAS_HANDLE 0xF5DBF0 - -// NOPs -#define FS_OFFSET_400_EXFAT_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_400_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0002023C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00021BE8, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 3, .adrp_offset = 0x00021EC4, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_400_EXFAT_H__ diff --git a/emummc/source/FS/offsets/410.h b/emummc/source/FS/offsets/410.h deleted file mode 100644 index 4d068e7134..0000000000 --- a/emummc/source/FS/offsets/410.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_410_H__ -#define __FS_410_H__ - -// Accessor vtable getters -#define FS_OFFSET_410_SDMMC_ACCESSOR_GC 0xA33D8 -#define FS_OFFSET_410_SDMMC_ACCESSOR_SD 0xA3178 -#define FS_OFFSET_410_SDMMC_ACCESSOR_NAND 0xA2CE4 - -// Hooks -#define FS_OFFSET_410_SDMMC_WRAPPER_READ 0x9DC30 -#define FS_OFFSET_410_SDMMC_WRAPPER_WRITE 0x9DCF0 -#define FS_OFFSET_410_RTLD 0x4DC -#define FS_OFFSET_410_RTLD_DESTINATION 0x98 - -#define FS_OFFSET_410_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_410_LOCK_MUTEX 0x39A0 -#define FS_OFFSET_410_UNLOCK_MUTEX 0x3A0C - -#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC - -// Misc Data -#define FS_OFFSET_410_SD_MUTEX 0xE80268 -#define FS_OFFSET_410_NAND_MUTEX 0xE7BC60 -#define FS_OFFSET_410_ACTIVE_PARTITION 0xE7BCA0 -#define FS_OFFSET_410_SDMMC_DAS_HANDLE 0xE7ABF0 - -// NOPs -#define FS_OFFSET_410_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_410_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0002023C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00021BE8, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 3, .adrp_offset = 0x00021EC4, .add_rel_offset = 0x0000000C}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_410_H__ diff --git a/emummc/source/FS/offsets/410_exfat.h b/emummc/source/FS/offsets/410_exfat.h deleted file mode 100644 index cf66c23d07..0000000000 --- a/emummc/source/FS/offsets/410_exfat.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_410_EXFAT_H__ -#define __FS_410_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_410_EXFAT_SDMMC_ACCESSOR_GC 0xA33D8 -#define FS_OFFSET_410_EXFAT_SDMMC_ACCESSOR_SD 0xA3178 -#define FS_OFFSET_410_EXFAT_SDMMC_ACCESSOR_NAND 0xA2CE4 - -// Hooks -#define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_READ 0x9DC30 -#define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_WRITE 0x9DCF0 -#define FS_OFFSET_410_EXFAT_RTLD 0x4DC -#define FS_OFFSET_410_EXFAT_RTLD_DESTINATION 0x98 - -#define FS_OFFSET_410_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_410_EXFAT_LOCK_MUTEX 0x39A0 -#define FS_OFFSET_410_EXFAT_UNLOCK_MUTEX 0x3A0C - -#define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC - -// Misc Data -#define FS_OFFSET_410_EXFAT_SD_MUTEX 0xF63268 -#define FS_OFFSET_410_EXFAT_NAND_MUTEX 0xF5EC60 -#define FS_OFFSET_410_EXFAT_ACTIVE_PARTITION 0xF5ECA0 -#define FS_OFFSET_410_EXFAT_SDMMC_DAS_HANDLE 0xF5DBF0 - -// NOPs -#define FS_OFFSET_410_EXFAT_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_410_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0002023C, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x00021BE8, .add_rel_offset = 12}, \ - {.opcode_reg = 3, .adrp_offset = 0x00021EC4, .add_rel_offset = 12}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_410_EXFAT_H__ diff --git a/emummc/source/FS/offsets/500.h b/emummc/source/FS/offsets/500.h deleted file mode 100644 index 630a3317d5..0000000000 --- a/emummc/source/FS/offsets/500.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_500_H__ -#define __FS_500_H__ - -// Accessor vtable getters -#define FS_OFFSET_500_SDMMC_ACCESSOR_GC 0xCF250 -#define FS_OFFSET_500_SDMMC_ACCESSOR_SD 0xCEFD0 -#define FS_OFFSET_500_SDMMC_ACCESSOR_NAND 0xCE990 - -// Hooks -#define FS_OFFSET_500_SDMMC_WRAPPER_READ 0xC9420 -#define FS_OFFSET_500_SDMMC_WRAPPER_WRITE 0xC9500 -#define FS_OFFSET_500_RTLD 0x584 -#define FS_OFFSET_500_RTLD_DESTINATION 0x94 - -#define FS_OFFSET_500_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_500_LOCK_MUTEX 0x4080 -#define FS_OFFSET_500_UNLOCK_MUTEX 0x40D0 - -#define FS_OFFSET_500_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_500_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380 - -// Misc Data -#define FS_OFFSET_500_SD_MUTEX 0xEC3268 -#define FS_OFFSET_500_NAND_MUTEX 0xEBDE58 -#define FS_OFFSET_500_ACTIVE_PARTITION 0xEBDE98 -#define FS_OFFSET_500_SDMMC_DAS_HANDLE 0xEBCE30 - -// NOPs -#define FS_OFFSET_500_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_500_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x00028980, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0002ACE4, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0002B220, .add_rel_offset = 4}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_500_H__ diff --git a/emummc/source/FS/offsets/500_exfat.h b/emummc/source/FS/offsets/500_exfat.h deleted file mode 100644 index df239f0487..0000000000 --- a/emummc/source/FS/offsets/500_exfat.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_500_EXFAT_H__ -#define __FS_500_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_500_EXFAT_SDMMC_ACCESSOR_GC 0xCF250 -#define FS_OFFSET_500_EXFAT_SDMMC_ACCESSOR_SD 0xCEFD0 -#define FS_OFFSET_500_EXFAT_SDMMC_ACCESSOR_NAND 0xCE990 - -// Hooks -#define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_READ 0xC9420 -#define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_WRITE 0xC9500 -#define FS_OFFSET_500_EXFAT_RTLD 0x584 -#define FS_OFFSET_500_EXFAT_RTLD_DESTINATION 0x94 - -#define FS_OFFSET_500_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_500_EXFAT_LOCK_MUTEX 0x4080 -#define FS_OFFSET_500_EXFAT_UNLOCK_MUTEX 0x40D0 - -#define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380 - -// Misc Data -#define FS_OFFSET_500_EXFAT_SD_MUTEX 0xFA8268 -#define FS_OFFSET_500_EXFAT_NAND_MUTEX 0xFA2E58 -#define FS_OFFSET_500_EXFAT_ACTIVE_PARTITION 0xFA2E98 -#define FS_OFFSET_500_EXFAT_SDMMC_DAS_HANDLE 0xFA1E30 - -// NOPs -#define FS_OFFSET_500_EXFAT_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_500_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x00028980, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0002ACE4, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0002B220, .add_rel_offset = 4}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_500_EXFAT_H__ diff --git a/emummc/source/FS/offsets/510.h b/emummc/source/FS/offsets/510.h deleted file mode 100644 index e867f190b4..0000000000 --- a/emummc/source/FS/offsets/510.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_510_H__ -#define __FS_510_H__ - -// Accessor vtable getters -#define FS_OFFSET_510_SDMMC_ACCESSOR_GC 0xCF620 -#define FS_OFFSET_510_SDMMC_ACCESSOR_SD 0xCF3A0 -#define FS_OFFSET_510_SDMMC_ACCESSOR_NAND 0xCED60 - -// Hooks -#define FS_OFFSET_510_SDMMC_WRAPPER_READ 0xC97F0 -#define FS_OFFSET_510_SDMMC_WRAPPER_WRITE 0xC98D0 -#define FS_OFFSET_510_RTLD 0x584 -#define FS_OFFSET_510_RTLD_DESTINATION 0x94 - -#define FS_OFFSET_510_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_510_LOCK_MUTEX 0x4080 -#define FS_OFFSET_510_UNLOCK_MUTEX 0x40D0 - -#define FS_OFFSET_510_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_510_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750 - -// Misc Data -#define FS_OFFSET_510_SD_MUTEX 0xEC4268 -#define FS_OFFSET_510_NAND_MUTEX 0xEBEE58 -#define FS_OFFSET_510_ACTIVE_PARTITION 0xEBEE98 -#define FS_OFFSET_510_SDMMC_DAS_HANDLE 0xEBDE30 - -// NOPs -#define FS_OFFSET_510_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_510_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x000289B0, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0002AD14, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0002B250, .add_rel_offset = 4}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_510_H__ diff --git a/emummc/source/FS/offsets/510_exfat.h b/emummc/source/FS/offsets/510_exfat.h deleted file mode 100644 index 8ce184f2a0..0000000000 --- a/emummc/source/FS/offsets/510_exfat.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_510_EXFAT_H__ -#define __FS_510_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_510_EXFAT_SDMMC_ACCESSOR_GC 0xCF620 -#define FS_OFFSET_510_EXFAT_SDMMC_ACCESSOR_SD 0xCF3A0 -#define FS_OFFSET_510_EXFAT_SDMMC_ACCESSOR_NAND 0xCED60 - -// Hooks -#define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_READ 0xC97F0 -#define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_WRITE 0xC98D0 -#define FS_OFFSET_510_EXFAT_RTLD 0x584 -#define FS_OFFSET_510_EXFAT_RTLD_DESTINATION 0x94 - -#define FS_OFFSET_510_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_510_EXFAT_LOCK_MUTEX 0x4080 -#define FS_OFFSET_510_EXFAT_UNLOCK_MUTEX 0x40D0 - -#define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750 - -// Misc Data -#define FS_OFFSET_510_EXFAT_SD_MUTEX 0xFA9268 -#define FS_OFFSET_510_EXFAT_NAND_MUTEX 0xFA3E58 -#define FS_OFFSET_510_EXFAT_ACTIVE_PARTITION 0xFA3E98 -#define FS_OFFSET_510_EXFAT_SDMMC_DAS_HANDLE 0xFA2E30 - -// NOPs -#define FS_OFFSET_510_EXFAT_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_510_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x000289B0, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0002AD14, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0002B250, .add_rel_offset = 4}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_510_EXFAT_H__ diff --git a/emummc/source/FS/offsets/600.h b/emummc/source/FS/offsets/600.h deleted file mode 100644 index a0835a0dff..0000000000 --- a/emummc/source/FS/offsets/600.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_600_H__ -#define __FS_600_H__ - -// Accessor vtable getters -#define FS_OFFSET_600_SDMMC_ACCESSOR_GC 0x153780 -#define FS_OFFSET_600_SDMMC_ACCESSOR_SD 0x1534F0 -#define FS_OFFSET_600_SDMMC_ACCESSOR_NAND 0x14F990 - -// Hooks -#define FS_OFFSET_600_SDMMC_WRAPPER_READ 0x1485A0 -#define FS_OFFSET_600_SDMMC_WRAPPER_WRITE 0x148680 -#define FS_OFFSET_600_RTLD 0x5B0 -#define FS_OFFSET_600_RTLD_DESTINATION 0x98 - -#define FS_OFFSET_600_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_600_LOCK_MUTEX 0x1412C0 -#define FS_OFFSET_600_UNLOCK_MUTEX 0x141310 - -#define FS_OFFSET_600_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_600_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x148500 - -// Misc Data -#define FS_OFFSET_600_SD_MUTEX 0xF06268 -#define FS_OFFSET_600_NAND_MUTEX 0xF01BA0 -#define FS_OFFSET_600_ACTIVE_PARTITION 0xF01BE0 -#define FS_OFFSET_600_SDMMC_DAS_HANDLE 0xE01670 - -// NOPs -#define FS_OFFSET_600_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_600_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x000790DC, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007A924, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007AB18, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007AEF4, .add_rel_offset = 4}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0} \ -} - -#endif // __FS_600_H__ diff --git a/emummc/source/FS/offsets/600_exfat.h b/emummc/source/FS/offsets/600_exfat.h deleted file mode 100644 index 0600b0163a..0000000000 --- a/emummc/source/FS/offsets/600_exfat.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_600_EXFAT_H__ -#define __FS_600_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_600_EXFAT_SDMMC_ACCESSOR_GC 0x15EE80 -#define FS_OFFSET_600_EXFAT_SDMMC_ACCESSOR_SD 0x15EBF0 -#define FS_OFFSET_600_EXFAT_SDMMC_ACCESSOR_NAND 0x15B090 - -// Hooks -#define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_READ 0x153CA0 -#define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_WRITE 0x153D80 -#define FS_OFFSET_600_EXFAT_RTLD 0x5B0 -#define FS_OFFSET_600_EXFAT_RTLD_DESTINATION 0x98 - -#define FS_OFFSET_600_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_600_EXFAT_LOCK_MUTEX 0x14C9C0 -#define FS_OFFSET_600_EXFAT_UNLOCK_MUTEX 0x14CA10 - -#define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x153C00 - -// Misc Data -#define FS_OFFSET_600_EXFAT_SD_MUTEX 0xFEB268 -#define FS_OFFSET_600_EXFAT_NAND_MUTEX 0xFE6BA0 -#define FS_OFFSET_600_EXFAT_ACTIVE_PARTITION 0xFE6BE0 -#define FS_OFFSET_600_EXFAT_SDMMC_DAS_HANDLE 0xEE6670 - -// NOPs -#define FS_OFFSET_600_EXFAT_SD_DAS_INIT 0x0 - -// Nintendo Paths -#define FS_OFFSET_600_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x000847DC, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x00086024, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x00086218, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x000865F4, .add_rel_offset = 4}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0} \ -} - -#endif // __FS_600_EXFAT_H__ diff --git a/emummc/source/FS/offsets/700.h b/emummc/source/FS/offsets/700.h deleted file mode 100644 index 9281cb905a..0000000000 --- a/emummc/source/FS/offsets/700.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_700_H__ -#define __FS_700_H__ - -// Accessor vtable getters -#define FS_OFFSET_700_SDMMC_ACCESSOR_GC 0x15BD90 -#define FS_OFFSET_700_SDMMC_ACCESSOR_SD 0x15BB00 -#define FS_OFFSET_700_SDMMC_ACCESSOR_NAND 0x157FF0 - -// Hooks -#define FS_OFFSET_700_SDMMC_WRAPPER_READ 0x14FDF0 -#define FS_OFFSET_700_SDMMC_WRAPPER_WRITE 0x14FED0 -#define FS_OFFSET_700_RTLD 0x5B4 -#define FS_OFFSET_700_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_700_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_700_LOCK_MUTEX 0x148A90 -#define FS_OFFSET_700_UNLOCK_MUTEX 0x148AE0 - -#define FS_OFFSET_700_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_700_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14FD50 - -// Misc Data -#define FS_OFFSET_700_SD_MUTEX 0xF123E8 -#define FS_OFFSET_700_NAND_MUTEX 0xF0DBE8 -#define FS_OFFSET_700_ACTIVE_PARTITION 0xF0DC28 -#define FS_OFFSET_700_SDMMC_DAS_HANDLE 0xE0E7A0 - -// NOPs -#define FS_OFFSET_700_SD_DAS_INIT 0x85FE8 - -// Nintendo Paths -#define FS_OFFSET_700_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0007DA90, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007F344, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007F538, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0007F914, .add_rel_offset = 4}, \ - {.opcode_reg = 4, .adrp_offset = 0x0007FAD8, .add_rel_offset = 4}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_700_H__ diff --git a/emummc/source/FS/offsets/700_exfat.h b/emummc/source/FS/offsets/700_exfat.h deleted file mode 100644 index 4f1ef13086..0000000000 --- a/emummc/source/FS/offsets/700_exfat.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_700_EXFAT_H__ -#define __FS_700_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_700_EXFAT_SDMMC_ACCESSOR_GC 0x167340 -#define FS_OFFSET_700_EXFAT_SDMMC_ACCESSOR_SD 0x1670B0 -#define FS_OFFSET_700_EXFAT_SDMMC_ACCESSOR_NAND 0x1635A0 - -// Hooks -#define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_READ 0x15B3A0 -#define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_WRITE 0x15B480 -#define FS_OFFSET_700_EXFAT_RTLD 0x5B4 -#define FS_OFFSET_700_EXFAT_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_700_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x0 - -// Misc funcs -#define FS_OFFSET_700_EXFAT_LOCK_MUTEX 0x154040 -#define FS_OFFSET_700_EXFAT_UNLOCK_MUTEX 0x154090 - -#define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15B300 - -// Misc Data -#define FS_OFFSET_700_EXFAT_SD_MUTEX 0xFF73E8 -#define FS_OFFSET_700_EXFAT_NAND_MUTEX 0xFF2BE8 -#define FS_OFFSET_700_EXFAT_ACTIVE_PARTITION 0xFF2C28 -#define FS_OFFSET_700_EXFAT_SDMMC_DAS_HANDLE 0xEF3A00 - -// NOPs -#define FS_OFFSET_700_EXFAT_SD_DAS_INIT 0x91598 - -// Nintendo Paths -#define FS_OFFSET_700_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x00089040, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0008A8F4, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0008AAE8, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0008AEC4, .add_rel_offset = 4}, \ - {.opcode_reg = 4, .adrp_offset = 0x0008B088, .add_rel_offset = 4}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_700_EXFAT_H__ diff --git a/emummc/source/FS/offsets/800.h b/emummc/source/FS/offsets/800.h deleted file mode 100644 index 2eef520cf8..0000000000 --- a/emummc/source/FS/offsets/800.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_800_H__ -#define __FS_800_H__ - -// Accessor vtable getters -#define FS_OFFSET_800_SDMMC_ACCESSOR_GC 0x15EA20 -#define FS_OFFSET_800_SDMMC_ACCESSOR_SD 0x15E790 -#define FS_OFFSET_800_SDMMC_ACCESSOR_NAND 0x15AC80 - -// Hooks -#define FS_OFFSET_800_SDMMC_WRAPPER_READ 0x152A80 -#define FS_OFFSET_800_SDMMC_WRAPPER_WRITE 0x152B60 -#define FS_OFFSET_800_RTLD 0x5B4 -#define FS_OFFSET_800_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_800_CLKRST_SET_MIN_V_CLK_RATE 0x16F370 - -// Misc funcs -#define FS_OFFSET_800_LOCK_MUTEX 0x14B6D0 -#define FS_OFFSET_800_UNLOCK_MUTEX 0x14B720 - -#define FS_OFFSET_800_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_800_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0 - -// Misc Data -#define FS_OFFSET_800_SD_MUTEX 0xF1A3E8 -#define FS_OFFSET_800_NAND_MUTEX 0xF15BE8 -#define FS_OFFSET_800_ACTIVE_PARTITION 0xF15C28 -#define FS_OFFSET_800_SDMMC_DAS_HANDLE 0xE167C0 - -// NOPs -#define FS_OFFSET_800_SD_DAS_INIT 0x87D58 - -// Nintendo Paths -#define FS_OFFSET_800_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0007F5F0, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081084, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081278, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081654, .add_rel_offset = 4}, \ - {.opcode_reg = 4, .adrp_offset = 0x00081818, .add_rel_offset = 4}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0} \ -} - -#endif // __FS_800_H__ diff --git a/emummc/source/FS/offsets/800_exfat.h b/emummc/source/FS/offsets/800_exfat.h deleted file mode 100644 index 786c40e5b4..0000000000 --- a/emummc/source/FS/offsets/800_exfat.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_800_EXFAT_H__ -#define __FS_800_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_800_EXFAT_SDMMC_ACCESSOR_GC 0x169FD0 -#define FS_OFFSET_800_EXFAT_SDMMC_ACCESSOR_SD 0x169D40 -#define FS_OFFSET_800_EXFAT_SDMMC_ACCESSOR_NAND 0x166230 - -// Hooks -#define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_READ 0x15E030 -#define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_WRITE 0x15E110 -#define FS_OFFSET_800_EXFAT_RTLD 0x5B4 -#define FS_OFFSET_800_EXFAT_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_800_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x17A920 - -// Misc funcs -#define FS_OFFSET_800_EXFAT_LOCK_MUTEX 0x156C80 -#define FS_OFFSET_800_EXFAT_UNLOCK_MUTEX 0x156CD0 - -#define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90 - -// Misc Data -#define FS_OFFSET_800_EXFAT_SD_MUTEX 0xFFE3E8 -#define FS_OFFSET_800_EXFAT_NAND_MUTEX 0xFF9BE8 -#define FS_OFFSET_800_EXFAT_ACTIVE_PARTITION 0xFF9C28 -#define FS_OFFSET_800_EXFAT_SDMMC_DAS_HANDLE 0xEFAA20 - -// NOPs -#define FS_OFFSET_800_EXFAT_SD_DAS_INIT 0x93308 - -// Nintendo Paths -#define FS_OFFSET_800_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0008ABA0, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0008C634, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0008C828, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0008CC04, .add_rel_offset = 4}, \ - {.opcode_reg = 4, .adrp_offset = 0x0008CDC8, .add_rel_offset = 4}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0} \ -} - -#endif // __FS_800_EXFAT_H__ diff --git a/emummc/source/FS/offsets/810.h b/emummc/source/FS/offsets/810.h deleted file mode 100644 index 7a6dd28551..0000000000 --- a/emummc/source/FS/offsets/810.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_810_H__ -#define __FS_810_H__ - -// Accessor vtable getters -#define FS_OFFSET_810_SDMMC_ACCESSOR_GC 0x15EA20 -#define FS_OFFSET_810_SDMMC_ACCESSOR_SD 0x15E790 -#define FS_OFFSET_810_SDMMC_ACCESSOR_NAND 0x15AC80 - -// Hooks -#define FS_OFFSET_810_SDMMC_WRAPPER_READ 0x152A80 -#define FS_OFFSET_810_SDMMC_WRAPPER_WRITE 0x152B60 -#define FS_OFFSET_810_RTLD 0x5B4 -#define FS_OFFSET_810_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_810_CLKRST_SET_MIN_V_CLK_RATE 0x16F370 - -// Misc funcs -#define FS_OFFSET_810_LOCK_MUTEX 0x14B6D0 -#define FS_OFFSET_810_UNLOCK_MUTEX 0x14B720 - -#define FS_OFFSET_810_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_810_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0 - -// Misc Data -#define FS_OFFSET_810_SD_MUTEX 0xF1A3E8 -#define FS_OFFSET_810_NAND_MUTEX 0xF15BE8 -#define FS_OFFSET_810_ACTIVE_PARTITION 0xF15C28 -#define FS_OFFSET_810_SDMMC_DAS_HANDLE 0xE167C0 - -// NOPs -#define FS_OFFSET_810_SD_DAS_INIT 0x87D58 - -// Nintendo Paths -#define FS_OFFSET_810_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0007F5F0, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081084, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081278, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081654, .add_rel_offset = 4}, \ - {.opcode_reg = 4, .adrp_offset = 0x00081818, .add_rel_offset = 4}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0} \ -} - -#endif // __FS_810_H__ diff --git a/emummc/source/FS/offsets/810_exfat.h b/emummc/source/FS/offsets/810_exfat.h deleted file mode 100644 index 47c425ff0c..0000000000 --- a/emummc/source/FS/offsets/810_exfat.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_810_EXFAT_H__ -#define __FS_810_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_810_EXFAT_SDMMC_ACCESSOR_GC 0x169FD0 -#define FS_OFFSET_810_EXFAT_SDMMC_ACCESSOR_SD 0x169D40 -#define FS_OFFSET_810_EXFAT_SDMMC_ACCESSOR_NAND 0x166230 - -// Hooks -#define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_READ 0x15E030 -#define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_WRITE 0x15E110 -#define FS_OFFSET_810_EXFAT_RTLD 0x5B4 -#define FS_OFFSET_810_EXFAT_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_810_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x17A920 - -// Misc funcs -#define FS_OFFSET_810_EXFAT_LOCK_MUTEX 0x156C80 -#define FS_OFFSET_810_EXFAT_UNLOCK_MUTEX 0x156CD0 - -#define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90 - -// Misc Data -#define FS_OFFSET_810_EXFAT_SD_MUTEX 0xFFE3E8 -#define FS_OFFSET_810_EXFAT_NAND_MUTEX 0xFF9BE8 -#define FS_OFFSET_810_EXFAT_ACTIVE_PARTITION 0xFF9C28 -#define FS_OFFSET_810_EXFAT_SDMMC_DAS_HANDLE 0xEFAA20 - -// NOPs -#define FS_OFFSET_810_EXFAT_SD_DAS_INIT 0x93308 - -// Nintendo Paths -#define FS_OFFSET_810_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x0008ABA0, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0008C634, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0008C828, .add_rel_offset = 4}, \ - {.opcode_reg = 3, .adrp_offset = 0x0008CC04, .add_rel_offset = 4}, \ - {.opcode_reg = 4, .adrp_offset = 0x0008CDC8, .add_rel_offset = 4}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0} \ -} - -#endif // __FS_810_EXFAT_H__ diff --git a/emummc/source/FS/offsets/900.h b/emummc/source/FS/offsets/900.h deleted file mode 100644 index c390ec8284..0000000000 --- a/emummc/source/FS/offsets/900.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_900_H__ -#define __FS_900_H__ - -// Accessor vtable getters -#define FS_OFFSET_900_SDMMC_ACCESSOR_GC 0x1430F0 -#define FS_OFFSET_900_SDMMC_ACCESSOR_SD 0x141200 -#define FS_OFFSET_900_SDMMC_ACCESSOR_NAND 0x13C080 - -// Hooks -#define FS_OFFSET_900_SDMMC_WRAPPER_READ 0x1377E0 -#define FS_OFFSET_900_SDMMC_WRAPPER_WRITE 0x1378C0 -#define FS_OFFSET_900_RTLD 0x454 -#define FS_OFFSET_900_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_900_CLKRST_SET_MIN_V_CLK_RATE 0x136A00 - -// Misc funcs -#define FS_OFFSET_900_LOCK_MUTEX 0x25280 -#define FS_OFFSET_900_UNLOCK_MUTEX 0x252D0 - -#define FS_OFFSET_900_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_900_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740 - -// Misc Data -#define FS_OFFSET_900_SD_MUTEX 0xE1D3E8 -#define FS_OFFSET_900_NAND_MUTEX 0xE18258 -#define FS_OFFSET_900_ACTIVE_PARTITION 0xE18298 -#define FS_OFFSET_900_SDMMC_DAS_HANDLE 0xDFEFA0 - -// NOPs -#define FS_OFFSET_900_SD_DAS_INIT 0x1472BC - -// Nintendo Paths -#define FS_OFFSET_900_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x00068A60, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00070A40, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081CB4, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081EF4, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0008211C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_900_H__ diff --git a/emummc/source/FS/offsets/900_exfat.h b/emummc/source/FS/offsets/900_exfat.h deleted file mode 100644 index 184d7d0909..0000000000 --- a/emummc/source/FS/offsets/900_exfat.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_900_EXFAT_H__ -#define __FS_900_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_900_EXFAT_SDMMC_ACCESSOR_GC 0x1430F0 -#define FS_OFFSET_900_EXFAT_SDMMC_ACCESSOR_SD 0x141200 -#define FS_OFFSET_900_EXFAT_SDMMC_ACCESSOR_NAND 0x13C080 - -// Hooks -#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_READ 0x1377E0 -#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_WRITE 0x1378C0 -#define FS_OFFSET_900_EXFAT_RTLD 0x454 -#define FS_OFFSET_900_EXFAT_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_900_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x136A00 - -// Misc funcs -#define FS_OFFSET_900_EXFAT_LOCK_MUTEX 0x25280 -#define FS_OFFSET_900_EXFAT_UNLOCK_MUTEX 0x252D0 - -#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740 - -// Misc Data -#define FS_OFFSET_900_EXFAT_SD_MUTEX 0xE2B3E8 -#define FS_OFFSET_900_EXFAT_NAND_MUTEX 0xE26258 -#define FS_OFFSET_900_EXFAT_ACTIVE_PARTITION 0xE26298 -#define FS_OFFSET_900_EXFAT_SDMMC_DAS_HANDLE 0xE0CFA0 - -// NOPs -#define FS_OFFSET_900_EXFAT_SD_DAS_INIT 0x1472BC - -// Nintendo Paths -#define FS_OFFSET_900_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x00068A60, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00070A40, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081CB4, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081EF4, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0008211C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_900_EXFAT_H__ diff --git a/emummc/source/FS/offsets/910.h b/emummc/source/FS/offsets/910.h deleted file mode 100644 index 65aded2deb..0000000000 --- a/emummc/source/FS/offsets/910.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_910_H__ -#define __FS_910_H__ - -// Accessor vtable getters -#define FS_OFFSET_910_SDMMC_ACCESSOR_GC 0x143100 -#define FS_OFFSET_910_SDMMC_ACCESSOR_SD 0x141210 -#define FS_OFFSET_910_SDMMC_ACCESSOR_NAND 0x13C090 - -// Hooks -#define FS_OFFSET_910_SDMMC_WRAPPER_READ 0x1377F0 -#define FS_OFFSET_910_SDMMC_WRAPPER_WRITE 0x1378D0 -#define FS_OFFSET_910_RTLD 0x454 -#define FS_OFFSET_910_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_910_CLKRST_SET_MIN_V_CLK_RATE 0x136A10 - -// Misc funcs -#define FS_OFFSET_910_LOCK_MUTEX 0x25280 -#define FS_OFFSET_910_UNLOCK_MUTEX 0x252D0 - -#define FS_OFFSET_910_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_910_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137750 - -// Misc Data -#define FS_OFFSET_910_SD_MUTEX 0xE1D3E8 -#define FS_OFFSET_910_NAND_MUTEX 0xE18258 -#define FS_OFFSET_910_ACTIVE_PARTITION 0xE18298 -#define FS_OFFSET_910_SDMMC_DAS_HANDLE 0xDFEFA0 - -// NOPs -#define FS_OFFSET_910_SD_DAS_INIT 0x1472CC - -// Nintendo Paths -#define FS_OFFSET_910_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x00068A70, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00070A50, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081CC4, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081F04, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0008212C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_910_H__ diff --git a/emummc/source/FS/offsets/910_exfat.h b/emummc/source/FS/offsets/910_exfat.h deleted file mode 100644 index fd59d1badf..0000000000 --- a/emummc/source/FS/offsets/910_exfat.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef __FS_910_EXFAT_H__ -#define __FS_910_EXFAT_H__ - -// Accessor vtable getters -#define FS_OFFSET_910_EXFAT_SDMMC_ACCESSOR_GC 0x143100 -#define FS_OFFSET_910_EXFAT_SDMMC_ACCESSOR_SD 0x141210 -#define FS_OFFSET_910_EXFAT_SDMMC_ACCESSOR_NAND 0x13C090 - -// Hooks -#define FS_OFFSET_910_EXFAT_SDMMC_WRAPPER_READ 0x1377F0 -#define FS_OFFSET_910_EXFAT_SDMMC_WRAPPER_WRITE 0x1378D0 -#define FS_OFFSET_910_EXFAT_RTLD 0x454 -#define FS_OFFSET_910_EXFAT_RTLD_DESTINATION 0x9C - -#define FS_OFFSET_910_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x136A10 - -// Misc funcs -#define FS_OFFSET_910_EXFAT_LOCK_MUTEX 0x25280 -#define FS_OFFSET_910_EXFAT_UNLOCK_MUTEX 0x252D0 - -#define FS_OFFSET_910_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0 -#define FS_OFFSET_910_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137750 - -// Misc Data -#define FS_OFFSET_910_EXFAT_SD_MUTEX 0xE2B3E8 -#define FS_OFFSET_910_EXFAT_NAND_MUTEX 0xE26258 -#define FS_OFFSET_910_EXFAT_ACTIVE_PARTITION 0xE26298 -#define FS_OFFSET_910_EXFAT_SDMMC_DAS_HANDLE 0xE0CFA0 - -// NOPs -#define FS_OFFSET_910_EXFAT_SD_DAS_INIT 0x1472CC - -// Nintendo Paths -#define FS_OFFSET_910_EXFAT_NINTENDO_PATHS \ -{ \ - {.opcode_reg = 3, .adrp_offset = 0x00068A70, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00070A50, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081CC4, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 3, .adrp_offset = 0x00081F04, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 4, .adrp_offset = 0x0008212C, .add_rel_offset = 0x00000004}, \ - {.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \ -} - -#endif // __FS_910_EXFAT_H__ diff --git a/emummc/source/emmc/mmc.h b/emummc/source/emmc/mmc.h deleted file mode 100644 index efa9e1075e..0000000000 --- a/emummc/source/emmc/mmc.h +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Header for MultiMediaCard (MMC) - * - * Copyright 2002 Hewlett-Packard Company - * - * Use consistent with the GNU GPL is permitted, - * provided that this copyright notice is - * preserved in its entirety in all copies and derived works. - * - * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, - * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS - * FITNESS FOR ANY PARTICULAR PURPOSE. - * - * Many thanks to Alessandro Rubini and Jonathan Corbet! - * - * Based strongly on code by: - * - * Author: Yong-iL Joh - * - * Author: Andrew Christian - * 15 May 2002 - */ - -#ifndef LINUX_MMC_MMC_H -#define LINUX_MMC_MMC_H - -/* Standard MMC commands (4.1) type argument response */ -/* class 1 */ -#define MMC_GO_IDLE_STATE 0 /* bc */ -#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */ -#define MMC_ALL_SEND_CID 2 /* bcr R2 */ -#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ -#define MMC_SET_DSR 4 /* bc [31:16] RCA */ -#define MMC_SLEEP_AWAKE 5 /* ac [31:16] RCA 15:flg R1b */ -#define MMC_SWITCH 6 /* ac [31:0] See below R1b */ -#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ -#define MMC_SEND_EXT_CSD 8 /* adtc R1 */ -#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */ -#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */ -#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ -#define MMC_STOP_TRANSMISSION 12 /* ac R1b */ -#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */ -#define MMC_BUS_TEST_R 14 /* adtc R1 */ -#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */ -#define MMC_BUS_TEST_W 19 /* adtc R1 */ -#define MMC_SPI_READ_OCR 58 /* spi spi_R3 */ -#define MMC_SPI_CRC_ON_OFF 59 /* spi [0:0] flag spi_R1 */ - -/* class 2 */ -#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */ -#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ -#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ -#define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */ -#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */ - -/* class 3 */ -#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ - -/* class 4 */ -#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */ -#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */ -#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */ -#define MMC_PROGRAM_CID 26 /* adtc R1 */ -#define MMC_PROGRAM_CSD 27 /* adtc R1 */ - -/* class 6 */ -#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */ -#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */ -#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */ - -/* class 5 */ -#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */ -#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */ -#define MMC_ERASE 38 /* ac R1b */ - -/* class 9 */ -#define MMC_FAST_IO 39 /* ac R4 */ -#define MMC_GO_IRQ_STATE 40 /* bcr R5 */ - -/* class 7 */ -#define MMC_LOCK_UNLOCK 42 /* adtc R1b */ - -/* class 8 */ -#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ -#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */ - -/* class 11 */ -#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */ -#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */ -#define MMC_EXECUTE_READ_TASK 46 /* adtc [20:16] task id R1 */ -#define MMC_EXECUTE_WRITE_TASK 47 /* adtc [20:16] task id R1 */ -#define MMC_CMDQ_TASK_MGMT 48 /* ac [20:16] task id R1b */ - -/* -* MMC_SWITCH argument format: -* -* [31:26] Always 0 -* [25:24] Access Mode -* [23:16] Location of target Byte in EXT_CSD -* [15:08] Value Byte -* [07:03] Always 0 -* [02:00] Command Set -*/ - -/* -MMC status in R1, for native mode (SPI bits are different) -Type -e : error bit -s : status bit -r : detected and set for the actual command response -x : detected and set during command execution. the host must poll -the card by sending status command in order to read these bits. -Clear condition -a : according to the card state -b : always related to the previous command. Reception of -a valid command will clear it (with a delay of one command) -c : clear by read -*/ - -#define R1_OUT_OF_RANGE (1 << 31) /* er, c */ -#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ -#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ -#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ -#define R1_ERASE_PARAM (1 << 27) /* ex, c */ -#define R1_WP_VIOLATION (1 << 26) /* erx, c */ -#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ -#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ -#define R1_COM_CRC_ERROR (1 << 23) /* er, b */ -#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ -#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ -#define R1_CC_ERROR (1 << 20) /* erx, c */ -#define R1_ERROR (1 << 19) /* erx, c */ -#define R1_UNDERRUN (1 << 18) /* ex, c */ -#define R1_OVERRUN (1 << 17) /* ex, c */ -#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ -#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ -#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ -#define R1_ERASE_RESET (1 << 13) /* sr, c */ -#define R1_STATUS(x) ((x) & 0xFFFFE000) -#define R1_CURRENT_STATE(x) (((x) & 0x00001E00) >> 9) /* sx, b (4 bits) */ -#define R1_READY_FOR_DATA (1 << 8) /* sx, a */ -#define R1_SWITCH_ERROR (1 << 7) /* sx, c */ -#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */ -#define R1_APP_CMD (1 << 5) /* sr, c */ - -#define R1_STATE_IDLE 0 -#define R1_STATE_READY 1 -#define R1_STATE_IDENT 2 -#define R1_STATE_STBY 3 -#define R1_STATE_TRAN 4 -#define R1_STATE_DATA 5 -#define R1_STATE_RCV 6 -#define R1_STATE_PRG 7 -#define R1_STATE_DIS 8 - -/* -* MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS -* R1 is the low order byte; R2 is the next highest byte, when present. -*/ -#define R1_SPI_IDLE (1 << 0) -#define R1_SPI_ERASE_RESET (1 << 1) -#define R1_SPI_ILLEGAL_COMMAND (1 << 2) -#define R1_SPI_COM_CRC (1 << 3) -#define R1_SPI_ERASE_SEQ (1 << 4) -#define R1_SPI_ADDRESS (1 << 5) -#define R1_SPI_PARAMETER (1 << 6) -/* R1 bit 7 is always zero */ -#define R2_SPI_CARD_LOCKED (1 << 8) -#define R2_SPI_WP_ERASE_SKIP (1 << 9) /* or lock/unlock fail */ -#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP -#define R2_SPI_ERROR (1 << 10) -#define R2_SPI_CC_ERROR (1 << 11) -#define R2_SPI_CARD_ECC_ERROR (1 << 12) -#define R2_SPI_WP_VIOLATION (1 << 13) -#define R2_SPI_ERASE_PARAM (1 << 14) -#define R2_SPI_OUT_OF_RANGE (1 << 15) /* or CSD overwrite */ -#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE - -/* -* OCR bits are mostly in host.h -*/ -#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */ - -/* -* Card Command Classes (CCC) -*/ -#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */ -/* (CMD0,1,2,3,4,7,9,10,12,13,15) */ -/* (and for SPI, CMD58,59) */ -#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */ -/* (CMD11) */ -#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */ -/* (CMD16,17,18) */ -#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */ -/* (CMD20) */ -#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */ -/* (CMD16,24,25,26,27) */ -#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */ -/* (CMD32,33,34,35,36,37,38,39) */ -#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */ -/* (CMD28,29,30) */ -#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */ -/* (CMD16,CMD42) */ -#define CCC_APP_SPEC (1<<8) /* (8) Application specific */ -/* (CMD55,56,57,ACMD*) */ -#define CCC_IO_MODE (1<<9) /* (9) I/O mode */ -/* (CMD5,39,40,52,53) */ -#define CCC_SWITCH (1<<10) /* (10) High speed switch */ -/* (CMD6,34,35,36,37,50) */ -/* (11) Reserved */ -/* (CMD?) */ - -/* -* CSD field definitions -*/ - -#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */ -#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */ -#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */ -#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */ - -#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */ -#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */ -#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */ -#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */ -#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */ - -/* -* EXT_CSD fields -*/ - -#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */ -#define EXT_CSD_FLUSH_CACHE 32 /* W */ -#define EXT_CSD_CACHE_CTRL 33 /* R/W */ -#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */ -#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */ -#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */ -#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */ -#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */ -#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ -#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ -#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ -#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ -#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ -#define EXT_CSD_HPI_MGMT 161 /* R/W */ -#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ -#define EXT_CSD_BKOPS_EN 163 /* R/W */ -#define EXT_CSD_BKOPS_START 164 /* W */ -#define EXT_CSD_SANITIZE_START 165 /* W */ -#define EXT_CSD_WR_REL_PARAM 166 /* RO */ -#define EXT_CSD_RPMB_MULT 168 /* RO */ -#define EXT_CSD_FW_CONFIG 169 /* R/W */ -#define EXT_CSD_BOOT_WP 173 /* R/W */ -#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ -#define EXT_CSD_PART_CONFIG 179 /* R/W */ -#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ -#define EXT_CSD_BUS_WIDTH 183 /* R/W */ -#define EXT_CSD_STROBE_SUPPORT 184 /* RO */ -#define EXT_CSD_HS_TIMING 185 /* R/W */ -#define EXT_CSD_POWER_CLASS 187 /* R/W */ -#define EXT_CSD_REV 192 /* RO */ -#define EXT_CSD_STRUCTURE 194 /* RO */ -#define EXT_CSD_CARD_TYPE 196 /* RO */ -#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */ -#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */ -#define EXT_CSD_PART_SWITCH_TIME 199 /* RO */ -#define EXT_CSD_PWR_CL_52_195 200 /* RO */ -#define EXT_CSD_PWR_CL_26_195 201 /* RO */ -#define EXT_CSD_PWR_CL_52_360 202 /* RO */ -#define EXT_CSD_PWR_CL_26_360 203 /* RO */ -#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ -#define EXT_CSD_S_A_TIMEOUT 217 /* RO */ -#define EXT_CSD_REL_WR_SEC_C 222 /* RO */ -#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */ -#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */ -#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ -#define EXT_CSD_BOOT_MULT 226 /* RO */ -#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */ -#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */ -#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */ -#define EXT_CSD_TRIM_MULT 232 /* RO */ -#define EXT_CSD_PWR_CL_200_195 236 /* RO */ -#define EXT_CSD_PWR_CL_200_360 237 /* RO */ -#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */ -#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */ -#define EXT_CSD_BKOPS_STATUS 246 /* RO */ -#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */ -#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ -#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */ -#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */ -#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */ -#define EXT_CSD_DEVICE_VERSION 262 /* RO, 2 bytes */ -#define EXT_CSD_PRE_EOL_INFO 267 /* RO */ -#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */ -#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */ -#define EXT_CSD_CMDQ_DEPTH 307 /* RO */ -#define EXT_CSD_CMDQ_SUPPORT 308 /* RO */ -#define EXT_CSD_SUPPORTED_MODE 493 /* RO */ -#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ -#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ -#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */ -#define EXT_CSD_MAX_PACKED_READS 501 /* RO */ -#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */ -#define EXT_CSD_HPI_FEATURES 503 /* RO */ - -/* -* EXT_CSD field definitions -*/ - -#define EXT_CSD_WR_REL_PARAM_EN (1<<2) - -#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40) -#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10) -#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04) -#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01) - -#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7) -#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1) -#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3) -#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4) - -#define EXT_CSD_PART_SETTING_COMPLETED (0x1) -#define EXT_CSD_PART_SUPPORT_PART_EN (0x1) - -#define EXT_CSD_CMD_SET_NORMAL (1<<0) -#define EXT_CSD_CMD_SET_SECURE (1<<1) -#define EXT_CSD_CMD_SET_CPSECURE (1<<2) - -#define EXT_CSD_CARD_TYPE_HS_26 (1<<0) /* Card can run at 26MHz */ -#define EXT_CSD_CARD_TYPE_HS_52 (1<<1) /* Card can run at 52MHz */ -#define EXT_CSD_CARD_TYPE_HS (EXT_CSD_CARD_TYPE_HS_26 | \ - EXT_CSD_CARD_TYPE_HS_52) -#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */ -/* DDR mode @1.8V or 3V I/O */ -#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */ -/* DDR mode @1.2V I/O */ -#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \ - | EXT_CSD_CARD_TYPE_DDR_1_2V) -#define EXT_CSD_CARD_TYPE_HS200_1_8V (1<<4) /* Card can run at 200MHz */ -#define EXT_CSD_CARD_TYPE_HS200_1_2V (1<<5) /* Card can run at 200MHz */ -/* SDR mode @1.2V I/O */ -#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \ - EXT_CSD_CARD_TYPE_HS200_1_2V) -#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6) /* Card can run at 200MHz DDR, 1.8V */ -#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz DDR, 1.2V */ -#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \ - EXT_CSD_CARD_TYPE_HS400_1_2V) -#define EXT_CSD_CARD_TYPE_HS400ES (1<<8) /* Card can run at HS400ES */ - -#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ -#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ -#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ -#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */ -#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */ -#define EXT_CSD_BUS_WIDTH_STROBE (1<<7) /* Enhanced strobe mode */ - -#define EXT_CSD_TIMING_BC 0 /* Backwards compatility */ -#define EXT_CSD_TIMING_HS 1 /* High speed */ -#define EXT_CSD_TIMING_HS200 2 /* HS200 */ -#define EXT_CSD_TIMING_HS400 3 /* HS400 */ -#define EXT_CSD_DRV_STR_SHIFT 4 /* Driver Strength shift */ - -#define EXT_CSD_SEC_ER_EN (1<<0) -#define EXT_CSD_SEC_BD_BLK_EN (1<<2) -#define EXT_CSD_SEC_GB_CL_EN (1<<4) -#define EXT_CSD_SEC_SANITIZE (1<<6) /* v4.5 only */ - -#define EXT_CSD_RST_N_EN_MASK 0x3 -#define EXT_CSD_RST_N_ENABLED 1 /* RST_n is enabled on card */ - -#define EXT_CSD_NO_POWER_NOTIFICATION 0 -#define EXT_CSD_POWER_ON 1 -#define EXT_CSD_POWER_OFF_SHORT 2 -#define EXT_CSD_POWER_OFF_LONG 3 - -#define EXT_CSD_PWR_CL_8BIT_MASK 0xF0 /* 8 bit PWR CLS */ -#define EXT_CSD_PWR_CL_4BIT_MASK 0x0F /* 8 bit PWR CLS */ -#define EXT_CSD_PWR_CL_8BIT_SHIFT 4 -#define EXT_CSD_PWR_CL_4BIT_SHIFT 0 - -#define EXT_CSD_PACKED_EVENT_EN (1<<3) - -/* -* EXCEPTION_EVENT_STATUS field -*/ -#define EXT_CSD_URGENT_BKOPS (1<<0) -#define EXT_CSD_DYNCAP_NEEDED (1<<1) -#define EXT_CSD_SYSPOOL_EXHAUSTED (1<<2) -#define EXT_CSD_PACKED_FAILURE (1<<3) - -#define EXT_CSD_PACKED_GENERIC_ERROR (1<<0) -#define EXT_CSD_PACKED_INDEXED_ERROR (1<<1) - -/* -* BKOPS status level -*/ -#define EXT_CSD_BKOPS_LEVEL_2 0x2 - -/* -* BKOPS modes -*/ -#define EXT_CSD_MANUAL_BKOPS_MASK 0x01 -#define EXT_CSD_AUTO_BKOPS_MASK 0x02 - -/* -* Command Queue -*/ -#define EXT_CSD_CMDQ_MODE_ENABLED (1<<0) -#define EXT_CSD_CMDQ_DEPTH_MASK 0x1F -#define EXT_CSD_CMDQ_SUPPORTED (1<<0) - -/* -* MMC_SWITCH access modes -*/ -#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */ -#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */ -#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */ -#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ - -/* -* Erase/trim/discard -*/ -#define MMC_ERASE_ARG 0x00000000 -#define MMC_SECURE_ERASE_ARG 0x80000000 -#define MMC_TRIM_ARG 0x00000001 -#define MMC_DISCARD_ARG 0x00000003 -#define MMC_SECURE_TRIM1_ARG 0x80000001 -#define MMC_SECURE_TRIM2_ARG 0x80008000 -#define MMC_SECURE_ARGS 0x80000000 -#define MMC_TRIM_ARGS 0x00008001 - -#endif /* LINUX_MMC_MMC_H */ diff --git a/emummc/source/emmc/nx_emmc.c b/emummc/source/emmc/nx_emmc.c deleted file mode 100644 index 2dca775ae7..0000000000 --- a/emummc/source/emmc/nx_emmc.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include "../utils/types.h" -#include "nx_emmc.h" - -int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf) -{ - // The last LBA is inclusive. - if (part->lba_start + sector_off > part->lba_end) - return 0; - return sdmmc_storage_read(storage, part->lba_start + sector_off, num_sectors, buf); -} - -int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf) -{ - // The last LBA is inclusive. - if (part->lba_start + sector_off > part->lba_end) - return 0; - return sdmmc_storage_write(storage, part->lba_start + sector_off, num_sectors, buf); -} diff --git a/emummc/source/emmc/nx_emmc.h b/emummc/source/emmc/nx_emmc.h deleted file mode 100644 index e90d49f606..0000000000 --- a/emummc/source/emmc/nx_emmc.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _NX_EMMC_H_ -#define _NX_EMMC_H_ - -#include "../utils/types.h" -#include "sdmmc.h" - -typedef struct _gpt_entry_t -{ - u8 type_guid[0x10]; - u8 part_guid[0x10]; - u64 lba_start; - u64 lba_end; - u64 attrs; - u16 name[36]; -} gpt_entry_t; - -typedef struct _gpt_header_t -{ - u64 signature; - u32 revision; - u32 size; - u32 crc32; - u32 res1; - u64 my_lba; - u64 alt_lba; - u64 first_use_lba; - u64 last_use_lba; - u8 disk_guid[0x10]; - u64 part_ent_lba; - u32 num_part_ents; - u32 part_ent_size; - u32 part_ents_crc32; - u8 res2[420]; -} gpt_header_t; - -#define NX_GPT_FIRST_LBA 1 -#define NX_GPT_NUM_BLOCKS 33 -#define NX_EMMC_BLOCKSIZE 512 - -typedef struct _emmc_part_t -{ - u32 lba_start; - u32 lba_end; - u64 attrs; - s8 name[37]; -} emmc_part_t; - -int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); -int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); - -#endif diff --git a/emummc/source/emmc/nx_sd.c b/emummc/source/emmc/nx_sd.c deleted file mode 100644 index 1f5fd50d2d..0000000000 --- a/emummc/source/emmc/nx_sd.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2019 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "nx_sd.h" -#include "sdmmc.h" -#include "sdmmc_driver.h" -#include "../soc/gpio.h" -#include "../libs/fatfs/ff.h" - -extern sdmmc_t sd_sdmmc; -extern sdmmc_storage_t sd_storage; - -static u32 sd_mode = SD_UHS_SDR104; - -u32 nx_sd_mode_get() -{ - return sd_mode; -} - -int nx_sd_init_retry(bool power_cycle) -{ - u32 bus_width = SDMMC_BUS_WIDTH_4; - u32 type = SDHCI_TIMING_UHS_SDR104; - - // Power cycle SD card. - if (power_cycle) - { - sd_mode--; - sdmmc_storage_end(&sd_storage); - } - - // Get init parameters. - switch (sd_mode) - { - case SD_INIT_FAIL: // Reset to max. - return 0; - case SD_1BIT_HS25: - bus_width = SDMMC_BUS_WIDTH_1; - type = SDHCI_TIMING_SD_HS25; - break; - case SD_4BIT_HS25: - type = SDHCI_TIMING_SD_HS25; - break; - case SD_UHS_SDR82: - type = SDHCI_TIMING_UHS_SDR82; - break; - case SD_UHS_SDR104: - type = SDHCI_TIMING_UHS_SDR104; - break; - default: - sd_mode = SD_UHS_SDR104; - } - - return sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type); -} - -bool nx_sd_initialize(bool power_cycle) -{ - if (power_cycle) - sdmmc_storage_end(&sd_storage); - - int res = !nx_sd_init_retry(false); - - while (true) - { - if (!res) - return true; - else - { - if (sd_mode == SD_INIT_FAIL) - break; - - res = !nx_sd_init_retry(true); - } - } - - return false; -} \ No newline at end of file diff --git a/emummc/source/emmc/nx_sd.h b/emummc/source/emmc/nx_sd.h deleted file mode 100644 index 38c74edbb4..0000000000 --- a/emummc/source/emmc/nx_sd.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef NX_SD_H -#define NX_SD_H - -#include "../utils/types.h" - -enum -{ - SD_INIT_FAIL = 0, - SD_1BIT_HS25 = 1, - SD_4BIT_HS25 = 2, - SD_UHS_SDR82 = 3, - SD_UHS_SDR104 = 4 -}; - -u32 nx_sd_get_mode(); -int nx_sd_init_retry(bool power_cycle); -bool nx_sd_initialize(bool power_cycle); - -#endif \ No newline at end of file diff --git a/emummc/source/emmc/sd.h b/emummc/source/emmc/sd.h deleted file mode 100644 index a780ec8564..0000000000 --- a/emummc/source/emmc/sd.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved. - * Copyright (c) 2018 CTCaer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - */ - -#ifndef MMC_SD_H -#define MMC_SD_H - -/* SD commands type argument response */ -/* class 0 */ -/* This is basically the same command as for MMC with some quirks. */ -#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ -#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ -#define SD_SWITCH_VOLTAGE 11 /* ac R1 */ - -/* class 10 */ -#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ - -/* class 5 */ -#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */ -#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */ - -/* Application commands */ -#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ -#define SD_APP_SD_STATUS 13 /* adtc R1 */ -#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ -#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ -#define SD_APP_SET_CLR_CARD_DETECT 42 -#define SD_APP_SEND_SCR 51 /* adtc R1 */ - -/* OCR bit definitions */ -#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ -#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ -#define SD_OCR_XPC (1 << 28) /* SDXC power control */ -#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ -#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */ -#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */ -#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */ - -/* -* SD_SWITCH argument format: -* -* [31] Check (0) or switch (1) -* [30:24] Reserved (0) -* [23:20] Function group 6 -* [19:16] Function group 5 -* [15:12] Function group 4 -* [11:8] Function group 3 -* [7:4] Function group 2 -* [3:0] Function group 1 -*/ - -/* -* SD_SEND_IF_COND argument format: -* -* [31:12] Reserved (0) -* [11:8] Host Voltage Supply Flags -* [7:0] Check Pattern (0xAA) -*/ - -/* -* SCR field definitions -*/ -#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ -#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ -#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */ -#define SD_SCR_BUS_WIDTH_1 (1<<0) -#define SD_SCR_BUS_WIDTH_4 (1<<2) - -/* -* SD bus widths -*/ -#define SD_BUS_WIDTH_1 0 -#define SD_BUS_WIDTH_4 2 - -/* -* SD bus speeds -*/ -#define UHS_SDR12_BUS_SPEED 0 -#define HIGH_SPEED_BUS_SPEED 1 -#define UHS_SDR25_BUS_SPEED 1 -#define UHS_SDR50_BUS_SPEED 2 -#define UHS_SDR104_BUS_SPEED 3 -#define UHS_DDR50_BUS_SPEED 4 -#define HS400_BUS_SPEED 5 - -#define SD_MODE_HIGH_SPEED (1 << HIGH_SPEED_BUS_SPEED) -#define SD_MODE_UHS_SDR12 (1 << UHS_SDR12_BUS_SPEED) -#define SD_MODE_UHS_SDR25 (1 << UHS_SDR25_BUS_SPEED) -#define SD_MODE_UHS_SDR50 (1 << UHS_SDR50_BUS_SPEED) -#define SD_MODE_UHS_SDR104 (1 << UHS_SDR104_BUS_SPEED) -#define SD_MODE_UHS_DDR50 (1 << UHS_DDR50_BUS_SPEED) - -#define SD_DRIVER_TYPE_B 0x01 -#define SD_DRIVER_TYPE_A 0x02 - -#define SD_SET_CURRENT_LIMIT_200 0 -#define SD_SET_CURRENT_LIMIT_400 1 -#define SD_SET_CURRENT_LIMIT_600 2 -#define SD_SET_CURRENT_LIMIT_800 3 - -#define SD_MAX_CURRENT_200 (1 << SD_SET_CURRENT_LIMIT_200) -#define SD_MAX_CURRENT_400 (1 << SD_SET_CURRENT_LIMIT_400) -#define SD_MAX_CURRENT_600 (1 << SD_SET_CURRENT_LIMIT_600) -#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) - -/* -* SD_SWITCH mode -*/ -#define SD_SWITCH_CHECK 0 -#define SD_SWITCH_SET 1 - -/* -* SD_SWITCH function groups -*/ -#define SD_SWITCH_GRP_ACCESS 0 - -/* -* SD_SWITCH access modes -*/ -#define SD_SWITCH_ACCESS_DEF 0 -#define SD_SWITCH_ACCESS_HS 1 - -#endif /* LINUX_MMC_SD_H */ diff --git a/emummc/source/emmc/sdmmc.c b/emummc/source/emmc/sdmmc.c deleted file mode 100644 index 56024bd53a..0000000000 --- a/emummc/source/emmc/sdmmc.c +++ /dev/null @@ -1,1480 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include "sdmmc.h" -#include "mmc.h" -#include "nx_sd.h" -#include "sd.h" -#include "../utils/types.h" -#include "../utils/util.h" -#include "../utils/fatal.h" -#include "../emuMMC/emummc.h" - -#define DPRINTF(...) //fprintf(stdout, __VA_ARGS__) - -sdmmc_accessor_t *_current_accessor = NULL; -bool sdmmc_memcpy_buf = false; -extern bool custom_driver; - -static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size) -{ - const u32 mask = (size < 32 ? 1 << size : 0) - 1; - const u32 off = 3 - ((start) / 32); - const u32 shft = (start) & 31; - u32 res = resp[off] >> shft; - if (size + shft > 32) - res |= resp[off - 1] << ((32 - shft) % 32); - return res & mask; -} - -/* -* Common functions for SD and MMC. -*/ - -// FS DMA calculations. -intptr_t sdmmc_calculate_dma_addr(sdmmc_accessor_t *_this, void *buf, unsigned int num_sectors) -{ - int dma_buf_idx = 0; - char *_buf = (char *)buf; - char *actual_buf_start = _buf; - char *actual_buf_end = &_buf[512 * num_sectors]; - char *dma_buffer_start = _this->parent->dmaBuffers[0].device_addr_buffer; - - if (dma_buffer_start <= _buf && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[0].device_addr_buffer_size]) - { - dma_buf_idx = 0; - } - else - { - dma_buffer_start = _this->parent->dmaBuffers[1].device_addr_buffer; - if (dma_buffer_start <= actual_buf_start && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[1].device_addr_buffer_size]) - { - dma_buf_idx = 1; - } - else - { - dma_buffer_start = _this->parent->dmaBuffers[2].device_addr_buffer; - if (dma_buffer_start <= actual_buf_start && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[2].device_addr_buffer_size]) - { - dma_buf_idx = 2; - } - else - { - // If buffer is on a random heap - return 0; - } - } - } - - sdmmc_memcpy_buf = false; - - intptr_t admaaddr = (intptr_t)&_this->parent->dmaBuffers[dma_buf_idx].device_addr_buffer_masked[actual_buf_start - dma_buffer_start]; - return admaaddr; -} - -int sdmmc_calculate_dma_index(sdmmc_accessor_t *_this, void *buf, unsigned int num_sectors) -{ - int dma_buf_idx = 0; - char *_buf = (char *)buf; - char *actual_buf_start = _buf; - char *actual_buf_end = &_buf[512 * num_sectors]; - char *dma_buffer_start = _this->parent->dmaBuffers[0].device_addr_buffer; - - if (dma_buffer_start <= _buf && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[0].device_addr_buffer_size]) - { - dma_buf_idx = 0; - } - else - { - dma_buffer_start = _this->parent->dmaBuffers[1].device_addr_buffer; - if (dma_buffer_start <= actual_buf_start && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[1].device_addr_buffer_size]) - { - dma_buf_idx = 1; - } - else - { - dma_buffer_start = _this->parent->dmaBuffers[2].device_addr_buffer; - if (dma_buffer_start <= actual_buf_start && actual_buf_end <= &dma_buffer_start[_this->parent->dmaBuffers[2].device_addr_buffer_size]) - { - dma_buf_idx = 2; - } - else - { - // If buffer is on a random heap - return -1; - } - } - } - - sdmmc_memcpy_buf = false; - - return dma_buf_idx; -} - -int sdmmc_calculate_fitting_dma_index(sdmmc_accessor_t *_this, unsigned int num_sectors) -{ - int dma_buf_idx = 0; - int blkSize = num_sectors * 512; - - if (_this->parent->dmaBuffers[0].device_addr_buffer_size >= blkSize) - { - dma_buf_idx = 0; - } - else - { - if (_this->parent->dmaBuffers[1].device_addr_buffer_size >= blkSize) - { - dma_buf_idx = 1; - } - else - { - if (_this->parent->dmaBuffers[2].device_addr_buffer_size >= blkSize) - { - dma_buf_idx = 2; - } - else - { - // Can't find a fitting buffer - return 0; - } - } - } - - sdmmc_memcpy_buf = true; - return dma_buf_idx; -} - -static int _sdmmc_storage_check_result(u32 res) -{ - //Error mask: - //TODO: R1_SWITCH_ERROR can be skipped for certain card types. - if (res & - (R1_OUT_OF_RANGE | R1_ADDRESS_ERROR | R1_BLOCK_LEN_ERROR | - R1_ERASE_SEQ_ERROR | R1_ERASE_PARAM | R1_WP_VIOLATION | - R1_LOCK_UNLOCK_FAILED | R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND | - R1_CARD_ECC_FAILED | R1_CC_ERROR | R1_ERROR | - R1_CID_CSD_OVERWRITE | R1_WP_ERASE_SKIP | R1_ERASE_RESET | - R1_SWITCH_ERROR)) - return 0; - - // No errors. - return 1; -} - -static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state, u32 mask) -{ - sdmmc_cmd_t cmdbuf; - sdmmc_init_cmd(&cmdbuf, cmd, arg, SDMMC_RSP_TYPE_1, check_busy); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) - return 0; - - sdmmc_get_rsp(storage->sdmmc, resp, 4, SDMMC_RSP_TYPE_1); - if (mask) - *resp &= ~mask; - - if (_sdmmc_storage_check_result(*resp)) - if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state) - return 1; - - return 0; -} - -static int _sdmmc_storage_execute_cmd_type1(sdmmc_storage_t *storage, u32 cmd, u32 arg, u32 check_busy, u32 expected_state) -{ - u32 tmp; - return _sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, cmd, arg, check_busy, expected_state, 0); -} - -static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage) -{ - sdmmc_cmd_t cmd; - sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0); - - return sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0); -} - -static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf) -{ - sdmmc_cmd_t cmd; - sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0)) - return 0; - - sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2); - - return 1; -} - -static int _sdmmc_storage_select_card(sdmmc_storage_t *storage) -{ - return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, 0x10); -} - -static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf) -{ - sdmmc_cmd_t cmdbuf; - sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) - return 0; - - sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2); - - return 1; -} - -static int _sdmmc_storage_set_blocklen(sdmmc_storage_t *storage, u32 blocklen) -{ - return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_BLOCKLEN, blocklen, 0, R1_STATE_TRAN); -} - -static int _sdmmc_storage_get_status(sdmmc_storage_t *storage, u32 *resp, u32 mask) -{ - return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, MMC_SEND_STATUS, storage->rca << 16, 0, R1_STATE_TRAN, mask); -} - -static int _sdmmc_storage_check_status(sdmmc_storage_t *storage) -{ - u32 tmp; - return _sdmmc_storage_get_status(storage, &tmp, 0); -} - -static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out, u32 sector, u32 num_sectors, void *buf, u32 is_write) -{ - u32 tmp = 0; - sdmmc_cmd_t cmdbuf; - sdmmc_req_t reqbuf; - - sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0); - - reqbuf.buf = buf; - reqbuf.num_sectors = num_sectors; - reqbuf.blksize = 512; - reqbuf.is_write = is_write; - reqbuf.is_multi_block = 1; - reqbuf.is_auto_cmd12 = 1; - - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out)) - { - sdmmc_stop_transmission(storage->sdmmc, &tmp); - _sdmmc_storage_get_status(storage, &tmp, 0); - - return 0; - } - - return 1; -} - -int sdmmc_storage_end(sdmmc_storage_t *storage) -{ - if (!_sdmmc_storage_go_idle_state(storage)) - return 0; - - sdmmc_end(storage->sdmmc); - - storage->initialized = 0; - - return 1; -} - -static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write) -{ - u8 *bbuf = (u8 *)buf; - u32 sct_off = sector; - u32 sct_total = num_sectors; - bool first_reinit = true; - - // Exit if not initialized. - if (!storage->initialized) - return 0; - - while (sct_total) - { - u32 blkcnt = 0; - // Retry 5 times if failed. - u32 retries = 5; - do - { -reinit_try: - if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sct_off, MIN(sct_total, 0xFFFF), bbuf, is_write)) - goto out; - else - retries--; - - msleep(50); - } while (retries); - - // Disk IO failure! Reinit SD Card to a lower speed. - if (storage->sdmmc->id == SDMMC_1) - { - int res; - - if (first_reinit) - res = nx_sd_initialize(true); - else - res = nx_sd_init_retry(true); - - // Reset values for a retry. - blkcnt = 0; - retries = 3; - first_reinit = false; - - // If succesful reinit, restart xfer. - if (res) - { - bbuf = (u8 *)buf; - sct_off = sector; - sct_total = num_sectors; - - goto reinit_try; - } - } - - // Failed. - return 0; - -out: - sct_off += blkcnt; - sct_total -= blkcnt; - bbuf += 512 * blkcnt; - } - - return 1; -} - -extern _sdmmc_accessor_sd sdmmc_accessor_sd; -extern _sdmmc_accessor_nand sdmmc_accessor_nand; -int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf) -{ - if (!custom_driver) - { - sdmmc_accessor_t *accessor_sd = sdmmc_accessor_sd(); - sdmmc_accessor_t *accessor_nand = sdmmc_accessor_nand(); - - if (sdmmc_calculate_dma_addr(accessor_sd, buf, num_sectors)) - { - return !accessor_sd->vtab->read_write(accessor_sd, sector, num_sectors, buf, num_sectors * 512, 1); - } - else - { - if (sdmmc_calculate_dma_addr(accessor_nand, buf, num_sectors)) - { - // buf is on the nand dma buffer - int original_dma_idx = sdmmc_calculate_dma_index(accessor_nand, buf, num_sectors); - sdmmc_dma_buffer_t *original_dma_buffer = &accessor_nand->parent->dmaBuffers[original_dma_idx]; - - // Next entry - int dma_idx = sdmmc_calculate_fitting_dma_index(accessor_sd, num_sectors) + 1; - - accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer = original_dma_buffer->device_addr_buffer; - accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_masked = original_dma_buffer->device_addr_buffer_masked; - accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_size = original_dma_buffer->device_addr_buffer_size; - - u64 res = accessor_sd->vtab->read_write(accessor_sd, sector, num_sectors, buf, num_sectors * 512, 1); - - accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer = 0; - accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_masked = 0; - accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_size = 0; - - return !res; - } - else - { - // buf is on a heap - int dma_idx = sdmmc_calculate_fitting_dma_index(accessor_sd, num_sectors); - void *dma_buf = &accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer[0]; - - u64 res = accessor_sd->vtab->read_write(accessor_sd, sector, num_sectors, dma_buf, num_sectors * 512, 1); - memcpy(buf, dma_buf, num_sectors * 512); - - return !res; - } - } - } - else - { - return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 0); - } -} - -int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf) -{ - if (!custom_driver) - { - sdmmc_accessor_t *accessor_sd = sdmmc_accessor_sd(); - sdmmc_accessor_t *accessor_nand = sdmmc_accessor_nand(); - - if (sdmmc_calculate_dma_addr(accessor_sd, buf, num_sectors)) - { - return !accessor_sd->vtab->read_write(accessor_sd, sector, num_sectors, buf, num_sectors * 512, 0); - } - else - { - if (sdmmc_calculate_dma_addr(accessor_nand, buf, num_sectors)) - { - // buf is on the nand dma buffer - int original_dma_idx = sdmmc_calculate_dma_index(accessor_nand, buf, num_sectors); - sdmmc_dma_buffer_t *original_dma_buffer = &accessor_nand->parent->dmaBuffers[original_dma_idx]; - - // Next entry - int dma_idx = sdmmc_calculate_fitting_dma_index(accessor_sd, num_sectors) + 1; - - accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer = original_dma_buffer->device_addr_buffer; - accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_masked = original_dma_buffer->device_addr_buffer_masked; - accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_size = original_dma_buffer->device_addr_buffer_size; - - u64 res = accessor_sd->vtab->read_write(accessor_sd, sector, num_sectors, buf, num_sectors * 512, 0); - - accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer = 0; - accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_masked = 0; - accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer_size = 0; - - return !res; - } - else - { - // buf is on a heap - int dma_idx = sdmmc_calculate_fitting_dma_index(accessor_sd, num_sectors); - void *dma_buf = &accessor_sd->parent->dmaBuffers[dma_idx].device_addr_buffer[0]; - - memcpy(dma_buf, buf, num_sectors * 512); - u64 res = accessor_sd->vtab->read_write(accessor_sd, sector, num_sectors, dma_buf, num_sectors * 512, 0); - - return !res; - } - } - } - else - { - return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 1); - } -} - -/* -* MMC specific functions. -*/ - -static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power) -{ - sdmmc_cmd_t cmd; - - u32 arg = 0; - switch (power) - { - case SDMMC_POWER_1_8: - arg = SD_OCR_CCS | SD_OCR_VDD_18; - break; - - case SDMMC_POWER_3_3: - arg = SD_OCR_CCS | SD_OCR_VDD_27_34; - break; - - default: - return 0; - } - - sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0)) - return 0; - - return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3); -} - -static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power) -{ - u64 timeout = get_tmr_ms() + 1500; - - while (1) - { - u32 cond = 0; - if (!_mmc_storage_get_op_cond_inner(storage, &cond, power)) - break; - - if (cond & MMC_CARD_BUSY) - { - if (cond & SD_OCR_CCS) - storage->has_sector_access = 1; - - return 1; - } - if (get_tmr_ms() > timeout) - break; - - usleep(1000); - } - - return 0; -} - -static int _mmc_storage_set_relative_addr(sdmmc_storage_t *storage) -{ - return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_RELATIVE_ADDR, storage->rca << 16, 0, 0x10); -} - -static void _mmc_storage_parse_cid(sdmmc_storage_t *storage) -{ - u32 *raw_cid = (u32 *)&(storage->raw_cid); - - switch (storage->csd.mmca_vsn) - { - case 0: /* MMC v1.0 - v1.2 */ - case 1: /* MMC v1.4 */ - storage->cid.prod_name[6] = unstuff_bits(raw_cid, 48, 8); - storage->cid.manfid = unstuff_bits(raw_cid, 104, 24); - storage->cid.hwrev = unstuff_bits(raw_cid, 44, 4); - storage->cid.fwrev = unstuff_bits(raw_cid, 40, 4); - storage->cid.serial = unstuff_bits(raw_cid, 16, 24); - break; - - case 2: /* MMC v2.0 - v2.2 */ - case 3: /* MMC v3.1 - v3.3 */ - case 4: /* MMC v4 */ - storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); - storage->cid.card_bga = unstuff_bits(raw_cid, 112, 2); - storage->cid.oemid = unstuff_bits(raw_cid, 104, 8); - storage->cid.prv = unstuff_bits(raw_cid, 48, 8); - storage->cid.serial = unstuff_bits(raw_cid, 16, 32); - break; - - default: - break; - } - - storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8); - storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8); - storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8); - storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8); - storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8); - storage->cid.prod_name[5] = unstuff_bits(raw_cid, 56, 8); - - storage->cid.month = unstuff_bits(raw_cid, 12, 4); - storage->cid.year = unstuff_bits(raw_cid, 8, 4) + 1997; - if (storage->ext_csd.rev >= 5) - { - if (storage->cid.year < 2010) - storage->cid.year += 16; - } -} - -static void _mmc_storage_parse_csd(sdmmc_storage_t *storage) -{ - u32 *raw_csd = (u32 *)&(storage->raw_csd); - - storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4); - storage->csd.structure = unstuff_bits(raw_csd, 126, 2); - storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12); - storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4); - storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); -} - -static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf) -{ - storage->ext_csd.rev = buf[EXT_CSD_REV]; - storage->ext_csd.ext_struct = buf[EXT_CSD_STRUCTURE]; - storage->ext_csd.card_type = buf[EXT_CSD_CARD_TYPE]; - storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION]; - storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT]; - storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT]; - storage->ext_csd.sectors = *(u32 *)&buf[EXT_CSD_SEC_CNT]; - storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT]; - storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN]; - storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS]; - - storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO]; - storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A]; - storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B]; - - storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT]; -} - -static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf) -{ - sdmmc_cmd_t cmdbuf; - sdmmc_init_cmd(&cmdbuf, MMC_SEND_EXT_CSD, 0, SDMMC_RSP_TYPE_1, 0); - - sdmmc_req_t reqbuf; - reqbuf.buf = buf; - reqbuf.blksize = 512; - reqbuf.num_sectors = 1; - reqbuf.is_write = 0; - reqbuf.is_multi_block = 0; - reqbuf.is_auto_cmd12 = 0; - - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) - return 0; - - u32 tmp = 0; - sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); - _mmc_storage_parse_ext_csd(storage, buf); - - return _sdmmc_storage_check_result(tmp); -} - -static int _mmc_storage_switch(sdmmc_storage_t *storage, u32 arg) -{ - return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, 0x10); -} - -static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width) -{ - if (bus_width == SDMMC_BUS_WIDTH_1) - return 1; - - u32 arg = 0; - switch (bus_width) - { - case SDMMC_BUS_WIDTH_4: - arg = SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4); - break; - - case SDMMC_BUS_WIDTH_8: - arg = SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8); - break; - } - - if (_mmc_storage_switch(storage, arg)) - if (_sdmmc_storage_check_status(storage)) - { - sdmmc_set_bus_width(storage->sdmmc, bus_width); - - return 1; - } - - return 0; -} - -static int _mmc_storage_enable_HS(sdmmc_storage_t *storage, int check) -{ - if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS))) - return 0; - - if (check && !_sdmmc_storage_check_status(storage)) - return 0; - - if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS52)) - return 0; - -DPRINTF("[MMC] switched to HS\n"); - storage->csd.busspeed = 52; - - if (check || _sdmmc_storage_check_status(storage)) - return 1; - - return 0; -} - -static int _mmc_storage_enable_HS200(sdmmc_storage_t *storage) -{ - if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200))) - return 0; - - if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS200)) - return 0; - - if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS200, MMC_SEND_TUNING_BLOCK_HS200)) - return 0; - -DPRINTF("[MMC] switched to HS200\n"); - storage->csd.busspeed = 200; - - return _sdmmc_storage_check_status(storage); -} - -static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage) -{ - if (!_mmc_storage_enable_HS200(storage)) - return 0; - - sdmmc_save_tap_value(storage->sdmmc); - - if (!_mmc_storage_enable_HS(storage, 0)) - return 0; - - if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_DDR_BUS_WIDTH_8))) - return 0; - - if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400))) - return 0; - - if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS400)) - return 0; - -DPRINTF("[MMC] switched to HS400\n"); - storage->csd.busspeed = 400; - - return _sdmmc_storage_check_status(storage); -} - -static int _mmc_storage_enable_highspeed(sdmmc_storage_t *storage, u32 card_type, u32 type) -{ - if (sdmmc_get_io_power(storage->sdmmc) != SDMMC_POWER_1_8) - goto out; - - if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 && - card_type & EXT_CSD_CARD_TYPE_HS400_1_8V && type == SDHCI_TIMING_MMC_HS400) - return _mmc_storage_enable_HS400(storage); - - if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 || - (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_4 - && card_type & EXT_CSD_CARD_TYPE_HS200_1_8V - && (type == SDHCI_TIMING_MMC_HS400 || type == SDHCI_TIMING_MMC_HS200))) - return _mmc_storage_enable_HS200(storage); - -out: - if (card_type & EXT_CSD_CARD_TYPE_HS_52) - return _mmc_storage_enable_HS(storage, 1); - - return 1; -} - -static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage) -{ - if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2))) - return 0; - - return _sdmmc_storage_check_status(storage); -} - -int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type) -{ - memset(storage, 0, sizeof(sdmmc_storage_t)); - storage->sdmmc = sdmmc; - storage->rca = 2; //TODO: this could be a config item. - - if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE)) - return 0; -DPRINTF("[MMC] after init\n"); - - usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor); - - if (!_sdmmc_storage_go_idle_state(storage)) - return 0; -DPRINTF("[MMC] went to idle state\n"); - - if (!_mmc_storage_get_op_cond(storage, SDMMC_POWER_1_8)) - return 0; -DPRINTF("[MMC] got op cond\n"); - - if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) - return 0; -DPRINTF("[MMC] got cid\n"); - - if (!_mmc_storage_set_relative_addr(storage)) - return 0; -DPRINTF("[MMC] set relative addr\n"); - - if (!_sdmmc_storage_get_csd(storage, storage->raw_csd)) - return 0; -DPRINTF("[MMC] got csd\n"); - _mmc_storage_parse_csd(storage); - - if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_LS26)) - return 0; -DPRINTF("[MMC] after setup clock\n"); - - if (!_sdmmc_storage_select_card(storage)) - return 0; -DPRINTF("[MMC] card selected\n"); - - if (!_sdmmc_storage_set_blocklen(storage, 512)) - return 0; -DPRINTF("[MMC] set blocklen to 512\n"); - - u32 *csd = (u32 *)storage->raw_csd; - //Check system specification version, only version 4.0 and later support below features. - if (unstuff_bits(csd, 122, 4) < CSD_SPEC_VER_4) - { - storage->sec_cnt = (1 + unstuff_bits(csd, 62, 12)) << (unstuff_bits(csd, 47, 3) + 2); - return 1; - } - - if (!_mmc_storage_switch_buswidth(storage, bus_width)) - return 0; -DPRINTF("[MMC] switched buswidth\n"); - u8 buf[512]; - memset(buf, 0, sizeof(buf)); - if (!_mmc_storage_get_ext_csd(storage, buf)) - return 0; -DPRINTF("[MMC] got ext_csd\n"); - - _mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd - - /* When auto BKOPS is enabled the mmc device should be powered all the time until we disable this and check status. - Disable it for now until BKOPS disable added to power down sequence at sdmmc_storage_end(). - Additionally this works only when we put the device in idle mode which we don't after enabling it. */ - if (0 && storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2)) - { - _mmc_storage_enable_bkops(storage); -DPRINTF("[MMC] BKOPS enabled\n"); - } - - if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type)) - return 0; -DPRINTF("[MMC] succesfully switched to HS mode\n"); - - sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE); - - storage->initialized = 1; - - return 1; -} - -int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition) -{ - if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_PART_CONFIG, partition))) - return 0; - - if (!_sdmmc_storage_check_status(storage)) - return 0; - - storage->partition = partition; - - return 1; -} - -/* -* SD specific functions. -*/ - -static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out) -{ - u32 tmp; - if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask)) - return 0; - - return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out); -} - -static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state) -{ - if (!_sdmmc_storage_execute_cmd_type1(storage, MMC_APP_CMD, storage->rca << 16, 0, R1_STATE_TRAN)) - return 0; - - return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0); -} - -static int _sd_storage_send_if_cond(sdmmc_storage_t *storage) -{ - sdmmc_cmd_t cmdbuf; - sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, 0x1AA, SDMMC_RSP_TYPE_5, 0); - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) - return 1; // The SD Card is version 1.X - - u32 resp = 0; - if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5)) - return 2; - - return (resp & 0xFF) == 0xAA ? 0 : 2; -} - -static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_low_voltage_support) -{ - sdmmc_cmd_t cmdbuf; - // Support for Current > 150mA - u32 arg = (~is_version_1 & 1) ? SD_OCR_XPC : 0; - // Support for handling block-addressed SDHC cards - arg |= (~is_version_1 & 1) ? SD_OCR_CCS : 0; - // Support for 1.8V - arg |= (bus_low_voltage_support & ~is_version_1 & 1) ? SD_OCR_S18R : 0; - // This is needed for most cards. Do not set bit7 even if 1.8V is supported. - arg |= SD_OCR_VDD_32_33; - sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); - if (!_sd_storage_execute_app_cmd(storage, 0x10, is_version_1 ? 0x400000 : 0, &cmdbuf, 0, 0)) - return 0; - - return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3); -} - -static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_low_voltage_support) -{ - u64 timeout = get_tmr_ms() + 1500; - - while (1) - { - u32 cond = 0; - if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_low_voltage_support)) - break; - if (cond & MMC_CARD_BUSY) - { -DPRINTF("[SD] cond: %08X, lv: %d\n", cond, bus_low_voltage_support); - - if (cond & SD_OCR_CCS) - storage->has_sector_access = 1; - - // Check if card supports 1.8V signaling. - if (cond & SD_ROCR_S18A && bus_low_voltage_support) - { - //The low voltage regulator configuration is valid for SDMMC1 only. - if (storage->sdmmc->id == SDMMC_1 && - _sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY)) - { - if (!sdmmc_enable_low_voltage(storage->sdmmc)) - return 0; - storage->is_low_voltage = 1; - -DPRINTF("-> switched to low voltage\n"); - } - } - else - { -DPRINTF("[SD] no low voltage support\n"); - } - - return 1; - } - if (get_tmr_ms() > timeout) - break; - msleep(10); // Needs to be at least 10ms for some SD Cards - } - - return 0; -} - -static int _sd_storage_get_rca(sdmmc_storage_t *storage) -{ - sdmmc_cmd_t cmdbuf; - sdmmc_init_cmd(&cmdbuf, SD_SEND_RELATIVE_ADDR, 0, SDMMC_RSP_TYPE_4, 0); - - u64 timeout = get_tmr_ms() + 1500; - - while (1) - { - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) - break; - - u32 resp = 0; - if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_4)) - break; - - if (resp >> 16) - { - storage->rca = resp >> 16; - return 1; - } - - if (get_tmr_ms() > timeout) - break; - usleep(1000); - } - - return 0; -} - -static void _sd_storage_parse_scr(sdmmc_storage_t *storage) -{ - // unstuff_bits can parse only 4 u32 - u32 resp[4]; - - resp[3] = *(u32 *)&storage->raw_scr[4]; - resp[2] = *(u32 *)&storage->raw_scr[0]; - - storage->scr.sda_vsn = unstuff_bits(resp, 56, 4); - storage->scr.bus_widths = unstuff_bits(resp, 48, 4); - if (storage->scr.sda_vsn == SCR_SPEC_VER_2) - /* Check if Physical Layer Spec v3.0 is supported */ - storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1); - if (storage->scr.sda_spec3) - storage->scr.cmds = unstuff_bits(resp, 32, 2); -} - -int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf) -{ - sdmmc_cmd_t cmdbuf; - sdmmc_init_cmd(&cmdbuf, SD_APP_SEND_SCR, 0, SDMMC_RSP_TYPE_1, 0); - - sdmmc_req_t reqbuf; - reqbuf.buf = buf; - reqbuf.blksize = 8; - reqbuf.num_sectors = 1; - reqbuf.is_write = 0; - reqbuf.is_multi_block = 0; - reqbuf.is_auto_cmd12 = 0; - - if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0)) - return 0; - - u32 tmp = 0; - sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); - //Prepare buffer for unstuff_bits - for (int i = 0; i < 8; i+=4) - { - storage->raw_scr[i + 3] = buf[i]; - storage->raw_scr[i + 2] = buf[i + 1]; - storage->raw_scr[i + 1] = buf[i + 2]; - storage->raw_scr[i] = buf[i + 3]; - } - _sd_storage_parse_scr(storage); - - return _sdmmc_storage_check_result(tmp); -} - -int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf) -{ - sdmmc_cmd_t cmdbuf; - sdmmc_init_cmd(&cmdbuf, SD_SWITCH, 0xFFFFFF, SDMMC_RSP_TYPE_1, 0); - - sdmmc_req_t reqbuf; - reqbuf.buf = buf; - reqbuf.blksize = 64; - reqbuf.num_sectors = 1; - reqbuf.is_write = 0; - reqbuf.is_multi_block = 0; - reqbuf.is_auto_cmd12 = 0; - - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) - return 0; - - u32 tmp = 0; - sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); - return _sdmmc_storage_check_result(tmp); -} - -int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, u32 arg) -{ - sdmmc_cmd_t cmdbuf; - u32 switchcmd = mode << 31 | 0x00FFFFFF; - switchcmd &= ~(0xF << (group * 4)); - switchcmd |= arg << (group * 4); - sdmmc_init_cmd(&cmdbuf, SD_SWITCH, switchcmd, SDMMC_RSP_TYPE_1, 0); - - sdmmc_req_t reqbuf; - reqbuf.buf = buf; - reqbuf.blksize = 64; - reqbuf.num_sectors = 1; - reqbuf.is_write = 0; - reqbuf.is_multi_block = 0; - reqbuf.is_auto_cmd12 = 0; - - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) - return 0; - - u32 tmp = 0; - sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); - return _sdmmc_storage_check_result(tmp); -} - -void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u16 current_limit, u8 *buf) -{ - u32 pwr = SD_SET_CURRENT_LIMIT_200; - - if (current_limit & SD_MAX_CURRENT_800) - pwr = SD_SET_CURRENT_LIMIT_800; - else if (current_limit & SD_MAX_CURRENT_600) - pwr = SD_SET_CURRENT_LIMIT_600; - else if (current_limit & SD_MAX_CURRENT_400) - pwr = SD_SET_CURRENT_LIMIT_400; - - _sd_storage_switch(storage, buf, SD_SWITCH_SET, 3, pwr); - - if (((buf[15] >> 4) & 0x0F) == pwr) - { - switch (pwr) - { - case SD_SET_CURRENT_LIMIT_800: -DPRINTF("[SD] power limit raised to 800mA\n"); - break; - - case SD_SET_CURRENT_LIMIT_600: -DPRINTF("[SD] power limit raised to 600mA\n"); - break; - - case SD_SET_CURRENT_LIMIT_400: -DPRINTF("[SD] power limit raised to 400mA\n"); - break; - - default: - case SD_SET_CURRENT_LIMIT_200: -DPRINTF("[SD] power limit defaulted to 200mA\n"); - break; - } - } -} - -int _sd_storage_enable_highspeed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf) -{ - if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, 0, hs_type)) - return 0; -DPRINTF("[SD] supports (U)HS mode: %d\n", buf[16] & 0xF); - - u32 type_out = buf[16] & 0xF; - if (type_out != hs_type) - return 0; -DPRINTF("[SD] supports selected (U)HS mode\n"); - - u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1]; -DPRINTF("[SD] total max current: %d\n", total_pwr_consumption); - - if (total_pwr_consumption <= 800) - { - if (!_sd_storage_switch(storage, buf, SD_SWITCH_SET, 0, hs_type)) - return 0; - - if (type_out != (buf[16] & 0xF)) - return 0; - - return 1; - } -DPRINTF("[SD] card max current over limit\n"); - - return 0; -} - -int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u8 *buf) -{ - if (sdmmc_get_bus_width(storage->sdmmc) != SDMMC_BUS_WIDTH_4) - return 0; - - if (!_sd_storage_switch_get(storage, buf)) - return 0; - //gfx_hexdump(0, (u8 *)buf, 64); - - u8 access_mode = buf[13]; - u16 current_limit = buf[7] | buf[6] << 8; -DPRINTF("[SD] access: %02X, current: %02X\n", access_mode, current_limit); - - // Try to raise the current limit to let the card perform better. - _sd_storage_set_current_limit(storage, current_limit, buf); - - u32 hs_type = 0; - switch (type) - { - case SDHCI_TIMING_UHS_SDR104: - case SDHCI_TIMING_UHS_SDR82: - // Fall through if not supported. - if (access_mode & SD_MODE_UHS_SDR104) - { - hs_type = UHS_SDR104_BUS_SPEED; -DPRINTF("[SD] bus speed set to SDR104\n"); - switch (type) - { - case SDHCI_TIMING_UHS_SDR104: - storage->csd.busspeed = 104; - break; - case SDHCI_TIMING_UHS_SDR82: - storage->csd.busspeed = 82; - break; - } - break; - } - case SDHCI_TIMING_UHS_SDR50: - if (access_mode & SD_MODE_UHS_SDR50) - { - type = SDHCI_TIMING_UHS_SDR50; - hs_type = UHS_SDR50_BUS_SPEED; -DPRINTF("[SD] bus speed set to SDR50\n"); - storage->csd.busspeed = 50; - break; - } - case SDHCI_TIMING_UHS_SDR25: - if (access_mode & SD_MODE_UHS_SDR25) - { - type = SDHCI_TIMING_UHS_SDR25; - hs_type = UHS_SDR25_BUS_SPEED; -DPRINTF("[SD] bus speed set to SDR25\n"); - storage->csd.busspeed = 25; - break; - } - case SDHCI_TIMING_UHS_SDR12: - if (!(access_mode & SD_MODE_UHS_SDR12)) - return 0; - type = SDHCI_TIMING_UHS_SDR12; - hs_type = UHS_SDR12_BUS_SPEED; -DPRINTF("[SD] bus speed set to SDR12\n"); - storage->csd.busspeed = 12; - break; - - default: - return 0; - break; - } - - if (!_sd_storage_enable_highspeed(storage, hs_type, buf)) - return 0; -DPRINTF("[SD] card accepted UHS\n"); - if (!sdmmc_setup_clock(storage->sdmmc, type)) - return 0; -DPRINTF("[SD] after setup clock\n"); - if (!sdmmc_tuning_execute(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK)) - return 0; -DPRINTF("[SD] after tuning\n"); - return _sdmmc_storage_check_status(storage); -} - -int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf) -{ - if (!_sd_storage_switch_get(storage, buf)) - return 0; - //gfx_hexdump(0, (u8 *)buf, 64); - - u8 access_mode = buf[13]; - u16 current_limit = buf[7] | buf[6] << 8; - - // Try to raise the current limit to let the card perform better. - _sd_storage_set_current_limit(storage, current_limit, buf); - - if (!(access_mode & SD_MODE_HIGH_SPEED)) - return 1; - - if (!_sd_storage_enable_highspeed(storage, HIGH_SPEED_BUS_SPEED, buf)) - return 0; - - if (!_sdmmc_storage_check_status(storage)) - return 0; - - return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25); -} - -static void _sd_storage_parse_cid(sdmmc_storage_t *storage) -{ - u32 *raw_cid = (u32 *)&(storage->raw_cid); - - storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); - storage->cid.oemid = unstuff_bits(raw_cid, 104, 16); - storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8); - storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8); - storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8); - storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8); - storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8); - storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4); - storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4); - storage->cid.serial = unstuff_bits(raw_cid, 24, 32); - storage->cid.month = unstuff_bits(raw_cid, 8, 4); - storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000; -} - -static void _sd_storage_parse_csd(sdmmc_storage_t *storage) -{ - u32 *raw_csd = (u32 *)&(storage->raw_csd); - - storage->csd.structure = unstuff_bits(raw_csd, 126, 2); - storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12); - storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4); - storage->csd.write_protect = unstuff_bits(raw_csd, 12, 2); - switch(storage->csd.structure) - { - case 0: - storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); - break; - - case 1: - storage->csd.c_size = (1 + unstuff_bits(raw_csd, 48, 22)); - storage->csd.capacity = storage->csd.c_size << 10; - storage->csd.read_blkbits = 9; - break; - } -} - -static bool _sdmmc_storage_get_low_voltage_support(u32 bus_width, u32 type) -{ - switch (type) - { - case SDHCI_TIMING_UHS_SDR12: - case SDHCI_TIMING_UHS_SDR25: - case SDHCI_TIMING_UHS_SDR50: - case SDHCI_TIMING_UHS_SDR104: - case SDHCI_TIMING_UHS_SDR82: - case SDHCI_TIMING_UHS_DDR50: - if (bus_width == SDMMC_BUS_WIDTH_4) - return true; - default: - return false; - } -} - -int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type) -{ - u8 buf[512]; - int is_version_1 = 0; - - memset(buf, 0, sizeof(buf)); - memset(storage, 0, sizeof(sdmmc_storage_t)); - storage->sdmmc = sdmmc; - - if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, SDMMC_POWER_SAVE_DISABLE)) - return 0; -DPRINTF("[SD] after init\n"); - - usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor); - - if (!_sdmmc_storage_go_idle_state(storage)) - return 0; -DPRINTF("[SD] went to idle state\n"); - - is_version_1 = _sd_storage_send_if_cond(storage); - if (is_version_1 == 2) - return 0; -DPRINTF("[SD] after send if cond\n"); - - bool bus_low_voltage_support = _sdmmc_storage_get_low_voltage_support(bus_width, type); - - if (!_sd_storage_get_op_cond(storage, is_version_1, bus_low_voltage_support)) - return 0; -DPRINTF("[SD] got op cond\n"); - - if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) - return 0; -DPRINTF("[SD] got cid\n"); - _sd_storage_parse_cid(storage); - - if (!_sd_storage_get_rca(storage)) - return 0; -DPRINTF("[SD] got rca (= %04X)\n", storage->rca); - - if (!_sdmmc_storage_get_csd(storage, storage->raw_csd)) - return 0; -DPRINTF("[SD] got csd\n"); - - //Parse CSD. - _sd_storage_parse_csd(storage); - switch (storage->csd.structure) - { - case 0: - storage->sec_cnt = storage->csd.capacity; - break; - case 1: - storage->sec_cnt = storage->csd.c_size << 10; - break; - default: -DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure); - break; - } - - if (!storage->is_low_voltage) - { - if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12)) - return 0; -DPRINTF("[SD] after setup clock\n"); - } - - if (!_sdmmc_storage_select_card(storage)) - return 0; -DPRINTF("[SD] card selected\n"); - - if (!_sdmmc_storage_set_blocklen(storage, 512)) - return 0; -DPRINTF("[SD] set blocklen to 512\n"); - - u32 tmp = 0; - if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN)) - return 0; -DPRINTF("[SD] cleared card detect\n"); - - if (!_sd_storage_get_scr(storage, buf)) - return 0; - - //gfx_hexdump(0, storage->raw_scr, 8); -DPRINTF("[SD] got scr\n"); - - // Check if card supports a wider bus and if it's not SD Version 1.X - if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF)) - { - if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN)) - return 0; - - sdmmc_set_bus_width(storage->sdmmc, SDMMC_BUS_WIDTH_4); -DPRINTF("[SD] switched to wide bus width\n"); - } - else - { -DPRINTF("[SD] SD does not support wide bus width\n"); - } - - if (storage->is_low_voltage) - { - if (!_sd_storage_enable_uhs_low_volt(storage, type, buf)) - return 0; -DPRINTF("[SD] enabled UHS\n"); - - sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); - } - else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF) != 0) - { - if (!_sd_storage_enable_hs_high_volt(storage, buf)) - return 0; - -DPRINTF("[SD] enabled HS\n"); - switch (bus_width) - { - case SDMMC_BUS_WIDTH_4: - storage->csd.busspeed = 25; - break; - - case SDMMC_BUS_WIDTH_1: - storage->csd.busspeed = 6; - break; - } - } - - storage->initialized = 1; - - return 1; -} - -/* -* Gamecard specific functions. -*/ - -int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf) -{ - u32 resp; - sdmmc_cmd_t cmdbuf; - sdmmc_init_cmd(&cmdbuf, 60, 0, SDMMC_RSP_TYPE_1, 1); - - sdmmc_req_t reqbuf; - reqbuf.buf = buf; - reqbuf.blksize = 64; - reqbuf.num_sectors = 1; - reqbuf.is_write = 1; - reqbuf.is_multi_block = 0; - reqbuf.is_auto_cmd12 = 0; - - if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, 0)) - { - sdmmc_stop_transmission(storage->sdmmc, &resp); - return 0; - } - - if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1)) - return 0; - if (!_sdmmc_storage_check_result(resp)) - return 0; - return _sdmmc_storage_check_status(storage); -} - -int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc) -{ - memset(storage, 0, sizeof(sdmmc_storage_t)); - storage->sdmmc = sdmmc; - - if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS102, SDMMC_POWER_SAVE_DISABLE)) - return 0; -DPRINTF("[gc] after init\n"); - - usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor); - - if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS102, MMC_SEND_TUNING_BLOCK_HS200)) - return 0; -DPRINTF("[gc] after tuning\n"); - - sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); - - storage->initialized = 1; - - return 1; -} diff --git a/emummc/source/emmc/sdmmc.h b/emummc/source/emmc/sdmmc.h deleted file mode 100644 index 536bd8d2b4..0000000000 --- a/emummc/source/emmc/sdmmc.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _SDMMC_H_ -#define _SDMMC_H_ - -#include "../utils/types.h" -#include "../FS/FS.h" -#include "sdmmc_driver.h" - -typedef struct _mmc_cid -{ - u32 manfid; - u8 prod_name[8]; - u8 card_bga; - u8 prv; - u32 serial; - u16 oemid; - u16 year; - u8 hwrev; - u8 fwrev; - u8 month; -} mmc_cid_t; - -typedef struct _mmc_csd -{ - u8 structure; - u8 mmca_vsn; - u16 cmdclass; - u32 c_size; - u32 r2w_factor; - u32 max_dtr; - u32 erase_size; /* In sectors */ - u32 read_blkbits; - u32 write_blkbits; - u32 capacity; - u8 write_protect; - u16 busspeed; -} mmc_csd_t; - -typedef struct _mmc_ext_csd -{ - u32 sectors; - int bkops; /* background support bit */ - int bkops_en; /* manual bkops enable bit */ - u8 rev; - u8 ext_struct; /* 194 */ - u8 card_type; /* 196 */ - u8 bkops_status; /* 246 */ - u8 pre_eol_info; - u8 dev_life_est_a; - u8 dev_life_est_b; - u8 boot_mult; - u8 rpmb_mult; - u16 dev_version; -} mmc_ext_csd_t; - -typedef struct _sd_scr -{ - u8 sda_vsn; - u8 sda_spec3; - u8 bus_widths; - u8 cmds; -} sd_scr_t; - -typedef struct _sd_ssr -{ - u8 bus_width; - u8 speed_class; - u8 uhs_grade; - u8 video_class; - u8 app_class; - u32 protected_size; -} sd_ssr_t; - -/*! SDMMC storage context. */ -typedef struct _sdmmc_storage_t -{ - sdmmc_t *sdmmc; - u32 rca; - int has_sector_access; - u32 sec_cnt; - int is_low_voltage; - u32 partition; - u8 raw_cid[0x10]; - u8 raw_csd[0x10]; - u8 raw_scr[8]; - mmc_cid_t cid; - mmc_csd_t csd; - mmc_ext_csd_t ext_csd; - sd_scr_t scr; - int initialized; -} sdmmc_storage_t; - -extern sdmmc_accessor_t *_current_accessor; -extern bool sdmmc_memcpy_buf; - -int sdmmc_storage_end(sdmmc_storage_t *storage); -int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); -int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf); -int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type); -int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition); -int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type); -int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); -intptr_t sdmmc_calculate_dma_addr(sdmmc_accessor_t *_this, void *buf, unsigned int num_sectors); -int sdmmc_calculate_dma_index(sdmmc_accessor_t *_this, void *buf, unsigned int num_sectors); -int sdmmc_calculate_fitting_dma_index(sdmmc_accessor_t *_this, unsigned int num_sectors); - -#endif diff --git a/emummc/source/emmc/sdmmc_driver.c b/emummc/source/emmc/sdmmc_driver.c deleted file mode 100644 index 64b2ba0851..0000000000 --- a/emummc/source/emmc/sdmmc_driver.c +++ /dev/null @@ -1,1429 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include "mmc.h" -#include "sdmmc.h" -#include "../nx/cache.h" -#include "../power/max7762x.h" -#include "../soc/clock.h" -#include "../soc/gpio.h" -#include "../soc/pinmux.h" -#include "../soc/pmc.h" -#include "../soc/t210.h" -#include "../utils/fatal.h" -#include "../utils/types.h" -#include "../utils/util.h" - -#define DPRINTF(...) - -/*! SCMMC controller base addresses. */ -static const u64 _sdmmc_bases[4] = { - 0x700B0000, - 0x700B0200, - 0x700B0400, - 0x700B0600, -}; - -int sdmmc_get_io_power(sdmmc_t *sdmmc) -{ - u32 p = sdmmc->regs->pwrcon; - if (!(p & SDHCI_POWER_ON)) - return SDMMC_POWER_OFF; - if (p & SDHCI_POWER_180) - return SDMMC_POWER_1_8; - if (p & SDHCI_POWER_330) - return SDMMC_POWER_3_3; - return -1; -} - -static int _sdmmc_set_io_power(sdmmc_t *sdmmc, u32 power) -{ - switch (power) - { - case SDMMC_POWER_OFF: - sdmmc->regs->pwrcon &= ~SDHCI_POWER_ON; - break; - - case SDMMC_POWER_1_8: - sdmmc->regs->pwrcon = SDHCI_POWER_180; - break; - - case SDMMC_POWER_3_3: - sdmmc->regs->pwrcon = SDHCI_POWER_330; - break; - - default: - return 0; - } - - if (power != SDMMC_POWER_OFF) - sdmmc->regs->pwrcon |= SDHCI_POWER_ON; - - return 1; -} - -u32 sdmmc_get_bus_width(sdmmc_t *sdmmc) -{ - u32 h = sdmmc->regs->hostctl; - if (h & SDHCI_CTRL_8BITBUS) - return SDMMC_BUS_WIDTH_8; - if (h & SDHCI_CTRL_4BITBUS) - return SDMMC_BUS_WIDTH_4; - return SDMMC_BUS_WIDTH_1; -} - -void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width) -{ - u32 host_control = sdmmc->regs->hostctl & ~(SDHCI_CTRL_4BITBUS | SDHCI_CTRL_8BITBUS); - - if (bus_width == SDMMC_BUS_WIDTH_1) - sdmmc->regs->hostctl = host_control; - else if (bus_width == SDMMC_BUS_WIDTH_4) - sdmmc->regs->hostctl = host_control | SDHCI_CTRL_4BITBUS; - else if (bus_width == SDMMC_BUS_WIDTH_8) - sdmmc->regs->hostctl = host_control | SDHCI_CTRL_8BITBUS; -} - -void sdmmc_save_tap_value(sdmmc_t *sdmmc) -{ - sdmmc->venclkctl_tap = sdmmc->regs->venclkctl >> 16; - sdmmc->venclkctl_set = 1; -} - -static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type) -{ - const u32 dqs_trim_val = 0x28; - const u32 tap_values_t210[] = { 4, 0, 3, 0 }; - - u32 tap_val = 0; - - if (type == SDHCI_TIMING_MMC_HS400) - sdmmc->regs->vencapover = (sdmmc->regs->vencapover & 0xFFFFC0FF) | (dqs_trim_val << 8); - - sdmmc->regs->ventunctl0 &= ~TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW; - - if (type == SDHCI_TIMING_MMC_HS400) - { - if (!sdmmc->venclkctl_set) - return 0; - - tap_val = sdmmc->venclkctl_tap; - } - else - tap_val = sdmmc->t210b01 ? 11 : tap_values_t210[sdmmc->id]; - - sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xFF00FFFF) | (tap_val << 16); - - return 1; -} - -static int _sdmmc_commit_changes(sdmmc_t *sdmmc) -{ - return sdmmc->regs->clkcon; -} - -static void _sdmmc_pad_config_fallback(sdmmc_t *sdmmc, u32 power) -{ - _sdmmc_commit_changes(sdmmc); - switch (sdmmc->id) - { - case SDMMC_1: // 33 Ohm 2X Driver. - if (power == SDMMC_POWER_OFF) - break; - u32 sdmmc1_pad_cfg = APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) & 0xF8080FFF; - if (sdmmc->t210b01) - sdmmc1_pad_cfg |= (0x808 << 12); // Up: 8, Dn: 8. For 33 ohm. - else if (power == SDMMC_POWER_1_8) - sdmmc1_pad_cfg |= (0xB0F << 12); // Up: 11, Dn: 15. For 33 ohm. - else if (power == SDMMC_POWER_3_3) - sdmmc1_pad_cfg |= (0xC0C << 12); // Up: 12, Dn: 12. For 33 ohm. - APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = sdmmc1_pad_cfg; - (void)APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL); // Commit write. - break; - - case SDMMC_2: - if (sdmmc->t210b01) - APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) & 0xF8080FFF) | 0xA0A000; - else - APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) & 0xFFFFC003) | 0x1040; // PU:16, PD:16. - (void)APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL); - break; - - case SDMMC_4: // 50 Ohm 2X Driver. PU:16, PD:16, B01: PU:10, PD:10. - APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) = - (APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) & 0xFFFFC003) | (sdmmc->t210b01 ? 0xA28 : 0x1040); - (void)APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL); // Commit write. - break; - } -} - -static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power) -{ - bool should_enable_sd_clock = false; - if (sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN) - { - should_enable_sd_clock = true; - sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; - } - - // Enable E_INPUT power. - if (!(sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD)) - { - sdmmc->regs->sdmemcmppadctl |= TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD; - _sdmmc_commit_changes(sdmmc); - usleep(1); - } - - // Enable auto calibration and start auto configuration. - sdmmc->regs->autocalcfg |= TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE | TEGRA_MMC_AUTOCALCFG_AUTO_CAL_START; - _sdmmc_commit_changes(sdmmc); - usleep(2); - - u64 timeout = get_tmr_ms() + 10; - while (sdmmc->regs->autocalsts & TEGRA_MMC_AUTOCALSTS_AUTO_CAL_ACTIVE) - { - if (get_tmr_ms() > timeout) - { - timeout = 0; // Set timeout to 0 if we timed out. - break; - } - } - -#if 0 - // Check if Comp pad is open or short to ground. - // SDMMC1: CZ pads - T210/T210B01: 7-bit/5-bit. SDMMC2/4: LV_CZ pads - 5-bit. - u8 code_mask = (sdmmc->t210b01 || sdmmc->id != SDMMC_1) ? 0x1F : 0x7F; - u8 autocal_pu_status = sdmmc->regs->autocalsts & code_mask; - if (!autocal_pu_status) - EPRINTF("SDMMC: Comp Pad short to gnd!"); - else if (autocal_pu_status == code_mask) - EPRINTF("SDMMC: Comp Pad open!"); -#endif - - // In case auto calibration fails, we load suggested standard values. - if (!timeout) - { - _sdmmc_pad_config_fallback(sdmmc, power); - sdmmc->regs->autocalcfg &= ~TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE; - } - - // Disable E_INPUT to conserve power. - sdmmc->regs->sdmemcmppadctl &= ~TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD; - - if(should_enable_sd_clock) - sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; -} - -static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc) -{ - int result = 1, should_disable_sd_clock = 0; - - if (!(sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN)) - { - should_disable_sd_clock = 1; - sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; - } - - sdmmc->regs->vendllcalcfg |= TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE; - _sdmmc_commit_changes(sdmmc); - - u64 timeout = get_tmr_ms() + 5; - while (sdmmc->regs->vendllcalcfg & TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE) - { - if (get_tmr_ms() > timeout) - { - result = 0; - goto out; - } - } - - timeout = get_tmr_ms() + 10; - while (sdmmc->regs->vendllcalcfgsts & TEGRA_MMC_DLLCAL_CFG_STATUS_DLL_ACTIVE) - { - if (get_tmr_ms() > timeout) - { - result = 0; - goto out; - } - } - -out:; - if (should_disable_sd_clock) - sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; - return result; -} - -static void _sdmmc_reset(sdmmc_t *sdmmc) -{ - sdmmc->regs->swrst |= SDHCI_RESET_CMD | SDHCI_RESET_DATA; - _sdmmc_commit_changes(sdmmc); - u64 timeout = get_tmr_ms() + 2000; - while ((sdmmc->regs->swrst & (SDHCI_RESET_CMD | SDHCI_RESET_DATA)) && get_tmr_ms() < timeout) - ; -} - -static void _sdmmc_reset_all(sdmmc_t *sdmmc) -{ - sdmmc->regs->swrst |= SDHCI_RESET_ALL; - _sdmmc_commit_changes(sdmmc); - u32 timeout = get_tmr_ms() + 2000;//100ms - while ((sdmmc->regs->swrst & SDHCI_RESET_ALL) && get_tmr_ms() < timeout) - ; -} - -int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) -{ - // Disable the SD clock if it was enabled, and reenable it later. - bool should_enable_sd_clock = false; - if (sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN) - { - should_enable_sd_clock = true; - sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; - } - - _sdmmc_config_tap_val(sdmmc, type); - - _sdmmc_reset(sdmmc); - - switch (type) - { - case SDHCI_TIMING_MMC_ID: - case SDHCI_TIMING_MMC_LS26: - case SDHCI_TIMING_SD_ID: - case SDHCI_TIMING_SD_DS12: - sdmmc->regs->hostctl &= ~SDHCI_CTRL_HISPD; - sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_VDD_180; - break; - - case SDHCI_TIMING_MMC_HS52: - case SDHCI_TIMING_SD_HS25: - sdmmc->regs->hostctl |= SDHCI_CTRL_HISPD; - sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_VDD_180; - break; - - case SDHCI_TIMING_MMC_HS200: - case SDHCI_TIMING_UHS_SDR50: // T210 Errata for SDR50, the host must be set to SDR104. - case SDHCI_TIMING_UHS_SDR104: - case SDHCI_TIMING_UHS_SDR82: - case SDHCI_TIMING_UHS_DDR50: - case SDHCI_TIMING_MMC_HS102: - sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR104_BUS_SPEED; - sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; - break; - - case SDHCI_TIMING_MMC_HS400: - // Non standard. - sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | HS400_BUS_SPEED; - sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; - break; - - case SDHCI_TIMING_UHS_SDR25: - sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR25_BUS_SPEED; - sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; - break; - - case SDHCI_TIMING_UHS_SDR12: - sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR12_BUS_SPEED; - sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; - break; - } - - _sdmmc_commit_changes(sdmmc); - - u32 clock; - u16 divisor; - clock_sdmmc_get_card_clock_div(&clock, &divisor, type); - clock_sdmmc_config_clock_source(&clock, sdmmc->id, clock); - sdmmc->divisor = (clock + divisor - 1) / divisor; - - //if divisor != 1 && divisor << 31 -> error - - u16 div = divisor >> 1; - divisor = 0; - if (div > 0xFF) - divisor = div >> SDHCI_DIVIDER_SHIFT; - - sdmmc->regs->clkcon = (sdmmc->regs->clkcon & ~(SDHCI_DIV_MASK | SDHCI_DIV_HI_MASK)) - | (div << SDHCI_DIVIDER_SHIFT) | (divisor << SDHCI_DIVIDER_HI_SHIFT); - - // Enable the SD clock again. - if (should_enable_sd_clock) - sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; - - if (type == SDHCI_TIMING_MMC_HS400) - return _sdmmc_dll_cal_execute(sdmmc); - return 1; -} - -static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc) -{ - // Recalibrate conditionally. - if (sdmmc->manual_cal && !sdmmc->powersave_enabled) - _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); - - if (!sdmmc->powersave_enabled) - { - if (!(sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN)) - sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; - } - sdmmc->card_clock_enabled = 1; -} - -static void _sdmmc_sd_clock_disable(sdmmc_t *sdmmc) -{ - sdmmc->card_clock_enabled = 0; - sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; -} - -void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable) -{ - // Recalibrate periodically for SDMMC1. - if (sdmmc->manual_cal && !powersave_enable && sdmmc->card_clock_enabled) - _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); - - sdmmc->powersave_enabled = powersave_enable; - if (powersave_enable) - { - if (sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN) - sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; - return; - } - - if (sdmmc->card_clock_enabled) - if (!(sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN)) - sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; -} - -static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type) -{ - switch (type) - { - case SDMMC_RSP_TYPE_1: - case SDMMC_RSP_TYPE_3: - case SDMMC_RSP_TYPE_4: - case SDMMC_RSP_TYPE_5: - if (size < 4) - return 0; - rsp[0] = sdmmc->regs->rspreg0; - break; - - case SDMMC_RSP_TYPE_2: - if (size < 0x10) - return 0; - // CRC is stripped, so shifting is needed. - u32 tempreg; - for (int i = 0; i < 4; i++) - { - switch(i) - { - case 0: - tempreg = sdmmc->regs->rspreg3; - break; - case 1: - tempreg = sdmmc->regs->rspreg2; - break; - case 2: - tempreg = sdmmc->regs->rspreg1; - break; - case 3: - tempreg = sdmmc->regs->rspreg0; - break; - } - rsp[i] = tempreg << 8; - - if (i != 0) - rsp[i - 1] |= (tempreg >> 24) & 0xFF; - } - break; - - default: - return 0; - } - - return 1; -} - -int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type) -{ - if (!rsp || sdmmc->expected_rsp_type != type) - return 0; - - switch (type) - { - case SDMMC_RSP_TYPE_1: - case SDMMC_RSP_TYPE_3: - case SDMMC_RSP_TYPE_4: - case SDMMC_RSP_TYPE_5: - if (size < 4) - return 0; - rsp[0] = sdmmc->rsp[0]; - break; - - case SDMMC_RSP_TYPE_2: - if (size < 0x10) - return 0; - rsp[0] = sdmmc->rsp[0]; - rsp[1] = sdmmc->rsp[1]; - rsp[2] = sdmmc->rsp[2]; - rsp[3] = sdmmc->rsp[3]; - break; - - default: - return 0; - } - - return 1; -} - -static int _sdmmc_wait_cmd_data_inhibit(sdmmc_t *sdmmc, bool wait_dat) -{ - _sdmmc_commit_changes(sdmmc); - - u64 timeout = get_tmr_ms() + 2000; - while(sdmmc->regs->prnsts & SDHCI_CMD_INHIBIT) - if (get_tmr_ms() > timeout) - { - _sdmmc_reset(sdmmc); - return 0; - } - - if (wait_dat) - { - timeout = get_tmr_ms() + 2000; - while (sdmmc->regs->prnsts & SDHCI_DATA_INHIBIT) - if (get_tmr_ms() > timeout) - { - _sdmmc_reset(sdmmc); - return 0; - } - } - - return 1; -} - -static int _sdmmc_wait_card_busy(sdmmc_t *sdmmc) -{ - _sdmmc_commit_changes(sdmmc); - - u64 timeout = get_tmr_ms() + 2000; - while (!(sdmmc->regs->prnsts & SDHCI_DATA_0_LVL_MASK)) - if (get_tmr_ms() > timeout) - { - _sdmmc_reset(sdmmc); - return 0; - } - - return 1; -} - -static int _sdmmc_setup_read_small_block(sdmmc_t *sdmmc) -{ - switch (sdmmc_get_bus_width(sdmmc)) - { - case SDMMC_BUS_WIDTH_1: - return 0; - - case SDMMC_BUS_WIDTH_4: - sdmmc->regs->blksize = 64; - break; - - case SDMMC_BUS_WIDTH_8: - sdmmc->regs->blksize = 128; - break; - } - - sdmmc->regs->blkcnt = 1; - sdmmc->regs->trnmod = SDHCI_TRNS_READ; - - return 1; -} - -static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_present) -{ - u16 cmdflags = 0; - - switch (cmd->rsp_type) - { - case SDMMC_RSP_TYPE_0: - break; - - case SDMMC_RSP_TYPE_1: - case SDMMC_RSP_TYPE_4: - case SDMMC_RSP_TYPE_5: - if (cmd->check_busy) - cmdflags = SDHCI_CMD_RESP_LEN48_BUSY | SDHCI_CMD_INDEX | SDHCI_CMD_CRC; - else - cmdflags = SDHCI_CMD_RESP_LEN48 | SDHCI_CMD_INDEX | SDHCI_CMD_CRC; - break; - - case SDMMC_RSP_TYPE_2: - cmdflags = SDHCI_CMD_RESP_LEN136 | SDHCI_CMD_CRC; - break; - - case SDMMC_RSP_TYPE_3: - cmdflags = SDHCI_CMD_RESP_LEN48; - break; - - default: - return 0; - } - - if (is_data_present) - cmdflags |= SDHCI_CMD_DATA; - sdmmc->regs->argument = cmd->arg; - sdmmc->regs->cmdreg = (cmd->cmd << 8) | cmdflags; - - return 1; -} - -static void _sdmmc_send_tuning_cmd(sdmmc_t *sdmmc, u32 cmd) -{ - sdmmc_cmd_t cmdbuf; - cmdbuf.cmd = cmd; - cmdbuf.arg = 0; - cmdbuf.rsp_type = SDMMC_RSP_TYPE_1; - cmdbuf.check_busy = 0; - _sdmmc_send_cmd(sdmmc, &cmdbuf, true); -} - -static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd) -{ - if (sdmmc->powersave_enabled) - return 0; - if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, true)) - return 0; - - _sdmmc_setup_read_small_block(sdmmc); - - sdmmc->regs->norintstsen |= SDHCI_INT_DATA_AVAIL; - sdmmc->regs->norintsts = sdmmc->regs->norintsts; - sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; - - _sdmmc_send_tuning_cmd(sdmmc, cmd); - _sdmmc_commit_changes(sdmmc); - usleep(1); - - _sdmmc_reset(sdmmc); - - sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; - _sdmmc_commit_changes(sdmmc); - - u64 timeout = get_tmr_us() + 5000; - while (get_tmr_us() < timeout) - { - if (sdmmc->regs->norintsts & SDHCI_INT_DATA_AVAIL) - { - sdmmc->regs->norintsts = SDHCI_INT_DATA_AVAIL; - sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL; - _sdmmc_commit_changes(sdmmc); - usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); - return 1; - } - } - - _sdmmc_reset(sdmmc); - - sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL; - _sdmmc_commit_changes(sdmmc); - usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); - - return 0; -} - -int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd) -{ - u32 max = 0, flag = 0; - - switch (type) - { - case SDHCI_TIMING_MMC_HS200: - case SDHCI_TIMING_MMC_HS400: - case SDHCI_TIMING_UHS_SDR104: - case SDHCI_TIMING_UHS_SDR82: - max = 128; - flag = (2 << 13); // 128 iterations. - break; - - case SDHCI_TIMING_UHS_SDR50: - case SDHCI_TIMING_UHS_DDR50: - case SDHCI_TIMING_MMC_HS102: - max = 256; - flag = (4 << 13); // 256 iterations. - break; - - case SDHCI_TIMING_UHS_SDR12: - case SDHCI_TIMING_UHS_SDR25: - return 1; - - default: - return 0; - } - - sdmmc->regs->ventunctl1 = 0; // step_size 1. - - sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; // Tries. - sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | (1 << 6); // 1x Multiplier. - sdmmc->regs->ventunctl0 |= TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW; - sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING; - - for (u32 i = 0; i < max; i++) - { - _sdmmc_tuning_execute_once(sdmmc, cmd); - if (!(sdmmc->regs->hostctl2 & SDHCI_CTRL_EXEC_TUNING)) - break; - } - - if (sdmmc->regs->hostctl2 & SDHCI_CTRL_TUNED_CLK) - return 1; - - return 0; -} - -static int _sdmmc_enable_internal_clock(sdmmc_t *sdmmc) -{ - //Enable internal clock and wait till it is stable. - sdmmc->regs->clkcon |= SDHCI_CLOCK_INT_EN; - _sdmmc_commit_changes(sdmmc); - u64 timeout = get_tmr_ms() + 2000; - while (!(sdmmc->regs->clkcon & SDHCI_CLOCK_INT_STABLE)) - { - if (get_tmr_ms() > timeout) - return 0; - } - - sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_PRESET_VAL_EN; - sdmmc->regs->clkcon &= ~SDHCI_PROG_CLOCK_MODE; - sdmmc->regs->hostctl2 |= SDHCI_HOST_VERSION_4_EN; - - if (!(sdmmc->regs->capareg & SDHCI_CAN_64BIT)) - return 0; - - sdmmc->regs->hostctl2 |= SDHCI_ADDRESSING_64BIT_EN; - sdmmc->regs->hostctl &= ~SDHCI_CTRL_DMA_MASK; - sdmmc->regs->timeoutcon = (sdmmc->regs->timeoutcon & 0xF0) | 0xE; - - return 1; -} - -static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power) -{ - u32 off_pd = 0; - u32 off_pu = 0; - - switch (sdmmc->id) - { - case SDMMC_2: - case SDMMC_4: - if (power != SDMMC_POWER_1_8) - return 0; - off_pd = 5; - off_pu = 5; - break; - - case SDMMC_1: - if (power == SDMMC_POWER_1_8) - { - if (!sdmmc->t210b01) - { - off_pd = 123; - off_pu = 123; - } - else - { - off_pd = 6; - off_pu = 6; - } - } - else if (power == SDMMC_POWER_3_3) - { - if (!sdmmc->t210b01) - { - off_pd = 125; - off_pu = 0; - } - } - else - return 0; - break; - } - - sdmmc->regs->autocalcfg = (sdmmc->regs->autocalcfg & 0xFFFF8080) | (off_pd << 8) | off_pu; - return 1; -} - -static void _sdmmc_enable_interrupts(sdmmc_t *sdmmc) -{ - sdmmc->regs->norintstsen |= SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE; - sdmmc->regs->errintstsen |= SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR; - sdmmc->regs->norintsts = sdmmc->regs->norintsts; - sdmmc->regs->errintsts = sdmmc->regs->errintsts; -} - -static void _sdmmc_mask_interrupts(sdmmc_t *sdmmc) -{ - sdmmc->regs->errintstsen &= ~SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR; - sdmmc->regs->norintstsen &= ~(SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); -} - -static int _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask) -{ - u16 norintsts = sdmmc->regs->norintsts; - u16 errintsts = sdmmc->regs->errintsts; - -DPRINTF("norintsts %08X, errintsts %08X\n", norintsts, errintsts); - - if (pout) - *pout = norintsts; - - // Check for error interrupt. - if (norintsts & SDHCI_INT_ERROR) - { - sdmmc->regs->errintsts = errintsts; - return SDMMC_MASKINT_ERROR; - } - else if (norintsts & mask) - { - sdmmc->regs->norintsts = norintsts & mask; - return SDMMC_MASKINT_MASKED; - } - - return SDMMC_MASKINT_NOERROR; -} - -static int _sdmmc_wait_response(sdmmc_t *sdmmc) -{ - _sdmmc_commit_changes(sdmmc); - - u64 timeout = get_tmr_ms() + 2000; - while (true) - { - int result = _sdmmc_check_mask_interrupt(sdmmc, NULL, SDHCI_INT_RESPONSE); - if (result == SDMMC_MASKINT_MASKED) - break; - if (result != SDMMC_MASKINT_NOERROR || get_tmr_ms() > timeout) - { - _sdmmc_reset(sdmmc); - return 0; - } - } - - return 1; -} - -static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp) -{ - sdmmc_cmd_t cmd; - - if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, false)) - return 0; - - _sdmmc_enable_interrupts(sdmmc); - - cmd.cmd = MMC_STOP_TRANSMISSION; - cmd.arg = 0; - cmd.rsp_type = SDMMC_RSP_TYPE_1; - cmd.check_busy = 1; - - _sdmmc_send_cmd(sdmmc, &cmd, false); - - int result = _sdmmc_wait_response(sdmmc); - _sdmmc_mask_interrupts(sdmmc); - - if (!result) - return 0; - - _sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1); - - return _sdmmc_wait_card_busy(sdmmc); -} - -int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp) -{ - if (!sdmmc->card_clock_enabled) - return 0; - - // Recalibrate periodically for SDMMC1. - if (sdmmc->manual_cal && sdmmc->powersave_enabled) - _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); - - bool should_disable_sd_clock = false; - if (!(sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN)) - { - should_disable_sd_clock = true; - sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; - _sdmmc_commit_changes(sdmmc); - usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); - } - - int result = _sdmmc_stop_transmission_inner(sdmmc, rsp); - usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); - - if (should_disable_sd_clock) - sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; - - return result; -} - -static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req) -{ - if (!req->blksize || !req->num_sectors) - return 0; - - u32 blkcnt = req->num_sectors; - if (blkcnt >= 0xFFFF) - blkcnt = 0xFFFF; - - u64 admaaddr = (u64)sdmmc_calculate_dma_addr(_current_accessor, req->buf, blkcnt); - if (!admaaddr) - { - // buf is on a heap - int dma_idx = sdmmc_calculate_fitting_dma_index(_current_accessor, blkcnt); - admaaddr = (u64)&_current_accessor->parent->dmaBuffers[dma_idx].device_addr_buffer_masked[0]; - sdmmc->last_dma_idx = dma_idx; - } - - // Check alignment. - if (admaaddr & 7) - return 0; - - sdmmc->regs->admaaddr = admaaddr & 0xFFFFFFFFF; - sdmmc->regs->admaaddr_hi = (admaaddr >> 32) & 0xFFFFFFFFF; - - sdmmc->dma_addr_next = (admaaddr + 0x80000) & 0xFFFFFFFFFFF80000; - - sdmmc->regs->blksize = req->blksize | 0x7000; // DMA 512KB (Detects A18 carry out). - sdmmc->regs->blkcnt = blkcnt; - - if (blkcnt_out) - *blkcnt_out = blkcnt; - - u32 trnmode = SDHCI_TRNS_DMA; - if (req->is_multi_block) - trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA; - if (!req->is_write) - trnmode |= SDHCI_TRNS_READ; - if (req->is_auto_cmd12) - trnmode = (trnmode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23)) | SDHCI_TRNS_AUTO_CMD12; - - sdmmc->regs->trnmod = trnmode; - - return 1; -} - -static int _sdmmc_update_dma(sdmmc_t *sdmmc) -{ - u16 blkcnt = 0; - do - { - blkcnt = sdmmc->regs->blkcnt; - u64 timeout = get_tmr_ms() + 1500; - do - { - int result = 0; - while (true) - { - u16 intr = 0; - result = _sdmmc_check_mask_interrupt(sdmmc, &intr, - SDHCI_INT_DATA_END | SDHCI_INT_DMA_END); - if (result < 0) - break; - - if (intr & SDHCI_INT_DATA_END) - return 1; // Transfer complete. - - if (intr & SDHCI_INT_DMA_END) - { - // Update DMA. - sdmmc->regs->admaaddr = sdmmc->dma_addr_next & 0xFFFFFFFFF; - sdmmc->regs->admaaddr_hi = (sdmmc->dma_addr_next >> 32) & 0xFFFFFFFFF; - sdmmc->dma_addr_next += 0x80000; - } - } - if (result != SDMMC_MASKINT_NOERROR) - { - _sdmmc_reset(sdmmc); - return 0; - } - } while (get_tmr_ms() < timeout); - } while (sdmmc->regs->blkcnt != blkcnt); - - _sdmmc_reset(sdmmc); - return 0; -} - -static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out) -{ - int has_req_or_check_busy = req || cmd->check_busy; - if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, has_req_or_check_busy)) - return 0; - - u32 blkcnt = 0; - bool is_data_present = false; - if (req) - { - if (!_sdmmc_config_dma(sdmmc, &blkcnt, req)) - return 0; - - if(!sdmmc_memcpy_buf) - { - // Flush from/to phys - armDCacheFlush(req->buf, req->blksize * blkcnt); - } - else - { - if(req->is_write) - { - void* dma_addr = &_current_accessor->parent->dmaBuffers[sdmmc->last_dma_idx].device_addr_buffer[0]; - memcpy(dma_addr, req->buf, req->blksize * blkcnt); - - // Flush to phys - armDCacheFlush(dma_addr, req->blksize * blkcnt); - } - } - - is_data_present = true; - } - - _sdmmc_enable_interrupts(sdmmc); - - if (!_sdmmc_send_cmd(sdmmc, cmd, is_data_present)) - return 0; - - int result = _sdmmc_wait_response(sdmmc); -DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, - sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3); - if (result) - { - if (cmd->rsp_type) - { - sdmmc->expected_rsp_type = cmd->rsp_type; - result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type); - } - - if (req && result) - result = _sdmmc_update_dma(sdmmc); - } - - _sdmmc_mask_interrupts(sdmmc); - - if (result) - { - if (req) - { - if(!req->is_write) - { - if(!sdmmc_memcpy_buf) - { - // Flush from phys - armDCacheFlush(req->buf, req->blksize * blkcnt); - } - else - { - void* dma_addr = &_current_accessor->parent->dmaBuffers[sdmmc->last_dma_idx].device_addr_buffer[0]; - // Flush from phys - armDCacheFlush(dma_addr, req->blksize * blkcnt); - // Copy to buffer - memcpy(req->buf, dma_addr, req->blksize * blkcnt); - } - } - - if (blkcnt_out) - *blkcnt_out = blkcnt; - - if (req->is_auto_cmd12) - sdmmc->rsp3 = sdmmc->regs->rspreg3; - } - - if (cmd->check_busy || req) - return _sdmmc_wait_card_busy(sdmmc); - } - - return result; -} - -int sdmmc_get_sd_power_enabled() -{ - return gpio_read(GPIO_PORT_E, GPIO_PIN_4); -} - -bool sdmmc_get_sd_inserted() -{ - return (!gpio_read(GPIO_PORT_Z, GPIO_PIN_1)); -} - -static void _sdmmc_config_sdmmc1_schmitt() -{ - PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT2) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) |= PINMUX_SCHMT; -} - -static void _sdmmc_config_sdmmc2_schmitt() -{ - PINMUX_AUX(PINMUX_AUX_SDMMC2_CLK) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC2_CMD) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT7) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT6) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT5) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT4) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT3) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT2) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT1) |= PINMUX_SCHMT; - PINMUX_AUX(PINMUX_AUX_SDMMC2_DAT0) |= PINMUX_SCHMT; -} - -static void _sdmmc_config_sdmmc1_pads(bool discharge) -{ - u32 sdmmc1_pin_mask = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; - - // Set values for Reset state. - u32 function = GPIO_MODE_SPIO; - u32 level = GPIO_LOW; - u32 output = GPIO_OUTPUT_DISABLE; - - // Set values for dicharging. - if (discharge) - { - function = GPIO_MODE_GPIO; - level = GPIO_HIGH; - output = GPIO_OUTPUT_ENABLE; - } - - // Set all pads function. - gpio_config(GPIO_PORT_M, sdmmc1_pin_mask, function); - // Set all pads output level. - gpio_write(GPIO_PORT_M, sdmmc1_pin_mask, level); - // Set all pads output. - gpio_output_enable(GPIO_PORT_M, sdmmc1_pin_mask, output); -} - -static int _sdmmc_config_sdmmc1(bool t210b01) -{ - // Configure SD card detect. - PINMUX_AUX(PINMUX_AUX_GPIO_PZ1) = PINMUX_INPUT_ENABLE | PINMUX_PULL_UP | 2; // GPIO control, pull up. - APB_MISC(APB_MISC_GP_VGPIO_GPIO_MUX_SEL) = 0; - gpio_config(GPIO_PORT_Z, GPIO_PIN_1, GPIO_MODE_GPIO); - gpio_output_enable(GPIO_PORT_Z, GPIO_PIN_1, GPIO_OUTPUT_DISABLE); - usleep(100); - - // Check if SD card is inserted. - if(!sdmmc_get_sd_inserted()) - return 0; - - /* - * Pinmux config: - * DRV_TYPE = DRIVE_2X (for 33 Ohm driver) - * E_SCHMT = ENABLE (for 1.8V), DISABLE (for 3.3V) - * E_INPUT = ENABLE - * TRISTATE = PASSTHROUGH - * APB_MISC_GP_SDMMCx_CLK_LPBK_CONTROL = SDMMCx_CLK_PAD_E_LPBK for CLK - */ - - // Enable deep loopback for SDMMC1 CLK pad. - APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; - - // Configure SDMMC1 CLK pinmux, based on state and SoC type. - if (PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) != (PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN)) // Check if CLK pad is already configured. - PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | (t210b01 ? PINMUX_PULL_NONE : PINMUX_PULL_DOWN); - - // Configure the reset of SDMMC1 pins pinmux. - PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT2) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT1) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP; - PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT0) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP; - - // Force schmitt trigger for T210B01. - if (t210b01) - _sdmmc_config_sdmmc1_schmitt(); - - // Make sure the SDMMC1 controller is powered. - smcReadWriteRegister(PMC_BASE + APBDEV_PMC_NO_IOPOWER, ~PMC_NO_IOPOWER_SDMMC1_IO_EN, PMC_NO_IOPOWER_SDMMC1_IO_EN); - smcReadWriteRegister(PMC_BASE + APBDEV_PMC_NO_IOPOWER, 0, 0); // Commit write. - - // Inform IO pads that voltage is gonna be 3.3V. - smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, PMC_PWR_DET_SDMMC1_IO_EN, PMC_PWR_DET_SDMMC1_IO_EN); - smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, 0, 0); // Commit write. - - // Set enable SD card power. - //PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2; // Proper pinmuxing. Breaks on HOS, takes over 1 minute to recover. - PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN | 1; // Wrong but working pinmuxing. Instant take over by FS. - gpio_config(GPIO_PORT_E, GPIO_PIN_4, GPIO_MODE_GPIO); - gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH); - gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_ENABLE); - usleep(10000); - - // Enable SD card IO power. - max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000); - max77620_regulator_enable(REGULATOR_LDO2, 1); - usleep(1000); - - // Set pad slew codes to get good quality clock. - if (!t210b01) - { - APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL) & 0xFFFFFFF) | 0x50000000; - (void)APB_MISC(APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL); // Commit write. - usleep(1000); - } - - return 1; -} - -static void _sdmmc_config_emmc(u32 id, bool t210b01) -{ - switch (id) - { - case SDMMC_2: - if (!t210b01) - { - // Unset park for pads. - APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL) &= 0xF8003FFF; - (void)APB_MISC(APB_MISC_GP_EMMC2_PAD_CFGPADCTRL); // Commit write. - } - else // Enable schmitt trigger for T210B01. - _sdmmc_config_sdmmc2_schmitt(); - break; - - case SDMMC_4: - // Unset park for pads. - APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) &= 0xF8003FFF; - // Set default pad cfg. - if (t210b01) - APB_MISC(APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL) &= 0xFFBFFFF9; // Unset CMD/CLK/DQS powedown. - // Enable schmitt trigger. - APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) |= 1; - (void)APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL); // Commit write. - break; - } -} - -int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int powersave_enable) -{ - u32 clock; - u16 divisor; - u8 vref_sel = 7; - - const u32 trim_values_t210[] = { 2, 8, 3, 8 }; - const u32 trim_values_t210b01[] = { 14, 13, 15, 13 }; - const u32 *trim_values = sdmmc->t210b01 ? trim_values_t210b01 : trim_values_t210; - - if (id > SDMMC_4 || id == SDMMC_3) - return 0; - - memset(sdmmc, 0, sizeof(sdmmc_t)); - - sdmmc->regs = (t210_sdmmc_t *)QueryIoMapping(_sdmmc_bases[id], 0x200); - sdmmc->id = id; - sdmmc->clock_stopped = 1; - sdmmc->t210b01 = splGetSocType() == SplSocType_Mariko; - - // Do specific SDMMC HW configuration. - switch (id) - { - case SDMMC_1: - if (!_sdmmc_config_sdmmc1(sdmmc->t210b01)) - return 0; - if (sdmmc->t210b01) - vref_sel = 0; - else - sdmmc->manual_cal = 1; - break; - - case SDMMC_2: - case SDMMC_4: - _sdmmc_config_emmc(id, sdmmc->t210b01); - break; - } - - // Disable clock if enabled. - if (clock_sdmmc_is_not_reset_and_enabled(id)) - { - _sdmmc_sd_clock_disable(sdmmc); - _sdmmc_commit_changes(sdmmc); - } - - // Configure and enable selected clock. - clock_sdmmc_get_card_clock_div(&clock, &divisor, type); - clock_sdmmc_enable(id, clock); - - // Make sure all sdmmc registers are reset. - _sdmmc_reset_all(sdmmc); - - sdmmc->clock_stopped = 0; - - // Set default pad IO trimming configuration. - sdmmc->regs->iospare |= 0x80000; // Enable muxing. - sdmmc->regs->veniotrimctl &= 0xFFFFFFFB; // Set Band Gap VREG to supply DLL. - sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xE0FFFFFB) | (trim_values[sdmmc->id] << 24); - sdmmc->regs->sdmemcmppadctl = - (sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_COMP_VREF_SEL_MASK) | vref_sel; - - // Configure auto calibration values. - if (!_sdmmc_autocal_config_offset(sdmmc, power)) - return 0; - - // Calibrate pads. - _sdmmc_autocal_execute(sdmmc, power); - - // Enable internal clock and power. - if (_sdmmc_enable_internal_clock(sdmmc)) - { - sdmmc_set_bus_width(sdmmc, bus_width); - _sdmmc_set_io_power(sdmmc, power); - - if (sdmmc_setup_clock(sdmmc, type)) - { - sdmmc_card_clock_powersave(sdmmc, powersave_enable); - _sdmmc_card_clock_enable(sdmmc); - _sdmmc_commit_changes(sdmmc); - - return 1; - } - } - - return 0; -} - -void sdmmc1_disable_power() -{ - // Clear pull down from CLK pad. - PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_PULL_MASK; - - // Set pads to discharge state. - _sdmmc_config_sdmmc1_pads(true); - - // Disable SD card IO power regulator. - max77620_regulator_enable(REGULATOR_LDO2, 0); - usleep(4000); - - // Disable SD card IO power pin. - gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW); - - // T210/T210B01 WAR: Set start timer for IO and Controller power discharge. - msleep(239); - - // Disable SDMMC1 controller power. - smcReadWriteRegister(PMC_BASE + APBDEV_PMC_NO_IOPOWER, PMC_NO_IOPOWER_SDMMC1_IO_EN, PMC_NO_IOPOWER_SDMMC1_IO_EN); - smcReadWriteRegister(PMC_BASE + APBDEV_PMC_NO_IOPOWER, 0, 0); // Commit write. - - // Inform IO pads that next voltage might be 3.3V. - smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, PMC_PWR_DET_SDMMC1_IO_EN, PMC_PWR_DET_SDMMC1_IO_EN); - smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, 0, 0); // Commit write. - - // Set pads to reset state. - _sdmmc_config_sdmmc1_pads(false); - - // Set pull down to CLK pad. - PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) |= PINMUX_PULL_DOWN; -} - -void sdmmc_end(sdmmc_t *sdmmc) -{ - if (!sdmmc->clock_stopped) - { - _sdmmc_sd_clock_disable(sdmmc); - // Disable SDMMC power. - _sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF); - - // Disable SD card power. - if (sdmmc->id == SDMMC_1) - sdmmc1_disable_power(); - - _sdmmc_commit_changes(sdmmc); - clock_sdmmc_disable(sdmmc->id); - sdmmc->clock_stopped = 1; - } -} - -void sdmmc_init_cmd(sdmmc_cmd_t *cmdbuf, u16 cmd, u32 arg, u32 rsp_type, u32 check_busy) -{ - cmdbuf->cmd = cmd; - cmdbuf->arg = arg; - cmdbuf->rsp_type = rsp_type; - cmdbuf->check_busy = check_busy; -} - -int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out) -{ - if (!sdmmc->card_clock_enabled) - return 0; - - // Recalibrate periodically for SDMMC1. - if (sdmmc->manual_cal && sdmmc->powersave_enabled) - _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); - - int should_disable_sd_clock = 0; - if (!(sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN)) - { - should_disable_sd_clock = 1; - sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; - _sdmmc_commit_changes(sdmmc); - usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); - } - - int result = _sdmmc_execute_cmd_inner(sdmmc, cmd, req, blkcnt_out); - usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); - - if (should_disable_sd_clock) - sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; - - return result; -} - -int sdmmc_enable_low_voltage(sdmmc_t *sdmmc) -{ - if(sdmmc->id != SDMMC_1) - return 0; - - if (!sdmmc_setup_clock(sdmmc, SDHCI_TIMING_UHS_SDR12)) - return 0; - - _sdmmc_commit_changes(sdmmc); - - // Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed. - max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000); - usleep(150); - - // Inform IO pads that we switched to 1.8V. - smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, ~PMC_PWR_DET_SDMMC1_IO_EN, PMC_PWR_DET_SDMMC1_IO_EN); - smcReadWriteRegister(PMC_BASE + APBDEV_PMC_PWR_DET_VAL, 0, 0); // Commit write. - - // Enable schmitt trigger for better duty cycle and low jitter clock. - _sdmmc_config_sdmmc1_schmitt(); - - _sdmmc_autocal_config_offset(sdmmc, SDMMC_POWER_1_8); - _sdmmc_autocal_execute(sdmmc, SDMMC_POWER_1_8); - _sdmmc_set_io_power(sdmmc, SDMMC_POWER_1_8); - _sdmmc_commit_changes(sdmmc); - msleep(5); // Wait minimum 5ms before turning on the card clock. - - // Turn on SDCLK. - if (sdmmc->regs->hostctl2 & SDHCI_CTRL_VDD_180) - { - sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; - _sdmmc_commit_changes(sdmmc); - usleep(1000); - if ((sdmmc->regs->prnsts & SDHCI_DATA_LVL_MASK) == SDHCI_DATA_LVL_MASK) - return 1; - } - - return 0; -} diff --git a/emummc/source/emmc/sdmmc_driver.h b/emummc/source/emmc/sdmmc_driver.h deleted file mode 100644 index c4c8067c82..0000000000 --- a/emummc/source/emmc/sdmmc_driver.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _SDMMC_DRIVER_H_ -#define _SDMMC_DRIVER_H_ - -#include "../utils/types.h" -#include "sdmmc_t210.h" - -/*! SDMMC controller IDs. */ -#define SDMMC_1 0 -#define SDMMC_2 1 -#define SDMMC_3 2 -#define SDMMC_4 3 - -/*! SDMMC power types. */ -#define SDMMC_POWER_OFF 0 -#define SDMMC_POWER_1_8 1 -#define SDMMC_POWER_3_3 2 - -/*! SDMMC bus widths. */ -#define SDMMC_BUS_WIDTH_1 0 -#define SDMMC_BUS_WIDTH_4 1 -#define SDMMC_BUS_WIDTH_8 2 - -/*! SDMMC response types. */ -#define SDMMC_RSP_TYPE_0 0 -#define SDMMC_RSP_TYPE_1 1 -#define SDMMC_RSP_TYPE_2 2 -#define SDMMC_RSP_TYPE_3 3 -#define SDMMC_RSP_TYPE_4 4 -#define SDMMC_RSP_TYPE_5 5 - -/*! SDMMC mask interrupt status. */ -#define SDMMC_MASKINT_MASKED 0 -#define SDMMC_MASKINT_NOERROR -1 -#define SDMMC_MASKINT_ERROR -2 - -/*! SDMMC present state. */ -#define SDHCI_CMD_INHIBIT 0x1 -#define SDHCI_DATA_INHIBIT 0x2 -#define SDHCI_DOING_WRITE 0x100 -#define SDHCI_DOING_READ 0x200 -#define SDHCI_SPACE_AVAILABLE 0x400 -#define SDHCI_DATA_AVAILABLE 0x800 -#define SDHCI_CARD_PRESENT 0x10000 -#define SDHCI_CD_STABLE 0x20000 -#define SDHCI_CD_LVL 0x40000 -#define SDHCI_WRITE_PROTECT 0x80000 -#define SDHCI_DATA_LVL_MASK 0xF00000 -#define SDHCI_DATA_0_LVL_MASK 0x100000 -#define SDHCI_CMD_LVL 0x1000000 - -/*! SDMMC transfer mode. */ -#define SDHCI_TRNS_DMA 0x01 -#define SDHCI_TRNS_BLK_CNT_EN 0x02 -#define SDHCI_TRNS_AUTO_CMD12 0x04 -#define SDHCI_TRNS_AUTO_CMD23 0x08 -#define SDHCI_TRNS_AUTO_SEL 0x0C -#define SDHCI_TRNS_WRITE 0x00 -#define SDHCI_TRNS_READ 0x10 -#define SDHCI_TRNS_MULTI 0x20 - -/*! SDMMC command. */ -#define SDHCI_CMD_RESP_MASK 0x3 -#define SDHCI_CMD_RESP_NO_RESP 0x0 -#define SDHCI_CMD_RESP_LEN136 0x1 -#define SDHCI_CMD_RESP_LEN48 0x2 -#define SDHCI_CMD_RESP_LEN48_BUSY 0x3 -#define SDHCI_CMD_CRC 0x08 -#define SDHCI_CMD_INDEX 0x10 -#define SDHCI_CMD_DATA 0x20 -#define SDHCI_CMD_ABORTCMD 0xC0 - -/*! SDMMC host control. */ -#define SDHCI_CTRL_LED 0x01 -#define SDHCI_CTRL_4BITBUS 0x02 -#define SDHCI_CTRL_HISPD 0x04 -#define SDHCI_CTRL_DMA_MASK 0x18 -#define SDHCI_CTRL_SDMA 0x00 -#define SDHCI_CTRL_ADMA1 0x08 -#define SDHCI_CTRL_ADMA32 0x10 -#define SDHCI_CTRL_ADMA64 0x18 -#define SDHCI_CTRL_8BITBUS 0x20 -#define SDHCI_CTRL_CDTEST_INS 0x40 -#define SDHCI_CTRL_CDTEST_EN 0x80 - -/*! SDMMC host control 2. */ -#define SDHCI_CTRL_UHS_MASK 0xFFF8 -#define SDHCI_CTRL_VDD_180 8 -#define SDHCI_CTRL_DRV_TYPE_B 0x00 -#define SDHCI_CTRL_DRV_TYPE_A 0x10 -#define SDHCI_CTRL_DRV_TYPE_C 0x20 -#define SDHCI_CTRL_DRV_TYPE_D 0x30 -#define SDHCI_CTRL_EXEC_TUNING 0x40 -#define SDHCI_CTRL_TUNED_CLK 0x80 -#define SDHCI_HOST_VERSION_4_EN 0x1000 -#define SDHCI_ADDRESSING_64BIT_EN 0x2000 -#define SDHCI_CTRL_PRESET_VAL_EN 0x8000 - -/*! SDMMC power control. */ -#define SDHCI_POWER_ON 0x01 -#define SDHCI_POWER_180 0x0A -#define SDHCI_POWER_300 0x0C -#define SDHCI_POWER_330 0x0E -#define SDHCI_POWER_MASK 0xF1 - -// /*! SDMMC max current. */ -// #define SDHCI_MAX_CURRENT_330_MASK 0xFF -// #define SDHCI_MAX_CURRENT_180_MASK 0xFF0000 -// #define SDHCI_MAX_CURRENT_MULTIPLIER 4 - -/*! SDMMC clock control. */ -#define SDHCI_DIVIDER_SHIFT 8 -#define SDHCI_DIVIDER_HI_SHIFT 6 -#define SDHCI_DIV_MASK 0xFF00 -#define SDHCI_DIV_HI_MASK 0xC0 -#define SDHCI_PROG_CLOCK_MODE 0x20 -#define SDHCI_CLOCK_CARD_EN 0x4 -#define SDHCI_CLOCK_INT_STABLE 0x2 -#define SDHCI_CLOCK_INT_EN 0x1 - -/*! SDMMC software reset. */ -#define SDHCI_RESET_ALL 0x01 -#define SDHCI_RESET_CMD 0x02 -#define SDHCI_RESET_DATA 0x04 - -/*! SDMMC interrupt status and control. */ -#define SDHCI_INT_RESPONSE 0x1 -#define SDHCI_INT_DATA_END 0x2 -#define SDHCI_INT_BLK_GAP 0x4 -#define SDHCI_INT_DMA_END 0x8 -#define SDHCI_INT_SPACE_AVAIL 0x10 -#define SDHCI_INT_DATA_AVAIL 0x20 -#define SDHCI_INT_CARD_INSERT 0x40 -#define SDHCI_INT_CARD_REMOVE 0x80 -#define SDHCI_INT_CARD_INT 0x100 -#define SDHCI_INT_RETUNE 0x1000 -#define SDHCI_INT_CQE 0x4000 -#define SDHCI_INT_ERROR 0x8000 - -/*! SDMMC error interrupt status and control. */ -#define SDHCI_ERR_INT_TIMEOUT 0x1 -#define SDHCI_ERR_INT_CRC 0x2 -#define SDHCI_ERR_INT_END_BIT 0x4 -#define SDHCI_ERR_INT_INDEX 0x8 -#define SDHCI_ERR_INT_DATA_TIMEOUT 0x10 -#define SDHCI_ERR_INT_DATA_CRC 0x20 -#define SDHCI_ERR_INT_DATA_END_BIT 0x40 -#define SDHCI_ERR_INT_BUS_POWER 0x80 -#define SDHCI_ERR_INT_AUTO_CMD_ERR 0x100 -#define SDHCI_ERR_INT_ADMA_ERROR 0x200 - -#define SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR \ - (SDHCI_ERR_INT_AUTO_CMD_ERR | SDHCI_ERR_INT_DATA_END_BIT | \ - SDHCI_ERR_INT_DATA_CRC | SDHCI_ERR_INT_DATA_TIMEOUT | \ - SDHCI_ERR_INT_INDEX | SDHCI_ERR_INT_END_BIT | \ - SDHCI_ERR_INT_CRC | SDHCI_ERR_INT_TIMEOUT) - -/*! SD bus speeds. */ -#define UHS_SDR12_BUS_SPEED 0 -#define HIGH_SPEED_BUS_SPEED 1 -#define UHS_SDR25_BUS_SPEED 1 -#define UHS_SDR50_BUS_SPEED 2 -#define UHS_SDR104_BUS_SPEED 3 -#define UHS_DDR50_BUS_SPEED 4 -#define HS400_BUS_SPEED 5 - -/*! SDMMC timmings. */ -#define SDHCI_TIMING_MMC_ID 0 -#define SDHCI_TIMING_MMC_LS26 1 -#define SDHCI_TIMING_MMC_HS52 2 -#define SDHCI_TIMING_MMC_HS200 3 -#define SDHCI_TIMING_MMC_HS400 4 -#define SDHCI_TIMING_SD_ID 5 -#define SDHCI_TIMING_SD_DS12 6 -#define SDHCI_TIMING_SD_HS25 7 -#define SDHCI_TIMING_UHS_SDR12 8 -#define SDHCI_TIMING_UHS_SDR25 9 -#define SDHCI_TIMING_UHS_SDR50 10 -#define SDHCI_TIMING_UHS_SDR104 11 -#define SDHCI_TIMING_UHS_SDR82 12 // SDR104 with a 163.2MHz -> 81.6MHz clock. -#define SDHCI_TIMING_UHS_DDR50 13 -#define SDHCI_TIMING_MMC_HS102 14 - -#define SDHCI_CAN_64BIT 0x10000000 - -/*! SDMMC Low power features. */ -#define SDMMC_POWER_SAVE_DISABLE 0 -#define SDMMC_POWER_SAVE_ENABLE 1 - -/*! Helper for SWITCH command argument. */ -#define SDMMC_SWITCH(mode, index, value) (((mode) << 24) | ((index) << 16) | ((value) << 8)) - -/*! SDMMC controller context. */ -typedef struct _sdmmc_t -{ - t210_sdmmc_t *regs; - u32 id; - u32 divisor; - u32 clock_stopped; - int powersave_enabled; - int manual_cal; - int card_clock_enabled; - int venclkctl_set; - u32 venclkctl_tap; - u32 expected_rsp_type; - u64 last_dma_idx; - u64 dma_addr_next; - u32 rsp[4]; - u32 rsp3; - int t210b01; -} sdmmc_t; - -/*! SDMMC command. */ -typedef struct _sdmmc_cmd_t -{ - u16 cmd; - u32 arg; - u32 rsp_type; - u32 check_busy; -} sdmmc_cmd_t; - -/*! SDMMC request. */ -typedef struct _sdmmc_req_t -{ - void *buf; - u32 blksize; - u32 num_sectors; - int is_write; - int is_multi_block; - int is_auto_cmd12; -} sdmmc_req_t; - -int sdmmc_get_io_power(sdmmc_t *sdmmc); -u32 sdmmc_get_bus_width(sdmmc_t *sdmmc); -void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width); -void sdmmc_save_tap_value(sdmmc_t *sdmmc); -int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type); -void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable); -int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type); -int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd); -int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp); -int sdmmc_get_sd_power_enabled(); -bool sdmmc_get_sd_inserted(); -int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int powersave_enable); -void sdmmc_end(sdmmc_t *sdmmc); -void sdmmc_init_cmd(sdmmc_cmd_t *cmdbuf, u16 cmd, u32 arg, u32 rsp_type, u32 check_busy); -int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out); -int sdmmc_enable_low_voltage(sdmmc_t *sdmmc); - -#endif diff --git a/emummc/source/emmc/sdmmc_t210.h b/emummc/source/emmc/sdmmc_t210.h deleted file mode 100644 index 2fcf3d0422..0000000000 --- a/emummc/source/emmc/sdmmc_t210.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _SDMMC_T210_H_ -#define _SDMMC_T210_H_ - -#include "../utils/types.h" - -#define TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW 0x20000 -#define TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE 0x80000000 -#define TEGRA_MMC_DLLCAL_CFG_STATUS_DLL_ACTIVE 0x80000000 -#define TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD 0x80000000 -#define TEGRA_MMC_SDMEMCOMPPADCTRL_COMP_VREF_SEL_MASK 0xFFFFFFF0 -#define TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE 0x20000000 -#define TEGRA_MMC_AUTOCALCFG_AUTO_CAL_START 0x80000000 -#define TEGRA_MMC_AUTOCALSTS_AUTO_CAL_ACTIVE 0x80000000 - -typedef struct _t210_sdmmc_t -{ - vu32 sysad; - vu16 blksize; - vu16 blkcnt; - vu32 argument; - vu16 trnmod; - vu16 cmdreg; - vu32 rspreg0; - vu32 rspreg1; - vu32 rspreg2; - vu32 rspreg3; - vu32 bdata; - vu32 prnsts; - vu8 hostctl; - vu8 pwrcon; - vu8 blkgap; - vu8 wakcon; - vu16 clkcon; - vu8 timeoutcon; - vu8 swrst; - vu16 norintsts; - vu16 errintsts; - vu16 norintstsen; // Enable irq status. - vu16 errintstsen; // Enable irq status. - vu16 norintsigen; // Enable irq signal to LIC/GIC. - vu16 errintsigen; // Enable irq signal to LIC/GIC. - vu16 acmd12errsts; - vu16 hostctl2; - vu32 capareg; - vu32 capareg_1; - vu32 maxcurr; - vu8 rsvd0[4]; // 4C-4F reserved for more max current. - vu16 setacmd12err; - vu16 setinterr; - vu8 admaerr; - vu8 rsvd1[3]; // 55-57 reserved. - vu32 admaaddr; - vu32 admaaddr_hi; - vu8 rsvd2[156]; // 60-FB reserved. - vu16 slotintsts; - vu16 hcver; - vu32 venclkctl; - vu32 vensysswctl; - vu32 venerrintsts; - vu32 vencapover; - vu32 venbootctl; - vu32 venbootacktout; - vu32 venbootdattout; - vu32 vendebouncecnt; - vu32 venmiscctl; - vu32 maxcurrover; - vu32 maxcurrover_hi; - vu32 unk0[32]; // 0x12C - vu32 veniotrimctl; - vu32 vendllcalcfg; - vu32 vendllctl0; - vu32 vendllctl1; - vu32 vendllcalcfgsts; - vu32 ventunctl0; - vu32 ventunctl1; - vu32 ventunsts0; - vu32 ventunsts1; - vu32 venclkgatehystcnt; - vu32 venpresetval0; - vu32 venpresetval1; - vu32 venpresetval2; - vu32 sdmemcmppadctl; - vu32 autocalcfg; - vu32 autocalintval; - vu32 autocalsts; - vu32 iospare; - vu32 mcciffifoctl; - vu32 timeoutwcoal; - vu32 unk1; -} t210_sdmmc_t; - -#endif diff --git a/emummc/source/emuMMC/emummc.c b/emummc/source/emuMMC/emummc.c deleted file mode 100644 index 04c8e95bdd..0000000000 --- a/emummc/source/emuMMC/emummc.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * Copyright (c) 2019 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "emummc.h" -#include "emummc_ctx.h" -#include "../utils/fatal.h" -#include "../libs/fatfs/diskio.h" - -static bool sdmmc_first_init = false; -static bool storageSDinitialized = false; - -// hekate sdmmmc vars -sdmmc_t sdmmc; -sdmmc_storage_t storage; -sdmmc_t sd_sdmmc; -sdmmc_storage_t sd_storage; - -// init vars -bool init_done = false; -bool custom_driver = true; - -// FS funcs -_sdmmc_accessor_gc sdmmc_accessor_gc; -_sdmmc_accessor_sd sdmmc_accessor_sd; -_sdmmc_accessor_nand sdmmc_accessor_nand; -_lock_mutex lock_mutex; -_unlock_mutex unlock_mutex; - -// FS misc -void *sd_mutex; -void *nand_mutex; -volatile int *active_partition; -volatile Handle *sdmmc_das_handle; - -// FatFS -file_based_ctxt f_emu; -static bool fat_mounted = false; - -static void _sdmmc_ensure_device_attached(void) -{ - // This ensures that the sd device address space handle is always attached, - // even if FS hasn't attached it - static bool did_attach = false; - if (!did_attach) - { - svcAttachDeviceAddressSpace(DeviceName_SDMMC1A, *sdmmc_das_handle); - did_attach = true; - } -} - -static void _sdmmc_ensure_initialized(void) -{ - // First Initial init - if (!sdmmc_first_init) - { - sdmmc_initialize(); - sdmmc_first_init = true; - } - else - { - // The boot sysmodule will eventually kill power to SD. - // Detect this, and reinitialize when it happens. - if (!init_done) - { - if (sdmmc_get_sd_power_enabled() == 0) - { - sdmmc_finalize(); - sdmmc_initialize(); - init_done = true; - } - } - } -} - -static void _file_based_update_filename(char *outFilename, unsigned int sd_path_len, unsigned int part_idx) -{ - snprintf(outFilename + sd_path_len, 3, "%02d", part_idx); -} - -static void _file_based_emmc_finalize(void) -{ - if ((emuMMC_ctx.EMMC_Type == emuMMC_SD_File) && fat_mounted) - { - // Close all open handles. - f_close(&f_emu.fp_boot0); - f_close(&f_emu.fp_boot1); - - for (int i = 0; i < f_emu.parts; i++) - f_close(&f_emu.fp_gpp[i]); - - // Force unmount FAT volume. - f_mount(NULL, "", 1); - - fat_mounted = false; - } -} - -static void _nand_patrol_ensure_integrity(void) -{ - fs_nand_patrol_t nand_patrol; - static bool nand_patrol_checked = false; - - if (!nand_patrol_checked) - { - if (emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw) - { - unsigned int nand_patrol_sector = emuMMC_ctx.EMMC_StoragePartitionOffset + NAND_PATROL_SECTOR; - if (!sdmmc_storage_read(&sd_storage, nand_patrol_sector, 1, &nand_patrol)) - goto out; - - // Clear nand patrol if last offset exceeds storage. - if (nand_patrol.offset > sd_storage.sec_cnt) - { - memset(&nand_patrol, 0, sizeof(fs_nand_patrol_t)); - sdmmc_storage_write(&sd_storage, nand_patrol_sector, 1, &nand_patrol); - } - } - else if (emuMMC_ctx.EMMC_Type == emuMMC_SD_File && fat_mounted) - { - FIL *fp = &f_emu.fp_boot0; - if (f_lseek(fp, NAND_PATROL_OFFSET) != FR_OK) - goto out; - - if (f_read_fast(fp, &nand_patrol, sizeof(fs_nand_patrol_t)) != FR_OK) - goto out; - - // Clear nand patrol if last offset exceeds total file based size. - if (nand_patrol.offset > f_emu.total_sect) - { - memset(&nand_patrol, 0, sizeof(fs_nand_patrol_t)); - - if (f_lseek(fp, NAND_PATROL_OFFSET) != FR_OK) - goto out; - - if (f_write_fast(fp, &nand_patrol, sizeof(fs_nand_patrol_t)) != FR_OK) - goto out; - - f_sync(fp); - } - } - -out: - nand_patrol_checked = true; - } -} - -void sdmmc_finalize(void) -{ - if (!sdmmc_storage_end(&sd_storage)) - fatal_abort(Fatal_InitSD); - - storageSDinitialized = false; -} - -static void _file_based_emmc_initialize(void) -{ - char path[sizeof(emuMMC_ctx.storagePath) + 0x20]; - memset(&path, 0, sizeof(path)); - - memcpy(path, (void *)emuMMC_ctx.storagePath, sizeof(emuMMC_ctx.storagePath)); - strcat(path, "/eMMC/"); - int path_len = strlen(path); - - // Open BOOT0 physical partition. - memcpy(path + path_len, "BOOT0", 6); - if (f_open(&f_emu.fp_boot0, path, FA_READ | FA_WRITE) != FR_OK) - fatal_abort(Fatal_FatfsFileOpen); - if (!f_expand_cltbl(&f_emu.fp_boot0, EMUMMC_FP_CLMT_COUNT, f_emu.clmt_boot0, f_size(&f_emu.fp_boot0))) - fatal_abort(Fatal_FatfsMemExhaustion); - - // Open BOOT1 physical partition. - memcpy(path + path_len, "BOOT1", 6); - if (f_open(&f_emu.fp_boot1, path, FA_READ | FA_WRITE) != FR_OK) - fatal_abort(Fatal_FatfsFileOpen); - if (!f_expand_cltbl(&f_emu.fp_boot1, EMUMMC_FP_CLMT_COUNT, f_emu.clmt_boot1, f_size(&f_emu.fp_boot1))) - fatal_abort(Fatal_FatfsMemExhaustion); - - // Open handles for GPP physical partition files. - _file_based_update_filename(path, path_len, 00); - - if (f_open(&f_emu.fp_gpp[0], path, FA_READ | FA_WRITE) != FR_OK) - fatal_abort(Fatal_FatfsFileOpen); - if (!f_expand_cltbl(&f_emu.fp_gpp[0], EMUMMC_FP_CLMT_COUNT, &f_emu.clmt_gpp[0], f_size(&f_emu.fp_gpp[0]))) - fatal_abort(Fatal_FatfsMemExhaustion); - - f_emu.part_size = (uint64_t)f_size(&f_emu.fp_gpp[0]) >> 9; - f_emu.total_sect = f_emu.part_size; - - // Iterate folder for split parts and stop if next doesn't exist. - for (f_emu.parts = 1; f_emu.parts < EMUMMC_FILE_MAX_PARTS; f_emu.parts++) - { - _file_based_update_filename(path, path_len, f_emu.parts); - - if (f_open(&f_emu.fp_gpp[f_emu.parts], path, FA_READ | FA_WRITE) != FR_OK) - { - // Check if single file. - if (f_emu.parts == 1) - f_emu.parts = 0; - - return; - } - - if (!f_expand_cltbl(&f_emu.fp_gpp[f_emu.parts], EMUMMC_FP_CLMT_COUNT, - &f_emu.clmt_gpp[f_emu.parts * EMUMMC_FP_CLMT_COUNT], f_size(&f_emu.fp_gpp[f_emu.parts]))) - { - fatal_abort(Fatal_FatfsMemExhaustion); - } - - f_emu.total_sect += (uint64_t)f_size(&f_emu.fp_gpp[f_emu.parts]) >> 9; - } -} - -bool sdmmc_initialize(void) -{ - if (!storageSDinitialized) - { - int retries = 3; - while (retries) - { - if (nx_sd_initialize(false)) - { - storageSDinitialized = true; - - // Init file based emummc. - if ((emuMMC_ctx.EMMC_Type == emuMMC_SD_File) && !fat_mounted) - { - if (f_mount(&f_emu.sd_fs, "", 1) != FR_OK) - fatal_abort(Fatal_InitSD); - else - fat_mounted = true; - - _file_based_emmc_initialize(); - } - - // Check if nand patrol offset is inside limits. - _nand_patrol_ensure_integrity(); - - break; - } - - retries--; - } - - if (!storageSDinitialized) - fatal_abort(Fatal_InitSD); - } - - return storageSDinitialized; -} - -sdmmc_accessor_t *sdmmc_accessor_get(int mmc_id) -{ - sdmmc_accessor_t *_this; - switch (mmc_id) - { - case FS_SDMMC_EMMC: - _this = sdmmc_accessor_nand(); - break; - case FS_SDMMC_SD: - _this = sdmmc_accessor_sd(); - break; - case FS_SDMMC_GC: - _this = sdmmc_accessor_gc(); - break; - default: - fatal_abort(Fatal_InvalidAccessor); - } - - return _this; -} - -void mutex_lock_handler(int mmc_id) -{ - if (custom_driver) - lock_mutex(sd_mutex); - - lock_mutex(nand_mutex); -} - -void mutex_unlock_handler(int mmc_id) -{ - unlock_mutex(nand_mutex); - - if (custom_driver) - unlock_mutex(sd_mutex); -} - -int sdmmc_nand_get_active_partition_index() -{ - switch (*active_partition) - { - case FS_EMMC_PARTITION_GPP: - return 2; - case FS_EMMC_PARTITION_BOOT1: - return 1; - case FS_EMMC_PARTITION_BOOT0: - return 0; - } - - fatal_abort(Fatal_InvalidAccessor); -} - -static uint64_t emummc_read_write_inner(void *buf, unsigned int sector, unsigned int num_sectors, bool is_write) -{ - if (emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw) - { - // raw partition sector offset: emuMMC_ctx.EMMC_StoragePartitionOffset. - sector += emuMMC_ctx.EMMC_StoragePartitionOffset; - // Set physical partition offset. - sector += (sdmmc_nand_get_active_partition_index() * BOOT_PARTITION_SIZE); - - if (__builtin_expect(sector + num_sectors > sd_storage.sec_cnt, 0)) - return 0; // Out of bounds. Can only happen with Nand Patrol if resized. - - if (!is_write) - return sdmmc_storage_read(&sd_storage, sector, num_sectors, buf); - else - return sdmmc_storage_write(&sd_storage, sector, num_sectors, buf); - } - - // File based emummc. - FIL *fp = NULL; - switch (*active_partition) - { - case FS_EMMC_PARTITION_GPP: - if (f_emu.parts) - { - if (__builtin_expect(sector + num_sectors > f_emu.total_sect, 0)) - return 0; // Out of bounds. Can only happen with Nand Patrol if resized. - - fp = &f_emu.fp_gpp[sector / f_emu.part_size]; - sector = sector % f_emu.part_size; - - // Special handling for reads/writes which cross file-boundaries. - if (__builtin_expect(sector + num_sectors > f_emu.part_size, 0)) - { - unsigned int remaining = num_sectors; - while (remaining > 0) { - const unsigned int cur_sectors = MIN(remaining, f_emu.part_size - sector); - - if (f_lseek(fp, (uint64_t)sector << 9) != FR_OK) - return 0; // Out of bounds. - - if (!is_write) - { - if (f_read_fast(fp, buf, (uint64_t)cur_sectors << 9) != FR_OK) - return 0; - } - else - { - if (f_write_fast(fp, buf, (uint64_t)cur_sectors << 9) != FR_OK) - return 0; - } - - buf = (char *)buf + ((uint64_t)cur_sectors << 9); - remaining -= cur_sectors; - sector = 0; - ++fp; - } - - return 1; - } - } - else - fp = &f_emu.fp_gpp[0]; - break; - - case FS_EMMC_PARTITION_BOOT1: - fp = &f_emu.fp_boot1; - break; - - case FS_EMMC_PARTITION_BOOT0: - fp = &f_emu.fp_boot0; - break; - } - - if (f_lseek(fp, (uint64_t)sector << 9) != FR_OK) - return 0; // Out of bounds. Can only happen with Nand Patrol if resized. - - if (!is_write) - return !f_read_fast(fp, buf, (uint64_t)num_sectors << 9); - else - return !f_write_fast(fp, buf, (uint64_t)num_sectors << 9); -} - -// Controller open wrapper -uint64_t sdmmc_wrapper_controller_open(int mmc_id) -{ - uint64_t result; - sdmmc_accessor_t *_this; - _this = sdmmc_accessor_get(mmc_id); - - if (_this != NULL) - { - // Lock eMMC xfer while SD card is being initialized by FS. - if (mmc_id == FS_SDMMC_SD) - mutex_lock_handler(FS_SDMMC_EMMC); // Recursive Mutex, handler will lock SD as well if custom_driver - - result = _this->vtab->sdmmc_accessor_controller_open(_this); - - // Unlock eMMC. - if (mmc_id == FS_SDMMC_SD) - mutex_unlock_handler(FS_SDMMC_EMMC); - - return result; - } - - fatal_abort(Fatal_OpenAccessor); -} - -// Controller close wrapper -uint64_t sdmmc_wrapper_controller_close(int mmc_id) -{ - sdmmc_accessor_t *_this; - _this = sdmmc_accessor_get(mmc_id); - - if (_this != NULL) - { - if (mmc_id == FS_SDMMC_SD) - return 0; - - if (mmc_id == FS_SDMMC_EMMC) - { - // Close file handles and unmount - _file_based_emmc_finalize(); - - // Close SD - sdmmc_accessor_get(FS_SDMMC_SD)->vtab->sdmmc_accessor_controller_close(sdmmc_accessor_get(FS_SDMMC_SD)); - - // Close eMMC - return _this->vtab->sdmmc_accessor_controller_close(_this); - } - - return _this->vtab->sdmmc_accessor_controller_close(_this); - } - - fatal_abort(Fatal_CloseAccessor); -} - -// FS read wrapper. -uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned int sector, unsigned int num_sectors) -{ - sdmmc_accessor_t *_this; - uint64_t read_res; - - _this = sdmmc_accessor_get(mmc_id); - - if (_this != NULL) - { - if (mmc_id == FS_SDMMC_EMMC || mmc_id == FS_SDMMC_SD) - { - mutex_lock_handler(mmc_id); - // Assign FS accessor to the SDMMC driver - _current_accessor = _this; - // Make sure we're attached to the device address space. - _sdmmc_ensure_device_attached(); - // Make sure we're still initialized if boot killed sd card power. - _sdmmc_ensure_initialized(); - } - - if (mmc_id == FS_SDMMC_EMMC) - { - // Call hekates driver. - if (emummc_read_write_inner(buf, sector, num_sectors, false)) - { - mutex_unlock_handler(mmc_id); - return 0; - } - - mutex_unlock_handler(mmc_id); - return FS_READ_WRITE_ERROR; - } - - if (mmc_id == FS_SDMMC_SD) - { - static bool first_sd_read = true; - if (first_sd_read) - { - first_sd_read = false; - if (emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw) - { - // Because some SD cards have issues with emuMMC's driver - // we currently swap to FS's driver after first SD read - // for raw based emuMMC - custom_driver = false; - // FS will handle sd mutex w/o custom driver from here on - unlock_mutex(sd_mutex); - } - } - - // Call hekate's driver. - if (sdmmc_storage_read(&sd_storage, sector, num_sectors, buf)) - { - mutex_unlock_handler(mmc_id); - return 0; - } - - mutex_unlock_handler(mmc_id); - return FS_READ_WRITE_ERROR; - } - - read_res = _this->vtab->read_write(_this, sector, num_sectors, buf, bufSize, 1); - return read_res; - } - - fatal_abort(Fatal_ReadNoAccessor); -} - -// FS write wrapper. -uint64_t sdmmc_wrapper_write(int mmc_id, unsigned int sector, unsigned int num_sectors, void *buf, uint64_t bufSize) -{ - sdmmc_accessor_t *_this; - uint64_t write_res; - - _this = sdmmc_accessor_get(mmc_id); - - if (_this != NULL) - { - if (mmc_id == FS_SDMMC_EMMC) - { - mutex_lock_handler(mmc_id); - _current_accessor = _this; - - // Call hekates driver. - if (emummc_read_write_inner(buf, sector, num_sectors, true)) - { - mutex_unlock_handler(mmc_id); - return 0; - } - - mutex_unlock_handler(mmc_id); - return FS_READ_WRITE_ERROR; - } - - if (mmc_id == FS_SDMMC_SD) - { - mutex_lock_handler(mmc_id); - _current_accessor = _this; - - // Call hekates driver. - if (sdmmc_storage_write(&sd_storage, sector, num_sectors, buf)) - { - mutex_unlock_handler(mmc_id); - return 0; - } - - mutex_unlock_handler(mmc_id); - return FS_READ_WRITE_ERROR; - } - - write_res = _this->vtab->read_write(_this, sector, num_sectors, buf, bufSize, 0); - return write_res; - } - - fatal_abort(Fatal_WriteNoAccessor); -} diff --git a/emummc/source/emuMMC/emummc.h b/emummc/source/emuMMC/emummc.h deleted file mode 100644 index 24580c18c4..0000000000 --- a/emummc/source/emuMMC/emummc.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __EMUMMC_H__ -#define __EMUMMC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -#include - -#include "../emmc/nx_sd.h" -#include "../emmc/sdmmc.h" -#include "../soc/i2c.h" -#include "../soc/gpio.h" -#include "../utils/util.h" -#include "../FS/FS.h" -#include "../libs/fatfs/ff.h" - -#define EMUMMC_FILE_MAX_PARTS 32 -#define EMUMMC_FP_CLMT_COUNT 1024 - -// FS typedefs -typedef sdmmc_accessor_t *(*_sdmmc_accessor_gc)(); -typedef sdmmc_accessor_t *(*_sdmmc_accessor_sd)(); -typedef sdmmc_accessor_t *(*_sdmmc_accessor_nand)(); -typedef void (*_lock_mutex)(void *mtx); -typedef void (*_unlock_mutex)(void *mtx); - -bool sdmmc_initialize(void); -void sdmmc_finalize(void); -int sdmmc_nand_get_active_partition_index(); -sdmmc_accessor_t *sdmmc_accessor_get(int mmc_id); - -void mutex_lock_handler(int mmc_id); -void mutex_unlock_handler(int mmc_id); - -// Hooks -uint64_t sdmmc_wrapper_controller_open(int mmc_id); -uint64_t sdmmc_wrapper_controller_close(int mmc_id); -uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned int sector, unsigned int num_sectors); -uint64_t sdmmc_wrapper_write(int mmc_id, unsigned int sector, unsigned int num_sectors, void *buf, uint64_t bufSize); - -typedef struct _file_based_ctxt -{ - FATFS sd_fs; - uint64_t parts; - uint64_t part_size; - FIL fp_boot0; - DWORD clmt_boot0[EMUMMC_FP_CLMT_COUNT]; - FIL fp_boot1; - DWORD clmt_boot1[EMUMMC_FP_CLMT_COUNT]; - FIL fp_gpp[EMUMMC_FILE_MAX_PARTS]; - DWORD clmt_gpp[EMUMMC_FILE_MAX_PARTS * EMUMMC_FP_CLMT_COUNT]; - uint64_t total_sect; -} file_based_ctxt; - -#ifdef __cplusplus -} -#endif - -#endif /* __EMUMMC_H__ */ diff --git a/emummc/source/emuMMC/emummc_ctx.h b/emummc/source/emuMMC/emummc_ctx.h deleted file mode 100644 index 9bee3fd094..0000000000 --- a/emummc/source/emuMMC/emummc_ctx.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __EMUMMC_CTX_H__ -#define __EMUMMC_CTX_H__ - -#include "../utils/types.h" -#include "../FS/FS_versions.h" - -#define EMUMMC_STORAGE_MAGIC 0x30534645 /* EFS0, EmuFS0 */ -#define EMUMMC_MAX_DIR_LENGTH 0x7F - -enum emuMMC_Type -{ - // EMMC Device raw - emuMMC_EMMC = 0, - - // SD Device raw - emuMMC_SD_Raw, - // SD Device File - emuMMC_SD_File, - - emuMMC_MAX -}; - -typedef struct _emuMMC_ctx_t -{ - u32 magic; - u32 id; - enum FS_VER fs_ver; - enum emuMMC_Type EMMC_Type; - enum emuMMC_Type SD_Type; - - /* Partition based */ - u64 EMMC_StoragePartitionOffset; - u64 SD_StoragePartitionOffset; - - /* File-Based */ - char storagePath[EMUMMC_MAX_DIR_LENGTH+1]; -} emuMMC_ctx_t, *PemuMMC_ctx_t; - -#endif /* __EMUMMC_CTX_H__ */ diff --git a/emummc/source/libs/fatfs/diskio.c b/emummc/source/libs/fatfs/diskio.c deleted file mode 100644 index d800d21825..0000000000 --- a/emummc/source/libs/fatfs/diskio.c +++ /dev/null @@ -1,72 +0,0 @@ -/*-----------------------------------------------------------------------*/ -/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */ -/*-----------------------------------------------------------------------*/ -/* If a working storage control module is available, it should be */ -/* attached to the FatFs via a glue function rather than modifying it. */ -/* This is an example of glue functions to attach various exsisting */ -/* storage control modules to the FatFs module with a defined API. */ -/*-----------------------------------------------------------------------*/ - -#include -#include "diskio.h" /* FatFs lower layer API */ -#include "../../emmc/sdmmc.h" - -extern sdmmc_storage_t sd_storage; - -/*-----------------------------------------------------------------------*/ -/* Get Drive Status */ -/*-----------------------------------------------------------------------*/ -DSTATUS disk_status ( - BYTE pdrv /* Physical drive nmuber to identify the drive */ -) -{ - return 0; -} - -/*-----------------------------------------------------------------------*/ -/* Inidialize a Drive */ -/*-----------------------------------------------------------------------*/ -DSTATUS disk_initialize ( - BYTE pdrv /* Physical drive nmuber to identify the drive */ -) -{ - return 0; -} - -/*-----------------------------------------------------------------------*/ -/* Read Sector(s) */ -/*-----------------------------------------------------------------------*/ -DRESULT disk_read ( - BYTE pdrv, /* Physical drive nmuber to identify the drive */ - BYTE *buff, /* Data buffer to store read data */ - DWORD sector, /* Start sector in LBA */ - UINT count /* Number of sectors to read */ -) -{ - return sdmmc_storage_read(&sd_storage, sector, count, buff) ? RES_OK : RES_ERROR; -} - -/*-----------------------------------------------------------------------*/ -/* Write Sector(s) */ -/*-----------------------------------------------------------------------*/ -DRESULT disk_write ( - BYTE pdrv, /* Physical drive nmuber to identify the drive */ - const BYTE *buff, /* Data to be written */ - DWORD sector, /* Start sector in LBA */ - UINT count /* Number of sectors to write */ -) -{ - return sdmmc_storage_write(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR; -} - -/*-----------------------------------------------------------------------*/ -/* Miscellaneous Functions */ -/*-----------------------------------------------------------------------*/ -DRESULT disk_ioctl ( - BYTE pdrv, /* Physical drive nmuber (0..) */ - BYTE cmd, /* Control code */ - void *buff /* Buffer to send/receive control data */ -) -{ - return RES_OK; -} diff --git a/emummc/source/libs/fatfs/diskio.h b/emummc/source/libs/fatfs/diskio.h deleted file mode 100644 index d6ae8f83ad..0000000000 --- a/emummc/source/libs/fatfs/diskio.h +++ /dev/null @@ -1,79 +0,0 @@ -/*-----------------------------------------------------------------------/ -/ Low level disk interface modlue include file (C)ChaN, 2014 / -/-----------------------------------------------------------------------*/ - -#ifndef _DISKIO_DEFINED -#define _DISKIO_DEFINED - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../../utils/types.h" - -/* Status of Disk Functions */ -typedef BYTE DSTATUS; - -/* Results of Disk Functions */ -typedef enum { - RES_OK = 0, /* 0: Successful */ - RES_ERROR, /* 1: R/W Error */ - RES_WRPRT, /* 2: Write Protected */ - RES_NOTRDY, /* 3: Not Ready */ - RES_PARERR /* 4: Invalid Parameter */ -} DRESULT; - - -/*---------------------------------------*/ -/* Prototypes for disk control functions */ - - -DSTATUS disk_initialize (BYTE pdrv); -DSTATUS disk_status (BYTE pdrv); -DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); -DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); -DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); - - -/* Disk Status Bits (DSTATUS) */ - -#define STA_NOINIT 0x01 /* Drive not initialized */ -#define STA_NODISK 0x02 /* No medium in the drive */ -#define STA_PROTECT 0x04 /* Write protected */ - - -/* Command code for disk_ioctrl fucntion */ - -/* Generic command (Used by FatFs) */ -#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */ -#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */ -#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ -#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ -#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ - -/* Generic command (Not used by FatFs) */ -#define CTRL_POWER 5 /* Get/Set power status */ -#define CTRL_LOCK 6 /* Lock/Unlock media removal */ -#define CTRL_EJECT 7 /* Eject media */ -#define CTRL_FORMAT 8 /* Create physical format on the media */ - -/* MMC/SDC specific ioctl command */ -#define MMC_GET_TYPE 10 /* Get card type */ -#define MMC_GET_CSD 11 /* Get CSD */ -#define MMC_GET_CID 12 /* Get CID */ -#define MMC_GET_OCR 13 /* Get OCR */ -#define MMC_GET_SDSTAT 14 /* Get SD status */ -#define ISDIO_READ 55 /* Read data form SD iSDIO register */ -#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ -#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ - -/* ATA/CF specific ioctl command */ -#define ATA_GET_REV 20 /* Get F/W revision */ -#define ATA_GET_MODEL 21 /* Get model name */ -#define ATA_GET_SN 22 /* Get serial number */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/emummc/source/libs/fatfs/ff.c b/emummc/source/libs/fatfs/ff.c deleted file mode 100644 index 50105173e3..0000000000 --- a/emummc/source/libs/fatfs/ff.c +++ /dev/null @@ -1,6883 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT Filesystem Module R0.13c (p4) / -/-----------------------------------------------------------------------------/ -/ -/ Copyright (C) 2018, ChaN, all right reserved. -/ -/ FatFs module is an open source software. Redistribution and use of FatFs in -/ source and binary forms, with or without modification, are permitted provided -/ that the following condition is met: -/ -/ 1. Redistributions of source code must retain the above copyright notice, -/ this condition and the following disclaimer. -/ -/ This software is provided by the copyright holder and contributors "AS IS" -/ and any warranties related to this software are DISCLAIMED. -/ The copyright owner or contributors be NOT LIABLE for any damages caused -/ by use of this software. -/ -/----------------------------------------------------------------------------*/ - - -#include "ff.h" /* Declarations of FatFs API */ -#include "diskio.h" /* Declarations of device I/O functions */ - -#define EFSPRINTF(text, ...) - -/*-------------------------------------------------------------------------- - - Module Private Definitions - ----------------------------------------------------------------------------*/ - -#if FF_DEFINED != 86604 /* Revision ID */ -#error Wrong include file (ff.h). -#endif - - -/* Limits and boundaries */ -#define MAX_DIR 0x200000 /* Max size of FAT directory */ -#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */ -#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */ -#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */ -#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */ -#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */ - - -/* Character code support macros */ -#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z') -#define IsLower(c) ((c) >= 'a' && (c) <= 'z') -#define IsDigit(c) ((c) >= '0' && (c) <= '9') -#define IsSurrogate(c) ((c) >= 0xD800 && (c) <= 0xDFFF) -#define IsSurrogateH(c) ((c) >= 0xD800 && (c) <= 0xDBFF) -#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF) - - -/* Additional file access control and file status flags for internal use */ -#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */ -#define FA_MODIFIED 0x40 /* File has been modified */ -#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */ - - -/* Additional file attribute bits for internal use */ -#define AM_VOL 0x08 /* Volume label */ -#define AM_LFN 0x0F /* LFN entry */ -#define AM_MASK 0x3F /* Mask of defined bits */ - - -/* Name status flags in fn[11] */ -#define NSFLAG 11 /* Index of the name status byte */ -#define NS_LOSS 0x01 /* Out of 8.3 format */ -#define NS_LFN 0x02 /* Force to create LFN entry */ -#define NS_LAST 0x04 /* Last segment */ -#define NS_BODY 0x08 /* Lower case flag (body) */ -#define NS_EXT 0x10 /* Lower case flag (ext) */ -#define NS_DOT 0x20 /* Dot entry */ -#define NS_NOLFN 0x40 /* Do not find LFN */ -#define NS_NONAME 0x80 /* Not followed */ - - -/* exFAT directory entry types */ -#define ET_BITMAP 0x81 /* Allocation bitmap */ -#define ET_UPCASE 0x82 /* Up-case table */ -#define ET_VLABEL 0x83 /* Volume label */ -#define ET_FILEDIR 0x85 /* File and directory */ -#define ET_STREAM 0xC0 /* Stream extension */ -#define ET_FILENAME 0xC1 /* Name extension */ - - -/* FatFs refers the FAT structure as simple byte array instead of structure member -/ because the C structure is not binary compatible between different platforms */ - -#define BS_JmpBoot 0 /* x86 jump instruction (3-byte) */ -#define BS_OEMName 3 /* OEM name (8-byte) */ -#define BPB_BytsPerSec 11 /* Sector size [byte] (WORD) */ -#define BPB_SecPerClus 13 /* Cluster size [sector] (BYTE) */ -#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (WORD) */ -#define BPB_NumFATs 16 /* Number of FATs (BYTE) */ -#define BPB_RootEntCnt 17 /* Size of root directory area for FAT [entry] (WORD) */ -#define BPB_TotSec16 19 /* Volume size (16-bit) [sector] (WORD) */ -#define BPB_Media 21 /* Media descriptor byte (BYTE) */ -#define BPB_FATSz16 22 /* FAT size (16-bit) [sector] (WORD) */ -#define BPB_SecPerTrk 24 /* Number of sectors per track for int13h [sector] (WORD) */ -#define BPB_NumHeads 26 /* Number of heads for int13h (WORD) */ -#define BPB_HiddSec 28 /* Volume offset from top of the drive (DWORD) */ -#define BPB_TotSec32 32 /* Volume size (32-bit) [sector] (DWORD) */ -#define BS_DrvNum 36 /* Physical drive number for int13h (BYTE) */ -#define BS_NTres 37 /* WindowsNT error flag (BYTE) */ -#define BS_BootSig 38 /* Extended boot signature (BYTE) */ -#define BS_VolID 39 /* Volume serial number (DWORD) */ -#define BS_VolLab 43 /* Volume label string (8-byte) */ -#define BS_FilSysType 54 /* Filesystem type string (8-byte) */ -#define BS_BootCode 62 /* Boot code (448-byte) */ -#define BS_55AA 510 /* Signature word (WORD) */ - -#define BPB_FATSz32 36 /* FAT32: FAT size [sector] (DWORD) */ -#define BPB_ExtFlags32 40 /* FAT32: Extended flags (WORD) */ -#define BPB_FSVer32 42 /* FAT32: Filesystem version (WORD) */ -#define BPB_RootClus32 44 /* FAT32: Root directory cluster (DWORD) */ -#define BPB_FSInfo32 48 /* FAT32: Offset of FSINFO sector (WORD) */ -#define BPB_BkBootSec32 50 /* FAT32: Offset of backup boot sector (WORD) */ -#define BS_DrvNum32 64 /* FAT32: Physical drive number for int13h (BYTE) */ -#define BS_NTres32 65 /* FAT32: Error flag (BYTE) */ -#define BS_BootSig32 66 /* FAT32: Extended boot signature (BYTE) */ -#define BS_VolID32 67 /* FAT32: Volume serial number (DWORD) */ -#define BS_VolLab32 71 /* FAT32: Volume label string (8-byte) */ -#define BS_FilSysType32 82 /* FAT32: Filesystem type string (8-byte) */ -#define BS_BootCode32 90 /* FAT32: Boot code (420-byte) */ - -#define BPB_ZeroedEx 11 /* exFAT: MBZ field (53-byte) */ -#define BPB_VolOfsEx 64 /* exFAT: Volume offset from top of the drive [sector] (QWORD) */ -#define BPB_TotSecEx 72 /* exFAT: Volume size [sector] (QWORD) */ -#define BPB_FatOfsEx 80 /* exFAT: FAT offset from top of the volume [sector] (DWORD) */ -#define BPB_FatSzEx 84 /* exFAT: FAT size [sector] (DWORD) */ -#define BPB_DataOfsEx 88 /* exFAT: Data offset from top of the volume [sector] (DWORD) */ -#define BPB_NumClusEx 92 /* exFAT: Number of clusters (DWORD) */ -#define BPB_RootClusEx 96 /* exFAT: Root directory start cluster (DWORD) */ -#define BPB_VolIDEx 100 /* exFAT: Volume serial number (DWORD) */ -#define BPB_FSVerEx 104 /* exFAT: Filesystem version (WORD) */ -#define BPB_VolFlagEx 106 /* exFAT: Volume flags (WORD) */ -#define BPB_BytsPerSecEx 108 /* exFAT: Log2 of sector size in unit of byte (BYTE) */ -#define BPB_SecPerClusEx 109 /* exFAT: Log2 of cluster size in unit of sector (BYTE) */ -#define BPB_NumFATsEx 110 /* exFAT: Number of FATs (BYTE) */ -#define BPB_DrvNumEx 111 /* exFAT: Physical drive number for int13h (BYTE) */ -#define BPB_PercInUseEx 112 /* exFAT: Percent in use (BYTE) */ -#define BPB_RsvdEx 113 /* exFAT: Reserved (7-byte) */ -#define BS_BootCodeEx 120 /* exFAT: Boot code (390-byte) */ - -#define DIR_Name 0 /* Short file name (11-byte) */ -#define DIR_Attr 11 /* Attribute (BYTE) */ -#define DIR_NTres 12 /* Lower case flag (BYTE) */ -#define DIR_CrtTime10 13 /* Created time sub-second (BYTE) */ -#define DIR_CrtTime 14 /* Created time (DWORD) */ -#define DIR_LstAccDate 18 /* Last accessed date (WORD) */ -#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (WORD) */ -#define DIR_ModTime 22 /* Modified time (DWORD) */ -#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (WORD) */ -#define DIR_FileSize 28 /* File size (DWORD) */ -#define LDIR_Ord 0 /* LFN: LFN order and LLE flag (BYTE) */ -#define LDIR_Attr 11 /* LFN: LFN attribute (BYTE) */ -#define LDIR_Type 12 /* LFN: Entry type (BYTE) */ -#define LDIR_Chksum 13 /* LFN: Checksum of the SFN (BYTE) */ -#define LDIR_FstClusLO 26 /* LFN: MBZ field (WORD) */ -#define XDIR_Type 0 /* exFAT: Type of exFAT directory entry (BYTE) */ -#define XDIR_NumLabel 1 /* exFAT: Number of volume label characters (BYTE) */ -#define XDIR_Label 2 /* exFAT: Volume label (11-WORD) */ -#define XDIR_CaseSum 4 /* exFAT: Sum of case conversion table (DWORD) */ -#define XDIR_NumSec 1 /* exFAT: Number of secondary entries (BYTE) */ -#define XDIR_SetSum 2 /* exFAT: Sum of the set of directory entries (WORD) */ -#define XDIR_Attr 4 /* exFAT: File attribute (WORD) */ -#define XDIR_CrtTime 8 /* exFAT: Created time (DWORD) */ -#define XDIR_ModTime 12 /* exFAT: Modified time (DWORD) */ -#define XDIR_AccTime 16 /* exFAT: Last accessed time (DWORD) */ -#define XDIR_CrtTime10 20 /* exFAT: Created time subsecond (BYTE) */ -#define XDIR_ModTime10 21 /* exFAT: Modified time subsecond (BYTE) */ -#define XDIR_CrtTZ 22 /* exFAT: Created timezone (BYTE) */ -#define XDIR_ModTZ 23 /* exFAT: Modified timezone (BYTE) */ -#define XDIR_AccTZ 24 /* exFAT: Last accessed timezone (BYTE) */ -#define XDIR_GenFlags 33 /* exFAT: General secondary flags (BYTE) */ -#define XDIR_NumName 35 /* exFAT: Number of file name characters (BYTE) */ -#define XDIR_NameHash 36 /* exFAT: Hash of file name (WORD) */ -#define XDIR_ValidFileSize 40 /* exFAT: Valid file size (QWORD) */ -#define XDIR_FstClus 52 /* exFAT: First cluster of the file data (DWORD) */ -#define XDIR_FileSize 56 /* exFAT: File/Directory size (QWORD) */ - -#define SZDIRE 32 /* Size of a directory entry */ -#define DDEM 0xE5 /* Deleted directory entry mark set to DIR_Name[0] */ -#define RDDEM 0x05 /* Replacement of the character collides with DDEM */ -#define LLEF 0x40 /* Last long entry flag in LDIR_Ord */ - -#define FSI_LeadSig 0 /* FAT32 FSI: Leading signature (DWORD) */ -#define FSI_StrucSig 484 /* FAT32 FSI: Structure signature (DWORD) */ -#define FSI_Free_Count 488 /* FAT32 FSI: Number of free clusters (DWORD) */ -#define FSI_Nxt_Free 492 /* FAT32 FSI: Last allocated cluster (DWORD) */ - -#define MBR_Table 446 /* MBR: Offset of partition table in the MBR */ -#define SZ_PTE 16 /* MBR: Size of a partition table entry */ -#define PTE_Boot 0 /* MBR PTE: Boot indicator */ -#define PTE_StHead 1 /* MBR PTE: Start head */ -#define PTE_StSec 2 /* MBR PTE: Start sector */ -#define PTE_StCyl 3 /* MBR PTE: Start cylinder */ -#define PTE_System 4 /* MBR PTE: System ID */ -#define PTE_EdHead 5 /* MBR PTE: End head */ -#define PTE_EdSec 6 /* MBR PTE: End sector */ -#define PTE_EdCyl 7 /* MBR PTE: End cylinder */ -#define PTE_StLba 8 /* MBR PTE: Start in LBA */ -#define PTE_SizLba 12 /* MBR PTE: Size in LBA */ - - -/* Post process on fatal error in the file operations */ -#define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); } - - -/* Re-entrancy related */ -#if FF_FS_REENTRANT -#if FF_USE_LFN == 1 -#error Static LFN work area cannot be used at thread-safe configuration -#endif -#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } -#else -#define LEAVE_FF(fs, res) return res -#endif - - -/* Definitions of volume - physical location conversion */ -#if FF_MULTI_PARTITION -#define LD2PD(vol) VolToPart[vol].pd /* Get physical drive number */ -#define LD2PT(vol) VolToPart[vol].pt /* Get partition index */ -#else -#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ -#define LD2PT(vol) 0 /* Find first valid partition or in SFD */ -#endif - - -/* Definitions of sector size */ -#if (FF_MAX_SS < FF_MIN_SS) || (FF_MAX_SS != 512 && FF_MAX_SS != 1024 && FF_MAX_SS != 2048 && FF_MAX_SS != 4096) || (FF_MIN_SS != 512 && FF_MIN_SS != 1024 && FF_MIN_SS != 2048 && FF_MIN_SS != 4096) -#error Wrong sector size configuration -#endif -#if FF_MAX_SS == FF_MIN_SS -#define SS(fs) ((UINT)FF_MAX_SS) /* Fixed sector size */ -#else -#define SS(fs) ((fs)->ssize) /* Variable sector size */ -#endif - - -/* Timestamp */ -#if FF_FS_NORTC == 1 -#if FF_NORTC_YEAR < 1980 || FF_NORTC_YEAR > 2107 || FF_NORTC_MON < 1 || FF_NORTC_MON > 12 || FF_NORTC_MDAY < 1 || FF_NORTC_MDAY > 31 -#error Invalid FF_FS_NORTC settings -#endif -#define GET_FATTIME() ((DWORD)(FF_NORTC_YEAR - 1980) << 25 | (DWORD)FF_NORTC_MON << 21 | (DWORD)FF_NORTC_MDAY << 16) -#else -#define GET_FATTIME() get_fattime() -#endif - - -/* File lock controls */ -#if FF_FS_LOCK != 0 -#if FF_FS_READONLY -#error FF_FS_LOCK must be 0 at read-only configuration -#endif -typedef struct { - FATFS *fs; /* Object ID 1, volume (NULL:blank entry) */ - DWORD clu; /* Object ID 2, containing directory (0:root) */ - DWORD ofs; /* Object ID 3, offset in the directory */ - WORD ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */ -} FILESEM; -#endif - - -/* SBCS up-case tables (\x80-\xFF) */ -#define TBL_CT437 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ - 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT720 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT737 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ - 0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ - 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xEF,0xF5,0xF0,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT771 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDC,0xDE,0xDE, \ - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF} -#define TBL_CT775 {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F, \ - 0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT850 {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, \ - 0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, \ - 0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT852 {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F, \ - 0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0xAC, \ - 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} -#define TBL_CT855 {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F, \ - 0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ - 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ - 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF, \ - 0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT857 {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x49,0x8E,0x8F, \ - 0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0x49,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0xED,0xEE,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT860 {0x80,0x9A,0x90,0x8F,0x8E,0x91,0x86,0x80,0x89,0x89,0x92,0x8B,0x8C,0x98,0x8E,0x8F, \ - 0x90,0x91,0x92,0x8C,0x99,0xA9,0x96,0x9D,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x86,0x8B,0x9F,0x96,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT861 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x8B,0x8B,0x8D,0x8E,0x8F, \ - 0x90,0x92,0x92,0x4F,0x99,0x8D,0x55,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xA4,0xA5,0xA6,0xA7,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT862 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT863 {0x43,0x55,0x45,0x41,0x41,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x41,0x8F, \ - 0x45,0x45,0x45,0x4F,0x45,0x49,0x55,0x55,0x98,0x4F,0x55,0x9B,0x9C,0x55,0x55,0x9F, \ - 0xA0,0xA1,0x4F,0x55,0xA4,0xA5,0xA6,0xA7,0x49,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT864 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ - 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT865 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ - 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ - 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT866 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} -#define TBL_CT869 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x86,0x9C,0x8D,0x8F,0x90, \ - 0x91,0x90,0x92,0x95,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ - 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ - 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xA4,0xA5,0xA6,0xD9,0xDA,0xDB,0xDC,0xA7,0xA8,0xDF, \ - 0xA9,0xAA,0xAC,0xAD,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xCF,0xCF,0xD0,0xEF, \ - 0xF0,0xF1,0xD1,0xD2,0xD3,0xF5,0xD4,0xF7,0xF8,0xF9,0xD5,0x96,0x95,0x98,0xFE,0xFF} - - -/* DBCS code range |----- 1st byte -----| |----------- 2nd byte -----------| */ -#define TBL_DC932 {0x81, 0x9F, 0xE0, 0xFC, 0x40, 0x7E, 0x80, 0xFC, 0x00, 0x00} -#define TBL_DC936 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0x80, 0xFE, 0x00, 0x00} -#define TBL_DC949 {0x81, 0xFE, 0x00, 0x00, 0x41, 0x5A, 0x61, 0x7A, 0x81, 0xFE} -#define TBL_DC950 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0xA1, 0xFE, 0x00, 0x00} - - -/* Macros for table definitions */ -#define MERGE_2STR(a, b) a ## b -#define MKCVTBL(hd, cp) MERGE_2STR(hd, cp) - - - - -/*-------------------------------------------------------------------------- - - Module Private Work Area - ----------------------------------------------------------------------------*/ -/* Remark: Variables defined here without initial value shall be guaranteed -/ zero/null at start-up. If not, the linker option or start-up routine is -/ not compliance with C standard. */ - -/*--------------------------------*/ -/* File/Volume controls */ -/*--------------------------------*/ - -#if FF_VOLUMES < 1 || FF_VOLUMES > 10 -#error Wrong FF_VOLUMES setting -#endif -static FATFS* FatFs[FF_VOLUMES]; /* Pointer to the filesystem objects (logical drives) */ -static WORD Fsid; /* Filesystem mount ID */ - -#if FF_FS_RPATH != 0 -static BYTE CurrVol; /* Current drive */ -#endif - -#if FF_FS_LOCK != 0 -static FILESEM Files[FF_FS_LOCK]; /* Open object lock semaphores */ -#endif - -#if FF_STR_VOLUME_ID -#ifdef FF_VOLUME_STRS -static const char* const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS}; /* Pre-defined volume ID */ -#endif -#endif - - -/*--------------------------------*/ -/* LFN/Directory working buffer */ -/*--------------------------------*/ - -#if FF_USE_LFN == 0 /* Non-LFN configuration */ -#if FF_FS_EXFAT -#error LFN must be enabled when enable exFAT -#endif -#define DEF_NAMBUF -#define INIT_NAMBUF(fs) -#define FREE_NAMBUF() -#define LEAVE_MKFS(res) return res - -#else /* LFN configurations */ -#if FF_MAX_LFN < 12 || FF_MAX_LFN > 255 -#error Wrong setting of FF_MAX_LFN -#endif -#if FF_LFN_BUF < FF_SFN_BUF || FF_SFN_BUF < 12 -#error Wrong setting of FF_LFN_BUF or FF_SFN_BUF -#endif -#if FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3 -#error Wrong setting of FF_LFN_UNICODE -#endif -static const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* FAT: Offset of LFN characters in the directory entry */ -#define MAXDIRB(nc) ((nc + 44U) / 15 * SZDIRE) /* exFAT: Size of directory entry block scratchpad buffer needed for the name length */ - -#if FF_USE_LFN == 1 /* LFN enabled with static working buffer */ -#if FF_FS_EXFAT -static BYTE DirBuf[MAXDIRB(FF_MAX_LFN)]; /* Directory entry block scratchpad buffer */ -#endif -static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */ -#define DEF_NAMBUF -#define INIT_NAMBUF(fs) -#define FREE_NAMBUF() -#define LEAVE_MKFS(res) return res - -#elif FF_USE_LFN == 2 /* LFN enabled with dynamic working buffer on the stack */ -#if FF_FS_EXFAT -#define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN+1]; BYTE dbuf[MAXDIRB(FF_MAX_LFN)]; /* LFN working buffer and directory entry block scratchpad buffer */ -#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; (fs)->dirbuf = dbuf; } -#define FREE_NAMBUF() -#else -#define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN+1]; /* LFN working buffer */ -#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; } -#define FREE_NAMBUF() -#endif -#define LEAVE_MKFS(res) return res - -#elif FF_USE_LFN == 3 /* LFN enabled with dynamic working buffer on the heap */ -#if FF_FS_EXFAT -#define DEF_NAMBUF WCHAR *lfn; /* Pointer to LFN working buffer and directory entry block scratchpad buffer */ -#define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN+1)*2 + MAXDIRB(FF_MAX_LFN)); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; (fs)->dirbuf = (BYTE*)(lfn+FF_MAX_LFN+1); } -#define FREE_NAMBUF() ff_memfree(lfn) -#else -#define DEF_NAMBUF WCHAR *lfn; /* Pointer to LFN working buffer */ -#define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN+1)*2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; } -#define FREE_NAMBUF() ff_memfree(lfn) -#endif -#define LEAVE_MKFS(res) { if (!work) ff_memfree(buf); return res; } -#define MAX_MALLOC 0x4000 /* Must be >=FF_MAX_SS */ - -#else -#error Wrong setting of FF_USE_LFN - -#endif /* FF_USE_LFN == 1 */ -#endif /* FF_USE_LFN == 0 */ - - - -/*--------------------------------*/ -/* Code conversion tables */ -/*--------------------------------*/ - -#if FF_CODE_PAGE == 0 /* Run-time code page configuration */ -#define CODEPAGE CodePage -static WORD CodePage; /* Current code page */ -static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */ - -static const BYTE Ct437[] = TBL_CT437; -static const BYTE Ct720[] = TBL_CT720; -static const BYTE Ct737[] = TBL_CT737; -static const BYTE Ct771[] = TBL_CT771; -static const BYTE Ct775[] = TBL_CT775; -static const BYTE Ct850[] = TBL_CT850; -static const BYTE Ct852[] = TBL_CT852; -static const BYTE Ct855[] = TBL_CT855; -static const BYTE Ct857[] = TBL_CT857; -static const BYTE Ct860[] = TBL_CT860; -static const BYTE Ct861[] = TBL_CT861; -static const BYTE Ct862[] = TBL_CT862; -static const BYTE Ct863[] = TBL_CT863; -static const BYTE Ct864[] = TBL_CT864; -static const BYTE Ct865[] = TBL_CT865; -static const BYTE Ct866[] = TBL_CT866; -static const BYTE Ct869[] = TBL_CT869; -static const BYTE Dc932[] = TBL_DC932; -static const BYTE Dc936[] = TBL_DC936; -static const BYTE Dc949[] = TBL_DC949; -static const BYTE Dc950[] = TBL_DC950; - -#elif FF_CODE_PAGE < 900 /* Static code page configuration (SBCS) */ -#define CODEPAGE FF_CODE_PAGE -static const BYTE ExCvt[] = MKCVTBL(TBL_CT, FF_CODE_PAGE); - -#else /* Static code page configuration (DBCS) */ -#define CODEPAGE FF_CODE_PAGE -static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE); - -#endif - - - - -/*-------------------------------------------------------------------------- - - Module Private Functions - ----------------------------------------------------------------------------*/ - -/*-----------------------------------------------------------------------*/ -/* Load/Store multi-byte word in the FAT structure */ -/*-----------------------------------------------------------------------*/ - -static WORD ld_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ -{ - WORD rv; - - rv = ptr[1]; - rv = rv << 8 | ptr[0]; - return rv; -} - -static DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ -{ - DWORD rv; - - rv = ptr[3]; - rv = rv << 8 | ptr[2]; - rv = rv << 8 | ptr[1]; - rv = rv << 8 | ptr[0]; - return rv; -} - -#if FF_FS_EXFAT -static QWORD ld_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ -{ - QWORD rv; - - rv = ptr[7]; - rv = rv << 8 | ptr[6]; - rv = rv << 8 | ptr[5]; - rv = rv << 8 | ptr[4]; - rv = rv << 8 | ptr[3]; - rv = rv << 8 | ptr[2]; - rv = rv << 8 | ptr[1]; - rv = rv << 8 | ptr[0]; - return rv; -} -#endif - -#if !FF_FS_READONLY -static void st_word (BYTE* ptr, WORD val) /* Store a 2-byte word in little-endian */ -{ - *ptr++ = (BYTE)val; val >>= 8; - *ptr++ = (BYTE)val; -} - -static void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ -{ - *ptr++ = (BYTE)val; val >>= 8; - *ptr++ = (BYTE)val; val >>= 8; - *ptr++ = (BYTE)val; val >>= 8; - *ptr++ = (BYTE)val; -} - -#if FF_FS_EXFAT -static void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ -{ - *ptr++ = (BYTE)val; val >>= 8; - *ptr++ = (BYTE)val; val >>= 8; - *ptr++ = (BYTE)val; val >>= 8; - *ptr++ = (BYTE)val; val >>= 8; - *ptr++ = (BYTE)val; val >>= 8; - *ptr++ = (BYTE)val; val >>= 8; - *ptr++ = (BYTE)val; val >>= 8; - *ptr++ = (BYTE)val; -} -#endif -#endif /* !FF_FS_READONLY */ - - - -/*-----------------------------------------------------------------------*/ -/* String functions */ -/*-----------------------------------------------------------------------*/ - -/* Copy memory to memory */ -static void mem_cpy (void* dst, const void* src, UINT cnt) -{ - BYTE *d = (BYTE*)dst; - const BYTE *s = (const BYTE*)src; - - if (cnt != 0) { - do { - *d++ = *s++; - } while (--cnt); - } -} - - -/* Fill memory block */ -static void mem_set (void* dst, int val, UINT cnt) -{ - BYTE *d = (BYTE*)dst; - - do { - *d++ = (BYTE)val; - } while (--cnt); -} - - -/* Compare memory block */ -static int mem_cmp (const void* dst, const void* src, UINT cnt) /* ZR:same, NZ:different */ -{ - const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; - int r = 0; - - do { - r = *d++ - *s++; - } while (--cnt && r == 0); - - return r; -} - - -/* Check if chr is contained in the string */ -static int chk_chr (const char* str, int chr) /* NZ:contained, ZR:not contained */ -{ - while (*str && *str != chr) str++; - return *str; -} - - -/* Test if the character is DBC 1st byte */ -static int dbc_1st (BYTE c) -{ -#if FF_CODE_PAGE == 0 /* Variable code page */ - if (DbcTbl && c >= DbcTbl[0]) { - if (c <= DbcTbl[1]) return 1; /* 1st byte range 1 */ - if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1; /* 1st byte range 2 */ - } -#elif FF_CODE_PAGE >= 900 /* DBCS fixed code page */ - if (c >= DbcTbl[0]) { - if (c <= DbcTbl[1]) return 1; - if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1; - } -#else /* SBCS fixed code page */ - if (c != 0) return 0; /* Always false */ -#endif - return 0; -} - - -/* Test if the character is DBC 2nd byte */ -static int dbc_2nd (BYTE c) -{ -#if FF_CODE_PAGE == 0 /* Variable code page */ - if (DbcTbl && c >= DbcTbl[4]) { - if (c <= DbcTbl[5]) return 1; /* 2nd byte range 1 */ - if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1; /* 2nd byte range 2 */ - if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1; /* 2nd byte range 3 */ - } -#elif FF_CODE_PAGE >= 900 /* DBCS fixed code page */ - if (c >= DbcTbl[4]) { - if (c <= DbcTbl[5]) return 1; - if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1; - if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1; - } -#else /* SBCS fixed code page */ - if (c != 0) return 0; /* Always false */ -#endif - return 0; -} - - -#if FF_USE_LFN - -/* Get a character from TCHAR string in defined API encodeing */ -static DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double encoding unit, 0xFFFFFFFF on decode error) */ - const TCHAR** str /* Pointer to pointer to TCHAR string in configured encoding */ -) -{ - DWORD uc; - const TCHAR *p = *str; - -#if FF_LFN_UNICODE == 1 /* UTF-16 input */ - WCHAR wc; - - uc = *p++; /* Get a unit */ - if (IsSurrogate(uc)) { /* Surrogate? */ - wc = *p++; /* Get low surrogate */ - if (!IsSurrogateH(uc) || !IsSurrogateL(wc)) return 0xFFFFFFFF; /* Wrong surrogate? */ - uc = uc << 16 | wc; - } - -#elif FF_LFN_UNICODE == 2 /* UTF-8 input */ - BYTE b; - int nf; - - uc = (BYTE)*p++; /* Get a unit */ - if (uc & 0x80) { /* Multiple byte code? */ - if ((uc & 0xE0) == 0xC0) { /* 2-byte sequence? */ - uc &= 0x1F; nf = 1; - } else { - if ((uc & 0xF0) == 0xE0) { /* 3-byte sequence? */ - uc &= 0x0F; nf = 2; - } else { - if ((uc & 0xF8) == 0xF0) { /* 4-byte sequence? */ - uc &= 0x07; nf = 3; - } else { /* Wrong sequence */ - return 0xFFFFFFFF; - } - } - } - do { /* Get trailing bytes */ - b = (BYTE)*p++; - if ((b & 0xC0) != 0x80) return 0xFFFFFFFF; /* Wrong sequence? */ - uc = uc << 6 | (b & 0x3F); - } while (--nf != 0); - if (uc < 0x80 || IsSurrogate(uc) || uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ - if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ - } - -#elif FF_LFN_UNICODE == 3 /* UTF-32 input */ - uc = (TCHAR)*p++; /* Get a unit */ - if (uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ - if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ - -#else /* ANSI/OEM input */ - BYTE b; - WCHAR wc; - - wc = (BYTE)*p++; /* Get a byte */ - if (dbc_1st((BYTE)wc)) { /* Is it a DBC 1st byte? */ - b = (BYTE)*p++; /* Get 2nd byte */ - if (!dbc_2nd(b)) return 0xFFFFFFFF; /* Invalid code? */ - wc = (wc << 8) + b; /* Make a DBC */ - } - if (wc != 0) { - wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM ==> Unicode */ - if (wc == 0) return 0xFFFFFFFF; /* Invalid code? */ - } - uc = wc; - -#endif - *str = p; /* Next read pointer */ - return uc; -} - - -/* Output a TCHAR string in defined API encoding */ -static BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or wrong encoding) */ - DWORD chr, /* UTF-16 encoded character (Double encoding unit char if >=0x10000) */ - TCHAR* buf, /* Output buffer */ - UINT szb /* Size of the buffer */ -) -{ -#if FF_LFN_UNICODE == 1 /* UTF-16 output */ - WCHAR hs, wc; - - hs = (WCHAR)(chr >> 16); - wc = (WCHAR)chr; - if (hs == 0) { /* Single encoding unit? */ - if (szb < 1 || IsSurrogate(wc)) return 0; /* Buffer overflow or wrong code? */ - *buf = wc; - return 1; - } - if (szb < 2 || !IsSurrogateH(hs) || !IsSurrogateL(wc)) return 0; /* Buffer overflow or wrong surrogate? */ - *buf++ = hs; - *buf++ = wc; - return 2; - -#elif FF_LFN_UNICODE == 2 /* UTF-8 output */ - DWORD hc; - - if (chr < 0x80) { /* Single byte code? */ - if (szb < 1) return 0; /* Buffer overflow? */ - *buf = (TCHAR)chr; - return 1; - } - if (chr < 0x800) { /* 2-byte sequence? */ - if (szb < 2) return 0; /* Buffer overflow? */ - *buf++ = (TCHAR)(0xC0 | (chr >> 6 & 0x1F)); - *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); - return 2; - } - if (chr < 0x10000) { /* 3-byte sequence? */ - if (szb < 3 || IsSurrogate(chr)) return 0; /* Buffer overflow or wrong code? */ - *buf++ = (TCHAR)(0xE0 | (chr >> 12 & 0x0F)); - *buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F)); - *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); - return 3; - } - /* 4-byte sequence */ - if (szb < 4) return 0; /* Buffer overflow? */ - hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */ - chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */ - if (hc >= 0x100000 || chr >= 0x400) return 0; /* Wrong surrogate? */ - chr = (hc | chr) + 0x10000; - *buf++ = (TCHAR)(0xF0 | (chr >> 18 & 0x07)); - *buf++ = (TCHAR)(0x80 | (chr >> 12 & 0x3F)); - *buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F)); - *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); - return 4; - -#elif FF_LFN_UNICODE == 3 /* UTF-32 output */ - DWORD hc; - - if (szb < 1) return 0; /* Buffer overflow? */ - if (chr >= 0x10000) { /* Out of BMP? */ - hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */ - chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */ - if (hc >= 0x100000 || chr >= 0x400) return 0; /* Wrong surrogate? */ - chr = (hc | chr) + 0x10000; - } - *buf++ = (TCHAR)chr; - return 1; - -#else /* ANSI/OEM output */ - WCHAR wc; - - wc = ff_uni2oem(chr, CODEPAGE); - if (wc >= 0x100) { /* Is this a DBC? */ - if (szb < 2) return 0; - *buf++ = (char)(wc >> 8); /* Store DBC 1st byte */ - *buf++ = (TCHAR)wc; /* Store DBC 2nd byte */ - return 2; - } - if (wc == 0 || szb < 1) return 0; /* Invalid char or buffer overflow? */ - *buf++ = (TCHAR)wc; /* Store the character */ - return 1; -#endif -} -#endif /* FF_USE_LFN */ - - -#if FF_FS_REENTRANT -/*-----------------------------------------------------------------------*/ -/* Request/Release grant to access the volume */ -/*-----------------------------------------------------------------------*/ -static int lock_fs ( /* 1:Ok, 0:timeout */ - FATFS* fs /* Filesystem object */ -) -{ - return ff_req_grant(fs->sobj); -} - - -static void unlock_fs ( - FATFS* fs, /* Filesystem object */ - FRESULT res /* Result code to be returned */ -) -{ - if (fs && res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_TIMEOUT) { - ff_rel_grant(fs->sobj); - } -} - -#endif - - - -#if FF_FS_LOCK != 0 -/*-----------------------------------------------------------------------*/ -/* File lock control functions */ -/*-----------------------------------------------------------------------*/ - -static FRESULT chk_lock ( /* Check if the file can be accessed */ - DIR* dp, /* Directory object pointing the file to be checked */ - int acc /* Desired access type (0:Read mode open, 1:Write mode open, 2:Delete or rename) */ -) -{ - UINT i, be; - - /* Search open object table for the object */ - be = 0; - for (i = 0; i < FF_FS_LOCK; i++) { - if (Files[i].fs) { /* Existing entry */ - if (Files[i].fs == dp->obj.fs && /* Check if the object matches with an open object */ - Files[i].clu == dp->obj.sclust && - Files[i].ofs == dp->dptr) break; - } else { /* Blank entry */ - be = 1; - } - } - if (i == FF_FS_LOCK) { /* The object has not been opened */ - return (!be && acc != 2) ? FR_TOO_MANY_OPEN_FILES : FR_OK; /* Is there a blank entry for new object? */ - } - - /* The object was opened. Reject any open against writing file and all write mode open */ - return (acc != 0 || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; -} - - -static int enq_lock (void) /* Check if an entry is available for a new object */ -{ - UINT i; - - for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; - return (i == FF_FS_LOCK) ? 0 : 1; -} - - -static UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ - DIR* dp, /* Directory object pointing the file to register or increment */ - int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ -) -{ - UINT i; - - - for (i = 0; i < FF_FS_LOCK; i++) { /* Find the object */ - if (Files[i].fs == dp->obj.fs && - Files[i].clu == dp->obj.sclust && - Files[i].ofs == dp->dptr) break; - } - - if (i == FF_FS_LOCK) { /* Not opened. Register it as new. */ - for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; - if (i == FF_FS_LOCK) return 0; /* No free entry to register (int err) */ - Files[i].fs = dp->obj.fs; - Files[i].clu = dp->obj.sclust; - Files[i].ofs = dp->dptr; - Files[i].ctr = 0; - } - - if (acc >= 1 && Files[i].ctr) return 0; /* Access violation (int err) */ - - Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ - - return i + 1; /* Index number origin from 1 */ -} - - -static FRESULT dec_lock ( /* Decrement object open counter */ - UINT i /* Semaphore index (1..) */ -) -{ - WORD n; - FRESULT res; - - - if (--i < FF_FS_LOCK) { /* Index number origin from 0 */ - n = Files[i].ctr; - if (n == 0x100) n = 0; /* If write mode open, delete the entry */ - if (n > 0) n--; /* Decrement read mode open count */ - Files[i].ctr = n; - if (n == 0) Files[i].fs = 0; /* Delete the entry if open count gets zero */ - res = FR_OK; - } else { - res = FR_INT_ERR; /* Invalid index nunber */ - } - return res; -} - - -static void clear_lock ( /* Clear lock entries of the volume */ - FATFS *fs -) -{ - UINT i; - - for (i = 0; i < FF_FS_LOCK; i++) { - if (Files[i].fs == fs) Files[i].fs = 0; - } -} - -#endif /* FF_FS_LOCK != 0 */ - - - -/*-----------------------------------------------------------------------*/ -/* Move/Flush disk access window in the filesystem object */ -/*-----------------------------------------------------------------------*/ -#if !FF_FS_READONLY -static FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ - FATFS* fs /* Filesystem object */ -) -{ - FRESULT res = FR_OK; - - - if (fs->wflag) { /* Is the disk access window dirty */ - if (disk_write(fs->pdrv, fs->win, fs->winsect, 1) == RES_OK) { /* Write back the window */ - fs->wflag = 0; /* Clear window dirty flag */ - if (fs->winsect - fs->fatbase < fs->fsize) { /* Is it in the 1st FAT? */ - if (fs->n_fats == 2) disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1); /* Reflect it to 2nd FAT if needed */ - } - } else { - res = FR_DISK_ERR; - } - } - return res; -} -#endif - - -static FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ - FATFS* fs, /* Filesystem object */ - DWORD sector /* Sector number to make appearance in the fs->win[] */ -) -{ - FRESULT res = FR_OK; - - - if (sector != fs->winsect) { /* Window offset changed? */ -#if !FF_FS_READONLY - res = sync_window(fs); /* Write-back changes */ -#endif - if (res == FR_OK) { /* Fill sector window with new data */ - if (disk_read(fs->pdrv, fs->win, sector, 1) != RES_OK) { - sector = 0xFFFFFFFF; /* Invalidate window if read data is not valid */ - res = FR_DISK_ERR; - } - fs->winsect = sector; - } - } - return res; -} - - - - -#if !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Synchronize filesystem and data on the storage */ -/*-----------------------------------------------------------------------*/ - -static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ - FATFS* fs /* Filesystem object */ -) -{ - FRESULT res; - - - res = sync_window(fs); - if (res == FR_OK) { - if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */ - /* Create FSInfo structure */ - mem_set(fs->win, 0, sizeof fs->win); - st_word(fs->win + BS_55AA, 0xAA55); - st_dword(fs->win + FSI_LeadSig, 0x41615252); - st_dword(fs->win + FSI_StrucSig, 0x61417272); - st_dword(fs->win + FSI_Free_Count, fs->free_clst); - st_dword(fs->win + FSI_Nxt_Free, fs->last_clst); - /* Write it into the FSInfo sector */ - fs->winsect = fs->volbase + 1; - disk_write(fs->pdrv, fs->win, fs->winsect, 1); - fs->fsi_flag = 0; - } - /* Make sure that no pending write process in the lower layer */ - if (disk_ioctl(fs->pdrv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; - } - - return res; -} - -#endif - - - -/*-----------------------------------------------------------------------*/ -/* Get physical sector number from cluster number */ -/*-----------------------------------------------------------------------*/ - -static DWORD clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ - FATFS* fs, /* Filesystem object */ - DWORD clst /* Cluster# to be converted */ -) -{ - clst -= 2; /* Cluster number is origin from 2 */ - if (clst >= fs->n_fatent - 2) return 0; /* Is it invalid cluster number? */ - return fs->database + fs->csize * clst; /* Start sector number of the cluster */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* FAT access - Read value of a FAT entry */ -/*-----------------------------------------------------------------------*/ - -static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */ - FFOBJID* obj, /* Corresponding object */ - DWORD clst /* Cluster number to get the value */ -) -{ - UINT wc, bc; - DWORD val; - FATFS *fs = obj->fs; - - - if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */ - val = 1; /* Internal error */ - - } else { - val = 0xFFFFFFFF; /* Default value falls on disk error */ - - switch (fs->fs_type) { - case FS_FAT12 : - bc = (UINT)clst; bc += bc / 2; - if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; - wc = fs->win[bc++ % SS(fs)]; /* Get 1st byte of the entry */ - if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; - wc |= fs->win[bc % SS(fs)] << 8; /* Merge 2nd byte of the entry */ - val = (clst & 1) ? (wc >> 4) : (wc & 0xFFF); /* Adjust bit position */ - break; - - case FS_FAT16 : - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break; - val = ld_word(fs->win + clst * 2 % SS(fs)); /* Simple WORD array */ - break; - - case FS_FAT32 : - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; - val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF; /* Simple DWORD array but mask out upper 4 bits */ - break; -#if FF_FS_EXFAT - case FS_EXFAT : - if ((obj->objsize != 0 && obj->sclust != 0) || obj->stat == 0) { /* Object except root dir must have valid data length */ - DWORD cofs = clst - obj->sclust; /* Offset from start cluster */ - DWORD clen = (DWORD)((obj->objsize - 1) / SS(fs)) / fs->csize; /* Number of clusters - 1 */ - - if (obj->stat == 2 && cofs <= clen) { /* Is it a contiguous chain? */ - val = (cofs == clen) ? 0x7FFFFFFF : clst + 1; /* No data on the FAT, generate the value */ - break; - } - if (obj->stat == 3 && cofs < obj->n_cont) { /* Is it in the 1st fragment? */ - val = clst + 1; /* Generate the value */ - break; - } - if (obj->stat != 2) { /* Get value from FAT if FAT chain is valid */ - if (obj->n_frag != 0) { /* Is it on the growing edge? */ - val = 0x7FFFFFFF; /* Generate EOC */ - } else { - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; - val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF; - } - break; - } - } - /* go to default */ -#endif - default: - val = 1; /* Internal error */ - } - } - - return val; -} - - - - -#if !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* FAT access - Change value of a FAT entry */ -/*-----------------------------------------------------------------------*/ - -static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ - FATFS* fs, /* Corresponding filesystem object */ - DWORD clst, /* FAT index number (cluster number) to be changed */ - DWORD val /* New value to be set to the entry */ -) -{ - UINT bc; - BYTE *p; - FRESULT res = FR_INT_ERR; - - - if (clst >= 2 && clst < fs->n_fatent) { /* Check if in valid range */ - switch (fs->fs_type) { - case FS_FAT12 : - bc = (UINT)clst; bc += bc / 2; /* bc: byte offset of the entry */ - res = move_window(fs, fs->fatbase + (bc / SS(fs))); - if (res != FR_OK) break; - p = fs->win + bc++ % SS(fs); - *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; /* Put 1st byte */ - fs->wflag = 1; - res = move_window(fs, fs->fatbase + (bc / SS(fs))); - if (res != FR_OK) break; - p = fs->win + bc % SS(fs); - *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); /* Put 2nd byte */ - fs->wflag = 1; - break; - - case FS_FAT16 : - res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); - if (res != FR_OK) break; - st_word(fs->win + clst * 2 % SS(fs), (WORD)val); /* Simple WORD array */ - fs->wflag = 1; - break; - - case FS_FAT32 : -#if FF_FS_EXFAT - case FS_EXFAT : -#endif - res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); - if (res != FR_OK) break; - if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { - val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000); - } - st_dword(fs->win + clst * 4 % SS(fs), val); - fs->wflag = 1; - break; - } - } - return res; -} - -#endif /* !FF_FS_READONLY */ - - - - -#if FF_FS_EXFAT && !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* exFAT: Accessing FAT and Allocation Bitmap */ -/*-----------------------------------------------------------------------*/ - -/*--------------------------------------*/ -/* Find a contiguous free cluster block */ -/*--------------------------------------*/ - -static DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */ - FATFS* fs, /* Filesystem object */ - DWORD clst, /* Cluster number to scan from */ - DWORD ncl /* Number of contiguous clusters to find (1..) */ -) -{ - BYTE bm, bv; - UINT i; - DWORD val, scl, ctr; - - - clst -= 2; /* The first bit in the bitmap corresponds to cluster #2 */ - if (clst >= fs->n_fatent - 2) clst = 0; - scl = val = clst; ctr = 0; - for (;;) { - if (move_window(fs, fs->bitbase + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; - i = val / 8 % SS(fs); bm = 1 << (val % 8); - do { - do { - bv = fs->win[i] & bm; bm <<= 1; /* Get bit value */ - if (++val >= fs->n_fatent - 2) { /* Next cluster (with wrap-around) */ - val = 0; bm = 0; i = SS(fs); - } - if (bv == 0) { /* Is it a free cluster? */ - if (++ctr == ncl) return scl + 2; /* Check if run length is sufficient for required */ - } else { - scl = val; ctr = 0; /* Encountered a cluster in-use, restart to scan */ - } - if (val == clst) return 0; /* All cluster scanned? */ - } while (bm != 0); - bm = 1; - } while (++i < SS(fs)); - } -} - - -/*----------------------------------------*/ -/* Set/Clear a block of allocation bitmap */ -/*----------------------------------------*/ - -static FRESULT change_bitmap ( - FATFS* fs, /* Filesystem object */ - DWORD clst, /* Cluster number to change from */ - DWORD ncl, /* Number of clusters to be changed */ - int bv /* bit value to be set (0 or 1) */ -) -{ - BYTE bm; - UINT i; - DWORD sect; - - - clst -= 2; /* The first bit corresponds to cluster #2 */ - sect = fs->bitbase + clst / 8 / SS(fs); /* Sector address */ - i = clst / 8 % SS(fs); /* Byte offset in the sector */ - bm = 1 << (clst % 8); /* Bit mask in the byte */ - for (;;) { - if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR; - do { - do { - if (bv == (int)((fs->win[i] & bm) != 0)) return FR_INT_ERR; /* Is the bit expected value? */ - fs->win[i] ^= bm; /* Flip the bit */ - fs->wflag = 1; - if (--ncl == 0) return FR_OK; /* All bits processed? */ - } while (bm <<= 1); /* Next bit */ - bm = 1; - } while (++i < SS(fs)); /* Next byte */ - i = 0; - } -} - - -/*---------------------------------------------*/ -/* Fill the first fragment of the FAT chain */ -/*---------------------------------------------*/ - -static FRESULT fill_first_frag ( - FFOBJID* obj /* Pointer to the corresponding object */ -) -{ - FRESULT res; - DWORD cl, n; - - - if (obj->stat == 3) { /* Has the object been changed 'fragmented' in this session? */ - for (cl = obj->sclust, n = obj->n_cont; n; cl++, n--) { /* Create cluster chain on the FAT */ - res = put_fat(obj->fs, cl, cl + 1); - if (res != FR_OK) return res; - } - obj->stat = 0; /* Change status 'FAT chain is valid' */ - } - return FR_OK; -} - - -/*---------------------------------------------*/ -/* Fill the last fragment of the FAT chain */ -/*---------------------------------------------*/ - -static FRESULT fill_last_frag ( - FFOBJID* obj, /* Pointer to the corresponding object */ - DWORD lcl, /* Last cluster of the fragment */ - DWORD term /* Value to set the last FAT entry */ -) -{ - FRESULT res; - - - while (obj->n_frag > 0) { /* Create the chain of last fragment */ - res = put_fat(obj->fs, lcl - obj->n_frag + 1, (obj->n_frag > 1) ? lcl - obj->n_frag + 2 : term); - if (res != FR_OK) return res; - obj->n_frag--; - } - return FR_OK; -} - -#endif /* FF_FS_EXFAT && !FF_FS_READONLY */ - - - -#if !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* FAT handling - Remove a cluster chain */ -/*-----------------------------------------------------------------------*/ - -static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ - FFOBJID* obj, /* Corresponding object */ - DWORD clst, /* Cluster to remove a chain from */ - DWORD pclst /* Previous cluster of clst (0 if entire chain) */ -) -{ - FRESULT res = FR_OK; - DWORD nxt; - FATFS *fs = obj->fs; -#if FF_FS_EXFAT || FF_USE_TRIM - DWORD scl = clst, ecl = clst; -#endif -#if FF_USE_TRIM - DWORD rt[2]; -#endif - - if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Check if in valid range */ - - /* Mark the previous cluster 'EOC' on the FAT if it exists */ - if (pclst != 0 && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) { - res = put_fat(fs, pclst, 0xFFFFFFFF); - if (res != FR_OK) return res; - } - - /* Remove the chain */ - do { - nxt = get_fat(obj, clst); /* Get cluster status */ - if (nxt == 0) break; /* Empty cluster? */ - if (nxt == 1) return FR_INT_ERR; /* Internal error? */ - if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error? */ - if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { - res = put_fat(fs, clst, 0); /* Mark the cluster 'free' on the FAT */ - if (res != FR_OK) return res; - } - if (fs->free_clst < fs->n_fatent - 2) { /* Update FSINFO */ - fs->free_clst++; - fs->fsi_flag |= 1; - } -#if FF_FS_EXFAT || FF_USE_TRIM - if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ - ecl = nxt; - } else { /* End of contiguous cluster block */ -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - res = change_bitmap(fs, scl, ecl - scl + 1, 0); /* Mark the cluster block 'free' on the bitmap */ - if (res != FR_OK) return res; - } -#endif -#if FF_USE_TRIM - rt[0] = clst2sect(fs, scl); /* Start of data area freed */ - rt[1] = clst2sect(fs, ecl) + fs->csize - 1; /* End of data area freed */ - disk_ioctl(fs->pdrv, CTRL_TRIM, rt); /* Inform device the data in the block is no longer needed */ -#endif - scl = ecl = nxt; - } -#endif - clst = nxt; /* Next cluster */ - } while (clst < fs->n_fatent); /* Repeat while not the last link */ - -#if FF_FS_EXFAT - /* Some post processes for chain status */ - if (fs->fs_type == FS_EXFAT) { - if (pclst == 0) { /* Has the entire chain been removed? */ - obj->stat = 0; /* Change the chain status 'initial' */ - } else { - if (obj->stat == 0) { /* Is it a fragmented chain from the beginning of this session? */ - clst = obj->sclust; /* Follow the chain to check if it gets contiguous */ - while (clst != pclst) { - nxt = get_fat(obj, clst); - if (nxt < 2) return FR_INT_ERR; - if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; - if (nxt != clst + 1) break; /* Not contiguous? */ - clst++; - } - if (clst == pclst) { /* Has the chain got contiguous again? */ - obj->stat = 2; /* Change the chain status 'contiguous' */ - } - } else { - if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) { /* Was the chain fragmented in this session and got contiguous again? */ - obj->stat = 2; /* Change the chain status 'contiguous' */ - } - } - } - } -#endif - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* FAT handling - Stretch a chain or Create a new chain */ -/*-----------------------------------------------------------------------*/ - -static DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ - FFOBJID* obj, /* Corresponding object */ - DWORD clst /* Cluster# to stretch, 0:Create a new chain */ -) -{ - DWORD cs, ncl, scl; - FRESULT res; - FATFS *fs = obj->fs; - - - if (clst == 0) { /* Create a new chain */ - scl = fs->last_clst; /* Suggested cluster to start to find */ - if (scl == 0 || scl >= fs->n_fatent) scl = 1; - } - else { /* Stretch a chain */ - cs = get_fat(obj, clst); /* Check the cluster status */ - if (cs < 2) return 1; /* Test for insanity */ - if (cs == 0xFFFFFFFF) return cs; /* Test for disk error */ - if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ - scl = clst; /* Cluster to start to find */ - } - if (fs->free_clst == 0) return 0; /* No free cluster */ - -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ - ncl = find_bitmap(fs, scl, 1); /* Find a free cluster */ - if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl; /* No free cluster or hard error? */ - res = change_bitmap(fs, ncl, 1, 1); /* Mark the cluster 'in use' */ - if (res == FR_INT_ERR) return 1; - if (res == FR_DISK_ERR) return 0xFFFFFFFF; - if (clst == 0) { /* Is it a new chain? */ - obj->stat = 2; /* Set status 'contiguous' */ - } else { /* It is a stretched chain */ - if (obj->stat == 2 && ncl != scl + 1) { /* Is the chain got fragmented? */ - obj->n_cont = scl - obj->sclust; /* Set size of the contiguous part */ - obj->stat = 3; /* Change status 'just fragmented' */ - } - } - if (obj->stat != 2) { /* Is the file non-contiguous? */ - if (ncl == clst + 1) { /* Is the cluster next to previous one? */ - obj->n_frag = obj->n_frag ? obj->n_frag + 1 : 2; /* Increment size of last framgent */ - } else { /* New fragment */ - if (obj->n_frag == 0) obj->n_frag = 1; - res = fill_last_frag(obj, clst, ncl); /* Fill last fragment on the FAT and link it to new one */ - if (res == FR_OK) obj->n_frag = 1; - } - } - } else -#endif - { /* On the FAT/FAT32 volume */ - ncl = 0; - if (scl == clst) { /* Stretching an existing chain? */ - ncl = scl + 1; /* Test if next cluster is free */ - if (ncl >= fs->n_fatent) ncl = 2; - cs = get_fat(obj, ncl); /* Get next cluster status */ - if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* Test for error */ - if (cs != 0) { /* Not free? */ - cs = fs->last_clst; /* Start at suggested cluster if it is valid */ - if (cs >= 2 && cs < fs->n_fatent) scl = cs; - ncl = 0; - } - } - if (ncl == 0) { /* The new cluster cannot be contiguous and find another fragment */ - ncl = scl; /* Start cluster */ - for (;;) { - ncl++; /* Next cluster */ - if (ncl >= fs->n_fatent) { /* Check wrap-around */ - ncl = 2; - if (ncl > scl) return 0; /* No free cluster found? */ - } - cs = get_fat(obj, ncl); /* Get the cluster status */ - if (cs == 0) break; /* Found a free cluster? */ - if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* Test for error */ - if (ncl == scl) return 0; /* No free cluster found? */ - } - } - res = put_fat(fs, ncl, 0xFFFFFFFF); /* Mark the new cluster 'EOC' */ - if (res == FR_OK && clst != 0) { - res = put_fat(fs, clst, ncl); /* Link it from the previous one if needed */ - } - } - - if (res == FR_OK) { /* Update FSINFO if function succeeded. */ - fs->last_clst = ncl; - if (fs->free_clst <= fs->n_fatent - 2) fs->free_clst--; - fs->fsi_flag |= 1; - } else { - ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; /* Failed. Generate error status */ - } - - return ncl; /* Return new cluster number or error status */ -} - -#endif /* !FF_FS_READONLY */ - - - - -#if FF_USE_FASTSEEK -/*-----------------------------------------------------------------------*/ -/* FAT handling - Convert offset into cluster with link map table */ -/*-----------------------------------------------------------------------*/ - -static DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ - FIL* fp, /* Pointer to the file object */ - FSIZE_t ofs /* File offset to be converted to cluster# */ -) -{ - DWORD cl, ncl, *tbl; - FATFS *fs = fp->obj.fs; - - - tbl = fp->cltbl + 1; /* Top of CLMT */ - cl = (DWORD)(ofs / SS(fs) / fs->csize); /* Cluster order from top of the file */ - for (;;) { - ncl = *tbl++; /* Number of cluters in the fragment */ - if (ncl == 0) return 0; /* End of table? (error) */ - if (cl < ncl) break; /* In this fragment? */ - cl -= ncl; tbl++; /* Next fragment */ - } - return cl + *tbl; /* Return the cluster number */ -} - -#endif /* FF_USE_FASTSEEK */ - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Fill a cluster with zeros */ -/*-----------------------------------------------------------------------*/ - -#if !FF_FS_READONLY -static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ - FATFS *fs, /* Filesystem object */ - DWORD clst /* Directory table to clear */ -) -{ - DWORD sect; - UINT n, szb; - BYTE *ibuf; - - - if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */ - sect = clst2sect(fs, clst); /* Top of the cluster */ - fs->winsect = sect; /* Set window to top of the cluster */ - mem_set(fs->win, 0, sizeof fs->win); /* Clear window buffer */ -#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */ - /* Allocate a temporary buffer */ - for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ; - if (szb > SS(fs)) { /* Buffer allocated? */ - mem_set(ibuf, 0, szb); - szb /= SS(fs); /* Bytes -> Sectors */ - for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ - ff_memfree(ibuf); - } else -#endif - { - ibuf = fs->win; szb = 1; /* Use window buffer (many single-sector writes may take a time) */ - for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ - } - return (n == fs->csize) ? FR_OK : FR_DISK_ERR; -} -#endif /* !FF_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Set directory index */ -/*-----------------------------------------------------------------------*/ - -static FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ - DIR* dp, /* Pointer to directory object */ - DWORD ofs /* Offset of directory table */ -) -{ - DWORD csz, clst; - FATFS *fs = dp->obj.fs; - - - if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR) || ofs % SZDIRE) { /* Check range of offset and alignment */ - return FR_INT_ERR; - } - dp->dptr = ofs; /* Set current offset */ - clst = dp->obj.sclust; /* Table start cluster (0:root) */ - if (clst == 0 && fs->fs_type >= FS_FAT32) { /* Replace cluster# 0 with root cluster# */ - clst = fs->dirbase; - if (FF_FS_EXFAT) dp->obj.stat = 0; /* exFAT: Root dir has an FAT chain */ - } - - if (clst == 0) { /* Static table (root-directory on the FAT volume) */ - if (ofs / SZDIRE >= fs->n_rootdir) return FR_INT_ERR; /* Is index out of range? */ - dp->sect = fs->dirbase; - - } else { /* Dynamic table (sub-directory or root-directory on the FAT32/exFAT volume) */ - csz = (DWORD)fs->csize * SS(fs); /* Bytes per cluster */ - while (ofs >= csz) { /* Follow cluster chain */ - clst = get_fat(&dp->obj, clst); /* Get next cluster */ - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ - if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Reached to end of table or internal error */ - ofs -= csz; - } - dp->sect = clst2sect(fs, clst); - } - dp->clust = clst; /* Current cluster# */ - if (dp->sect == 0) return FR_INT_ERR; - dp->sect += ofs / SS(fs); /* Sector# of the directory entry */ - dp->dir = fs->win + (ofs % SS(fs)); /* Pointer to the entry in the win[] */ - - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Move directory table index next */ -/*-----------------------------------------------------------------------*/ - -static FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ - DIR* dp, /* Pointer to the directory object */ - int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ -) -{ - DWORD ofs, clst; - FATFS *fs = dp->obj.fs; - - - ofs = dp->dptr + SZDIRE; /* Next entry */ - if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) dp->sect = 0; /* Disable it if the offset reached the max value */ - if (dp->sect == 0) return FR_NO_FILE; /* Report EOT if it has been disabled */ - - if (ofs % SS(fs) == 0) { /* Sector changed? */ - dp->sect++; /* Next sector */ - - if (dp->clust == 0) { /* Static table */ - if (ofs / SZDIRE >= fs->n_rootdir) { /* Report EOT if it reached end of static table */ - dp->sect = 0; return FR_NO_FILE; - } - } - else { /* Dynamic table */ - if ((ofs / SS(fs) & (fs->csize - 1)) == 0) { /* Cluster changed? */ - clst = get_fat(&dp->obj, dp->clust); /* Get next cluster */ - if (clst <= 1) return FR_INT_ERR; /* Internal error */ - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ - if (clst >= fs->n_fatent) { /* It reached end of dynamic table */ -#if !FF_FS_READONLY - if (!stretch) { /* If no stretch, report EOT */ - dp->sect = 0; return FR_NO_FILE; - } - clst = create_chain(&dp->obj, dp->clust); /* Allocate a cluster */ - if (clst == 0) return FR_DENIED; /* No free cluster */ - if (clst == 1) return FR_INT_ERR; /* Internal error */ - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ - if (dir_clear(fs, clst) != FR_OK) return FR_DISK_ERR; /* Clean up the stretched table */ - if (FF_FS_EXFAT) dp->obj.stat |= 4; /* exFAT: The directory has been stretched */ -#else - if (!stretch) dp->sect = 0; /* (this line is to suppress compiler warning) */ - dp->sect = 0; return FR_NO_FILE; /* Report EOT */ -#endif - } - dp->clust = clst; /* Initialize data for new cluster */ - dp->sect = clst2sect(fs, clst); - } - } - } - dp->dptr = ofs; /* Current entry */ - dp->dir = fs->win + ofs % SS(fs); /* Pointer to the entry in the win[] */ - - return FR_OK; -} - - - - -#if !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Directory handling - Reserve a block of directory entries */ -/*-----------------------------------------------------------------------*/ - -static FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ - DIR* dp, /* Pointer to the directory object */ - UINT nent /* Number of contiguous entries to allocate */ -) -{ - FRESULT res; - UINT n; - FATFS *fs = dp->obj.fs; - - - res = dir_sdi(dp, 0); - if (res == FR_OK) { - n = 0; - do { - res = move_window(fs, dp->sect); - if (res != FR_OK) break; -#if FF_FS_EXFAT - if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) { -#else - if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) { -#endif - if (++n == nent) break; /* A block of contiguous free entries is found */ - } else { - n = 0; /* Not a blank entry. Restart to search */ - } - res = dir_next(dp, 1); - } while (res == FR_OK); /* Next entry with table stretch enabled */ - } - - if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */ - return res; -} - -#endif /* !FF_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* FAT: Directory handling - Load/Store start cluster number */ -/*-----------------------------------------------------------------------*/ - -static DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ - FATFS* fs, /* Pointer to the fs object */ - const BYTE* dir /* Pointer to the key entry */ -) -{ - DWORD cl; - - cl = ld_word(dir + DIR_FstClusLO); - if (fs->fs_type == FS_FAT32) { - cl |= (DWORD)ld_word(dir + DIR_FstClusHI) << 16; - } - - return cl; -} - - -#if !FF_FS_READONLY -static void st_clust ( - FATFS* fs, /* Pointer to the fs object */ - BYTE* dir, /* Pointer to the key entry */ - DWORD cl /* Value to be set */ -) -{ - st_word(dir + DIR_FstClusLO, (WORD)cl); - if (fs->fs_type == FS_FAT32) { - st_word(dir + DIR_FstClusHI, (WORD)(cl >> 16)); - } -} -#endif - - - -#if FF_USE_LFN -/*--------------------------------------------------------*/ -/* FAT-LFN: Compare a part of file name with an LFN entry */ -/*--------------------------------------------------------*/ - -static int cmp_lfn ( /* 1:matched, 0:not matched */ - const WCHAR* lfnbuf, /* Pointer to the LFN working buffer to be compared */ - BYTE* dir /* Pointer to the directory entry containing the part of LFN */ -) -{ - UINT i, s; - WCHAR wc, uc; - - - if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO */ - - i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ - - for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */ - uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ - if (wc != 0) { - if (i >= FF_MAX_LFN + 1 || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */ - return 0; /* Not matched */ - } - wc = uc; - } else { - if (uc != 0xFFFF) return 0; /* Check filler */ - } - } - - if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) return 0; /* Last segment matched but different length */ - - return 1; /* The part of LFN matched */ -} - - -#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT -/*-----------------------------------------------------*/ -/* FAT-LFN: Pick a part of file name from an LFN entry */ -/*-----------------------------------------------------*/ - -static int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ - WCHAR* lfnbuf, /* Pointer to the LFN working buffer */ - BYTE* dir /* Pointer to the LFN entry */ -) -{ - UINT i, s; - WCHAR wc, uc; - - - if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO is 0 */ - - i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13; /* Offset in the LFN buffer */ - - for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */ - uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ - if (wc != 0) { - if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */ - lfnbuf[i++] = wc = uc; /* Store it */ - } else { - if (uc != 0xFFFF) return 0; /* Check filler */ - } - } - - if (dir[LDIR_Ord] & LLEF && wc != 0) { /* Put terminator if it is the last LFN part and not terminated */ - if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */ - lfnbuf[i] = 0; - } - - return 1; /* The part of LFN is valid */ -} -#endif - - -#if !FF_FS_READONLY -/*-----------------------------------------*/ -/* FAT-LFN: Create an entry of LFN entries */ -/*-----------------------------------------*/ - -static void put_lfn ( - const WCHAR* lfn, /* Pointer to the LFN */ - BYTE* dir, /* Pointer to the LFN entry to be created */ - BYTE ord, /* LFN order (1-20) */ - BYTE sum /* Checksum of the corresponding SFN */ -) -{ - UINT i, s; - WCHAR wc; - - - dir[LDIR_Chksum] = sum; /* Set checksum */ - dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ - dir[LDIR_Type] = 0; - st_word(dir + LDIR_FstClusLO, 0); - - i = (ord - 1) * 13; /* Get offset in the LFN working buffer */ - s = wc = 0; - do { - if (wc != 0xFFFF) wc = lfn[i++]; /* Get an effective character */ - st_word(dir + LfnOfs[s], wc); /* Put it */ - if (wc == 0) wc = 0xFFFF; /* Padding characters for left locations */ - } while (++s < 13); - if (wc == 0xFFFF || !lfn[i]) ord |= LLEF; /* Last LFN part is the start of LFN sequence */ - dir[LDIR_Ord] = ord; /* Set the LFN order */ -} - -#endif /* !FF_FS_READONLY */ -#endif /* FF_USE_LFN */ - - - -#if FF_USE_LFN && !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* FAT-LFN: Create a Numbered SFN */ -/*-----------------------------------------------------------------------*/ - -static void gen_numname ( - BYTE* dst, /* Pointer to the buffer to store numbered SFN */ - const BYTE* src, /* Pointer to SFN */ - const WCHAR* lfn, /* Pointer to LFN */ - UINT seq /* Sequence number */ -) -{ - BYTE ns[8], c; - UINT i, j; - WCHAR wc; - DWORD sr; - - - mem_cpy(dst, src, 11); - - if (seq > 5) { /* In case of many collisions, generate a hash number instead of sequential number */ - sr = seq; - while (*lfn) { /* Create a CRC as hash value */ - wc = *lfn++; - for (i = 0; i < 16; i++) { - sr = (sr << 1) + (wc & 1); - wc >>= 1; - if (sr & 0x10000) sr ^= 0x11021; - } - } - seq = (UINT)sr; - } - - /* itoa (hexdecimal) */ - i = 7; - do { - c = (BYTE)((seq % 16) + '0'); - if (c > '9') c += 7; - ns[i--] = c; - seq /= 16; - } while (seq); - ns[i] = '~'; - - /* Append the number to the SFN body */ - for (j = 0; j < i && dst[j] != ' '; j++) { - if (dbc_1st(dst[j])) { - if (j == i - 1) break; - j++; - } - } - do { - dst[j++] = (i < 8) ? ns[i++] : ' '; - } while (j < 8); -} -#endif /* FF_USE_LFN && !FF_FS_READONLY */ - - - -#if FF_USE_LFN -/*-----------------------------------------------------------------------*/ -/* FAT-LFN: Calculate checksum of an SFN entry */ -/*-----------------------------------------------------------------------*/ - -static BYTE sum_sfn ( - const BYTE* dir /* Pointer to the SFN entry */ -) -{ - BYTE sum = 0; - UINT n = 11; - - do { - sum = (sum >> 1) + (sum << 7) + *dir++; - } while (--n); - return sum; -} - -#endif /* FF_USE_LFN */ - - - -#if FF_FS_EXFAT -/*-----------------------------------------------------------------------*/ -/* exFAT: Checksum */ -/*-----------------------------------------------------------------------*/ - -static WORD xdir_sum ( /* Get checksum of the directoly entry block */ - const BYTE* dir /* Directory entry block to be calculated */ -) -{ - UINT i, szblk; - WORD sum; - - - szblk = (dir[XDIR_NumSec] + 1) * SZDIRE; /* Number of bytes of the entry block */ - for (i = sum = 0; i < szblk; i++) { - if (i == XDIR_SetSum) { /* Skip 2-byte sum field */ - i++; - } else { - sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + dir[i]; - } - } - return sum; -} - - - -static WORD xname_sum ( /* Get check sum (to be used as hash) of the file name */ - const WCHAR* name /* File name to be calculated */ -) -{ - WCHAR chr; - WORD sum = 0; - - - while ((chr = *name++) != 0) { - chr = (WCHAR)ff_wtoupper(chr); /* File name needs to be up-case converted */ - sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr & 0xFF); - sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr >> 8); - } - return sum; -} - - -#if !FF_FS_READONLY && FF_USE_MKFS -static DWORD xsum32 ( /* Returns 32-bit checksum */ - BYTE dat, /* Byte to be calculated (byte-by-byte processing) */ - DWORD sum /* Previous sum value */ -) -{ - sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat; - return sum; -} -#endif - - -#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 -/*------------------------------------------------------*/ -/* exFAT: Get object information from a directory block */ -/*------------------------------------------------------*/ - -static void get_xfileinfo ( - BYTE* dirb, /* Pointer to the direcotry entry block 85+C0+C1s */ - FILINFO* fno /* Buffer to store the extracted file information */ -) -{ - WCHAR wc, hs; - UINT di, si, nc; - - /* Get file name from the entry block */ - si = SZDIRE * 2; /* 1st C1 entry */ - nc = 0; hs = 0; di = 0; - while (nc < dirb[XDIR_NumName]) { - if (si >= MAXDIRB(FF_MAX_LFN)) { di = 0; break; } /* Truncated directory block? */ - if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */ - wc = ld_word(dirb + si); si += 2; nc++; /* Get a character */ - if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ - hs = wc; continue; /* Get low surrogate */ - } - wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in API encoding */ - if (wc == 0) { di = 0; break; } /* Buffer overflow or wrong encoding? */ - di += wc; - hs = 0; - } - if (hs != 0) di = 0; /* Broken surrogate pair? */ - if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object name? */ - fno->fname[di] = 0; /* Terminate the name */ - fno->altname[0] = 0; /* exFAT does not support SFN */ - - fno->fattrib = dirb[XDIR_Attr]; /* Attribute */ - fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize); /* Size */ - fno->ftime = ld_word(dirb + XDIR_ModTime + 0); /* Time */ - fno->fdate = ld_word(dirb + XDIR_ModTime + 2); /* Date */ -} - -#endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */ - - -/*-----------------------------------*/ -/* exFAT: Get a directry entry block */ -/*-----------------------------------*/ - -static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ - DIR* dp /* Reading direcotry object pointing top of the entry block to load */ -) -{ - FRESULT res; - UINT i, sz_ent; - BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */ - - - /* Load file-directory entry */ - res = move_window(dp->obj.fs, dp->sect); - if (res != FR_OK) return res; - if (dp->dir[XDIR_Type] != ET_FILEDIR) return FR_INT_ERR; /* Invalid order */ - mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE); - sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE; - if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR; - - /* Load stream-extension entry */ - res = dir_next(dp, 0); - if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */ - if (res != FR_OK) return res; - res = move_window(dp->obj.fs, dp->sect); - if (res != FR_OK) return res; - if (dp->dir[XDIR_Type] != ET_STREAM) return FR_INT_ERR; /* Invalid order */ - mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE); - if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR; - - /* Load file-name entries */ - i = 2 * SZDIRE; /* Name offset to load */ - do { - res = dir_next(dp, 0); - if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */ - if (res != FR_OK) return res; - res = move_window(dp->obj.fs, dp->sect); - if (res != FR_OK) return res; - if (dp->dir[XDIR_Type] != ET_FILENAME) return FR_INT_ERR; /* Invalid order */ - if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE); - } while ((i += SZDIRE) < sz_ent); - - /* Sanity check (do it for only accessible object) */ - if (i <= MAXDIRB(FF_MAX_LFN)) { - if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum)) return FR_INT_ERR; - } - return FR_OK; -} - - -/*------------------------------------------------------------------*/ -/* exFAT: Initialize object allocation info with loaded entry block */ -/*------------------------------------------------------------------*/ - -static void init_alloc_info ( - FATFS* fs, /* Filesystem object */ - FFOBJID* obj /* Object allocation information to be initialized */ -) -{ - obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Start cluster */ - obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize); /* Size */ - obj->stat = fs->dirbuf[XDIR_GenFlags] & 2; /* Allocation status */ - obj->n_frag = 0; /* No last fragment info */ -} - - - -#if !FF_FS_READONLY || FF_FS_RPATH != 0 -/*------------------------------------------------*/ -/* exFAT: Load the object's directory entry block */ -/*------------------------------------------------*/ - -static FRESULT load_obj_xdir ( - DIR* dp, /* Blank directory object to be used to access containing direcotry */ - const FFOBJID* obj /* Object with its containing directory information */ -) -{ - FRESULT res; - - /* Open object containing directory */ - dp->obj.fs = obj->fs; - dp->obj.sclust = obj->c_scl; - dp->obj.stat = (BYTE)obj->c_size; - dp->obj.objsize = obj->c_size & 0xFFFFFF00; - dp->obj.n_frag = 0; - dp->blk_ofs = obj->c_ofs; - - res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */ - if (res == FR_OK) { - res = load_xdir(dp); /* Load the object's entry block */ - } - return res; -} -#endif - - -#if !FF_FS_READONLY -/*----------------------------------------*/ -/* exFAT: Store the directory entry block */ -/*----------------------------------------*/ - -static FRESULT store_xdir ( - DIR* dp /* Pointer to the direcotry object */ -) -{ - FRESULT res; - UINT nent; - BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the direcotry entry block 85+C0+C1s */ - - /* Create set sum */ - st_word(dirb + XDIR_SetSum, xdir_sum(dirb)); - nent = dirb[XDIR_NumSec] + 1; - - /* Store the direcotry entry block to the directory */ - res = dir_sdi(dp, dp->blk_ofs); - while (res == FR_OK) { - res = move_window(dp->obj.fs, dp->sect); - if (res != FR_OK) break; - mem_cpy(dp->dir, dirb, SZDIRE); - dp->obj.fs->wflag = 1; - if (--nent == 0) break; - dirb += SZDIRE; - res = dir_next(dp, 0); - } - return (res == FR_OK || res == FR_DISK_ERR) ? res : FR_INT_ERR; -} - - - -/*-------------------------------------------*/ -/* exFAT: Create a new directory enrty block */ -/*-------------------------------------------*/ - -static void create_xdir ( - BYTE* dirb, /* Pointer to the direcotry entry block buffer */ - const WCHAR* lfn /* Pointer to the object name */ -) -{ - UINT i; - BYTE nc1, nlen; - WCHAR wc; - - - /* Create file-directory and stream-extension entry */ - mem_set(dirb, 0, 2 * SZDIRE); - dirb[0 * SZDIRE + XDIR_Type] = ET_FILEDIR; - dirb[1 * SZDIRE + XDIR_Type] = ET_STREAM; - - /* Create file-name entries */ - i = SZDIRE * 2; /* Top of file_name entries */ - nlen = nc1 = 0; wc = 1; - do { - dirb[i++] = ET_FILENAME; dirb[i++] = 0; - do { /* Fill name field */ - if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */ - st_word(dirb + i, wc); /* Store it */ - i += 2; - } while (i % SZDIRE != 0); - nc1++; - } while (lfn[nlen]); /* Fill next entry if any char follows */ - - dirb[XDIR_NumName] = nlen; /* Set name length */ - dirb[XDIR_NumSec] = 1 + nc1; /* Set secondary count (C0 + C1s) */ - st_word(dirb + XDIR_NameHash, xname_sum(lfn)); /* Set name hash */ -} - -#endif /* !FF_FS_READONLY */ -#endif /* FF_FS_EXFAT */ - - - -#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT -/*-----------------------------------------------------------------------*/ -/* Read an object from the directory */ -/*-----------------------------------------------------------------------*/ - -#define DIR_READ_FILE(dp) dir_read(dp, 0) -#define DIR_READ_LABEL(dp) dir_read(dp, 1) - -static FRESULT dir_read ( - DIR* dp, /* Pointer to the directory object */ - int vol /* Filtered by 0:file/directory or 1:volume label */ -) -{ - FRESULT res = FR_NO_FILE; - FATFS *fs = dp->obj.fs; - BYTE attr, b; -#if FF_USE_LFN - BYTE ord = 0xFF, sum = 0xFF; -#endif - - while (dp->sect) { - res = move_window(fs, dp->sect); - if (res != FR_OK) break; - b = dp->dir[DIR_Name]; /* Test for the entry type */ - if (b == 0) { - res = FR_NO_FILE; break; /* Reached to end of the directory */ - } -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ - if (FF_USE_LABEL && vol) { - if (b == ET_VLABEL) break; /* Volume label entry? */ - } else { - if (b == ET_FILEDIR) { /* Start of the file entry block? */ - dp->blk_ofs = dp->dptr; /* Get location of the block */ - res = load_xdir(dp); /* Load the entry block */ - if (res == FR_OK) { - dp->obj.attr = fs->dirbuf[XDIR_Attr] & AM_MASK; /* Get attribute */ - } - break; - } - } - } else -#endif - { /* On the FAT/FAT32 volume */ - dp->obj.attr = attr = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */ -#if FF_USE_LFN /* LFN configuration */ - if (b == DDEM || b == '.' || (int)((attr & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */ - ord = 0xFF; - } else { - if (attr == AM_LFN) { /* An LFN entry is found */ - if (b & LLEF) { /* Is it start of an LFN sequence? */ - sum = dp->dir[LDIR_Chksum]; - b &= (BYTE)~LLEF; ord = b; - dp->blk_ofs = dp->dptr; - } - /* Check LFN validity and capture it */ - ord = (b == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; - } else { /* An SFN entry is found */ - if (ord != 0 || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */ - dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */ - } - break; - } - } -#else /* Non LFN configuration */ - if (b != DDEM && b != '.' && attr != AM_LFN && (int)((attr & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */ - break; - } -#endif - } - res = dir_next(dp, 0); /* Next entry */ - if (res != FR_OK) break; - } - - if (res != FR_OK) dp->sect = 0; /* Terminate the read operation on error or EOT */ - return res; -} - -#endif /* FF_FS_MINIMIZE <= 1 || FF_USE_LABEL || FF_FS_RPATH >= 2 */ - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Find an object in the directory */ -/*-----------------------------------------------------------------------*/ - -static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ - DIR* dp /* Pointer to the directory object with the file name */ -) -{ - FRESULT res; - FATFS *fs = dp->obj.fs; - BYTE c; -#if FF_USE_LFN - BYTE a, ord, sum; -#endif - - res = dir_sdi(dp, 0); /* Rewind directory object */ - if (res != FR_OK) return res; -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ - BYTE nc; - UINT di, ni; - WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */ - - while ((res = DIR_READ_FILE(dp)) == FR_OK) { /* Read an item */ -#if FF_MAX_LFN < 255 - if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */ -#endif - if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue; /* Skip comparison if hash mismatched */ - for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) { /* Compare the name */ - if ((di % SZDIRE) == 0) di += 2; - if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break; - } - if (nc == 0 && !fs->lfnbuf[ni]) break; /* Name matched? */ - } - return res; - } -#endif - /* On the FAT/FAT32 volume */ -#if FF_USE_LFN - ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ -#endif - do { - res = move_window(fs, dp->sect); - if (res != FR_OK) break; - c = dp->dir[DIR_Name]; - if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ -#if FF_USE_LFN /* LFN configuration */ - dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; - if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ - ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ - } else { - if (a == AM_LFN) { /* An LFN entry is found */ - if (!(dp->fn[NSFLAG] & NS_NOLFN)) { - if (c & LLEF) { /* Is it start of LFN sequence? */ - sum = dp->dir[LDIR_Chksum]; - c &= (BYTE)~LLEF; ord = c; /* LFN start order */ - dp->blk_ofs = dp->dptr; /* Start offset of LFN */ - } - /* Check validity of the LFN entry and compare it with given name */ - ord = (c == ord && sum == dp->dir[LDIR_Chksum] && cmp_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; - } - } else { /* An SFN entry is found */ - if (ord == 0 && sum == sum_sfn(dp->dir)) break; /* LFN matched? */ - if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* SFN matched? */ - ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ - } - } -#else /* Non LFN configuration */ - dp->obj.attr = dp->dir[DIR_Attr] & AM_MASK; - if (!(dp->dir[DIR_Attr] & AM_VOL) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* Is it a valid entry? */ -#endif - res = dir_next(dp, 0); /* Next entry */ - } while (res == FR_OK); - - return res; -} - - - - -#if !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Register an object to the directory */ -/*-----------------------------------------------------------------------*/ - -static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */ - DIR* dp /* Target directory with object name to be created */ -) -{ - FRESULT res; - FATFS *fs = dp->obj.fs; -#if FF_USE_LFN /* LFN configuration */ - UINT n, nlen, nent; - BYTE sn[12], sum; - - - if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME; /* Check name validity */ - for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */ - -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ - nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */ - res = dir_alloc(dp, nent); /* Allocate directory entries */ - if (res != FR_OK) return res; - dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */ - - if (dp->obj.stat & 4) { /* Has the directory been stretched by new allocation? */ - dp->obj.stat &= ~4; - res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */ - if (res != FR_OK) return res; - res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */ - if (res != FR_OK) return res; - if (dp->obj.sclust != 0) { /* Is it a sub-directory? */ - DIR dj; - - res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */ - if (res != FR_OK) return res; - dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */ - st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */ - st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize); - fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1; - res = store_xdir(&dj); /* Store the object status */ - if (res != FR_OK) return res; - } - } - - create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */ - return FR_OK; - } -#endif - /* On the FAT/FAT32 volume */ - mem_cpy(sn, dp->fn, 12); - if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ - dp->fn[NSFLAG] = NS_NOLFN; /* Find only SFN */ - for (n = 1; n < 100; n++) { - gen_numname(dp->fn, sn, fs->lfnbuf, n); /* Generate a numbered name */ - res = dir_find(dp); /* Check if the name collides with existing SFN */ - if (res != FR_OK) break; - } - if (n == 100) return FR_DENIED; /* Abort if too many collisions */ - if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ - dp->fn[NSFLAG] = sn[NSFLAG]; - } - - /* Create an SFN with/without LFNs. */ - nent = (sn[NSFLAG] & NS_LFN) ? (nlen + 12) / 13 + 1 : 1; /* Number of entries to allocate */ - res = dir_alloc(dp, nent); /* Allocate entries */ - if (res == FR_OK && --nent) { /* Set LFN entry if needed */ - res = dir_sdi(dp, dp->dptr - nent * SZDIRE); - if (res == FR_OK) { - sum = sum_sfn(dp->fn); /* Checksum value of the SFN tied to the LFN */ - do { /* Store LFN entries in bottom first */ - res = move_window(fs, dp->sect); - if (res != FR_OK) break; - put_lfn(fs->lfnbuf, dp->dir, (BYTE)nent, sum); - fs->wflag = 1; - res = dir_next(dp, 0); /* Next entry */ - } while (res == FR_OK && --nent); - } - } - -#else /* Non LFN configuration */ - res = dir_alloc(dp, 1); /* Allocate an entry for SFN */ - -#endif - - /* Set SFN entry */ - if (res == FR_OK) { - res = move_window(fs, dp->sect); - if (res == FR_OK) { - mem_set(dp->dir, 0, SZDIRE); /* Clean the entry */ - mem_cpy(dp->dir + DIR_Name, dp->fn, 11); /* Put SFN */ -#if FF_USE_LFN - dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */ -#endif - fs->wflag = 1; - } - } - - return res; -} - -#endif /* !FF_FS_READONLY */ - - - -#if !FF_FS_READONLY && FF_FS_MINIMIZE == 0 -/*-----------------------------------------------------------------------*/ -/* Remove an object from the directory */ -/*-----------------------------------------------------------------------*/ - -static FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ - DIR* dp /* Directory object pointing the entry to be removed */ -) -{ - FRESULT res; - FATFS *fs = dp->obj.fs; -#if FF_USE_LFN /* LFN configuration */ - DWORD last = dp->dptr; - - res = (dp->blk_ofs == 0xFFFFFFFF) ? FR_OK : dir_sdi(dp, dp->blk_ofs); /* Goto top of the entry block if LFN is exist */ - if (res == FR_OK) { - do { - res = move_window(fs, dp->sect); - if (res != FR_OK) break; - if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ - dp->dir[XDIR_Type] &= 0x7F; /* Clear the entry InUse flag. */ - } else { /* On the FAT/FAT32 volume */ - dp->dir[DIR_Name] = DDEM; /* Mark the entry 'deleted'. */ - } - fs->wflag = 1; - if (dp->dptr >= last) break; /* If reached last entry then all entries of the object has been deleted. */ - res = dir_next(dp, 0); /* Next entry */ - } while (res == FR_OK); - if (res == FR_NO_FILE) res = FR_INT_ERR; - } -#else /* Non LFN configuration */ - - res = move_window(fs, dp->sect); - if (res == FR_OK) { - dp->dir[DIR_Name] = DDEM; /* Mark the entry 'deleted'.*/ - fs->wflag = 1; - } -#endif - - return res; -} - -#endif /* !FF_FS_READONLY && FF_FS_MINIMIZE == 0 */ - - - -#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 -/*-----------------------------------------------------------------------*/ -/* Get file information from directory entry */ -/*-----------------------------------------------------------------------*/ - -static void get_fileinfo ( - DIR* dp, /* Pointer to the directory object */ - FILINFO* fno /* Pointer to the file information to be filled */ -) -{ - UINT si, di; -#if FF_USE_LFN - BYTE lcf; - WCHAR wc, hs; - FATFS *fs = dp->obj.fs; -#else - TCHAR c; -#endif - - - fno->fname[0] = 0; /* Invaidate file info */ - if (dp->sect == 0) return; /* Exit if read pointer has reached end of directory */ - -#if FF_USE_LFN /* LFN configuration */ -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ - get_xfileinfo(fs->dirbuf, fno); - return; - } else -#endif - { /* On the FAT/FAT32 volume */ - if (dp->blk_ofs != 0xFFFFFFFF) { /* Get LFN if available */ - si = di = hs = 0; - while (fs->lfnbuf[si] != 0) { - wc = fs->lfnbuf[si++]; /* Get an LFN character (UTF-16) */ - if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ - hs = wc; continue; /* Get low surrogate */ - } - wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in UTF-16 or UTF-8 encoding */ - if (wc == 0) { di = 0; break; } /* Invalid char or buffer overflow? */ - di += wc; - hs = 0; - } - if (hs != 0) di = 0; /* Broken surrogate pair? */ - fno->fname[di] = 0; /* Terminate the LFN (null string means LFN is invalid) */ - } - } - - si = di = 0; - while (si < 11) { /* Get SFN from SFN entry */ - wc = dp->dir[si++]; /* Get a char */ - if (wc == ' ') continue; /* Skip padding spaces */ - if (wc == RDDEM) wc = DDEM; /* Restore replaced DDEM character */ - if (si == 9 && di < FF_SFN_BUF) fno->altname[di++] = '.'; /* Insert a . if extension is exist */ -#if FF_LFN_UNICODE >= 1 /* Unicode output */ - if (dbc_1st((BYTE)wc) && si != 8 && si != 11 && dbc_2nd(dp->dir[si])) { /* Make a DBC if needed */ - wc = wc << 8 | dp->dir[si++]; - } - wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM -> Unicode */ - if (wc == 0) { di = 0; break; } /* Wrong char in the current code page? */ - wc = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di); /* Store it in Unicode */ - if (wc == 0) { di = 0; break; } /* Buffer overflow? */ - di += wc; -#else /* ANSI/OEM output */ - fno->altname[di++] = (TCHAR)wc; /* Store it without any conversion */ -#endif - } - fno->altname[di] = 0; /* Terminate the SFN (null string means SFN is invalid) */ - - if (fno->fname[0] == 0) { /* If LFN is invalid, altname[] needs to be copied to fname[] */ - if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */ - fno->fname[di++] = '?'; - } else { - for (si = di = 0, lcf = NS_BODY; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */ - wc = (WCHAR)fno->altname[si]; - if (wc == '.') lcf = NS_EXT; - if (IsUpper(wc) && (dp->dir[DIR_NTres] & lcf)) wc += 0x20; - fno->fname[di] = (TCHAR)wc; - } - } - fno->fname[di] = 0; /* Terminate the LFN */ - if (!dp->dir[DIR_NTres]) fno->altname[0] = 0; /* Altname is not needed if neither LFN nor case info is exist. */ - } - -#else /* Non-LFN configuration */ - si = di = 0; - while (si < 11) { /* Copy name body and extension */ - c = (TCHAR)dp->dir[si++]; - if (c == ' ') continue; /* Skip padding spaces */ - if (c == RDDEM) c = DDEM; /* Restore replaced DDEM character */ - if (si == 9) fno->fname[di++] = '.';/* Insert a . if extension is exist */ - fno->fname[di++] = c; - } - fno->fname[di] = 0; -#endif - - fno->fattrib = dp->dir[DIR_Attr]; /* Attribute */ - fno->fsize = ld_dword(dp->dir + DIR_FileSize); /* Size */ - fno->ftime = ld_word(dp->dir + DIR_ModTime + 0); /* Time */ - fno->fdate = ld_word(dp->dir + DIR_ModTime + 2); /* Date */ -} - -#endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */ - - - -#if FF_USE_FIND && FF_FS_MINIMIZE <= 1 -/*-----------------------------------------------------------------------*/ -/* Pattern matching */ -/*-----------------------------------------------------------------------*/ - -static DWORD get_achar ( /* Get a character and advances ptr */ - const TCHAR** ptr /* Pointer to pointer to the ANSI/OEM or Unicode string */ -) -{ - DWORD chr; - - -#if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode input */ - chr = tchar2uni(ptr); - if (chr == 0xFFFFFFFF) chr = 0; /* Wrong UTF encoding is recognized as end of the string */ - chr = ff_wtoupper(chr); - -#else /* ANSI/OEM input */ - chr = (BYTE)*(*ptr)++; /* Get a byte */ - if (IsLower(chr)) chr -= 0x20; /* To upper ASCII char */ -#if FF_CODE_PAGE == 0 - if (ExCvt && chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ -#elif FF_CODE_PAGE < 900 - if (chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ -#endif -#if FF_CODE_PAGE == 0 || FF_CODE_PAGE >= 900 - if (dbc_1st((BYTE)chr)) { /* Get DBC 2nd byte if needed */ - chr = dbc_2nd((BYTE)**ptr) ? chr << 8 | (BYTE)*(*ptr)++ : 0; - } -#endif - -#endif - return chr; -} - - -static int pattern_matching ( /* 0:not matched, 1:matched */ - const TCHAR* pat, /* Matching pattern */ - const TCHAR* nam, /* String to be tested */ - int skip, /* Number of pre-skip chars (number of ?s) */ - int inf /* Infinite search (* specified) */ -) -{ - const TCHAR *pp, *np; - DWORD pc, nc; - int nm, nx; - - - while (skip--) { /* Pre-skip name chars */ - if (!get_achar(&nam)) return 0; /* Branch mismatched if less name chars */ - } - if (*pat == 0 && inf) return 1; /* (short circuit) */ - - do { - pp = pat; np = nam; /* Top of pattern and name to match */ - for (;;) { - if (*pp == '?' || *pp == '*') { /* Wildcard? */ - nm = nx = 0; - do { /* Analyze the wildcard block */ - if (*pp++ == '?') nm++; else nx = 1; - } while (*pp == '?' || *pp == '*'); - if (pattern_matching(pp, np, nm, nx)) return 1; /* Test new branch (recurs upto number of wildcard blocks in the pattern) */ - nc = *np; break; /* Branch mismatched */ - } - pc = get_achar(&pp); /* Get a pattern char */ - nc = get_achar(&np); /* Get a name char */ - if (pc != nc) break; /* Branch mismatched? */ - if (pc == 0) return 1; /* Branch matched? (matched at end of both strings) */ - } - get_achar(&nam); /* nam++ */ - } while (inf && nc); /* Retry until end of name if infinite search is specified */ - - return 0; -} - -#endif /* FF_USE_FIND && FF_FS_MINIMIZE <= 1 */ - - - -/*-----------------------------------------------------------------------*/ -/* Pick a top segment and create the object name in directory form */ -/*-----------------------------------------------------------------------*/ - -static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ - DIR* dp, /* Pointer to the directory object */ - const TCHAR** path /* Pointer to pointer to the segment in the path string */ -) -{ -#if FF_USE_LFN /* LFN configuration */ - BYTE b, cf; - WCHAR wc, *lfn; - DWORD uc; - UINT i, ni, si, di; - const TCHAR *p; - - - /* Create LFN into LFN working buffer */ - p = *path; lfn = dp->obj.fs->lfnbuf; di = 0; - for (;;) { - uc = tchar2uni(&p); /* Get a character */ - if (uc == 0xFFFFFFFF) return FR_INVALID_NAME; /* Invalid code or UTF decode error */ - if (uc >= 0x10000) lfn[di++] = (WCHAR)(uc >> 16); /* Store high surrogate if needed */ - wc = (WCHAR)uc; - if (wc < ' ' || wc == '/' || wc == '\\') break; /* Break if end of the path or a separator is found */ - if (wc < 0x80 && chk_chr("\"*:<>\?|\x7F", wc)) return FR_INVALID_NAME; /* Reject illegal characters for LFN */ - if (di >= FF_MAX_LFN) return FR_INVALID_NAME; /* Reject too long name */ - lfn[di++] = wc; /* Store the Unicode character */ - } - while (*p == '/' || *p == '\\') p++; /* Skip duplicated separators if exist */ - *path = p; /* Return pointer to the next segment */ - cf = (wc < ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ - -#if FF_FS_RPATH != 0 - if ((di == 1 && lfn[di - 1] == '.') || - (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { /* Is this segment a dot name? */ - lfn[di] = 0; - for (i = 0; i < 11; i++) { /* Create dot name for SFN entry */ - dp->fn[i] = (i < di) ? '.' : ' '; - } - dp->fn[i] = cf | NS_DOT; /* This is a dot entry */ - return FR_OK; - } -#endif - while (di) { /* Snip off trailing spaces and dots if exist */ - wc = lfn[di - 1]; - if (wc != ' ' && wc != '.') break; - di--; - } - lfn[di] = 0; /* LFN is created into the working buffer */ - if (di == 0) return FR_INVALID_NAME; /* Reject null name */ - - /* Create SFN in directory form */ - for (si = 0; lfn[si] == ' '; si++) ; /* Remove leading spaces */ - if (si > 0 || lfn[si] == '.') cf |= NS_LOSS | NS_LFN; /* Is there any leading space or dot? */ - while (di > 0 && lfn[di - 1] != '.') di--; /* Find last dot (di<=si: no extension) */ - - mem_set(dp->fn, ' ', 11); - i = b = 0; ni = 8; - for (;;) { - wc = lfn[si++]; /* Get an LFN character */ - if (wc == 0) break; /* Break on end of the LFN */ - if (wc == ' ' || (wc == '.' && si != di)) { /* Remove embedded spaces and dots */ - cf |= NS_LOSS | NS_LFN; - continue; - } - - if (i >= ni || si == di) { /* End of field? */ - if (ni == 11) { /* Name extension overflow? */ - cf |= NS_LOSS | NS_LFN; - break; - } - if (si != di) cf |= NS_LOSS | NS_LFN; /* Name body overflow? */ - if (si > di) break; /* No name extension? */ - si = di; i = 8; ni = 11; b <<= 2; /* Enter name extension */ - continue; - } - - if (wc >= 0x80) { /* Is this a non-ASCII character? */ - cf |= NS_LFN; /* LFN entry needs to be created */ -#if FF_CODE_PAGE == 0 - if (ExCvt) { /* At SBCS */ - wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */ - if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */ - } else { /* At DBCS */ - wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Upper convert ==> ANSI/OEM code */ - } -#elif FF_CODE_PAGE < 900 /* SBCS cfg */ - wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */ - if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */ -#else /* DBCS cfg */ - wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Upper convert ==> ANSI/OEM code */ -#endif - } - - if (wc >= 0x100) { /* Is this a DBC? */ - if (i >= ni - 1) { /* Field overflow? */ - cf |= NS_LOSS | NS_LFN; - i = ni; continue; /* Next field */ - } - dp->fn[i++] = (BYTE)(wc >> 8); /* Put 1st byte */ - } else { /* SBC */ - if (wc == 0 || chk_chr("+,;=[]", wc)) { /* Replace illegal characters for SFN if needed */ - wc = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ - } else { - if (IsUpper(wc)) { /* ASCII upper case? */ - b |= 2; - } - if (IsLower(wc)) { /* ASCII lower case? */ - b |= 1; wc -= 0x20; - } - } - } - dp->fn[i++] = (BYTE)wc; - } - - if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ - - if (ni == 8) b <<= 2; /* Shift capital flags if no extension */ - if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) cf |= NS_LFN; /* LFN entry needs to be created if composite capitals */ - if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended character, NT flags are created */ - if (b & 0x01) cf |= NS_EXT; /* NT flag (Extension has small capital letters only) */ - if (b & 0x04) cf |= NS_BODY; /* NT flag (Body has small capital letters only) */ - } - - dp->fn[NSFLAG] = cf; /* SFN is created into dp->fn[] */ - - return FR_OK; - - -#else /* FF_USE_LFN : Non-LFN configuration */ - BYTE c, d, *sfn; - UINT ni, si, i; - const char *p; - - /* Create file name in directory form */ - p = *path; sfn = dp->fn; - mem_set(sfn, ' ', 11); - si = i = 0; ni = 8; -#if FF_FS_RPATH != 0 - if (p[si] == '.') { /* Is this a dot entry? */ - for (;;) { - c = (BYTE)p[si++]; - if (c != '.' || si >= 3) break; - sfn[i++] = c; - } - if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; - *path = p + si; /* Return pointer to the next segment */ - sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of the path */ - return FR_OK; - } -#endif - for (;;) { - c = (BYTE)p[si++]; /* Get a byte */ - if (c <= ' ') break; /* Break if end of the path name */ - if (c == '/' || c == '\\') { /* Break if a separator is found */ - while (p[si] == '/' || p[si] == '\\') si++; /* Skip duplicated separator if exist */ - break; - } - if (c == '.' || i >= ni) { /* End of body or field overflow? */ - if (ni == 11 || c != '.') return FR_INVALID_NAME; /* Field overflow or invalid dot? */ - i = 8; ni = 11; /* Enter file extension field */ - continue; - } -#if FF_CODE_PAGE == 0 - if (ExCvt && c >= 0x80) { /* Is SBC extended character? */ - c = ExCvt[c & 0x7F]; /* To upper SBC extended character */ - } -#elif FF_CODE_PAGE < 900 - if (c >= 0x80) { /* Is SBC extended character? */ - c = ExCvt[c & 0x7F]; /* To upper SBC extended character */ - } -#endif - if (dbc_1st(c)) { /* Check if it is a DBC 1st byte */ - d = (BYTE)p[si++]; /* Get 2nd byte */ - if (!dbc_2nd(d) || i >= ni - 1) return FR_INVALID_NAME; /* Reject invalid DBC */ - sfn[i++] = c; - sfn[i++] = d; - } else { /* SBC */ - if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) return FR_INVALID_NAME; /* Reject illegal chrs for SFN */ - if (IsLower(c)) c -= 0x20; /* To upper */ - sfn[i++] = c; - } - } - *path = p + si; /* Return pointer to the next segment */ - if (i == 0) return FR_INVALID_NAME; /* Reject nul string */ - - if (sfn[0] == DDEM) sfn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ - sfn[NSFLAG] = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ - - return FR_OK; -#endif /* FF_USE_LFN */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Follow a file path */ -/*-----------------------------------------------------------------------*/ - -static FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ - DIR* dp, /* Directory object to return last directory and found object */ - const TCHAR* path /* Full-path string to find a file or directory */ -) -{ - FRESULT res; - BYTE ns; - FATFS *fs = dp->obj.fs; - - -#if FF_FS_RPATH != 0 - if (*path != '/' && *path != '\\') { /* Without heading separator */ - dp->obj.sclust = fs->cdir; /* Start from current directory */ - } else -#endif - { /* With heading separator */ - while (*path == '/' || *path == '\\') path++; /* Strip heading separator */ - dp->obj.sclust = 0; /* Start from root directory */ - } -#if FF_FS_EXFAT - dp->obj.n_frag = 0; /* Invalidate last fragment counter of the object */ -#if FF_FS_RPATH != 0 - if (fs->fs_type == FS_EXFAT && dp->obj.sclust) { /* exFAT: Retrieve the sub-directory's status */ - DIR dj; - - dp->obj.c_scl = fs->cdc_scl; - dp->obj.c_size = fs->cdc_size; - dp->obj.c_ofs = fs->cdc_ofs; - res = load_obj_xdir(&dj, &dp->obj); - if (res != FR_OK) return res; - dp->obj.objsize = ld_dword(fs->dirbuf + XDIR_FileSize); - dp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; - } -#endif -#endif - - if ((UINT)*path < ' ') { /* Null path name is the origin directory itself */ - dp->fn[NSFLAG] = NS_NONAME; - res = dir_sdi(dp, 0); - - } else { /* Follow path */ - for (;;) { - res = create_name(dp, &path); /* Get a segment name of the path */ - if (res != FR_OK) break; - res = dir_find(dp); /* Find an object with the segment name */ - ns = dp->fn[NSFLAG]; - if (res != FR_OK) { /* Failed to find the object */ - if (res == FR_NO_FILE) { /* Object is not found */ - if (FF_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exist, stay there */ - if (!(ns & NS_LAST)) continue; /* Continue to follow if not last segment */ - dp->fn[NSFLAG] = NS_NONAME; - res = FR_OK; - } else { /* Could not find the object */ - if (!(ns & NS_LAST)) res = FR_NO_PATH; /* Adjust error code if not last segment */ - } - } - break; - } - if (ns & NS_LAST) break; /* Last segment matched. Function completed. */ - /* Get into the sub-directory */ - if (!(dp->obj.attr & AM_DIR)) { /* It is not a sub-directory and cannot follow */ - res = FR_NO_PATH; break; - } -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* Save containing directory information for next dir */ - dp->obj.c_scl = dp->obj.sclust; - dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; - dp->obj.c_ofs = dp->blk_ofs; - init_alloc_info(fs, &dp->obj); /* Open next directory */ - } else -#endif - { - dp->obj.sclust = ld_clust(fs, fs->win + dp->dptr % SS(fs)); /* Open next directory */ - } - } - } - - return res; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Get logical drive number from path name */ -/*-----------------------------------------------------------------------*/ - -static int get_ldnumber ( /* Returns logical drive number (-1:invalid drive number or null pointer) */ - const TCHAR** path /* Pointer to pointer to the path name */ -) -{ - const TCHAR *tp, *tt; - TCHAR tc; - int i, vol = -1; -#if FF_STR_VOLUME_ID /* Find string volume ID */ - const char *sp; - char c; -#endif - - tt = tp = *path; - if (!tp) return vol; /* Invalid path name? */ - do tc = *tt++; while ((UINT)tc >= (FF_USE_LFN ? ' ' : '!') && tc != ':'); /* Find a colon in the path */ - - if (tc == ':') { /* DOS/Windows style volume ID? */ - i = FF_VOLUMES; - if (IsDigit(*tp) && tp + 2 == tt) { /* Is there a numeric volume ID + colon? */ - i = (int)*tp - '0'; /* Get the LD number */ - } -#if FF_STR_VOLUME_ID == 1 /* Arbitrary string is enabled */ - else { - i = 0; - do { - sp = VolumeStr[i]; tp = *path; /* This string volume ID and path name */ - do { /* Compare the volume ID with path name */ - c = *sp++; tc = *tp++; - if (IsLower(c)) c -= 0x20; - if (IsLower(tc)) tc -= 0x20; - } while (c && (TCHAR)c == tc); - } while ((c || tp != tt) && ++i < FF_VOLUMES); /* Repeat for each id until pattern match */ - } -#endif - if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */ - vol = i; /* Drive number */ - *path = tt; /* Snip the drive prefix off */ - } - return vol; - } -#if FF_STR_VOLUME_ID == 2 /* Unix style volume ID is enabled */ - if (*tp == '/') { - i = 0; - do { - sp = VolumeStr[i]; tp = *path; /* This string volume ID and path name */ - do { /* Compare the volume ID with path name */ - c = *sp++; tc = *(++tp); - if (IsLower(c)) c -= 0x20; - if (IsLower(tc)) tc -= 0x20; - } while (c && (TCHAR)c == tc); - } while ((c || (tc != '/' && (UINT)tc >= (FF_USE_LFN ? ' ' : '!'))) && ++i < FF_VOLUMES); /* Repeat for each ID until pattern match */ - if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */ - vol = i; /* Drive number */ - *path = tp; /* Snip the drive prefix off */ - return vol; - } - } -#endif - /* No drive prefix is found */ -#if FF_FS_RPATH != 0 - vol = CurrVol; /* Default drive is current drive */ -#else - vol = 0; /* Default drive is 0 */ -#endif - return vol; /* Return the default drive */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Load a sector and check if it is an FAT VBR */ -/*-----------------------------------------------------------------------*/ - -static BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */ - FATFS* fs, /* Filesystem object */ - DWORD sect /* Sector# (lba) to load and check if it is an FAT-VBR or not */ -) -{ - fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */ - if (move_window(fs, sect) != FR_OK) return 4; /* Load boot record */ - - if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3; /* Check boot record signature (always here regardless of the sector size) */ - -#if FF_FS_EXFAT - if (!mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* Check if exFAT VBR */ -#endif - if (fs->win[BS_JmpBoot] == 0xE9 || fs->win[BS_JmpBoot] == 0xEB || fs->win[BS_JmpBoot] == 0xE8) { /* Valid JumpBoot code? */ - if (!mem_cmp(fs->win + BS_FilSysType, "FAT", 3)) return 0; /* Is it an FAT VBR? */ - if (!mem_cmp(fs->win + BS_FilSysType32, "FAT32", 5)) return 0; /* Is it an FAT32 VBR? */ - } - return 2; /* Valid BS but not FAT */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Determine logical drive number and mount the volume if needed */ -/*-----------------------------------------------------------------------*/ - -static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */ - const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ - FATFS** rfs, /* Pointer to pointer to the found filesystem object */ - BYTE mode /* !=0: Check write protection for write access */ -) -{ - BYTE fmt, *pt; - int vol; - DSTATUS stat; - DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4]; - WORD nrsv; - FATFS *fs; - UINT i; - - - /* Get logical drive number */ - *rfs = 0; - vol = get_ldnumber(path); - if (vol < 0) return FR_INVALID_DRIVE; - - /* Check if the filesystem object is valid or not */ - fs = FatFs[vol]; /* Get pointer to the filesystem object */ - if (!fs) return FR_NOT_ENABLED; /* Is the filesystem object available? */ -#if FF_FS_REENTRANT - if (!lock_fs(fs)) return FR_TIMEOUT; /* Lock the volume */ -#endif - *rfs = fs; /* Return pointer to the filesystem object */ - - mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not */ - if (fs->fs_type != 0) { /* If the volume has been mounted */ - stat = disk_status(fs->pdrv); - if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ - if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */ - EFSPRINTF("WPEN1"); - return FR_WRITE_PROTECTED; - } - return FR_OK; /* The filesystem object is valid */ - } - } - - /* The filesystem object is not valid. */ - /* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */ - - fs->fs_type = 0; /* Clear the filesystem object */ - fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */ - stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */ - if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ - EFSPRINTF("MDNR"); - return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ - } - if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */ - EFSPRINTF("WPEN2"); - return FR_WRITE_PROTECTED; - } -#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */ - if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR; - if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR; -#endif - - /* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK (MBR) and SFD (w/o partition). */ - bsect = 0; - fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */ - if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */ - for (i = 0; i < 4; i++) { /* Get partition offset */ - pt = fs->win + (MBR_Table + i * SZ_PTE); - br[i] = pt[PTE_System] ? ld_dword(pt + PTE_StLba) : 0; - } - i = LD2PT(vol); /* Partition number: 0:auto, 1-4:forced */ - if (i != 0) i--; - do { /* Find an FAT volume */ - bsect = br[i]; - fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */ - } while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4); - } - if (fmt == 4) { - EFSPRINTF("BRNL"); - return FR_DISK_ERR; /* An error occured in the disk I/O layer */ - } - if (fmt >= 2) { - EFSPRINTF("NOFAT"); - return FR_NO_FILESYSTEM; /* No FAT volume is found */ - } - - /* An FAT volume is found (bsect). Following code initializes the filesystem object */ - -#if FF_FS_EXFAT - if (fmt == 1) { - QWORD maxlba; - DWORD so, cv, bcl; - - for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */ - if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM; - - if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */ - - if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */ - EFSPRINTF("EXSPS"); - return FR_NO_FILESYSTEM; - } - - maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */ - if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */ - - fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */ - - fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */ - if (fs->n_fats != 1) { - EFSPRINTF("EXFNF"); - return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */ - } - - fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */ - if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768) */ - - nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */ - if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */ - fs->n_fatent = nclst + 2; - - /* Boundaries and Limits */ - fs->volbase = bsect; - fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx); - fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx); - if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */ - fs->dirbase = ld_dword(fs->win + BPB_RootClusEx); - - /* Get bitmap location and check if it is contiguous (implementation assumption) */ - so = i = 0; - for (;;) { /* Find the bitmap entry in the root directory (in only first cluster) */ - if (i == 0) { - if (so >= fs->csize) return FR_NO_FILESYSTEM; /* Not found? */ - if (move_window(fs, clst2sect(fs, fs->dirbase) + so) != FR_OK) { - EFSPRINTF("EXBM1C"); - return FR_DISK_ERR; - } - so++; - } - if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */ - i = (i + SZDIRE) % SS(fs); /* Next entry */ - } - bcl = ld_dword(fs->win + i + 20); /* Bitmap cluster */ - if (bcl < 2 || bcl >= fs->n_fatent) { - EFSPRINTF("EXBMM"); - return FR_NO_FILESYSTEM; - } - fs->bitbase = fs->database + fs->csize * (bcl - 2); /* Bitmap sector */ - for (;;) { /* Check if bitmap is contiguous */ - if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR; - cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4); - if (cv == 0xFFFFFFFF) break; /* Last link? */ - if (cv != ++bcl) { - EFSPRINTF("EXBMM"); - return FR_NO_FILESYSTEM; /* Fragmented? */ - } - } - -#if !FF_FS_READONLY - fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ -#endif - fmt = FS_EXFAT; /* FAT sub-type */ - } else -#endif /* FF_FS_EXFAT */ - { - if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) { - EFSPRINTF("32SPS"); - return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */ - } - - fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */ - if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32); - fs->fsize = fasize; - - fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */ - if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ - fasize *= fs->n_fats; /* Number of sectors for FAT area */ - - fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */ - if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ - - fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */ - if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) */ - - tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */ - if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32); - - nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */ - if (nrsv == 0) return FR_NO_FILESYSTEM; /* (Must not be 0) */ - - /* Determine the FAT sub type */ - sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */ - if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ - nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ - if (nclst == 0) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ - fmt = 0; - if (nclst <= MAX_FAT32) fmt = FS_FAT32; - if (nclst <= MAX_FAT16) fmt = FS_FAT16; - if (nclst <= MAX_FAT12) fmt = FS_FAT12; - if (fmt == 0) return FR_NO_FILESYSTEM; - - /* Boundaries and Limits */ - fs->n_fatent = nclst + 2; /* Number of FAT entries */ - fs->volbase = bsect; /* Volume start sector */ - fs->fatbase = bsect + nrsv; /* FAT start sector */ - fs->database = bsect + sysect; /* Data start sector */ - if (fmt == FS_FAT32) { - if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */ - if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ - fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */ - szbfat = fs->n_fatent * 4; /* (Needed FAT size) */ - } else { - if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ - fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ - szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */ - fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); - } - if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */ - -#if !FF_FS_READONLY - /* Get FSInfo if available */ - fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ - fs->fsi_flag = 0x80; -#if (FF_FS_NOFSINFO & 3) != 3 - if (fmt == FS_FAT32 /* Allow to update FSInfo only if BPB_FSInfo32 == 1 */ - && ld_word(fs->win + BPB_FSInfo32) == 1 - && move_window(fs, bsect + 1) == FR_OK) - { - fs->fsi_flag = 0; - if (ld_word(fs->win + BS_55AA) == 0xAA55 /* Load FSInfo data if available */ - && ld_dword(fs->win + FSI_LeadSig) == 0x41615252 - && ld_dword(fs->win + FSI_StrucSig) == 0x61417272) - { -#if (FF_FS_NOFSINFO & 1) == 0 - fs->free_clst = ld_dword(fs->win + FSI_Free_Count); -#endif -#if (FF_FS_NOFSINFO & 2) == 0 - fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free); -#endif - } - } -#endif /* (FF_FS_NOFSINFO & 3) != 3 */ -#endif /* !FF_FS_READONLY */ - } - - fs->fs_type = fmt; /* FAT sub-type */ - fs->id = ++Fsid; /* Volume mount ID */ -#if FF_USE_LFN == 1 - fs->lfnbuf = LfnBuf; /* Static LFN working buffer */ -#if FF_FS_EXFAT - fs->dirbuf = DirBuf; /* Static directory block scratchpad buffer */ -#endif -#endif -#if FF_FS_RPATH != 0 - fs->cdir = 0; /* Initialize current directory */ -#endif -#if FF_FS_LOCK != 0 /* Clear file lock semaphores */ - clear_lock(fs); -#endif - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Check if the file/directory object is valid or not */ -/*-----------------------------------------------------------------------*/ - -static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ - FFOBJID* obj, /* Pointer to the FFOBJID, the 1st member in the FIL/DIR object, to check validity */ - FATFS** rfs /* Pointer to pointer to the owner filesystem object to return */ -) -{ - FRESULT res = FR_INVALID_OBJECT; - - - if (obj && obj->fs && obj->fs->fs_type && obj->id == obj->fs->id) { /* Test if the object is valid */ -#if FF_FS_REENTRANT - if (lock_fs(obj->fs)) { /* Obtain the filesystem object */ - if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ - res = FR_OK; - } else { - unlock_fs(obj->fs, FR_OK); - } - } else { - res = FR_TIMEOUT; - } -#else - if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ - res = FR_OK; - } -#endif - } - *rfs = (res == FR_OK) ? obj->fs : 0; /* Corresponding filesystem object */ - return res; -} - - - - -/*--------------------------------------------------------------------------- - - Public Functions (FatFs API) - -----------------------------------------------------------------------------*/ - - - -/*-----------------------------------------------------------------------*/ -/* Mount/Unmount a Logical Drive */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_mount ( - FATFS* fs, /* Pointer to the filesystem object (NULL:unmount)*/ - const TCHAR* path, /* Logical drive number to be mounted/unmounted */ - BYTE opt /* Mode option 0:Do not mount (delayed mount), 1:Mount immediately */ -) -{ - FATFS *cfs; - int vol; - FRESULT res; - const TCHAR *rp = path; - - - /* Get logical drive number */ - vol = get_ldnumber(&rp); - if (vol < 0) { - EFSPRINTF("IDRIVE!"); - return FR_INVALID_DRIVE; - } - cfs = FatFs[vol]; /* Pointer to fs object */ - - if (cfs) { -#if FF_FS_LOCK != 0 - clear_lock(cfs); -#endif -#if FF_FS_REENTRANT /* Discard sync object of the current volume */ - if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR; -#endif - cfs->fs_type = 0; /* Clear old fs object */ - } - - if (fs) { - fs->fs_type = 0; /* Clear new fs object */ -#if FF_FS_REENTRANT /* Create sync object for the new volume */ - if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR; -#endif - } - FatFs[vol] = fs; /* Register new fs object */ - - if (opt == 0) return FR_OK; /* Do not mount now, it will be mounted later */ - - res = find_volume(&path, &fs, 0); /* Force mounted the volume */ - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Open or Create a File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_open ( - FIL* fp, /* Pointer to the blank file object */ - const TCHAR* path, /* Pointer to the file name */ - BYTE mode /* Access mode and file open mode flags */ -) -{ - FRESULT res; - DIR dj; - FATFS *fs; -#if !FF_FS_READONLY - DWORD dw, cl, bcs, clst, sc; - FSIZE_t ofs; -#endif - DEF_NAMBUF - - - if (!fp) return FR_INVALID_OBJECT; - - /* Get logical drive number */ - mode &= FF_FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND; - res = find_volume(&path, &fs, mode); - if (res == FR_OK) { - dj.obj.fs = fs; - INIT_NAMBUF(fs); - res = follow_path(&dj, path); /* Follow the file path */ -#if !FF_FS_READONLY /* Read/Write configuration */ - if (res == FR_OK) { - if (dj.fn[NSFLAG] & NS_NONAME) { /* Origin directory itself? */ - res = FR_INVALID_NAME; - } -#if FF_FS_LOCK != 0 - else { - res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Check if the file can be used */ - } -#endif - } - /* Create or Open a file */ - if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { - if (res != FR_OK) { /* No file, create new */ - if (res == FR_NO_FILE) { /* There is no file to open, create a new entry */ -#if FF_FS_LOCK != 0 - res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; -#else - res = dir_register(&dj); -#endif - } - mode |= FA_CREATE_ALWAYS; /* File is created */ - } - else { /* Any object with the same name is already existing */ - if (dj.obj.attr & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ - res = FR_DENIED; - } else { - if (mode & FA_CREATE_NEW) res = FR_EXIST; /* Cannot create as new file */ - } - } - if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate the file if overwrite mode */ -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - /* Get current allocation info */ - fp->obj.fs = fs; - init_alloc_info(fs, &fp->obj); - /* Set directory entry block initial state */ - mem_set(fs->dirbuf + 2, 0, 30); /* Clear 85 entry except for NumSec */ - mem_set(fs->dirbuf + 38, 0, 26); /* Clear C0 entry except for NumName and NameHash */ - fs->dirbuf[XDIR_Attr] = AM_ARC; - st_dword(fs->dirbuf + XDIR_CrtTime, GET_FATTIME()); - fs->dirbuf[XDIR_GenFlags] = 1; - res = store_xdir(&dj); - if (res == FR_OK && fp->obj.sclust != 0) { /* Remove the cluster chain if exist */ - res = remove_chain(&fp->obj, fp->obj.sclust, 0); - fs->last_clst = fp->obj.sclust - 1; /* Reuse the cluster hole */ - } - } else -#endif - { - /* Set directory entry initial state */ - cl = ld_clust(fs, dj.dir); /* Get current cluster chain */ - st_dword(dj.dir + DIR_CrtTime, GET_FATTIME()); /* Set created time */ - dj.dir[DIR_Attr] = AM_ARC; /* Reset attribute */ - st_clust(fs, dj.dir, 0); /* Reset file allocation info */ - st_dword(dj.dir + DIR_FileSize, 0); - fs->wflag = 1; - if (cl != 0) { /* Remove the cluster chain if exist */ - dw = fs->winsect; - res = remove_chain(&dj.obj, cl, 0); - if (res == FR_OK) { - res = move_window(fs, dw); - fs->last_clst = cl - 1; /* Reuse the cluster hole */ - } - } - } - } - } - else { /* Open an existing file */ - if (res == FR_OK) { /* Is the object exsiting? */ - if (dj.obj.attr & AM_DIR) { /* File open against a directory */ - res = FR_NO_FILE; - } else { - if ((mode & FA_WRITE) && (dj.obj.attr & AM_RDO)) { /* Write mode open against R/O file */ - res = FR_DENIED; - } - } - } - } - if (res == FR_OK) { - if (mode & FA_CREATE_ALWAYS) mode |= FA_MODIFIED; /* Set file change flag if created or overwritten */ - fp->dir_sect = fs->winsect; /* Pointer to the directory entry */ - fp->dir_ptr = dj.dir; -#if FF_FS_LOCK != 0 - fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Lock the file for this session */ - if (fp->obj.lockid == 0) res = FR_INT_ERR; -#endif - } -#else /* R/O configuration */ - if (res == FR_OK) { - if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it origin directory itself? */ - res = FR_INVALID_NAME; - } else { - if (dj.obj.attr & AM_DIR) { /* Is it a directory? */ - res = FR_NO_FILE; - } - } - } -#endif - - if (res == FR_OK) { -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - fp->obj.c_scl = dj.obj.sclust; /* Get containing directory info */ - fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; - fp->obj.c_ofs = dj.blk_ofs; - init_alloc_info(fs, &fp->obj); - } else -#endif - { - fp->obj.sclust = ld_clust(fs, dj.dir); /* Get object allocation info */ - fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize); - } -#if FF_USE_FASTSEEK - fp->cltbl = 0; /* Disable fast seek mode */ -#endif - fp->obj.fs = fs; /* Validate the file object */ - fp->obj.id = fs->id; - fp->flag = mode; /* Set file access mode */ - fp->err = 0; /* Clear error flag */ - fp->sect = 0; /* Invalidate current data sector */ - fp->fptr = 0; /* Set file pointer top of the file */ -#if !FF_FS_READONLY -#if !FF_FS_TINY - mem_set(fp->buf, 0, sizeof fp->buf); /* Clear sector buffer */ -#endif - if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */ - fp->fptr = fp->obj.objsize; /* Offset to seek */ - bcs = (DWORD)fs->csize * SS(fs); /* Cluster size in byte */ - clst = fp->obj.sclust; /* Follow the cluster chain */ - for (ofs = fp->obj.objsize; res == FR_OK && ofs > bcs; ofs -= bcs) { - clst = get_fat(&fp->obj, clst); - if (clst <= 1) res = FR_INT_ERR; - if (clst == 0xFFFFFFFF) res = FR_DISK_ERR; - } - fp->clust = clst; - if (res == FR_OK && ofs % SS(fs)) { /* Fill sector buffer if not on the sector boundary */ - if ((sc = clst2sect(fs, clst)) == 0) { - res = FR_INT_ERR; - } else { - fp->sect = sc + (DWORD)(ofs / SS(fs)); -#if !FF_FS_TINY - if (disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR; -#endif - } - } - } -#endif - } - - FREE_NAMBUF(); - } - - if (res != FR_OK) fp->obj.fs = 0; /* Invalidate file object on error */ - - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Read File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_read ( - FIL* fp, /* Pointer to the file object */ - void* buff, /* Pointer to data buffer */ - UINT btr, /* Number of bytes to read */ - UINT* br /* Pointer to number of bytes read */ -) -{ - FRESULT res; - FATFS *fs; - DWORD clst, sect; - FSIZE_t remain; - UINT rcnt, cc, csect; - BYTE *rbuff = (BYTE*)buff; - - UINT br_tmp; - if (!br) - br = &br_tmp; - *br = 0; /* Clear read byte counter */ - res = validate(&fp->obj, &fs); /* Check validity of the file object */ - if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) { - EFSPRINTF("FOV"); - LEAVE_FF(fs, res); /* Check validity */ - } - if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ - remain = fp->obj.objsize - fp->fptr; - if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ - - for ( ; btr; /* Repeat until btr bytes read */ - btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) { - if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ - csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ - if (csect == 0) { /* On the cluster boundary? */ - if (fp->fptr == 0) { /* On the top of the file? */ - clst = fp->obj.sclust; /* Follow cluster chain from the origin */ - } else { /* Middle or end of the file */ -#if FF_USE_FASTSEEK - if (fp->cltbl) { - clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ - } else -#endif - { - clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */ - } - } - if (clst < 2) { - EFSPRINTF("CCHK"); - ABORT(fs, FR_INT_ERR); - } - if (clst == 0xFFFFFFFF) { - EFSPRINTF("DSKC"); - ABORT(fs, FR_DISK_ERR); - } - fp->clust = clst; /* Update current cluster */ - } - sect = clst2sect(fs, fp->clust); /* Get current sector */ - if (sect == 0) ABORT(fs, FR_INT_ERR); - sect += csect; - cc = btr / SS(fs); /* When remaining bytes >= sector size, */ - if (cc > 0) { /* Read maximum contiguous sectors directly */ - if (csect + cc > fs->csize) { /* Clip at cluster boundary */ - cc = fs->csize - csect; - } - if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) { - EFSPRINTF("RLIO"); - ABORT(fs, FR_DISK_ERR); - } -#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ -#if FF_FS_TINY - if (fs->wflag && fs->winsect - sect < cc) { - mem_cpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs)); - } -#else - if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) { - mem_cpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs)); - } -#endif -#endif - rcnt = SS(fs) * cc; /* Number of bytes transferred */ - continue; - } -#if !FF_FS_TINY - if (fp->sect != sect) { /* Load data sector if not in cache */ -#if !FF_FS_READONLY - if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) { - EFSPRINTF("RDC"); - ABORT(fs, FR_DISK_ERR); - } - fp->flag &= (BYTE)~FA_DIRTY; - } -#endif - if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) { - EFSPRINTF("RSC"); - ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ - } - } -#endif - fp->sect = sect; - } - rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ - if (rcnt > btr) rcnt = btr; /* Clip it by btr if needed */ -#if FF_FS_TINY - if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ - mem_cpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ -#else - mem_cpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ -#endif - } - - LEAVE_FF(fs, FR_OK); -} - - - - -#ifdef FF_FASTFS -/*-----------------------------------------------------------------------*/ -/* Fast Read Aligned Sized File Without a Cache */ -/*-----------------------------------------------------------------------*/ -#if FF_USE_FASTSEEK -FRESULT f_read_fast ( - FIL* fp, /* Pointer to the file object */ - const void* buff, /* Pointer to the data to be written */ - UINT btr /* Number of bytes to read */ -) -{ - FRESULT res; - FATFS *fs; - UINT csize_bytes; - DWORD clst; - DWORD wbytes; - UINT count; - FSIZE_t work_sector = 0; - FSIZE_t sector_base = 0; - BYTE *wbuff = (BYTE*)buff; - - res = validate(&fp->obj, &fs); /* Check validity of the file object */ - if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) { - EFSPRINTF("FOV"); - LEAVE_FF(fs, res); /* Check validity */ - } - - if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ - FSIZE_t remain = fp->obj.objsize - fp->fptr; - if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ - - csize_bytes = fs->csize * SS(fs); - DWORD csect = (UINT)((fp->fptr / SS(fs)) & (fs->csize - 1)); /* Sector offset in the cluster */ - - /* If inside a cluster, read the sectors and align to cluster. */ - if (csect) { - wbytes = MIN(btr, (fs->csize - csect) * SS(fs)); - f_read(fp, wbuff, wbytes, (void *)0); - wbuff += wbytes; - btr -= wbytes; - if (!btr) - goto out; - } - - if (!fp->fptr) { /* On the top of the file? */ - clst = fp->obj.sclust; /* Follow from the origin */ - } else { - if (fp->cltbl) clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ - else { EFSPRINTF("CLTBL"); ABORT(fs, FR_CLTBL_NO_INIT); } - } - - if (clst < 2) { EFSPRINTF("CCHK"); ABORT(fs, FR_INT_ERR); } - else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); } - - fp->clust = clst; /* Set working cluster */ - - wbytes = MIN(btr, csize_bytes); - sector_base = clst2sect(fs, fp->clust); - count = wbytes / SS(fs); - fp->fptr += wbytes; - btr -= wbytes; - - if (!btr) { /* Final cluster/sectors read. */ - if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); - goto out; - } - - while (btr) { - clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ - - if (clst < 2) { EFSPRINTF("CCHK2"); ABORT(fs, FR_INT_ERR); } - else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); } - - fp->clust = clst; - - work_sector = clst2sect(fs, fp->clust); - wbytes = MIN(btr, csize_bytes); - if ((work_sector - sector_base) == count) count += wbytes / SS(fs); - else { - if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); - wbuff += count * SS(fs); - - sector_base = work_sector; - count = wbytes / SS(fs); - } - - fp->fptr += wbytes; - btr -= wbytes; - - if (!btr) { /* Final cluster/sectors read. */ - if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); - } - } - -out: - LEAVE_FF(fs, FR_OK); -} -#endif -#endif - - - - -#if !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Write File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_write ( - FIL* fp, /* Pointer to the file object */ - const void* buff, /* Pointer to the data to be written */ - UINT btw, /* Number of bytes to write */ - UINT* bw /* Pointer to number of bytes written */ -) -{ - FRESULT res; - FATFS *fs; - DWORD clst, sect; - UINT wcnt, cc, csect; - const BYTE *wbuff = (const BYTE*)buff; - - UINT bw_tmp; - if (!bw) - bw = &bw_tmp; - *bw = 0; /* Clear write byte counter */ - res = validate(&fp->obj, &fs); /* Check validity of the file object */ - if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) { - EFSPRINTF("FOV"); - LEAVE_FF(fs, res); /* Check validity */ - } - if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ - - /* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */ - if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) { - btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr); - } - - for ( ; btw; /* Repeat until all data written */ - btw -= wcnt, *bw += wcnt, wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) { - if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ - csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1); /* Sector offset in the cluster */ - if (csect == 0) { /* On the cluster boundary? */ - if (fp->fptr == 0) { /* On the top of the file? */ - clst = fp->obj.sclust; /* Follow from the origin */ - if (clst == 0) { /* If no cluster is allocated, */ - clst = create_chain(&fp->obj, 0); /* create a new cluster chain */ - } - } else { /* On the middle or end of the file */ -#if FF_USE_FASTSEEK - if (fp->cltbl) { - clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ - } else -#endif - { - clst = create_chain(&fp->obj, fp->clust); /* Follow or stretch cluster chain on the FAT */ - } - } - if (clst == 0) { - EFSPRINTF("DSKFULL"); - break; /* Could not allocate a new cluster (disk full) */ - } - if (clst == 1) { - EFSPRINTF("CCHK"); - ABORT(fs, FR_INT_ERR); - } - if (clst == 0xFFFFFFFF) { - EFSPRINTF("DERR"); - ABORT(fs, FR_DISK_ERR); - } - fp->clust = clst; /* Update current cluster */ - if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */ - } -#if FF_FS_TINY - if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */ -#else - if (fp->flag & FA_DIRTY) { /* Write-back sector cache */ - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA_DIRTY; - } -#endif - sect = clst2sect(fs, fp->clust); /* Get current sector */ - if (sect == 0) ABORT(fs, FR_INT_ERR); - sect += csect; - cc = btw / SS(fs); /* When remaining bytes >= sector size, */ - if (cc > 0) { /* Write maximum contiguous sectors directly */ - if (csect + cc > fs->csize) { /* Clip at cluster boundary */ - cc = fs->csize - csect; - } - if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) { - EFSPRINTF("WLIO"); - ABORT(fs, FR_DISK_ERR); - } -#if FF_FS_MINIMIZE <= 2 -#if FF_FS_TINY - if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ - mem_cpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs)); - fs->wflag = 0; - } -#else - if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ - mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs)); - fp->flag &= (BYTE)~FA_DIRTY; - } -#endif -#endif - wcnt = SS(fs) * cc; /* Number of bytes transferred */ - continue; - } -#if FF_FS_TINY - if (fp->fptr >= fp->obj.objsize) { /* Avoid silly cache filling on the growing edge */ - if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); - fs->winsect = sect; - } -#else - if (fp->sect != sect && /* Fill sector cache with file data */ - fp->fptr < fp->obj.objsize && - disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) { - ABORT(fs, FR_DISK_ERR); - } -#endif - fp->sect = sect; - } - wcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ - if (wcnt > btw) wcnt = btw; /* Clip it by btw if needed */ -#if FF_FS_TINY - if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ - mem_cpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ - fs->wflag = 1; -#else - mem_cpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ - fp->flag |= FA_DIRTY; -#endif - } - - fp->flag |= FA_MODIFIED; /* Set file change flag */ - - LEAVE_FF(fs, FR_OK); -} - - - - -#ifdef FF_FASTFS -/*-----------------------------------------------------------------------*/ -/* Fast Write Aligned Sized File Without a Cache */ -/*-----------------------------------------------------------------------*/ -#if FF_USE_FASTSEEK -FRESULT f_write_fast ( - FIL* fp, /* Pointer to the file object */ - const void* buff, /* Pointer to the data to be written */ - UINT btw /* Number of bytes to write */ -) -{ - FRESULT res; - FATFS *fs; - UINT csize_bytes; - DWORD clst; - DWORD wbytes; - UINT count; - FSIZE_t work_sector = 0; - FSIZE_t sector_base = 0; - BYTE *wbuff = (BYTE*)buff; - - res = validate(&fp->obj, &fs); /* Check validity of the file object */ - if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) { - EFSPRINTF("FOV"); - LEAVE_FF(fs, res); /* Check validity */ - } - - if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ - /* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */ - if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) { - btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr); - } - - csize_bytes = fs->csize * SS(fs); - DWORD csect = (UINT)((fp->fptr / SS(fs)) & (fs->csize - 1)); /* Sector offset in the cluster */ - - /* If inside a cluster, write the sectors and align to cluster. */ - if (csect) { - wbytes = MIN(btw, (fs->csize - csect) * SS(fs)); - f_write(fp, wbuff, wbytes, (void *)0); - /* Ensure flushing of it. FatFS is not notified for next write if raw. */ - f_sync(fp); - wbuff += wbytes; - btw -= wbytes; - if (!btw) - goto out; - } - - if (!fp->fptr) { /* On the top of the file? */ - clst = fp->obj.sclust; /* Follow from the origin */ - } else { - if (fp->cltbl) clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ - else { EFSPRINTF("CLTBL"); ABORT(fs, FR_CLTBL_NO_INIT); } - } - - if (clst < 2) { EFSPRINTF("CCHK"); ABORT(fs, FR_INT_ERR); } - else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); } - - fp->clust = clst; /* Set working cluster */ - - wbytes = MIN(btw, csize_bytes); - sector_base = clst2sect(fs, fp->clust); - count = wbytes / SS(fs); - fp->fptr += wbytes; - btw -= wbytes; - - if (!btw) { /* Final cluster/sectors write. */ - if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA_DIRTY; - goto out; - } - - while (btw) { - clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ - - if (clst < 2) { EFSPRINTF("CCHK2"); ABORT(fs, FR_INT_ERR); } - else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); } - - fp->clust = clst; - - work_sector = clst2sect(fs, fp->clust); - wbytes = MIN(btw, csize_bytes); - if ((work_sector - sector_base) == count) count += wbytes / SS(fs); - else { - if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); - wbuff += count * SS(fs); - - sector_base = work_sector; - count = wbytes / SS(fs); - } - - fp->fptr += wbytes; - btw -= wbytes; - - if (!btw) { /* Final cluster/sectors write. */ - if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA_DIRTY; - } - } - -out: - fp->flag |= FA_MODIFIED; /* Set file change flag */ - - LEAVE_FF(fs, FR_OK); -} -#endif -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Synchronize the File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_sync ( - FIL* fp /* Pointer to the file object */ -) -{ - FRESULT res; - FATFS *fs; - DWORD tm; - BYTE *dir; - - - res = validate(&fp->obj, &fs); /* Check validity of the file object */ - if (res == FR_OK) { - if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */ -#if !FF_FS_TINY - if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */ - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA_DIRTY; - } -#endif - /* Update the directory entry */ - tm = GET_FATTIME(); /* Modified time */ -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - res = fill_first_frag(&fp->obj); /* Fill first fragment on the FAT if needed */ - if (res == FR_OK) { - res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ - } - if (res == FR_OK) { - DIR dj; - DEF_NAMBUF - - INIT_NAMBUF(fs); - res = load_obj_xdir(&dj, &fp->obj); /* Load directory entry block */ - if (res == FR_OK) { - fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ - fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1; /* Update file allocation information */ - st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust); - st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize); - st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize); - st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Update modified time */ - fs->dirbuf[XDIR_ModTime10] = 0; - st_dword(fs->dirbuf + XDIR_AccTime, 0); - res = store_xdir(&dj); /* Restore it to the directory */ - if (res == FR_OK) { - res = sync_fs(fs); - fp->flag &= (BYTE)~FA_MODIFIED; - } - } - FREE_NAMBUF(); - } - } else -#endif - { - res = move_window(fs, fp->dir_sect); - if (res == FR_OK) { - dir = fp->dir_ptr; - dir[DIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ - st_clust(fp->obj.fs, dir, fp->obj.sclust); /* Update file allocation information */ - st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize); /* Update file size */ - st_dword(dir + DIR_ModTime, tm); /* Update modified time */ - st_word(dir + DIR_LstAccDate, 0); - fs->wflag = 1; - res = sync_fs(fs); /* Restore it to the directory */ - fp->flag &= (BYTE)~FA_MODIFIED; - } - } - } - } - - LEAVE_FF(fs, res); -} - -#endif /* !FF_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* Close File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_close ( - FIL* fp /* Pointer to the file object to be closed */ -) -{ - FRESULT res; - FATFS *fs; - -#if !FF_FS_READONLY - res = f_sync(fp); /* Flush cached data */ - if (res == FR_OK) -#endif - { - res = validate(&fp->obj, &fs); /* Lock volume */ - if (res == FR_OK) { -#if FF_FS_LOCK != 0 - res = dec_lock(fp->obj.lockid); /* Decrement file open counter */ - if (res == FR_OK) fp->obj.fs = 0; /* Invalidate file object */ -#else - fp->obj.fs = 0; /* Invalidate file object */ -#endif -#if FF_FS_REENTRANT - unlock_fs(fs, FR_OK); /* Unlock volume */ -#endif - } - } - return res; -} - - - - -#if FF_FS_RPATH >= 1 -/*-----------------------------------------------------------------------*/ -/* Change Current Directory or Current Drive, Get Current Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_chdrive ( - const TCHAR* path /* Drive number to set */ -) -{ - int vol; - - - /* Get logical drive number */ - vol = get_ldnumber(&path); - if (vol < 0) return FR_INVALID_DRIVE; - CurrVol = (BYTE)vol; /* Set it as current volume */ - - return FR_OK; -} - - - -FRESULT f_chdir ( - const TCHAR* path /* Pointer to the directory path */ -) -{ -#if FF_STR_VOLUME_ID == 2 - UINT i; -#endif - FRESULT res; - DIR dj; - FATFS *fs; - DEF_NAMBUF - - - /* Get logical drive */ - res = find_volume(&path, &fs, 0); - if (res == FR_OK) { - dj.obj.fs = fs; - INIT_NAMBUF(fs); - res = follow_path(&dj, path); /* Follow the path */ - if (res == FR_OK) { /* Follow completed */ - if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it the start directory itself? */ - fs->cdir = dj.obj.sclust; -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - fs->cdc_scl = dj.obj.c_scl; - fs->cdc_size = dj.obj.c_size; - fs->cdc_ofs = dj.obj.c_ofs; - } -#endif - } else { - if (dj.obj.attr & AM_DIR) { /* It is a sub-directory */ -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus); /* Sub-directory cluster */ - fs->cdc_scl = dj.obj.sclust; /* Save containing directory information */ - fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; - fs->cdc_ofs = dj.blk_ofs; - } else -#endif - { - fs->cdir = ld_clust(fs, dj.dir); /* Sub-directory cluster */ - } - } else { - res = FR_NO_PATH; /* Reached but a file */ - } - } - } - FREE_NAMBUF(); - if (res == FR_NO_FILE) res = FR_NO_PATH; -#if FF_STR_VOLUME_ID == 2 /* Also current drive is changed at Unix style volume ID */ - if (res == FR_OK) { - for (i = FF_VOLUMES - 1; i && fs != FatFs[i]; i--) ; /* Set current drive */ - CurrVol = (BYTE)i; - } -#endif - } - - LEAVE_FF(fs, res); -} - - -#if FF_FS_RPATH >= 2 -FRESULT f_getcwd ( - TCHAR* buff, /* Pointer to the directory path */ - UINT len /* Size of buff in unit of TCHAR */ -) -{ - FRESULT res; - DIR dj; - FATFS *fs; - UINT i, n; - DWORD ccl; - TCHAR *tp = buff; -#if FF_VOLUMES >= 2 - UINT vl; -#if FF_STR_VOLUME_ID - const char *vp; -#endif -#endif - FILINFO fno; - DEF_NAMBUF - - - /* Get logical drive */ - buff[0] = 0; /* Set null string to get current volume */ - res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */ - if (res == FR_OK) { - dj.obj.fs = fs; - INIT_NAMBUF(fs); - - /* Follow parent directories and create the path */ - i = len; /* Bottom of buffer (directory stack base) */ - if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* (Cannot do getcwd on exFAT and returns root path) */ - dj.obj.sclust = fs->cdir; /* Start to follow upper directory from current directory */ - while ((ccl = dj.obj.sclust) != 0) { /* Repeat while current directory is a sub-directory */ - res = dir_sdi(&dj, 1 * SZDIRE); /* Get parent directory */ - if (res != FR_OK) break; - res = move_window(fs, dj.sect); - if (res != FR_OK) break; - dj.obj.sclust = ld_clust(fs, dj.dir); /* Goto parent directory */ - res = dir_sdi(&dj, 0); - if (res != FR_OK) break; - do { /* Find the entry links to the child directory */ - res = DIR_READ_FILE(&dj); - if (res != FR_OK) break; - if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */ - res = dir_next(&dj, 0); - } while (res == FR_OK); - if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ - if (res != FR_OK) break; - get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */ - for (n = 0; fno.fname[n]; n++) ; /* Name length */ - if (i < n + 1) { /* Insufficient space to store the path name? */ - res = FR_NOT_ENOUGH_CORE; break; - } - while (n) buff[--i] = fno.fname[--n]; /* Stack the name */ - buff[--i] = '/'; - } - } - if (res == FR_OK) { - if (i == len) buff[--i] = '/'; /* Is it the root-directory? */ -#if FF_VOLUMES >= 2 /* Put drive prefix */ - vl = 0; -#if FF_STR_VOLUME_ID >= 1 /* String volume ID */ - for (n = 0, vp = (const char*)VolumeStr[CurrVol]; vp[n]; n++) ; - if (i >= n + 2) { - if (FF_STR_VOLUME_ID == 2) *tp++ = (TCHAR)'/'; - for (vl = 0; vl < n; *tp++ = (TCHAR)vp[vl], vl++) ; - if (FF_STR_VOLUME_ID == 1) *tp++ = (TCHAR)':'; - vl++; - } -#else /* Numeric volume ID */ - if (i >= 3) { - *tp++ = (TCHAR)'0' + CurrVol; - *tp++ = (TCHAR)':'; - vl = 2; - } -#endif - if (vl == 0) res = FR_NOT_ENOUGH_CORE; -#endif - /* Add current directory path */ - if (res == FR_OK) { - do *tp++ = buff[i++]; while (i < len); /* Copy stacked path string */ - } - } - FREE_NAMBUF(); - } - - *tp = 0; - LEAVE_FF(fs, res); -} - -#endif /* FF_FS_RPATH >= 2 */ -#endif /* FF_FS_RPATH >= 1 */ - - - -#if FF_FS_MINIMIZE <= 2 -/*-----------------------------------------------------------------------*/ -/* Seek File Read/Write Pointer */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_lseek ( - FIL* fp, /* Pointer to the file object */ - FSIZE_t ofs /* File pointer from top of file */ -) -{ - FRESULT res; - FATFS *fs; - DWORD clst, bcs, nsect; - FSIZE_t ifptr; -#if FF_USE_FASTSEEK - DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; -#endif - - res = validate(&fp->obj, &fs); /* Check validity of the file object */ - if (res == FR_OK) res = (FRESULT)fp->err; -#if FF_FS_EXFAT && !FF_FS_READONLY - if (res == FR_OK && fs->fs_type == FS_EXFAT) { - res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ - } -#endif - if (res != FR_OK) LEAVE_FF(fs, res); - -#if FF_USE_FASTSEEK - if (fp->cltbl) { /* Fast seek */ - if (ofs == CREATE_LINKMAP) { /* Create CLMT */ - tbl = fp->cltbl; - tlen = *tbl++; ulen = 2; /* Given table size and required table size */ - cl = fp->obj.sclust; /* Origin of the chain */ - if (cl != 0) { - do { - /* Get a fragment */ - tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ - do { - pcl = cl; ncl++; - cl = get_fat(&fp->obj, cl); - if (cl <= 1) ABORT(fs, FR_INT_ERR); - if (cl == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); - } while (cl == pcl + 1); - if (ulen <= tlen) { /* Store the length and top of the fragment */ - *tbl++ = ncl; *tbl++ = tcl; - } - } while (cl < fs->n_fatent); /* Repeat until end of chain */ - } - *fp->cltbl = ulen; /* Number of items used */ - if (ulen <= tlen) { - *tbl = 0; /* Terminate table */ - } else { - res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ - } - } else { /* Fast seek */ - if (ofs > fp->obj.objsize) ofs = fp->obj.objsize; /* Clip offset at the file size */ - fp->fptr = ofs; /* Set file pointer */ - if (ofs > 0) { - fp->clust = clmt_clust(fp, ofs - 1); - dsc = clst2sect(fs, fp->clust); - if (dsc == 0) ABORT(fs, FR_INT_ERR); - dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1); - if (fp->fptr % SS(fs) && dsc != fp->sect) { /* Refill sector cache if needed */ -#if !FF_FS_TINY -#if !FF_FS_READONLY - if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA_DIRTY; - } -#endif - if (disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */ -#endif - fp->sect = dsc; - } - } - } - } else -#endif - - /* Normal Seek */ - { -#if FF_FS_EXFAT - if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF; /* Clip at 4 GiB - 1 if at FATxx */ -#endif - if (ofs > fp->obj.objsize && (FF_FS_READONLY || !(fp->flag & FA_WRITE))) { /* In read-only mode, clip offset with the file size */ - ofs = fp->obj.objsize; - } - ifptr = fp->fptr; - fp->fptr = nsect = 0; - if (ofs > 0) { - bcs = (DWORD)fs->csize * SS(fs); /* Cluster size (byte) */ - if (ifptr > 0 && - (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ - fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1); /* start from the current cluster */ - ofs -= fp->fptr; - clst = fp->clust; - } else { /* When seek to back cluster, */ - clst = fp->obj.sclust; /* start from the first cluster */ -#if !FF_FS_READONLY - if (clst == 0) { /* If no cluster chain, create a new chain */ - clst = create_chain(&fp->obj, 0); - if (clst == 1) ABORT(fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); - fp->obj.sclust = clst; - } -#endif - fp->clust = clst; - } - if (clst != 0) { - while (ofs > bcs) { /* Cluster following loop */ - ofs -= bcs; fp->fptr += bcs; -#if !FF_FS_READONLY - if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ - if (FF_FS_EXFAT && fp->fptr > fp->obj.objsize) { /* No FAT chain object needs correct objsize to generate FAT value */ - fp->obj.objsize = fp->fptr; - fp->flag |= FA_MODIFIED; - } - clst = create_chain(&fp->obj, clst); /* Follow chain with forceed stretch */ - if (clst == 0) { /* Clip file size in case of disk full */ - ofs = 0; break; - } - } else -#endif - { - clst = get_fat(&fp->obj, clst); /* Follow cluster chain if not in write mode */ - } - if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); - if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR); - fp->clust = clst; - } - fp->fptr += ofs; - if (ofs % SS(fs)) { - nsect = clst2sect(fs, clst); /* Current sector */ - if (nsect == 0) ABORT(fs, FR_INT_ERR); - nsect += (DWORD)(ofs / SS(fs)); - } - } - } - if (!FF_FS_READONLY && fp->fptr > fp->obj.objsize) { /* Set file change flag if the file size is extended */ - fp->obj.objsize = fp->fptr; - fp->flag |= FA_MODIFIED; - } - if (fp->fptr % SS(fs) && nsect != fp->sect) { /* Fill sector cache if needed */ -#if !FF_FS_TINY -#if !FF_FS_READONLY - if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA_DIRTY; - } -#endif - if (disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ -#endif - fp->sect = nsect; - } - } - - LEAVE_FF(fs, res); -} - - - -#ifdef FF_FASTFS -#if FF_USE_FASTSEEK -/*-----------------------------------------------------------------------*/ -/* Seek File Read/Write Pointer */ -/*-----------------------------------------------------------------------*/ - -DWORD *f_expand_cltbl ( - FIL* fp, /* Pointer to the file object */ - UINT tblsz, /* Size of table */ - DWORD *tbl, /* Table pointer */ - FSIZE_t ofs /* File pointer from top of file */ -) -{ - if (fp->flag & FA_WRITE) f_lseek(fp, ofs); /* Expand file if write is enabled */ - fp->cltbl = (DWORD *)tbl; - fp->cltbl[0] = tblsz; - if (f_lseek(fp, CREATE_LINKMAP)) { /* Create cluster link table */ - fp->cltbl = (void *)0; - EFSPRINTF("CLTBLSZ"); - return (void *)0; - } - f_lseek(fp, 0); - - return fp->cltbl; -} -#endif -#endif - - - - -#if FF_FS_MINIMIZE <= 1 -/*-----------------------------------------------------------------------*/ -/* Create a Directory Object */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_opendir ( - DIR* dp, /* Pointer to directory object to create */ - const TCHAR* path /* Pointer to the directory path */ -) -{ - FRESULT res; - FATFS *fs; - DEF_NAMBUF - - - if (!dp) return FR_INVALID_OBJECT; - - /* Get logical drive */ - res = find_volume(&path, &fs, 0); - if (res == FR_OK) { - dp->obj.fs = fs; - INIT_NAMBUF(fs); - res = follow_path(dp, path); /* Follow the path to the directory */ - if (res == FR_OK) { /* Follow completed */ - if (!(dp->fn[NSFLAG] & NS_NONAME)) { /* It is not the origin directory itself */ - if (dp->obj.attr & AM_DIR) { /* This object is a sub-directory */ -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - dp->obj.c_scl = dp->obj.sclust; /* Get containing directory inforamation */ - dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; - dp->obj.c_ofs = dp->blk_ofs; - init_alloc_info(fs, &dp->obj); /* Get object allocation info */ - } else -#endif - { - dp->obj.sclust = ld_clust(fs, dp->dir); /* Get object allocation info */ - } - } else { /* This object is a file */ - res = FR_NO_PATH; - } - } - if (res == FR_OK) { - dp->obj.id = fs->id; - res = dir_sdi(dp, 0); /* Rewind directory */ -#if FF_FS_LOCK != 0 - if (res == FR_OK) { - if (dp->obj.sclust != 0) { - dp->obj.lockid = inc_lock(dp, 0); /* Lock the sub directory */ - if (!dp->obj.lockid) res = FR_TOO_MANY_OPEN_FILES; - } else { - dp->obj.lockid = 0; /* Root directory need not to be locked */ - } - } -#endif - } - } - FREE_NAMBUF(); - if (res == FR_NO_FILE) res = FR_NO_PATH; - } - if (res != FR_OK) dp->obj.fs = 0; /* Invalidate the directory object if function faild */ - - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Close Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_closedir ( - DIR *dp /* Pointer to the directory object to be closed */ -) -{ - FRESULT res; - FATFS *fs; - - - res = validate(&dp->obj, &fs); /* Check validity of the file object */ - if (res == FR_OK) { -#if FF_FS_LOCK != 0 - if (dp->obj.lockid) res = dec_lock(dp->obj.lockid); /* Decrement sub-directory open counter */ - if (res == FR_OK) dp->obj.fs = 0; /* Invalidate directory object */ -#else - dp->obj.fs = 0; /* Invalidate directory object */ -#endif -#if FF_FS_REENTRANT - unlock_fs(fs, FR_OK); /* Unlock volume */ -#endif - } - return res; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Read Directory Entries in Sequence */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_readdir ( - DIR* dp, /* Pointer to the open directory object */ - FILINFO* fno /* Pointer to file information to return */ -) -{ - FRESULT res; - FATFS *fs; - DEF_NAMBUF - - - res = validate(&dp->obj, &fs); /* Check validity of the directory object */ - if (res == FR_OK) { - if (!fno) { - res = dir_sdi(dp, 0); /* Rewind the directory object */ - } else { - INIT_NAMBUF(fs); - res = DIR_READ_FILE(dp); /* Read an item */ - if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */ - if (res == FR_OK) { /* A valid entry is found */ - get_fileinfo(dp, fno); /* Get the object information */ - res = dir_next(dp, 0); /* Increment index for next */ - if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory now */ - } - FREE_NAMBUF(); - } - } - LEAVE_FF(fs, res); -} - - - -#if FF_USE_FIND -/*-----------------------------------------------------------------------*/ -/* Find Next File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_findnext ( - DIR* dp, /* Pointer to the open directory object */ - FILINFO* fno /* Pointer to the file information structure */ -) -{ - FRESULT res; - - - for (;;) { - res = f_readdir(dp, fno); /* Get a directory item */ - if (res != FR_OK || !fno || !fno->fname[0]) break; /* Terminate if any error or end of directory */ - if (pattern_matching(dp->pat, fno->fname, 0, 0)) break; /* Test for the file name */ -#if FF_USE_LFN && FF_USE_FIND == 2 - if (pattern_matching(dp->pat, fno->altname, 0, 0)) break; /* Test for alternative name if exist */ -#endif - } - return res; -} - - - -/*-----------------------------------------------------------------------*/ -/* Find First File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_findfirst ( - DIR* dp, /* Pointer to the blank directory object */ - FILINFO* fno, /* Pointer to the file information structure */ - const TCHAR* path, /* Pointer to the directory to open */ - const TCHAR* pattern /* Pointer to the matching pattern */ -) -{ - FRESULT res; - - - dp->pat = pattern; /* Save pointer to pattern string */ - res = f_opendir(dp, path); /* Open the target directory */ - if (res == FR_OK) { - res = f_findnext(dp, fno); /* Find the first item */ - } - return res; -} - -#endif /* FF_USE_FIND */ - - - -#if FF_FS_MINIMIZE == 0 -/*-----------------------------------------------------------------------*/ -/* Get File Status */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_stat ( - const TCHAR* path, /* Pointer to the file path */ - FILINFO* fno /* Pointer to file information to return */ -) -{ - FRESULT res; - DIR dj; - DEF_NAMBUF - - - /* Get logical drive */ - res = find_volume(&path, &dj.obj.fs, 0); - if (res == FR_OK) { - INIT_NAMBUF(dj.obj.fs); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) { /* Follow completed */ - if (dj.fn[NSFLAG] & NS_NONAME) { /* It is origin directory */ - res = FR_INVALID_NAME; - } else { /* Found an object */ - if (fno) get_fileinfo(&dj, fno); - } - } - FREE_NAMBUF(); - } - - LEAVE_FF(dj.obj.fs, res); -} - - - -#if !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Get Number of Free Clusters */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_getfree ( - const TCHAR* path, /* Logical drive number */ - DWORD* nclst, /* Pointer to a variable to return number of free clusters */ - FATFS** fatfs /* Pointer to return pointer to corresponding filesystem object */ -) -{ - FRESULT res; - FATFS *fs; - DWORD nfree, clst, sect, stat; - UINT i; - FFOBJID obj; - - - /* Get logical drive */ - res = find_volume(&path, &fs, 0); - if (res == FR_OK) { - if (fatfs) *fatfs = fs; /* Return ptr to the fs object */ - /* If free_clst is valid, return it without full FAT scan */ - if (fs->free_clst <= fs->n_fatent - 2) { - *nclst = fs->free_clst; - } else { - /* Scan FAT to obtain number of free clusters */ - nfree = 0; - if (fs->fs_type == FS_FAT12) { /* FAT12: Scan bit field FAT entries */ - clst = 2; obj.fs = fs; - do { - stat = get_fat(&obj, clst); - if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } - if (stat == 1) { res = FR_INT_ERR; break; } - if (stat == 0) nfree++; - } while (++clst < fs->n_fatent); - } else { -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* exFAT: Scan allocation bitmap */ - BYTE bm; - UINT b; - - clst = fs->n_fatent - 2; /* Number of clusters */ - sect = fs->bitbase; /* Bitmap sector */ - i = 0; /* Offset in the sector */ - do { /* Counts numbuer of bits with zero in the bitmap */ - if (i == 0) { - res = move_window(fs, sect++); - if (res != FR_OK) break; - } - for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) { - if (!(bm & 1)) nfree++; - bm >>= 1; - } - i = (i + 1) % SS(fs); - } while (clst); - } else -#endif - { /* FAT16/32: Scan WORD/DWORD FAT entries */ - clst = fs->n_fatent; /* Number of entries */ - sect = fs->fatbase; /* Top of the FAT */ - i = 0; /* Offset in the sector */ - do { /* Counts numbuer of entries with zero in the FAT */ - if (i == 0) { - res = move_window(fs, sect++); - if (res != FR_OK) break; - } - if (fs->fs_type == FS_FAT16) { - if (ld_word(fs->win + i) == 0) nfree++; - i += 2; - } else { - if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++; - i += 4; - } - i %= SS(fs); - } while (--clst); - } - } - *nclst = nfree; /* Return the free clusters */ - fs->free_clst = nfree; /* Now free_clst is valid */ - fs->fsi_flag |= 1; /* FAT32: FSInfo is to be updated */ - } - } - - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Truncate File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_truncate ( - FIL* fp /* Pointer to the file object */ -) -{ - FRESULT res; - FATFS *fs; - DWORD ncl; - - - res = validate(&fp->obj, &fs); /* Check validity of the file object */ - if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); - if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ - - if (fp->fptr < fp->obj.objsize) { /* Process when fptr is not on the eof */ - if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ - res = remove_chain(&fp->obj, fp->obj.sclust, 0); - fp->obj.sclust = 0; - } else { /* When truncate a part of the file, remove remaining clusters */ - ncl = get_fat(&fp->obj, fp->clust); - res = FR_OK; - if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (ncl == 1) res = FR_INT_ERR; - if (res == FR_OK && ncl < fs->n_fatent) { - res = remove_chain(&fp->obj, ncl, fp->clust); - } - } - fp->obj.objsize = fp->fptr; /* Set file size to current read/write point */ - fp->flag |= FA_MODIFIED; -#if !FF_FS_TINY - if (res == FR_OK && (fp->flag & FA_DIRTY)) { - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) { - res = FR_DISK_ERR; - } else { - fp->flag &= (BYTE)~FA_DIRTY; - } - } -#endif - if (res != FR_OK) ABORT(fs, res); - } - - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Delete a File/Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_unlink ( - const TCHAR* path /* Pointer to the file or directory path */ -) -{ - FRESULT res; - DIR dj, sdj; - DWORD dclst = 0; - FATFS *fs; -#if FF_FS_EXFAT - FFOBJID obj; -#endif - DEF_NAMBUF - - - /* Get logical drive */ - res = find_volume(&path, &fs, FA_WRITE); - if (res == FR_OK) { - dj.obj.fs = fs; - INIT_NAMBUF(fs); - res = follow_path(&dj, path); /* Follow the file path */ - if (FF_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) { - res = FR_INVALID_NAME; /* Cannot remove dot entry */ - } -#if FF_FS_LOCK != 0 - if (res == FR_OK) res = chk_lock(&dj, 2); /* Check if it is an open object */ -#endif - if (res == FR_OK) { /* The object is accessible */ - if (dj.fn[NSFLAG] & NS_NONAME) { - res = FR_INVALID_NAME; /* Cannot remove the origin directory */ - } else { - if (dj.obj.attr & AM_RDO) { - res = FR_DENIED; /* Cannot remove R/O object */ - } - } - if (res == FR_OK) { -#if FF_FS_EXFAT - obj.fs = fs; - if (fs->fs_type == FS_EXFAT) { - init_alloc_info(fs, &obj); - dclst = obj.sclust; - } else -#endif - { - dclst = ld_clust(fs, dj.dir); - } - if (dj.obj.attr & AM_DIR) { /* Is it a sub-directory? */ -#if FF_FS_RPATH != 0 - if (dclst == fs->cdir) { /* Is it the current directory? */ - res = FR_DENIED; - } else -#endif - { - sdj.obj.fs = fs; /* Open the sub-directory */ - sdj.obj.sclust = dclst; -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - sdj.obj.objsize = obj.objsize; - sdj.obj.stat = obj.stat; - } -#endif - res = dir_sdi(&sdj, 0); - if (res == FR_OK) { - res = DIR_READ_FILE(&sdj); /* Test if the directory is empty */ - if (res == FR_OK) res = FR_DENIED; /* Not empty? */ - if (res == FR_NO_FILE) res = FR_OK; /* Empty? */ - } - } - } - } - if (res == FR_OK) { - res = dir_remove(&dj); /* Remove the directory entry */ - if (res == FR_OK && dclst != 0) { /* Remove the cluster chain if exist */ -#if FF_FS_EXFAT - res = remove_chain(&obj, dclst, 0); -#else - res = remove_chain(&dj.obj, dclst, 0); -#endif - } - if (res == FR_OK) res = sync_fs(fs); - } - } - FREE_NAMBUF(); - } - - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Create a Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_mkdir ( - const TCHAR* path /* Pointer to the directory path */ -) -{ - FRESULT res; - DIR dj; - FFOBJID sobj; - FATFS *fs; - DWORD dcl, pcl, tm; - DEF_NAMBUF - - - res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ - if (res == FR_OK) { - dj.obj.fs = fs; - INIT_NAMBUF(fs); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) res = FR_EXIST; /* Name collision? */ - if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) { /* Invalid name? */ - res = FR_INVALID_NAME; - } - if (res == FR_NO_FILE) { /* It is clear to create a new directory */ - sobj.fs = fs; /* New object id to create a new chain */ - dcl = create_chain(&sobj, 0); /* Allocate a cluster for the new directory */ - res = FR_OK; - if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster? */ - if (dcl == 1) res = FR_INT_ERR; /* Any insanity? */ - if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; /* Disk error? */ - tm = GET_FATTIME(); - if (res == FR_OK) { - res = dir_clear(fs, dcl); /* Clean up the new table */ - if (res == FR_OK) { - if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* Create dot entries (FAT only) */ - mem_set(fs->win + DIR_Name, ' ', 11); /* Create "." entry */ - fs->win[DIR_Name] = '.'; - fs->win[DIR_Attr] = AM_DIR; - st_dword(fs->win + DIR_ModTime, tm); - st_clust(fs, fs->win, dcl); - mem_cpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */ - fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust; - st_clust(fs, fs->win + SZDIRE, pcl); - fs->wflag = 1; - } - res = dir_register(&dj); /* Register the object to the parent directoy */ - } - } - if (res == FR_OK) { -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */ - st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */ - st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */ - st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs)); /* File size needs to be valid */ - st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs)); - fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */ - fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */ - res = store_xdir(&dj); - } else -#endif - { - st_dword(dj.dir + DIR_ModTime, tm); /* Created time */ - st_clust(fs, dj.dir, dcl); /* Table start cluster */ - dj.dir[DIR_Attr] = AM_DIR; /* Attribute */ - fs->wflag = 1; - } - if (res == FR_OK) { - res = sync_fs(fs); - } - } else { - remove_chain(&sobj, dcl, 0); /* Could not register, remove the allocated cluster */ - } - } - FREE_NAMBUF(); - } - - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Rename a File/Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_rename ( - const TCHAR* path_old, /* Pointer to the object name to be renamed */ - const TCHAR* path_new /* Pointer to the new name */ -) -{ - FRESULT res; - DIR djo, djn; - FATFS *fs; - BYTE buf[FF_FS_EXFAT ? SZDIRE * 2 : SZDIRE], *dir; - DWORD dw; - DEF_NAMBUF - - - get_ldnumber(&path_new); /* Snip the drive number of new name off */ - res = find_volume(&path_old, &fs, FA_WRITE); /* Get logical drive of the old object */ - if (res == FR_OK) { - djo.obj.fs = fs; - INIT_NAMBUF(fs); - res = follow_path(&djo, path_old); /* Check old object */ - if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check validity of name */ -#if FF_FS_LOCK != 0 - if (res == FR_OK) { - res = chk_lock(&djo, 2); - } -#endif - if (res == FR_OK) { /* Object to be renamed is found */ -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* At exFAT volume */ - BYTE nf, nn; - WORD nh; - - mem_cpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */ - mem_cpy(&djn, &djo, sizeof djo); - res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ - if (res == FR_OK) { /* Is new name already in use by any other object? */ - res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; - } - if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ - res = dir_register(&djn); /* Register the new entry */ - if (res == FR_OK) { - nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName]; - nh = ld_word(fs->dirbuf + XDIR_NameHash); - mem_cpy(fs->dirbuf, buf, SZDIRE * 2); /* Restore 85+C0 entry */ - fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn; - st_word(fs->dirbuf + XDIR_NameHash, nh); - if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ -/* Start of critical section where an interruption can cause a cross-link */ - res = store_xdir(&djn); - } - } - } else -#endif - { /* At FAT/FAT32 volume */ - mem_cpy(buf, djo.dir, SZDIRE); /* Save directory entry of the object */ - mem_cpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */ - res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ - if (res == FR_OK) { /* Is new name already in use by any other object? */ - res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; - } - if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ - res = dir_register(&djn); /* Register the new entry */ - if (res == FR_OK) { - dir = djn.dir; /* Copy directory entry of the object except name */ - mem_cpy(dir + 13, buf + 13, SZDIRE - 13); - dir[DIR_Attr] = buf[DIR_Attr]; - if (!(dir[DIR_Attr] & AM_DIR)) dir[DIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ - fs->wflag = 1; - if ((dir[DIR_Attr] & AM_DIR) && djo.obj.sclust != djn.obj.sclust) { /* Update .. entry in the sub-directory if needed */ - dw = clst2sect(fs, ld_clust(fs, dir)); - if (dw == 0) { - res = FR_INT_ERR; - } else { -/* Start of critical section where an interruption can cause a cross-link */ - res = move_window(fs, dw); - dir = fs->win + SZDIRE * 1; /* Ptr to .. entry */ - if (res == FR_OK && dir[1] == '.') { - st_clust(fs, dir, djn.obj.sclust); - fs->wflag = 1; - } - } - } - } - } - } - if (res == FR_OK) { - res = dir_remove(&djo); /* Remove old entry */ - if (res == FR_OK) { - res = sync_fs(fs); - } - } -/* End of the critical section */ - } - FREE_NAMBUF(); - } - - LEAVE_FF(fs, res); -} - -#endif /* !FF_FS_READONLY */ -#endif /* FF_FS_MINIMIZE == 0 */ -#endif /* FF_FS_MINIMIZE <= 1 */ -#endif /* FF_FS_MINIMIZE <= 2 */ - - - -#if FF_USE_CHMOD && !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Change Attribute */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_chmod ( - const TCHAR* path, /* Pointer to the file path */ - BYTE attr, /* Attribute bits */ - BYTE mask /* Attribute mask to change */ -) -{ - FRESULT res; - DIR dj; - FATFS *fs; - DEF_NAMBUF - - - res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ - if (res == FR_OK) { - dj.obj.fs = fs; - INIT_NAMBUF(fs); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ - if (res == FR_OK) { - mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - fs->dirbuf[XDIR_Attr] = (attr & mask) | (fs->dirbuf[XDIR_Attr] & (BYTE)~mask); /* Apply attribute change */ - res = store_xdir(&dj); - } else -#endif - { - dj.dir[DIR_Attr] = (attr & mask) | (dj.dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ - fs->wflag = 1; - } - if (res == FR_OK) { - res = sync_fs(fs); - } - } - FREE_NAMBUF(); - } - - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Change Timestamp */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_utime ( - const TCHAR* path, /* Pointer to the file/directory name */ - const FILINFO* fno /* Pointer to the timestamp to be set */ -) -{ - FRESULT res; - DIR dj; - FATFS *fs; - DEF_NAMBUF - - - res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ - if (res == FR_OK) { - dj.obj.fs = fs; - INIT_NAMBUF(fs); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ - if (res == FR_OK) { -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - st_dword(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); - res = store_xdir(&dj); - } else -#endif - { - st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); - fs->wflag = 1; - } - if (res == FR_OK) { - res = sync_fs(fs); - } - } - FREE_NAMBUF(); - } - - LEAVE_FF(fs, res); -} - -#endif /* FF_USE_CHMOD && !FF_FS_READONLY */ - - - -#if FF_USE_LABEL -/*-----------------------------------------------------------------------*/ -/* Get Volume Label */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_getlabel ( - const TCHAR* path, /* Logical drive number */ - TCHAR* label, /* Buffer to store the volume label */ - DWORD* vsn /* Variable to store the volume serial number */ -) -{ - FRESULT res; - DIR dj; - FATFS *fs; - UINT si, di; - WCHAR wc; - - /* Get logical drive */ - res = find_volume(&path, &fs, 0); - - /* Get volume label */ - if (res == FR_OK && label) { - dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */ - res = dir_sdi(&dj, 0); - if (res == FR_OK) { - res = DIR_READ_LABEL(&dj); /* Find a volume label entry */ - if (res == FR_OK) { -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - WCHAR hs; - - for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel]; si++) { /* Extract volume label from 83 entry */ - wc = ld_word(dj.dir + XDIR_Label + si * 2); - if (hs == 0 && IsSurrogate(wc)) { /* Is the code a surrogate? */ - hs = wc; continue; - } - wc = put_utf((DWORD)hs << 16 | wc, &label[di], 4); - if (wc == 0) { di = 0; break; } - di += wc; - hs = 0; - } - if (hs != 0) di = 0; /* Broken surrogate pair? */ - label[di] = 0; - } else -#endif - { - si = di = 0; /* Extract volume label from AM_VOL entry */ - while (si < 11) { - wc = dj.dir[si++]; -#if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode output */ - if (dbc_1st((BYTE)wc) && si < 11) wc = wc << 8 | dj.dir[si++]; /* Is it a DBC? */ - wc = ff_oem2uni(wc, CODEPAGE); /* Convert it into Unicode */ - if (wc != 0) wc = put_utf(wc, &label[di], 4); /* Put it in Unicode */ - if (wc == 0) { di = 0; break; } - di += wc; -#else /* ANSI/OEM output */ - label[di++] = (TCHAR)wc; -#endif - } - do { /* Truncate trailing spaces */ - label[di] = 0; - if (di == 0) break; - } while (label[--di] == ' '); - } - } - } - if (res == FR_NO_FILE) { /* No label entry and return nul string */ - label[0] = 0; - res = FR_OK; - } - } - - /* Get volume serial number */ - if (res == FR_OK && vsn) { - res = move_window(fs, fs->volbase); - if (res == FR_OK) { - switch (fs->fs_type) { - case FS_EXFAT: - di = BPB_VolIDEx; break; - - case FS_FAT32: - di = BS_VolID32; break; - - default: - di = BS_VolID; - } - *vsn = ld_dword(fs->win + di); - } - } - - LEAVE_FF(fs, res); -} - - - -#if !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Set Volume Label */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_setlabel ( - const TCHAR* label /* Volume label to set with heading logical drive number */ -) -{ - FRESULT res; - DIR dj; - FATFS *fs; - BYTE dirvn[22]; - UINT di; - WCHAR wc; - static const char badchr[] = "+.,;=[]/\\\"*:<>\?|\x7F"; /* [0..] for FAT, [7..] for exFAT */ -#if FF_USE_LFN - DWORD dc; -#endif - - /* Get logical drive */ - res = find_volume(&label, &fs, FA_WRITE); - if (res != FR_OK) LEAVE_FF(fs, res); - -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ - mem_set(dirvn, 0, 22); - di = 0; - while ((UINT)*label >= ' ') { /* Create volume label */ - dc = tchar2uni(&label); /* Get a Unicode character */ - if (dc >= 0x10000) { - if (dc == 0xFFFFFFFF || di >= 10) { /* Wrong surrogate or buffer overflow */ - dc = 0; - } else { - st_word(dirvn + di * 2, (WCHAR)(dc >> 16)); di++; - } - } - if (dc == 0 || chk_chr(badchr + 7, (int)dc) || di >= 11) { /* Check validity of the volume label */ - LEAVE_FF(fs, FR_INVALID_NAME); - } - st_word(dirvn + di * 2, (WCHAR)dc); di++; - } - } else -#endif - { /* On the FAT/FAT32 volume */ - mem_set(dirvn, ' ', 11); - di = 0; - while ((UINT)*label >= ' ') { /* Create volume label */ -#if FF_USE_LFN - dc = tchar2uni(&label); - wc = (dc < 0x10000) ? ff_uni2oem(ff_wtoupper(dc), CODEPAGE) : 0; -#else /* ANSI/OEM input */ - wc = (BYTE)*label++; - if (dbc_1st((BYTE)wc)) wc = dbc_2nd((BYTE)*label) ? wc << 8 | (BYTE)*label++ : 0; - if (IsLower(wc)) wc -= 0x20; /* To upper ASCII characters */ -#if FF_CODE_PAGE == 0 - if (ExCvt && wc >= 0x80) wc = ExCvt[wc - 0x80]; /* To upper extended characters (SBCS cfg) */ -#elif FF_CODE_PAGE < 900 - if (wc >= 0x80) wc = ExCvt[wc - 0x80]; /* To upper extended characters (SBCS cfg) */ -#endif -#endif - if (wc == 0 || chk_chr(badchr + 0, (int)wc) || di >= (UINT)((wc >= 0x100) ? 10 : 11)) { /* Reject invalid characters for volume label */ - LEAVE_FF(fs, FR_INVALID_NAME); - } - if (wc >= 0x100) dirvn[di++] = (BYTE)(wc >> 8); - dirvn[di++] = (BYTE)wc; - } - if (dirvn[0] == DDEM) LEAVE_FF(fs, FR_INVALID_NAME); /* Reject illegal name (heading DDEM) */ - while (di && dirvn[di - 1] == ' ') di--; /* Snip trailing spaces */ - } - - /* Set volume label */ - dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */ - res = dir_sdi(&dj, 0); - if (res == FR_OK) { - res = DIR_READ_LABEL(&dj); /* Get volume label entry */ - if (res == FR_OK) { - if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { - dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */ - mem_cpy(dj.dir + XDIR_Label, dirvn, 22); - } else { - if (di != 0) { - mem_cpy(dj.dir, dirvn, 11); /* Change the volume label */ - } else { - dj.dir[DIR_Name] = DDEM; /* Remove the volume label */ - } - } - fs->wflag = 1; - res = sync_fs(fs); - } else { /* No volume label entry or an error */ - if (res == FR_NO_FILE) { - res = FR_OK; - if (di != 0) { /* Create a volume label entry */ - res = dir_alloc(&dj, 1); /* Allocate an entry */ - if (res == FR_OK) { - mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */ - if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { - dj.dir[XDIR_Type] = ET_VLABEL; /* Create volume label entry */ - dj.dir[XDIR_NumLabel] = (BYTE)di; - mem_cpy(dj.dir + XDIR_Label, dirvn, 22); - } else { - dj.dir[DIR_Attr] = AM_VOL; /* Create volume label entry */ - mem_cpy(dj.dir, dirvn, 11); - } - fs->wflag = 1; - res = sync_fs(fs); - } - } - } - } - } - - LEAVE_FF(fs, res); -} - -#endif /* !FF_FS_READONLY */ -#endif /* FF_USE_LABEL */ - - - -#if FF_USE_EXPAND && !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Allocate a Contiguous Blocks to the File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_expand ( - FIL* fp, /* Pointer to the file object */ - FSIZE_t fsz, /* File size to be expanded to */ - BYTE opt /* Operation mode 0:Find and prepare or 1:Find and allocate */ -) -{ - FRESULT res; - FATFS *fs; - DWORD n, clst, stcl, scl, ncl, tcl, lclst; - - - res = validate(&fp->obj, &fs); /* Check validity of the file object */ - if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); - if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); -#if FF_FS_EXFAT - if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED); /* Check if in size limit */ -#endif - n = (DWORD)fs->csize * SS(fs); /* Cluster size */ - tcl = (DWORD)(fsz / n) + ((fsz & (n - 1)) ? 1 : 0); /* Number of clusters required */ - stcl = fs->last_clst; lclst = 0; - if (stcl < 2 || stcl >= fs->n_fatent) stcl = 2; - -#if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - scl = find_bitmap(fs, stcl, tcl); /* Find a contiguous cluster block */ - if (scl == 0) res = FR_DENIED; /* No contiguous cluster block was found */ - if (scl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (res == FR_OK) { /* A contiguous free area is found */ - if (opt) { /* Allocate it now */ - res = change_bitmap(fs, scl, tcl, 1); /* Mark the cluster block 'in use' */ - lclst = scl + tcl - 1; - } else { /* Set it as suggested point for next allocation */ - lclst = scl - 1; - } - } - } else -#endif - { - scl = clst = stcl; ncl = 0; - for (;;) { /* Find a contiguous cluster block */ - n = get_fat(&fp->obj, clst); - if (++clst >= fs->n_fatent) clst = 2; - if (n == 1) { res = FR_INT_ERR; break; } - if (n == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } - if (n == 0) { /* Is it a free cluster? */ - if (++ncl == tcl) break; /* Break if a contiguous cluster block is found */ - } else { - scl = clst; ncl = 0; /* Not a free cluster */ - } - if (clst == stcl) { res = FR_DENIED; break; } /* No contiguous cluster? */ - } - if (res == FR_OK) { /* A contiguous free area is found */ - if (opt) { /* Allocate it now */ - for (clst = scl, n = tcl; n; clst++, n--) { /* Create a cluster chain on the FAT */ - res = put_fat(fs, clst, (n == 1) ? 0xFFFFFFFF : clst + 1); - if (res != FR_OK) break; - lclst = clst; - } - } else { /* Set it as suggested point for next allocation */ - lclst = scl - 1; - } - } - } - - if (res == FR_OK) { - fs->last_clst = lclst; /* Set suggested start cluster to start next */ - if (opt) { /* Is it allocated now? */ - fp->obj.sclust = scl; /* Update object allocation information */ - fp->obj.objsize = fsz; - if (FF_FS_EXFAT) fp->obj.stat = 2; /* Set status 'contiguous chain' */ - fp->flag |= FA_MODIFIED; - if (fs->free_clst <= fs->n_fatent - 2) { /* Update FSINFO */ - fs->free_clst -= tcl; - fs->fsi_flag |= 1; - } - } - } - - LEAVE_FF(fs, res); -} - -#endif /* FF_USE_EXPAND && !FF_FS_READONLY */ - - - -#if FF_USE_FORWARD -/*-----------------------------------------------------------------------*/ -/* Forward Data to the Stream Directly */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_forward ( - FIL* fp, /* Pointer to the file object */ - UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ - UINT btf, /* Number of bytes to forward */ - UINT* bf /* Pointer to number of bytes forwarded */ -) -{ - FRESULT res; - FATFS *fs; - DWORD clst, sect; - FSIZE_t remain; - UINT rcnt, csect; - BYTE *dbuf; - - - *bf = 0; /* Clear transfer byte counter */ - res = validate(&fp->obj, &fs); /* Check validity of the file object */ - if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); - if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ - - remain = fp->obj.objsize - fp->fptr; - if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */ - - for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream goes busy */ - fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) { - csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ - if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ - if (csect == 0) { /* On the cluster boundary? */ - clst = (fp->fptr == 0) ? /* On the top of the file? */ - fp->obj.sclust : get_fat(&fp->obj, fp->clust); - if (clst <= 1) ABORT(fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); - fp->clust = clst; /* Update current cluster */ - } - } - sect = clst2sect(fs, fp->clust); /* Get current data sector */ - if (sect == 0) ABORT(fs, FR_INT_ERR); - sect += csect; -#if FF_FS_TINY - if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window to the file data */ - dbuf = fs->win; -#else - if (fp->sect != sect) { /* Fill sector cache with file data */ -#if !FF_FS_READONLY - if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA_DIRTY; - } -#endif - if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); - } - dbuf = fp->buf; -#endif - fp->sect = sect; - rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ - if (rcnt > btf) rcnt = btf; /* Clip it by btr if needed */ - rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt); /* Forward the file data */ - if (rcnt == 0) ABORT(fs, FR_INT_ERR); - } - - LEAVE_FF(fs, FR_OK); -} -#endif /* FF_USE_FORWARD */ - - - -#if FF_USE_MKFS && !FF_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Create an FAT/exFAT volume */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_mkfs ( - const TCHAR* path, /* Logical drive number */ - BYTE opt, /* Format option */ - DWORD au, /* Size of allocation unit (cluster) [byte] */ - void* work, /* Pointer to working buffer (null: use heap memory) */ - UINT len /* Size of working buffer [byte] */ -) -{ - const UINT n_fats = 1; /* Number of FATs for FAT/FAT32 volume (1 or 2) */ - const UINT n_rootdir = 512; /* Number of root directory entries for FAT volume */ - static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT volume (4Ks unit) */ - static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */ - BYTE fmt, sys, *buf, *pte, pdrv, part; - WORD ss; /* Sector size */ - DWORD szb_buf, sz_buf, sz_blk, n_clst, pau, sect, nsect, n; - DWORD b_vol, b_fat, b_data; /* Base LBA for volume, fat, data */ - DWORD sz_vol, sz_rsv, sz_fat, sz_dir; /* Size for volume, fat, dir, data */ - UINT i; - int vol; - DSTATUS stat; -#if FF_USE_TRIM || FF_FS_EXFAT - DWORD tbl[3]; -#endif - - - /* Check mounted drive and clear work area */ - vol = get_ldnumber(&path); /* Get target logical drive */ - if (vol < 0) return FR_INVALID_DRIVE; - if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear the volume if mounted */ - pdrv = LD2PD(vol); /* Physical drive */ - part = LD2PT(vol); /* Partition (0:create as new, 1-4:get from partition table) */ - - /* Check physical drive status */ - stat = disk_initialize(pdrv); - if (stat & STA_NOINIT) return FR_NOT_READY; - if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; - if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1; /* Erase block to align data area */ -#if FF_MAX_SS != FF_MIN_SS /* Get sector size of the medium if variable sector size cfg. */ - if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; - if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; -#else - ss = FF_MAX_SS; -#endif - if ((au != 0 && au < ss) || au > 0x1000000 || (au & (au - 1))) return FR_INVALID_PARAMETER; /* Check if au is valid */ - au /= ss; /* Cluster size in unit of sector */ - - /* Get working buffer */ -#if FF_USE_LFN == 3 - if (!work) { /* Use heap memory for working buffer */ - for (szb_buf = MAX_MALLOC, buf = 0; szb_buf >= ss && (buf = ff_memalloc(szb_buf)) == 0; szb_buf /= 2) ; - sz_buf = szb_buf / ss; /* Size of working buffer (sector) */ - } else -#endif - { - buf = (BYTE*)work; /* Working buffer */ - sz_buf = len / ss; /* Size of working buffer (sector) */ - szb_buf = sz_buf * ss; /* Size of working buffer (byte) */ - } - if (!buf || sz_buf == 0) return FR_NOT_ENOUGH_CORE; - - /* Determine where the volume to be located (b_vol, sz_vol) */ - if (FF_MULTI_PARTITION && part != 0) { - /* Get partition information from partition table in the MBR */ - if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */ - if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if MBR is valid */ - pte = buf + (MBR_Table + (part - 1) * SZ_PTE); - if (pte[PTE_System] == 0) LEAVE_MKFS(FR_MKFS_ABORTED); /* No partition? */ - b_vol = ld_dword(pte + PTE_StLba); /* Get volume start sector */ - sz_vol = ld_dword(pte + PTE_SizLba); /* Get volume size */ - } else { - /* Create a single-partition in this function */ - if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - b_vol = (opt & FM_SFD) ? 0 : 63; /* Volume start sector */ - if (sz_vol < b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); - sz_vol -= b_vol; /* Volume size */ - } - if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >=128s */ - - /* Pre-determine the FAT type */ - do { - if (FF_FS_EXFAT && (opt & FM_EXFAT)) { /* exFAT possible? */ - if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au > 128) { /* exFAT only, vol >= 64Ms or au > 128s ? */ - fmt = FS_EXFAT; break; - } - } - if (au > 128) LEAVE_MKFS(FR_INVALID_PARAMETER); /* Too large au for FAT/FAT32 */ - if (opt & FM_FAT32) { /* FAT32 possible? */ - if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) { /* FAT32 only or no-FAT? */ - fmt = FS_FAT32; break; - } - } - if (!(opt & FM_FAT)) LEAVE_MKFS(FR_INVALID_PARAMETER); /* no-FAT? */ - fmt = FS_FAT16; - } while (0); - -#if FF_FS_EXFAT - if (fmt == FS_EXFAT) { /* Create an exFAT volume */ - DWORD szb_bit, szb_case, sum, nb, cl; - WCHAR ch, si; - UINT j, st; - BYTE b; - - if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ -#if FF_USE_TRIM - tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area may be erased */ - disk_ioctl(pdrv, CTRL_TRIM, tbl); -#endif - /* Determine FAT location, data location and number of clusters */ - if (au == 0) { /* au auto-selection */ - au = 8; - if (sz_vol >= 0x80000) au = 64; /* >= 512Ks */ - if (sz_vol >= 0x4000000) au = 256; /* >= 64Ms */ - } - b_fat = b_vol + 32; /* FAT start at offset 32 */ - sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */ - b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */ - if (b_data - b_vol >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ - n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */ - if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */ - if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */ - - szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */ - tbl[0] = (szb_bit + au * ss - 1) / (au * ss); /* Number of allocation bitmap clusters */ - - /* Create a compressed up-case table */ - sect = b_data + au * tbl[0]; /* Table start sector */ - sum = 0; /* Table checksum to be stored in the 82 entry */ - st = 0; si = 0; i = 0; j = 0; szb_case = 0; - do { - switch (st) { - case 0: - ch = (WCHAR)ff_wtoupper(si); /* Get an up-case char */ - if (ch != si) { - si++; break; /* Store the up-case char if exist */ - } - for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ; /* Get run length of no-case block */ - if (j >= 128) { - ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 */ - } - st = 1; /* Do not compress short run */ - /* go to next case */ - case 1: - ch = si++; /* Fill the short run */ - if (--j == 0) st = 0; - break; - - default: - ch = (WCHAR)j; si += (WCHAR)j; /* Number of chars to skip */ - st = 0; - } - sum = xsum32(buf[i + 0] = (BYTE)ch, sum); /* Put it into the write buffer */ - sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum); - i += 2; szb_case += 2; - if (si == 0 || i == szb_buf) { /* Write buffered data when buffer full or end of process */ - n = (i + ss - 1) / ss; - if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - sect += n; i = 0; - } - } while (si); - tbl[1] = (szb_case + au * ss - 1) / (au * ss); /* Number of up-case table clusters */ - tbl[2] = 1; /* Number of root dir clusters */ - - /* Initialize the allocation bitmap */ - sect = b_data; nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of sectors */ - nb = tbl[0] + tbl[1] + tbl[2]; /* Number of clusters in-use by system */ - do { - mem_set(buf, 0, szb_buf); - for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ; - for (b = 1; nb != 0 && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ; - n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ - if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - sect += n; nsect -= n; - } while (nsect); - - /* Initialize the FAT */ - sect = b_fat; nsect = sz_fat; /* Start of FAT and number of FAT sectors */ - j = nb = cl = 0; - do { - mem_set(buf, 0, szb_buf); i = 0; /* Clear work area and reset write index */ - if (cl == 0) { /* Set entry 0 and 1 */ - st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++; - st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++; - } - do { /* Create chains of bitmap, up-case and root dir */ - while (nb != 0 && i < szb_buf) { /* Create a chain */ - st_dword(buf + i, (nb > 1) ? cl + 1 : 0xFFFFFFFF); - i += 4; cl++; nb--; - } - if (nb == 0 && j < 3) nb = tbl[j++]; /* Next chain */ - } while (nb != 0 && i < szb_buf); - n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ - if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - sect += n; nsect -= n; - } while (nsect); - - /* Initialize the root directory */ - mem_set(buf, 0, szb_buf); - buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry */ - buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */ - st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */ - st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */ - buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */ - st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */ - st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */ - st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */ - sect = b_data + au * (tbl[0] + tbl[1]); nsect = au; /* Start of the root directory and number of sectors */ - do { /* Fill root directory sectors */ - n = (nsect > sz_buf) ? sz_buf : nsect; - if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - mem_set(buf, 0, ss); - sect += n; nsect -= n; - } while (nsect); - - /* Create two set of the exFAT VBR blocks */ - sect = b_vol; - for (n = 0; n < 2; n++) { - /* Main record (+0) */ - mem_set(buf, 0, ss); - mem_cpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11); /* Boot jump code (x86), OEM name */ - st_dword(buf + BPB_VolOfsEx, b_vol); /* Volume offset in the physical drive [sector] */ - st_dword(buf + BPB_TotSecEx, sz_vol); /* Volume size [sector] */ - st_dword(buf + BPB_FatOfsEx, b_fat - b_vol); /* FAT offset [sector] */ - st_dword(buf + BPB_FatSzEx, sz_fat); /* FAT size [sector] */ - st_dword(buf + BPB_DataOfsEx, b_data - b_vol); /* Data offset [sector] */ - st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */ - st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]); /* Root dir cluster # */ - st_dword(buf + BPB_VolIDEx, GET_FATTIME()); /* VSN */ - st_word(buf + BPB_FSVerEx, 0x100); /* Filesystem version (1.00) */ - for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */ - for (buf[BPB_SecPerClusEx] = 0, i = au; i >>= 1; buf[BPB_SecPerClusEx]++) ; /* Log2 of cluster size [sector] */ - buf[BPB_NumFATsEx] = 1; /* Number of FATs */ - buf[BPB_DrvNumEx] = 0x80; /* Drive number (for int13) */ - st_word(buf + BS_BootCodeEx, 0xFEEB); /* Boot code (x86) */ - st_word(buf + BS_55AA, 0xAA55); /* Signature (placed here regardless of sector size) */ - for (i = sum = 0; i < ss; i++) { /* VBR checksum */ - if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum); - } - if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - /* Extended bootstrap record (+1..+8) */ - mem_set(buf, 0, ss); - st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */ - for (j = 1; j < 9; j++) { - for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ - if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - } - /* OEM/Reserved record (+9..+10) */ - mem_set(buf, 0, ss); - for ( ; j < 11; j++) { - for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ - if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - } - /* Sum record (+11) */ - for (i = 0; i < ss; i += 4) st_dword(buf + i, sum); /* Fill with checksum value */ - if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - } - - } else -#endif /* FF_FS_EXFAT */ - { /* Create an FAT/FAT32 volume */ - do { - pau = au; - /* Pre-determine number of clusters and FAT sub-type */ - if (fmt == FS_FAT32) { /* FAT32 volume */ - if (pau == 0) { /* au auto-selection */ - n = sz_vol / 0x20000; /* Volume size in unit of 128KS */ - for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ; /* Get from table */ - } - n_clst = sz_vol / pau; /* Number of clusters */ - sz_fat = (n_clst * 4 + 8 + ss - 1) / ss; /* FAT size [sector] */ - sz_rsv = 32; /* Number of reserved sectors */ - sz_dir = 0; /* No static directory */ - if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) LEAVE_MKFS(FR_MKFS_ABORTED); - } else { /* FAT volume */ - if (pau == 0) { /* au auto-selection */ - n = sz_vol / 0x1000; /* Volume size in unit of 4KS */ - for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ; /* Get from table */ - } - n_clst = sz_vol / pau; - if (n_clst > MAX_FAT12) { - n = n_clst * 2 + 4; /* FAT size [byte] */ - } else { - fmt = FS_FAT12; - n = (n_clst * 3 + 1) / 2 + 3; /* FAT size [byte] */ - } - sz_fat = (n + ss - 1) / ss; /* FAT size [sector] */ - sz_rsv = 1; /* Number of reserved sectors */ - sz_dir = (DWORD)n_rootdir * SZDIRE / ss; /* Rootdir size [sector] */ - } - b_fat = b_vol + sz_rsv; /* FAT base */ - b_data = b_fat + sz_fat * n_fats + sz_dir; /* Data base */ - - /* Align data base to erase block boundary (for flash memory media) */ - n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data; /* Next nearest erase block from current data base */ - if (fmt == FS_FAT32) { /* FAT32: Move FAT base */ - sz_rsv += n; b_fat += n; - } else { /* FAT: Expand FAT size */ - sz_fat += n / n_fats; - } - - /* Determine number of clusters and final check of validity of the FAT sub-type */ - if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume */ - n_clst = (sz_vol - sz_rsv - sz_fat * n_fats - sz_dir) / pau; - if (fmt == FS_FAT32) { - if (n_clst <= MAX_FAT16) { /* Too few clusters for FAT32 */ - if (au == 0 && (au = pau / 2) != 0) continue; /* Adjust cluster size and retry */ - LEAVE_MKFS(FR_MKFS_ABORTED); - } - } - if (fmt == FS_FAT16) { - if (n_clst > MAX_FAT16) { /* Too many clusters for FAT16 */ - if (au == 0 && (pau * 2) <= 64) { - au = pau * 2; continue; /* Adjust cluster size and retry */ - } - if ((opt & FM_FAT32)) { - fmt = FS_FAT32; continue; /* Switch type to FAT32 and retry */ - } - if (au == 0 && (au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ - LEAVE_MKFS(FR_MKFS_ABORTED); - } - if (n_clst <= MAX_FAT12) { /* Too few clusters for FAT16 */ - if (au == 0 && (au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ - LEAVE_MKFS(FR_MKFS_ABORTED); - } - } - if (fmt == FS_FAT12 && n_clst > MAX_FAT12) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters for FAT12 */ - - /* Ok, it is the valid cluster configuration */ - break; - } while (1); - -#if FF_USE_TRIM - tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area can be erased */ - disk_ioctl(pdrv, CTRL_TRIM, tbl); -#endif - /* Create FAT VBR */ - mem_set(buf, 0, ss); - mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */ - st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ - buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ - st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ - buf[BPB_NumFATs] = (BYTE)n_fats; /* Number of FATs */ - st_word(buf + BPB_RootEntCnt, (WORD)((fmt == FS_FAT32) ? 0 : n_rootdir)); /* Number of root directory entries */ - if (sz_vol < 0x10000) { - st_word(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */ - } else { - st_dword(buf + BPB_TotSec32, sz_vol); /* Volume size in 32-bit LBA */ - } - buf[BPB_Media] = 0xF8; /* Media descriptor byte */ - st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ - st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ - st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */ - if (fmt == FS_FAT32) { - st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */ - st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ - st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ - st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ - st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ - buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ - buf[BS_BootSig32] = 0x29; /* Extended boot signature */ - mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ - } else { - st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */ - st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ - buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ - buf[BS_BootSig] = 0x29; /* Extended boot signature */ - mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ - } - st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ - if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */ - - /* Create FSINFO record if needed */ - if (fmt == FS_FAT32) { - disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */ - mem_set(buf, 0, ss); - st_dword(buf + FSI_LeadSig, 0x41615252); - st_dword(buf + FSI_StrucSig, 0x61417272); - st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */ - st_dword(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */ - st_word(buf + BS_55AA, 0xAA55); - disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */ - disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ - } - - /* Initialize FAT area */ - mem_set(buf, 0, (UINT)szb_buf); - sect = b_fat; /* FAT start sector */ - for (i = 0; i < n_fats; i++) { /* Initialize FATs each */ - if (fmt == FS_FAT32) { - st_dword(buf + 0, 0xFFFFFFF8); /* Entry 0 */ - st_dword(buf + 4, 0xFFFFFFFF); /* Entry 1 */ - st_dword(buf + 8, 0x0FFFFFFF); /* Entry 2 (root directory) */ - } else { - st_dword(buf + 0, (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8); /* Entry 0 and 1 */ - } - nsect = sz_fat; /* Number of FAT sectors */ - do { /* Fill FAT sectors */ - n = (nsect > sz_buf) ? sz_buf : nsect; - if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - mem_set(buf, 0, ss); - sect += n; nsect -= n; - } while (nsect); - } - - /* Initialize root directory (fill with zero) */ - nsect = (fmt == FS_FAT32) ? pau : sz_dir; /* Number of root directory sectors */ - do { - n = (nsect > sz_buf) ? sz_buf : nsect; - if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - sect += n; nsect -= n; - } while (nsect); - } - - /* Determine system ID in the partition table */ - if (FF_FS_EXFAT && fmt == FS_EXFAT) { - sys = 0x07; /* HPFS/NTFS/exFAT */ - } else { - if (fmt == FS_FAT32) { - sys = 0x0C; /* FAT32X */ - } else { - if (sz_vol >= 0x10000) { - sys = 0x06; /* FAT12/16 (large) */ - } else { - sys = (fmt == FS_FAT16) ? 0x04 : 0x01; /* FAT16 : FAT12 */ - } - } - } - - /* Update partition information */ - if (FF_MULTI_PARTITION && part != 0) { /* Created in the existing partition */ - /* Update system ID in the partition table */ - if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */ - buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */ - if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it back to the MBR */ - } else { /* Created as a new single partition */ - if (!(opt & FM_SFD)) { /* Create partition table if in FDISK format */ - mem_set(buf, 0, ss); - st_word(buf + BS_55AA, 0xAA55); /* MBR signature */ - pte = buf + MBR_Table; /* Create partition table for single partition in the drive */ - pte[PTE_Boot] = 0; /* Boot indicator */ - pte[PTE_StHead] = 1; /* Start head */ - pte[PTE_StSec] = 1; /* Start sector */ - pte[PTE_StCyl] = 0; /* Start cylinder */ - pte[PTE_System] = sys; /* System type */ - n = (b_vol + sz_vol) / (63 * 255); /* (End CHS may be invalid) */ - pte[PTE_EdHead] = 254; /* End head */ - pte[PTE_EdSec] = (BYTE)(((n >> 2) & 0xC0) | 63); /* End sector */ - pte[PTE_EdCyl] = (BYTE)n; /* End cylinder */ - st_dword(pte + PTE_StLba, b_vol); /* Start offset in LBA */ - st_dword(pte + PTE_SizLba, sz_vol); /* Size in sectors */ - if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the MBR */ - } - } - - if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); - - LEAVE_MKFS(FR_OK); -} - - - -#if FF_MULTI_PARTITION -/*-----------------------------------------------------------------------*/ -/* Create Partition Table on the Physical Drive */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_fdisk ( - BYTE pdrv, /* Physical drive number */ - const DWORD* szt, /* Pointer to the size table for each partitions */ - void* work /* Pointer to the working buffer (null: use heap memory) */ -) -{ - UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; - BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; - DSTATUS stat; - DWORD sz_disk, sz_part, s_part; - FRESULT res; - - - stat = disk_initialize(pdrv); - if (stat & STA_NOINIT) return FR_NOT_READY; - if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; - if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; - - buf = (BYTE*)work; -#if FF_USE_LFN == 3 - if (!buf) buf = ff_memalloc(FF_MAX_SS); /* Use heap memory for working buffer */ -#endif - if (!buf) return FR_NOT_ENOUGH_CORE; - - /* Determine the CHS without any consideration of the drive geometry */ - for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; - if (n == 256) n--; - e_hd = (BYTE)(n - 1); - sz_cyl = 63 * n; - tot_cyl = sz_disk / sz_cyl; - - /* Create partition table */ - mem_set(buf, 0, FF_MAX_SS); - p = buf + MBR_Table; b_cyl = 0; - for (i = 0; i < 4; i++, p += SZ_PTE) { - p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; /* Number of cylinders */ - if (p_cyl == 0) continue; - s_part = (DWORD)sz_cyl * b_cyl; - sz_part = (DWORD)sz_cyl * p_cyl; - if (i == 0) { /* Exclude first track of cylinder 0 */ - s_hd = 1; - s_part += 63; sz_part -= 63; - } else { - s_hd = 0; - } - e_cyl = b_cyl + p_cyl - 1; /* End cylinder */ - if (e_cyl >= tot_cyl) LEAVE_MKFS(FR_INVALID_PARAMETER); - - /* Set partition table */ - p[1] = s_hd; /* Start head */ - p[2] = (BYTE)(((b_cyl >> 2) & 0xC0) | 1); /* Start sector */ - p[3] = (BYTE)b_cyl; /* Start cylinder */ - p[4] = 0x07; /* System type (temporary setting) */ - p[5] = e_hd; /* End head */ - p[6] = (BYTE)(((e_cyl >> 2) & 0xC0) | 63); /* End sector */ - p[7] = (BYTE)e_cyl; /* End cylinder */ - st_dword(p + 8, s_part); /* Start sector in LBA */ - st_dword(p + 12, sz_part); /* Number of sectors */ - - /* Next partition */ - b_cyl += p_cyl; - } - st_word(p, 0xAA55); /* MBR signature (always at offset 510) */ - - /* Write it to the MBR */ - res = (disk_write(pdrv, buf, 0, 1) == RES_OK && disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; - LEAVE_MKFS(res); -} - -#endif /* FF_MULTI_PARTITION */ -#endif /* FF_USE_MKFS && !FF_FS_READONLY */ - - - - -#if FF_USE_STRFUNC -#if FF_USE_LFN && FF_LFN_UNICODE && (FF_STRF_ENCODE < 0 || FF_STRF_ENCODE > 3) -#error Wrong FF_STRF_ENCODE setting -#endif -/*-----------------------------------------------------------------------*/ -/* Get a String from the File */ -/*-----------------------------------------------------------------------*/ - -TCHAR* f_gets ( - TCHAR* buff, /* Pointer to the string buffer to read */ - int len, /* Size of string buffer (items) */ - FIL* fp /* Pointer to the file object */ -) -{ - int nc = 0; - TCHAR *p = buff; - BYTE s[4]; - UINT rc; - DWORD dc; -#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE <= 2 - WCHAR wc; -#endif -#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE == 3 - UINT ct; -#endif - -#if FF_USE_LFN && FF_LFN_UNICODE /* With code conversion (Unicode API) */ - /* Make a room for the character and terminator */ - if (FF_LFN_UNICODE == 1) len -= (FF_STRF_ENCODE == 0) ? 1 : 2; - if (FF_LFN_UNICODE == 2) len -= (FF_STRF_ENCODE == 0) ? 3 : 4; - if (FF_LFN_UNICODE == 3) len -= 1; - while (nc < len) { -#if FF_STRF_ENCODE == 0 /* Read a character in ANSI/OEM */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; - wc = s[0]; - if (dbc_1st((BYTE)wc)) { - f_read(fp, s, 1, &rc); - if (rc != 1 || !dbc_2nd(s[0])) continue; - wc = wc << 8 | s[0]; - } - dc = ff_oem2uni(wc, CODEPAGE); - if (dc == 0) continue; -#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 /* Read a character in UTF-16LE/BE */ - f_read(fp, s, 2, &rc); - if (rc != 2) break; - dc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; - if (IsSurrogateL(dc)) continue; - if (IsSurrogateH(dc)) { - f_read(fp, s, 2, &rc); - if (rc != 2) break; - wc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; - if (!IsSurrogateL(wc)) continue; - dc = ((dc & 0x3FF) + 0x40) << 10 | (wc & 0x3FF); - } -#else /* Read a character in UTF-8 */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; - dc = s[0]; - if (dc >= 0x80) { /* Multi-byte character? */ - ct = 0; - if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; } /* 2-byte? */ - if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; } /* 3-byte? */ - if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; } /* 4-byte? */ - if (ct == 0) continue; - f_read(fp, s, ct, &rc); /* Get trailing bytes */ - if (rc != ct) break; - rc = 0; - do { /* Merge trailing bytes */ - if ((s[rc] & 0xC0) != 0x80) break; - dc = dc << 6 | (s[rc] & 0x3F); - } while (++rc < ct); - if (rc != ct || dc < 0x80 || IsSurrogate(dc) || dc >= 0x110000) continue; /* Wrong encoding? */ - } -#endif - if (FF_USE_STRFUNC == 2 && dc == '\r') continue; /* Strip \r off if needed */ -#if FF_LFN_UNICODE == 1 || FF_LFN_UNICODE == 3 /* Output it in UTF-16/32 encoding */ - if (FF_LFN_UNICODE == 1 && dc >= 0x10000) { /* Out of BMP at UTF-16? */ - *p++ = (TCHAR)(0xD800 | ((dc >> 10) - 0x40)); nc++; /* Make and output high surrogate */ - dc = 0xDC00 | (dc & 0x3FF); /* Make low surrogate */ - } - *p++ = (TCHAR)dc; nc++; - if (dc == '\n') break; /* End of line? */ -#elif FF_LFN_UNICODE == 2 /* Output it in UTF-8 encoding */ - if (dc < 0x80) { /* 1-byte */ - *p++ = (TCHAR)dc; - nc++; - if (dc == '\n') break; /* End of line? */ - } else { - if (dc < 0x800) { /* 2-byte */ - *p++ = (TCHAR)(0xC0 | (dc >> 6 & 0x1F)); - *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); - nc += 2; - } else { - if (dc < 0x10000) { /* 3-byte */ - *p++ = (TCHAR)(0xE0 | (dc >> 12 & 0x0F)); - *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F)); - *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); - nc += 3; - } else { /* 4-byte */ - *p++ = (TCHAR)(0xF0 | (dc >> 18 & 0x07)); - *p++ = (TCHAR)(0x80 | (dc >> 12 & 0x3F)); - *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F)); - *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); - nc += 4; - } - } - } -#endif - } - -#else /* Byte-by-byte without any conversion (ANSI/OEM API) */ - len -= 1; /* Make a room for the terminator */ - while (nc < len) { - f_read(fp, s, 1, &rc); - if (rc != 1) break; - dc = s[0]; - if (FF_USE_STRFUNC == 2 && dc == '\r') continue; - *p++ = (TCHAR)dc; nc++; - if (dc == '\n') break; - } -#endif - - *p = 0; /* Terminate the string */ - return nc ? buff : 0; /* When no data read due to EOF or error, return with error. */ -} - - - - -#if !FF_FS_READONLY -#include -/*-----------------------------------------------------------------------*/ -/* Put a Character to the File */ -/*-----------------------------------------------------------------------*/ - -typedef struct { /* Putchar output buffer and work area */ - FIL *fp; /* Ptr to the writing file */ - int idx, nchr; /* Write index of buf[] (-1:error), number of encoding units written */ -#if FF_USE_LFN && FF_LFN_UNICODE == 1 - WCHAR hs; -#elif FF_USE_LFN && FF_LFN_UNICODE == 2 - BYTE bs[4]; - UINT wi, ct; -#endif - BYTE buf[64]; /* Write buffer */ -} putbuff; - - -static void putc_bfd ( /* Buffered write with code conversion */ - putbuff* pb, - TCHAR c -) -{ - UINT n; - int i, nc; -#if FF_USE_LFN && FF_LFN_UNICODE - WCHAR hs, wc; -#if FF_LFN_UNICODE == 2 - DWORD dc; - TCHAR *tp; -#endif -#endif - - if (FF_USE_STRFUNC == 2 && c == '\n') { /* LF -> CRLF conversion */ - putc_bfd(pb, '\r'); - } - - i = pb->idx; /* Write index of pb->buf[] */ - if (i < 0) return; - nc = pb->nchr; /* Write unit counter */ - -#if FF_USE_LFN && FF_LFN_UNICODE -#if FF_LFN_UNICODE == 1 /* UTF-16 input */ - if (IsSurrogateH(c)) { - pb->hs = c; return; - } - hs = pb->hs; pb->hs = 0; - if (hs != 0) { - if (!IsSurrogateL(c)) hs = 0; - } else { - if (IsSurrogateL(c)) return; - } - wc = c; -#elif FF_LFN_UNICODE == 2 /* UTF-8 input */ - for (;;) { - if (pb->ct == 0) { /* Out of multi-byte sequence? */ - pb->bs[pb->wi = 0] = (BYTE)c; /* Save 1st byte */ - if ((BYTE)c < 0x80) break; /* 1-byte? */ - if (((BYTE)c & 0xE0) == 0xC0) pb->ct = 1; /* 2-byte? */ - if (((BYTE)c & 0xF0) == 0xE0) pb->ct = 2; /* 3-byte? */ - if (((BYTE)c & 0xF1) == 0xF0) pb->ct = 3; /* 4-byte? */ - return; - } else { /* In the multi-byte sequence */ - if (((BYTE)c & 0xC0) != 0x80) { /* Broken sequence? */ - pb->ct = 0; continue; - } - pb->bs[++pb->wi] = (BYTE)c; /* Save the trailing byte */ - if (--pb->ct == 0) break; /* End of multi-byte sequence? */ - return; - } - } - tp = (TCHAR*)pb->bs; - dc = tchar2uni(&tp); /* UTF-8 ==> UTF-16 */ - if (dc == 0xFFFFFFFF) return; - wc = (WCHAR)dc; - hs = (WCHAR)(dc >> 16); -#elif FF_LFN_UNICODE == 3 /* UTF-32 input */ - if (IsSurrogate(c) || c >= 0x110000) return; - if (c >= 0x10000) { - hs = (WCHAR)(0xD800 | ((c >> 10) - 0x40)); /* Make high surrogate */ - wc = 0xDC00 | (c & 0x3FF); /* Make low surrogate */ - } else { - hs = 0; - wc = (WCHAR)c; - } -#endif - -#if FF_STRF_ENCODE == 1 /* Write a character in UTF-16LE */ - if (hs != 0) { - st_word(&pb->buf[i], hs); - i += 2; - nc++; - } - st_word(&pb->buf[i], wc); - i += 2; -#elif FF_STRF_ENCODE == 2 /* Write a character in UTF-16BE */ - if (hs != 0) { - pb->buf[i++] = (BYTE)(hs >> 8); - pb->buf[i++] = (BYTE)hs; - nc++; - } - pb->buf[i++] = (BYTE)(wc >> 8); - pb->buf[i++] = (BYTE)wc; -#elif FF_STRF_ENCODE == 3 /* Write it in UTF-8 */ - if (hs != 0) { /* 4-byte */ - nc += 3; - hs = (hs & 0x3FF) + 0x40; - pb->buf[i++] = (BYTE)(0xF0 | hs >> 8); - pb->buf[i++] = (BYTE)(0x80 | (hs >> 2 & 0x3F)); - pb->buf[i++] = (BYTE)(0x80 | (hs & 3) << 4 | (wc >> 6 & 0x0F)); - pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); - } else { - if (wc < 0x80) { /* 1-byte */ - pb->buf[i++] = (BYTE)wc; - } else { - if (wc < 0x800) { /* 2-byte */ - nc += 1; - pb->buf[i++] = (BYTE)(0xC0 | wc >> 6); - } else { /* 3-byte */ - nc += 2; - pb->buf[i++] = (BYTE)(0xE0 | wc >> 12); - pb->buf[i++] = (BYTE)(0x80 | (wc >> 6 & 0x3F)); - } - pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); - } - } -#else /* Write it in ANSI/OEM */ - if (hs != 0) return; - wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */ - if (wc == 0) return; - if (wc >= 0x100) { - pb->buf[i++] = (BYTE)(wc >> 8); nc++; - } - pb->buf[i++] = (BYTE)wc; -#endif - -#else /* ANSI/OEM input (without re-encode) */ - pb->buf[i++] = (BYTE)c; -#endif - - if (i >= (int)(sizeof pb->buf) - 4) { /* Write buffered characters to the file */ - f_write(pb->fp, pb->buf, (UINT)i, &n); - i = (n == (UINT)i) ? 0 : -1; - } - pb->idx = i; - pb->nchr = nc + 1; -} - - -static int putc_flush ( /* Flush left characters in the buffer */ - putbuff* pb -) -{ - UINT nw; - - if ( pb->idx >= 0 /* Flush buffered characters to the file */ - && f_write(pb->fp, pb->buf, (UINT)pb->idx, &nw) == FR_OK - && (UINT)pb->idx == nw) return pb->nchr; - return EOF; -} - - -static void putc_init ( /* Initialize write buffer */ - putbuff* pb, - FIL* fp -) -{ - mem_set(pb, 0, sizeof (putbuff)); - pb->fp = fp; -} - - - -int f_putc ( - TCHAR c, /* A character to be output */ - FIL* fp /* Pointer to the file object */ -) -{ - putbuff pb; - - - putc_init(&pb, fp); - putc_bfd(&pb, c); /* Put the character */ - return putc_flush(&pb); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Put a String to the File */ -/*-----------------------------------------------------------------------*/ - -int f_puts ( - const TCHAR* str, /* Pointer to the string to be output */ - FIL* fp /* Pointer to the file object */ -) -{ - putbuff pb; - - - putc_init(&pb, fp); - while (*str) putc_bfd(&pb, *str++); /* Put the string */ - return putc_flush(&pb); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Put a Formatted String to the File */ -/*-----------------------------------------------------------------------*/ - -int f_printf ( - FIL* fp, /* Pointer to the file object */ - const TCHAR* fmt, /* Pointer to the format string */ - ... /* Optional arguments... */ -) -{ - va_list arp; - putbuff pb; - BYTE f, r; - UINT i, j, w; - DWORD v; - TCHAR c, d, str[32], *p; - - - putc_init(&pb, fp); - - va_start(arp, fmt); - - for (;;) { - c = *fmt++; - if (c == 0) break; /* End of string */ - if (c != '%') { /* Non escape character */ - putc_bfd(&pb, c); - continue; - } - w = f = 0; - c = *fmt++; - if (c == '0') { /* Flag: '0' padding */ - f = 1; c = *fmt++; - } else { - if (c == '-') { /* Flag: left justified */ - f = 2; c = *fmt++; - } - } - if (c == '*') { /* Minimum width by argument */ - w = va_arg(arp, int); - c = *fmt++; - } else { - while (IsDigit(c)) { /* Minimum width */ - w = w * 10 + c - '0'; - c = *fmt++; - } - } - if (c == 'l' || c == 'L') { /* Type prefix: Size is long int */ - f |= 4; c = *fmt++; - } - if (c == 0) break; - d = c; - if (IsLower(d)) d -= 0x20; - switch (d) { /* Atgument type is... */ - case 'S' : /* String */ - p = va_arg(arp, TCHAR*); - for (j = 0; p[j]; j++) ; - if (!(f & 2)) { /* Right padded */ - while (j++ < w) putc_bfd(&pb, ' ') ; - } - while (*p) putc_bfd(&pb, *p++) ; /* String body */ - while (j++ < w) putc_bfd(&pb, ' ') ; /* Left padded */ - continue; - - case 'C' : /* Character */ - putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue; - - case 'B' : /* Unsigned binary */ - r = 2; break; - - case 'O' : /* Unsigned octal */ - r = 8; break; - - case 'D' : /* Signed decimal */ - case 'U' : /* Unsigned decimal */ - r = 10; break; - - case 'X' : /* Unsigned hexdecimal */ - r = 16; break; - - default: /* Unknown type (pass-through) */ - putc_bfd(&pb, c); continue; - } - - /* Get an argument and put it in numeral */ - v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int)); - if (d == 'D' && (v & 0x80000000)) { - v = 0 - v; - f |= 8; - } - i = 0; - do { - d = (TCHAR)(v % r); v /= r; - if (d > 9) d += (c == 'x') ? 0x27 : 0x07; - str[i++] = d + '0'; - } while (v && i < sizeof str / sizeof *str); - if (f & 8) str[i++] = '-'; - j = i; d = (f & 1) ? '0' : ' '; - if (!(f & 2)) { - while (j++ < w) putc_bfd(&pb, d); /* Right pad */ - } - do { - putc_bfd(&pb, str[--i]); /* Number body */ - } while (i); - while (j++ < w) putc_bfd(&pb, d); /* Left pad */ - } - - va_end(arp); - - return putc_flush(&pb); -} - -#endif /* !FF_FS_READONLY */ -#endif /* FF_USE_STRFUNC */ - - - -#if FF_CODE_PAGE == 0 -/*-----------------------------------------------------------------------*/ -/* Set Active Codepage for the Path Name */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_setcp ( - WORD cp /* Value to be set as active code page */ -) -{ - static const WORD validcp[] = { 437, 720, 737, 771, 775, 850, 852, 857, 860, 861, 862, 863, 864, 865, 866, 869, 932, 936, 949, 950, 0}; - static const BYTE* const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0}; - UINT i; - - - for (i = 0; validcp[i] != 0 && validcp[i] != cp; i++) ; /* Find the code page */ - if (validcp[i] != cp) return FR_INVALID_PARAMETER; /* Not found? */ - - CodePage = cp; - if (cp >= 900) { /* DBCS */ - ExCvt = 0; - DbcTbl = tables[i]; - } else { /* SBCS */ - ExCvt = tables[i]; - DbcTbl = 0; - } - return FR_OK; -} -#endif /* FF_CODE_PAGE == 0 */ - diff --git a/emummc/source/libs/fatfs/ff.h b/emummc/source/libs/fatfs/ff.h deleted file mode 100644 index 68dc7ab650..0000000000 --- a/emummc/source/libs/fatfs/ff.h +++ /dev/null @@ -1,391 +0,0 @@ -/*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT Filesystem module R0.13c / -/-----------------------------------------------------------------------------/ -/ -/ Copyright (C) 2018, ChaN, all right reserved. -/ -/ FatFs module is an open source software. Redistribution and use of FatFs in -/ source and binary forms, with or without modification, are permitted provided -/ that the following condition is met: - -/ 1. Redistributions of source code must retain the above copyright notice, -/ this condition and the following disclaimer. -/ -/ This software is provided by the copyright holder and contributors "AS IS" -/ and any warranties related to this software are DISCLAIMED. -/ The copyright owner or contributors be NOT LIABLE for any damages caused -/ by use of this software. -/ -/----------------------------------------------------------------------------*/ - - -#ifndef FF_DEFINED -#define FF_DEFINED 86604 /* Revision ID */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../../utils/types.h" /* Basic integer types */ -#include "ffconf.h" /* FatFs configuration options */ - -#if FF_DEFINED != FFCONF_DEF -#error Wrong configuration file (ffconf.h). -#endif - - - -/* Definitions of volume management */ - -#if FF_MULTI_PARTITION /* Multiple partition configuration */ -typedef struct { - BYTE pd; /* Physical drive number */ - BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ -} PARTITION; -extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ -#endif - -#if FF_STR_VOLUME_ID -#ifndef FF_VOLUME_STRS -extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */ -#endif -#endif - - - -/* Type of path name strings on FatFs API */ - -#ifndef _INC_TCHAR -#define _INC_TCHAR - -#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */ -typedef WCHAR TCHAR; -#define _T(x) L ## x -#define _TEXT(x) L ## x -#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */ -typedef char TCHAR; -#define _T(x) u8 ## x -#define _TEXT(x) u8 ## x -#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */ -typedef DWORD TCHAR; -#define _T(x) U ## x -#define _TEXT(x) U ## x -#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3) -#error Wrong FF_LFN_UNICODE setting -#else /* ANSI/OEM code in SBCS/DBCS */ -typedef char TCHAR; -#define _T(x) x -#define _TEXT(x) x -#endif - -#endif - - - -/* Type of file size variables */ - -#if FF_FS_EXFAT -typedef QWORD FSIZE_t; -#else -typedef DWORD FSIZE_t; -#endif - - - -/* Filesystem object structure (FATFS) */ - -typedef struct { - BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ - BYTE fs_type; /* Filesystem type (0:not mounted) */ - BYTE pdrv; /* Associated physical drive */ - BYTE n_fats; /* Number of FATs (1 or 2) */ - BYTE wflag; /* win[] flag (b0:dirty) */ - BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ - WORD id; /* Volume mount ID */ - WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ - WORD csize; /* Cluster size [sectors] */ -#if FF_MAX_SS != FF_MIN_SS - WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ -#endif -#if FF_USE_LFN - WCHAR* lfnbuf; /* LFN working buffer */ -#endif -#if FF_FS_EXFAT - BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ -#endif -#if FF_FS_REENTRANT - FF_SYNC_t sobj; /* Identifier of sync object */ -#endif -#if !FF_FS_READONLY - DWORD last_clst; /* Last allocated cluster */ - DWORD free_clst; /* Number of free clusters */ -#endif -#if FF_FS_RPATH - DWORD cdir; /* Current directory start cluster (0:root) */ -#if FF_FS_EXFAT - DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ - DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ - DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ -#endif -#endif - DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ - DWORD fsize; /* Size of an FAT [sectors] */ - DWORD volbase; /* Volume base sector */ - DWORD fatbase; /* FAT base sector */ - DWORD dirbase; /* Root directory base sector/cluster */ - DWORD database; /* Data base sector */ -#if FF_FS_EXFAT - DWORD bitbase; /* Allocation bitmap base sector */ -#endif - DWORD winsect; /* Current sector appearing in the win[] */ -} FATFS; - - - -/* Object ID and allocation information (FFOBJID) */ - -typedef struct { - FATFS* fs; /* Pointer to the hosting volume of this object */ - WORD id; /* Hosting volume mount ID */ - BYTE attr; /* Object attribute */ - BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */ - DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */ - FSIZE_t objsize; /* Object size (valid when sclust != 0) */ -#if FF_FS_EXFAT - DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */ - DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */ - DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ - DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ - DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */ -#endif -#if FF_FS_LOCK - UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ -#endif -} FFOBJID; - - - -/* File object structure (FIL) */ - -typedef struct { -#if !FF_FS_TINY - BYTE buf[FF_MAX_SS]; /* File private data read/write window */ -#endif - FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ - BYTE flag; /* File status flags */ - BYTE err; /* Abort flag (error code) */ - FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ - DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ - DWORD sect; /* Sector number appearing in buf[] (0:invalid) */ -#if !FF_FS_READONLY - DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */ - BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */ -#endif -#if FF_USE_FASTSEEK - DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ -#endif -} FIL; - - - -/* Directory object structure (DIR) */ - -typedef struct { - FFOBJID obj; /* Object identifier */ - DWORD dptr; /* Current read/write offset */ - DWORD clust; /* Current cluster */ - DWORD sect; /* Current sector (0:Read operation has terminated) */ - BYTE* dir; /* Pointer to the directory item in the win[] */ - BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ -#if FF_USE_LFN - DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ -#endif -#if FF_USE_FIND - const TCHAR* pat; /* Pointer to the name matching pattern */ -#endif -} DIR; - - - -/* File information structure (FILINFO) */ - -typedef struct { - FSIZE_t fsize; /* File size */ - WORD fdate; /* Modified date */ - WORD ftime; /* Modified time */ - BYTE fattrib; /* File attribute */ -#if FF_USE_LFN - TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */ - TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */ -#else - TCHAR fname[12 + 1]; /* File name */ -#endif -} FILINFO; - - - -/* File function return code (FRESULT) */ - -typedef enum { - FR_OK = 0, /* (0) Succeeded */ - FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ - FR_INT_ERR, /* (2) Assertion failed */ - FR_NOT_READY, /* (3) The physical drive cannot work */ - FR_NO_FILE, /* (4) Could not find the file */ - FR_NO_PATH, /* (5) Could not find the path */ - FR_INVALID_NAME, /* (6) The path name format is invalid */ - FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ - FR_EXIST, /* (8) Access denied due to prohibited access */ - FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ - FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ - FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ - FR_NOT_ENABLED, /* (12) The volume has no work area */ - FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ - FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ - FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ - FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ - FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ - FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ -#ifdef FF_FASTFS - FR_INVALID_PARAMETER, /* (19) Given parameter is invalid */ - FR_CLTBL_NO_INIT /* (20) The cluster table for fast seek/read/write was not created */ -#else - FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ -#endif -} FRESULT; - - - -/*--------------------------------------------------------------*/ -/* FatFs module application interface */ - -FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ -FRESULT f_close (FIL* fp); /* Close an open file object */ -FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ -FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ -#ifdef FF_FASTFS -FRESULT f_read_fast (FIL* fp, const void* buff, UINT btr); /* Fast read data from the file */ -FRESULT f_write_fast (FIL* fp, const void* buff, UINT btw); /* Fast write data to the file */ -#endif -FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ -FRESULT f_truncate (FIL* fp); /* Truncate the file */ -FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ -FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ -FRESULT f_closedir (DIR* dp); /* Close an open directory */ -FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ -FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ -FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ -FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ -FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ -FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ -FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ -FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ -FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */ -FRESULT f_chdir (const TCHAR* path); /* Change current directory */ -FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ -FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ -FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ -FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ -FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ -FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ -#ifdef FF_FASTFS -DWORD *f_expand_cltbl (FIL* fp, UINT tblsz, DWORD *tbl, FSIZE_t ofs); /* Expand file and populate cluster table */ -#endif -FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */ -FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ -FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ -FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */ -FRESULT f_setcp (WORD cp); /* Set current code page */ -int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ -int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ -int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ -TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ - -#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) -#define f_error(fp) ((fp)->err) -#define f_tell(fp) ((fp)->fptr) -#define f_size(fp) ((fp)->obj.objsize) -#define f_rewind(fp) f_lseek((fp), 0) -#define f_rewinddir(dp) f_readdir((dp), 0) -#define f_rmdir(path) f_unlink(path) -#define f_unmount(path) f_mount(0, path, 0) - -#ifndef EOF -#define EOF (-1) -#endif - - - - -/*--------------------------------------------------------------*/ -/* Additional user defined functions */ - -/* RTC function */ -#if !FF_FS_READONLY && !FF_FS_NORTC -DWORD get_fattime (void); -#endif - -/* LFN support functions */ -#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */ -WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ -WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */ -DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */ -#endif -#if FF_USE_LFN == 3 /* Dynamic memory allocation */ -void* ff_memalloc (UINT msize); /* Allocate memory block */ -void ff_memfree (void* mblock); /* Free memory block */ -#endif - -/* Sync functions */ -#if FF_FS_REENTRANT -int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */ -int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */ -void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */ -int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */ -#endif - - - - -/*--------------------------------------------------------------*/ -/* Flags and offset address */ - - -/* File access mode and open method flags (3rd argument of f_open) */ -#define FA_READ 0x01 -#define FA_WRITE 0x02 -#define FA_OPEN_EXISTING 0x00 -#define FA_CREATE_NEW 0x04 -#define FA_CREATE_ALWAYS 0x08 -#define FA_OPEN_ALWAYS 0x10 -#define FA_OPEN_APPEND 0x30 - -/* Fast seek controls (2nd argument of f_lseek) */ -#define CREATE_LINKMAP ((FSIZE_t)0 - 1) - -/* Format options (2nd argument of f_mkfs) */ -#define FM_FAT 0x01 -#define FM_FAT32 0x02 -#define FM_EXFAT 0x04 -#define FM_ANY 0x07 -#define FM_SFD 0x08 - -/* Filesystem type (FATFS.fs_type) */ -#define FS_FAT12 1 -#define FS_FAT16 2 -#define FS_FAT32 3 -#define FS_EXFAT 4 - -/* File attribute bits for directory entry (FILINFO.fattrib) */ -#define AM_RDO 0x01 /* Read only */ -#define AM_HID 0x02 /* Hidden */ -#define AM_SYS 0x04 /* System */ -#define AM_DIR 0x10 /* Directory */ -#define AM_ARC 0x20 /* Archive */ - - -#ifdef __cplusplus -} -#endif - -#endif /* FF_DEFINED */ diff --git a/emummc/source/libs/fatfs/ffconf.h b/emummc/source/libs/fatfs/ffconf.h deleted file mode 100644 index 3d01d8b0cb..0000000000 --- a/emummc/source/libs/fatfs/ffconf.h +++ /dev/null @@ -1,292 +0,0 @@ -/*---------------------------------------------------------------------------/ -/ FatFs Functional Configurations -/---------------------------------------------------------------------------*/ - -#define FFCONF_DEF 86604 /* Revision ID */ - -/*---------------------------------------------------------------------------/ -/ Function Configurations -/---------------------------------------------------------------------------*/ - -#define FF_FS_READONLY 0 -/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) -/ Read-only configuration removes writing API functions, f_write(), f_sync(), -/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() -/ and optional writing functions as well. */ - - -#define FF_FS_MINIMIZE 2 -/* This option defines minimization level to remove some basic API functions. -/ -/ 0: Basic functions are fully enabled. -/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() -/ are removed. -/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. -/ 3: f_lseek() function is removed in addition to 2. */ - - -#define FF_USE_STRFUNC 2 -/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). -/ -/ 0: Disable string functions. -/ 1: Enable without LF-CRLF conversion. -/ 2: Enable with LF-CRLF conversion. */ - - -#define FF_USE_FIND 0 -/* This option switches filtered directory read functions, f_findfirst() and -/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ - - -#define FF_USE_MKFS 0 -/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ - -#define FF_FASTFS 1 - -#ifdef FF_FASTFS -#define FF_USE_FASTSEEK 1 -#else -#define FF_USE_FASTSEEK 0 -#endif -/* This option switches fast seek function. (0:Disable or 1:Enable) */ - - -#define FF_USE_EXPAND 0 -/* This option switches f_expand function. (0:Disable or 1:Enable) */ - - -#define FF_USE_CHMOD 0 -/* This option switches attribute manipulation functions, f_chmod() and f_utime(). -/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ - - -#define FF_USE_LABEL 0 -/* This option switches volume label functions, f_getlabel() and f_setlabel(). -/ (0:Disable or 1:Enable) */ - - -#define FF_USE_FORWARD 0 -/* This option switches f_forward() function. (0:Disable or 1:Enable) */ - - -/*---------------------------------------------------------------------------/ -/ Locale and Namespace Configurations -/---------------------------------------------------------------------------*/ - -#define FF_CODE_PAGE 850 -/* This option specifies the OEM code page to be used on the target system. -/ Incorrect code page setting can cause a file open failure. -/ -/ 437 - U.S. -/ 720 - Arabic -/ 737 - Greek -/ 771 - KBL -/ 775 - Baltic -/ 850 - Latin 1 -/ 852 - Latin 2 -/ 855 - Cyrillic -/ 857 - Turkish -/ 860 - Portuguese -/ 861 - Icelandic -/ 862 - Hebrew -/ 863 - Canadian French -/ 864 - Arabic -/ 865 - Nordic -/ 866 - Russian -/ 869 - Greek 2 -/ 932 - Japanese (DBCS) -/ 936 - Simplified Chinese (DBCS) -/ 949 - Korean (DBCS) -/ 950 - Traditional Chinese (DBCS) -/ 0 - Include all code pages above and configured by f_setcp() -*/ - - -#define FF_USE_LFN 3 -#define FF_MAX_LFN 255 -/* The FF_USE_LFN switches the support for LFN (long file name). -/ -/ 0: Disable LFN. FF_MAX_LFN has no effect. -/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. -/ 2: Enable LFN with dynamic working buffer on the STACK. -/ 3: Enable LFN with dynamic working buffer on the HEAP. -/ -/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function -/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and -/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. -/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can -/ be in range of 12 to 255. It is recommended to be set 255 to fully support LFN -/ specification. -/ When use stack for the working buffer, take care on stack overflow. When use heap -/ memory for the working buffer, memory management functions, ff_memalloc() and -/ ff_memfree() in ffsystem.c, need to be added to the project. */ - - -#define FF_LFN_UNICODE 0 -/* This option switches the character encoding on the API when LFN is enabled. -/ -/ 0: ANSI/OEM in current CP (TCHAR = char) -/ 1: Unicode in UTF-16 (TCHAR = WCHAR) -/ 2: Unicode in UTF-8 (TCHAR = char) -/ 3: Unicode in UTF-32 (TCHAR = DWORD) -/ -/ Also behavior of string I/O functions will be affected by this option. -/ When LFN is not enabled, this option has no effect. */ - - -#define FF_LFN_BUF 255 -#define FF_SFN_BUF 12 -/* This set of options defines size of file name members in the FILINFO structure -/ which is used to read out directory items. These values should be suffcient for -/ the file names to read. The maximum possible length of the read file name depends -/ on character encoding. When LFN is not enabled, these options have no effect. */ - - -#define FF_STRF_ENCODE 0 -/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(), -/ f_putc(), f_puts and f_printf() convert the character encoding in it. -/ This option selects assumption of character encoding ON THE FILE to be -/ read/written via those functions. -/ -/ 0: ANSI/OEM in current CP -/ 1: Unicode in UTF-16LE -/ 2: Unicode in UTF-16BE -/ 3: Unicode in UTF-8 -*/ - - -#define FF_FS_RPATH 0 -/* This option configures support for relative path. -/ -/ 0: Disable relative path and remove related functions. -/ 1: Enable relative path. f_chdir() and f_chdrive() are available. -/ 2: f_getcwd() function is available in addition to 1. -*/ - - -/*---------------------------------------------------------------------------/ -/ Drive/Volume Configurations -/---------------------------------------------------------------------------*/ - -#define FF_VOLUMES 1 -/* Number of volumes (logical drives) to be used. (1-10) */ - - -#define FF_STR_VOLUME_ID 0 -#define FF_VOLUME_STRS "sd" -/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. -/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive -/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each -/ logical drives. Number of items must not be less than FF_VOLUMES. Valid -/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are -/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is -/ not defined, a user defined volume string table needs to be defined as: -/ -/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... -*/ - - -#define FF_MULTI_PARTITION 0 -/* This option switches support for multiple volumes on the physical drive. -/ By default (0), each logical drive number is bound to the same physical drive -/ number and only an FAT volume found on the physical drive will be mounted. -/ When this function is enabled (1), each logical drive number can be bound to -/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() -/ funciton will be available. */ - - -#define FF_MIN_SS 512 -#define FF_MAX_SS 512 -/* This set of options configures the range of sector size to be supported. (512, -/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and -/ harddisk. But a larger value may be required for on-board flash memory and some -/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured -/ for variable sector size mode and disk_ioctl() function needs to implement -/ GET_SECTOR_SIZE command. */ - - -#define FF_USE_TRIM 0 -/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) -/ To enable Trim function, also CTRL_TRIM command should be implemented to the -/ disk_ioctl() function. */ - - -#define FF_FS_NOFSINFO 0 -/* If you need to know correct free space on the FAT32 volume, set bit 0 of this -/ option, and f_getfree() function at first time after volume mount will force -/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. -/ -/ bit0=0: Use free cluster count in the FSINFO if available. -/ bit0=1: Do not trust free cluster count in the FSINFO. -/ bit1=0: Use last allocated cluster number in the FSINFO if available. -/ bit1=1: Do not trust last allocated cluster number in the FSINFO. -*/ - - - -/*---------------------------------------------------------------------------/ -/ System Configurations -/---------------------------------------------------------------------------*/ - -#define FF_FS_TINY 0 -/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) -/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. -/ Instead of private sector buffer eliminated from the file object, common sector -/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ - - -#define FF_FS_EXFAT 1 -/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) -/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1) -/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ - - -#define FF_FS_NORTC 1 -#define FF_NORTC_MON 1 -#define FF_NORTC_MDAY 1 -#define FF_NORTC_YEAR 2020 -/* The option FF_FS_NORTC switches timestamp function. If the system does not have -/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable -/ the timestamp function. Every object modified by FatFs will have a fixed timestamp -/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. -/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be -/ added to the project to read current time form real-time clock. FF_NORTC_MON, -/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. -/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ - - -#define FF_FS_LOCK 0 -/* The option FF_FS_LOCK switches file lock function to control duplicated file open -/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY -/ is 1. -/ -/ 0: Disable file lock function. To avoid volume corruption, application program -/ should avoid illegal open, remove and rename to the open objects. -/ >0: Enable file lock function. The value defines how many files/sub-directories -/ can be opened simultaneously under file lock control. Note that the file -/ lock control is independent of re-entrancy. */ - - -#define FF_FS_REENTRANT 0 -#define FF_FS_TIMEOUT 1000 -#define FF_SYNC_t HANDLE -/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs -/ module itself. Note that regardless of this option, file access to different -/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() -/ and f_fdisk() function, are always not re-entrant. Only file/directory access -/ to the same volume is under control of this function. -/ -/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. -/ 1: Enable re-entrancy. Also user provided synchronization handlers, -/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() -/ function, must be added to the project. Samples are available in -/ option/syscall.c. -/ -/ The FF_FS_TIMEOUT defines timeout period in unit of time tick. -/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, -/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be -/ included somewhere in the scope of ff.h. */ - - - -/*--- End of configuration options ---*/ diff --git a/emummc/source/libs/fatfs/ffsystem.c b/emummc/source/libs/fatfs/ffsystem.c deleted file mode 100644 index 8485c07d3d..0000000000 --- a/emummc/source/libs/fatfs/ffsystem.c +++ /dev/null @@ -1,39 +0,0 @@ -/*------------------------------------------------------------------------*/ -/* Sample Code of OS Dependent Functions for FatFs */ -/* (C) ChaN, 2018 */ -/* (C) CTCaer, 2018 */ -/*------------------------------------------------------------------------*/ - - -#include "ff.h" -#include "../../utils/types.h" -#include - - -#if FF_USE_LFN == 3 /* Dynamic memory allocation */ - -/*------------------------------------------------------------------------*/ -/* Allocate a memory block */ -/*------------------------------------------------------------------------*/ - -void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */ - UINT msize /* Number of bytes to allocate */ -) -{ - return malloc(msize); /* Allocate a new memory block with POSIX API */ -} - - -/*------------------------------------------------------------------------*/ -/* Free a memory block */ -/*------------------------------------------------------------------------*/ - -void ff_memfree ( - void* mblock /* Pointer to the memory block to free (nothing to do if null) */ -) -{ - free(mblock); /* Free the memory block with POSIX API */ -} - -#endif - diff --git a/emummc/source/libs/fatfs/ffunicode.c b/emummc/source/libs/fatfs/ffunicode.c deleted file mode 100644 index 9f039637b0..0000000000 --- a/emummc/source/libs/fatfs/ffunicode.c +++ /dev/null @@ -1,625 +0,0 @@ -/*------------------------------------------------------------------------*/ -/* Unicode handling functions for FatFs R0.13c */ -/*------------------------------------------------------------------------*/ -/* This module will occupy a huge memory in the .const section when the / -/ FatFs is configured for LFN with DBCS. If the system has any Unicode / -/ utilitiy for the code conversion, this module should be modified to use / -/ that function to avoid silly memory consumption. / -/-------------------------------------------------------------------------*/ -/* -/ Copyright (C) 2018, ChaN, all right reserved. -/ -/ FatFs module is an open source software. Redistribution and use of FatFs in -/ source and binary forms, with or without modification, are permitted provided -/ that the following condition is met: -/ -/ 1. Redistributions of source code must retain the above copyright notice, -/ this condition and the following disclaimer. -/ -/ This software is provided by the copyright holder and contributors "AS IS" -/ and any warranties related to this software are DISCLAIMED. -/ The copyright owner or contributors be NOT LIABLE for any damages caused -/ by use of this software. -*/ - - -#include "ff.h" - -#if FF_USE_LFN /* This module will be blanked at non-LFN configuration */ - -#if FF_DEFINED != 86604 /* Revision ID */ -#error Wrong include file (ff.h). -#endif - -#define MERGE2(a, b) a ## b -#define CVTBL(tbl, cp) MERGE2(tbl, cp) - -/*------------------------------------------------------------------------*/ -/* Code Conversion Tables */ -/*------------------------------------------------------------------------*/ - -#if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0 -static const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, - 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0 -static const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */ - 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, - 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, - 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0 -static const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */ - 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, - 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, - 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, - 0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0 -static const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */ - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, - 0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0 -static const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */ - 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, - 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D, - 0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019, - 0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0 -static const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, - 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, - 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0 -static const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, - 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, - 0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4, - 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0 -static const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */ - 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, - 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, - 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, - 0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116, - 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0 -static const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, - 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4, - 0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0 -static const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2, - 0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, - 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0 -static const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, - 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0 -static const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */ - 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, - 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, - 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0 -static const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0, - 0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192, - 0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219, - 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0 -static const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */ - 0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518, - 0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000, - 0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5, - 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F, - 0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9, - 0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9, - 0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1, - 0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000 -}; -#endif -#if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0 -static const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */ - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, - 0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, - 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0 -static const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */ - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, - 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0 -}; -#endif -#if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0 -static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */ - 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389, - 0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF, - 0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3, - 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580, - 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384, - 0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0 -}; -#endif - - - - -/*------------------------------------------------------------------------*/ -/* OEM <==> Unicode conversions for static code page configuration */ -/* SBCS fixed code page */ -/*------------------------------------------------------------------------*/ - -#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900 -WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ - DWORD uni, /* UTF-16 encoded character to be converted */ - WORD cp /* Code page for the conversion */ -) -{ - WCHAR c = 0; - const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); - - - if (uni < 0x80) { /* ASCII? */ - c = (WCHAR)uni; - - } else { /* Non-ASCII */ - if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ - for (c = 0; c < 0x80 && uni != p[c]; c++) ; - c = (c + 0x80) & 0xFF; - } - } - - return c; -} - -WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ - WCHAR oem, /* OEM code to be converted */ - WORD cp /* Code page for the conversion */ -) -{ - WCHAR c = 0; - const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); - - - if (oem < 0x80) { /* ASCII? */ - c = oem; - - } else { /* Extended char */ - if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */ - if (oem < 0x100) c = p[oem - 0x80]; - } - } - - return c; -} - -#endif - - - -/*------------------------------------------------------------------------*/ -/* OEM <==> Unicode conversions for static code page configuration */ -/* DBCS fixed code page */ -/*------------------------------------------------------------------------*/ - -#if FF_CODE_PAGE >= 900 -WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ - DWORD uni, /* UTF-16 encoded character to be converted */ - WORD cp /* Code page for the conversion */ -) -{ - const WCHAR *p; - WCHAR c = 0, uc; - UINT i = 0, n, li, hi; - - - if (uni < 0x80) { /* ASCII? */ - c = (WCHAR)uni; - - } else { /* Non-ASCII */ - if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ - uc = (WCHAR)uni; - p = CVTBL(uni2oem, FF_CODE_PAGE); - hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1; - li = 0; - for (n = 16; n; n--) { - i = li + (hi - li) / 2; - if (uc == p[i * 2]) break; - if (uc > p[i * 2]) { - li = i; - } else { - hi = i; - } - } - if (n != 0) c = p[i * 2 + 1]; - } - } - - return c; -} - - -WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ - WCHAR oem, /* OEM code to be converted */ - WORD cp /* Code page for the conversion */ -) -{ - const WCHAR *p; - WCHAR c = 0; - UINT i = 0, n, li, hi; - - - if (oem < 0x80) { /* ASCII? */ - c = oem; - - } else { /* Extended char */ - if (cp == FF_CODE_PAGE) { /* Is it valid code page? */ - p = CVTBL(oem2uni, FF_CODE_PAGE); - hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1; - li = 0; - for (n = 16; n; n--) { - i = li + (hi - li) / 2; - if (oem == p[i * 2]) break; - if (oem > p[i * 2]) { - li = i; - } else { - hi = i; - } - } - if (n != 0) c = p[i * 2 + 1]; - } - } - - return c; -} -#endif - - - -/*------------------------------------------------------------------------*/ -/* OEM <==> Unicode conversions for dynamic code page configuration */ -/*------------------------------------------------------------------------*/ - -#if FF_CODE_PAGE == 0 - -static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0}; -static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0}; - - -WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ - DWORD uni, /* UTF-16 encoded character to be converted */ - WORD cp /* Code page for the conversion */ -) -{ - const WCHAR *p; - WCHAR c = 0, uc; - UINT i, n, li, hi; - - - if (uni < 0x80) { /* ASCII? */ - c = (WCHAR)uni; - - } else { /* Non-ASCII */ - if (uni < 0x10000) { /* Is it in BMP? */ - uc = (WCHAR)uni; - p = 0; - if (cp < 900) { /* SBCS */ - for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get conversion table */ - p = cp_table[i]; - if (p) { /* Is it valid code page ? */ - for (c = 0; c < 0x80 && uc != p[c]; c++) ; /* Find OEM code in the table */ - c = (c + 0x80) & 0xFF; - } - } else { /* DBCS */ - switch (cp) { /* Get conversion table */ - case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break; - case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break; - case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break; - case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break; - } - if (p) { /* Is it valid code page? */ - li = 0; - for (n = 16; n; n--) { /* Find OEM code */ - i = li + (hi - li) / 2; - if (uc == p[i * 2]) break; - if (uc > p[i * 2]) { - li = i; - } else { - hi = i; - } - } - if (n != 0) c = p[i * 2 + 1]; - } - } - } - } - - return c; -} - - -WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ - WCHAR oem, /* OEM code to be converted (DBC if >=0x100) */ - WORD cp /* Code page for the conversion */ -) -{ - const WCHAR *p; - WCHAR c = 0; - UINT i, n, li, hi; - - - if (oem < 0x80) { /* ASCII? */ - c = oem; - - } else { /* Extended char */ - p = 0; - if (cp < 900) { /* SBCS */ - for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */ - p = cp_table[i]; - if (p) { /* Is it a valid CP ? */ - if (oem < 0x100) c = p[oem - 0x80]; - } - } else { /* DBCS */ - switch (cp) { - case 932 : p = oem2uni932; hi = sizeof oem2uni932 / 4 - 1; break; - case 936 : p = oem2uni936; hi = sizeof oem2uni936 / 4 - 1; break; - case 949 : p = oem2uni949; hi = sizeof oem2uni949 / 4 - 1; break; - case 950 : p = oem2uni950; hi = sizeof oem2uni950 / 4 - 1; break; - } - if (p) { - li = 0; - for (n = 16; n; n--) { - i = li + (hi - li) / 2; - if (oem == p[i * 2]) break; - if (oem > p[i * 2]) { - li = i; - } else { - hi = i; - } - } - if (n != 0) c = p[i * 2 + 1]; - } - } - } - - return c; -} -#endif - - - -/*------------------------------------------------------------------------*/ -/* Unicode up-case conversion */ -/*------------------------------------------------------------------------*/ - -DWORD ff_wtoupper ( /* Returns up-converted code point */ - DWORD uni /* Unicode code point to be up-converted */ -) -{ - const WORD *p; - WORD uc, bc, nc, cmd; - static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */ - /* Basic Latin */ - 0x0061,0x031A, - /* Latin-1 Supplement */ - 0x00E0,0x0317, - 0x00F8,0x0307, - 0x00FF,0x0001,0x0178, - /* Latin Extended-A */ - 0x0100,0x0130, - 0x0132,0x0106, - 0x0139,0x0110, - 0x014A,0x012E, - 0x0179,0x0106, - /* Latin Extended-B */ - 0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA, - 0x01CD,0x0110, - 0x01DD,0x0001,0x018E, - 0x01DE,0x0112, - 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, - 0x01F8,0x0128, - 0x0222,0x0112, - 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, - 0x0246,0x010A, - /* IPA Extensions */ - 0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7, - /* Greek, Coptic */ - 0x037B,0x0003,0x03FD,0x03FE,0x03FF, - 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, - 0x03B1,0x0311, - 0x03C2,0x0002,0x03A3,0x03A3, - 0x03C4,0x0308, - 0x03CC,0x0003,0x038C,0x038E,0x038F, - 0x03D8,0x0118, - 0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA, - /* Cyrillic */ - 0x0430,0x0320, - 0x0450,0x0710, - 0x0460,0x0122, - 0x048A,0x0136, - 0x04C1,0x010E, - 0x04CF,0x0001,0x04C0, - 0x04D0,0x0144, - /* Armenian */ - 0x0561,0x0426, - - 0x0000 /* EOT */ - }; - static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */ - /* Phonetic Extensions */ - 0x1D7D,0x0001,0x2C63, - /* Latin Extended Additional */ - 0x1E00,0x0196, - 0x1EA0,0x015A, - /* Greek Extended */ - 0x1F00,0x0608, - 0x1F10,0x0606, - 0x1F20,0x0608, - 0x1F30,0x0608, - 0x1F40,0x0606, - 0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, - 0x1F60,0x0608, - 0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB, - 0x1F80,0x0608, - 0x1F90,0x0608, - 0x1FA0,0x0608, - 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC, - 0x1FCC,0x0001,0x1FC3, - 0x1FD0,0x0602, - 0x1FE0,0x0602, - 0x1FE5,0x0001,0x1FEC, - 0x1FF3,0x0001,0x1FFC, - /* Letterlike Symbols */ - 0x214E,0x0001,0x2132, - /* Number forms */ - 0x2170,0x0210, - 0x2184,0x0001,0x2183, - /* Enclosed Alphanumerics */ - 0x24D0,0x051A, - 0x2C30,0x042F, - /* Latin Extended-C */ - 0x2C60,0x0102, - 0x2C67,0x0106, 0x2C75,0x0102, - /* Coptic */ - 0x2C80,0x0164, - /* Georgian Supplement */ - 0x2D00,0x0826, - /* Full-width */ - 0xFF41,0x031A, - - 0x0000 /* EOT */ - }; - - - if (uni < 0x10000) { /* Is it in BMP? */ - uc = (WORD)uni; - p = uc < 0x1000 ? cvt1 : cvt2; - for (;;) { - bc = *p++; /* Get the block base */ - if (bc == 0 || uc < bc) break; /* Not matched? */ - nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */ - if (uc < bc + nc) { /* In the block? */ - switch (cmd) { - case 0: uc = p[uc - bc]; break; /* Table conversion */ - case 1: uc -= (uc - bc) & 1; break; /* Case pairs */ - case 2: uc -= 16; break; /* Shift -16 */ - case 3: uc -= 32; break; /* Shift -32 */ - case 4: uc -= 48; break; /* Shift -48 */ - case 5: uc -= 26; break; /* Shift -26 */ - case 6: uc += 8; break; /* Shift +8 */ - case 7: uc -= 80; break; /* Shift -80 */ - case 8: uc -= 0x1C60; break; /* Shift -0x1C60 */ - } - break; - } - if (cmd == 0) p += nc; /* Skip table if needed */ - } - uni = uc; - } - - return uni; -} - -#endif /* #if FF_USE_LFN */ diff --git a/emummc/source/main.c b/emummc/source/main.c deleted file mode 100644 index a06101a9e5..0000000000 --- a/emummc/source/main.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include "nx/svc.h" -#include "nx/smc.h" -#include "soc/clock.h" -#include "soc/i2c.h" -#include "emuMMC/emummc.h" -#include "emuMMC/emummc_ctx.h" -#include "FS/FS_offsets.h" -#include "utils/fatal.h" - -// Prototypes -void __init(); -void __initheap(void); -void setup_hooks(void); -void __libc_init_array(void); -void setup_nintendo_paths(void); -void hook_function(uintptr_t source, uintptr_t target); - -void *__stack_top; -uintptr_t text_base; -size_t fs_code_size; -u8 *fs_rw_mapping = NULL; -Handle self_proc_handle = 0; -char inner_heap[INNER_HEAP_SIZE]; -size_t inner_heap_size = INNER_HEAP_SIZE; - -extern char _start; -extern char __argdata__; - -// Nintendo Path -static char nintendo_path[0x80] = "Nintendo"; - -// 1.0.0 requires special path handling because it has separate album and contents paths. -#define FS_100_ALBUM_PATH 0 -#define FS_100_CONTENTS_PATH 1 -static char nintendo_path_album_100[0x100] = "/Nintendo/Album"; -static char nintendo_path_contents_100[0x100] = "/Nintendo/Contents"; - -// FS offsets -static const fs_offsets_t *fs_offsets; - -// Defined by linkerscript -#define INJECTED_SIZE ((uintptr_t)&__argdata__ - (uintptr_t)&_start) -#define INJECT_OFFSET(type, offset) (type)(text_base + INJECTED_SIZE + offset) -#define FS_CODE_BASE INJECT_OFFSET(uintptr_t, 0) - -#define GENERATE_ADD(register, register_target, value) (0x91000000 | value << 10 | register << 5 | register_target) -#define GENERATE_ADRP(register, page_addr) (0x90000000 | ((((page_addr) >> 12) & 0x3) << 29) | ((((page_addr) >> 12) & 0x1FFFFC) << 3) | ((register) & 0x1F)) -#define GENERATE_BRANCH(source, destination) (0x14000000 | ((((destination) - (source)) >> 2) & 0x3FFFFFF)) -#define GENERATE_NOP() (0xD503201F) - -#define INJECT_HOOK(offset, destination) hook_function(INJECT_OFFSET(uintptr_t, offset), (uintptr_t)&destination) -#define INJECT_HOOK_RELATIVE(offset, relative_destination) hook_function(INJECT_OFFSET(uintptr_t, offset), INJECT_OFFSET(uintptr_t, offset) + relative_destination) -#define INJECT_NOP(offset) write_nop(INJECT_OFFSET(uintptr_t, offset)) - -// emuMMC -extern _sdmmc_accessor_gc sdmmc_accessor_gc; -extern _sdmmc_accessor_sd sdmmc_accessor_sd; -extern _sdmmc_accessor_nand sdmmc_accessor_nand; -extern _lock_mutex lock_mutex; -extern _unlock_mutex unlock_mutex; -extern void *sd_mutex; -extern void *nand_mutex; -extern volatile int *active_partition; -extern volatile Handle *sdmmc_das_handle; - -// Storage -volatile __attribute__((aligned(0x1000))) emuMMC_ctx_t emuMMC_ctx = { - .magic = EMUMMC_STORAGE_MAGIC, - .id = 0, - .fs_ver = FS_VER_MAX, - - // SD Default Metadata - .SD_Type = emuMMC_SD_Raw, - .SD_StoragePartitionOffset = 0, - - // EMMC Default Metadata - .EMMC_Type = emuMMC_EMMC, - .EMMC_StoragePartitionOffset = 0, - - // File Default Path - .storagePath = "", -}; - -// TODO: move into another file -typedef struct -{ - void *_0x0; - void *_0x8; - void *_0x10; - void *_0x18; - void *_0x20; - void *_0x28; - void *_0x30; - void *_0x38; - void *_0x40; - Result (*set_min_v_clock_rate)(void *, uint32_t, uint32_t); -} nn_clkrst_session_vt_t; - -typedef struct -{ - nn_clkrst_session_vt_t *vt; -} nn_clkrst_session_t; - -Result clkrst_set_min_v_clock_rate(nn_clkrst_session_t **_this, uint32_t clk_rate) -{ - Result rc = (*_this)->vt->set_min_v_clock_rate((void *)*_this, clk_rate, clk_rate); - - if (rc == 0x6C0 || rc == 0) - { // TODO #define - return 0; - } - if (rc != 0xAC0) - { // TODO #define - fatal_abort(Fatal_BadResult); - } - - return rc; -} - -void __initheap(void) -{ - void *addr = inner_heap; - size_t size = inner_heap_size; - - /* Newlib Heap Management */ - extern char *fake_heap_start; - extern char *fake_heap_end; - - fake_heap_start = (char *)addr; - fake_heap_end = (char *)addr + size; -} - -static void _receive_process_handle_thread(void *_session_handle) { - Result rc; - - // Convert the argument to a handle copy we can use. - Handle session_handle = *(Handle*)_session_handle; - - // Receive the request from the client thread. - memset(armGetTls(), 0, 0x10); - s32 idx = 0; - rc = svcReplyAndReceive(&idx, &session_handle, 1, INVALID_HANDLE, UINT64_MAX); - if (rc != 0) - { - fatal_abort(Fatal_BadResult); - } - - // Set the process handle. - self_proc_handle = ((u32 *)armGetTls())[3]; - - // Close the session. - svcCloseHandle(session_handle); - - // Terminate ourselves. - svcExitThread(); - - // This code will never execute. - while (true); -} - -static void _init_process_handle(void) { - Result rc; - u8 temp_thread_stack[0x1000]; - - // Create a new session to transfer our process handle to ourself - Handle server_handle, client_handle; - rc = svcCreateSession(&server_handle, &client_handle, 0, 0); - if (rc != 0) - { - fatal_abort(Fatal_BadResult); - } - - // Create a new thread to receive our handle. - Handle thread_handle; - rc = svcCreateThread(&thread_handle, _receive_process_handle_thread, &server_handle, temp_thread_stack + sizeof(temp_thread_stack), 0x20, 3); - if (rc != 0) - { - fatal_abort(Fatal_BadResult); - } - - // Start the new thread. - rc = svcStartThread(thread_handle); - if (rc != 0) - { - fatal_abort(Fatal_BadResult); - } - - // Send the message. - static const u32 SendProcessHandleMessage[4] = { 0x00000000, 0x80000000, 0x00000002, CUR_PROCESS_HANDLE }; - memcpy(armGetTls(), SendProcessHandleMessage, sizeof(SendProcessHandleMessage)); - svcSendSyncRequest(client_handle); - - // Close the session handle. - svcCloseHandle(client_handle); - - // Wait for the thread to be done. - rc = svcWaitSynchronizationSingle(thread_handle, UINT64_MAX); - if (rc != 0) - { - fatal_abort(Fatal_BadResult); - } - - // Close the thread handle. - svcCloseHandle(thread_handle); -} - -static void _map_fs_rw(void) { - Result rc; - - do { - fs_rw_mapping = (u8 *)(smcGenerateRandomU64() & 0xFFFFFF000ull); - rc = svcMapProcessMemory(fs_rw_mapping, self_proc_handle, FS_CODE_BASE, fs_code_size); - } while (rc == 0xDC01 || rc == 0xD401); - - if (rc != 0) - { - fatal_abort(Fatal_BadResult); - } -} - -static void _unmap_fs_rw(void) { - Result rc = svcUnmapProcessMemory(fs_rw_mapping, self_proc_handle, FS_CODE_BASE, fs_code_size); - if (rc != 0) - { - fatal_abort(Fatal_BadResult); - } - - fs_rw_mapping = NULL; -} - -static void _write32(uintptr_t source, u32 value) { - *((u32 *)(fs_rw_mapping + (source - FS_CODE_BASE))) = value; -} - -void hook_function(uintptr_t source, uintptr_t target) -{ - u32 branch_opcode = GENERATE_BRANCH(source, target); - _write32(source, branch_opcode); -} - -void write_nop(uintptr_t source) -{ - _write32(source, GENERATE_NOP()); -} - -void write_adrp_add(int reg, uintptr_t pc, uintptr_t add_rel_offset, intptr_t destination) -{ - uintptr_t add_opcode_location = pc + add_rel_offset; - - intptr_t offset = (destination & 0xFFFFF000) - (pc & 0xFFFFF000); - uint32_t opcode_adrp = GENERATE_ADRP(reg, offset); - uint32_t opcode_add = GENERATE_ADD(reg, reg, (destination & 0x00000FFF)); - - _write32(pc, opcode_adrp); - _write32(add_opcode_location, opcode_add); -} - -void setup_hooks(void) -{ - // rtld - INJECT_HOOK_RELATIVE(fs_offsets->rtld, fs_offsets->rtld_destination); - // sdmmc_wrapper_read hook - INJECT_HOOK(fs_offsets->sdmmc_wrapper_read, sdmmc_wrapper_read); - // sdmmc_wrapper_write hook - INJECT_HOOK(fs_offsets->sdmmc_wrapper_write, sdmmc_wrapper_write); - // sdmmc_wrapper_controller_open hook - if (fs_offsets->sdmmc_accessor_controller_open) - INJECT_HOOK(fs_offsets->sdmmc_accessor_controller_open, sdmmc_wrapper_controller_open); - // sdmmc_wrapper_controller_close hook - INJECT_HOOK(fs_offsets->sdmmc_accessor_controller_close, sdmmc_wrapper_controller_close); - - // On 8.0.0+, we need to hook the regulator setup, because - // otherwise it will abort because we have already turned it on. - if (emuMMC_ctx.fs_ver >= FS_VER_8_0_0) - { - INJECT_HOOK(fs_offsets->clkrst_set_min_v_clock_rate, clkrst_set_min_v_clock_rate); - } -} - -void populate_function_pointers(void) -{ - // Accessor getters - sdmmc_accessor_gc = INJECT_OFFSET(_sdmmc_accessor_gc, fs_offsets->sdmmc_accessor_gc); - sdmmc_accessor_sd = INJECT_OFFSET(_sdmmc_accessor_sd, fs_offsets->sdmmc_accessor_sd); - sdmmc_accessor_nand = INJECT_OFFSET(_sdmmc_accessor_nand, fs_offsets->sdmmc_accessor_nand); - - // MutexLock functions - lock_mutex = INJECT_OFFSET(_lock_mutex, fs_offsets->lock_mutex); - unlock_mutex = INJECT_OFFSET(_unlock_mutex, fs_offsets->unlock_mutex); - - // Other - sd_mutex = INJECT_OFFSET(void *, fs_offsets->sd_mutex); - nand_mutex = INJECT_OFFSET(void *, fs_offsets->nand_mutex); - active_partition = INJECT_OFFSET(volatile int *, fs_offsets->active_partition); - sdmmc_das_handle = INJECT_OFFSET(volatile Handle *, fs_offsets->sdmmc_das_handle); -} - -void write_nops(void) -{ - // On 7.0.0+, we need to attach to device address space ourselves. - // This patches an abort that happens when Nintendo's code sees SD - // is already attached - if (emuMMC_ctx.fs_ver >= FS_VER_7_0_0) - { - INJECT_NOP(fs_offsets->sd_das_init); - } -} - -static void load_emummc_ctx(void) -{ - exo_emummc_config_t config; - static struct - { - char storage_path[sizeof(emuMMC_ctx.storagePath)]; - char nintendo_path[sizeof(nintendo_path)]; - } __attribute__((aligned(0x1000))) paths; - - int x = smcGetEmummcConfig(EXO_EMUMMC_MMC_NAND, &config, &paths); - if (x != 0) - { - fatal_abort(Fatal_GetConfig); - } - - if (config.base_cfg.magic == EMUMMC_STORAGE_MAGIC) - { - emuMMC_ctx.magic = config.base_cfg.magic; - emuMMC_ctx.id = config.base_cfg.id; - emuMMC_ctx.EMMC_Type = (enum emuMMC_Type)config.base_cfg.type; - emuMMC_ctx.fs_ver = (enum FS_VER)config.base_cfg.fs_version; - if (emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw) - { - emuMMC_ctx.EMMC_StoragePartitionOffset = config.partition_cfg.start_sector; - } - else if (emuMMC_ctx.EMMC_Type == emuMMC_SD_File) - { - memcpy((void *)emuMMC_ctx.storagePath, paths.storage_path, sizeof(emuMMC_ctx.storagePath) - 1); - emuMMC_ctx.storagePath[sizeof(emuMMC_ctx.storagePath) - 1] = 0; - } - memcpy(nintendo_path, paths.nintendo_path, sizeof(nintendo_path) - 1); - nintendo_path[sizeof(nintendo_path) - 1] = 0; - if (strcmp(nintendo_path, "") == 0) - { - snprintf(nintendo_path, sizeof(nintendo_path), "emummc/Nintendo_%04x", emuMMC_ctx.id); - } - } - else - { - fatal_abort(Fatal_GetConfig); - } -} - -void setup_nintendo_paths(void) -{ - if (emuMMC_ctx.fs_ver > FS_VER_1_0_0) - { - for (int i = 0; fs_offsets->nintendo_paths[i].adrp_offset; i++) - { - intptr_t nintendo_path_location = (intptr_t)&nintendo_path; - uintptr_t fs_adrp_opcode_location = INJECT_OFFSET(uintptr_t, fs_offsets->nintendo_paths[i].adrp_offset); - write_adrp_add(fs_offsets->nintendo_paths[i].opcode_reg, fs_adrp_opcode_location, fs_offsets->nintendo_paths[i].add_rel_offset, nintendo_path_location); - } - } - else - { - // 1.0.0 needs special handling because it uses two paths. - // Do album path - { - snprintf(nintendo_path_album_100, sizeof(nintendo_path_album_100), "/%s/Album", nintendo_path); - intptr_t nintendo_album_path_location = (intptr_t)&nintendo_path_album_100; - uintptr_t fs_adrp_opcode_location = INJECT_OFFSET(uintptr_t, fs_offsets->nintendo_paths[FS_100_ALBUM_PATH].adrp_offset); - write_adrp_add(fs_offsets->nintendo_paths[FS_100_ALBUM_PATH].opcode_reg, fs_adrp_opcode_location, fs_offsets->nintendo_paths[FS_100_ALBUM_PATH].add_rel_offset, nintendo_album_path_location); - } - - // Do contents path - { - snprintf(nintendo_path_contents_100, sizeof(nintendo_path_contents_100), "/%s/Contents", nintendo_path); - intptr_t nintendo_contents_path_location = (intptr_t)&nintendo_path_contents_100; - uintptr_t fs_adrp_opcode_location = INJECT_OFFSET(uintptr_t, fs_offsets->nintendo_paths[FS_100_CONTENTS_PATH].adrp_offset); - write_adrp_add(fs_offsets->nintendo_paths[FS_100_CONTENTS_PATH].opcode_reg, fs_adrp_opcode_location, fs_offsets->nintendo_paths[FS_100_CONTENTS_PATH].add_rel_offset, nintendo_contents_path_location); - } - } -} - -// inject main func -void __init() -{ - // Call constructors. - __libc_init_array(); - - MemoryInfo meminfo; - u32 pageinfo; - svcQueryMemory(&meminfo, &pageinfo, (u64)&_start); - - text_base = meminfo.addr; - - // Get code size - svcQueryMemory(&meminfo, &pageinfo, FS_CODE_BASE); - fs_code_size = meminfo.size; - - load_emummc_ctx(); - - fs_offsets = get_fs_offsets(emuMMC_ctx.fs_ver); - - _init_process_handle(); - _map_fs_rw(); - setup_hooks(); - populate_function_pointers(); - write_nops(); - setup_nintendo_paths(); - _unmap_fs_rw(); - - clock_enable_i2c5(); - i2c_init(); -} diff --git a/emummc/source/nx/cache.h b/emummc/source/nx/cache.h deleted file mode 100644 index f3a646d2d0..0000000000 --- a/emummc/source/nx/cache.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @file cache.h - * @brief AArch64 cache operations. - * @author plutoo - * @copyright libnx Authors - */ -#pragma once -#include "../utils/types.h" - -/** - * @brief Performs a data cache flush on the specified buffer. - * @param addr Address of the buffer. - * @param size Size of the buffer, in bytes. - * @remarks Cache flush is defined as Clean + Invalidate. - * @note The start and end addresses of the buffer are forcibly rounded to cache line boundaries (read from CTR_EL0 system register). - */ -void armDCacheFlush(void* addr, size_t size); - -/** - * @brief Performs a data cache clean on the specified buffer. - * @param addr Address of the buffer. - * @param size Size of the buffer, in bytes. - * @note The start and end addresses of the buffer are forcibly rounded to cache line boundaries (read from CTR_EL0 system register). - */ -void armDCacheClean(void* addr, size_t size); - -/** - * @brief Performs an instruction cache invalidation clean on the specified buffer. - * @param addr Address of the buffer. - * @param size Size of the buffer, in bytes. - * @note The start and end addresses of the buffer are forcibly rounded to cache line boundaries (read from CTR_EL0 system register). - */ -void armICacheInvalidate(void* addr, size_t size); - -/** - * @brief Performs a data cache zeroing operation on the specified buffer. - * @param addr Address of the buffer. - * @param size Size of the buffer, in bytes. - * @note The start and end addresses of the buffer are forcibly rounded to cache line boundaries (read from CTR_EL0 system register). - */ -void armDCacheZero(void* addr, size_t size); diff --git a/emummc/source/nx/cache.s b/emummc/source/nx/cache.s deleted file mode 100644 index 7facecb1fe..0000000000 --- a/emummc/source/nx/cache.s +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file cache.s - * @copyright libnx Authors - */ - -.macro CODE_BEGIN name - .section .text.\name, "ax", %progbits - .global \name - .type \name, %function - .align 2 - .cfi_startproc -\name: -.endm - -.macro CODE_END - .cfi_endproc -.endm - -CODE_BEGIN armDCacheFlush - add x1, x1, x0 - mrs x8, CTR_EL0 - lsr x8, x8, #16 - and x8, x8, #0xf - mov x9, #4 - lsl x9, x9, x8 - sub x10, x9, #1 - bic x8, x0, x10 - mov x10, x1 - -armDCacheFlush_L0: - dc civac, x8 - add x8, x8, x9 - cmp x8, x10 - bcc armDCacheFlush_L0 - - dsb sy - ret -CODE_END - -CODE_BEGIN armDCacheClean - add x1, x1, x0 - mrs x8, CTR_EL0 - lsr x8, x8, #16 - and x8, x8, #0xf - mov x9, #4 - lsl x9, x9, x8 - sub x10, x9, #1 - bic x8, x0, x10 - mov x10, x1 - -armDCacheClean_L0: - dc cvac, x8 - add x8, x8, x9 - cmp x8, x10 - bcc armDCacheClean_L0 - - dsb sy - ret -CODE_END - -CODE_BEGIN armICacheInvalidate - add x1, x1, x0 - mrs x8, CTR_EL0 - and x8, x8, #0xf - mov x9, #4 - lsl x9, x9, x8 - sub x10, x9, #1 - bic x8, x0, x10 - mov x10, x1 - -armICacheInvalidate_L0: - ic ivau, x8 - add x8, x8, x9 - cmp x8, x10 - bcc armICacheInvalidate_L0 - - dsb sy - ret -CODE_END - -CODE_BEGIN armDCacheZero - add x1, x1, x0 - mrs x8, CTR_EL0 - lsr x8, x8, #16 - and x8, x8, #0xf - mov x9, #4 - lsl x9, x9, x8 - sub x10, x9, #1 - bic x8, x0, x10 - mov x10, x1 - -armDCacheZero_L0: - dc zva, x8 - add x8, x8, x9 - cmp x8, x10 - bcc armDCacheZero_L0 - - dsb sy - ret -CODE_END diff --git a/emummc/source/nx/counter.h b/emummc/source/nx/counter.h deleted file mode 100644 index 072be64172..0000000000 --- a/emummc/source/nx/counter.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @file counter.h - * @brief AArch64 system counter-timer. - * @author fincs - * @copyright libnx Authors - */ -#pragma once -#include "../utils/types.h" - -/** - * @brief Gets the current system tick. - * @return The current system tick. - */ -static inline u64 armGetSystemTick(void) { - u64 ret; - __asm__ __volatile__ ("mrs %x[data], cntpct_el0" : [data] "=r" (ret)); - return ret; -} - -/** - * @brief Gets the system counter-timer frequency - * @return The system counter-timer frequency, in Hz. - */ -static inline u64 armGetSystemTickFreq(void) { - u64 ret; - __asm__ ("mrs %x[data], cntfrq_el0" : [data] "=r" (ret)); - return ret; -} - -/** - * @brief Converts from nanoseconds to CPU ticks unit. - * @param ns Time in nanoseconds. - * @return Time in CPU ticks. - */ -static inline u64 armNsToTicks(u64 ns) { - return (ns * 12) / 625; -} - -/** - * @brief Converts from CPU ticks unit to nanoseconds. - * @param tick Time in ticks. - * @return Time in nanoseconds. - */ -static inline u64 armTicksToNs(u64 tick) { - return (tick * 625) / 12; -} diff --git a/emummc/source/nx/dynamic.c b/emummc/source/nx/dynamic.c deleted file mode 100644 index f1a24f88c2..0000000000 --- a/emummc/source/nx/dynamic.c +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @file dynamic.c - * @copyright libnx Authors - */ - -#include -#include "../utils/types.h" -#include - -void __nx_dynamic(uintptr_t base, const Elf64_Dyn* dyn) -{ - const Elf64_Rela* rela = NULL; - u64 relasz = 0; - - for (; dyn->d_tag != DT_NULL; dyn++) - { - switch (dyn->d_tag) - { - case DT_RELA: - rela = (const Elf64_Rela*)(base + dyn->d_un.d_ptr); - break; - case DT_RELASZ: - relasz = dyn->d_un.d_val / sizeof(Elf64_Rela); - break; - } - } - - if (rela == NULL) { - while(true) - ; - } - - for (; relasz--; rela++) - { - switch (ELF64_R_TYPE(rela->r_info)) - { - case R_AARCH64_RELATIVE: - { - u64* ptr = (u64*)(base + rela->r_offset); - *ptr = base + rela->r_addend; - break; - } - } - } -} diff --git a/emummc/source/nx/smc.c b/emummc/source/nx/smc.c deleted file mode 100644 index b07c6e721a..0000000000 --- a/emummc/source/nx/smc.c +++ /dev/null @@ -1,217 +0,0 @@ -/** - * @file smc.c - * @copyright libnx Authors - */ - -#include -#include -#include "smc.h" -#include "../utils/fatal.h" - -void smcRebootToRcm(void) -{ - SecmonArgs args; - args.X[0] = 0xC3000401; /* smcSetConfig */ - args.X[1] = SplConfigItem_NeedsReboot; /* Exosphere reboot */ - args.X[3] = 1; /* Perform reboot to RCM. */ - svcCallSecureMonitor(&args); -} - -void smcRebootToIramPayload(void) -{ - SecmonArgs args; - args.X[0] = 0xC3000401; /* smcSetConfig */ - args.X[1] = SplConfigItem_NeedsReboot; /* Exosphere reboot */ - args.X[3] = 2; /* Perform reboot to payload at 0x40010000 in IRAM. */ - svcCallSecureMonitor(&args); -} - -void smcPerformShutdown(void) -{ - SecmonArgs args; - args.X[0] = 0xC3000401; /* smcSetConfig */ - args.X[1] = SplConfigItem_NeedsShutdown; /* Exosphere shutdown */ - args.X[3] = 1; /* Perform shutdown. */ - svcCallSecureMonitor(&args); -} - -Result smcGetConfig(SplConfigItem config_item, u64 *out_config) -{ - SecmonArgs args; - args.X[0] = 0xC3000002; /* smcGetConfig */ - args.X[1] = (u64)config_item; /* config item */ - Result rc = svcCallSecureMonitor(&args); - if (rc == 0) - { - if (args.X[0] == 0) - { - if (out_config) - { - *out_config = args.X[1]; - } - } - else - { - /* SPL result n = SMC result n */ - rc = (26u | ((u32)args.X[0] << 9u)); - } - } - return rc; -} - -SplHardwareType splGetHardwareType(void) -{ - u64 value; - Result rc = smcGetConfig(SplConfigItem_HardwareType, &value); - if (rc != 0) - { - fatal_abort(Fatal_BadResult); - } - return (SplHardwareType)value; -} - -SplSocType splGetSocType(void) -{ - static SplSocType soc_type; - static bool soc_type_set = false; - - if (soc_type_set) - return soc_type; - - switch (splGetHardwareType()) - { - case SplHardwareType_Icosa: - case SplHardwareType_Copper: - soc_type = SplSocType_Erista; - break; - case SplHardwareType_Hoag: - case SplHardwareType_Iowa: - case SplHardwareType_Calcio: - case SplHardwareType_Five: - soc_type = SplSocType_Mariko; - break; - default: - fatal_abort(Fatal_InvalidEnum); - } - - soc_type_set = true; - - return soc_type; -} - - -Result smcCopyToIram(uintptr_t iram_addr, const void *src_addr, u32 size) -{ - SecmonArgs args; - args.X[0] = 0xF0000201; /* smcAmsIramCopy */ - args.X[1] = (u64)src_addr; /* DRAM address */ - args.X[2] = (u64)iram_addr; /* IRAM address */ - args.X[3] = size; /* Amount to copy */ - args.X[4] = 1; /* 1 = Write */ - Result rc = svcCallSecureMonitor(&args); - if (rc == 0) - { - if (args.X[0] != 0) - { - /* SPL result n = SMC result n */ - rc = (26u | ((u32)args.X[0] << 9u)); - } - } - return rc; -} - -Result smcCopyFromIram(void *dst_addr, uintptr_t iram_addr, u32 size) -{ - SecmonArgs args; - args.X[0] = 0xF0000201; /* smcAmsIramCopy */ - args.X[1] = (u64)dst_addr; /* DRAM address */ - args.X[2] = (u64)iram_addr; /* IRAM address */ - args.X[3] = size; /* Amount to copy */ - args.X[4] = 0; /* 0 = Read */ - Result rc = svcCallSecureMonitor(&args); - if (rc == 0) - { - if (args.X[0] != 0) - { - /* SPL result n = SMC result n */ - rc = (26u | ((u32)args.X[0] << 9u)); - } - } - return rc; -} - -Result smcReadWriteRegister(u32 phys_addr, u32 value, u32 mask) -{ - SecmonArgs args; - args.X[0] = 0xF0000002; /* smcAmsReadWriteRegister */ - args.X[1] = phys_addr; /* MMIO address */ - args.X[2] = mask; /* mask */ - args.X[3] = value; /* value */ - Result rc = svcCallSecureMonitor(&args); - if (rc == 0) - { - if (args.X[0] != 0) - { - /* SPL result n = SMC result n */ - rc = (26u | ((u32)args.X[0] << 9u)); - } - } - return rc; -} - -Result smcGetEmummcConfig(exo_emummc_mmc_t mmc_id, exo_emummc_config_t *out_cfg, void *out_paths) -{ - SecmonArgs args; - args.X[0] = 0xF0000404; /* smcAmsGetEmunandConfig */ - args.X[1] = mmc_id; - args.X[2] = (u64)out_paths; /* out path */ - Result rc = svcCallSecureMonitor(&args); - if (rc == 0) - { - if (args.X[0] != 0) - { - /* SPL result n = SMC result n */ - rc = (26u | ((u32)args.X[0] << 9u)); - } - if (rc == 0) - { - memcpy(out_cfg, &args.X[1], sizeof(*out_cfg)); - } - } - return rc; - -} - -Result smcGenerateRandomBytes(void *dst, u32 size) -{ - SecmonArgs args; - args.X[0] = 0xC3000006; /* smcGenerateRandomBytes */ - args.X[1] = size; - Result rc = svcCallSecureMonitor(&args); - if (rc == 0) - { - if (args.X[0] != 0) - { - /* SPL result n = SMC result n */ - rc = (26u | ((u32)args.X[0] << 9u)); - } - if (rc == 0) - { - memcpy(dst, &args.X[1], size); - } - } - return rc; -} - -u64 smcGenerateRandomU64(void) -{ - u64 random; - - Result rc = smcGenerateRandomBytes(&random, sizeof(random)); - if (rc != 0) - { - fatal_abort(Fatal_BadResult); - } - - return random; -} diff --git a/emummc/source/nx/smc.h b/emummc/source/nx/smc.h deleted file mode 100644 index 08572002c7..0000000000 --- a/emummc/source/nx/smc.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file smc.h - * @brief Wrappers for secure monitor calls. - * @copyright libnx Authors - */ -#pragma once -#include "../utils/types.h" -#include "svc.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - SplConfigItem_DisableProgramVerification = 1, - SplConfigItem_DramId = 2, - SplConfigItem_SecurityEngineIrqNumber = 3, - SplConfigItem_Version = 4, - SplConfigItem_HardwareType = 5, - SplConfigItem_IsRetail = 6, - SplConfigItem_IsRecoveryBoot = 7, - SplConfigItem_DeviceId = 8, - SplConfigItem_BootReason = 9, - SplConfigItem_MemoryArrange = 10, - SplConfigItem_IsDebugMode = 11, - SplConfigItem_KernelMemoryConfiguration = 12, - SplConfigItem_IsChargerHiZModeEnabled = 13, - SplConfigItem_IsKiosk = 14, - SplConfigItem_NewHardwareType = 15, - SplConfigItem_NewKeyGeneration = 16, - SplConfigItem_Package2Hash = 17, - - SplConfigItem_ExosphereVersion = 65000, - SplConfigItem_NeedsReboot = 65001, - SplConfigItem_NeedsShutdown = 65002, - SplConfigItem_ExosphereVerHash = 65003, - SplConfigItem_HasRcmBugPatch = 65004, -} SplConfigItem; - -typedef enum { - SplSocType_Erista = 0, - SplSocType_Mariko = 1, -} SplSocType; - -typedef enum { - SplHardwareType_Icosa = 0, - SplHardwareType_Copper = 1, - SplHardwareType_Hoag = 2, - SplHardwareType_Iowa = 3, - SplHardwareType_Calcio = 4, - SplHardwareType_Five = 5, -} SplHardwareType; - -typedef enum { - EXO_EMUMMC_TYPE_NONE = 0, - EXO_EMUMMC_TYPE_PARTITION = 1, - EXO_EMUMMC_TYPE_FILES = 2, -} exo_emummc_type_t; - -typedef enum { - EXO_EMUMMC_MMC_NAND = 0, - EXO_EMUMMC_MMC_SD = 1, - EXO_EMUMMC_MMC_GC = 2, -} exo_emummc_mmc_t; - -typedef struct { - uint32_t magic; - uint32_t type; - uint32_t id; - uint32_t fs_version; -} exo_emummc_base_config_t; - -typedef struct { - uint64_t start_sector; -} exo_emummc_partition_config_t; - -typedef struct { - exo_emummc_base_config_t base_cfg; - union { - exo_emummc_partition_config_t partition_cfg; - }; -} exo_emummc_config_t; - -Result smcGetConfig(SplConfigItem config_item, u64 *out_config); - -SplHardwareType splGetHardwareType(void); -SplSocType splGetSocType(void); - -void smcRebootToRcm(void); -void smcRebootToIramPayload(void); -void smcPerformShutdown(void); - -Result smcCopyToIram(uintptr_t iram_addr, const void *src_addr, u32 size); -Result smcCopyFromIram(void *dst_addr, uintptr_t iram_addr, u32 size); - -Result smcReadWriteRegister(u32 phys_addr, u32 value, u32 mask); - -Result smcGetEmummcConfig(exo_emummc_mmc_t mmc_id, exo_emummc_config_t *out_cfg, void *out_paths); - -Result smcGenerateRandomBytes(void *dst, u32 size); -u64 smcGenerateRandomU64(void); - -#ifdef __cplusplus -} -#endif diff --git a/emummc/source/nx/start.s b/emummc/source/nx/start.s deleted file mode 100644 index 4a20ed0ecd..0000000000 --- a/emummc/source/nx/start.s +++ /dev/null @@ -1,131 +0,0 @@ -/** - * @file start.s - * @copyright libnx Authors - */ - -.macro push_all - SUB SP, SP, #0x100 - STP X29, X30, [SP, #0x0] - STP X27, X28, [SP, #0x10] - STP X25, X26, [SP, #0x20] - STP X23, X24, [SP, #0x30] - STP X21, X22, [SP, #0x40] - STP X19, X20, [SP, #0x50] - STP X17, X18, [SP, #0x60] - STP X15, X16, [SP, #0x70] - STP X13, X14, [SP, #0x80] - STP X11, X12, [SP, #0x90] - STP X9, X10, [SP, #0xA0] - STP X7, X8, [SP, #0xB0] - STP X5, X6, [SP, #0xC0] - STP X3, X4, [SP, #0xD0] - STP X1, X2, [SP, #0xE0] - STR X0, [SP, #0xF0] -.endm - -.macro pop_all - LDR X0, [SP, #0xF0] - LDP X1, X2, [SP, #0xE0] - LDP X3, X4, [SP, #0xD0] - LDP X5, X6, [SP, #0xC0] - LDP X7, X8, [SP, #0xB0] - LDP X9, X10, [SP, #0xA0] - LDP X11, X12, [SP, #0x90] - LDP X13, X14, [SP, #0x80] - LDP X15, X16, [SP, #0x70] - LDP X17, X18, [SP, #0x60] - LDP X19, X20, [SP, #0x50] - LDP X21, X22, [SP, #0x40] - LDP X23, X24, [SP, #0x30] - LDP X25, X26, [SP, #0x20] - LDP X27, X28, [SP, #0x10] - LDP X29, X30, [SP, #0x0] - ADD SP, SP, #0x100 -.endm - -.section ".crt0","ax" -.global _start -_start: - B startup -.org _start+0xc - B sdmmc_wrapper_read -.org _start+0x18 - B sdmmc_wrapper_write -.org _start+0x80 - -.section ".crt0","ax" -startup: - # Save LR - MOV X7, X30 - - # Retrieve ASLR Base - BL +4 - SUB X6, X30, #0x88 - - # Context Ptr and MainThread Handle - MOV X5, X0 - MOV X4, X1 - - # Inject start - push_all - - MOV W0, #0xFFFF8001 - ADR X1, __rodata_start - ADR X2, __data_start - SUB X2, X2, X1 - MOV X3, #1 - SVC 0x73 - - MOV W0, #0xFFFF8001 - ADR X1, __data_start - ADR X2, __argdata__ - SUB X2, X2, X1 - MOV X3, #3 - SVC 0x73 - - pop_all - - MOV X27, X7 - MOV X25, X5 - MOV X26, X4 - - # Clear .bss - ADRP X0, __bss_start__ - ADRP X1, __bss_end__ - ADD X0, X0, #:lo12:__bss_start__ - ADD X1, X1, #:lo12:__bss_end__ - SUB X1, X1, X0 - ADD X1, X1, #7 - BIC X1, X1, #7 - -bss_loop: - STR XZR, [X0], #8 - SUBS X1, X1, #8 - BNE bss_loop - - # Store SP - MOV X1, SP - ADRP X0, __stack_top - STR X1, [X0, #:lo12:__stack_top] - - # Process _DYNAMIC Section - MOV X0, X6 - ADRP X1, _DYNAMIC - ADD X1, X1, #:lo12:_DYNAMIC - BL __nx_dynamic - - # TODO: handle in code - MOV X0, X25 - MOV X1, X26 - MOV X2, X27 - - BL __initheap - BL __init - - MOV X0, X25 - MOV X1, X26 - MOV X30, X27 - - # FS main - ADRP X16, __argdata__ - BR X16 diff --git a/emummc/source/nx/svc.h b/emummc/source/nx/svc.h deleted file mode 100644 index 320666390d..0000000000 --- a/emummc/source/nx/svc.h +++ /dev/null @@ -1,220 +0,0 @@ -/** - * @file svc.h - * @brief Wrappers for kernel syscalls. - * @copyright libnx Authors - */ -#pragma once -#include "../utils/types.h" - -/// Memory information structure. -typedef struct { - u64 addr; ///< Base address. - u64 size; ///< Size. - u32 type; ///< Memory type (see lower 8 bits of \ref MemoryState). - u32 attr; ///< Memory attributes (see \ref MemoryAttribute). - u32 perm; ///< Memory permissions (see \ref Permission). - u32 device_refcount; ///< Device reference count. - u32 ipc_refcount; ///< IPC reference count. - u32 padding; ///< Padding. -} MemoryInfo; - -/// Memory permission bitmasks. -typedef enum { - Perm_None = 0, ///< No permissions. - Perm_R = BIT(0), ///< Read permission. - Perm_W = BIT(1), ///< Write permission. - Perm_X = BIT(2), ///< Execute permission. - Perm_Rw = Perm_R | Perm_W, ///< Read/write permissions. - Perm_Rx = Perm_R | Perm_X, ///< Read/execute permissions. - Perm_DontCare = BIT(28), ///< Don't care -} Permission; - -/// Secure monitor arguments. -typedef struct { - u64 X[8]; ///< Values of X0 through X7. -} SecmonArgs; - -_Static_assert(sizeof(SecmonArgs) == 0x40, "SecmonArgs definition"); - -#define DeviceName_SDMMC1A 19 -#define DeviceName_SDMMC2A 20 -#define DeviceName_SDMMC3A 21 -#define DeviceName_SDMMC4A 22 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Returns a virtual address mapped to a given IO range. - * @return Result code. - * @note Syscall number 0x55. - * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. - * @warning Only exists on [10.0.0+]. For older versions use \ref svcLegacyQueryIoMapping. - */ -Result svcQueryIoMapping(u64* virtaddr, u64* out_size, u64 physaddr, u64 size); - -/** - * @brief Returns a virtual address mapped to a given IO range. - * @return Result code. - * @note Syscall number 0x55. - * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. - * @warning Only exists on [1.0.0-9.2.0]. For newer versions use \ref svcQueryIoMapping. - */ -Result svcLegacyQueryIoMapping(u64* virtaddr, u64 physaddr, u64 size); - -/** - * @brief Attaches a device address space to a device. - * @return Result code. - * @note Syscall number 0x57. - * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. - */ -Result svcAttachDeviceAddressSpace(u64 device, Handle handle); - -/** - * @brief Query information about an address. Will always fetch the lowest page-aligned mapping that contains the provided address. - * @param[out] meminfo_ptr \ref MemoryInfo structure which will be filled in. - * @param[out] pageinfo Page information which will be filled in. - * @param[in] addr Address to query. - * @return Result code. - * @note Syscall number 0x06. - */ -Result svcQueryMemory(MemoryInfo* meminfo_ptr, u32 *pageinfo, u64 addr); - -/** - * @brief Sets the memory permissions for the specified memory with the supplied process handle. - * @param[in] proc Process handle. - * @param[in] addr Address of the memory. - * @param[in] size Size of the memory. - * @param[in] perm Permissions (see \ref Permission). - * @return Result code. - * @remark This returns an error (0xD801) when \p perm is >0x5, hence -WX and RWX are not allowed. - * @note Syscall number 0x73. - * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. - */ -Result svcSetProcessMemoryPermission(Handle proc, u64 addr, u64 size, u32 perm); - -/** - * @brief Set the memory permissions of a (page-aligned) range of memory. - * @param[in] addr Start address of the range. - * @param[in] size Size of the range, in bytes. - * @param[in] perm Permissions (see \ref Permission). - * @return Result code. - * @remark Perm_X is not allowed. Setting write-only is not allowed either (Perm_W). - * This can be used to move back and forth between Perm_None, Perm_R and Perm_Rw. - * @note Syscall number 0x01. - */ -Result svcSetMemoryPermission(void* addr, u64 size, u32 perm); - -/** - * @brief Creates a thread. - * @return Result code. - * @note Syscall number 0x08. - */ -Result svcCreateThread(Handle* out, void* entry, void* arg, void* stack_top, int prio, int cpuid); - -/** - * @brief Starts a freshly created thread. - * @return Result code. - * @note Syscall number 0x09. - */ -Result svcStartThread(Handle handle); - -/** - * @brief Exits the current thread. - * @note Syscall number 0x0A. - */ -void __attribute__((noreturn)) svcExitThread(void); - -/** - * @brief Closes a handle, decrementing the reference count of the corresponding kernel object. - * This might result in the kernel freeing the object. - * @param handle Handle to close. - * @return Result code. - * @note Syscall number 0x16. - */ -Result svcCloseHandle(Handle handle); - -/** - * @brief Waits on one or more synchronization objects, optionally with a timeout. - * @return Result code. - * @note Syscall number 0x18. - * @note \p handleCount must not be greater than \ref MAX_WAIT_OBJECTS. This is a Horizon kernel limitation. - * @note This is the raw syscall, which can be cancelled by \ref svcCancelSynchronization or other means. \ref waitHandles or \ref waitMultiHandle should normally be used instead. - */ -Result svcWaitSynchronization(s32* index, const Handle* handles, s32 handleCount, u64 timeout); - -/** - * @brief Waits on a single synchronization object, optionally with a timeout. - * @return Result code. - * @note Wrapper for \ref svcWaitSynchronization. - * @note This is the raw syscall, which can be cancelled by \ref svcCancelSynchronization or other means. \ref waitSingleHandle should normally be used instead. - */ -static inline Result svcWaitSynchronizationSingle(Handle handle, u64 timeout) { - s32 tmp; - return svcWaitSynchronization(&tmp, &handle, 1, timeout); -} - -/** - * @brief Creates an IPC session. - * @return Result code. - * @note Syscall number 0x40. - * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. - */ -Result svcCreateSession(Handle *server_handle, Handle *client_handle, u32 unk0, u64 unk1);//unk* are normally 0? - -/** - * @brief Sends an IPC synchronization request to a session. - * @return Result code. - * @note Syscall number 0x21. - */ -Result svcSendSyncRequest(Handle session); - -/** - * @brief Performs IPC input/output. - * @return Result code. - * @note Syscall number 0x43. - * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. - */ -Result svcReplyAndReceive(s32* index, const Handle* handles, s32 handleCount, Handle replyTarget, u64 timeout); - -/** - * @brief Maps the src address from the supplied process handle into the current process. - * @param[in] dst Address to which map the memory in the current process. - * @param[in] proc Process handle. - * @param[in] src Source mapping address. - * @param[in] size Size of the memory. - * @return Result code. - * @remark This allows mapping code and rodata with RW- permission. - * @note Syscall number 0x74. - * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. - */ -Result svcMapProcessMemory(void* dst, Handle proc, u64 src, u64 size); - -/** - * @brief Undoes the effects of \ref svcMapProcessMemory. - * @param[in] dst Destination mapping address - * @param[in] proc Process handle. - * @param[in] src Address of the memory in the process. - * @param[in] size Size of the memory. - * @return Result code. - * @remark This allows mapping code and rodata with RW- permission. - * @note Syscall number 0x75. - * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. - */ -Result svcUnmapProcessMemory(void* dst, Handle proc, u64 src, u64 size); - -/** - * @brief Calls a secure monitor function (TrustZone, EL3). - * @param regs Arguments to pass to the secure monitor. - * @return Return value from the secure monitor. - * @note Syscall number 0x7F. - * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. - */ -u64 svcCallSecureMonitor(SecmonArgs* regs); - -#ifdef __cplusplus -} -#endif - -///@} diff --git a/emummc/source/nx/svc.s b/emummc/source/nx/svc.s deleted file mode 100644 index fc03f96c34..0000000000 --- a/emummc/source/nx/svc.s +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @file svc.s - * @copyright libnx Authors - */ - -.macro SVC_BEGIN name - .section .text.\name, "ax", %progbits - .global \name - .type \name, %function - .align 2 - .cfi_startproc -\name: -.endm - -.macro SVC_END - .cfi_endproc -.endm - -SVC_BEGIN svcQueryIoMapping - STP X0, X1, [SP, #-16]! - SVC 0x55 - LDP X3, X4, [SP], #16 - STR X1, [X3] - STR X2, [X4] - RET -SVC_END - -SVC_BEGIN svcLegacyQueryIoMapping - STR X0, [SP, #-16]! - SVC 0x55 - LDR X2, [SP], #16 - STR X1, [X2] - RET -SVC_END - -SVC_BEGIN svcAttachDeviceAddressSpace - SVC 0x57 - RET -SVC_END - -SVC_BEGIN svcQueryMemory - STR X1, [SP, #-16]! - SVC 0x6 - LDR X2, [SP], #16 - STR W1, [X2] - RET -SVC_END - -SVC_BEGIN svcSetMemoryPermission - SVC 0x2 - RET -SVC_END - -SVC_BEGIN svcSetProcessMemoryPermission - SVC 0x73 - RET -SVC_END - -SVC_BEGIN svcCreateThread - STR X0, [SP, #-16]! - SVC 0x8 - LDR X2, [SP], #16 - STR W1, [X2] - RET -SVC_END - -SVC_BEGIN svcStartThread - SVC 0x9 - RET -SVC_END - -SVC_BEGIN svcExitThread - SVC 0xA - RET -SVC_END - -SVC_BEGIN svcCloseHandle - SVC 0x16 - RET -SVC_END - -SVC_BEGIN svcWaitSynchronization - STR X0, [SP, #-16]! - SVC 0x18 - LDR X2, [SP], #16 - STR W1, [X2] - RET -SVC_END - -SVC_BEGIN svcCreateSession - STP X0, X1, [SP, #-16]! - SVC 0x40 - LDP X3, X4, [SP], #16 - STR W1, [X3] - STR W2, [X4] - RET -SVC_END - -SVC_BEGIN svcSendSyncRequest - SVC 0x21 - RET -SVC_END - -SVC_BEGIN svcReplyAndReceive - STR X0, [SP, #-16]! - SVC 0x43 - LDR X2, [SP], #16 - STR W1, [X2] - RET -SVC_END - -SVC_BEGIN svcMapProcessMemory - SVC 0x74 - RET -SVC_END - -SVC_BEGIN svcUnmapProcessMemory - SVC 0x75 - RET -SVC_END - -SVC_BEGIN svcCallSecureMonitor - STR X0, [SP, #-16]! - MOV X8, X0 - LDP X0, X1, [X8] - LDP X2, X3, [X8, #0x10] - LDP X4, X5, [X8, #0x20] - LDP X6, X7, [X8, #0x30] - SVC 0x7F - LDR X8, [SP], #16 - STP X0, X1, [X8] - STP X2, X3, [X8, #0x10] - STP X4, X5, [X8, #0x20] - STP X6, X7, [X8, #0x30] - RET -SVC_END \ No newline at end of file diff --git a/emummc/source/power/max77620.h b/emummc/source/power/max77620.h deleted file mode 100644 index 26ea855957..0000000000 --- a/emummc/source/power/max77620.h +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Defining registers address and its bit definitions of MAX77620 and MAX20024 - * - * Copyright (c) 2016 NVIDIA CORPORATION. All rights reserved. - * Copyright (c) 2019 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - */ - -#ifndef _MFD_MAX77620_H_ -#define _MFD_MAX77620_H_ - -#define MAX77620_I2C_ADDR 0x3C - -/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ -#define MAX77620_REG_CNFGGLBL1 0x00 -#define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7) -#define MAX77620_CNFGGLBL1_MPPLD (1 << 6) -#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4)) -#define MAX77620_CNFGGLBL1_LBHYST_100 (0 << 4) -#define MAX77620_CNFGGLBL1_LBHYST_200 (1 << 4) -#define MAX77620_CNFGGLBL1_LBHYST_300 (2 << 4) -#define MAX77620_CNFGGLBL1_LBHYST_400 (3 << 4) -#define MAX77620_CNFGGLBL1_LBDAC_MASK 0x0E -#define MAX77620_CNFGGLBL1_LBDAC_2700 (0 << 1) -#define MAX77620_CNFGGLBL1_LBDAC_2800 (1 << 1) -#define MAX77620_CNFGGLBL1_LBDAC_2900 (2 << 1) -#define MAX77620_CNFGGLBL1_LBDAC_3000 (3 << 1) -#define MAX77620_CNFGGLBL1_LBDAC_3100 (4 << 1) -#define MAX77620_CNFGGLBL1_LBDAC_3200 (5 << 1) -#define MAX77620_CNFGGLBL1_LBDAC_3300 (6 << 1) -#define MAX77620_CNFGGLBL1_LBDAC_3400 (7 << 1) -#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0) - -#define MAX77620_REG_CNFGGLBL2 0x01 -#define MAX77620_REG_CNFGGLBL3 0x02 -#define MAX77620_WDTC_MASK 0x3 -#define MAX77620_WDTOFFC (1 << 4) -#define MAX77620_WDTSLPC (1 << 3) -#define MAX77620_WDTEN (1 << 2) -#define MAX77620_TWD_MASK 0x3 -#define MAX77620_TWD_2s 0x0 -#define MAX77620_TWD_16s 0x1 -#define MAX77620_TWD_64s 0x2 -#define MAX77620_TWD_128s 0x3 - -#define MAX77620_REG_CNFG1_32K 0x03 -#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2) - -#define MAX77620_REG_CNFGBBC 0x04 -#define MAX77620_CNFGBBC_ENABLE (1 << 0) -#define MAX77620_CNFGBBC_CURRENT_MASK 0x06 -#define MAX77620_CNFGBBC_CURRENT_SHIFT 1 -#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18 -#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3 -#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5) -#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0 -#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6 -#define MAX77620_CNFGBBC_RESISTOR_100 (0 << MAX77620_CNFGBBC_RESISTOR_SHIFT) -#define MAX77620_CNFGBBC_RESISTOR_1K (1 << MAX77620_CNFGBBC_RESISTOR_SHIFT) -#define MAX77620_CNFGBBC_RESISTOR_3K (2 << MAX77620_CNFGBBC_RESISTOR_SHIFT) -#define MAX77620_CNFGBBC_RESISTOR_6K (3 << MAX77620_CNFGBBC_RESISTOR_SHIFT) - -#define MAX77620_REG_IRQTOP 0x05 -#define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7) -#define MAX77620_IRQ_TOP_SD_MASK (1 << 6) -#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5) -#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4) -#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3) -#define MAX77620_IRQ_TOP_32K_MASK (1 << 2) -#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1) - -#define MAX77620_REG_INTLBT 0x06 -#define MAX77620_REG_IRQTOPM 0x0D -#define MAX77620_IRQ_LBM_MASK (1 << 3) -#define MAX77620_IRQ_TJALRM1_MASK (1 << 2) -#define MAX77620_IRQ_TJALRM2_MASK (1 << 1) - -#define MAX77620_REG_IRQSD 0x07 -#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 -#define MAX77620_REG_IRQ_LVL2_L8 0x09 -#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A -#define MAX77620_REG_ONOFFIRQ 0x0B -#define MAX77620_REG_NVERC 0x0C - -#define MAX77620_REG_INTENLBT 0x0E -#define MAX77620_GLBLM_MASK (1 << 0) - -#define MAX77620_REG_IRQMASKSD 0x0F -#define MAX77620_REG_IRQ_MSK_L0_7 0x10 -#define MAX77620_REG_IRQ_MSK_L8 0x11 -#define MAX77620_REG_ONOFFIRQM 0x12 -#define MAX77620_REG_STATLBT 0x13 -#define MAX77620_REG_STATSD 0x14 -#define MAX77620_REG_ONOFFSTAT 0x15 - -/* SD and LDO Registers */ -#define MAX77620_REG_SD0 0x16 -#define MAX77620_REG_SD1 0x17 -#define MAX77620_REG_SD2 0x18 -#define MAX77620_REG_SD3 0x19 -#define MAX77620_REG_SD4 0x1A -#define MAX77620_SDX_VOLT_MASK 0xFF -#define MAX77620_SD0_VOLT_MASK 0x3F -#define MAX77620_SD1_VOLT_MASK 0x7F -#define MAX77620_LDO_VOLT_MASK 0x3F -#define MAX77620_REG_DVSSD0 0x1B -#define MAX77620_REG_DVSSD1 0x1C -#define MAX77620_REG_SD0_CFG 0x1D -#define MAX77620_REG_SD1_CFG 0x1E -#define MAX77620_REG_SD2_CFG 0x1F -#define MAX77620_REG_SD3_CFG 0x20 -#define MAX77620_REG_SD4_CFG 0x21 -#define MAX77620_REG_SD_CFG2 0x22 -#define MAX77620_REG_LDO0_CFG 0x23 -#define MAX77620_REG_LDO0_CFG2 0x24 -#define MAX77620_REG_LDO1_CFG 0x25 -#define MAX77620_REG_LDO1_CFG2 0x26 -#define MAX77620_REG_LDO2_CFG 0x27 -#define MAX77620_REG_LDO2_CFG2 0x28 -#define MAX77620_REG_LDO3_CFG 0x29 -#define MAX77620_REG_LDO3_CFG2 0x2A -#define MAX77620_REG_LDO4_CFG 0x2B -#define MAX77620_REG_LDO4_CFG2 0x2C -#define MAX77620_REG_LDO5_CFG 0x2D -#define MAX77620_REG_LDO5_CFG2 0x2E -#define MAX77620_REG_LDO6_CFG 0x2F -#define MAX77620_REG_LDO6_CFG2 0x30 -#define MAX77620_REG_LDO7_CFG 0x31 -#define MAX77620_REG_LDO7_CFG2 0x32 -#define MAX77620_REG_LDO8_CFG 0x33 -#define MAX77620_REG_LDO8_CFG2 0x34 -#define MAX77620_LDO_POWER_MODE_MASK 0xC0 -#define MAX77620_LDO_POWER_MODE_SHIFT 6 -#define MAX77620_POWER_MODE_NORMAL 3 -#define MAX77620_POWER_MODE_LPM 2 -#define MAX77620_POWER_MODE_GLPM 1 -#define MAX77620_POWER_MODE_DISABLE 0 -#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2) -#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) -#define MAX77620_LDO_CFG2_ADE_DISABLE (0 << 1) -#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) -#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) -#define MAX77620_LDO_CFG2_SS_FAST (1 << 0) -#define MAX77620_LDO_CFG2_SS_SLOW 0 - -#define MAX77620_REG_LDO_CFG3 0x35 -#define MAX77620_TRACK4_MASK (1 << 5) -#define MAX77620_TRACK4_SHIFT 5 - -#define MAX77620_LDO_SLEW_RATE_MASK 0x1 - -#define MAX77620_REG_GPIO0 0x36 -#define MAX77620_REG_GPIO1 0x37 -#define MAX77620_REG_GPIO2 0x38 -#define MAX77620_REG_GPIO3 0x39 -#define MAX77620_REG_GPIO4 0x3A -#define MAX77620_REG_GPIO5 0x3B -#define MAX77620_REG_GPIO6 0x3C -#define MAX77620_REG_GPIO7 0x3D -#define MAX77620_REG_PUE_GPIO 0x3E -#define MAX77620_REG_PDE_GPIO 0x3F -#define MAX77620_REG_AME_GPIO 0x40 -#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0) -#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0) -#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN (0 << 0) -#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1) -#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1) -#define MAX77620_CNFG_GPIO_DIR_OUTPUT (0 << 1) -#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2) -#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3) -#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3) -#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW (0 << 3) -#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4) -#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4) -#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5) -#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6) -#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6) -#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6) -#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6) -#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6) - -#define MAX77620_REG_ONOFFCNFG1 0x41 -#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7) -#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 -#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 -#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2) -#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1) -#define MAX20024_ONOFFCNFG1_CLRSE 0x18 - -#define MAX77620_REG_ONOFFCNFG2 0x42 -#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7) -#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6) -#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5) -#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2) -#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0) - -/* FPS Registers */ -#define MAX77620_REG_FPS_CFG0 0x43 -#define MAX77620_REG_FPS_CFG1 0x44 -#define MAX77620_REG_FPS_CFG2 0x45 -#define MAX77620_REG_FPS_LDO0 0x46 -#define MAX77620_REG_FPS_LDO1 0x47 -#define MAX77620_REG_FPS_LDO2 0x48 -#define MAX77620_REG_FPS_LDO3 0x49 -#define MAX77620_REG_FPS_LDO4 0x4A -#define MAX77620_REG_FPS_LDO5 0x4B -#define MAX77620_REG_FPS_LDO6 0x4C -#define MAX77620_REG_FPS_LDO7 0x4D -#define MAX77620_REG_FPS_LDO8 0x4E -#define MAX77620_REG_FPS_SD0 0x4F -#define MAX77620_REG_FPS_SD1 0x50 -#define MAX77620_REG_FPS_SD2 0x51 -#define MAX77620_REG_FPS_SD3 0x52 -#define MAX77620_REG_FPS_SD4 0x53 -#define MAX77620_REG_FPS_NONE 0 -#define MAX77620_FPS_SRC_MASK 0xC0 -#define MAX77620_FPS_SRC_SHIFT 6 -#define MAX77620_FPS_PU_PERIOD_MASK 0x38 -#define MAX77620_FPS_PU_PERIOD_SHIFT 3 -#define MAX77620_FPS_PD_PERIOD_MASK 0x07 -#define MAX77620_FPS_PD_PERIOD_SHIFT 0 - -/* Minimum and maximum FPS period time (in microseconds) are - * different for MAX77620 and Max20024. - */ -#define MAX77620_FPS_COUNT 3 - -#define MAX77620_FPS_PERIOD_MIN_US 40 -#define MAX20024_FPS_PERIOD_MIN_US 20 - -#define MAX77620_FPS_PERIOD_MAX_US 2560 -#define MAX20024_FPS_PERIOD_MAX_US 5120 - -#define MAX77620_REG_FPS_GPIO1 0x54 -#define MAX77620_REG_FPS_GPIO2 0x55 -#define MAX77620_REG_FPS_GPIO3 0x56 -#define MAX77620_FPS_TIME_PERIOD_MASK 0x38 -#define MAX77620_FPS_TIME_PERIOD_SHIFT 3 -#define MAX77620_FPS_EN_SRC_MASK 0x06 -#define MAX77620_FPS_EN_SRC_SHIFT 1 -#define MAX77620_FPS_ENFPS_SW_MASK 0x01 -#define MAX77620_FPS_ENFPS_SW 0x01 - -#define MAX77620_REG_FPS_RSO 0x57 -#define MAX77620_REG_CID0 0x58 -#define MAX77620_REG_CID1 0x59 -#define MAX77620_REG_CID2 0x5A -#define MAX77620_REG_CID3 0x5B -#define MAX77620_REG_CID4 0x5C -#define MAX77620_REG_CID5 0x5D - -#define MAX77620_REG_DVSSD4 0x5E -#define MAX20024_REG_MAX_ADD 0x70 - -#define MAX77620_CID_DIDM_MASK 0xF0 -#define MAX77620_CID_DIDM_SHIFT 4 - -/* CNCG2SD */ -#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1) -#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2) - -/* Device Identification Metal */ -#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) -/* Device Indentification OTP */ -#define MAX77620_CID5_DIDO(n) ((n) & 0xF) - -/* SD CNFG1 */ -#define MAX77620_SD_SR_MASK 0xC0 -#define MAX77620_SD_SR_SHIFT 6 -#define MAX77620_SD_POWER_MODE_MASK 0x30 -#define MAX77620_SD_POWER_MODE_SHIFT 4 -#define MAX77620_SD_CFG1_ADE_MASK (1 << 3) -#define MAX77620_SD_CFG1_ADE_DISABLE 0 -#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3) -#define MAX77620_SD_FPWM_MASK 0x04 -#define MAX77620_SD_FPWM_SHIFT 2 -#define MAX77620_SD_FSRADE_MASK 0x01 -#define MAX77620_SD_FSRADE_SHIFT 0 -#define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2) -#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 -#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2) -#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1) -#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0) -#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 -#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0) - -#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0) -#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1) -#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2) -#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3) -#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4) -#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5) -#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6) -#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7) - -/* Interrupts */ -enum { - MAX77620_IRQ_TOP_GLBL, /* Low-Battery */ - MAX77620_IRQ_TOP_SD, /* SD power fail */ - MAX77620_IRQ_TOP_LDO, /* LDO power fail */ - MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */ - MAX77620_IRQ_TOP_RTC, /* RTC */ - MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */ - MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */ - MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */ - MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */ - MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */ -}; - -/* GPIOs */ -enum { - MAX77620_GPIO0, - MAX77620_GPIO1, - MAX77620_GPIO2, - MAX77620_GPIO3, - MAX77620_GPIO4, - MAX77620_GPIO5, - MAX77620_GPIO6, - MAX77620_GPIO7, - MAX77620_GPIO_NR, -}; - -/* FPS Source */ -enum max77620_fps_src { - MAX77620_FPS_SRC_0, - MAX77620_FPS_SRC_1, - MAX77620_FPS_SRC_2, - MAX77620_FPS_SRC_NONE, - MAX77620_FPS_SRC_DEF, -}; - -enum max77620_chip_id { - MAX77620, - MAX20024, -}; - -#endif /* _MFD_MAX77620_H_ */ diff --git a/emummc/source/power/max7762x.c b/emummc/source/power/max7762x.c deleted file mode 100644 index 1e090bf525..0000000000 --- a/emummc/source/power/max7762x.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2019 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "max7762x.h" -#include "max77620.h" -#include "../soc/i2c.h" -#include "../utils/util.h" - -#define REGULATOR_SD 0 -#define REGULATOR_LDO 1 - -typedef struct _max77620_regulator_t -{ - u8 type; - const char *name; - u8 reg_sd; - - u32 mv_step; - u32 mv_min; - u32 mv_default; - u32 mv_max; - - u8 volt_addr; - u8 cfg_addr; - - u8 volt_mask; - u8 enable_mask; - u8 enable_shift; - u8 status_mask; - - u8 fps_addr; - u8 fps_src; - u8 pd_period; - u8 pu_period; -} max77620_regulator_t; - -static const max77620_regulator_t _pmic_regulators[] = { - { REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x80, MAX77620_REG_FPS_SD0, 1, 7, 1 }, - { REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x40, MAX77620_REG_FPS_SD1, 0, 1, 5 }, - { REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x20, MAX77620_REG_FPS_SD2, 1, 5, 2 }, - { REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, MAX77620_SD_POWER_MODE_MASK, MAX77620_SD_POWER_MODE_SHIFT, 0x10, MAX77620_REG_FPS_SD3, 0, 3, 3 }, - { REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO0, 3, 7, 0 }, - { REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO1, 3, 7, 0 }, - { REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO2, 3, 7, 0 }, - { REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO3, 3, 7, 0 }, - { REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO4, 0, 7, 1 }, - { REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO5, 3, 7, 0 }, - { REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO6, 3, 7, 0 }, - { REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO7, 1, 4, 3 }, - { REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, MAX77620_LDO_POWER_MODE_MASK, MAX77620_LDO_POWER_MODE_SHIFT, 0x00, MAX77620_REG_FPS_LDO8, 3, 7, 0 } -}; - -int max77620_regulator_get_status(u32 id) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - if (reg->type == REGULATOR_SD) - return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_STATSD) & reg->status_mask) ? 0 : 1; - return (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->cfg_addr) & 8) ? 1 : 0; -} - -int max77620_regulator_config_fps(u32 id) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg->fps_addr, - (reg->fps_src << MAX77620_FPS_SRC_SHIFT) | (reg->pu_period << MAX77620_FPS_PU_PERIOD_SHIFT) | (reg->pd_period)); - - return 1; -} - -int max77620_regulator_set_voltage(u32 id, u32 mv) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - if (mv < reg->mv_min || mv > reg->mv_max) - return 0; - - u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; - u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr); - val = (val & ~reg->volt_mask) | (mult & reg->volt_mask); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr, val); - usleep(1000); - - return 1; -} - -int max77620_regulator_enable(u32 id, int enable) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - u32 addr = reg->type == REGULATOR_SD ? reg->cfg_addr : reg->volt_addr; - u8 val = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, addr); - if (enable) - val = (val & ~reg->enable_mask) | ((MAX77620_POWER_MODE_NORMAL << reg->enable_shift) & reg->enable_mask); - else - val &= ~reg->enable_mask; - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, addr, val); - usleep(1000); - - return 1; -} - -int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - if (mv < reg->mv_min || mv > reg->mv_max) - return 0; - - u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; - u8 val = ((flags << reg->enable_shift) & ~reg->volt_mask) | (mult & reg->volt_mask); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, reg->volt_addr, val); - usleep(1000); - - return 1; -} - -void max77620_config_default() -{ - for (u32 i = 1; i <= REGULATOR_MAX; i++) - { - i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CID4); - max77620_regulator_config_fps(i); - max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); - if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE) - max77620_regulator_enable(i, 1); - } - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, 4); -} diff --git a/emummc/source/power/max7762x.h b/emummc/source/power/max7762x.h deleted file mode 100644 index c8b5c5309f..0000000000 --- a/emummc/source/power/max7762x.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2019 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _MAX7762X_H_ -#define _MAX7762X_H_ - -#include "../utils/types.h" - -/* -* Switch Power domains (max77620): -* Name | Usage | uV step | uV min | uV default | uV max | Init -*-------+---------------+---------+--------+------------+---------+------------------ -* sd0 | SoC | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1) -* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1) -* sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv) -* sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 | -* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1) -* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv) -* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 | -* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv) -* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | -* ldo5 | GC ASIC | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv) -* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V -* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | -* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 | -*/ - -/* -* MAX77620_AME_GPIO: control GPIO modes (bits 0 - 7 correspond to GPIO0 - GPIO7); 0 -> GPIO, 1 -> alt-mode -* MAX77620_REG_GPIOx: 0x9 sets output and enable -*/ - -/*! MAX77620 partitions. */ -#define REGULATOR_SD0 0 -#define REGULATOR_SD1 1 -#define REGULATOR_SD2 2 -#define REGULATOR_SD3 3 -#define REGULATOR_LDO0 4 -#define REGULATOR_LDO1 5 -#define REGULATOR_LDO2 6 -#define REGULATOR_LDO3 7 -#define REGULATOR_LDO4 8 -#define REGULATOR_LDO5 9 -#define REGULATOR_LDO6 10 -#define REGULATOR_LDO7 11 -#define REGULATOR_LDO8 12 -#define REGULATOR_MAX 12 - -#define MAX77621_CPU_I2C_ADDR 0x1B -#define MAX77621_GPU_I2C_ADDR 0x1C - -#define MAX77621_VOUT_REG 0 -#define MAX77621_VOUT_DVC_REG 1 -#define MAX77621_CONTROL1_REG 2 -#define MAX77621_CONTROL2_REG 3 - -/* MAX77621_VOUT */ -#define MAX77621_VOUT_ENABLE (1 << 7) -#define MAX77621_VOUT_MASK 0x7F -#define MAX77621_VOUT_0_95V 0x37 -#define MAX77621_VOUT_1_09V 0x4F - -/* MAX77621_VOUT_DVC_DVS */ -#define MAX77621_DVS_VOUT_MASK 0x7F - -/* MAX77621_CONTROL1 */ -#define MAX77621_SNS_ENABLE (1 << 7) -#define MAX77621_FPWM_EN_M (1 << 6) -#define MAX77621_NFSR_ENABLE (1 << 5) -#define MAX77621_AD_ENABLE (1 << 4) -#define MAX77621_BIAS_ENABLE (1 << 3) -#define MAX77621_FREQSHIFT_9PER (1 << 2) - -#define MAX77621_RAMP_12mV_PER_US 0x0 -#define MAX77621_RAMP_25mV_PER_US 0x1 -#define MAX77621_RAMP_50mV_PER_US 0x2 -#define MAX77621_RAMP_200mV_PER_US 0x3 -#define MAX77621_RAMP_MASK 0x3 - -/* MAX77621_CONTROL2 */ -#define MAX77621_WDTMR_ENABLE (1 << 6) -#define MAX77621_DISCH_ENBABLE (1 << 5) -#define MAX77621_FT_ENABLE (1 << 4) -#define MAX77621_T_JUNCTION_120 (1 << 7) - -#define MAX77621_CKKADV_TRIP_DISABLE 0xC -#define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0 -#define MAX77621_CKKADV_TRIP_150mV_PER_US 0x4 -#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS 0x8 - -#define MAX77621_INDUCTOR_MIN_30_PER 0x0 -#define MAX77621_INDUCTOR_NOMINAL 0x1 -#define MAX77621_INDUCTOR_PLUS_30_PER 0x2 -#define MAX77621_INDUCTOR_PLUS_60_PER 0x3 - -int max77620_regulator_get_status(u32 id); -int max77620_regulator_config_fps(u32 id); -int max77620_regulator_set_voltage(u32 id, u32 mv); -int max77620_regulator_enable(u32 id, int enable); -int max77620_regulator_set_volt_and_flags(u32 id, u32 mv, u8 flags); -void max77620_config_default(); - -#endif diff --git a/emummc/source/soc/clock.c b/emummc/source/soc/clock.c deleted file mode 100644 index 541cd16379..0000000000 --- a/emummc/source/soc/clock.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "../soc/clock.h" -#include "../soc/t210.h" -#include "../utils/util.h" -#include "../emmc/sdmmc.h" - -static const sclock_t _clock_i2c5 = { - CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, 0xF, 0, 4 //81.6MHz -> 400KHz -}; - -static sclock_t _clock_sdmmc_legacy_tm = { - CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, 1, 4, 66 -}; - -void clock_enable(const sclock_t *clk) -{ - // Put clock into reset. - CLOCK(clk->reset) = (CLOCK(clk->reset) & ~(1 << clk->index)) | (1 << clk->index); - // Disable. - CLOCK(clk->enable) &= ~(1 << clk->index); - // Configure clock source if required. - if (clk->source) - CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29); - // Enable. - CLOCK(clk->enable) = (CLOCK(clk->enable) & ~(1 << clk->index)) | (1 << clk->index); - usleep(2); - - // Take clock off reset. - CLOCK(clk->reset) &= ~(1 << clk->index); -} - -void clock_disable(const sclock_t *clk) -{ - // Put clock into reset. - CLOCK(clk->reset) = (CLOCK(clk->reset) & ~(1 << clk->index)) | (1 << clk->index); - // Disable. - CLOCK(clk->enable) &= ~(1 << clk->index); -} - -void clock_enable_i2c5() -{ - clock_enable(&_clock_i2c5); -} - -void clock_disable_i2c5() -{ - clock_disable(&_clock_i2c5); -} - -static void _clock_enable_pllc4() -{ - if ((CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) & (PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | 0xFFFFFF)) - == (PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | (104 << 8) | 4)) - return; - - // Enable Phase and Frequency lock detection. - //CLOCK(CLK_RST_CONTROLLER_PLLC4_MISC) = PLLC4_MISC_EN_LCKDET; - - // Disable PLL and IDDQ in case they are on. - CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLCX_BASE_ENABLE; - CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLC4_BASE_IDDQ; - (void)CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE); - usleep(10); - - // Set PLLC4 dividers. - CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (104 << 8) | 4; // DIVM: 4, DIVP: 1. - - // Enable PLLC4 and wait for Phase and Frequency lock. - CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLCX_BASE_ENABLE; - (void)CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE); - while (!(CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) & PLLCX_BASE_LOCK)) - ; - - msleep(1); // Wait a bit for PLL to stabilize. -} - -#define L_SWR_SDMMC1_RST (1 << 14) -#define L_SWR_SDMMC2_RST (1 << 9) -#define L_SWR_SDMMC4_RST (1 << 15) -#define U_SWR_SDMMC3_RST (1 << 5) - -#define L_CLK_ENB_SDMMC1 (1 << 14) -#define L_CLK_ENB_SDMMC2 (1 << 9) -#define L_CLK_ENB_SDMMC4 (1 << 15) -#define U_CLK_ENB_SDMMC3 (1 << 5) - -#define L_SET_SDMMC1_RST (1 << 14) -#define L_SET_SDMMC2_RST (1 << 9) -#define L_SET_SDMMC4_RST (1 << 15) -#define U_SET_SDMMC3_RST (1 << 5) - -#define L_CLR_SDMMC1_RST (1 << 14) -#define L_CLR_SDMMC2_RST (1 << 9) -#define L_CLR_SDMMC4_RST (1 << 15) -#define U_CLR_SDMMC3_RST (1 << 5) - -#define L_SET_CLK_ENB_SDMMC1 (1 << 14) -#define L_SET_CLK_ENB_SDMMC2 (1 << 9) -#define L_SET_CLK_ENB_SDMMC4 (1 << 15) -#define U_SET_CLK_ENB_SDMMC3 (1 << 5) - -#define L_CLR_CLK_ENB_SDMMC1 (1 << 14) -#define L_CLR_CLK_ENB_SDMMC2 (1 << 9) -#define L_CLR_CLK_ENB_SDMMC4 (1 << 15) -#define U_CLR_CLK_ENB_SDMMC3 (1 << 5) - -static int _clock_sdmmc_is_reset(u32 id) -{ - switch (id) - { - case SDMMC_1: - return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC1_RST; - case SDMMC_2: - return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC2_RST; - case SDMMC_3: - return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_U) & U_SWR_SDMMC3_RST; - case SDMMC_4: - return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC4_RST; - } - return 0; -} - -static void _clock_sdmmc_set_reset(u32 id) -{ - switch (id) - { - case SDMMC_1: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC1_RST; - break; - case SDMMC_2: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC2_RST; - break; - case SDMMC_3: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = U_SET_SDMMC3_RST; - break; - case SDMMC_4: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC4_RST; - break; - } -} - -static void _clock_sdmmc_clear_reset(u32 id) -{ - switch (id) - { - case SDMMC_1: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC1_RST; - break; - case SDMMC_2: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC2_RST; - break; - case SDMMC_3: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = U_CLR_SDMMC3_RST; - break; - case SDMMC_4: - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC4_RST; - break; - } -} - -static int _clock_sdmmc_is_enabled(u32 id) -{ - switch (id) - { - case SDMMC_1: - return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC1; - case SDMMC_2: - return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC2; - case SDMMC_3: - return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) & U_CLK_ENB_SDMMC3; - case SDMMC_4: - return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC4; - } - return 0; -} - -static void _clock_sdmmc_set_enable(u32 id) -{ - switch (id) - { - case SDMMC_1: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC1; - break; - case SDMMC_2: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC2; - break; - case SDMMC_3: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_SET) = U_SET_CLK_ENB_SDMMC3; - break; - case SDMMC_4: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC4; - break; - } -} - -static void _clock_sdmmc_clear_enable(u32 id) -{ - switch (id) - { - case SDMMC_1: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC1; - break; - case SDMMC_2: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC2; - break; - case SDMMC_3: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = U_CLR_CLK_ENB_SDMMC3; - break; - case SDMMC_4: - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC4; - break; - } -} - -static void _clock_sdmmc_config_legacy_tm() -{ - sclock_t *clk = &_clock_sdmmc_legacy_tm; - if (!(CLOCK(clk->enable) & (1 << clk->index))) - clock_enable(clk); -} - -typedef struct _clock_sdmmc_t -{ - u32 clock; - u32 real_clock; -} clock_sdmmc_t; - -static clock_sdmmc_t _clock_sdmmc_table[4] = { 0 }; - -#define SDMMC_CLOCK_SRC_PLLP_OUT0 0x0 -#define SDMMC_CLOCK_SRC_PLLC4_OUT2 0x3 -#define SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ 0x1 - -static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val) -{ - u32 divisor = 0; - u32 source = SDMMC_CLOCK_SRC_PLLP_OUT0; - - if (id > SDMMC_4) - return 0; - - // Get IO clock divisor. - switch (val) - { - case 25000: - *pclock = 24728; - divisor = 31; // 16.5 div. - break; - case 26000: - *pclock = 25500; - divisor = 30; // 16 div. - break; - case 40800: - *pclock = 40800; - divisor = 18; // 10 div. - break; - case 50000: - *pclock = 48000; - divisor = 15; // 8.5 div. - break; - case 52000: - *pclock = 51000; - divisor = 14; // 8 div. - break; - case 100000: - source = SDMMC_CLOCK_SRC_PLLC4_OUT2; - *pclock = 99840; - divisor = 2; // 2 div. - break; - case 164000: - *pclock = 163200; - divisor = 3; // 2.5 div. - break; - case 200000: - switch (id) - { - case SDMMC_1: - source = SDMMC_CLOCK_SRC_PLLC4_OUT2; - break; - case SDMMC_2: - source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; - break; - case SDMMC_3: - source = SDMMC_CLOCK_SRC_PLLC4_OUT2; - break; - case SDMMC_4: - source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; - break; - } - *pclock = 199680; - divisor = 0; // 1 div. - break; - default: - *pclock = 24728; - divisor = 31; // 16.5 div. - } - - _clock_sdmmc_table[id].clock = val; - _clock_sdmmc_table[id].real_clock = *pclock; - - // PLLC4 and LEGACY_TM clocks are already initialized, - // because we init at the first eMMC read. - // // Enable PLLC4 if in use by any SDMMC. - // if (source) - // _clock_enable_pllc4(); - - // // Set SDMMC legacy timeout clock. - // _clock_sdmmc_config_legacy_tm(); - - - // Set SDMMC clock. - switch (id) - { - case SDMMC_1: - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1) = (source << 29) | divisor; - break; - case SDMMC_2: - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2) = (source << 29) | divisor; - break; - case SDMMC_3: - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3) = (source << 29) | divisor; - break; - case SDMMC_4: - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4) = (source << 29) | divisor; - break; - } - - return 1; -} - -void clock_sdmmc_config_clock_source(u32 *pclock, u32 id, u32 val) -{ - if (_clock_sdmmc_table[id].clock == val) - { - *pclock = _clock_sdmmc_table[id].real_clock; - } - else - { - int is_enabled = _clock_sdmmc_is_enabled(id); - if (is_enabled) - _clock_sdmmc_clear_enable(id); - _clock_sdmmc_config_clock_host(pclock, id, val); - if (is_enabled) - _clock_sdmmc_set_enable(id); - _clock_sdmmc_is_reset(id); - } -} - -void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type) -{ - // Get Card clock divisor. - switch (type) - { - case SDHCI_TIMING_MMC_ID: // Actual IO Freq: 380.59 KHz. - *pclock = 26000; - *pdivisor = 66; - break; - case SDHCI_TIMING_MMC_LS26: - *pclock = 26000; - *pdivisor = 1; - break; - case SDHCI_TIMING_MMC_HS52: - *pclock = 52000; - *pdivisor = 1; - break; - case SDHCI_TIMING_MMC_HS200: - case SDHCI_TIMING_MMC_HS400: - case SDHCI_TIMING_UHS_SDR104: - *pclock = 200000; - *pdivisor = 1; - break; - case SDHCI_TIMING_SD_ID: // Actual IO Freq: 380.43 KHz. - *pclock = 25000; - *pdivisor = 64; - break; - case SDHCI_TIMING_SD_DS12: - case SDHCI_TIMING_UHS_SDR12: - *pclock = 25000; - *pdivisor = 1; - break; - case SDHCI_TIMING_SD_HS25: - case SDHCI_TIMING_UHS_SDR25: - *pclock = 50000; - *pdivisor = 1; - break; - case SDHCI_TIMING_UHS_SDR50: - *pclock = 100000; - *pdivisor = 1; - break; - case SDHCI_TIMING_UHS_SDR82: - *pclock = 164000; - *pdivisor = 1; - break; - case SDHCI_TIMING_UHS_DDR50: - *pclock = 40800; - *pdivisor = 1; - break; - case SDHCI_TIMING_MMC_HS102: // Actual IO Freq: 99.84 MHz. - *pclock = 200000; - *pdivisor = 2; - break; - } -} - -int clock_sdmmc_is_not_reset_and_enabled(u32 id) -{ - return !_clock_sdmmc_is_reset(id) && _clock_sdmmc_is_enabled(id); -} - -void clock_sdmmc_enable(u32 id, u32 val) -{ - u32 clock = 0; - - if (_clock_sdmmc_is_enabled(id)) - _clock_sdmmc_clear_enable(id); - _clock_sdmmc_set_reset(id); - _clock_sdmmc_config_clock_host(&clock, id, val); - _clock_sdmmc_set_enable(id); - _clock_sdmmc_is_reset(id); - usleep((100000 + clock - 1) / clock); - _clock_sdmmc_clear_reset(id); - _clock_sdmmc_is_reset(id); -} - -void clock_sdmmc_disable(u32 id) -{ - _clock_sdmmc_set_reset(id); - _clock_sdmmc_clear_enable(id); - _clock_sdmmc_is_reset(id); -} diff --git a/emummc/source/soc/clock.h b/emummc/source/soc/clock.h deleted file mode 100644 index 73171b114f..0000000000 --- a/emummc/source/soc/clock.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CLOCK_H_ -#define _CLOCK_H_ - -#include "../utils/types.h" - -/*! Clock registers. */ -#define CLK_RST_CONTROLLER_RST_SOURCE 0x0 -#define CLK_RST_CONTROLLER_RST_DEVICES_L 0x4 -#define CLK_RST_CONTROLLER_RST_DEVICES_H 0x8 -#define CLK_RST_CONTROLLER_RST_DEVICES_U 0xC -#define CLK_RST_CONTROLLER_CLK_OUT_ENB_L 0x10 -#define CLK_RST_CONTROLLER_CLK_OUT_ENB_H 0x14 -#define CLK_RST_CONTROLLER_CLK_OUT_ENB_U 0x18 -#define CLK_RST_CONTROLLER_CCLK_BURST_POLICY 0x20 -#define CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER 0x24 -#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY 0x28 -#define CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER 0x2C -#define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30 -#define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48 -#define CLK_RST_CONTROLLER_OSC_CTRL 0x50 -#define CLK_RST_CONTROLLER_PLLC_BASE 0x80 -#define CLK_RST_CONTROLLER_PLLC_OUT 0x84 -#define CLK_RST_CONTROLLER_PLLC_MISC 0x88 -#define CLK_RST_CONTROLLER_PLLC_MISC_1 0x8C -#define CLK_RST_CONTROLLER_PLLM_BASE 0x90 -#define CLK_RST_CONTROLLER_PLLM_MISC1 0x98 -#define CLK_RST_CONTROLLER_PLLM_MISC2 0x9C -#define CLK_RST_CONTROLLER_PLLP_BASE 0xA0 -#define CLK_RST_CONTROLLER_PLLD_BASE 0xD0 -#define CLK_RST_CONTROLLER_PLLD_MISC1 0xD8 -#define CLK_RST_CONTROLLER_PLLD_MISC 0xDC -#define CLK_RST_CONTROLLER_PLLX_BASE 0xE0 -#define CLK_RST_CONTROLLER_PLLX_MISC 0xE4 -#define CLK_RST_CONTROLLER_PLLE_BASE 0xE8 -#define CLK_RST_CONTROLLER_PLLE_MISC 0xEC -#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA 0xF8 -#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB 0xFC -#define CLK_RST_CONTROLLER_CLK_SOURCE_PWM 0x110 -#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 0x124 -#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 0x128 -#define CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 0x138 -#define CLK_RST_CONTROLLER_CLK_SOURCE_VI 0x148 -#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1 0x150 -#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2 0x154 -#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4 0x164 -#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA 0x178 -#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB 0x17C -#define CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X 0x180 -#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C2 0x198 -#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC 0x19C -#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC 0x1A0 -#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C3 0x1B8 -#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 0x1BC -#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTD 0x1C0 -#define CLK_RST_CONTROLLER_CLK_SOURCE_CSITE 0x1D4 -#define CLK_RST_CONTROLLER_CLK_SOURCE_TSEC 0x1F4 -#define CLK_RST_CONTROLLER_CLK_OUT_ENB_X 0x280 -#define CLK_RST_CONTROLLER_CLK_ENB_X_SET 0x284 -#define CLK_RST_CONTROLLER_CLK_ENB_X_CLR 0x288 -#define CLK_RST_CONTROLLER_RST_DEVICES_X 0x28C -#define CLK_RST_CONTROLLER_RST_DEV_X_SET 0x290 -#define CLK_RST_CONTROLLER_RST_DEV_X_CLR 0x294 -#define CLK_RST_CONTROLLER_CLK_OUT_ENB_Y 0x298 -#define CLK_RST_CONTROLLER_CLK_ENB_Y_SET 0x29C -#define CLK_RST_CONTROLLER_CLK_ENB_Y_CLR 0x2A0 -#define CLK_RST_CONTROLLER_RST_DEVICES_Y 0x2A4 -#define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2A8 -#define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2AC -#define CLK_RST_CONTROLLER_RST_DEV_L_SET 0x300 -#define CLK_RST_CONTROLLER_RST_DEV_L_CLR 0x304 -#define CLK_RST_CONTROLLER_RST_DEV_H_SET 0x308 -#define CLK_RST_CONTROLLER_RST_DEV_H_CLR 0x30C -#define CLK_RST_CONTROLLER_RST_DEV_U_SET 0x310 -#define CLK_RST_CONTROLLER_RST_DEV_U_CLR 0x314 -#define CLK_RST_CONTROLLER_CLK_ENB_L_SET 0x320 -#define CLK_RST_CONTROLLER_CLK_ENB_L_CLR 0x324 -#define CLK_RST_CONTROLLER_CLK_ENB_H_SET 0x328 -#define CLK_RST_CONTROLLER_CLK_ENB_H_CLR 0x32C -#define CLK_RST_CONTROLLER_CLK_ENB_U_SET 0x330 -#define CLK_RST_CONTROLLER_CLK_ENB_U_CLR 0x334 -#define CLK_RST_CONTROLLER_RST_DEVICES_V 0x358 -#define CLK_RST_CONTROLLER_RST_DEVICES_W 0x35C -#define CLK_RST_CONTROLLER_CLK_OUT_ENB_V 0x360 -#define CLK_RST_CONTROLLER_CLK_OUT_ENB_W 0x364 -#define CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2 0x388 -#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC 0x3A0 -#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD 0x3A4 -#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT 0x3B4 -#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 0x3C4 -#define CLK_RST_CONTROLLER_CLK_SOURCE_SYS 0x400 -#define CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 0x410 -#define CLK_RST_CONTROLLER_CLK_SOURCE_SE 0x42C -#define CLK_RST_CONTROLLER_RST_DEV_V_CLR 0x434 -#define CLK_RST_CONTROLLER_CLK_ENB_V_SET 0x440 -#define CLK_RST_CONTROLLER_CLK_ENB_V_CLR 0x444 -#define CLK_RST_CONTROLLER_CLK_ENB_W_SET 0x448 -#define CLK_RST_CONTROLLER_CLK_ENB_W_CLR 0x44C -#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET 0x450 -#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR 0x454 -#define CLK_RST_CONTROLLER_UTMIP_PLL_CFG2 0x488 -#define CLK_RST_CONTROLLER_PLLE_AUX 0x48C -#define CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S0 0x4A0 -#define CLK_RST_CONTROLLER_PLLX_MISC_3 0x518 -#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE 0x554 -#define CLK_RST_CONTROLLER_SPARE_REG0 0x55C -#define CLK_RST_CONTROLLER_PLLC4_BASE 0x5A4 -#define CLK_RST_CONTROLLER_PLLC4_MISC 0x5A8 -#define CLK_RST_CONTROLLER_PLLC_MISC_2 0x5D0 -#define CLK_RST_CONTROLLER_PLLC4_OUT 0x5E4 -#define CLK_RST_CONTROLLER_PLLMB_BASE 0x5E8 -#define CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP 0x620 -#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 0x65C -#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL 0x664 -#define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL 0x66C -#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM 0x694 -#define CLK_RST_CONTROLLER_CLK_SOURCE_NVENC 0x6A0 -#define CLK_RST_CONTROLLER_SE_SUPER_CLK_DIVIDER 0x704 -#define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710 - -#define CLK_NO_SOURCE 0x0 - -/*! PLL control and status bits */ -#define PLLCX_BASE_ENABLE (1 << 30) -#define PLLCX_BASE_REF_DIS (1 << 29) -#define PLLCX_BASE_LOCK (1 << 27) - -#define PLLC4_MISC_EN_LCKDET (1 << 30) -#define PLLC4_BASE_IDDQ (1 << 18) -#define PLLC4_OUT3_CLKEN (1 << 1) -#define PLLC4_OUT3_RSTN_CLR (1 << 0) - -/*! Generic clock descriptor. */ -typedef struct _sclock_t -{ - u32 reset; - u32 enable; - u32 source; - u8 index; - u8 clk_src; - u8 clk_div; -} sclock_t; - -/*! Generic clock enable/disable. */ -void clock_enable(const sclock_t *clk); -void clock_disable(const sclock_t *clk); - -/*! Clock control for specific hardware portions. */ -void clock_enable_i2c5(); -void clock_disable_i2c5(); -void clock_sdmmc_config_clock_source(u32 *pclock, u32 id, u32 val); -void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type); -int clock_sdmmc_is_not_reset_and_enabled(u32 id); -void clock_sdmmc_enable(u32 id, u32 val); -void clock_sdmmc_disable(u32 id); - -#endif diff --git a/emummc/source/soc/gpio.c b/emummc/source/soc/gpio.c deleted file mode 100644 index b84b0d254e..0000000000 --- a/emummc/source/soc/gpio.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2019 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "../soc/gpio.h" -#include "../soc/t210.h" - -#define GPIO_BANK_IDX(port) ((port) >> 2) - -#define GPIO_CNF_OFFSET(port) (0x00 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_OE_OFFSET(port) (0x10 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_OUT_OFFSET(port) (0x20 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_IN_OFFSET(port) (0x30 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_STA_OFFSET(port) (0x40 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_ENB_OFFSET(port) (0x50 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_LVL_OFFSET(port) (0x60 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_CLR_OFFSET(port) (0x70 + (((port) >> 2) << 8) + (((port) % 4) << 2)) - -#define GPIO_CNF_MASKED_OFFSET(port) (0x80 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_OE_MASKED_OFFSET(port) (0x90 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_OUT_MASKED_OFFSET(port) (0xA0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_STA_MASKED_OFFSET(port) (0xC0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_ENB_MASKED_OFFSET(port) (0xD0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_LVL_MASKED_OFFSET(port) (0xE0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) - -#define GPIO_IRQ_BANK1 32 -#define GPIO_IRQ_BANK2 33 -#define GPIO_IRQ_BANK3 34 -#define GPIO_IRQ_BANK4 35 -#define GPIO_IRQ_BANK5 55 -#define GPIO_IRQ_BANK6 87 -#define GPIO_IRQ_BANK7 89 -#define GPIO_IRQ_BANK8 125 - -static u8 gpio_bank_irq_ids[8] = { - GPIO_IRQ_BANK1, GPIO_IRQ_BANK2, GPIO_IRQ_BANK3, GPIO_IRQ_BANK4, - GPIO_IRQ_BANK5, GPIO_IRQ_BANK6, GPIO_IRQ_BANK7, GPIO_IRQ_BANK8 -}; - -void gpio_config(u32 port, u32 pins, int mode) -{ - u32 offset = GPIO_CNF_OFFSET(port); - - if (mode) - GPIO(offset) |= pins; - else - GPIO(offset) &= ~pins; - - (void)GPIO(offset); // Commit the write. -} - -void gpio_output_enable(u32 port, u32 pins, int enable) -{ - u32 port_offset = GPIO_OE_OFFSET(port); - - if (enable) - GPIO(port_offset) |= pins; - else - GPIO(port_offset) &= ~pins; - - (void)GPIO(port_offset); // Commit the write. -} - -void gpio_write(u32 port, u32 pins, int high) -{ - u32 port_offset = GPIO_OUT_OFFSET(port); - - if (high) - GPIO(port_offset) |= pins; - else - GPIO(port_offset) &= ~pins; - - (void)GPIO(port_offset); // Commit the write. -} - -int gpio_read(u32 port, u32 pins) -{ - u32 port_offset = GPIO_IN_OFFSET(port); - - return (GPIO(port_offset) & pins) ? 1 : 0; -} - -static void _gpio_interrupt_clear(u32 port, u32 pins) -{ - u32 port_offset = GPIO_INT_CLR_OFFSET(port); - - GPIO(port_offset) |= pins; - - (void)GPIO(port_offset); // Commit the write. -} - -int gpio_interrupt_status(u32 port, u32 pins) -{ - u32 port_offset = GPIO_INT_STA_OFFSET(port); - u32 enabled = GPIO(GPIO_INT_ENB_OFFSET(port)) & pins; - - int status = ((GPIO(port_offset) & pins) && enabled) ? 1 : 0; - - // Clear the interrupt status. - if (status) - _gpio_interrupt_clear(port, pins); - - return status; -} - -void gpio_interrupt_enable(u32 port, u32 pins, int enable) -{ - u32 port_offset = GPIO_INT_ENB_OFFSET(port); - - // Clear any possible stray interrupt. - _gpio_interrupt_clear(port, pins); - - if (enable) - GPIO(port_offset) |= pins; - else - GPIO(port_offset) &= ~pins; - - (void)GPIO(port_offset); // Commit the write. -} - -void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta) -{ - u32 port_offset = GPIO_INT_LVL_OFFSET(port); - - u32 val = GPIO(port_offset); - - if (high) - val |= pins; - else - val &= ~pins; - - if (edge) - val |= pins << 8; - else - val &= ~(pins << 8); - - if (delta) - val |= pins << 16; - else - val &= ~(pins << 16); - - GPIO(port_offset) = val; - - (void)GPIO(port_offset); // Commit the write. - - // Clear any possible stray interrupt. - _gpio_interrupt_clear(port, pins); -} - -u32 gpio_get_bank_irq_id(u32 port) -{ - u32 bank_idx = GPIO_BANK_IDX(port); - - return gpio_bank_irq_ids[bank_idx]; -} diff --git a/emummc/source/soc/gpio.h b/emummc/source/soc/gpio.h deleted file mode 100644 index a7f999db2e..0000000000 --- a/emummc/source/soc/gpio.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2019 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _GPIO_H_ -#define _GPIO_H_ - -#include "../utils/types.h" - -#define GPIO_MODE_SPIO 0 -#define GPIO_MODE_GPIO 1 - -#define GPIO_OUTPUT_DISABLE 0 -#define GPIO_OUTPUT_ENABLE 1 - -#define GPIO_IRQ_DISABLE 0 -#define GPIO_IRQ_ENABLE 1 - -#define GPIO_LOW 0 -#define GPIO_HIGH 1 -#define GPIO_FALLING 0 -#define GPIO_RISING 1 - -#define GPIO_LEVEL 0 -#define GPIO_EDGE 1 - -#define GPIO_CONFIGURED_EDGE 0 -#define GPIO_ANY_EDGE_CHANGE 1 - -/*! GPIO pins (0-7 for each port). */ -#define GPIO_PIN_0 (1 << 0) -#define GPIO_PIN_1 (1 << 1) -#define GPIO_PIN_2 (1 << 2) -#define GPIO_PIN_3 (1 << 3) -#define GPIO_PIN_4 (1 << 4) -#define GPIO_PIN_5 (1 << 5) -#define GPIO_PIN_6 (1 << 6) -#define GPIO_PIN_7 (1 << 7) - -/*! GPIO ports (A-EE). */ -#define GPIO_PORT_A 0 -#define GPIO_PORT_B 1 -#define GPIO_PORT_C 2 -#define GPIO_PORT_D 3 -#define GPIO_PORT_E 4 -#define GPIO_PORT_F 5 -#define GPIO_PORT_G 6 -#define GPIO_PORT_H 7 -#define GPIO_PORT_I 8 -#define GPIO_PORT_J 9 -#define GPIO_PORT_K 10 -#define GPIO_PORT_L 11 -#define GPIO_PORT_M 12 -#define GPIO_PORT_N 13 -#define GPIO_PORT_O 14 -#define GPIO_PORT_P 15 -#define GPIO_PORT_Q 16 -#define GPIO_PORT_R 17 -#define GPIO_PORT_S 18 -#define GPIO_PORT_T 19 -#define GPIO_PORT_U 20 -#define GPIO_PORT_V 21 -#define GPIO_PORT_W 22 -#define GPIO_PORT_X 23 -#define GPIO_PORT_Y 24 -#define GPIO_PORT_Z 25 -#define GPIO_PORT_AA 26 -#define GPIO_PORT_BB 27 -#define GPIO_PORT_CC 28 -#define GPIO_PORT_DD 29 -#define GPIO_PORT_EE 30 - -void gpio_config(u32 port, u32 pins, int mode); -void gpio_output_enable(u32 port, u32 pins, int enable); -void gpio_write(u32 port, u32 pins, int high); -int gpio_read(u32 port, u32 pins); -int gpio_interrupt_status(u32 port, u32 pins); -void gpio_interrupt_enable(u32 port, u32 pins, int enable); -void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta); -u32 gpio_get_bank_irq_id(u32 port); - -#endif diff --git a/emummc/source/soc/i2c.c b/emummc/source/soc/i2c.c deleted file mode 100644 index 32ef078bec..0000000000 --- a/emummc/source/soc/i2c.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "i2c.h" -#include "../utils/util.h" -#include "t210.h" - -#define I2C_PACKET_PROT_I2C (1 << 4) -#define I2C_HEADER_CONT_XFER (1 << 15) -#define I2C_HEADER_REP_START (1 << 16) -#define I2C_HEADER_IE_ENABLE (1 << 17) -#define I2C_HEADER_READ (1 << 19) - -#define I2C_CNFG (0x00 / 4) -#define CMD1_WRITE (0 << 6) -#define CMD1_READ (1 << 6) -#define NORMAL_MODE_GO (1 << 9) -#define PACKET_MODE_GO (1 << 10) -#define NEW_MASTER_FSM (1 << 11) -#define DEBOUNCE_CNT_4T (2 << 12) - -#define I2C_CMD_ADDR0 (0x04 / 4) -#define ADDR0_WRITE 0 -#define ADDR0_READ 1 - -#define I2C_CMD_DATA1 (0x0C / 4) -#define I2C_CMD_DATA2 (0x10 / 4) - -#define I2C_STATUS (0x1C / 4) -#define I2C_STATUS_NOACK (0xF << 0) -#define I2C_STATUS_BUSY (1 << 8) - -#define I2C_TX_FIFO (0x50 / 4) -#define I2C_RX_FIFO (0x54 / 4) - -#define I2C_FIFO_CONTROL (0x5C / 4) -#define RX_FIFO_FLUSH (1 << 0) -#define TX_FIFO_FLUSH (1 << 1) - -#define I2C_FIFO_STATUS (0x60 / 4) -#define RX_FIFO_FULL_CNT (0xF << 0) -#define TX_FIFO_EMPTY_CNT (0xF << 4) - -#define I2C_INT_EN (0x64 / 4) -#define I2C_INT_STATUS (0x68 / 4) -#define I2C_INT_SOURCE (0x70 / 4) -#define RX_FIFO_DATA_REQ (1 << 0) -#define TX_FIFO_DATA_REQ (1 << 1) -#define ARB_LOST (1 << 2) -#define NO_ACK (1 << 3) -#define RX_FIFO_UNDER (1 << 4) -#define TX_FIFO_OVER (1 << 5) -#define ALL_PACKETS_COMPLETE (1 << 6) -#define PACKET_COMPLETE (1 << 7) -#define BUS_CLEAR_DONE (1 << 11) - -#define I2C_CLK_DIVISOR (0x6C / 4) - -#define I2C_BUS_CLEAR_CONFIG (0x84 / 4) -#define BC_ENABLE (1 << 0) -#define BC_TERMINATE (1 << 1) - -#define I2C_BUS_CLEAR_STATUS (0x88 / 4) - -#define I2C_CONFIG_LOAD (0x8C / 4) -#define MSTR_CONFIG_LOAD (1 << 0) -#define TIMEOUT_CONFIG_LOAD (1 << 2) - -static const u64 i2c_addrs[] = { - 0x7000C000, // I2C_1. - 0x7000C400, // I2C_2. - 0x7000C500, // I2C_3. - 0x7000C700, // I2C_4. - 0x7000D000, // I2C_5. - 0x7000D100 // I2C_6. -}; - -static void _i2c_load_cfg_wait(vu32 *base) -{ - base[I2C_CONFIG_LOAD] = (1 << 5) | TIMEOUT_CONFIG_LOAD | MSTR_CONFIG_LOAD; - for (u32 i = 0; i < 20; i++) - { - usleep(1); - if (!(base[I2C_CONFIG_LOAD] & MSTR_CONFIG_LOAD)) - break; - } -} - -static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size) -{ - if (size > 4) - return 0; - - u32 tmp = 0; - memcpy(&tmp, buf, size); - - vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[I2C_5], 0x1000); - - // Set device address and send mode. - base[I2C_CMD_ADDR0] = dev_addr << 1 | ADDR0_WRITE; - base[I2C_CMD_DATA1] = tmp; //Set value. - // Set size and send mode. - base[I2C_CNFG] = ((size - 1) << 1) | DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_WRITE; - - // Load configuration. - _i2c_load_cfg_wait(base); - - // Initiate transaction on normal mode. - base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO; - - u64 timeout = get_tmr_ms() + 100; - while (base[I2C_STATUS] & I2C_STATUS_BUSY) - { - if (get_tmr_ms() > timeout) - return 0; - } - - if (base[I2C_STATUS] & I2C_STATUS_NOACK) - return 0; - - return 1; -} - -static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr) -{ - if (size > 4) - return 0; - - vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[I2C_5], 0x1000); - // Set device address and recv mode. - base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_READ; - - // Set size and recv mode. - base[I2C_CNFG] = ((size - 1) << 1) | DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_READ; - - // Load configuration. - _i2c_load_cfg_wait(base); - - // Initiate transaction on normal mode. - base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO; - - u64 timeout = get_tmr_ms() + 100; - while (base[I2C_STATUS] & I2C_STATUS_BUSY) - { - if (get_tmr_ms() > timeout) - return 0; - } - - if (base[I2C_STATUS] & I2C_STATUS_NOACK) - return 0; - - u32 tmp = base[I2C_CMD_DATA1]; // Get LS value. - if (size > 4) - { - memcpy(buf, &tmp, 4); - tmp = base[I2C_CMD_DATA2]; // Get MS value. - memcpy(buf + 4, &tmp, size - 4); - } - else - memcpy(buf, &tmp, size); - - return 1; -} - -void i2c_init() -{ - vu32 *base = (vu32 *)QueryIoMapping(i2c_addrs[I2C_5], 0x1000); - - base[I2C_CLK_DIVISOR] = (5 << 16) | 1; // SF mode Div: 6, HS mode div: 2. - base[I2C_BUS_CLEAR_CONFIG] = (9 << 16) | BC_TERMINATE | BC_ENABLE; - - // Load configuration. - _i2c_load_cfg_wait(base); - - for (u32 i = 0; i < 10; i++) - { - if (base[I2C_INT_STATUS] & BUS_CLEAR_DONE) - break; - } - - (vu32)base[I2C_BUS_CLEAR_STATUS]; - base[I2C_INT_STATUS] = base[I2C_INT_STATUS]; -} - -int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size) -{ - u8 tmp[4]; - - if (size > 3) - return 0; - - tmp[0] = reg; - memcpy(tmp + 1, buf, size); - - return _i2c_send_single(i2c_idx, dev_addr, tmp, size + 1); -} - -int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg) -{ - int res = _i2c_send_single(i2c_idx, dev_addr, (u8 *)®, 1); - if (res) - res = _i2c_recv_single(i2c_idx, buf, size, dev_addr); - return res; -} - -int i2c_send_byte(u32 i2c_idx, u32 dev_addr, u32 reg, u8 val) -{ - return i2c_send_buf_small(i2c_idx, dev_addr, reg, &val, 1); -} - -u8 i2c_recv_byte(u32 i2c_idx, u32 dev_addr, u32 reg) -{ - u8 tmp = 0; - i2c_recv_buf_small(&tmp, 1, i2c_idx, dev_addr, reg); - return tmp; -} - diff --git a/emummc/source/soc/i2c.h b/emummc/source/soc/i2c.h deleted file mode 100644 index 095974feee..0000000000 --- a/emummc/source/soc/i2c.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2020 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _I2C_H_ -#define _I2C_H_ - -#include "../utils/types.h" - -#define I2C_1 0 -#define I2C_2 1 -#define I2C_3 2 -#define I2C_4 3 -#define I2C_5 4 -#define I2C_6 5 - -void i2c_init(); -int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size); -int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg); -int i2c_send_byte(u32 i2c_idx, u32 dev_addr, u32 reg, u8 val); -u8 i2c_recv_byte(u32 i2c_idx, u32 dev_addr, u32 reg); - -#endif diff --git a/emummc/source/soc/pinmux.c b/emummc/source/soc/pinmux.c deleted file mode 100644 index 5966be2050..0000000000 --- a/emummc/source/soc/pinmux.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "../soc/pinmux.h" -#include "../soc/t210.h" - -void pinmux_config_i2c(u32 idx) -{ - PINMUX_AUX(PINMUX_AUX_X_I2C_SCL(idx)) = PINMUX_INPUT_ENABLE; - PINMUX_AUX(PINMUX_AUX_X_I2C_SDA(idx)) = PINMUX_INPUT_ENABLE; -} diff --git a/emummc/source/soc/pinmux.h b/emummc/source/soc/pinmux.h deleted file mode 100644 index 977d9b4d6a..0000000000 --- a/emummc/source/soc/pinmux.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _PINMUX_H_ -#define _PINMUX_H_ - -#include "../utils/types.h" - -/*! APB MISC registers. */ -#define APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL 0x8D4 -#define APB_MISC_GP_SDMMC3_CLK_LPBK_CONTROL 0x8D8 -#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL 0xA98 -#define APB_MISC_GP_VGPIO_GPIO_MUX_SEL 0xB74 - -/*! Pinmux registers. */ -#define PINMUX_AUX_SDMMC1_CLK 0x00 -#define PINMUX_AUX_SDMMC1_CMD 0x04 -#define PINMUX_AUX_SDMMC1_DAT3 0x08 -#define PINMUX_AUX_SDMMC1_DAT2 0x0C -#define PINMUX_AUX_SDMMC1_DAT1 0x10 -#define PINMUX_AUX_SDMMC1_DAT0 0x14 -#define PINMUX_AUX_SDMMC3_CLK 0x1C -#define PINMUX_AUX_SDMMC3_CMD 0x20 -#define PINMUX_AUX_SDMMC3_DAT0 0x24 -#define PINMUX_AUX_SDMMC3_DAT1 0x28 -#define PINMUX_AUX_SDMMC3_DAT2 0x2C -#define PINMUX_AUX_SDMMC3_DAT3 0x30 -#define PINMUX_AUX_DMIC3_CLK 0xB4 -#define PINMUX_AUX_UART2_TX 0xF4 -#define PINMUX_AUX_UART3_TX 0x104 -#define PINMUX_AUX_WIFI_EN 0x1B4 -#define PINMUX_AUX_WIFI_RST 0x1B8 -#define PINMUX_AUX_NFC_EN 0x1D0 -#define PINMUX_AUX_NFC_INT 0x1D4 -#define PINMUX_AUX_LCD_BL_PWM 0x1FC -#define PINMUX_AUX_LCD_BL_EN 0x200 -#define PINMUX_AUX_LCD_RST 0x204 -#define PINMUX_AUX_GPIO_PE6 0x248 -#define PINMUX_AUX_GPIO_PH6 0x250 -#define PINMUX_AUX_GPIO_PZ1 0x280 -/* Only in T210B01 */ -#define PINMUX_AUX_SDMMC2_DAT0 0x294 -#define PINMUX_AUX_SDMMC2_DAT1 0x298 -#define PINMUX_AUX_SDMMC2_DAT2 0x29C -#define PINMUX_AUX_SDMMC2_DAT3 0x2A0 -#define PINMUX_AUX_SDMMC2_DAT4 0x2A4 -#define PINMUX_AUX_SDMMC2_DAT5 0x2A8 -#define PINMUX_AUX_SDMMC2_DAT6 0x2AC -#define PINMUX_AUX_SDMMC2_DAT7 0x2B0 -#define PINMUX_AUX_SDMMC2_CLK 0x2B4 -#define PINMUX_AUX_SDMMC2_CMD 0x2BC - -/*! 0:UART-A, 1:UART-B, 3:UART-C, 3:UART-D */ -#define PINMUX_AUX_UARTX_TX(x) (0xE4 + 0x10 * (x)) -#define PINMUX_AUX_UARTX_RX(x) (0xE8 + 0x10 * (x)) -#define PINMUX_AUX_UARTX_RTS(x) (0xEC + 0x10 * (x)) -#define PINMUX_AUX_UARTX_CTS(x) (0xF0 + 0x10 * (x)) -/*! 0:GEN1, 1:GEN2, 2:GEN3, 3:CAM, 4:PWR */ -#define PINMUX_AUX_X_I2C_SCL(x) (0xBC + 8 * (x)) -#define PINMUX_AUX_X_I2C_SDA(x) (0xC0 + 8 * (x)) - -#define PINMUX_FUNC_MASK (3 << 0) - -#define PINMUX_PULL_MASK (3 << 2) -#define PINMUX_PULL_NONE (0 << 2) -#define PINMUX_PULL_DOWN (1 << 2) -#define PINMUX_PULL_UP (2 << 2) - -#define PINMUX_TRISTATE (1 << 4) -#define PINMUX_PARKED (1 << 5) -#define PINMUX_INPUT_ENABLE (1 << 6) -#define PINMUX_LOCK (1 << 7) -#define PINMUX_LPDR (1 << 8) -#define PINMUX_HSM (1 << 9) - -#define PINMUX_IO_HV (1 << 10) -#define PINMUX_OPEN_DRAIN (1 << 11) -#define PINMUX_SCHMT (1 << 12) - -#define PINMUX_DRIVE_MASK (3 << 13) -#define PINMUX_DRIVE_1X (0 << 13) -#define PINMUX_DRIVE_2X (1 << 13) -#define PINMUX_DRIVE_3X (2 << 13) -#define PINMUX_DRIVE_4X (3 << 13) - -void pinmux_config_i2c(u32 idx); - -#endif diff --git a/emummc/source/soc/pmc.h b/emummc/source/soc/pmc.h deleted file mode 100644 index 8cd916160a..0000000000 --- a/emummc/source/soc/pmc.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (c) 2018 st4rk - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _PMC_H_ -#define _PMC_H_ - -/*! PMC registers. */ -#define APBDEV_PMC_CNTRL 0x0 -#define PMC_CNTRL_MAIN_RST (1 << 4) -#define APBDEV_PMC_SEC_DISABLE 0x4 -#define APBDEV_PMC_PWRGATE_TOGGLE 0x30 -#define APBDEV_PMC_PWRGATE_STATUS 0x38 -#define APBDEV_PMC_NO_IOPOWER 0x44 -#define PMC_NO_IOPOWER_SDMMC1_IO_EN (1 << 12) -#define APBDEV_PMC_SCRATCH0 0x50 -#define APBDEV_PMC_SCRATCH1 0x54 -#define APBDEV_PMC_SCRATCH20 0xA0 -#define APBDEV_PMC_PWR_DET_VAL 0xE4 -#define PMC_PWR_DET_SDMMC1_IO_EN (1 << 12) -#define APBDEV_PMC_DDR_PWR 0xE8 -#define APBDEV_PMC_CRYPTO_OP 0xF4 -#define PMC_CRYPTO_OP_SE_ENABLE 0 -#define PMC_CRYPTO_OP_SE_DISABLE 1 -#define APBDEV_PMC_SCRATCH33 0x120 -#define APBDEV_PMC_SCRATCH40 0x13C -#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4 -#define PMC_OSC_EDPD_OVER_OSC_CTRL_OVER 0x400000 -#define APBDEV_PMC_RST_STATUS 0x1B4 -#define APBDEV_PMC_IO_DPD_REQ 0x1B8 -#define APBDEV_PMC_IO_DPD2_REQ 0x1C0 -#define APBDEV_PMC_VDDP_SEL 0x1CC -#define APBDEV_PMC_DDR_CFG 0x1D0 -#define APBDEV_PMC_SCRATCH45 0x234 -#define APBDEV_PMC_SCRATCH46 0x238 -#define APBDEV_PMC_SCRATCH49 0x244 -#define APBDEV_PMC_TSC_MULT 0x2B4 -#define APBDEV_PMC_SEC_DISABLE2 0x2C4 -#define APBDEV_PMC_WEAK_BIAS 0x2C8 -#define APBDEV_PMC_REG_SHORT 0x2CC -#define APBDEV_PMC_SEC_DISABLE3 0x2D8 -#define APBDEV_PMC_SECURE_SCRATCH21 0x334 -#define PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT 0x10 -#define APBDEV_PMC_SECURE_SCRATCH32 0x360 -#define APBDEV_PMC_SECURE_SCRATCH49 0x3A4 -#define APBDEV_PMC_CNTRL2 0x440 -#define PMC_CNTRL2_HOLD_CKE_LOW_EN 0x1000 -#define APBDEV_PMC_IO_DPD3_REQ 0x45C -#define APBDEV_PMC_IO_DPD4_REQ 0x464 -#define APBDEV_PMC_UTMIP_PAD_CFG1 0x4C4 -#define APBDEV_PMC_UTMIP_PAD_CFG3 0x4CC -#define APBDEV_PMC_DDR_CNTRL 0x4E4 -#define APBDEV_PMC_SEC_DISABLE4 0x5B0 -#define APBDEV_PMC_SEC_DISABLE5 0x5B4 -#define APBDEV_PMC_SEC_DISABLE6 0x5B8 -#define APBDEV_PMC_SEC_DISABLE7 0x5BC -#define APBDEV_PMC_SEC_DISABLE8 0x5C0 -#define APBDEV_PMC_SCRATCH188 0x810 -#define APBDEV_PMC_SCRATCH190 0x818 -#define APBDEV_PMC_SCRATCH200 0x840 - -#endif diff --git a/emummc/source/soc/pmc_lp0_t210.h b/emummc/source/soc/pmc_lp0_t210.h deleted file mode 100644 index 641d9f7355..0000000000 --- a/emummc/source/soc/pmc_lp0_t210.h +++ /dev/null @@ -1,564 +0,0 @@ -/* - * Copyright (c) 2010-2015, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#ifndef _TEGRA210_PMC_H_ -#define _TEGRA210_PMC_H_ - -#include "../utils/types.h" - -struct tegra_pmc_regs -{ - u32 cntrl; - u32 sec_disable; - u32 pmc_swrst; - u32 wake_mask; - u32 wake_lvl; - u32 wake_status; - u32 sw_wake_status; - u32 dpd_pads_oride; - u32 dpd_sample; - u32 dpd_enable; - u32 pwrgate_timer_off; - u32 clamp_status; - u32 pwrgate_toggle; - u32 remove_clamping_cmd; - u32 pwrgate_status; - u32 pwrgood_timer; - u32 blink_timer; - u32 no_iopower; - u32 pwr_det; - u32 pwr_det_latch; - u32 scratch0; - u32 scratch1; - u32 scratch2; - u32 scratch3; - u32 scratch4; - u32 scratch5; - u32 scratch6; - u32 scratch7; - u32 scratch8; - u32 scratch9; - u32 scratch10; - u32 scratch11; - u32 scratch12; - u32 scratch13; - u32 scratch14; - u32 scratch15; - u32 scratch16; - u32 scratch17; - u32 scratch18; - u32 scratch19; - u32 odmdata; - u32 scratch21; - u32 scratch22; - u32 scratch23; - u32 secure_scratch0; - u32 secure_scratch1; - u32 secure_scratch2; - u32 secure_scratch3; - u32 secure_scratch4; - u32 secure_scratch5; - u32 cpupwrgood_timer; - u32 cpupwroff_timer; - u32 pg_mask; - u32 pg_mask_1; - u32 auto_wake_lvl; - u32 auto_wake_lvl_mask; - u32 wake_delay; - u32 pwr_det_val; - u32 ddr_pwr; - u32 usb_debounce_del; - u32 usb_a0; - u32 crypto_op; - u32 pllp_wb0_override; - u32 scratch24; - u32 scratch25; - u32 scratch26; - u32 scratch27; - u32 scratch28; - u32 scratch29; - u32 scratch30; - u32 scratch31; - u32 scratch32; - u32 scratch33; - u32 scratch34; - u32 scratch35; - u32 scratch36; - u32 scratch37; - u32 scratch38; - u32 scratch39; - u32 scratch40; - u32 scratch41; - u32 scratch42; - u32 bondout_mirror[3]; - u32 sys_33v_en; - u32 bondout_mirror_access; - u32 gate; - u32 wake2_mask; - u32 wake2_lvl; - u32 wake2_status; - u32 sw_wake2_status; - u32 auto_wake2_lvl_mask; - u32 pg_mask_2; - u32 pg_mask_ce1; - u32 pg_mask_ce2; - u32 pg_mask_ce3; - u32 pwrgate_timer_ce[7]; - u32 pcx_edpd_cntrl; - u32 osc_edpd_over; - u32 clk_out_cntrl; - u32 sata_pwrgt; - u32 sensor_ctrl; - u32 rst_status; - u32 io_dpd_req; - u32 io_dpd_status; - u32 io_dpd2_req; - u32 io_dpd2_status; - u32 sel_dpd_tim; - u32 vddp_sel; - u32 ddr_cfg; - u32 e_no_vttgen; - u8 _rsv0[4]; - u32 pllm_wb0_override_freq; - u32 test_pwrgate; - u32 pwrgate_timer_mult; - u32 dis_sel_dpd; - u32 utmip_uhsic_triggers; - u32 utmip_uhsic_saved_state; - u32 utmip_pad_cfg; - u32 utmip_term_pad_cfg; - u32 utmip_uhsic_sleep_cfg; - u32 utmip_uhsic_sleepwalk_cfg; - u32 utmip_sleepwalk_p[3]; - u32 uhsic_sleepwalk_p0; - u32 utmip_uhsic_status; - u32 utmip_uhsic_fake; - u32 bondout_mirror3[5 - 3]; - u32 secure_scratch6; - u32 secure_scratch7; - u32 scratch43; - u32 scratch44; - u32 scratch45; - u32 scratch46; - u32 scratch47; - u32 scratch48; - u32 scratch49; - u32 scratch50; - u32 scratch51; - u32 scratch52; - u32 scratch53; - u32 scratch54; - u32 scratch55; - u32 scratch0_eco; - u32 por_dpd_ctrl; - u32 scratch2_eco; - u32 utmip_uhsic_line_wakeup; - u32 utmip_bias_master_cntrl; - u32 utmip_master_config; - u32 td_pwrgate_inter_part_timer; - u32 utmip_uhsic2_triggers; - u32 utmip_uhsic2_saved_state; - u32 utmip_uhsic2_sleep_cfg; - u32 utmip_uhsic2_sleepwalk_cfg; - u32 uhsic2_sleepwalk_p1; - u32 utmip_uhsic2_status; - u32 utmip_uhsic2_fake; - u32 utmip_uhsic2_line_wakeup; - u32 utmip_master2_config; - u32 utmip_uhsic_rpd_cfg; - u32 pg_mask_ce0; - u32 pg_mask3[5 - 3]; - u32 pllm_wb0_override2; - u32 tsc_mult; - u32 cpu_vsense_override; - u32 glb_amap_cfg; - u32 sticky_bits; - u32 sec_disable2; - u32 weak_bias; - u32 reg_short; - u32 pg_mask_andor; - u8 _rsv1[0x2c]; - u32 secure_scratch8; /* offset 0x300 */ - u32 secure_scratch9; - u32 secure_scratch10; - u32 secure_scratch11; - u32 secure_scratch12; - u32 secure_scratch13; - u32 secure_scratch14; - u32 secure_scratch15; - u32 secure_scratch16; - u32 secure_scratch17; - u32 secure_scratch18; - u32 secure_scratch19; - u32 secure_scratch20; - u32 secure_scratch21; - u32 secure_scratch22; - u32 secure_scratch23; - u32 secure_scratch24; - u32 secure_scratch25; - u32 secure_scratch26; - u32 secure_scratch27; - u32 secure_scratch28; - u32 secure_scratch29; - u32 secure_scratch30; - u32 secure_scratch31; - u32 secure_scratch32; - u32 secure_scratch33; - u32 secure_scratch34; - u32 secure_scratch35; - u32 secure_scratch36; - u32 secure_scratch37; - u32 secure_scratch38; - u32 secure_scratch39; - u32 secure_scratch40; - u32 secure_scratch41; - u32 secure_scratch42; - u32 secure_scratch43; - u32 secure_scratch44; - u32 secure_scratch45; - u32 secure_scratch46; - u32 secure_scratch47; - u32 secure_scratch48; - u32 secure_scratch49; - u32 secure_scratch50; - u32 secure_scratch51; - u32 secure_scratch52; - u32 secure_scratch53; - u32 secure_scratch54; - u32 secure_scratch55; - u32 secure_scratch56; - u32 secure_scratch57; - u32 secure_scratch58; - u32 secure_scratch59; - u32 secure_scratch60; - u32 secure_scratch61; - u32 secure_scratch62; - u32 secure_scratch63; - u32 secure_scratch64; - u32 secure_scratch65; - u32 secure_scratch66; - u32 secure_scratch67; - u32 secure_scratch68; - u32 secure_scratch69; - u32 secure_scratch70; - u32 secure_scratch71; - u32 secure_scratch72; - u32 secure_scratch73; - u32 secure_scratch74; - u32 secure_scratch75; - u32 secure_scratch76; - u32 secure_scratch77; - u32 secure_scratch78; - u32 secure_scratch79; - u32 _rsv0x420[8]; - u32 cntrl2; /* 0x440 */ - u32 _rsv0x444[2]; - u32 event_counter; /* 0x44C */ - u32 fuse_control; - u32 scratch1_eco; - u32 _rsv0x458[1]; - u32 io_dpd3_req; /* 0x45C */ - u32 io_dpd3_status; - u32 io_dpd4_req; - u32 io_dpd4_status; - u32 _rsv0x46C[30]; - u32 ddr_cntrl; /* 0x4E4 */ - u32 _rsv0x4E8[70]; - u32 scratch56; /* 0x600 */ - u32 scratch57; - u32 scratch58; - u32 scratch59; - u32 scratch60; - u32 scratch61; - u32 scratch62; - u32 scratch63; - u32 scratch64; - u32 scratch65; - u32 scratch66; - u32 scratch67; - u32 scratch68; - u32 scratch69; - u32 scratch70; - u32 scratch71; - u32 scratch72; - u32 scratch73; - u32 scratch74; - u32 scratch75; - u32 scratch76; - u32 scratch77; - u32 scratch78; - u32 scratch79; - u32 scratch80; - u32 scratch81; - u32 scratch82; - u32 scratch83; - u32 scratch84; - u32 scratch85; - u32 scratch86; - u32 scratch87; - u32 scratch88; - u32 scratch89; - u32 scratch90; - u32 scratch91; - u32 scratch92; - u32 scratch93; - u32 scratch94; - u32 scratch95; - u32 scratch96; - u32 scratch97; - u32 scratch98; - u32 scratch99; - u32 scratch100; - u32 scratch101; - u32 scratch102; - u32 scratch103; - u32 scratch104; - u32 scratch105; - u32 scratch106; - u32 scratch107; - u32 scratch108; - u32 scratch109; - u32 scratch110; - u32 scratch111; - u32 scratch112; - u32 scratch113; - u32 scratch114; - u32 scratch115; - u32 scratch116; - u32 scratch117; - u32 scratch118; - u32 scratch119; - u32 scratch120; /* 0x700 */ - u32 scratch121; - u32 scratch122; - u32 scratch123; - u32 scratch124; - u32 scratch125; - u32 scratch126; - u32 scratch127; - u32 scratch128; - u32 scratch129; - u32 scratch130; - u32 scratch131; - u32 scratch132; - u32 scratch133; - u32 scratch134; - u32 scratch135; - u32 scratch136; - u32 scratch137; - u32 scratch138; - u32 scratch139; - u32 scratch140; - u32 scratch141; - u32 scratch142; - u32 scratch143; - u32 scratch144; - u32 scratch145; - u32 scratch146; - u32 scratch147; - u32 scratch148; - u32 scratch149; - u32 scratch150; - u32 scratch151; - u32 scratch152; - u32 scratch153; - u32 scratch154; - u32 scratch155; - u32 scratch156; - u32 scratch157; - u32 scratch158; - u32 scratch159; - u32 scratch160; - u32 scratch161; - u32 scratch162; - u32 scratch163; - u32 scratch164; - u32 scratch165; - u32 scratch166; - u32 scratch167; - u32 scratch168; - u32 scratch169; - u32 scratch170; - u32 scratch171; - u32 scratch172; - u32 scratch173; - u32 scratch174; - u32 scratch175; - u32 scratch176; - u32 scratch177; - u32 scratch178; - u32 scratch179; - u32 scratch180; - u32 scratch181; - u32 scratch182; - u32 scratch183; - u32 scratch184; - u32 scratch185; - u32 scratch186; - u32 scratch187; - u32 scratch188; - u32 scratch189; - u32 scratch190; - u32 scratch191; - u32 scratch192; - u32 scratch193; - u32 scratch194; - u32 scratch195; - u32 scratch196; - u32 scratch197; - u32 scratch198; - u32 scratch199; - u32 scratch200; - u32 scratch201; - u32 scratch202; - u32 scratch203; - u32 scratch204; - u32 scratch205; - u32 scratch206; - u32 scratch207; - u32 scratch208; - u32 scratch209; - u32 scratch210; - u32 scratch211; - u32 scratch212; - u32 scratch213; - u32 scratch214; - u32 scratch215; - u32 scratch216; - u32 scratch217; - u32 scratch218; - u32 scratch219; - u32 scratch220; - u32 scratch221; - u32 scratch222; - u32 scratch223; - u32 scratch224; - u32 scratch225; - u32 scratch226; - u32 scratch227; - u32 scratch228; - u32 scratch229; - u32 scratch230; - u32 scratch231; - u32 scratch232; - u32 scratch233; - u32 scratch234; - u32 scratch235; - u32 scratch236; - u32 scratch237; - u32 scratch238; - u32 scratch239; - u32 scratch240; - u32 scratch241; - u32 scratch242; - u32 scratch243; - u32 scratch244; - u32 scratch245; - u32 scratch246; - u32 scratch247; - u32 scratch248; - u32 scratch249; - u32 scratch250; - u32 scratch251; - u32 scratch252; - u32 scratch253; - u32 scratch254; - u32 scratch255; - u32 scratch256; - u32 scratch257; - u32 scratch258; - u32 scratch259; - u32 scratch260; - u32 scratch261; - u32 scratch262; - u32 scratch263; - u32 scratch264; - u32 scratch265; - u32 scratch266; - u32 scratch267; - u32 scratch268; - u32 scratch269; - u32 scratch270; - u32 scratch271; - u32 scratch272; - u32 scratch273; - u32 scratch274; - u32 scratch275; - u32 scratch276; - u32 scratch277; - u32 scratch278; - u32 scratch279; - u32 scratch280; - u32 scratch281; - u32 scratch282; - u32 scratch283; - u32 scratch284; - u32 scratch285; - u32 scratch286; - u32 scratch287; - u32 scratch288; - u32 scratch289; - u32 scratch290; - u32 scratch291; - u32 scratch292; - u32 scratch293; - u32 scratch294; - u32 scratch295; - u32 scratch296; - u32 scratch297; - u32 scratch298; - u32 scratch299; /* 0x9CC */ - u32 _rsv0x9D0[50]; - u32 secure_scratch80; /* 0xa98 */ - u32 secure_scratch81; - u32 secure_scratch82; - u32 secure_scratch83; - u32 secure_scratch84; - u32 secure_scratch85; - u32 secure_scratch86; - u32 secure_scratch87; - u32 secure_scratch88; - u32 secure_scratch89; - u32 secure_scratch90; - u32 secure_scratch91; - u32 secure_scratch92; - u32 secure_scratch93; - u32 secure_scratch94; - u32 secure_scratch95; - u32 secure_scratch96; - u32 secure_scratch97; - u32 secure_scratch98; - u32 secure_scratch99; - u32 secure_scratch100; - u32 secure_scratch101; - u32 secure_scratch102; - u32 secure_scratch103; - u32 secure_scratch104; - u32 secure_scratch105; - u32 secure_scratch106; - u32 secure_scratch107; - u32 secure_scratch108; - u32 secure_scratch109; - u32 secure_scratch110; - u32 secure_scratch111; - u32 secure_scratch112; - u32 secure_scratch113; - u32 secure_scratch114; - u32 secure_scratch115; - u32 secure_scratch116; - u32 secure_scratch117; - u32 secure_scratch118; - u32 secure_scratch119; -}; - -#endif /* _TEGRA210_PMC_H_ */ diff --git a/emummc/source/soc/t210.h b/emummc/source/soc/t210.h deleted file mode 100644 index 8e6f3cfa94..0000000000 --- a/emummc/source/soc/t210.h +++ /dev/null @@ -1,123 +0,0 @@ -/* -* Copyright (c) 2018 naehrwert -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef _T210_H_ -#define _T210_H_ - -#include "../utils/types.h" - -intptr_t QueryIoMapping(u64 addr, u64 size); - -#define TMR_BASE 0x60005000 -#define CLOCK_BASE 0x60006000 -#define GPIO_BASE 0x6000D000 -#define GPIO_1_BASE (GPIO_BASE) -#define GPIO_2_BASE (GPIO_BASE + 0x100) -#define GPIO_3_BASE (GPIO_BASE + 0x200) -#define GPIO_4_BASE (GPIO_BASE + 0x300) -#define GPIO_5_BASE (GPIO_BASE + 0x400) -#define GPIO_6_BASE (GPIO_BASE + 0x500) -#define GPIO_7_BASE (GPIO_BASE + 0x600) -#define GPIO_8_BASE (GPIO_BASE + 0x700) -#define APB_MISC_BASE 0x70000000 -#define PINMUX_AUX_BASE 0x70003000 -#define PWM_BASE 0x7000A000 -#define RTC_BASE 0x7000E000 -#define PMC_BASE 0x7000E400 - -#define _REG(base, off) *(vu32 *)(QueryIoMapping((u64)base, 0) + (off)) -#define _REG_IO(base, off, size) *(vu32 *)(QueryIoMapping((u64)base, size) + (off)) - -#define RTC(off) _REG_IO(RTC_BASE, off, 0x4000) -#define TMR(off) _REG_IO(TMR_BASE, off, 0x3FF) -#define CLOCK(off) _REG_IO(CLOCK_BASE, off, 0x1000) - -#define PMC(off) _REG_IO(PMC_BASE, off, 0x1000) // ?????????? - -#define APB_MISC(off) _REG_IO(APB_MISC_BASE, off, 0x4000) -#define PINMUX_AUX(off) _REG_IO(APB_MISC_BASE, off + (PINMUX_AUX_BASE - APB_MISC_BASE), 0x4000) - -#define GPIO(off) _REG_IO(GPIO_BASE, off, 0x1000) -#define GPIO_1(off) _REG_IO(GPIO_BASE, off + (GPIO_1_BASE - GPIO_BASE), 0x1000) -#define GPIO_2(off) _REG_IO(GPIO_BASE, off + (GPIO_2_BASE - GPIO_BASE), 0x1000) -#define GPIO_3(off) _REG_IO(GPIO_BASE, off + (GPIO_3_BASE - GPIO_BASE), 0x1000) -#define GPIO_4(off) _REG_IO(GPIO_BASE, off + (GPIO_4_BASE - GPIO_BASE), 0x1000) -#define GPIO_5(off) _REG_IO(GPIO_BASE, off + (GPIO_5_BASE - GPIO_BASE), 0x1000) -#define GPIO_6(off) _REG_IO(GPIO_BASE, off + (GPIO_6_BASE - GPIO_BASE), 0x1000) -#define GPIO_7(off) _REG_IO(GPIO_BASE, off + (GPIO_7_BASE - GPIO_BASE), 0x1000) -#define GPIO_8(off) _REG_IO(GPIO_BASE, off + (GPIO_8_BASE - GPIO_BASE), 0x1000) - -#define HOST1X(off) _REG(HOST1X_BASE, off) -#define BPMP_CACHE_CTRL(off) _REG(BPMP_CACHE_BASE, off) -#define DISPLAY_A(off) _REG(DISPLAY_A_BASE, off) -#define DSI(off) _REG(DSI_BASE, off) -#define VIC(off) _REG(VIC_BASE, off) -#define TSEC(off) _REG(TSEC_BASE, off) -#define SOR1(off) _REG(SOR1_BASE, off) -#define FLOW_CTLR(off) _REG(FLOW_CTLR_BASE, off) -#define SYSREG(off) _REG(SYSREG_BASE, off) -#define SB(off) _REG(SB_BASE, off) -#define EXCP_VEC(off) _REG(EXCP_VEC_BASE, off) -#define PWM(off) _REG(PWM_BASE, off) -#define SYSCTR0(off) _REG(SYSCTR0_BASE, off) -#define FUSE(off) _REG(FUSE_BASE, off) -#define KFUSE(off) _REG(KFUSE_BASE, off) -#define SE(off) _REG(SE_BASE, off) -#define MC(off) _REG(MC_BASE, off) -#define EMC(off) _REG(EMC_BASE, off) -#define MIPI_CAL(off) _REG(MIPI_CAL_BASE, off) -#define I2S(off) _REG(I2S_BASE, off) -#define CL_DVFS(off) _REG(CL_DVFS_BASE, off) -#define TEST_REG(off) _REG(0x0, off) - -/*! Misc registers. */ -#define APB_MISC_PP_STRAPPING_OPT_A 0x08 -#define APB_MISC_PP_PINMUX_GLOBAL 0x40 -#define APB_MISC_GP_LCD_BL_PWM_CFGPADCTRL 0xA34 -#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL 0xA98 -#define APB_MISC_GP_EMMC2_PAD_CFGPADCTRL 0xA9C -#define APB_MISC_GP_EMMC4_PAD_CFGPADCTRL 0xAB4 -#define APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL 0xABC -#define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64 -#define APB_MISC_GP_WIFI_RST_CFGPADCTRL 0xB68 - -/*! System registers. */ -#define AHB_ARBITRATION_XBAR_CTRL 0xE0 -#define AHB_AHB_SPARE_REG 0x110 - -/*! RTC registers. */ -#define APBDEV_RTC_SECONDS 0x8 -#define APBDEV_RTC_SHADOW_SECONDS 0xC -#define APBDEV_RTC_MILLI_SECONDS 0x10 - -/*! TMR registers. */ -#define TIMERUS_CNTR_1US (0x10 + 0x0) -#define TIMERUS_USEC_CFG (0x10 + 0x4) -#define TIMER_TMR9_TMR_PTV 0x80 -#define TIMER_EN (1 << 31) -#define TIMER_PER_EN (1 << 30) -#define TIMER_WDT4_CONFIG (0x100 + 0x80) -#define TIMER_SRC(TMR) (TMR & 0xF) -#define TIMER_PER(PER) ((PER & 0xFF) << 4) -#define TIMER_SYSRESET_EN (1 << 14) -#define TIMER_PMCRESET_EN (1 << 15) -#define TIMER_WDT4_COMMAND (0x108 + 0x80) -#define TIMER_START_CNT (1 << 0) -#define TIMER_CNT_DISABLE (1 << 1) -#define TIMER_WDT4_UNLOCK_PATTERN (0x10C + 0x80) -#define TIMER_MAGIC_PTRN 0xC45A - -#endif diff --git a/emummc/source/utils/fatal.c b/emummc/source/utils/fatal.c deleted file mode 100644 index 0c912b6048..0000000000 --- a/emummc/source/utils/fatal.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include "fatal.h" - -void __attribute__((noreturn)) fatal_abort(enum FatalReason abortReason) -{ - atmosphere_fatal_error_ctx error_ctx; - memset(&error_ctx, 0, sizeof(atmosphere_fatal_error_ctx)); - - // Basic error storage for Atmosphere - // TODO: Maybe include a small reboot2payload stub? - error_ctx.magic = ATMOSPHERE_REBOOT_TO_FATAL_MAGIC; - error_ctx.title_id = 0x0100000000000000; // FS - error_ctx.error_desc = abortReason; - - // Copy fatal context - smcCopyToIram(ATMOSPHERE_FATAL_ERROR_ADDR, &error_ctx, sizeof(atmosphere_fatal_error_ctx)); - - // Reboot to RCM - smcRebootToRcm(); - - while (true) - ; // Should never be reached -} diff --git a/emummc/source/utils/fatal.h b/emummc/source/utils/fatal.h deleted file mode 100644 index 977c713ef3..0000000000 --- a/emummc/source/utils/fatal.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2019 m4xw - * Copyright (c) 2019 Atmosphere-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once -#include "../nx/smc.h" - -enum FatalReason -{ - Fatal_InitMMC = 0, - Fatal_InitSD, - Fatal_InvalidAccessor, - Fatal_ReadNoAccessor, - Fatal_WriteNoAccessor, - Fatal_IoMappingLegacy, - Fatal_UnknownVersion, - Fatal_BadResult, - Fatal_GetConfig, - Fatal_OpenAccessor, - Fatal_CloseAccessor, - Fatal_IoMapping, - Fatal_FatfsMount, - Fatal_FatfsFileOpen, - Fatal_FatfsMemExhaustion, - Fatal_InvalidEnum, - Fatal_Max -}; - -#define AMS_FATAL_ERROR_MAX_STACKTRACE 0x20 -#define AMS_FATAL_ERROR_MAX_STACKDUMP 0x100 - -/* Atmosphere reboot-to-fatal-error. */ -typedef struct -{ - uint32_t magic; - uint32_t error_desc; - uint64_t title_id; - union { - uint64_t gprs[32]; - struct - { - uint64_t _gprs[29]; - uint64_t fp; - uint64_t lr; - uint64_t sp; - }; - }; - uint64_t pc; - uint64_t module_base; - uint32_t pstate; - uint32_t afsr0; - uint32_t afsr1; - uint32_t esr; - uint64_t far; - uint64_t report_identifier; /* Normally just system tick. */ - uint64_t stack_trace_size; - uint64_t stack_dump_size; - uint64_t stack_trace[AMS_FATAL_ERROR_MAX_STACKTRACE]; - uint8_t stack_dump[AMS_FATAL_ERROR_MAX_STACKDUMP]; -} atmosphere_fatal_error_ctx; - -/* "AFE1" */ -#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC 0x31454641 -/* "AFE0" */ -#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_0 0x30454641 - -#define ATMOSPHERE_FATAL_ERROR_ADDR 0x4003E000 -#define ATMOSPHERE_FATAL_ERROR_CONTEXT ((volatile atmosphere_fatal_error_ctx *)(ATMOSPHERE_FATAL_ERROR_ADDR)) - -void __attribute__((noreturn)) fatal_abort(enum FatalReason abortReason); diff --git a/emummc/source/utils/types.h b/emummc/source/utils/types.h deleted file mode 100644 index ce4db820ca..0000000000 --- a/emummc/source/utils/types.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -* Copyright (c) 2018 naehrwert -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef _TYPES_H_ -#define _TYPES_H_ - -#include - -#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -#define OFFSET_OF(t, m) ((u32)&((t *)NULL)->m) -#define CONTAINER_OF(mp, t, mn) ((t *)((u32)mp - OFFSET_OF(t, mn))) - -/// Creates a bitmask from a bit number. -#ifndef BIT -#define BIT(n) (1U<<(n)) -#endif - -typedef int8_t s8; -typedef int16_t s16; -typedef int16_t SHORT; -typedef int32_t s32; -typedef int32_t INT; -typedef int64_t LONG; -typedef int64_t s64; -typedef uint8_t u8; -typedef uint8_t BYTE; -typedef uint16_t u16; -typedef uint16_t WORD; -typedef uint16_t WCHAR; -typedef uint32_t u32; -typedef uint32_t UINT; -typedef uint32_t DWORD; -typedef uint64_t QWORD; -typedef uint64_t u64; -typedef volatile uint8_t vu8; -typedef volatile uint16_t vu16; -typedef volatile uint32_t vu32; - -typedef u32 Handle; ///< Kernel object handle. -typedef u32 Result; ///< Function error code result type. - -#define INVALID_HANDLE ((Handle) 0) -#define CUR_PROCESS_HANDLE ((Handle) 0xFFFF8001) - -#ifndef __cplusplus -typedef int bool; -#define true 1 -#define false 0 -#endif /* __cplusplus */ - -#define BOOT_CFG_AUTOBOOT_EN (1 << 0) -#define BOOT_CFG_FROM_LAUNCH (1 << 1) -#define BOOT_CFG_SEPT_RUN (1 << 7) - -#define EXTRA_CFG_KEYS (1 << 0) -#define EXTRA_CFG_PAYLOAD (1 << 1) -#define EXTRA_CFG_MODULE (1 << 2) - -typedef struct __attribute__((__packed__)) _boot_cfg_t -{ - u8 boot_cfg; - u8 autoboot; - u8 autoboot_list; - u8 extra_cfg; - u8 rsvd[128]; -} boot_cfg_t; - -typedef struct __attribute__((__packed__)) _ipl_ver_meta_t -{ - u32 magic; - u32 version; - u16 rsvd0; - u16 rsvd1; -} ipl_ver_meta_t; - -typedef struct __attribute__((__packed__)) _reloc_meta_t -{ - u32 start; - u32 stack; - u32 end; - u32 ep; -} reloc_meta_t; - -#endif diff --git a/emummc/source/utils/util.c b/emummc/source/utils/util.c deleted file mode 100644 index e2fa527a51..0000000000 --- a/emummc/source/utils/util.c +++ /dev/null @@ -1,119 +0,0 @@ -/* -* Copyright (c) 2018 naehrwert -* Copyright (C) 2018 CTCaer -* Copyright (C) 2019 M4xw -* Copyright (c) 2019 Atmosphere-NX -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "util.h" -#include "fatal.h" -#include "types.h" -#include "../nx/counter.h" -#include "../nx/svc.h" -#include "../soc/t210.h" - -typedef struct _io_mapping_t -{ - u64 phys; - u64 virt; - u64 size; -} io_mapping_t; -static io_mapping_t io_mapping_list[10] = {0}; // Max 10 Mappings -#define IO_MAPPING_COUNT (sizeof(io_mapping_list) / sizeof(io_mapping_t)) - -static inline uintptr_t _GetIoMapping(u64 io_addr, u64 io_size) -{ - u64 vaddr; - u64 aligned_addr = (io_addr & ~0xFFFul); - u64 aligned_size = io_size + (io_addr - aligned_addr); - - if (emuMMC_ctx.fs_ver >= FS_VER_10_0_0) { - u64 out_size; - if (svcQueryIoMapping(&vaddr, &out_size, aligned_addr, aligned_size) != 0) { - fatal_abort(Fatal_IoMapping); - } - } else { - if (svcLegacyQueryIoMapping(&vaddr, aligned_addr, aligned_size) != 0) { - fatal_abort(Fatal_IoMappingLegacy); - } - } - - return (uintptr_t)(vaddr + (io_addr - aligned_addr)); -} - -intptr_t QueryIoMapping(u64 addr, u64 size) -{ - for (int i = 0; i < IO_MAPPING_COUNT; i++) - { - if (io_mapping_list[i].phys == addr && io_mapping_list[i].size == size) - { - return io_mapping_list[i].virt; - } - } - - u64 ioMap = _GetIoMapping(addr, size); - - for (int i = 0; i < IO_MAPPING_COUNT; i++) - { - if (io_mapping_list[i].phys == 0 && io_mapping_list[i].virt == 0 && io_mapping_list[i].size == 0) // First empty - { - io_mapping_list[i].virt = ioMap; - io_mapping_list[i].phys = addr; - io_mapping_list[i].size = size; - break; - } - } - - return (intptr_t)ioMap; -} - -u64 get_tmr_s() -{ - return armTicksToNs(armGetSystemTick()) / 1e+9; -} - -u64 get_tmr_ms() -{ - return armTicksToNs(armGetSystemTick()) / 1000000; -} - -u64 get_tmr_us() -{ - return armTicksToNs(armGetSystemTick()) / 1000; -} - -// TODO: Figure if Sleep or Busy loop -void msleep(u64 milliseconds) -{ - u64 now = get_tmr_ms(); - while (((u64)get_tmr_ms() - now) < milliseconds) - ; - //svcSleepThread(1000000 * milliseconds); -} - -// TODO: Figure if Sleep or Busy loop -void usleep(u64 microseconds) -{ - u64 now = get_tmr_us(); - while (((u64)get_tmr_us() - now) < microseconds) - ; - //svcSleepThread(1000 * microseconds); -} - -void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops) -{ - for (u32 i = 0; i < num_ops; i++) - base[ops[i].off] = ops[i].val; -} diff --git a/emummc/source/utils/util.h b/emummc/source/utils/util.h deleted file mode 100644 index 0c36d06ab2..0000000000 --- a/emummc/source/utils/util.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2018 naehrwert - * Copyright (C) 2018 CTCaer - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _UTIL_H_ -#define _UTIL_H_ - -#include "types.h" -#include "../emuMMC/emummc_ctx.h" - -intptr_t QueryIoMapping(u64 addr, u64 size); -#define byte_swap_32(num) (((num >> 24) & 0xff) | ((num << 8) & 0xff0000) | \ - ((num >> 8 )& 0xff00) | ((num << 24) & 0xff000000)) - -typedef struct _cfg_op_t -{ - u32 off; - u32 val; -} cfg_op_t; - -u64 get_tmr_us(); -u64 get_tmr_ms(); -u64 get_tmr_s(); -void usleep(u64 ticks); -void msleep(u64 milliseconds); -void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); - -static inline void *armGetTls(void) { - void *ret; - __asm__ __volatile__("MRS %x[data], TPIDRRO_EL0" : [data]"=r"(ret)); - return ret; -} - -extern volatile emuMMC_ctx_t emuMMC_ctx; - -#endif diff --git a/emummc/tools/fs_ida_nintendo_folder_xref_formatter.au3 b/emummc/tools/fs_ida_nintendo_folder_xref_formatter.au3 deleted file mode 100644 index 269ffc8cea..0000000000 --- a/emummc/tools/fs_ida_nintendo_folder_xref_formatter.au3 +++ /dev/null @@ -1,52 +0,0 @@ -ParseClipboard() - -Func FormatLineData($sLineData, $sLineDataAdd) - Local $lineData = StringReplace($sLineData, @TAB, " ") - Local $lineDataADRP, $lineDataADD - Local $isADRP = false - $lineData = StringReplace($lineData, "Up o sub_71000" , "0x") - $isADRP = StringInStr($lineData, "ADRP") - - Local $targetRegister = StringSplit(StringSplit($lineData, "X")[2], ",")[1] - $lineData = StringSplit($lineData, " ")[1] - $lineDataAddr = StringSplit($lineData, "+")[1] - $lineDataAddition = StringSplit($lineData, "+")[2] - - $lineDataAddr = StringReplace($lineDataAddr, "0x" , "") - $lineDataAddition = StringReplace($lineDataAddition, "0x" , "") - $addrADRP = Dec($lineDataAddr) + Dec($lineDataAddition) - - $lineDataADRP = "0x" & Hex($addrADRP) - - Local $lineDataADD = StringReplace($sLineDataAdd, @TAB, " ") - Local $isADD = false - $lineDataADD = StringReplace($lineDataADD, "Up o sub_71000" , "0x") - $isADD = StringInStr($lineData, "ADD") - - $lineDataADD = StringSplit($lineDataADD, " ")[1] - $lineDataAddAddr = StringSplit($lineDataADD, "+")[1] - $lineDataAddAddition = StringSplit($lineDataADD, "+")[2] - - $lineDataAddAddr = StringReplace($lineDataAddAddr, "0x" , "") - $lineDataAddAddition = StringReplace($lineDataAddAddition, "0x" , "") - $addrADD = Dec($lineDataAddAddr) + Dec($lineDataAddAddition) - $addrADD = $addrADD - $addrADRP - $lineDataADD = "0x" & Hex($addrADD) - - Return @TAB & "{.opcode_reg = " & $targetRegister & ", .adrp_offset = " & $lineDataADRP & ", .add_rel_offset = " & $lineDataADD & "}, \" & @LF -EndFunc - -Func ParseClipboard() - Local $sData = ClipGet() - Local $oData = "" - Local $sLineData = StringSplit(StringReplace($sData, @CRLF, @LF), @LF) - For $i = 2 to UBound($sLineData) - 2 Step 2 - Local $lineData = FormatLineData($sLineData[$i], $sLineData[$i+1]) - ;ConsoleWrite($lineData) - $oData = $oData & $lineData - Next - - $oData = "{ \" & @LF & $oData & @TAB & "{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \" & @LF & "}" & @LF - ;ConsoleWrite($oData) - ClipPut($oData) -EndFunc diff --git a/emummc/tools/kip1converter.py b/emummc/tools/kip1converter.py deleted file mode 100644 index 79b20154d4..0000000000 --- a/emummc/tools/kip1converter.py +++ /dev/null @@ -1,53 +0,0 @@ -# Modified kip1 conversion script, originally by jakibaki -# Used for dev purposes, will be replaced in the future - -from struct import pack, unpack -from sys import argv - -f = open(argv[1], "rb") - -header_start = f.read(0x20) - -section_names = [".text", ".rodata", ".data", ".bss"] - -sections = [] -for i in range(6): - section_bytes = f.read(0x10) - section = {} - - if i < len(section_names): - section["Name"] = section_names[i] - - section["OutOffset"], section["DecompressedSize"], section["CompressedSize"], section["Attribute"] = unpack("IIII", section_bytes) - sections.append(section) - print(section) - -assert (sections[3]["OutOffset"] + sections[3]["DecompressedSize"]) % 0x1000 == 0 - -kernel_caps = [] -for i in range(0x20): - val, = unpack("I", f.read(4)) - kernel_caps.append(val) - -f.seek(0x100) - -for i in range(3): - section = sections[i] - section["Buffer"] = f.read(section["DecompressedSize"]) -print(f.read()) - -f.close() - -f = open(argv[2], "wb") - -for i in range(3): - section = sections[i] - f.seek(section["OutOffset"]) - f.write(section["Buffer"]) - -f.seek(sections[3]["OutOffset"]) -f.write(b'\0' * sections[3]["DecompressedSize"]) - -caps = open("emummc.caps", "wb") -for i in range(0x20): - caps.write(pack("I", kernel_caps[i]))