git subrepo clone --branch=develop https://github.com/m4xw/emummc emummc

subrepo:
  subdir:   "emummc"
  merged:   "a9d569594"
upstream:
  origin:   "https://github.com/m4xw/emummc"
  branch:   "develop"
  commit:   "a9d569594"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
This commit is contained in:
Michael Scire 2022-03-23 09:20:54 -07:00
parent e3cb5e74b9
commit 12d83106fd
110 changed files with 21837 additions and 0 deletions

9
emummc/.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
*.kip
*.data
*.elf
build
.vscode/ipch
.vscode/settings.json
*.exe
*.kip*
emummc.caps

12
emummc/.gitrepo vendored Normal file
View file

@ -0,0 +1,12 @@
; 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 = e3cb5e74b98b704afdee3762dd13f92154a89abc
method = merge
cmdver = 0.4.1

35
emummc/.vscode/c_cpp_properties.json vendored Normal file
View file

@ -0,0 +1,35 @@
{
"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
}

339
emummc/LICENSE vendored Normal file
View file

@ -0,0 +1,339 @@
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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.
<signature of Ty Coon>, 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.

118
emummc/Makefile vendored Normal file
View file

@ -0,0 +1,118 @@
.SUFFIXES:
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/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

36
emummc/README.md vendored Normal file
View file

@ -0,0 +1,36 @@
# 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

9
emummc/build.sh vendored Normal file
View file

@ -0,0 +1,9 @@
#!/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

137
emummc/emummc.json vendored Normal file
View file

@ -0,0 +1,137 @@
{
"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"
}
}
]
}

201
emummc/emummc.ld vendored Normal file
View file

@ -0,0 +1,201 @@
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) }
}

8
emummc/emummc.specs vendored Normal file
View file

@ -0,0 +1,8 @@
%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

51
emummc/source/FS/FS.h vendored Normal file
View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__ */

224
emummc/source/FS/FS_offsets.c vendored Normal file
View file

@ -0,0 +1,224 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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 "../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);
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));
default:
fatal_abort(Fatal_UnknownVersion);
}
}

59
emummc/source/FS/FS_offsets.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef __FS_OFFSETS_H__
#define __FS_OFFSETS_H__
#include <stdint.h>
#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__

61
emummc/source/FS/FS_structs.h vendored Normal file
View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

92
emummc/source/FS/FS_versions.h vendored Normal file
View file

@ -0,0 +1,92 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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_MAX,
};
#endif // __FS_VERSIONS_H__

57
emummc/source/FS/offsets/100.h vendored Normal file
View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/1000.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/1000_exfat.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/1020.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/1020_exfat.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/1100.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/1100_exfat.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/1200.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/1200_exfat.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

60
emummc/source/FS/offsets/1203.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

60
emummc/source/FS/offsets/1203_exfat.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/1300.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/1300_exfat.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/1310.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/1310_exfat.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/200.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/200_exfat.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/210.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/210_exfat.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/300.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/300_exfat.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/301.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/301_exfat.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/400.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/400_exfat.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/410.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/410_exfat.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/500.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/500_exfat.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/510.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

58
emummc/source/FS/offsets/510_exfat.h vendored Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/600.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

59
emummc/source/FS/offsets/600_exfat.h vendored Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

60
emummc/source/FS/offsets/700.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

60
emummc/source/FS/offsets/700_exfat.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

60
emummc/source/FS/offsets/800.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

60
emummc/source/FS/offsets/800_exfat.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

60
emummc/source/FS/offsets/810.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

60
emummc/source/FS/offsets/810_exfat.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

60
emummc/source/FS/offsets/900.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

60
emummc/source/FS/offsets/900_exfat.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

60
emummc/source/FS/offsets/910.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

60
emummc/source/FS/offsets/910_exfat.h vendored Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

432
emummc/source/emmc/mmc.h vendored Normal file
View file

@ -0,0 +1,432 @@
/*
* 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 <tolkien@mizi.com>
*
* 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 <Complex> 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 */

35
emummc/source/emmc/nx_emmc.c vendored Normal file
View file

@ -0,0 +1,35 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#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);
}

67
emummc/source/emmc/nx_emmc.h vendored Normal file
View file

@ -0,0 +1,67 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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

91
emummc/source/emmc/nx_sd.c vendored Normal file
View file

@ -0,0 +1,91 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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;
}

36
emummc/source/emmc/nx_sd.h vendored Normal file
View file

@ -0,0 +1,36 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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

129
emummc/source/emmc/sd.h vendored Normal file
View file

@ -0,0 +1,129 @@
/*
* 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 */

1480
emummc/source/emmc/sdmmc.c vendored Normal file

File diff suppressed because it is too large Load diff

123
emummc/source/emmc/sdmmc.h vendored Normal file
View file

@ -0,0 +1,123 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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

1429
emummc/source/emmc/sdmmc_driver.c vendored Normal file

File diff suppressed because it is too large Load diff

266
emummc/source/emmc/sdmmc_driver.h vendored Normal file
View file

@ -0,0 +1,266 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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

109
emummc/source/emmc/sdmmc_t210.h vendored Normal file
View file

@ -0,0 +1,109 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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

573
emummc/source/emuMMC/emummc.c vendored Normal file
View file

@ -0,0 +1,573 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#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);
}

81
emummc/source/emuMMC/emummc.h vendored Normal file
View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef __EMUMMC_H__
#define __EMUMMC_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#include <stdint.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#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__ */

56
emummc/source/emuMMC/emummc_ctx.h vendored Normal file
View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#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__ */

72
emummc/source/libs/fatfs/diskio.c vendored Normal file
View file

@ -0,0 +1,72 @@
/*-----------------------------------------------------------------------*/
/* 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 <string.h>
#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;
}

79
emummc/source/libs/fatfs/diskio.h vendored Normal file
View file

@ -0,0 +1,79 @@
/*-----------------------------------------------------------------------/
/ 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

6883
emummc/source/libs/fatfs/ff.c vendored Normal file

File diff suppressed because it is too large Load diff

391
emummc/source/libs/fatfs/ff.h vendored Normal file
View file

@ -0,0 +1,391 @@
/*----------------------------------------------------------------------------/
/ 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 */

292
emummc/source/libs/fatfs/ffconf.h vendored Normal file
View file

@ -0,0 +1,292 @@
/*---------------------------------------------------------------------------/
/ 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 ---*/

39
emummc/source/libs/fatfs/ffsystem.c vendored Normal file
View file

@ -0,0 +1,39 @@
/*------------------------------------------------------------------------*/
/* Sample Code of OS Dependent Functions for FatFs */
/* (C) ChaN, 2018 */
/* (C) CTCaer, 2018 */
/*------------------------------------------------------------------------*/
#include "ff.h"
#include "../../utils/types.h"
#include <stdlib.h>
#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

625
emummc/source/libs/fatfs/ffunicode.c vendored Normal file
View file

@ -0,0 +1,625 @@
/*------------------------------------------------------------------------*/
/* 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 */

436
emummc/source/main.c vendored Normal file
View file

@ -0,0 +1,436 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdint.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#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();
}

41
emummc/source/nx/cache.h vendored Normal file
View file

@ -0,0 +1,41 @@
/**
* @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);

100
emummc/source/nx/cache.s vendored Normal file
View file

@ -0,0 +1,100 @@
/**
* @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

46
emummc/source/nx/counter.h vendored Normal file
View file

@ -0,0 +1,46 @@
/**
* @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;
}

45
emummc/source/nx/dynamic.c vendored Normal file
View file

@ -0,0 +1,45 @@
/**
* @file dynamic.c
* @copyright libnx Authors
*/
#include <stddef.h>
#include "../utils/types.h"
#include <elf.h>
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;
}
}
}
}

217
emummc/source/nx/smc.c vendored Normal file
View file

@ -0,0 +1,217 @@
/**
* @file smc.c
* @copyright libnx Authors
*/
#include <stddef.h>
#include <string.h>
#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;
}

105
emummc/source/nx/smc.h vendored Normal file
View file

@ -0,0 +1,105 @@
/**
* @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

131
emummc/source/nx/start.s vendored Normal file
View file

@ -0,0 +1,131 @@
/**
* @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

220
emummc/source/nx/svc.h vendored Normal file
View file

@ -0,0 +1,220 @@
/**
* @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
///@}

136
emummc/source/nx/svc.s vendored Normal file
View file

@ -0,0 +1,136 @@
/**
* @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

340
emummc/source/power/max77620.h vendored Normal file
View file

@ -0,0 +1,340 @@
/*
* 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_ */

159
emummc/source/power/max7762x.c vendored Normal file
View file

@ -0,0 +1,159 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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);
}

117
emummc/source/power/max7762x.h vendored Normal file
View file

@ -0,0 +1,117 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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

446
emummc/source/soc/clock.c vendored Normal file
View file

@ -0,0 +1,446 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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);
}

173
emummc/source/soc/clock.h vendored Normal file
View file

@ -0,0 +1,173 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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

168
emummc/source/soc/gpio.c vendored Normal file
View file

@ -0,0 +1,168 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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];
}

95
emummc/source/soc/gpio.h vendored Normal file
View file

@ -0,0 +1,95 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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

233
emummc/source/soc/i2c.c vendored Normal file
View file

@ -0,0 +1,233 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#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 *)&reg, 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;
}

36
emummc/source/soc/i2c.h vendored Normal file
View file

@ -0,0 +1,36 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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

24
emummc/source/soc/pinmux.c vendored Normal file
View file

@ -0,0 +1,24 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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;
}

101
emummc/source/soc/pinmux.h vendored Normal file
View file

@ -0,0 +1,101 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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

Some files were not shown because too many files have changed in this diff Show more