Compare commits
343 Commits
v9.0-joyco
...
3gx-master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bce9523a2 | ||
|
|
884b4a4e4a | ||
|
|
08110cb125 | ||
|
|
fd8dd82a8d | ||
|
|
47b5466a6e | ||
|
|
15342b5030 | ||
|
|
832c215a2d | ||
|
|
979c59d6f2 | ||
|
|
738a242e3c | ||
|
|
5fd6dc6dd4 | ||
|
|
3fd9cacb6d | ||
|
|
bb07a7334f | ||
|
|
748b771618 | ||
|
|
d6e72080d9 | ||
|
|
70109fed2c | ||
|
|
cf36d21daf | ||
|
|
781cd85b00 | ||
|
|
514537a983 | ||
|
|
184f4587fb | ||
|
|
e096aaabc4 | ||
|
|
ba26ae0f1c | ||
|
|
786adf0268 | ||
|
|
2af05220c2 | ||
|
|
362c4ffff1 | ||
|
|
95fd4e763b | ||
|
|
768e587b76 | ||
|
|
e3bb1c1b63 | ||
|
|
4c01bb453c | ||
|
|
dc67d438dc | ||
|
|
2d58ec4c86 | ||
|
|
555286ea47 | ||
|
|
b17eb66d55 | ||
|
|
5670062a0f | ||
|
|
9ca52054cf | ||
|
|
991f51831d | ||
|
|
53ab41e6d0 | ||
|
|
1176fa8f28 | ||
|
|
e69f89a0d4 | ||
|
|
9411a8c186 | ||
|
|
aa577d0e39 | ||
|
|
241dd35000 | ||
|
|
ca48641a7e | ||
|
|
1fce207bcf | ||
|
|
c58cb2d916 | ||
|
|
d734e36a3a | ||
|
|
28d84f30bb | ||
|
|
0bb56031d7 | ||
|
|
cc9977774e | ||
|
|
a39053c3c3 | ||
|
|
dc4de4ce6f | ||
|
|
4e12453fff | ||
|
|
3a0418e279 | ||
|
|
1899bf377b | ||
|
|
0471002d4c | ||
|
|
704e08dc23 | ||
|
|
905837468c | ||
|
|
19d95782e1 | ||
|
|
adda19ecb2 | ||
|
|
b02d0346fd | ||
|
|
9097276a06 | ||
|
|
e99ab11c6f | ||
|
|
a564d8536a | ||
|
|
a21eee9207 | ||
|
|
71cddef78f | ||
|
|
9ae913064c | ||
|
|
a2313d1c03 | ||
|
|
22db3445a0 | ||
|
|
6417720d7d | ||
|
|
8b10906d90 | ||
|
|
0c55324d11 | ||
|
|
0b4fdc6e66 | ||
|
|
d3e62df769 | ||
|
|
04bd881cfa | ||
|
|
96799455cb | ||
|
|
814792eb91 | ||
|
|
2834bae318 | ||
|
|
037fae99d6 | ||
|
|
49c8888948 | ||
|
|
1875556f81 | ||
|
|
00850bf691 | ||
|
|
09fd199487 | ||
|
|
32c53578e0 | ||
|
|
0da90f61fc | ||
|
|
9942e8b299 | ||
|
|
daaeb97834 | ||
|
|
92da214066 | ||
|
|
0f05dd5c0a | ||
|
|
166bdbeb7d | ||
|
|
7dc2b7123b | ||
|
|
3d0ec9b785 | ||
|
|
85cfa5cba6 | ||
|
|
fdc1eaa16c | ||
|
|
d4dcf1a3e9 | ||
|
|
43fd137d55 | ||
|
|
6931eadc34 | ||
|
|
3143e7e1d0 | ||
|
|
d03396d272 | ||
|
|
c8aa2e8a89 | ||
|
|
c7a3a0278c | ||
|
|
5924f60d06 | ||
|
|
cd68b66c03 | ||
|
|
44cd3928fb | ||
|
|
8c54613e44 | ||
|
|
7dfa83b8c0 | ||
|
|
b551061264 | ||
|
|
3e228c33c9 | ||
|
|
2b23be8f44 | ||
|
|
ced78cb072 | ||
|
|
fb17850c3d | ||
|
|
7f7c4852cc | ||
|
|
f334e3b951 | ||
|
|
9d62995799 | ||
|
|
1d8b793cf7 | ||
|
|
33431cb939 | ||
|
|
e677e0142c | ||
|
|
b313a4aa2f | ||
|
|
37c5c6f049 | ||
|
|
a6d92ed8fe | ||
|
|
eb37ac4142 | ||
|
|
a0d4b96915 | ||
|
|
31891efbca | ||
|
|
58f3edda12 | ||
|
|
4a655384e2 | ||
|
|
0543c208fd | ||
|
|
0e834ec004 | ||
|
|
26454dc832 | ||
|
|
5c16836626 | ||
|
|
67e28b2a82 | ||
|
|
c2a2893b5c | ||
|
|
68b670f94f | ||
|
|
5a83a46423 | ||
|
|
8785fd0236 | ||
|
|
a67e8e60c6 | ||
|
|
c7551a731c | ||
|
|
d9c5437902 | ||
|
|
55d51217d8 | ||
|
|
11c9caaf13 | ||
|
|
c4711e5e3a | ||
|
|
d34f0a8eca | ||
|
|
8233d4e226 | ||
|
|
ca49956219 | ||
|
|
5edfbfc1f7 | ||
|
|
dfd50d9d75 | ||
|
|
1946941340 | ||
|
|
31dae90dcd | ||
|
|
da8df54649 | ||
|
|
0e1415299a | ||
|
|
93f770888d | ||
|
|
0886b10619 | ||
|
|
e8493d18c5 | ||
|
|
60a8bf56c6 | ||
|
|
c95b59c72e | ||
|
|
7e14c83bdd | ||
|
|
a2e46919c1 | ||
|
|
a4befc29c8 | ||
|
|
93e87284aa | ||
|
|
236dbb043c | ||
|
|
77f0295a04 | ||
|
|
c3b97999f5 | ||
|
|
f1b787c7d9 | ||
|
|
3061001fb1 | ||
|
|
0bc51d5c34 | ||
|
|
c913de1e67 | ||
|
|
c9a578734e | ||
|
|
37544a0eb9 | ||
|
|
6b13b5d06b | ||
|
|
9705083b65 | ||
|
|
2423d1802e | ||
|
|
3ad314a5ac | ||
|
|
58a6a25eb3 | ||
|
|
6ed93a1f09 | ||
|
|
0b68baa0dd | ||
|
|
8168d2c2f9 | ||
|
|
76dbdf45cf | ||
|
|
d4e1da0174 | ||
|
|
fde3b70d03 | ||
|
|
8c03702c7d | ||
|
|
31c6ead2ad | ||
|
|
454fa16b3a | ||
|
|
301e84f1ca | ||
|
|
69634fdbd5 | ||
|
|
10e823a9d5 | ||
|
|
f4851cd533 | ||
|
|
39287d43e3 | ||
|
|
09b2bf5fb1 | ||
|
|
e989309771 | ||
|
|
d989c45c3d | ||
|
|
84c5cf0661 | ||
|
|
648541bb1f | ||
|
|
2cf04e8a83 | ||
|
|
af10782500 | ||
|
|
fe0e5ae83d | ||
|
|
8e4af5c823 | ||
|
|
570a8d5222 | ||
|
|
2c8a1eb5c6 | ||
|
|
23c40aeb8e | ||
|
|
c7c832a0dd | ||
|
|
6423d0c1b3 | ||
|
|
8b56098d64 | ||
|
|
2927bd5aa3 | ||
|
|
d357db25f2 | ||
|
|
9b3cc5391b | ||
|
|
54eeb97b24 | ||
|
|
593f50de91 | ||
|
|
85af8d9fa4 | ||
|
|
58ff96dc83 | ||
|
|
a5803d1b62 | ||
|
|
eddb0988a0 | ||
|
|
5d3585a33d | ||
|
|
4285736286 | ||
|
|
32b8cf6172 | ||
|
|
3e724e88a8 | ||
|
|
687dfddd9f | ||
|
|
90a43089ba | ||
|
|
1e0baeb30e | ||
|
|
353f7d1705 | ||
|
|
f5f3764f99 | ||
|
|
eef22f8701 | ||
|
|
9e1a9f2842 | ||
|
|
0b33134f6c | ||
|
|
5c4d6c68b2 | ||
|
|
89e42a457c | ||
|
|
17ca09346d | ||
|
|
54de645dc3 | ||
|
|
da6c02068b | ||
|
|
06bcb39721 | ||
|
|
2b31a4ab5c | ||
|
|
3b4ef682fe | ||
|
|
eab9a31dff | ||
|
|
ff86ed2e77 | ||
|
|
2fe1169423 | ||
|
|
4c9fe186d7 | ||
|
|
e11cc090b2 | ||
|
|
763a1de8d3 | ||
|
|
e57b546dd4 | ||
|
|
bd670cf87c | ||
|
|
1e0996c395 | ||
|
|
5f295c4227 | ||
|
|
4f699ccb81 | ||
|
|
70757e564d | ||
|
|
af822e5af5 | ||
|
|
63736d7873 | ||
|
|
fb800bd4c9 | ||
|
|
219f38169f | ||
|
|
c688600d33 | ||
|
|
ea14d8a186 | ||
|
|
cd18b85632 | ||
|
|
22ec031495 | ||
|
|
43b998d37d | ||
|
|
127101a683 | ||
|
|
5955ca6957 | ||
|
|
dcddcfc94d | ||
|
|
1453d9adac | ||
|
|
ef034a87d4 | ||
|
|
e688ec9257 | ||
|
|
ae1f85d341 | ||
|
|
7177799021 | ||
|
|
1041d7c438 | ||
|
|
e57abad52f | ||
|
|
74bbfb95d3 | ||
|
|
8345f31c2a | ||
|
|
d44055d232 | ||
|
|
4a431b8fdf | ||
|
|
e2ed200509 | ||
|
|
4e5f6e1eff | ||
|
|
474eb3001b | ||
|
|
f72d99d9b0 | ||
|
|
a9a569c79d | ||
|
|
68b8c99ad0 | ||
|
|
d8c6f94887 | ||
|
|
8b51141f54 | ||
|
|
0195ab34e9 | ||
|
|
0bb82feb81 | ||
|
|
6199f598e5 | ||
|
|
b92406afe2 | ||
|
|
244409fc98 | ||
|
|
f3b2a6c30d | ||
|
|
a65f7fbf88 | ||
|
|
35ad240018 | ||
|
|
e64f267e4c | ||
|
|
d28e961adc | ||
|
|
e6b7dc1dc5 | ||
|
|
9e7e967a5f | ||
|
|
33d40b491e | ||
|
|
7cb50d38b9 | ||
|
|
d6d440a47e | ||
|
|
52cd950ca6 | ||
|
|
9fad2dff21 | ||
|
|
4b40dd52f4 | ||
|
|
6bd7070d38 | ||
|
|
0c9365bcb7 | ||
|
|
c0bd69309a | ||
|
|
55bd62d7a9 | ||
|
|
020236742f | ||
|
|
faeb0d9395 | ||
|
|
b05f993221 | ||
|
|
e796abb155 | ||
|
|
3d2c12cf09 | ||
|
|
8ff5111e30 | ||
|
|
673ec9fc51 | ||
|
|
a7100a1e7f | ||
|
|
710ad11819 | ||
|
|
f718297591 | ||
|
|
1c7b55ee1e | ||
|
|
f437d92374 | ||
|
|
47916b2831 | ||
|
|
4b341e039a | ||
|
|
1ae01c2406 | ||
|
|
2182742708 | ||
|
|
0791aabbf8 | ||
|
|
bd15f51af3 | ||
|
|
932ed4222f | ||
|
|
1052e04679 | ||
|
|
3903ac6409 | ||
|
|
53622d777b | ||
|
|
2219b19d5f | ||
|
|
bc06b17823 | ||
|
|
2520079536 | ||
|
|
d7095ce37d | ||
|
|
0a87e41c66 | ||
|
|
89cc6ede1a | ||
|
|
dd6e071dde | ||
|
|
bec8daf028 | ||
|
|
2127271b33 | ||
|
|
1600171ffa | ||
|
|
7f7a9fab2d | ||
|
|
b15d86f31d | ||
|
|
89a3dc8643 | ||
|
|
3477beb05c | ||
|
|
8447c209a7 | ||
|
|
e78f706c1a | ||
|
|
f776c56cd4 | ||
|
|
dc195dffad | ||
|
|
74a0b2feae | ||
|
|
71039fc248 | ||
|
|
d0306609c3 | ||
|
|
d13cde3d7b | ||
|
|
38f54fd2b6 | ||
|
|
b5728e9c11 | ||
|
|
a2177c0510 | ||
|
|
356a94cc2e | ||
|
|
9d507e046c | ||
|
|
47c47f967a |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.xml text eol=lf
|
||||
@@ -1,14 +1,19 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Use this to report bugs you encounter with Luma3DS. Make sure you upload the crash dumps if Luma3DS crashes.
|
||||
---
|
||||
|
||||
<!--
|
||||
-- THIS IS NOT A SUPPORT FORUM! For support go here:
|
||||
-- Nintendo Homebrew: https://discord.gg/MjzatM8
|
||||
--
|
||||
-- Rosalina feature requests go here: https://github.com/AuroraWright/Luma3DS/issues/752
|
||||
-- Rosalina feature requests go here: https://github.com/LumaTeam/Luma3DS/issues/752
|
||||
--
|
||||
-- Also check the Wiki (https://github.com/AuroraWright/Luma3DS/wiki) before making an issue.
|
||||
-- Also check the Wiki (https://github.com/LumaTeam/Luma3DS/wiki) before making an issue.
|
||||
--
|
||||
-- For GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: https://3ds.guide/troubleshooting
|
||||
-- For GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: use https://github.com/MechanicalDragon0687/TWLFix-CFW and update your system.
|
||||
-- If you're using an emu/redNAND try installing anything on it to sysNAND.
|
||||
-- Please make sure to read "Enable game patching" https://github.com/AuroraWright/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable game patching" option(s).
|
||||
-- Please make sure to read "Enable game patching" https://github.com/LumaTeam/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable game patching" option(s).
|
||||
--
|
||||
-- Luma updaters that don't support Boot9Strap/Sighax won't work.
|
||||
-- This is due to support for non-B9S/Sighax entrypoints being dropped.
|
||||
@@ -16,11 +21,12 @@
|
||||
-- Please fill in the placeholders.-->
|
||||
**System model:**
|
||||
|
||||
[e.g. 2DS, New 3DS, Old 3DS]
|
||||
[New 2DS XL, New 3DS XL, New 3DS, Old 2DS, Old 3DS XL, Old 3DS]
|
||||
|
||||
**SysNAND version (+emu/redNAND version if applicable):**
|
||||
|
||||
[e.g. 11.6.0-39U SysNAND, 11.6.0-39J EmuNAND]
|
||||
[e.g. 11.13.0-45U SysNAND, 11.13.0-45E EmuNAND]
|
||||
<!--You can check which version you're on in System Settings. It will be on the bottom right of the top screen.-->
|
||||
|
||||
**Entrypoint (How/what you're using to boot Luma3DS):**
|
||||
|
||||
@@ -28,28 +34,31 @@
|
||||
|
||||
**Luma3DS version:**
|
||||
|
||||
[e.g. 8.1.1 stable or if using nightly/hourly specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/9570e6cbeca53128433abbf5e3473cb8a07fe69e]
|
||||
<!--You can check which version you're on in System Settings. It will be on the bottom right of the top screen.-->
|
||||
|
||||
[e.g. v10.2 stable or if using non-releases specify the commit like this https://github.com/LumaTeam/Luma3DS/commit/0543c208fd154e6326ea5da8cbf66ffcbdef010c]
|
||||
|
||||
**Luma3DS configuration/options:**
|
||||
|
||||
Default EmuNAND: ( )
|
||||
<!--This option is only available if there's at least one EmuNAND.-->
|
||||
|
||||
Screen brightness: ( )
|
||||
|
||||
Splash: ( )
|
||||
|
||||
Splash duration: ( )
|
||||
|
||||
PIN lock: ( )
|
||||
|
||||
New 3DS CPU: ( )
|
||||
<!--This option is only available for New 3DS/2DS.-->
|
||||
<!--This option is only available on New 3DS (XL)/New 2DS XL.-->
|
||||
|
||||
--
|
||||
|
||||
Autoboot EmuNAND: ( )
|
||||
<!--This option is only available if there's at least one EmuNAND.-->
|
||||
|
||||
Use EmuNAND FIRM if booting with R: ( )
|
||||
<!--This option is only available if there's at least one EmuNAND.-->
|
||||
|
||||
Enable loading external FIRMs and modules: ( )
|
||||
<!--Firmware (.bin) files are not required by Luma, or NTR CFW anymore.
|
||||
@@ -61,11 +70,12 @@ Show NAND or user string in System Settings: ( )
|
||||
|
||||
Show GBA boot screen in patched AGB_FIRM: ( )
|
||||
|
||||
Patch ARM9 access: ( )
|
||||
|
||||
Set developer UNITINFO: ( )
|
||||
|
||||
Disable ARM11 exception handlers: ( )
|
||||
Disable Arm11 exception handlers: ( )
|
||||
|
||||
Enable Rosalina on SAFE_FIRM: ( )
|
||||
<!--This option is only available on New 3DS (XL)/New 2DS XL.-->
|
||||
|
||||
--
|
||||
|
||||
@@ -85,6 +95,6 @@ Disable ARM11 exception handlers: ( )
|
||||
|
||||
|
||||
**Dump file:**
|
||||
<!--If the issue leads to a crash you must uncheck the "Disable ARM11 exception handlers" option.
|
||||
<!--If the issue leads to a crash you must uncheck the "Disable Arm11 exception handlers" option.
|
||||
-- The error message will tell you where the dump is.
|
||||
-- Zip the dmp file and drag & drop it below.-->
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -13,8 +13,12 @@ exceptions/arm11/build
|
||||
*.d
|
||||
*.elf
|
||||
*.cxi
|
||||
*.3dsx
|
||||
.DS_Store
|
||||
*.dmp
|
||||
.project
|
||||
.cproject
|
||||
.settings
|
||||
.idea/
|
||||
|
||||
Luma3DS*.zip
|
||||
|
||||
183
Makefile
183
Makefile
@@ -1,177 +1,34 @@
|
||||
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
ifneq ($(strip $(shell firmtool -v 2>&1 | grep usage)),)
|
||||
$(error "Please install firmtool v1.1 or greater")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/base_tools
|
||||
NAME := $(notdir $(CURDIR))
|
||||
REVISION := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/')
|
||||
|
||||
name := Luma3DS
|
||||
revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/')
|
||||
version_major := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f1 -d.)
|
||||
version_minor := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f2 -d.)
|
||||
version_build := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f3 -d.)
|
||||
commit := $(shell git rev-parse --short=8 HEAD)
|
||||
is_release := 0
|
||||
SUBFOLDERS := sysmodules arm11 arm9 k11_extension
|
||||
|
||||
ifeq ($(strip $(revision)),)
|
||||
revision := v0.0.0-0
|
||||
version_major := 0
|
||||
version_minor := 0
|
||||
version_build := 0
|
||||
endif
|
||||
.PHONY: all release clean $(SUBFOLDERS)
|
||||
|
||||
ifeq ($(strip $(commit)),)
|
||||
commit := 0
|
||||
endif
|
||||
all: boot.firm
|
||||
|
||||
ifeq ($(strip $(version_build)),)
|
||||
version_build := 0
|
||||
endif
|
||||
release: $(NAME)$(REVISION).zip
|
||||
|
||||
ifeq ($(strip $(shell git describe --tags --match v[0-9]* | grep -)),)
|
||||
is_release := 1
|
||||
endif
|
||||
|
||||
dir_source := source
|
||||
dir_patches := patches
|
||||
dir_arm11 := arm11
|
||||
dir_chainloader := chainloader
|
||||
dir_exceptions := exceptions
|
||||
dir_arm9_exceptions := $(dir_exceptions)/arm9
|
||||
dir_k11_extension := k11_extension
|
||||
dir_sysmodules := sysmodules
|
||||
dir_loader := $(dir_sysmodules)/loader
|
||||
dir_rosalina := $(dir_sysmodules)/rosalina
|
||||
dir_sm := $(dir_sysmodules)/sm
|
||||
dir_pxi := $(dir_sysmodules)/pxi
|
||||
dir_build := build
|
||||
dir_out := out
|
||||
|
||||
ASFLAGS := -mcpu=arm946e-s
|
||||
CFLAGS := -Wall -Wextra $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||
LDFLAGS := -nostartfiles -Wl,--nmagic
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
|
||||
bundled = $(dir_build)/reboot.bin.o $(dir_build)/emunand.bin.o $(dir_build)/chainloader.bin.o $(dir_build)/arm9_exceptions.bin.o
|
||||
|
||||
modules = $(dir_build)/loader.cxi $(dir_build)/rosalina.cxi $(dir_build)/sm.cxi $(dir_build)/pxi.cxi
|
||||
|
||||
define bin2o
|
||||
bin2s $< | $(AS) -o $(@)
|
||||
endef
|
||||
|
||||
.PHONY: all
|
||||
all: firm
|
||||
|
||||
.PHONY: release
|
||||
release: $(dir_out)/$(name)$(revision).7z
|
||||
|
||||
.PHONY: firm
|
||||
firm: $(dir_out)/boot.firm
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@$(MAKE) -C $(dir_arm11) clean
|
||||
@$(MAKE) -C $(dir_chainloader) clean
|
||||
@$(MAKE) -C $(dir_arm9_exceptions) clean
|
||||
@$(MAKE) -C $(dir_k11_extension) clean
|
||||
@$(MAKE) -C $(dir_loader) clean
|
||||
@$(MAKE) -C $(dir_rosalina) clean
|
||||
@$(MAKE) -C $(dir_sm) clean
|
||||
@$(MAKE) -C $(dir_pxi) clean
|
||||
@rm -rf $(dir_out) $(dir_build)
|
||||
@$(foreach dir, $(SUBFOLDERS), $(MAKE) -C $(dir) clean &&) true
|
||||
@rm -rf *.firm *.zip *.3dsx
|
||||
|
||||
.PRECIOUS: $(dir_build)/%.bin
|
||||
# boot.3dsx comes from https://github.com/fincs/new-hbmenu/releases
|
||||
$(NAME)$(REVISION).zip: boot.firm boot.3dsx
|
||||
@zip -r $@ $^ -x "*.DS_Store*" "*__MACOSX*"
|
||||
|
||||
.PHONY: $(dir_arm11)
|
||||
.PHONY: $(dir_chainloader)
|
||||
.PHONY: $(dir_arm9_exceptions)
|
||||
.PHONY: $(dir_k11_extension)
|
||||
.PHONY: $(dir_loader)
|
||||
.PHONY: $(dir_rosalina)
|
||||
.PHONY: $(dir_sm)
|
||||
.PHONY: $(dir_pxi)
|
||||
boot.firm: $(SUBFOLDERS)
|
||||
@firmtool build $@ -D sysmodules/sysmodules.bin arm11/arm11.elf arm9/arm9.elf k11_extension/k11_extension.elf \
|
||||
-A 0x18180000 -C XDMA XDMA NDMA XDMA
|
||||
@echo built... $(notdir $@)
|
||||
|
||||
boot.3dsx:
|
||||
@curl -sSL "https://github.com/fincs/new-hbmenu/releases/latest/download/boot.3dsx" -o "$@"
|
||||
@echo downloaded... $(notdir $@)
|
||||
|
||||
$(dir_out)/$(name)$(revision).7z: all
|
||||
@mkdir -p "$(@D)"
|
||||
@[ -f "$@" ] || 7z a -mx $@ ./$(@D)/* ./$(dir_exceptions)/exception_dump_parser -xr!.DS_Store
|
||||
|
||||
$(dir_out)/boot.firm: $(dir_build)/modules.bin $(dir_build)/arm11.elf $(dir_build)/main.elf $(dir_build)/k11_extension.bin
|
||||
@mkdir -p "$(@D)"
|
||||
@firmtool build $@ -D $^ -A 0x18180000 0x18000000 -C XDMA XDMA NDMA XDMA
|
||||
|
||||
$(dir_build)/modules.bin: $(modules)
|
||||
@mkdir -p "$(@D)"
|
||||
cat $^ > $@
|
||||
|
||||
$(dir_build)/arm11.elf: $(dir_arm11)
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/main.elf: $(bundled) $(objects)
|
||||
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
||||
$(dir_build)/k11_extension.bin: $(dir_k11_extension)
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/loader.cxi: $(dir_loader)
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/rosalina.cxi: $(dir_rosalina)
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/sm.cxi: $(dir_sm)
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/pxi.cxi: $(dir_pxi)
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/%.bin.o: $(dir_build)/%.bin
|
||||
@$(bin2o)
|
||||
|
||||
$(dir_build)/chainloader.bin: $(dir_chainloader)
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/arm9_exceptions.bin: $(dir_arm9_exceptions)
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/%.bin: $(dir_patches)/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
@armips $<
|
||||
|
||||
$(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3
|
||||
$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configuration\""
|
||||
$(dir_build)/patches.o: CFLAGS += -DVERSION_MAJOR="$(version_major)" -DVERSION_MINOR="$(version_minor)"\
|
||||
-DVERSION_BUILD="$(version_build)" -DISRELEASE="$(is_release)" -DCOMMIT_HASH="0x$(commit)"
|
||||
$(dir_build)/firm.o: $(dir_build)/modules.bin
|
||||
$(dir_build)/firm.o: CFLAGS += -DLUMA_SECTION0_SIZE="$(shell wc -c $(dir_build)/modules.bin | tr -d [:space:][:alpha:][:punct:])"
|
||||
|
||||
$(dir_build)/bundled.h: $(bundled)
|
||||
@$(foreach f, $(bundled),\
|
||||
echo "extern const u8" `(echo $(basename $(notdir $(f))) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> $@;\
|
||||
echo "extern const u32" `(echo $(basename $(notdir $(f)))| sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> $@;\
|
||||
)
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/bundled.h
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||
$(SUBFOLDERS):
|
||||
@$(MAKE) -C $@ all
|
||||
|
||||
85
README.md
85
README.md
@@ -1,40 +1,75 @@
|
||||
# Luma3DS
|
||||
*Noob-proof (N)3DS "Custom Firmware"*
|
||||
# Luma3DS-3GX Plugin Edition
|
||||
*Noob-proof (N)3DS "Custom Firmware", with 3GX plugins support*
|
||||
|
||||
## What it is
|
||||
### 3GX Plugin Edition
|
||||
This edition of **Luma3DS** allows the loading of **.3GX plugins** in Luma3DS, which are otherwise officially unsupported.
|
||||
|
||||
**Warning!** This was a quick, unstable hotfix I published to get things to work while waiting for official updates. The official firmware has now been updated to include 3gx plugins too. Do NOT use this fork.
|
||||
|
||||
#
|
||||
### How to install this Edition
|
||||
1. download the latest `boot.firm` from [the releases page](https://github.com/mind-overflow/Luma3DS-3GX/releases/latest)
|
||||
2. put the downloaded `boot.firm` file in the `root` directory of your SD card (`sd:/boot.firm`), overwriting the official Luma3DS `boot.firm`.
|
||||
3. (re)boot your 3DS, and when prompted, enable:
|
||||
- "Enable game patching"
|
||||
- "Show NAND or user string in System Settings"
|
||||
4. press `START` and let your 3DS boot.
|
||||
|
||||
**Luma3DS** is a program to patch the system software of (New) Nintendo 3DS handheld consoles "on the fly", adding features (such as per-game language settings and debugging capabilities for developers) and removing restrictions enforced by Nintendo (such as the region lock).
|
||||
It also allows you to run unauthorized ("homebrew") content by removing signature checks.
|
||||
To use it, you will need a console capable of running homebrew software on the ARM9 processor. We recommend [Plailect's guide](https://3ds.guide/) for details on how to get your system ready.
|
||||
You successfully installed the 3GX Plugin Loader! Now, proceed to the next step to learn how to install and enable 3GX plugins.
|
||||
|
||||
Since Luma3DS v8.0, Luma3DS has its own in-game menu, triggerable by `L+Down+Select` (see the [release notes](https://github.com/AuroraWright/Luma3DS/releases/tag/v8.0)).
|
||||
#
|
||||
### How to install 3GX plugins
|
||||
Plugins have to be installed in the `sd:/luma/plugins` folder.
|
||||
Usually, you need to put your specific plugin in the `<TITLEID>` subdirectory, eg: `sd:/luma/plugins/<TITLEID>/<filename>.3gx`.
|
||||
However, a `default.3gx` plugin can also be placed in the main `sd:/luma/plugins` directory: `sd:/luma/plugins/default.3gx`.
|
||||
|
||||
---
|
||||
So:
|
||||
``` yaml
|
||||
sd:/luma/plugins/default.3gx # will be loaded for all games, low priority
|
||||
sd:/luma/plugins/<TITLEID>/<filename>.3gx # will only be loaded for the specified title, high priority
|
||||
```
|
||||
|
||||
## Compiling
|
||||
Now you know how to install 3GX plugins! Proceed to the next step to learn how how to enable 3GX plugins.
|
||||
|
||||
First you need to clone the repository with: `git clone https://github.com/AuroraWright/Luma3DS.git`
|
||||
To compile, you'll need [armips](https://github.com/Kingcom/armips) and a build of a recent commit of [makerom](https://github.com/profi200/Project_CTR) added to your PATH. You'll also need to install [firmtool](https://github.com/TuxSH/firmtool), its README contains installation instructions.
|
||||
You'll also need to update your [libctru](https://github.com/smealum/ctrulib) install, building from the latest commit.
|
||||
Here are [Windows](https://buildbot.orphis.net/armips/) and [Linux](https://mega.nz/#!uQ1T1IAD!Q91O0e12LXKiaXh_YjXD3D5m8_W3FuMI-hEa6KVMRDQ) builds of armips (thanks to who compiled them!) and [makerom](https://github.com/Steveice10/buildtools/tree/master/3ds) (thanks @Steveice10!).
|
||||
Run `make` and everything should work!
|
||||
You can find the compiled files in the `out` folder.
|
||||
#
|
||||
### How to enable 3GX plugins
|
||||
1. when booted, press `L + D-Pad Down + Select` to open the Rosalina menu.
|
||||
2. Press `D-Pad Down` again until `Plugin Loader`, is selected, then press `A` and set it to `[Enabled]`.
|
||||
|
||||
---
|
||||
Done! You learned to install the 3GX Plugin loader, install 3GX Plugins and enable them. Now, simply launch the game you want to play and press `SELECT` to open up the 3GX menu!
|
||||
|
||||
## Setup / Usage / Features
|
||||
|
||||
See https://github.com/AuroraWright/Luma3DS/wiki
|
||||
#
|
||||
### Luma3DS introduction
|
||||
**Luma3DS** is a program to patch the system software of (New) Nintendo (2)3DS handheld consoles "on the fly", adding features such as per-game language settings, debugging capabilities for developers, and removing restrictions enforced by Nintendo such as the region lock.
|
||||
|
||||
---
|
||||
It also allows you to run unauthorized ("homebrew") content by removing signature checks.
|
||||
To use it, you will need a console capable of running homebrew software on the Arm9 processor.
|
||||
|
||||
## Credits
|
||||
Since v8.0, Luma3DS has its own in-game menu, triggerable by <kbd>L+Down+Select</kbd> (see the [release notes](https://github.com/LumaTeam/Luma3DS/releases/tag/v8.0)).
|
||||
|
||||
See https://github.com/AuroraWright/Luma3DS/wiki/Credits
|
||||
#
|
||||
### Compiling
|
||||
* Prerequisites
|
||||
1. git
|
||||
2. [makerom](https://github.com/jakcron/Project_CTR) in PATH
|
||||
3. [firmtool](https://github.com/TuxSH/firmtool)
|
||||
4. Up-to-date devkitARM+libctru
|
||||
1. Clone the repository with `git clone https://github.com/mind-overflow/Luma3DS-3GX.git`
|
||||
2. Run `make`.
|
||||
|
||||
---
|
||||
The produced `boot.firm` is meant to be copied to the root of your SD card for usage with Boot9Strap.
|
||||
|
||||
## Licensing
|
||||
#
|
||||
### Setup / Usage / Features
|
||||
See https://github.com/LumaTeam/Luma3DS/wiki
|
||||
|
||||
This software is licensed under the terms of the GPLv3.
|
||||
You can find a copy of the license in the LICENSE.txt file.
|
||||
#
|
||||
### Credits
|
||||
See https://github.com/LumaTeam/Luma3DS/wiki/Credits
|
||||
|
||||
#
|
||||
### Licensing
|
||||
This software is licensed under the terms of the GPLv3. You can find a copy of the license in the LICENSE.txt file.
|
||||
|
||||
Files in the GDB stub are instead triple-licensed as MIT or "GPLv2 or any later version", in which case it's specified in the file header.
|
||||
|
||||
156
arm11/Makefile
156
arm11/Makefile
@@ -1,39 +1,147 @@
|
||||
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/base_tools
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/base_rules
|
||||
|
||||
name := $(shell basename $(CURDIR))
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source source/svc
|
||||
DATA := data
|
||||
INCLUDES := include include/svc
|
||||
|
||||
dir_source := source
|
||||
dir_build := build
|
||||
dir_out := ../$(dir_build)
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
|
||||
DEFINES := -DARM11 -D_3DS
|
||||
|
||||
ASFLAGS := -mcpu=mpcore
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||
LDFLAGS := -nostartfiles -Wl,--nmagic
|
||||
CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections -fdata-sections \
|
||||
-Wno-main -fno-builtin $(ARCH) $(DEFINES)
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
CFLAGS += $(INCLUDE)
|
||||
|
||||
.PHONY: all
|
||||
all: $(dir_out)/$(name).elf
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
.PHONY: clean
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS :=
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
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)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
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)
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@rm -rf $(dir_build)
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
|
||||
|
||||
$(dir_out)/$(name).elf: $(objects)
|
||||
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
.PHONY: all
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).bin
|
||||
|
||||
$(OUTPUT).bin : $(OUTPUT).elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
@echo built ... $(notdir $@)
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
%.elf: $(OFILES)
|
||||
@echo linking $(notdir $@)
|
||||
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
@$(NM) -CSn $@ > $(notdir $*.lst)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
||||
158
arm11/linker.ld
158
arm11/linker.ld
@@ -1,16 +1,158 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */
|
||||
|
||||
PHDRS
|
||||
{
|
||||
main PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x1FF80000;
|
||||
PROVIDE(__start__ = 0x1FF80000);
|
||||
PROVIDE(__stack_top__ = 0x1FFFE000);
|
||||
PROVIDE(__stack_bottom__ = 0x1FFFD000);
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(4); }
|
||||
.bss : ALIGN(8) { __bss_start = .; *(.bss* COMMON); . = ALIGN(8); __bss_end = .; }
|
||||
. = __start__;
|
||||
|
||||
__stack_top__ = 0x1FFFE000;
|
||||
. = ALIGN(4);
|
||||
.text :
|
||||
{
|
||||
KEEP( *(.text.start) )
|
||||
KEEP( *(.init) )
|
||||
|
||||
/* .text */
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
*(.stub)
|
||||
*(.gnu.warning)
|
||||
*(.gnu.linkonce.t*)
|
||||
|
||||
/* .fini */
|
||||
KEEP( *(.fini) )
|
||||
. = ALIGN(32);
|
||||
} :main
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
*(.roda)
|
||||
*(.rodata.*)
|
||||
*all.rodata*(*)
|
||||
*(.gnu.linkonce.r*)
|
||||
SORT(CONSTRUCTORS)
|
||||
. = ALIGN(8);
|
||||
}
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
}
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE (__init_array_end = .);
|
||||
}
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE (__fini_array_end = .);
|
||||
}
|
||||
|
||||
.ctors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
}
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
}
|
||||
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = .;}
|
||||
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = .;}
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
KEEP (*(.large_patch*))
|
||||
*(.gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
. = ALIGN(32);
|
||||
}
|
||||
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__bss_start__ = ABSOLUTE(.));
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b*)
|
||||
*(COMMON)
|
||||
. = ALIGN(8);
|
||||
PROVIDE (__bss_end__ = ABSOLUTE(.));
|
||||
} :NONE
|
||||
|
||||
PROVIDE (__end__ = 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) }
|
||||
}
|
||||
|
||||
7
arm11/linker.specs
Normal file
7
arm11/linker.specs
Normal file
@@ -0,0 +1,7 @@
|
||||
%rename link old_link
|
||||
|
||||
*link:
|
||||
%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections
|
||||
|
||||
*startfile:
|
||||
crti%O%s crtbegin%O%s
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -40,6 +40,10 @@ extern volatile Arm11Operation operation;
|
||||
static void initScreens(u32 brightnessLevel, struct fb *fbs)
|
||||
{
|
||||
*(vu32 *)0x10141200 = 0x1007F;
|
||||
|
||||
*(vu32 *)0x10202204 = 0x01000000; //set LCD fill black to hide potential garbage -- NFIRM does it before firmlaunching
|
||||
*(vu32 *)0x10202A04 = 0x01000000;
|
||||
|
||||
*(vu32 *)0x10202014 = 0x00000001;
|
||||
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
|
||||
*(vu32 *)0x10202240 = brightnessLevel;
|
||||
@@ -118,16 +122,33 @@ static void initScreens(u32 brightnessLevel, struct fb *fbs)
|
||||
//Disco register
|
||||
for(u32 i = 0; i < 256; i++)
|
||||
*(vu32 *)0x10400584 = 0x10101 * i;
|
||||
|
||||
*(vu32 *)0x10202204 = 0x00000000; //unset LCD fill
|
||||
*(vu32 *)0x10202A04 = 0x00000000;
|
||||
}
|
||||
|
||||
static void setupFramebuffers(struct fb *fbs)
|
||||
{
|
||||
*(vu32 *)0x10202204 = 0x01000000; //set LCD fill black to hide potential garbage -- NFIRM does it before firmlaunching
|
||||
*(vu32 *)0x10202A04 = 0x01000000;
|
||||
|
||||
*(vu32 *)0x10400468 = (u32)fbs[0].top_left;
|
||||
*(vu32 *)0x1040046c = (u32)fbs[1].top_left;
|
||||
*(vu32 *)0x10400494 = (u32)fbs[0].top_right;
|
||||
*(vu32 *)0x10400498 = (u32)fbs[1].top_right;
|
||||
*(vu32 *)0x10400568 = (u32)fbs[0].bottom;
|
||||
*(vu32 *)0x1040056c = (u32)fbs[1].bottom;
|
||||
|
||||
//Set framebuffer format, framebuffer select and stride
|
||||
*(vu32 *)0x10400470 = 0x80341;
|
||||
*(vu32 *)0x10400478 = 0;
|
||||
*(vu32 *)0x10400490 = 0x2D0;
|
||||
*(vu32 *)0x10400570 = 0x80301;
|
||||
*(vu32 *)0x10400578 = 0;
|
||||
*(vu32 *)0x10400590 = 0x2D0;
|
||||
|
||||
*(vu32 *)0x10202204 = 0x00000000; //unset LCD fill
|
||||
*(vu32 *)0x10202A04 = 0x00000000;
|
||||
}
|
||||
|
||||
static void clearScreens(struct fb *fb)
|
||||
@@ -196,7 +217,7 @@ void main(void)
|
||||
break;
|
||||
case UPDATE_BRIGHTNESS:
|
||||
updateBrightness(*(vu32 *)ARM11_PARAMETERS_ADDRESS);
|
||||
break;
|
||||
break;
|
||||
case DEINIT_SCREENS:
|
||||
deinitScreens();
|
||||
break;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@ This file is part of Luma3DS
|
||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
@
|
||||
@ 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
|
||||
@@ -21,8 +21,8 @@
|
||||
@ * Prohibiting misrepresentation of the origin of that material,
|
||||
@ or requiring that modified versions of such material be marked in
|
||||
@ reasonable ways as different from the original version.
|
||||
|
||||
.section .text.start
|
||||
|
||||
.section .text.start, "ax", %progbits
|
||||
.align 4
|
||||
.global _start
|
||||
.type _start, %function
|
||||
@@ -53,20 +53,25 @@ start:
|
||||
mcr p15, 0, r0, c7, c7, 0
|
||||
mcr p15, 0, r0, c7, c10, 4
|
||||
|
||||
@ Clear BSS
|
||||
ldr r0, =__bss_start
|
||||
mov r1, #0
|
||||
ldr r2, =__bss_end
|
||||
sub r2, r0
|
||||
bl memset32
|
||||
|
||||
ldr sp, =__stack_top__
|
||||
mov fp, #0
|
||||
|
||||
@ Clear BSS
|
||||
ldr r0, =__bss_start__
|
||||
mov r1, #0
|
||||
ldr r2, =__bss_end__
|
||||
sub r2, r0
|
||||
bl memset
|
||||
|
||||
@ Call the init array
|
||||
bl __libc_init_array
|
||||
|
||||
b main
|
||||
|
||||
.global prepareForFirmlaunch
|
||||
.type prepareForFirmlaunch, %function
|
||||
prepareForFirmlaunch:
|
||||
str r0, [r1] @ tell ARM9 we're done
|
||||
str r0, [r1] @ tell Arm9 we're done
|
||||
mov r0, #0x20000000
|
||||
|
||||
_wait_for_core0_entrypoint_loop:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
|
||||
176
arm9/Makefile
Normal file
176
arm9/Makefile
Normal file
@@ -0,0 +1,176 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/base_rules
|
||||
|
||||
export REVISION := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/')
|
||||
export VERSION_MAJOR := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f1 -d.)
|
||||
export VERSION_MINOR := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f2 -d.)
|
||||
export VERSION_BUILD := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f3 -d.)
|
||||
export COMMIT := $(shell git rev-parse --short=8 HEAD)
|
||||
export IS_RELEASE := 0
|
||||
|
||||
ifeq ($(strip $(REVISION)),)
|
||||
export REVISION := v0.0.0-0
|
||||
export VERSION_MAJOR := 0
|
||||
export VERSION_MINOR := 0
|
||||
export VERSION_BUILD := 0
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(COMMIT)),)
|
||||
export COMMIT := 0
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(VERSION_BUILD)),)
|
||||
export VERSION_BUILD := 0
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(shell git describe --tags --match v[0-9]* | grep -)),)
|
||||
export IS_RELEASE := 1
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#---------------------------------------------------------------------------------
|
||||
APP_TITLE := Luma3DS
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source source/fatfs source/fatfs/sdmmc
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -marm -march=armv5te -mtune=arm946e-s
|
||||
DEFINES := -DARM9 -D_3DS
|
||||
|
||||
CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections -fdata-sections \
|
||||
-Wno-main $(ARCH) $(DEFINES)
|
||||
|
||||
CFLAGS += $(INCLUDE)
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS :=
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
export APP_TITLE := $(notdir $(TOPDIR)/..)
|
||||
|
||||
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)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
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)
|
||||
|
||||
.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).bin $(TARGET).elf
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
.PHONY: all
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).elf
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
%.elf: $(OFILES)
|
||||
@echo linking $(notdir $@)
|
||||
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
@$(NM) -CSn $@ > $(notdir $*.lst)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
memory.o strings.o: CFLAGS += -O3
|
||||
config.o: CFLAGS += -DCONFIG_TITLE="\"$(APP_TITLE) $(REVISION)_3gx_beta configuration\""
|
||||
patches.o: CFLAGS += -DVERSION_MAJOR="$(VERSION_MAJOR)" -DVERSION_MINOR="$(VERSION_MINOR)"\
|
||||
-DVERSION_BUILD="$(VERSION_BUILD)" -DISRELEASE="$(IS_RELEASE)" -DCOMMIT_HASH="0x$(COMMIT)"
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
209
arm9/linker.ld
Normal file
209
arm9/linker.ld
Normal file
@@ -0,0 +1,209 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
crt0 PT_LOAD;
|
||||
itcm PT_LOAD;
|
||||
main PT_LOAD;
|
||||
}
|
||||
|
||||
/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */
|
||||
MEMORY
|
||||
{
|
||||
main : ORIGIN = 0x08006000, LENGTH = 0x080F0000 - 0x08006000
|
||||
itcm : ORIGIN = 0x01FF8000, LENGTH = 0x01FFB800 - 0x01FF8000 /* Unused ITCM slice. */
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(__start__ = 0x08006000);
|
||||
PROVIDE(__stack_top__ = 0x08100000);
|
||||
PROVIDE(__stack_bottom__ = 0x080F0000);
|
||||
|
||||
PROVIDE(__itcm_stack_top__ = 0x01FFB800);
|
||||
PROVIDE(__itcm_stack_bottom__ = 0x01FFA800);
|
||||
|
||||
. = __start__;
|
||||
|
||||
.crt0 :
|
||||
{
|
||||
KEEP( *(.text.start) )
|
||||
KEEP( *(.init) )
|
||||
. = ALIGN(32);
|
||||
} >main :crt0
|
||||
|
||||
.itcm_loadable :
|
||||
{
|
||||
PROVIDE (__itcm_start__ = ABSOLUTE(.));
|
||||
PROVIDE (__itcm_lma__ = LOADADDR(.itcm_loadable));
|
||||
|
||||
KEEP(*(.arm9_exception_handlers.text))
|
||||
*(.arm9_exception_handlers.text*)
|
||||
KEEP(*(.chainloader.text.start))
|
||||
|
||||
chainloader.o(.text*)
|
||||
i2c.o(.text*)
|
||||
arm9_exception_handlers.o(.text*)
|
||||
|
||||
*(.arm9_exception_handlers.rodata*)
|
||||
chainloader.o(.rodata*)
|
||||
i2c.o(.rodata*)
|
||||
arm9_exception_handlers.o(.rodata*)
|
||||
|
||||
*(.arm9_exception_handlers.data*)
|
||||
chainloader.o(.data*)
|
||||
i2c.o(.data*)
|
||||
arm9_exception_handlers.o(.data*)
|
||||
. = ALIGN(32);
|
||||
} >itcm AT>main :itcm
|
||||
|
||||
.itcm_bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__itcm_bss_start__ = ABSOLUTE(.));
|
||||
|
||||
*(.arm9_exception_handlers.bss*)
|
||||
chainloader.o(.bss* COMMON)
|
||||
i2c.o(.bss* COMMON)
|
||||
arm9_exception_handlers.o(.bss* COMMON)
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__itcm_end__ = ABSOLUTE(.));
|
||||
} >itcm :NONE
|
||||
|
||||
.text :
|
||||
{
|
||||
/* .text */
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
*(.stub)
|
||||
*(.gnu.warning)
|
||||
*(.gnu.linkonce.t*)
|
||||
|
||||
/* .fini */
|
||||
KEEP( *(.fini) )
|
||||
. = ALIGN(8);
|
||||
} >main :main
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
*(.roda)
|
||||
*(.rodata.*)
|
||||
*all.rodata*(*)
|
||||
*(.gnu.linkonce.r*)
|
||||
SORT(CONSTRUCTORS)
|
||||
. = ALIGN(8);
|
||||
} >main
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
} >main
|
||||
|
||||
.init_array ALIGN(4) :
|
||||
{
|
||||
PROVIDE (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE (__init_array_end = .);
|
||||
} >main
|
||||
|
||||
.fini_array ALIGN(4) :
|
||||
{
|
||||
PROVIDE (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE (__fini_array_end = .);
|
||||
} >main
|
||||
|
||||
.ctors ALIGN(4) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >main
|
||||
|
||||
.dtors ALIGN(4) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >main
|
||||
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = ABSOLUTE(.);} >main
|
||||
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = ABSOLUTE(.);} >main
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
KEEP (*(.large_patch*))
|
||||
*(.gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
. = ALIGN(32);
|
||||
} >main
|
||||
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__bss_start__ = ABSOLUTE(.));
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b*)
|
||||
*(COMMON)
|
||||
. = ALIGN(8);
|
||||
PROVIDE (__bss_end__ = ABSOLUTE(.));
|
||||
} >main :NONE
|
||||
__end__ = 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) }
|
||||
}
|
||||
7
arm9/linker.specs
Normal file
7
arm9/linker.specs
Normal file
@@ -0,0 +1,7 @@
|
||||
%rename link old_link
|
||||
|
||||
*link:
|
||||
%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections
|
||||
|
||||
*startfile:
|
||||
crti%O%s crtbegin%O%s
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -30,21 +30,21 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
u32 address;
|
||||
u32 phyRegionSize;
|
||||
u32 size;
|
||||
} CodeSetInfo;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
u32 saveDataSize[2];
|
||||
u32 jumpID[2];
|
||||
u8 reserved[0x30];
|
||||
} SystemInfo;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
char appTitle[8];
|
||||
u8 reserved1[5];
|
||||
@@ -60,7 +60,7 @@ typedef struct __attribute__((packed))
|
||||
SystemInfo systemInfo;
|
||||
} SystemControlInfo;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
SystemControlInfo systemControlInfo;
|
||||
u8 aci[0x200];
|
||||
@@ -69,7 +69,7 @@ typedef struct __attribute__((packed))
|
||||
u8 aciLim[0x200];
|
||||
} ExHeader;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
u8 sig[0x100]; //RSA-2048 signature of the NCCH header, using SHA-256
|
||||
char magic[4]; //NCCH
|
||||
@@ -102,13 +102,13 @@ typedef struct __attribute__((packed))
|
||||
u8 romFsHash[0x20]; //RomFS superblock SHA-256 hash
|
||||
} Ncch;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
Ncch ncch;
|
||||
ExHeader exHeader;
|
||||
} Cxi;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
char sigIssuer[0x40];
|
||||
u8 eccPubKey[0x3C];
|
||||
@@ -134,7 +134,7 @@ typedef struct __attribute__((packed))
|
||||
u8 contentIndex[0xAC];
|
||||
} Ticket;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
u32 offset;
|
||||
u8 *address;
|
||||
@@ -143,7 +143,7 @@ typedef struct __attribute__((packed))
|
||||
u8 hash[0x20];
|
||||
} FirmSection;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
char magic[4];
|
||||
u32 reserved1;
|
||||
@@ -153,7 +153,7 @@ typedef struct __attribute__((packed))
|
||||
FirmSection section[4];
|
||||
} Firm;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
u8 keyX[0x10];
|
||||
u8 keyY[0x10];
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -23,9 +23,6 @@
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
void flushCaches(void);
|
||||
void *alignedseqmemcpy(void *dst, const void *src, u32 len);
|
||||
@@ -1,5 +1,5 @@
|
||||
@ This file is part of Luma3DS
|
||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
@
|
||||
@ 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
|
||||
@@ -21,40 +21,45 @@
|
||||
@ * Prohibiting misrepresentation of the origin of that material,
|
||||
@ or requiring that modified versions of such material be marked in
|
||||
@ reasonable ways as different from the original version.
|
||||
|
||||
.section .text.alignedseqmemcpy, "ax", %progbits
|
||||
.arm
|
||||
@ Align on cache line boundaries & make sure the loops don't cross them.
|
||||
.align 5
|
||||
.global alignedseqmemcpy
|
||||
.type alignedseqmemcpy, %function
|
||||
alignedseqmemcpy:
|
||||
@ src=r1 and dst=r0 are expected to be 4-byte-aligned
|
||||
push {r4-r10, lr}
|
||||
|
||||
.section .text.start
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
ldr sp, =__stack_top__
|
||||
b main
|
||||
lsrs r12, r2, #5
|
||||
sub r2, r2, r12, lsl #5
|
||||
beq 2f
|
||||
|
||||
.text
|
||||
.balign 4
|
||||
.global disableMpuAndJumpToEntrypoints
|
||||
.type disableMpuAndJumpToEntrypoints, %function
|
||||
disableMpuAndJumpToEntrypoints:
|
||||
mov r4, r0
|
||||
mov r5, r1
|
||||
mov r6, r2
|
||||
mov r7, r3
|
||||
1:
|
||||
ldmia r1!, {r3-r10}
|
||||
stmia r0!, {r3-r10}
|
||||
subs r12, #1
|
||||
bne 1b
|
||||
|
||||
bl flushCaches
|
||||
2:
|
||||
lsrs r12, r2, #2
|
||||
sub r2, r2, r12, lsl #2
|
||||
beq 4f
|
||||
|
||||
@ Disable caches / MPU
|
||||
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
||||
bic r0, #(1<<12) @ - instruction cache disable
|
||||
bic r0, #(1<<2) @ - data cache disable
|
||||
bic r0, #(1<<0) @ - MPU disable
|
||||
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
||||
3:
|
||||
ldr r3, [r1], #4
|
||||
str r3, [r0], #4
|
||||
subs r12, #1
|
||||
bne 3b
|
||||
|
||||
@ Set the ARM11 entrypoint
|
||||
mov r0, #0x20000000
|
||||
str r7, [r0, #-4]
|
||||
4:
|
||||
tst r2, #2
|
||||
ldrneh r3, [r1], #2
|
||||
strneh r3, [r0], #2
|
||||
|
||||
@ Jump to the ARM9 entrypoint
|
||||
mov r0, r4
|
||||
mov r1, r5
|
||||
ldr r2, =0x3BEEF
|
||||
bx r6
|
||||
tst r2, #1
|
||||
ldrneb r3, [r1], #1
|
||||
strneb r3, [r0], #1
|
||||
|
||||
pop {r4-r10, pc}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -24,15 +24,16 @@
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#include "arm9_exception_handlers.h"
|
||||
#include "i2c.h"
|
||||
#include "handlers.h"
|
||||
#include "screen.h"
|
||||
|
||||
#define FINAL_BUFFER 0x25000000
|
||||
|
||||
#define REG_DUMP_SIZE 4 * 17
|
||||
#define CODE_DUMP_SIZE 48
|
||||
|
||||
void __attribute__((noreturn)) mainHandler(u32 *registerDump, u32 type)
|
||||
void __attribute__((noreturn)) arm9ExceptionHandlerMain(u32 *registerDump, u32 type)
|
||||
{
|
||||
ExceptionDumpHeader dumpHeader;
|
||||
|
||||
@@ -73,10 +74,10 @@ void __attribute__((noreturn)) mainHandler(u32 *registerDump, u32 type)
|
||||
//Copy header (actually optimized by the compiler)
|
||||
*(ExceptionDumpHeader *)FINAL_BUFFER = dumpHeader;
|
||||
|
||||
if(ARESCREENSINITIALIZED) i2cWriteRegister(I2C_DEV_MCU, 0x22, 1 << 0); //Shutdown LCD
|
||||
if(ARESCREENSINITIALIZED) I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0); //Shutdown LCD
|
||||
|
||||
((void (*)())0xFFFF0830)(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||
|
||||
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot
|
||||
I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot
|
||||
while(true);
|
||||
}
|
||||
32
arm9/source/arm9_exception_handlers.h
Normal file
32
arm9/source/arm9_exception_handlers.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
* * Requiring preservation of specified reasonable legal notices or
|
||||
* author attributions in that material or in the Appropriate Legal
|
||||
* Notices displayed by works containing it.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
extern const u32 arm9ExceptionHandlerAddressTable[6];
|
||||
extern u32 arm9ExceptionHandlerSvcBreakAddress;
|
||||
|
||||
u32 safecpy(void *dst, const void *src, u32 len);
|
||||
@@ -1,5 +1,5 @@
|
||||
@ This file is part of Luma3DS
|
||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
@
|
||||
@ 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
|
||||
@@ -28,16 +28,16 @@
|
||||
stmia sp, {r0-r7}
|
||||
|
||||
mov r0, #\index
|
||||
b _commonHandler
|
||||
b _arm9ExceptionHandlerCommon
|
||||
.endm
|
||||
|
||||
.text
|
||||
.section .arm9_exception_handlers.text, "ax", %progbits
|
||||
.arm
|
||||
.balign 4
|
||||
.align 4
|
||||
|
||||
.global _commonHandler
|
||||
.type _commonHandler, %function
|
||||
_commonHandler:
|
||||
.global _arm9ExceptionHandlerCommon
|
||||
.type _arm9ExceptionHandlerCommon, %function
|
||||
_arm9ExceptionHandlerCommon:
|
||||
mov r1, r0
|
||||
mov r0, sp
|
||||
mrs r2, spsr
|
||||
@@ -60,7 +60,7 @@ _commonHandler:
|
||||
|
||||
msr cpsr_cxsf, #0xdf @ finally, switch to system mode, mask interrupts and clear flags (in case of double faults)
|
||||
ldr sp, =0x02000000
|
||||
b mainHandler
|
||||
b arm9ExceptionHandlerMain
|
||||
|
||||
|
||||
.global FIQHandler
|
||||
@@ -80,7 +80,7 @@ prefetchAbortHandler:
|
||||
cmp sp, #0x13
|
||||
bne _prefetchAbortNormalHandler
|
||||
|
||||
ldr sp, =BreakPtr
|
||||
ldr sp, =arm9ExceptionHandlerSvcBreakAddress
|
||||
ldr sp, [sp]
|
||||
cmp sp, #0
|
||||
beq _prefetchAbortNormalHandler
|
||||
@@ -147,6 +147,22 @@ safecpy:
|
||||
|
||||
_safecpy_end:
|
||||
|
||||
.bss
|
||||
.balign 4
|
||||
.section .arm9_exception_handlers.rodata, "a", %progbits
|
||||
.align 4
|
||||
.global arm9ExceptionHandlerAddressTable
|
||||
arm9ExceptionHandlerAddressTable:
|
||||
.word 0 @ IRQ
|
||||
.word FIQHandler @ FIQ
|
||||
.word 0 @ SVC
|
||||
.word undefinedInstructionHandler @ Undefined instruction
|
||||
.word prefetchAbortHandler @ Prefetch abort
|
||||
.word dataAbortHandler @ Data abort
|
||||
|
||||
.section .arm9_exception_handlers.bss, "aw", %nobits
|
||||
.align 4
|
||||
|
||||
.global arm9ExceptionHandlerSvcBreakAddress
|
||||
arm9ExceptionHandlerSvcBreakAddress:
|
||||
.skip 4
|
||||
|
||||
_regs: .skip (4 * 17)
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -33,7 +33,7 @@
|
||||
The data cache and/or the instruction cache MUST be flushed before doing one of the following:
|
||||
- rebooting
|
||||
- powering down
|
||||
- setting the ARM11 entrypoint to execute a function
|
||||
- setting the Arm11 entrypoint to execute a function
|
||||
- jumping to a payload
|
||||
***/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@ This file is part of Luma3DS
|
||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
@
|
||||
@ 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
|
||||
@@ -22,7 +22,7 @@
|
||||
@ or requiring that modified versions of such material be marked in
|
||||
@ reasonable ways as different from the original version.
|
||||
|
||||
.text
|
||||
.section .text.cache, "ax", %progbits
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
flushEntireDCache:
|
||||
@ Adapted from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html,
|
||||
@ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well
|
||||
@ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has)
|
||||
@ Note: Arm's example is actually for a 8KB DCache (which is what the 3DS has)
|
||||
|
||||
@ Implemented in bootROM at address 0xffff0830
|
||||
mov r1, #0 @ segment counter
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -24,11 +24,37 @@
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
#include "cache.h"
|
||||
#include "firm.h"
|
||||
#include "chainloader.h"
|
||||
#include "screen.h"
|
||||
|
||||
void main(int argc, char **argv, Firm *firm)
|
||||
void disableMpuAndJumpToEntrypoints(int argc, char **argv, void *arm11Entry, void *arm9Entry);
|
||||
|
||||
#pragma GCC optimize (3)
|
||||
|
||||
static void *xmemcpy(void *dst, const void *src, u32 len)
|
||||
{
|
||||
const u8 *src8 = (const u8 *)src;
|
||||
u8 *dst8 = (u8 *)dst;
|
||||
|
||||
for (u32 i = 0; i < len; i++) {
|
||||
dst8[i] = src8[i];
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
static void doLaunchFirm(Firm *firm, int argc, char **argv)
|
||||
{
|
||||
//Copy FIRM sections to respective memory locations
|
||||
for(u32 sectionNum = 0; sectionNum < 4; sectionNum++)
|
||||
xmemcpy(firm->section[sectionNum].address, (u8 *)firm + firm->section[sectionNum].offset, firm->section[sectionNum].size);
|
||||
|
||||
disableMpuAndJumpToEntrypoints(argc, argv, firm->arm9Entry, firm->arm11Entry);
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void chainloader_main(int argc, char **argv, Firm *firm)
|
||||
{
|
||||
char *argvPassed[2],
|
||||
absPath[24 + 255];
|
||||
@@ -54,5 +80,5 @@ void main(int argc, char **argv, Firm *firm)
|
||||
argvPassed[1] = (char *)&fbs;
|
||||
}
|
||||
|
||||
launchFirm(firm, argc, argvPassed);
|
||||
doLaunchFirm(firm, argc, argvPassed);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -24,12 +24,9 @@
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
/*
|
||||
* memcpy adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "firm.h"
|
||||
|
||||
void memcpy(void *dest, const void *src, u32 size);
|
||||
void chainload(int argc, char **argv, Firm *firm);
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -27,10 +27,10 @@
|
||||
#include "config.h"
|
||||
#include "memory.h"
|
||||
#include "fs.h"
|
||||
#include "strings.h"
|
||||
#include "utils.h"
|
||||
#include "screen.h"
|
||||
#include "draw.h"
|
||||
#include "emunand.h"
|
||||
#include "buttons.h"
|
||||
#include "pin.h"
|
||||
|
||||
@@ -94,7 +94,8 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
"( ) Show NAND or user string in System Settings",
|
||||
"( ) Show GBA boot screen in patched AGB_FIRM",
|
||||
"( ) Set developer UNITINFO",
|
||||
"( ) Disable ARM11 exception handlers",
|
||||
"( ) Disable Arm11 exception handlers",
|
||||
"( ) Enable Rosalina on SAFE_FIRM",
|
||||
};
|
||||
|
||||
static const char *optionsDescription[] = { "Select the default EmuNAND.\n\n"
|
||||
@@ -189,20 +190,36 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
"are doing!",
|
||||
|
||||
"Disables the fatal error exception\n"
|
||||
"handlers for the ARM11 CPU.\n\n"
|
||||
"handlers for the Arm11 CPU.\n\n"
|
||||
"Note: Disabling the exception handlers\n"
|
||||
"will disqualify you from submitting\n"
|
||||
"issues or bug reports to the Luma3DS\n"
|
||||
"GitHub repository!"
|
||||
"GitHub repository!",
|
||||
|
||||
"Enables Rosalina, the kernel ext.\n"
|
||||
"and sysmodule reimplementations on\n"
|
||||
"SAFE_FIRM (New 3DS only).\n\n"
|
||||
"Also suppresses QTM error 0xF96183FE,\n"
|
||||
"allowing to use 8.1-11.3 N3DS on\n"
|
||||
"New 2DS XL consoles.\n\n"
|
||||
"Only select this if you know what you\n"
|
||||
"are doing!",
|
||||
};
|
||||
|
||||
FirmwareSource nandType = FIRMWARE_SYSNAND;
|
||||
if(isSdMode)
|
||||
{
|
||||
nandType = FIRMWARE_EMUNAND;
|
||||
locateEmuNand(&nandType);
|
||||
}
|
||||
|
||||
struct multiOption {
|
||||
u32 posXs[4];
|
||||
u32 posY;
|
||||
u32 enabled;
|
||||
bool visible;
|
||||
} multiOptions[] = {
|
||||
{ .visible = isSdMode },
|
||||
{ .visible = nandType == FIRMWARE_EMUNAND },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
@@ -215,22 +232,23 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
bool enabled;
|
||||
bool visible;
|
||||
} singleOptions[] = {
|
||||
{ .visible = isSdMode },
|
||||
{ .visible = isSdMode },
|
||||
{ .visible = nandType == FIRMWARE_EMUNAND },
|
||||
{ .visible = nandType == FIRMWARE_EMUNAND },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = true }
|
||||
{ .visible = true },
|
||||
{ .visible = ISN3DS },
|
||||
};
|
||||
|
||||
//Calculate the amount of the various kinds of options and pre-select the first single one
|
||||
u32 multiOptionsAmount = sizeof(multiOptions) / sizeof(struct multiOption),
|
||||
singleOptionsAmount = sizeof(singleOptions) / sizeof(struct singleOption),
|
||||
totalIndexes = multiOptionsAmount + singleOptionsAmount - 1,
|
||||
selectedOption,
|
||||
singleSelected;
|
||||
selectedOption = 0,
|
||||
singleSelected = 0;
|
||||
bool isMultiOption = false;
|
||||
|
||||
//Parse the existing options
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#define CONFIG_FILE "config.bin"
|
||||
#define CONFIG_VERSIONMAJOR 2
|
||||
#define CONFIG_VERSIONMINOR 3
|
||||
#define CONFIG_VERSIONMINOR 4
|
||||
|
||||
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
|
||||
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
|
||||
@@ -60,7 +60,8 @@ enum singleOptions
|
||||
PATCHVERSTRING,
|
||||
SHOWGBABOOT,
|
||||
PATCHUNITINFO,
|
||||
DISABLEARM11EXCHANDLERS
|
||||
DISABLEARM11EXCHANDLERS,
|
||||
ENABLESAFEFIRMROSALINA,
|
||||
};
|
||||
|
||||
typedef enum ConfigurationStatus
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -34,8 +34,9 @@
|
||||
#include "crypto.h"
|
||||
#include "memory.h"
|
||||
#include "emunand.h"
|
||||
#include "strings.h"
|
||||
#include "utils.h"
|
||||
#include "alignedseqmemcpy.h"
|
||||
#include "strings.h"
|
||||
#include "fatfs/sdmmc/sdmmc.h"
|
||||
|
||||
/****************************************************************
|
||||
@@ -288,24 +289,18 @@ void sha(void *res, const void *src, u32 size, u32 mode)
|
||||
sha_wait_idle();
|
||||
*REG_SHA_CNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND;
|
||||
|
||||
const u32 *src32 = (const u32 *)src;
|
||||
int i;
|
||||
const u8 *src8 = (const u8 *)src;
|
||||
while(size >= 0x40)
|
||||
{
|
||||
sha_wait_idle();
|
||||
for(i = 0; i < 4; ++i)
|
||||
{
|
||||
*REG_SHA_INFIFO = *src32++;
|
||||
*REG_SHA_INFIFO = *src32++;
|
||||
*REG_SHA_INFIFO = *src32++;
|
||||
*REG_SHA_INFIFO = *src32++;
|
||||
}
|
||||
alignedseqmemcpy((void *)REG_SHA_INFIFO, src8, 0x40);
|
||||
|
||||
src8 += 0x40;
|
||||
size -= 0x40;
|
||||
}
|
||||
|
||||
sha_wait_idle();
|
||||
memcpy((void *)REG_SHA_INFIFO, src32, size);
|
||||
alignedseqmemcpy((void *)REG_SHA_INFIFO, src8, size);
|
||||
|
||||
*REG_SHA_CNT = (*REG_SHA_CNT & ~SHA_NORMAL_ROUND) | SHA_FINAL_ROUND;
|
||||
|
||||
@@ -318,7 +313,7 @@ void sha(void *res, const void *src, u32 size, u32 mode)
|
||||
else if(mode == SHA_1_MODE)
|
||||
hashSize = SHA_1_HASH_SIZE;
|
||||
|
||||
memcpy(res, (void *)REG_SHA_HASH, hashSize);
|
||||
alignedseqmemcpy(res, (void *)REG_SHA_HASH, hashSize);
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
@@ -532,7 +527,7 @@ void setupKeyslots(void)
|
||||
aes_setkey(0x25, keyX0x25s[ISDEVUNIT ? 1 : 0], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x2F, keyY0x2Fs[ISDEVUNIT ? 1 : 0], AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
|
||||
if(ISN3DS)
|
||||
if(ISN3DS)
|
||||
{
|
||||
//Setup 0x05 KeyY
|
||||
__attribute__((aligned(4))) static const u8 keyY0x5[AES_BLOCK_SIZE] = {0x4D, 0x80, 0x4F, 0x4E, 0x99, 0x90, 0x19, 0x46, 0x13, 0xA2, 0x04, 0xAC, 0x58, 0x44, 0x60, 0xBE};
|
||||
@@ -547,7 +542,7 @@ void setupKeyslots(void)
|
||||
{0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98}
|
||||
}, decKey[AES_BLOCK_SIZE];
|
||||
|
||||
//Initialize Key 0x18
|
||||
//Initialize Key 0x18
|
||||
aes_setkey(0x11, key1s[ISDEVUNIT ? 1 : 0], AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_use_keyslot(0x11);
|
||||
aes(decKey, keyBlocks[0], 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||
@@ -586,6 +581,9 @@ void kernel9Loader(Arm9Bin *arm9Section)
|
||||
|
||||
u8 arm9BinSlot = k9lVersion == 0 ? 0x15 : 0x16;
|
||||
|
||||
// Get size
|
||||
u32 arm9SectionSize = decAtoi(arm9Section->size, 8);
|
||||
|
||||
//Set keyX
|
||||
__attribute__((aligned(4))) u8 keyX[AES_BLOCK_SIZE];
|
||||
aes_use_keyslot(0x11);
|
||||
@@ -601,11 +599,11 @@ void kernel9Loader(Arm9Bin *arm9Section)
|
||||
__attribute__((aligned(4))) u8 arm9BinCtr[AES_BLOCK_SIZE];
|
||||
memcpy(arm9BinCtr, arm9Section->ctr, sizeof(arm9BinCtr));
|
||||
|
||||
//Decrypt ARM9 binary
|
||||
//Decrypt Arm9 binary
|
||||
aes_use_keyslot(arm9BinSlot);
|
||||
aes(startOfArm9Bin, startOfArm9Bin, decAtoi(arm9Section->size, sizeof(arm9Section->size)) / AES_BLOCK_SIZE, arm9BinCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes(startOfArm9Bin, startOfArm9Bin, arm9SectionSize / AES_BLOCK_SIZE, arm9BinCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
|
||||
if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the ARM9 binary.");
|
||||
if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the Arm9 binary.");
|
||||
}
|
||||
|
||||
void computePinHash(u8 *outbuf, const u8 *inbuf)
|
||||
@@ -614,7 +612,7 @@ void computePinHash(u8 *outbuf, const u8 *inbuf)
|
||||
cipherText[AES_BLOCK_SIZE];
|
||||
|
||||
sdmmc_get_cid(1, (u32 *)cid);
|
||||
aes_use_keyslot(0x04); //Console-unique keyslot whose keys are set by the ARM9 bootROM
|
||||
aes_use_keyslot(0x04); //Console-unique keyslot whose keys are set by the Arm9 bootROM
|
||||
aes(cipherText, inbuf, 1, cid, AES_CBC_ENCRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
sha(outbuf, cipherText, sizeof(cipherText), SHA_256_MODE);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include "draw.h"
|
||||
#include "strings.h"
|
||||
#include "memory.h"
|
||||
#include "screen.h"
|
||||
#include "utils.h"
|
||||
#include "fs.h"
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "memory.h"
|
||||
#include "utils.h"
|
||||
#include "fatfs/sdmmc/sdmmc.h"
|
||||
#include "../build/bundled.h"
|
||||
#include "large_patches.h"
|
||||
|
||||
u32 emuOffset,
|
||||
emuHeader;
|
||||
@@ -109,8 +109,8 @@ static inline bool getFreeK9Space(u8 *pos, u32 size, u8 **freeK9Space)
|
||||
//Looking for the last free space before Process9
|
||||
*freeK9Space = memsearch(pos, pattern, size, sizeof(pattern));
|
||||
|
||||
if(*freeK9Space == NULL || (u32)(pos + size - *freeK9Space) < 0x455 + emunand_bin_size ||
|
||||
*(u32 *)(*freeK9Space + 0x455 + emunand_bin_size - 4) != 0xFFFFFFFF) return false;
|
||||
if(*freeK9Space == NULL || (u32)(pos + size - *freeK9Space) < 0x455 + emunandPatchSize ||
|
||||
*(u32 *)(*freeK9Space + 0x455 + emunandPatchSize - 4) != 0xFFFFFFFF) return false;
|
||||
|
||||
*freeK9Space += 0x455;
|
||||
|
||||
@@ -195,20 +195,17 @@ u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 proce
|
||||
|
||||
u32 ret = 0;
|
||||
|
||||
//Copy EmuNAND code
|
||||
memcpy(freeK9Space, emunand_bin, emunand_bin_size);
|
||||
|
||||
//Add the data of the found EmuNAND
|
||||
u32 *posOffset = (u32 *)memsearch(freeK9Space, "NAND", emunand_bin_size, 4),
|
||||
*posHeader = (u32 *)memsearch(freeK9Space, "NCSD", emunand_bin_size, 4);
|
||||
*posOffset = emuOffset;
|
||||
*posHeader = emuHeader;
|
||||
emunandPatchNandOffset = emuOffset;
|
||||
emunandPatchNcsdHeaderOffset = emuHeader;
|
||||
|
||||
//Find and add the SDMMC struct
|
||||
u32 *posSdmmc = (u32 *)memsearch(freeK9Space, "SDMC", emunand_bin_size, 4);
|
||||
u32 sdmmc;
|
||||
ret += !ISN3DS && firmVersion < 0x25 ? getOldSdmmc(&sdmmc, firmVersion) : getSdmmc(process9Offset, process9Size, &sdmmc);
|
||||
if(!ret) *posSdmmc = sdmmc;
|
||||
if(!ret) emunandPatchSdmmcStructPtr = sdmmc;
|
||||
|
||||
//Copy EmuNAND code
|
||||
memcpy(freeK9Space, emunandPatch, emunandPatchSize);
|
||||
|
||||
//Add EmuNAND hooks
|
||||
u32 branchOffset = (u32)(freeK9Space - arm9Section + kernel9Address);
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -26,31 +26,28 @@
|
||||
|
||||
#include "exceptions.h"
|
||||
#include "fs.h"
|
||||
#include "strings.h"
|
||||
#include "memory.h"
|
||||
#include "screen.h"
|
||||
#include "draw.h"
|
||||
#include "utils.h"
|
||||
#include "fmt.h"
|
||||
#include "buttons.h"
|
||||
#include "../build/bundled.h"
|
||||
#include "arm9_exception_handlers.h"
|
||||
|
||||
// See https://github.com/LumaTeam/luma3ds_exception_dump_parser
|
||||
|
||||
void installArm9Handlers(void)
|
||||
{
|
||||
memcpy((void *)0x01FF8000, arm9_exceptions_bin, arm9_exceptions_bin_size);
|
||||
vu32 *dstVeneers = (vu32 *)0x08000000;
|
||||
|
||||
/* IRQHandler is at 0x08000000, but we won't handle it for some reasons
|
||||
svcHandler is at 0x08000010, but we won't handle svc either */
|
||||
|
||||
static const u32 offsets[] = {0x08, 0x18, 0x20, 0x28};
|
||||
|
||||
for(u32 i = 0; i < 4; i++)
|
||||
for(u32 i = 0; i < 6; i++)
|
||||
{
|
||||
*(vu32 *)(0x08000000 + offsets[i]) = 0xE51FF004;
|
||||
*(vu32 *)(0x08000000 + offsets[i] + 4) = *(vu32 *)(0x01FF8008 + 4 * i);
|
||||
if(arm9ExceptionHandlerAddressTable[i] != 0)
|
||||
{
|
||||
dstVeneers[2 * i] = 0xE51FF004;
|
||||
dstVeneers[2 * i + 1] = arm9ExceptionHandlerAddressTable[i];
|
||||
}
|
||||
}
|
||||
|
||||
*(vu32 *)0x01FF8004 = 0; //BreakPtr
|
||||
}
|
||||
|
||||
void detectAndProcessExceptionDumps(void)
|
||||
@@ -90,8 +87,8 @@ void detectAndProcessExceptionDumps(void)
|
||||
|
||||
drawString(true, 10, 10, COLOR_RED, "An exception occurred");
|
||||
u32 posY;
|
||||
if(dumpHeader->processor == 11) posY = drawFormattedString(true, 10, 30, COLOR_WHITE, "Processor: ARM11 (core %u)", dumpHeader->core);
|
||||
else posY = drawString(true, 10, 30, COLOR_WHITE, "Processor: ARM9");
|
||||
if(dumpHeader->processor == 11) posY = drawFormattedString(true, 10, 30, COLOR_WHITE, "Processor: Arm11 (core %u)", dumpHeader->core);
|
||||
else posY = drawString(true, 10, 30, COLOR_WHITE, "Processor: Arm9");
|
||||
|
||||
if(dumpHeader->type == 2)
|
||||
{
|
||||
@@ -138,16 +135,16 @@ void detectAndProcessExceptionDumps(void)
|
||||
|
||||
for(u32 i = 0; i < 17; i += 2)
|
||||
{
|
||||
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08X", registerNames[i], regs[i]);
|
||||
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08lX", registerNames[i], regs[i]);
|
||||
|
||||
if(i != 16)
|
||||
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08X", registerNames[i + 1], regs[i + 1]);
|
||||
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08lX", registerNames[i + 1], regs[i + 1]);
|
||||
else if(dumpHeader->processor == 11)
|
||||
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08X", registerNames[i + 1], regs[20]);
|
||||
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08lX", registerNames[i + 1], regs[20]);
|
||||
}
|
||||
|
||||
if(dumpHeader->processor == 11 && dumpHeader->type == 3)
|
||||
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08X Access type: %s", "FAR", regs[19], regs[17] & (1u << 11) ? "Write" : "Read");
|
||||
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08lX Access type: %s", "FAR", regs[19], regs[17] & (1u << 11) ? "Write" : "Read");
|
||||
|
||||
posY += SPACING_Y;
|
||||
|
||||
@@ -159,7 +156,7 @@ void detectAndProcessExceptionDumps(void)
|
||||
|
||||
for(u32 line = 0; line < 19 && stackDump < additionalData; line++)
|
||||
{
|
||||
posYBottom = drawFormattedString(false, 10, posYBottom + SPACING_Y, COLOR_WHITE, "%08X:", regs[13] + 8 * line);
|
||||
posYBottom = drawFormattedString(false, 10, posYBottom + SPACING_Y, COLOR_WHITE, "%08lX:", regs[13] + 8 * line);
|
||||
|
||||
for(u32 i = 0; i < 8 && stackDump < additionalData; i++, stackDump++)
|
||||
drawFormattedString(false, 10 + 10 * SPACING_X + 3 * i * SPACING_X, posYBottom, COLOR_WHITE, "%02X", *stackDump);
|
||||
@@ -175,9 +172,9 @@ void detectAndProcessExceptionDumps(void)
|
||||
drawString(true, 10, posY + SPACING_Y, COLOR_BLACK, choiceMessage[0]);
|
||||
drawString(true, 10, posY + SPACING_Y + SPACING_Y , COLOR_BLACK, choiceMessage[1]);
|
||||
|
||||
char folderPath[12],
|
||||
path[36],
|
||||
fileName[24];
|
||||
char folderPath[32],
|
||||
path[128],
|
||||
fileName[32];
|
||||
|
||||
sprintf(folderPath, "dumps/arm%u", dumpHeader->processor);
|
||||
findDumpFile(folderPath, fileName);
|
||||
@@ -195,6 +192,6 @@ void detectAndProcessExceptionDumps(void)
|
||||
waitInput(false);
|
||||
|
||||
exit:
|
||||
memset32((void *)dumpHeader, 0, dumpHeader->totalSize);
|
||||
memset((void *)dumpHeader, 0, dumpHeader->totalSize);
|
||||
mcuPowerOff();
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -300,3 +300,31 @@ R0.13 (May 21, 2017)
|
||||
Fixed exFAT FAT entry can be collapsed when write or lseek operation to the existing file is done. (appeared at R0.12c)
|
||||
Fixed creating a file can fail when a new cluster allocation to the exFAT directory occures. (appeared at R0.12c)
|
||||
|
||||
|
||||
|
||||
R0.13a (October 14, 2017)
|
||||
|
||||
Added support for UTF-8 encoding on the API. (FF_LFN_UNICODE = 2)
|
||||
Added options for file name output buffer. (FF_LFN_BUF, FF_SFN_BUF).
|
||||
Added dynamic memory allocation option for working buffer of f_mkfs() and f_fdisk().
|
||||
Fixed f_fdisk() and f_mkfs() create the partition table with wrong CHS parameters. (appeared at R0.09)
|
||||
Fixed f_unlink() can cause lost clusters at fragmented file on the exFAT volume. (appeared at R0.12c)
|
||||
Fixed f_setlabel() rejects some valid characters for exFAT volume. (appeared at R0.12)
|
||||
|
||||
|
||||
|
||||
R0.13b (April 07, 2018)
|
||||
|
||||
Added support for UTF-32 encoding on the API. (FF_LFN_UNICODE = 3)
|
||||
Added support for Unix style volume ID. (FF_STR_VOLUME_ID = 2)
|
||||
Fixed accesing any object on the exFAT root directory beyond the cluster boundary can fail. (appeared at R0.12c)
|
||||
Fixed f_setlabel() does not reject some invalid characters. (appeared at R0.09b)
|
||||
|
||||
|
||||
|
||||
R0.13c (October 14, 2018)
|
||||
Supported stdint.h for C99 and later. (integer.h was included in ff.h)
|
||||
Fixed reading a directory gets infinite loop when the last directory entry is not empty. (appeared at R0.12)
|
||||
Fixed creating a sub-directory in the fragmented sub-directory on the exFAT volume collapses FAT chain of the parent directory. (appeared at R0.12)
|
||||
Fixed f_getcwd() cause output buffer overrun when the buffer has a valid drive number. (appeared at R0.13b)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FatFs Module Source Files R0.13
|
||||
FatFs Module Source Files R0.13c
|
||||
|
||||
|
||||
FILES
|
||||
@@ -10,7 +10,6 @@ FILES
|
||||
ff.h Common include file for FatFs and application module.
|
||||
diskio.h Common include file for FatFs and disk I/O module.
|
||||
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
|
||||
integer.h Integer type definitions for FatFs.
|
||||
ffunicode.c Optional Unicode utility functions.
|
||||
ffsystem.c An example of optional O/S related functions.
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "diskio.h" /* FatFs lower layer API */
|
||||
#include "sdmmc/sdmmc.h"
|
||||
#include "../crypto.h"
|
||||
#include "../i2c.h"
|
||||
|
||||
/* Definitions of physical drive number for each media */
|
||||
#define SDCARD 0
|
||||
@@ -20,11 +21,11 @@
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_status (
|
||||
__attribute__((unused))
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
__attribute__((unused))
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
)
|
||||
{
|
||||
return RES_OK;
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +35,7 @@ DSTATUS disk_status (
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_initialize (
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
)
|
||||
{
|
||||
static u32 sdmmcInitResult = 4;
|
||||
@@ -52,10 +53,10 @@ DSTATUS disk_initialize (
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DRESULT disk_read (
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
BYTE *buff, /* Data buffer to store read data */
|
||||
DWORD sector, /* Sector address in LBA */
|
||||
UINT count /* Number of sectors to read */
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
BYTE *buff, /* Data buffer to store read data */
|
||||
DWORD sector, /* Sector address in LBA */
|
||||
UINT count /* Number of sectors to read */
|
||||
)
|
||||
{
|
||||
return ((pdrv == SDCARD && !sdmmc_sdcard_readsectors(sector, count, buff)) ||
|
||||
@@ -70,10 +71,10 @@ DRESULT disk_read (
|
||||
|
||||
#if _USE_WRITE
|
||||
DRESULT disk_write (
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
const BYTE *buff, /* Data to be written */
|
||||
DWORD sector, /* Sector address in LBA */
|
||||
UINT count /* Number of sectors to write */
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
const BYTE *buff, /* Data to be written */
|
||||
DWORD sector, /* Sector address in LBA */
|
||||
UINT count /* Number of sectors to write */
|
||||
)
|
||||
{
|
||||
return ((pdrv == SDCARD && (*(vu16 *)(SDMMC_BASE + REG_SDSTATUS0) & TMIO_STAT0_WRPROTECT) != 0 && !sdmmc_sdcard_writesectors(sector, count, buff)) ||
|
||||
@@ -89,13 +90,49 @@ DRESULT disk_write (
|
||||
|
||||
#if _USE_IOCTL
|
||||
DRESULT disk_ioctl (
|
||||
__attribute__((unused))
|
||||
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||
BYTE cmd, /* Control code */
|
||||
__attribute__((unused))
|
||||
void *buff /* Buffer to send/receive control data */
|
||||
__attribute__((unused))
|
||||
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||
BYTE cmd, /* Control code */
|
||||
__attribute__((unused))
|
||||
void *buff /* Buffer to send/receive control data */
|
||||
)
|
||||
{
|
||||
return cmd == CTRL_SYNC ? RES_OK : RES_PARERR;
|
||||
}
|
||||
#endif
|
||||
|
||||
// From GodMode9
|
||||
#define BCDVALID(b) (((b)<=0x99)&&(((b)&0xF)<=0x9)&&((((b)>>4)&0xF)<=0x9))
|
||||
#define BCD2NUM(b) (BCDVALID(b) ? (((b)&0xF)+((((b)>>4)&0xF)*10)) : 0xFF)
|
||||
#define NUM2BCD(n) ((n<99) ? (((n/10)*0x10)|(n%10)) : 0x99)
|
||||
#define DSTIMEGET(bcd,n) (BCD2NUM((bcd)->n))
|
||||
|
||||
// see: http://3dbrew.org/wiki/I2C_Registers#Device_3 (register 30)
|
||||
typedef struct DsTime {
|
||||
u8 bcd_s;
|
||||
u8 bcd_m;
|
||||
u8 bcd_h;
|
||||
u8 weekday;
|
||||
u8 bcd_D;
|
||||
u8 bcd_M;
|
||||
u8 bcd_Y;
|
||||
u8 leap_count;
|
||||
} DsTime;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Get current FAT time */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DWORD get_fattime( void ) {
|
||||
DsTime dstime;
|
||||
I2C_readRegBuf(I2C_DEV_MCU, 0x30, (u8 *)&dstime, sizeof(DsTime));
|
||||
DWORD fattime =
|
||||
((DSTIMEGET(&dstime, bcd_s)&0x3F) >> 1 ) |
|
||||
((DSTIMEGET(&dstime, bcd_m)&0x3F) << 5 ) |
|
||||
((DSTIMEGET(&dstime, bcd_h)&0x3F) << 11) |
|
||||
((DSTIMEGET(&dstime, bcd_D)&0x1F) << 16) |
|
||||
((DSTIMEGET(&dstime, bcd_M)&0x0F) << 21) |
|
||||
(((DSTIMEGET(&dstime, bcd_Y)+(2000-1980))&0x7F) << 25);
|
||||
|
||||
return fattime;
|
||||
}
|
||||
@@ -38,6 +38,7 @@ 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);
|
||||
|
||||
DWORD get_fattime( void ); // not a disk control function, but fits here
|
||||
|
||||
/* Disk Status Bits (DSTATUS) */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
||||
/*----------------------------------------------------------------------------/
|
||||
/ FatFs - Generic FAT Filesystem module R0.13 /
|
||||
/ FatFs - Generic FAT Filesystem module R0.13c /
|
||||
/-----------------------------------------------------------------------------/
|
||||
/
|
||||
/ Copyright (C) 2017, ChaN, all right reserved.
|
||||
/ 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
|
||||
@@ -20,13 +20,12 @@
|
||||
|
||||
|
||||
#ifndef FF_DEFINED
|
||||
#define FF_DEFINED 87030 /* Revision ID */
|
||||
#define FF_DEFINED 86604 /* Revision ID */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "integer.h" /* Basic integer types */
|
||||
#include "ffconf.h" /* FatFs configuration options */
|
||||
|
||||
#if FF_DEFINED != FFCONF_DEF
|
||||
@@ -34,6 +33,30 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Integer types used for FatFs API */
|
||||
|
||||
#if defined(_WIN32) /* Main development platform */
|
||||
#define FF_INTDEF 2
|
||||
#include <windows.h>
|
||||
typedef unsigned __int64 QWORD;
|
||||
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */
|
||||
#define FF_INTDEF 2
|
||||
#include <stdint.h>
|
||||
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||
typedef uint16_t WORD; /* 16-bit unsigned integer */
|
||||
typedef uint16_t WCHAR; /* 16-bit unsigned integer */
|
||||
typedef uint32_t DWORD; /* 32-bit unsigned integer */
|
||||
typedef uint64_t QWORD; /* 64-bit unsigned integer */
|
||||
#else /* Earlier than C99 */
|
||||
#define FF_INTDEF 1
|
||||
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||
typedef unsigned short WORD; /* 16-bit unsigned integer */
|
||||
typedef unsigned short WCHAR; /* 16-bit unsigned integer */
|
||||
typedef unsigned long DWORD; /* 32-bit unsigned integer */
|
||||
#endif
|
||||
|
||||
|
||||
/* Definitions of volume management */
|
||||
|
||||
@@ -45,24 +68,39 @@ typedef struct {
|
||||
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 */
|
||||
|
||||
#if FF_LFN_UNICODE && FF_USE_LFN /* Unicode (UTF-16) string */
|
||||
#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
|
||||
#define _INC_TCHAR
|
||||
#endif
|
||||
#else /* ANSI/OEM string */
|
||||
#ifndef _INC_TCHAR
|
||||
#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
|
||||
#define _INC_TCHAR
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -70,8 +108,8 @@ typedef char TCHAR;
|
||||
/* Type of file size variables */
|
||||
|
||||
#if FF_FS_EXFAT
|
||||
#if !FF_USE_LFN
|
||||
#error LFN must be enabled when enable exFAT
|
||||
#if FF_INTDEF != 2
|
||||
#error exFAT feature wants C99 or later
|
||||
#endif
|
||||
typedef QWORD FSIZE_t;
|
||||
#else
|
||||
@@ -83,8 +121,8 @@ typedef DWORD FSIZE_t;
|
||||
/* Filesystem object structure (FATFS) */
|
||||
|
||||
typedef struct {
|
||||
BYTE fs_type; /* Filesystem type (0:N/A) */
|
||||
BYTE pdrv; /* Physical drive number */
|
||||
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) */
|
||||
@@ -121,6 +159,9 @@ typedef struct {
|
||||
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[] */
|
||||
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||
} FATFS;
|
||||
@@ -133,7 +174,7 @@ 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:flagmented in this session, b2:sub-directory stretched) */
|
||||
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
|
||||
@@ -200,10 +241,10 @@ typedef struct {
|
||||
WORD ftime; /* Modified time */
|
||||
BYTE fattrib; /* File attribute */
|
||||
#if FF_USE_LFN
|
||||
TCHAR altname[13]; /* Altenative file name */
|
||||
TCHAR fname[FF_MAX_LFN + 1]; /* Primary file name */
|
||||
TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */
|
||||
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
|
||||
#else
|
||||
TCHAR fname[13]; /* File name */
|
||||
TCHAR fname[12 + 1]; /* File name */
|
||||
#endif
|
||||
} FILINFO;
|
||||
|
||||
@@ -299,10 +340,10 @@ DWORD get_fattime (void);
|
||||
#endif
|
||||
|
||||
/* LFN support functions */
|
||||
#if FF_USE_LFN /* Code conversion (defined in unicode.c) */
|
||||
#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 (WCHAR uni, WORD cp); /* Unicode to OEM code conversion */
|
||||
WCHAR ff_wtoupper (WCHAR uni); /* Unicode upper-case 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 */
|
||||
@@ -1,8 +1,8 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - Configuration file
|
||||
/ FatFs Functional Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FFCONF_DEF 87030 /* Revision ID */
|
||||
#define FFCONF_DEF 86604 /* Revision ID */
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function Configurations
|
||||
@@ -18,7 +18,7 @@
|
||||
#define FF_FS_MINIMIZE 0
|
||||
/* This option defines minimization level to remove some basic API functions.
|
||||
/
|
||||
/ 0: All basic functions are enabled.
|
||||
/ 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.
|
||||
@@ -106,32 +106,47 @@
|
||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
||||
/
|
||||
/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
|
||||
/ to the project. The working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
|
||||
/ additional 608 bytes at exFAT enabled. FF_MAX_LFN can be in range from 12 to 255.
|
||||
/ It should be set 255 to support full featured LFN operations.
|
||||
/ 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(), must be added to the project. */
|
||||
/ ff_memfree() in ffsystem.c, need to be added to the project. */
|
||||
|
||||
|
||||
#define FF_LFN_UNICODE 0
|
||||
/* This option switches character encoding on the API, 0:ANSI/OEM or 1:UTF-16,
|
||||
/ when LFN is enabled. 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_UNICODE 2
|
||||
/* 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 3
|
||||
/* When FF_LFN_UNICODE = 1 with LFN enabled, string I/O functions, f_gets(),
|
||||
/* 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
|
||||
/ 1: UTF-16LE
|
||||
/ 2: UTF-16BE
|
||||
/ 3: UTF-8
|
||||
/ 0: ANSI/OEM in current CP
|
||||
/ 1: Unicode in UTF-16LE
|
||||
/ 2: Unicode in UTF-16BE
|
||||
/ 3: Unicode in UTF-8
|
||||
*/
|
||||
|
||||
|
||||
@@ -154,11 +169,16 @@
|
||||
|
||||
#define FF_STR_VOLUME_ID 0
|
||||
#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
|
||||
/* FF_STR_VOLUME_ID switches string support for volume ID.
|
||||
/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
|
||||
/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each
|
||||
/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for
|
||||
/ the drive ID strings are: A-Z and 0-9. */
|
||||
/* 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
|
||||
@@ -212,17 +232,17 @@
|
||||
|
||||
#define FF_FS_EXFAT 0
|
||||
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
||||
/ When enable exFAT, also LFN needs to be enabled.
|
||||
/ 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 5
|
||||
#define FF_FS_NORTC 0
|
||||
#define FF_NORTC_MON 1
|
||||
#define FF_NORTC_MDAY 1
|
||||
#define FF_NORTC_YEAR 2017
|
||||
#define FF_NORTC_YEAR 2019
|
||||
/* The option FF_FS_NORTC switches timestamp functiton. 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. All objects modified by FatFs will have a fixed timestamp
|
||||
/ 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,
|
||||
@@ -242,6 +262,7 @@
|
||||
/ lock control is independent of re-entrancy. */
|
||||
|
||||
|
||||
/* #include <somertos.h> // O/S definitions */
|
||||
#define FF_FS_REENTRANT 0
|
||||
#define FF_FS_TIMEOUT 1000
|
||||
#define FF_SYNC_t HANDLE
|
||||
@@ -262,8 +283,6 @@
|
||||
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
||||
/ included somewhere in the scope of ff.h. */
|
||||
|
||||
/* #include <windows.h> // O/S definitions */
|
||||
|
||||
|
||||
|
||||
/*--- End of configuration options ---*/
|
||||
@@ -1,20 +1,19 @@
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Sample code of OS dependent controls for FatFs */
|
||||
/* (C)ChaN, 2017 */
|
||||
/* Sample Code of OS Dependent Functions for FatFs */
|
||||
/* (C)ChaN, 2018 */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include "ff.h"
|
||||
|
||||
|
||||
|
||||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Allocate a memory block */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */
|
||||
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
|
||||
UINT msize /* Number of bytes to allocate */
|
||||
)
|
||||
{
|
||||
@@ -27,7 +26,7 @@ void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on no
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void ff_memfree (
|
||||
void* mblock /* Pointer to the memory block to free */
|
||||
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
|
||||
)
|
||||
{
|
||||
free(mblock); /* Free the memory block with POSIX API */
|
||||
@@ -47,12 +46,12 @@ void ff_memfree (
|
||||
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
|
||||
*/
|
||||
|
||||
//const osMutexDef_t Mutex[FF_VOLUMES]; /* CMSIS-RTOS */
|
||||
//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */
|
||||
|
||||
|
||||
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
|
||||
BYTE vol, /* Corresponding volume (logical drive number) */
|
||||
FF_SYNC_t *sobj /* Pointer to return the created sync object */
|
||||
FF_SYNC_t* sobj /* Pointer to return the created sync object */
|
||||
)
|
||||
{
|
||||
/* Win32 */
|
||||
@@ -74,7 +73,7 @@ int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object
|
||||
// return (int)(*sobj != NULL);
|
||||
|
||||
/* CMSIS-RTOS */
|
||||
// *sobj = osMutexCreate(Mutex + vol);
|
||||
// *sobj = osMutexCreate(&Mutex[vol]);
|
||||
// return (int)(*sobj != NULL);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Unicode handling functions for FatFs R0.13+ */
|
||||
/* 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 /
|
||||
@@ -7,7 +7,7 @@
|
||||
/ that function to avoid silly memory consumption. /
|
||||
/-------------------------------------------------------------------------*/
|
||||
/*
|
||||
/ Copyright (C) 2017, ChaN, all right reserved.
|
||||
/ 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
|
||||
@@ -25,7 +25,11 @@
|
||||
|
||||
#include "ff.h"
|
||||
|
||||
#if FF_USE_LFN
|
||||
#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)
|
||||
@@ -36,8 +40,7 @@
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#if FF_CODE_PAGE == 932 || FF_CODE_PAGE == 0 /* Japanese */
|
||||
static
|
||||
const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */
|
||||
static const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */
|
||||
0x00A7, 0x8198, 0x00A8, 0x814E, 0x00B0, 0x818B, 0x00B1, 0x817D, 0x00B4, 0x814C, 0x00B6, 0x81F7, 0x00D7, 0x817E, 0x00F7, 0x8180,
|
||||
0x0391, 0x839F, 0x0392, 0x83A0, 0x0393, 0x83A1, 0x0394, 0x83A2, 0x0395, 0x83A3, 0x0396, 0x83A4, 0x0397, 0x83A5, 0x0398, 0x83A6,
|
||||
0x0399, 0x83A7, 0x039A, 0x83A8, 0x039B, 0x83A9, 0x039C, 0x83AA, 0x039D, 0x83AB, 0x039E, 0x83AC, 0x039F, 0x83AD, 0x03A0, 0x83AE,
|
||||
@@ -964,8 +967,7 @@ const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */
|
||||
0xFFE1, 0x8192, 0xFFE2, 0x81CA, 0xFFE3, 0x8150, 0xFFE4, 0xFA55, 0xFFE5, 0x818F, 0, 0
|
||||
};
|
||||
|
||||
static
|
||||
const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */
|
||||
static const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */
|
||||
0x00A1, 0xFF61, 0x00A2, 0xFF62, 0x00A3, 0xFF63, 0x00A4, 0xFF64, 0x00A5, 0xFF65, 0x00A6, 0xFF66, 0x00A7, 0xFF67, 0x00A8, 0xFF68,
|
||||
0x00A9, 0xFF69, 0x00AA, 0xFF6A, 0x00AB, 0xFF6B, 0x00AC, 0xFF6C, 0x00AD, 0xFF6D, 0x00AE, 0xFF6E, 0x00AF, 0xFF6F, 0x00B0, 0xFF70,
|
||||
0x00B1, 0xFF71, 0x00B2, 0xFF72, 0x00B3, 0xFF73, 0x00B4, 0xFF74, 0x00B5, 0xFF75, 0x00B6, 0xFF76, 0x00B7, 0xFF77, 0x00B8, 0xFF78,
|
||||
@@ -1894,8 +1896,7 @@ const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */
|
||||
#endif
|
||||
|
||||
#if FF_CODE_PAGE == 936 || FF_CODE_PAGE == 0 /* Simplified Chinese */
|
||||
static
|
||||
const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */
|
||||
static const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */
|
||||
0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3, 0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4,
|
||||
0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA, 0x00EC, 0xA8AC, 0x00ED, 0xA8AA, 0x00F2, 0xA8B0, 0x00F3, 0xA8AE,
|
||||
0x00F7, 0xA1C2, 0x00F9, 0xA8B4, 0x00FA, 0xA8B2, 0x00FC, 0xA8B9, 0x0101, 0xA8A1, 0x0113, 0xA8A5, 0x011B, 0xA8A7, 0x012B, 0xA8A9,
|
||||
@@ -4623,8 +4624,7 @@ const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */
|
||||
0, 0
|
||||
};
|
||||
|
||||
static
|
||||
const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */
|
||||
static const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */
|
||||
0x0080, 0x20AC, 0x8140, 0x4E02, 0x8141, 0x4E04, 0x8142, 0x4E05, 0x8143, 0x4E06, 0x8144, 0x4E0F, 0x8145, 0x4E12, 0x8146, 0x4E17,
|
||||
0x8147, 0x4E1F, 0x8148, 0x4E20, 0x8149, 0x4E21, 0x814A, 0x4E23, 0x814B, 0x4E26, 0x814C, 0x4E29, 0x814D, 0x4E2E, 0x814E, 0x4E2F,
|
||||
0x814F, 0x4E31, 0x8150, 0x4E33, 0x8151, 0x4E35, 0x8152, 0x4E37, 0x8153, 0x4E3C, 0x8154, 0x4E40, 0x8155, 0x4E41, 0x8156, 0x4E42,
|
||||
@@ -7354,8 +7354,7 @@ const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */
|
||||
#endif
|
||||
|
||||
#if FF_CODE_PAGE == 949 || FF_CODE_PAGE == 0 /* Korean */
|
||||
static
|
||||
const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */
|
||||
static const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */
|
||||
0x00A1, 0xA2AE, 0x00A4, 0xA2B4, 0x00A7, 0xA1D7, 0x00A8, 0xA1A7, 0x00AA, 0xA8A3, 0x00AD, 0xA1A9, 0x00AE, 0xA2E7, 0x00B0, 0xA1C6,
|
||||
0x00B1, 0xA1BE, 0x00B2, 0xA9F7, 0x00B3, 0xA9F8, 0x00B4, 0xA2A5, 0x00B6, 0xA2D2, 0x00B7, 0xA1A4, 0x00B8, 0xA2AC, 0x00B9, 0xA9F6,
|
||||
0x00BA, 0xA8AC, 0x00BC, 0xA8F9, 0x00BD, 0xA8F6, 0x00BE, 0xA8FA, 0x00BF, 0xA2AF, 0x00C6, 0xA8A1, 0x00D0, 0xA8A2, 0x00D7, 0xA1BF,
|
||||
@@ -9490,8 +9489,7 @@ const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */
|
||||
0, 0
|
||||
};
|
||||
|
||||
static
|
||||
const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */
|
||||
static const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */
|
||||
0x8141, 0xAC02, 0x8142, 0xAC03, 0x8143, 0xAC05, 0x8144, 0xAC06, 0x8145, 0xAC0B, 0x8146, 0xAC0C, 0x8147, 0xAC0D, 0x8148, 0xAC0E,
|
||||
0x8149, 0xAC0F, 0x814A, 0xAC18, 0x814B, 0xAC1E, 0x814C, 0xAC1F, 0x814D, 0xAC21, 0x814E, 0xAC22, 0x814F, 0xAC23, 0x8150, 0xAC25,
|
||||
0x8151, 0xAC26, 0x8152, 0xAC27, 0x8153, 0xAC28, 0x8154, 0xAC29, 0x8155, 0xAC2A, 0x8156, 0xAC2B, 0x8157, 0xAC2E, 0x8158, 0xAC32,
|
||||
@@ -11628,8 +11626,7 @@ const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */
|
||||
#endif
|
||||
|
||||
#if FF_CODE_PAGE == 950 || FF_CODE_PAGE == 0 /* Traditional Chinese */
|
||||
static
|
||||
const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */
|
||||
static const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */
|
||||
0x00A7, 0xA1B1, 0x00AF, 0xA1C2, 0x00B0, 0xA258, 0x00B1, 0xA1D3, 0x00B7, 0xA150, 0x00D7, 0xA1D1, 0x00F7, 0xA1D2, 0x02C7, 0xA3BE,
|
||||
0x02C9, 0xA3BC, 0x02CA, 0xA3BD, 0x02CB, 0xA3BF, 0x02CD, 0xA1C5, 0x02D9, 0xA3BB, 0x0391, 0xA344, 0x0392, 0xA345, 0x0393, 0xA346,
|
||||
0x0394, 0xA347, 0x0395, 0xA348, 0x0396, 0xA349, 0x0397, 0xA34A, 0x0398, 0xA34B, 0x0399, 0xA34C, 0x039A, 0xA34D, 0x039B, 0xA34E,
|
||||
@@ -13320,8 +13317,7 @@ const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */
|
||||
0xFF5C, 0xA155, 0xFF5D, 0xA162, 0xFF5E, 0xA1E3, 0xFFE0, 0xA246, 0xFFE1, 0xA247, 0xFFE3, 0xA1C3, 0xFFE5, 0xA244, 0, 0
|
||||
};
|
||||
|
||||
static
|
||||
const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */
|
||||
static const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */
|
||||
0xA140, 0x3000, 0xA141, 0xFF0C, 0xA142, 0x3001, 0xA143, 0x3002, 0xA144, 0xFF0E, 0xA145, 0x2027, 0xA146, 0xFF1B, 0xA147, 0xFF1A,
|
||||
0xA148, 0xFF1F, 0xA149, 0xFF01, 0xA14A, 0xFE30, 0xA14B, 0x2026, 0xA14C, 0x2025, 0xA14D, 0xFE50, 0xA14E, 0xFE51, 0xA14F, 0xFE52,
|
||||
0xA150, 0x00B7, 0xA151, 0xFE54, 0xA152, 0xFE55, 0xA153, 0xFE56, 0xA154, 0xFE57, 0xA155, 0xFF5C, 0xA156, 0x2013, 0xA157, 0xFE31,
|
||||
@@ -15014,8 +15010,7 @@ const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */
|
||||
#endif
|
||||
|
||||
#if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15027,8 +15022,7 @@ const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15040,8 +15034,7 @@ const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15053,8 +15046,7 @@ const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15066,8 +15058,7 @@ const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15079,8 +15070,7 @@ const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15092,8 +15082,7 @@ const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15105,8 +15094,7 @@ const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15118,8 +15106,7 @@ const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15131,8 +15118,7 @@ const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15144,8 +15130,7 @@ const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15157,8 +15142,7 @@ const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15170,8 +15154,7 @@ const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15183,8 +15166,7 @@ const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table *
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15196,8 +15178,7 @@ const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15209,8 +15190,7 @@ const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15222,8 +15202,7 @@ const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */
|
||||
};
|
||||
#endif
|
||||
#if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0
|
||||
static
|
||||
const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */
|
||||
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,
|
||||
@@ -15245,7 +15224,7 @@ const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */
|
||||
|
||||
#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900
|
||||
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
|
||||
WCHAR uni, /* Unicode character to be converted */
|
||||
DWORD uni, /* UTF-16 encoded character to be converted */
|
||||
WORD cp /* Code page for the conversion */
|
||||
)
|
||||
{
|
||||
@@ -15253,15 +15232,16 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
|
||||
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
|
||||
|
||||
|
||||
if (uni < 0x80) { /* ASCII char */
|
||||
c = uni;
|
||||
if (uni < 0x80) { /* ASCII? */
|
||||
c = (WCHAR)uni;
|
||||
|
||||
} else { /* Non-ASCII char */
|
||||
if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
|
||||
} 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;
|
||||
}
|
||||
|
||||
@@ -15274,7 +15254,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
||||
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
|
||||
|
||||
|
||||
if (oem < 0x80) { /* ASCII char */
|
||||
if (oem < 0x80) { /* ASCII? */
|
||||
c = oem;
|
||||
|
||||
} else { /* Extended char */
|
||||
@@ -15282,6 +15262,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
||||
if (oem < 0x100) c = p[oem - 0x80];
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -15294,29 +15275,30 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
||||
/* DBCS fixed code page */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#if FF_CODE_PAGE != 0 && FF_CODE_PAGE >= 900
|
||||
#if FF_CODE_PAGE >= 900
|
||||
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
|
||||
WCHAR uni, /* Unicode character to be converted */
|
||||
DWORD uni, /* UTF-16 encoded character to be converted */
|
||||
WORD cp /* Code page for the conversion */
|
||||
)
|
||||
{
|
||||
const WCHAR *p;
|
||||
WCHAR c = 0;
|
||||
UINT i, n, li, hi;
|
||||
WCHAR c = 0, uc;
|
||||
UINT i = 0, n, li, hi;
|
||||
|
||||
|
||||
if (uni < 0x80) { /* ASCII char */
|
||||
c = uni;
|
||||
if (uni < 0x80) { /* ASCII? */
|
||||
c = (WCHAR)uni;
|
||||
|
||||
} else { /* Non-ASCII char */
|
||||
if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
|
||||
} 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 (uni == p[i * 2]) break;
|
||||
if (uni > p[i * 2]) {
|
||||
if (uc == p[i * 2]) break;
|
||||
if (uc > p[i * 2]) {
|
||||
li = i;
|
||||
} else {
|
||||
hi = i;
|
||||
@@ -15325,6 +15307,7 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
|
||||
if (n != 0) c = p[i * 2 + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -15336,14 +15319,14 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
||||
{
|
||||
const WCHAR *p;
|
||||
WCHAR c = 0;
|
||||
UINT i, n, li, hi;
|
||||
UINT i = 0, n, li, hi;
|
||||
|
||||
|
||||
if (oem < 0x80) { /* ASCII char */
|
||||
if (oem < 0x80) { /* ASCII? */
|
||||
c = oem;
|
||||
|
||||
} else { /* Extended char */
|
||||
if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
|
||||
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;
|
||||
@@ -15359,6 +15342,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
||||
if (n != 0) c = p[i * 2 + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
@@ -15372,59 +15356,63 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
||||
#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};
|
||||
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 */
|
||||
WCHAR uni, /* Unicode character to be converted */
|
||||
DWORD uni, /* UTF-16 encoded character to be converted */
|
||||
WORD cp /* Code page for the conversion */
|
||||
)
|
||||
{
|
||||
const WCHAR *p;
|
||||
WCHAR c = 0;
|
||||
WCHAR c = 0, uc;
|
||||
UINT i, n, li, hi;
|
||||
|
||||
|
||||
if (uni < 0x80) { /* ASCII char */
|
||||
c = uni;
|
||||
if (uni < 0x80) { /* ASCII? */
|
||||
c = (WCHAR)uni;
|
||||
|
||||
} else { /* Non-ASCII 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 ? */
|
||||
for (c = 0; c < 0x80 && uni != p[c]; c++) ; /* Find OEM code in the table */
|
||||
c = (c + 0x80) & 0xFF;
|
||||
}
|
||||
} else { /* DBCS */
|
||||
switch (cp) {
|
||||
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 a valid code page? */
|
||||
li = 0;
|
||||
for (n = 16; n; n--) { /* Find OEM code */
|
||||
i = li + (hi - li) / 2;
|
||||
if (uni == p[i * 2]) break;
|
||||
if (uni > p[i * 2]) {
|
||||
li = i;
|
||||
} else {
|
||||
hi = i;
|
||||
}
|
||||
} 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];
|
||||
}
|
||||
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 */
|
||||
WCHAR oem, /* OEM code to be converted (DBC if >=0x100) */
|
||||
WORD cp /* Code page for the conversion */
|
||||
)
|
||||
{
|
||||
@@ -15433,7 +15421,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
||||
UINT i, n, li, hi;
|
||||
|
||||
|
||||
if (oem < 0x80) { /* ASCII char */
|
||||
if (oem < 0x80) { /* ASCII? */
|
||||
c = oem;
|
||||
|
||||
} else { /* Extended char */
|
||||
@@ -15466,6 +15454,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
@@ -15476,54 +15465,94 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
||||
/* Unicode up-case conversion */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
WCHAR ff_wtoupper ( /* Returns up-converted character */
|
||||
WCHAR uni /* Unicode character to be upper converted (BMP only) */
|
||||
DWORD ff_wtoupper ( /* Returns up-converted code point */
|
||||
DWORD uni /* Unicode code point to be up-converted */
|
||||
)
|
||||
{
|
||||
/* Compressed upper conversion table */
|
||||
static const WCHAR cvt1[] = { /* U+0000 - U+0FFF */
|
||||
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,
|
||||
0x00E0,0x0317,
|
||||
0x00F8,0x0307,
|
||||
0x00FF,0x0001,0x0178,
|
||||
/* Latin Extended-A */
|
||||
0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
0x0430,0x0320,
|
||||
0x0450,0x0710,
|
||||
0x0460,0x0122,
|
||||
0x048A,0x0136,
|
||||
0x04C1,0x010E,
|
||||
0x04CF,0x0001,0x04C0,
|
||||
0x04D0,0x0144,
|
||||
/* Armenian */
|
||||
0x0561,0x0426,
|
||||
|
||||
0x0000
|
||||
0x0000 /* EOT */
|
||||
};
|
||||
static const WCHAR cvt2[] = { /* U+1000 - U+FFFF */
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
0x2170,0x0210,
|
||||
0x2184,0x0001,0x2183,
|
||||
/* Enclosed Alphanumerics */
|
||||
0x24D0,0x051A, 0x2C30,0x042F,
|
||||
0x24D0,0x051A,
|
||||
0x2C30,0x042F,
|
||||
/* Latin Extended-C */
|
||||
0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102,
|
||||
0x2C60,0x0102,
|
||||
0x2C67,0x0106, 0x2C75,0x0102,
|
||||
/* Coptic */
|
||||
0x2C80,0x0164,
|
||||
/* Georgian Supplement */
|
||||
@@ -15531,36 +15560,38 @@ WCHAR ff_wtoupper ( /* Returns up-converted character */
|
||||
/* Full-width */
|
||||
0xFF41,0x031A,
|
||||
|
||||
0x0000
|
||||
0x0000 /* EOT */
|
||||
};
|
||||
const WCHAR *p;
|
||||
WCHAR bc, nc, cmd;
|
||||
|
||||
|
||||
p = uni < 0x1000 ? cvt1 : cvt2;
|
||||
for (;;) {
|
||||
bc = *p++; /* Get block base */
|
||||
if (!bc || uni < bc) break;
|
||||
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
|
||||
if (uni < bc + nc) { /* In the block? */
|
||||
switch (cmd) {
|
||||
case 0: uni = p[uni - bc]; break; /* Table conversion */
|
||||
case 1: uni -= (uni - bc) & 1; break; /* Case pairs */
|
||||
case 2: uni -= 16; break; /* Shift -16 */
|
||||
case 3: uni -= 32; break; /* Shift -32 */
|
||||
case 4: uni -= 48; break; /* Shift -48 */
|
||||
case 5: uni -= 26; break; /* Shift -26 */
|
||||
case 6: uni += 8; break; /* Shift +8 */
|
||||
case 7: uni -= 80; break; /* Shift -80 */
|
||||
case 8: uni -= 0x1C60; break; /* Shift -0x1C60 */
|
||||
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;
|
||||
}
|
||||
break;
|
||||
if (cmd == 0) p += nc; /* Skip table if needed */
|
||||
}
|
||||
if (!cmd) p += nc;
|
||||
uni = uc;
|
||||
}
|
||||
|
||||
return uni;
|
||||
}
|
||||
|
||||
|
||||
#endif /* #if _USE_LFN */
|
||||
#endif /* #if FF_USE_LFN */
|
||||
@@ -476,7 +476,7 @@ u32 sdmmc_sdcard_init()
|
||||
{
|
||||
u32 ret = 0;
|
||||
InitSD();
|
||||
if(Nand_Init() != 0) ret &= 1;
|
||||
if(SD_Init() != 0) ret &= 2;
|
||||
if(Nand_Init() != 0) ret |= 1;
|
||||
if(SD_Init() != 0) ret |= 2;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -31,13 +31,12 @@
|
||||
#include "exceptions.h"
|
||||
#include "patches.h"
|
||||
#include "memory.h"
|
||||
#include "strings.h"
|
||||
#include "cache.h"
|
||||
#include "emunand.h"
|
||||
#include "crypto.h"
|
||||
#include "screen.h"
|
||||
#include "fmt.h"
|
||||
#include "../build/bundled.h"
|
||||
#include "chainloader.h"
|
||||
|
||||
static Firm *firm = (Firm *)0x20001000;
|
||||
|
||||
@@ -59,7 +58,7 @@ static __attribute__((noinline)) bool inRange(u32 as, u32 ae, u32 bs, u32 be)
|
||||
|
||||
static bool checkFirm(u32 firmSize)
|
||||
{
|
||||
if(memcmp(firm->magic, "FIRM", 4) != 0 || firm->arm9Entry == NULL) //Allow for the ARM11 entrypoint to be zero in which case nothing is done on the ARM11 side
|
||||
if(memcmp(firm->magic, "FIRM", 4) != 0 || firm->arm9Entry == NULL) //Allow for the Arm11 entrypoint to be zero in which case nothing is done on the Arm11 side
|
||||
return false;
|
||||
|
||||
bool arm9EpFound = false,
|
||||
@@ -185,7 +184,7 @@ u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadF
|
||||
else if(ctrNandError) error("Unable to mount CTRNAND or load the CTRNAND FIRM.\nPlease use an external one.");
|
||||
}
|
||||
|
||||
//Check that the FIRM is right for the console from the ARM9 section address
|
||||
//Check that the FIRM is right for the console from the Arm9 section address
|
||||
if((firm->section[3].offset != 0 ? firm->section[3].address : firm->section[2].address) != (ISN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800))
|
||||
error("The %s FIRM is not for this console.", loadedFromStorage ? "external" : "CTRNAND");
|
||||
|
||||
@@ -279,10 +278,11 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo
|
||||
srcModuleSize = moduleList[nbModules].size = ((Cxi *)src)->ncch.contentSize * 0x200;
|
||||
}
|
||||
|
||||
if(firmType == NATIVE_FIRM && (ISN3DS || firmVersion >= 0x1D))
|
||||
// SAFE_FIRM only for N3DS and only if ENABLESAFEFIRMROSALINA is on
|
||||
if((firmType == NATIVE_FIRM || firmType == SAFE_FIRM) && (ISN3DS || firmVersion >= 0x1D))
|
||||
{
|
||||
//2) Merge that info with our own modules'
|
||||
for(u8 *src = (u8 *)0x18180000; src < (u8 *)(0x18180000 + LUMA_SECTION0_SIZE); src += srcModuleSize)
|
||||
for(u8 *src = (u8 *)0x18180000; memcmp(((Cxi *)src)->ncch.magic, "NCCH", 4) == 0; src += srcModuleSize)
|
||||
{
|
||||
const char *name = ((Cxi *)src)->exHeader.systemControlInfo.appTitle;
|
||||
|
||||
@@ -304,7 +304,9 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo
|
||||
//3) Read or copy the modules
|
||||
u8 *dst = firm->section[0].address;
|
||||
const char *extModuleSizeError = "The external FIRM modules are too large.";
|
||||
for(u32 i = 0, dstModuleSize, maxModuleSize = firmType == NATIVE_FIRM ? 0x80000 : 0x600000; i < nbModules; i++, dst += dstModuleSize, maxModuleSize -= dstModuleSize)
|
||||
// SAFE_FIRM only for N3DS and only if ENABLESAFEFIRMROSALINA is on
|
||||
u32 maxModuleSize = (firmType == NATIVE_FIRM || firmType == SAFE_FIRM) ? 0x80000 : 0x600000;
|
||||
for(u32 i = 0, dstModuleSize; i < nbModules; i++, dst += dstModuleSize, maxModuleSize -= dstModuleSize)
|
||||
{
|
||||
if(loadFromStorage)
|
||||
{
|
||||
@@ -336,7 +338,7 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo
|
||||
memcpy(dst, moduleList[i].src, dstModuleSize);
|
||||
}
|
||||
|
||||
//4) Patch NATIVE_FIRM if necessary
|
||||
//4) Patch NATIVE_FIRM/SAFE_FIRM (N3DS) if necessary
|
||||
if(nbModules == 6)
|
||||
{
|
||||
if(patchK11ModuleLoading(firm->section[0].size, dst - firm->section[0].address, (u8 *)firm + firm->section[1].offset, firm->section[1].size) != 0)
|
||||
@@ -344,14 +346,14 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo
|
||||
}
|
||||
}
|
||||
|
||||
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isFirmProtEnabled, bool isSafeMode, bool doUnitinfoPatch)
|
||||
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isFirmProtEnabled, bool needToInitSd, bool doUnitinfoPatch)
|
||||
{
|
||||
u8 *arm9Section = (u8 *)firm + firm->section[2].offset,
|
||||
*arm11Section1 = (u8 *)firm + firm->section[1].offset;
|
||||
|
||||
if(ISN3DS)
|
||||
{
|
||||
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
|
||||
//Decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader
|
||||
kernel9Loader((Arm9Bin *)arm9Section);
|
||||
firm->arm9Entry = (u8 *)0x801B01C;
|
||||
}
|
||||
@@ -374,7 +376,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
|
||||
//Skip on FIRMs < 4.0
|
||||
if(ISN3DS || firmVersion >= 0x1D)
|
||||
{
|
||||
ret += installK11Extension(arm11Section1, firm->section[1].size, isSafeMode, baseK11VA, arm11ExceptionsPage, &freeK11Space);
|
||||
ret += installK11Extension(arm11Section1, firm->section[1].size, needToInitSd, baseK11VA, arm11ExceptionsPage, &freeK11Space);
|
||||
ret += patchKernel11(arm11Section1, firm->section[1].size, baseK11VA, arm11SvcTable, arm11ExceptionsPage);
|
||||
}
|
||||
|
||||
@@ -400,6 +402,9 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
|
||||
//Apply anti-anti-DG patches on 11.0+
|
||||
if(firmVersion >= (ISN3DS ? 0x21 : 0x52)) ret += patchTitleInstallMinVersionChecks(process9Offset, process9Size, firmVersion);
|
||||
|
||||
//Patch P9 AM ticket wrapper on 11.8+ to use 0 Key and IV, only with UNITINFO patch on to prevent NIM from actually sending any
|
||||
if(doUnitinfoPatch && firmVersion >= (ISN3DS ? 0x35 : 0x64)) ret += patchP9AMTicketWrapperZeroKeyIV(process9Offset, process9Size, firmVersion);
|
||||
|
||||
//Apply UNITINFO patches
|
||||
if(doUnitinfoPatch)
|
||||
{
|
||||
@@ -407,7 +412,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
|
||||
if(!ISDEVUNIT) ret += patchCheckForDevCommonKey(process9Offset, process9Size);
|
||||
}
|
||||
|
||||
//ARM9 exception handlers
|
||||
//Arm9 exception handlers
|
||||
ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size);
|
||||
ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address);
|
||||
ret += patchKernel9Panic(arm9Section, kernel9Size);
|
||||
@@ -424,7 +429,7 @@ u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch)
|
||||
{
|
||||
u8 *arm9Section = (u8 *)firm + firm->section[3].offset;
|
||||
|
||||
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
|
||||
//On N3DS, decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader
|
||||
if(ISN3DS)
|
||||
{
|
||||
kernel9Loader((Arm9Bin *)arm9Section);
|
||||
@@ -463,7 +468,7 @@ u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch)
|
||||
{
|
||||
u8 *arm9Section = (u8 *)firm + firm->section[3].offset;
|
||||
|
||||
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
|
||||
//On N3DS, decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader
|
||||
if(ISN3DS)
|
||||
{
|
||||
kernel9Loader((Arm9Bin *)arm9Section);
|
||||
@@ -499,7 +504,7 @@ u32 patch1x2xNativeAndSafeFirm(void)
|
||||
|
||||
if(ISN3DS)
|
||||
{
|
||||
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
|
||||
//Decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader
|
||||
kernel9Loader((Arm9Bin *)arm9Section);
|
||||
firm->arm9Entry = (u8 *)0x801B01C;
|
||||
}
|
||||
@@ -516,21 +521,41 @@ u32 patch1x2xNativeAndSafeFirm(void)
|
||||
|
||||
ret += ISN3DS ? patchSignatureChecks(process9Offset, process9Size) : patchOldSignatureChecks(process9Offset, process9Size);
|
||||
|
||||
//ARM9 exception handlers
|
||||
//Arm9 exception handlers
|
||||
ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size);
|
||||
ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address);
|
||||
|
||||
if(ISN3DS && CONFIG(ENABLESAFEFIRMROSALINA))
|
||||
{
|
||||
u8 *arm11Section1 = (u8 *)firm + firm->section[1].offset;
|
||||
//Find the Kernel11 SVC table and handler, exceptions page and free space locations
|
||||
u32 baseK11VA;
|
||||
u8 *freeK11Space;
|
||||
u32 *arm11SvcHandler,
|
||||
*arm11ExceptionsPage,
|
||||
*arm11SvcTable = getKernel11Info(arm11Section1, firm->section[1].size, &baseK11VA, &freeK11Space, &arm11SvcHandler, &arm11ExceptionsPage);
|
||||
|
||||
ret += installK11Extension(arm11Section1, firm->section[1].size, false, baseK11VA, arm11ExceptionsPage, &freeK11Space);
|
||||
ret += patchKernel11(arm11Section1, firm->section[1].size, baseK11VA, arm11SvcTable, arm11ExceptionsPage);
|
||||
|
||||
// Add some other patches to the mix, as we can now launch homebrew on SAFE_FIRM:
|
||||
|
||||
//Apply firmlaunch patches
|
||||
//Or don't, this makes usm not work
|
||||
//ret += patchFirmlaunches(process9Offset, process9Size, process9MemAddr);
|
||||
|
||||
ret += patchKernel9Panic(arm9Section, kernel9Size);
|
||||
ret += patchP9AccessChecks(process9Offset, process9Size);
|
||||
|
||||
mergeSection0(NATIVE_FIRM, 0x45, false); // may change in the future
|
||||
firm->section[0].size = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void launchFirm(int argc, char **argv)
|
||||
{
|
||||
u32 *chainloaderAddress = (u32 *)0x01FF9000;
|
||||
|
||||
prepareArm11ForFirmlaunch();
|
||||
|
||||
memcpy(chainloaderAddress, chainloader_bin, chainloader_bin_size);
|
||||
|
||||
// No need to flush caches here, the chainloader is in ITCM
|
||||
((void (*)(int, char **, Firm *))chainloaderAddress)(argc, argv, firm);
|
||||
chainload(argc, argv, firm);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode);
|
||||
void loadHomebrewFirm(u32 pressed);
|
||||
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isFirmProtEnabled, bool isSafeMode, bool doUnitinfoPatch);
|
||||
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isFirmProtEnabled, bool needToInitSd, bool doUnitinfoPatch);
|
||||
u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch);
|
||||
u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch);
|
||||
u32 patch1x2xNativeAndSafeFirm(void);
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -59,7 +59,7 @@ This code is based on a file that contains the following:
|
||||
|
||||
//TuxSH's changes: add support for 64-bit numbers, remove floating-point code
|
||||
|
||||
#include "strings.h"
|
||||
#include "memory.h"
|
||||
#include "fmt.h"
|
||||
|
||||
#define ZEROPAD (1<<0) //Pad with zero
|
||||
@@ -148,7 +148,7 @@ static char *processNumber(char *str, s64 num, bool isHex, s32 size, s32 precisi
|
||||
return str;
|
||||
}
|
||||
|
||||
u32 vsprintf(char *buf, const char *fmt, va_list args)
|
||||
int vsprintf(char *buf, const char *fmt, va_list args)
|
||||
{
|
||||
char *str;
|
||||
|
||||
@@ -218,7 +218,7 @@ u32 vsprintf(char *buf, const char *fmt, va_list args)
|
||||
fmt++;
|
||||
integerType = 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if(*fmt == 'h')
|
||||
{
|
||||
@@ -306,14 +306,14 @@ u32 vsprintf(char *buf, const char *fmt, va_list args)
|
||||
}
|
||||
|
||||
*str = 0;
|
||||
return str - buf;
|
||||
return (int)(str - buf);
|
||||
}
|
||||
|
||||
u32 sprintf(char *buf, const char *fmt, ...)
|
||||
int sprintf(char *buf, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
u32 res = vsprintf(buf, fmt, args);
|
||||
int res = vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
return res;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -28,5 +28,5 @@
|
||||
#include "memory.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
u32 vsprintf(char *buf, const char *fmt, va_list args);
|
||||
u32 sprintf(char *buf, const char *fmt, ...);
|
||||
int vsprintf(char *buf, const char *fmt, va_list args);
|
||||
int sprintf(char *buf, const char *fmt, ...);
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
#include "fs.h"
|
||||
#include "memory.h"
|
||||
#include "strings.h"
|
||||
#include "fmt.h"
|
||||
#include "crypto.h"
|
||||
#include "cache.h"
|
||||
@@ -37,7 +36,7 @@
|
||||
#include "buttons.h"
|
||||
#include "firm.h"
|
||||
#include "crypto.h"
|
||||
#include "../build/bundled.h"
|
||||
#include "strings.h"
|
||||
|
||||
static FATFS sdFs,
|
||||
nandFs;
|
||||
@@ -88,7 +87,7 @@ u32 getFileSize(const char *path)
|
||||
bool fileWrite(const void *buffer, const char *path, u32 size)
|
||||
{
|
||||
FIL file;
|
||||
FRESULT result;
|
||||
FRESULT result = FR_OK;
|
||||
|
||||
switch(f_open(&file, path, FA_WRITE | FA_OPEN_ALWAYS))
|
||||
{
|
||||
@@ -283,7 +282,7 @@ u32 firmRead(void *dest, u32 firmType)
|
||||
if(f_closedir(&dir) != FR_OK || firmVersion == 0xFFFFFFFF) goto exit;
|
||||
|
||||
//Complete the string with the .app name
|
||||
sprintf(path, "%s/%08x.app", folderPath, firmVersion);
|
||||
sprintf(path, "%s/%08lx.app", folderPath, firmVersion);
|
||||
|
||||
if(fileRead(dest, path, 0x400000 + sizeof(Cxi) + 0x200) <= sizeof(Cxi) + 0x400) firmVersion = 0xFFFFFFFF;
|
||||
|
||||
@@ -300,7 +299,7 @@ void findDumpFile(const char *folderPath, char *fileName)
|
||||
{
|
||||
FILINFO info;
|
||||
|
||||
sprintf(fileName, "crash_dump_%08u.dmp", n);
|
||||
sprintf(fileName, "crash_dump_%08lu.dmp", n);
|
||||
result = f_findfirst(&dir, &info, folderPath, fileName);
|
||||
|
||||
if(result != FR_OK || !info.fname[0]) break;
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
225
arm9/source/i2c.c
Normal file
225
arm9/source/i2c.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "types.h"
|
||||
#include "i2c.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define I2C1_REGS_BASE (0x10161000)
|
||||
|
||||
#define I2C2_REGS_BASE (0x10144000)
|
||||
|
||||
#define I2C3_REGS_BASE (0x10148000)
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vu8 REG_I2C_DATA;
|
||||
vu8 REG_I2C_CNT;
|
||||
vu16 REG_I2C_CNTEX;
|
||||
vu16 REG_I2C_SCL;
|
||||
} I2cRegs;
|
||||
|
||||
static const struct
|
||||
{
|
||||
u8 busId;
|
||||
u8 devAddr;
|
||||
} i2cDevTable[] =
|
||||
{
|
||||
{0, 0x4A},
|
||||
{0, 0x7A},
|
||||
{0, 0x78},
|
||||
{1, 0x4A},
|
||||
{1, 0x78},
|
||||
{1, 0x2C},
|
||||
{1, 0x2E},
|
||||
{1, 0x40},
|
||||
{1, 0x44},
|
||||
{2, 0xA6}, // TODO: Find out if 0xA6 or 0xD6 is correct
|
||||
{2, 0xD0},
|
||||
{2, 0xD2},
|
||||
{2, 0xA4},
|
||||
{2, 0x9A},
|
||||
{2, 0xA0},
|
||||
{1, 0xEE},
|
||||
{0, 0x40},
|
||||
{2, 0x54}
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void i2cWaitBusy(I2cRegs *const regs)
|
||||
{
|
||||
while(regs->REG_I2C_CNT & I2C_ENABLE);
|
||||
}
|
||||
|
||||
static I2cRegs* i2cGetBusRegsBase(u8 busId)
|
||||
{
|
||||
I2cRegs *base;
|
||||
switch(busId)
|
||||
{
|
||||
case 0:
|
||||
base = (I2cRegs*)I2C1_REGS_BASE;
|
||||
break;
|
||||
case 1:
|
||||
base = (I2cRegs*)I2C2_REGS_BASE;
|
||||
break;
|
||||
case 2:
|
||||
base = (I2cRegs*)I2C3_REGS_BASE;
|
||||
break;
|
||||
default:
|
||||
base = NULL;
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
void I2C_init(void)
|
||||
{
|
||||
I2cRegs *regs = i2cGetBusRegsBase(0); // Bus 1
|
||||
i2cWaitBusy(regs);
|
||||
regs->REG_I2C_CNTEX = 2; // ?
|
||||
regs->REG_I2C_SCL = 1280; // ?
|
||||
|
||||
regs = i2cGetBusRegsBase(1); // Bus 2
|
||||
i2cWaitBusy(regs);
|
||||
regs->REG_I2C_CNTEX = 2; // ?
|
||||
regs->REG_I2C_SCL = 1280; // ?
|
||||
|
||||
regs = i2cGetBusRegsBase(2); // Bus 3
|
||||
i2cWaitBusy(regs);
|
||||
regs->REG_I2C_CNTEX = 2; // ?
|
||||
regs->REG_I2C_SCL = 1280; // ?
|
||||
}
|
||||
|
||||
static bool i2cStartTransfer(I2cDevice devId, u8 regAddr, bool read, I2cRegs *const regs)
|
||||
{
|
||||
const u8 devAddr = i2cDevTable[devId].devAddr;
|
||||
|
||||
|
||||
u32 i = 0;
|
||||
for(; i < 8; i++)
|
||||
{
|
||||
i2cWaitBusy(regs);
|
||||
|
||||
// Select device and start.
|
||||
regs->REG_I2C_DATA = devAddr;
|
||||
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_START;
|
||||
i2cWaitBusy(regs);
|
||||
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||
{
|
||||
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Select register and change direction to write.
|
||||
regs->REG_I2C_DATA = regAddr;
|
||||
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE;
|
||||
i2cWaitBusy(regs);
|
||||
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||
{
|
||||
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Select device in read mode for read transfer.
|
||||
if(read)
|
||||
{
|
||||
regs->REG_I2C_DATA = devAddr | 1u; // Set bit 0 for read.
|
||||
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_START;
|
||||
i2cWaitBusy(regs);
|
||||
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||
{
|
||||
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(i < 8) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
|
||||
{
|
||||
const u8 busId = i2cDevTable[devId].busId;
|
||||
I2cRegs *const regs = i2cGetBusRegsBase(busId);
|
||||
|
||||
|
||||
if(!i2cStartTransfer(devId, regAddr, true, regs)) return false;
|
||||
|
||||
while(--size)
|
||||
{
|
||||
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_ACK;
|
||||
i2cWaitBusy(regs);
|
||||
*out++ = regs->REG_I2C_DATA;
|
||||
}
|
||||
|
||||
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_STOP;
|
||||
i2cWaitBusy(regs);
|
||||
*out = regs->REG_I2C_DATA; // Last byte
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size)
|
||||
{
|
||||
const u8 busId = i2cDevTable[devId].busId;
|
||||
I2cRegs *const regs = i2cGetBusRegsBase(busId);
|
||||
|
||||
|
||||
if(!i2cStartTransfer(devId, regAddr, false, regs)) return false;
|
||||
|
||||
while(--size)
|
||||
{
|
||||
regs->REG_I2C_DATA = *in++;
|
||||
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE;
|
||||
i2cWaitBusy(regs);
|
||||
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||
{
|
||||
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
regs->REG_I2C_DATA = *in;
|
||||
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE | I2C_STOP;
|
||||
i2cWaitBusy(regs);
|
||||
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||
{
|
||||
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
u8 I2C_readReg(I2cDevice devId, u8 regAddr)
|
||||
{
|
||||
u8 data;
|
||||
if(!I2C_readRegBuf(devId, regAddr, &data, 1)) return 0xFF;
|
||||
return data;
|
||||
}
|
||||
|
||||
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data)
|
||||
{
|
||||
return I2C_writeRegBuf(devId, regAddr, &data, 1);
|
||||
}
|
||||
102
arm9/source/i2c.h
Normal file
102
arm9/source/i2c.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define I2C_STOP (1u)
|
||||
#define I2C_START (1u<<1)
|
||||
#define I2C_ERROR (1u<<2)
|
||||
#define I2C_ACK (1u<<4)
|
||||
#define I2C_DIRE_WRITE (0u)
|
||||
#define I2C_DIRE_READ (1u<<5)
|
||||
#define I2C_IRQ_ENABLE (1u<<6)
|
||||
#define I2C_ENABLE (1u<<7)
|
||||
|
||||
#define I2C_GET_ACK(reg) ((bool)((reg)>>4 & 1u))
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
I2C_DEV_POWER = 0, // Unconfirmed
|
||||
I2C_DEV_CAMERA = 1, // Unconfirmed
|
||||
I2C_DEV_CAMERA2 = 2, // Unconfirmed
|
||||
I2C_DEV_MCU = 3,
|
||||
I2C_DEV_GYRO = 10,
|
||||
I2C_DEV_DEBUG_PAD = 12,
|
||||
I2C_DEV_IR = 13,
|
||||
I2C_DEV_EEPROM = 14, // Unconfirmed
|
||||
I2C_DEV_NFC = 15,
|
||||
I2C_DEV_QTM = 16,
|
||||
I2C_DEV_N3DS_HID = 17
|
||||
} I2cDevice;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the I2C buses. Call this only once.
|
||||
*/
|
||||
void I2C_init(void);
|
||||
|
||||
/**
|
||||
* @brief Reads data from a I2C register to a buffer.
|
||||
*
|
||||
* @param[in] devId The device ID. Use the enum above.
|
||||
* @param[in] regAddr The register address.
|
||||
* @param out The output buffer pointer.
|
||||
* @param[in] size The read size.
|
||||
*
|
||||
* @return Returns true on success and false on failure.
|
||||
*/
|
||||
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size);
|
||||
|
||||
/**
|
||||
* @brief Writes a buffer to a I2C register.
|
||||
*
|
||||
* @param[in] devId The device ID. Use the enum above.
|
||||
* @param[in] regAddr The register address.
|
||||
* @param[in] in The input buffer pointer.
|
||||
* @param[in] size The write size.
|
||||
*
|
||||
* @return Returns true on success and false on failure.
|
||||
*/
|
||||
bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size);
|
||||
|
||||
/**
|
||||
* @brief Reads a byte from a I2C register.
|
||||
*
|
||||
* @param[in] devId The device ID. Use the enum above.
|
||||
* @param[in] regAddr The register address.
|
||||
*
|
||||
* @return Returns the value read on success otherwise 0xFF.
|
||||
*/
|
||||
u8 I2C_readReg(I2cDevice devId, u8 regAddr);
|
||||
|
||||
/**
|
||||
* @brief Writes a byte to a I2C register.
|
||||
*
|
||||
* @param[in] devId The device ID. Use the enum above.
|
||||
* @param[in] regAddr The register address.
|
||||
* @param[in] data The data to write.
|
||||
*
|
||||
* @return Returns true on success and false on failure.
|
||||
*/
|
||||
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data);
|
||||
38
arm9/source/large_patches.h
Normal file
38
arm9/source/large_patches.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
* * Requiring preservation of specified reasonable legal notices or
|
||||
* author attributions in that material or in the Appropriate Legal
|
||||
* Notices displayed by works containing it.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
extern const u8 emunandPatch[];
|
||||
extern const u32 emunandPatchSize;
|
||||
extern u32 emunandPatchSdmmcStructPtr, emunandPatchNandOffset, emunandPatchNcsdHeaderOffset;
|
||||
|
||||
extern const u8 rebootPatch[];
|
||||
extern const u32 rebootPatchSize;
|
||||
extern u32 rebootPatchFopenPtr;
|
||||
extern u16 rebootPatchFileName[80+1];
|
||||
291
arm9/source/large_patches.s
Normal file
291
arm9/source/large_patches.s
Normal file
@@ -0,0 +1,291 @@
|
||||
.section .large_patch.emunand, "aw", %progbits
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
@ Code originally by Normmatt
|
||||
|
||||
.global emunandPatch
|
||||
emunandPatch:
|
||||
@ Original code that still needs to be executed
|
||||
mov r4, r0
|
||||
mov r5, r1
|
||||
mov r7, r2
|
||||
mov r6, r3
|
||||
@ End
|
||||
|
||||
@ If we're already trying to access the SD, return
|
||||
ldr r2, [r0, #4]
|
||||
ldr r1, emunandPatchSdmmcStructPtr
|
||||
cmp r2, r1
|
||||
beq out
|
||||
|
||||
str r1, [r0, #4] @ Set object to be SD
|
||||
ldr r2, [r0, #8] @ Get sector to read
|
||||
cmp r2, #0 @ For GW compatibility, see if we're trying to read the ncsd header (sector 0)
|
||||
|
||||
ldr r3, emunandPatchNandOffset
|
||||
add r2, r3 @ Add the offset to the NAND in the SD
|
||||
|
||||
ldreq r3, emunandPatchNcsdHeaderOffset
|
||||
addeq r2, r3 @ If we're reading the ncsd header, add the offset of that sector
|
||||
|
||||
str r2, [r0, #8] @ Store sector to read
|
||||
|
||||
out:
|
||||
@ Restore registers.
|
||||
mov r1, r5
|
||||
mov r2, r7
|
||||
mov r3, r6
|
||||
|
||||
@ Return 4 bytes behind where we got called,
|
||||
@ due to the offset of this function being stored there
|
||||
mov r0, lr
|
||||
add r0, #4
|
||||
bx r0
|
||||
|
||||
.pool
|
||||
|
||||
.global emunandPatchSdmmcStructPtr
|
||||
.global emunandPatchNandOffset
|
||||
.global emunandPatchNcsdHeaderOffset
|
||||
|
||||
emunandPatchSdmmcStructPtr: .word 0 @ Pointer to sdmmc struct
|
||||
emunandPatchNandOffset: .word 0 @ For rednand this should be 1
|
||||
emunandPatchNcsdHeaderOffset: .word 0 @ Depends on nand manufacturer + emunand type (GW/RED)
|
||||
|
||||
.pool
|
||||
.balign 4
|
||||
|
||||
_emunandPatchEnd:
|
||||
|
||||
.global emunandPatchSize
|
||||
emunandPatchSize:
|
||||
.word _emunandPatchEnd - emunandPatch
|
||||
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
|
||||
@ Code originally from delebile and mid-kid
|
||||
|
||||
.section .large_patch.reboot, "aw", %progbits
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
#define copy_launch_stub_stack_top 0x01FFB800
|
||||
#define copy_launch_stub_stack_bottom 0x01FFA800
|
||||
#define copy_launch_stub_addr 0x01FF9000
|
||||
|
||||
#define argv_addr (copy_launch_stub_stack_bottom - 0x100)
|
||||
#define fname_addr (copy_launch_stub_stack_bottom - 0x200)
|
||||
#define low_tid_addr (copy_launch_stub_stack_bottom - 0x300)
|
||||
|
||||
#define firm_addr 0x20001000
|
||||
#define firm_maxsize 0x07FFF000
|
||||
|
||||
.global rebootPatch
|
||||
rebootPatch:
|
||||
@ Interesting registers and locations to keep in mind, set just before this code is ran:
|
||||
@ - r1: FIRM path in exefs.
|
||||
@ - r7 (or r8): pointer to file object
|
||||
@ - *r7: vtable
|
||||
@ - *(vtable + 0x28): fread function
|
||||
@ - *(r7 + 8): file handle
|
||||
|
||||
sub r7, r0, #8
|
||||
mov r8, r1
|
||||
|
||||
pxi_wait_recv:
|
||||
ldr r2, =0x44846
|
||||
ldr r0, =0x10008000
|
||||
readPxiLoop1:
|
||||
ldrh r1, [r0, #4]
|
||||
lsls r1, #0x17
|
||||
bmi readPxiLoop1
|
||||
ldr r0, [r0, #0xC]
|
||||
cmp r0, r2
|
||||
bne pxi_wait_recv
|
||||
|
||||
@ Open file
|
||||
add r0, r7, #8
|
||||
adr r1, rebootPatchFileName
|
||||
mov r2, #1
|
||||
adr r6, rebootPatchFopenPtr
|
||||
ldr r6, [r6]
|
||||
orr r6, #1
|
||||
blx r6
|
||||
cmp r0, #0
|
||||
bne panic
|
||||
|
||||
@ Read file
|
||||
mov r0, r7
|
||||
adr r1, bytes_read
|
||||
ldr r2, =firm_addr
|
||||
ldr r3, =firm_maxsize
|
||||
ldr r6, [r7]
|
||||
ldr r6, [r6, #0x28]
|
||||
blx r6
|
||||
|
||||
@ Copy the low TID (in UTF-16) of the wanted firm
|
||||
ldr r0, =low_tid_addr
|
||||
add r1, r8, #0x1A
|
||||
mov r2, #0x10
|
||||
bl memcpy16
|
||||
|
||||
@ Copy argv[0]
|
||||
ldr r0, =fname_addr
|
||||
adr r1, rebootPatchFileName
|
||||
mov r2, #82
|
||||
bl memcpy16
|
||||
|
||||
ldr r0, =argv_addr
|
||||
ldr r1, =fname_addr
|
||||
ldr r2, =low_tid_addr
|
||||
stmia r0, {r1, r2}
|
||||
|
||||
@ Set kernel state
|
||||
mov r0, #0
|
||||
mov r1, #0
|
||||
mov r2, #0
|
||||
mov r3, #0
|
||||
svc 0x7C
|
||||
|
||||
goto_reboot:
|
||||
@ Jump to reboot code
|
||||
ldr r0, kernel_func_displ
|
||||
add r0, pc @ pc is two instructions ahead of the instruction being executed (12 = 2*4 + 4)
|
||||
svc 0x7B
|
||||
|
||||
die:
|
||||
b die
|
||||
|
||||
memcpy16:
|
||||
cmp r2, #0
|
||||
bxeq lr
|
||||
add r2, r0, r2
|
||||
copy_loop16:
|
||||
ldrh r3, [r1], #2
|
||||
strh r3, [r0], #2
|
||||
cmp r0, r2
|
||||
blo copy_loop16
|
||||
bx lr
|
||||
|
||||
panic:
|
||||
mov r1, r0 @ unused register
|
||||
mov r0, #0
|
||||
svc 0x3C @ svcBreak(USERBREAK_PANIC)
|
||||
b die
|
||||
|
||||
kernel_func_displ:
|
||||
.word kernelcode_start - goto_reboot - 12
|
||||
|
||||
bytes_read:
|
||||
.word 0
|
||||
|
||||
.global rebootPatchFopenPtr
|
||||
rebootPatchFopenPtr:
|
||||
.word 0
|
||||
|
||||
.pool
|
||||
|
||||
.global rebootPatchFileName
|
||||
rebootPatchFileName:
|
||||
.skip 2*(80+1)
|
||||
|
||||
.balign 4
|
||||
kernelcode_start:
|
||||
|
||||
msr cpsr_cxsf, #0xD3 @ disable interrupts and clear flags
|
||||
|
||||
ldr sp, =copy_launch_stub_stack_top
|
||||
|
||||
ldr r0, =copy_launch_stub_addr
|
||||
adr r1, copy_launch_stub
|
||||
mov r2, #(copy_launch_stub_end - copy_launch_stub)
|
||||
bl memcpy32
|
||||
|
||||
@ Disable MPU
|
||||
ldr r0, =0x42078 @ alt vector select, enable itcm
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
bl flushCaches
|
||||
|
||||
ldr r0, =copy_launch_stub_addr
|
||||
bx r0
|
||||
|
||||
copy_launch_stub:
|
||||
|
||||
ldr r4, =firm_addr
|
||||
|
||||
mov r5, #0
|
||||
load_section_loop:
|
||||
@ Such checks. Very ghetto. Wow.
|
||||
add r3, r4, #0x40
|
||||
add r3, r5,lsl #5
|
||||
add r3, r5,lsl #4
|
||||
ldmia r3, {r6-r8}
|
||||
cmp r8, #0
|
||||
movne r0, r7
|
||||
addne r1, r4, r6
|
||||
movne r2, r8
|
||||
blne memcpy32
|
||||
add r5, #1
|
||||
cmp r5, #4
|
||||
blo load_section_loop
|
||||
|
||||
mov r0, #2 @ argc
|
||||
ldr r1, =argv_addr @ argv
|
||||
ldr r2, =0xBABE @ magic word
|
||||
|
||||
mov r5, #0x20000000
|
||||
ldr r6, [r4, #0x08]
|
||||
str r6, [r5, #-4] @ store arm11 entrypoint
|
||||
|
||||
ldr lr, [r4, #0x0c]
|
||||
bx lr
|
||||
|
||||
memcpy32:
|
||||
add r2, r0, r2
|
||||
copy_loop32:
|
||||
ldr r3, [r1], #4
|
||||
str r3, [r0], #4
|
||||
cmp r0, r2
|
||||
blo copy_loop32
|
||||
bx lr
|
||||
|
||||
.pool
|
||||
|
||||
copy_launch_stub_end:
|
||||
|
||||
flushCaches:
|
||||
|
||||
@ Clean and flush data cache
|
||||
mov r1, #0 @ segment counter
|
||||
outer_loop:
|
||||
mov r0, #0 @ line counter
|
||||
|
||||
inner_loop:
|
||||
orr r2, r1, r0 @ generate segment and line address
|
||||
mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line
|
||||
add r0, #0x20 @ increment to next line
|
||||
cmp r0, #0x400
|
||||
bne inner_loop
|
||||
|
||||
add r1, #0x40000000
|
||||
cmp r1, #0
|
||||
bne outer_loop
|
||||
|
||||
@ Drain write buffer
|
||||
mcr p15, 0, r1, c7, c10, 4
|
||||
|
||||
@ Flush instruction cache
|
||||
mcr p15, 0, r1, c7, c5, 0
|
||||
|
||||
bx lr
|
||||
|
||||
.pool
|
||||
.balign 4
|
||||
|
||||
_rebootPatchEnd:
|
||||
|
||||
.global rebootPatchSize
|
||||
rebootPatchSize:
|
||||
.word _rebootPatchEnd - rebootPatch
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -31,42 +31,47 @@
|
||||
#include "utils.h"
|
||||
#include "exceptions.h"
|
||||
#include "draw.h"
|
||||
#include "strings.h"
|
||||
#include "buttons.h"
|
||||
#include "pin.h"
|
||||
#include "crypto.h"
|
||||
#include "memory.h"
|
||||
#include "screen.h"
|
||||
#include "i2c.h"
|
||||
#include "fatfs/sdmmc/sdmmc.h"
|
||||
|
||||
extern u8 __itcm_start__[], __itcm_lma__[], __itcm_bss_start__[], __itcm_end__[];
|
||||
|
||||
extern CfgData configData;
|
||||
extern ConfigurationStatus needConfig;
|
||||
extern FirmwareSource firmSource;
|
||||
|
||||
bool isSdMode;
|
||||
u16 launchedPath[41];
|
||||
u16 launchedPath[80+1];
|
||||
BootType bootType;
|
||||
|
||||
void main(int argc, char **argv, u32 magicWord)
|
||||
{
|
||||
bool isFirmProtEnabled,
|
||||
isSafeMode = false,
|
||||
needToInitSd = false,
|
||||
isNoForceFlagSet = false,
|
||||
isInvalidLoader = false,
|
||||
isNtrBoot;
|
||||
FirmwareType firmType;
|
||||
FirmwareSource nandType;
|
||||
const vu8 *bootMediaStatus = (const vu8 *)0x1FFFE00C;
|
||||
const vu32 *bootPartitionsStatus = (const vu32 *)0x1FFFE010;
|
||||
u32 firmlaunchTidLow = 0;
|
||||
|
||||
//Shell closed, no error booting NTRCARD, NAND paritions not even considered
|
||||
isNtrBoot = bootMediaStatus[3] == 2 && !bootMediaStatus[1] && !bootPartitionsStatus[0] && !bootPartitionsStatus[1];
|
||||
|
||||
|
||||
if((magicWord & 0xFFFF) == 0xBEEF && argc >= 1) //Normal (B9S) boot
|
||||
{
|
||||
bootType = isNtrBoot ? B9SNTR : B9S;
|
||||
|
||||
u32 i;
|
||||
for(i = 0; i < 40 && argv[0][i] != 0; i++) //Copy and convert the path to UTF-16
|
||||
for(i = 0; i < sizeof(launchedPath)/2 - 1 && argv[0][i] != 0; i++) //Copy and convert the path to UTF-16
|
||||
launchedPath[i] = argv[0][i];
|
||||
launchedPath[i] = 0;
|
||||
}
|
||||
@@ -76,9 +81,12 @@ void main(int argc, char **argv, u32 magicWord)
|
||||
|
||||
u32 i;
|
||||
u16 *p = (u16 *)argv[0];
|
||||
for(i = 0; i < 40 && p[i] != 0; i++)
|
||||
for(i = 0; i < sizeof(launchedPath)/2 - 1 && p[i] != 0; i++)
|
||||
launchedPath[i] = p[i];
|
||||
launchedPath[i] = 0;
|
||||
|
||||
for(i = 0; i < 8; i++)
|
||||
firmlaunchTidLow = (argv[1][2 * i] > '9' ? argv[1][2 * i] - 'a' + 10 : argv[1][2 * i] - '0') | (firmlaunchTidLow << 4);
|
||||
}
|
||||
else if(magicWord == 0xB002) //FIRM/NTRCARD boot
|
||||
{
|
||||
@@ -103,7 +111,15 @@ void main(int argc, char **argv, u32 magicWord)
|
||||
|
||||
setupKeyslots();
|
||||
}
|
||||
else error("Launched using an unsupported loader.");
|
||||
else isInvalidLoader = true;
|
||||
|
||||
// Set up the additional sections, overwrites argc
|
||||
memcpy(__itcm_start__, __itcm_lma__, __itcm_bss_start__ - __itcm_start__);
|
||||
memset(__itcm_bss_start__, 0, __itcm_end__ - __itcm_bss_start__);
|
||||
I2C_init();
|
||||
if(isInvalidLoader) error("Launched using an unsupported loader.");
|
||||
|
||||
installArm9Handlers();
|
||||
|
||||
if(memcmp(launchedPath, u"sdmc", 8) == 0)
|
||||
{
|
||||
@@ -140,6 +156,8 @@ void main(int argc, char **argv, u32 magicWord)
|
||||
error("Launched from an unsupported location: %s.", mountPoint);
|
||||
}
|
||||
|
||||
detectAndProcessExceptionDumps();
|
||||
|
||||
//Attempt to read the configuration file
|
||||
needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
|
||||
|
||||
@@ -148,15 +166,15 @@ void main(int argc, char **argv, u32 magicWord)
|
||||
{
|
||||
if(needConfig == CREATE_CONFIGURATION) mcuPowerOff();
|
||||
|
||||
switch(argv[1][14])
|
||||
switch(firmlaunchTidLow & 0xF)
|
||||
{
|
||||
case '2':
|
||||
firmType = (FirmwareType)(argv[1][10] - '0');
|
||||
case 2:
|
||||
firmType = (FirmwareType)((firmlaunchTidLow >> 8) & 0xF);
|
||||
break;
|
||||
case '3':
|
||||
case 3:
|
||||
firmType = SAFE_FIRM;
|
||||
break;
|
||||
case '1':
|
||||
case 1:
|
||||
firmType = SYSUPDATER_FIRM;
|
||||
break;
|
||||
}
|
||||
@@ -168,9 +186,6 @@ void main(int argc, char **argv, u32 magicWord)
|
||||
goto boot;
|
||||
}
|
||||
|
||||
detectAndProcessExceptionDumps();
|
||||
installArm9Handlers();
|
||||
|
||||
firmType = NATIVE_FIRM;
|
||||
isFirmProtEnabled = bootType != NTR;
|
||||
|
||||
@@ -192,9 +207,16 @@ void main(int argc, char **argv, u32 magicWord)
|
||||
goto boot;
|
||||
}
|
||||
|
||||
/* Else, force the last used boot options unless a button is pressed
|
||||
//Account for DSiWare soft resets if exiting TWL_FIRM
|
||||
if(CFG_BOOTENV == 3)
|
||||
{
|
||||
static const u8 TLNC[] = {0x54, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x43};
|
||||
if(memcmp((void *)0x20000C00, TLNC, 10) == 0) needToInitSd = true;
|
||||
}
|
||||
|
||||
/* Force the last used boot options if autobooting a TWL title, or unless a button is pressed
|
||||
or the no-forcing flag is set */
|
||||
if(!pressed && !BOOTCFG_NOFORCEFLAG)
|
||||
if(needToInitSd || memcmp((void *)0x20000300, "TLNC", 4) == 0 || (!pressed && !BOOTCFG_NOFORCEFLAG))
|
||||
{
|
||||
nandType = (FirmwareSource)BOOTCFG_NAND;
|
||||
firmSource = (FirmwareSource)BOOTCFG_FIRM;
|
||||
@@ -204,11 +226,21 @@ void main(int argc, char **argv, u32 magicWord)
|
||||
}
|
||||
|
||||
u32 pinMode = MULTICONFIG(PIN);
|
||||
bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT);
|
||||
bool pinExists = pinMode != 0 && verifyPin(pinMode);
|
||||
|
||||
//If no configuration file exists or SELECT is held or if booted from NTRCARD, load configuration menu
|
||||
bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT);
|
||||
/* If the PIN has been verified, wait to make it easier to press the SAFE_MODE combo or the configuration menu button
|
||||
(if not already pressed, for the latter) */
|
||||
if(pinExists && !shouldLoadConfigMenu)
|
||||
{
|
||||
while(HID_PAD & PIN_BUTTONS);
|
||||
wait(2000ULL);
|
||||
|
||||
//Update pressed buttons
|
||||
pressed = HID_PAD;
|
||||
}
|
||||
|
||||
shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT);
|
||||
if(shouldLoadConfigMenu)
|
||||
{
|
||||
configMenu(pinExists, pinMode);
|
||||
@@ -223,13 +255,7 @@ void main(int argc, char **argv, u32 magicWord)
|
||||
firmSource = FIRMWARE_SYSNAND;
|
||||
|
||||
isSafeMode = true;
|
||||
|
||||
//If the PIN has been verified, wait to make it easier to press the SAFE_MODE combo
|
||||
if(pinExists && !shouldLoadConfigMenu)
|
||||
{
|
||||
while(HID_PAD & PIN_BUTTONS);
|
||||
wait(2000ULL);
|
||||
}
|
||||
needToInitSd = true;
|
||||
|
||||
goto boot;
|
||||
}
|
||||
@@ -248,7 +274,19 @@ void main(int argc, char **argv, u32 magicWord)
|
||||
else if((((pressed & SINGLE_PAYLOAD_BUTTONS) || (!autoBootEmu && (pressed & DPAD_BUTTONS))) && !(pressed & (BUTTON_L1 | BUTTON_R1))) ||
|
||||
(((pressed & L_PAYLOAD_BUTTONS) || (autoBootEmu && (pressed & DPAD_BUTTONS))) && (pressed & BUTTON_L1))) loadHomebrewFirm(pressed);
|
||||
|
||||
if(splashMode == 2) loadSplash();
|
||||
if(splashMode == 2 && loadSplash()) pressed = HID_PAD;
|
||||
|
||||
//Check SAFE_MODE combo again
|
||||
if(!CFG_BOOTENV && pressed == SAFE_MODE)
|
||||
{
|
||||
nandType = FIRMWARE_SYSNAND;
|
||||
firmSource = FIRMWARE_SYSNAND;
|
||||
|
||||
isSafeMode = true;
|
||||
needToInitSd = true;
|
||||
|
||||
goto boot;
|
||||
}
|
||||
|
||||
//If booting from CTRNAND, always use SysNAND
|
||||
if(!isSdMode) nandType = FIRMWARE_SYSNAND;
|
||||
@@ -324,11 +362,11 @@ boot:
|
||||
u32 firmVersion = loadNintendoFirm(&firmType, firmSource, loadFromStorage, isSafeMode);
|
||||
|
||||
bool doUnitinfoPatch = CONFIG(PATCHUNITINFO);
|
||||
u32 res;
|
||||
u32 res = 0;
|
||||
switch(firmType)
|
||||
{
|
||||
case NATIVE_FIRM:
|
||||
res = patchNativeFirm(firmVersion, nandType, loadFromStorage, isFirmProtEnabled, isSafeMode, doUnitinfoPatch);
|
||||
res = patchNativeFirm(firmVersion, nandType, loadFromStorage, isFirmProtEnabled, needToInitSd, doUnitinfoPatch);
|
||||
break;
|
||||
case TWL_FIRM:
|
||||
res = patchTwlFirm(firmVersion, loadFromStorage, doUnitinfoPatch);
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -26,50 +26,11 @@
|
||||
|
||||
/*
|
||||
* Boyer-Moore Horspool algorithm adapted from http://www-igm.univ-mlv.fr/~lecroq/string/node18.html#SECTION00180
|
||||
* memcpy, memset32 and memcmp adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
|
||||
* memcpy, memset and memcmp adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
void memcpy(void *dest, const void *src, u32 size)
|
||||
{
|
||||
u8 *destc = (u8 *)dest;
|
||||
const u8 *srcc = (const u8 *)src;
|
||||
|
||||
for(u32 i = 0; i < size; i++)
|
||||
destc[i] = srcc[i];
|
||||
}
|
||||
|
||||
void memset(void *dest, u32 filler, u32 size)
|
||||
{
|
||||
u8 *destc = (u8 *)dest;
|
||||
|
||||
for(u32 i = 0; i < size; i++)
|
||||
destc[i] = (u8)filler;
|
||||
}
|
||||
|
||||
void memset32(void *dest, u32 filler, u32 size)
|
||||
{
|
||||
u32 *dest32 = (u32 *)dest;
|
||||
|
||||
for(u32 i = 0; i < size / 4; i++)
|
||||
dest32[i] = filler;
|
||||
}
|
||||
|
||||
int memcmp(const void *buf1, const void *buf2, u32 size)
|
||||
{
|
||||
const u8 *buf1c = (const u8 *)buf1,
|
||||
*buf2c = (const u8 *)buf2;
|
||||
|
||||
for(u32 i = 0; i < size; i++)
|
||||
{
|
||||
int cmp = buf1c[i] - buf2c[i];
|
||||
if(cmp != 0) return cmp;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize)
|
||||
{
|
||||
const u8 *patternc = (const u8 *)pattern;
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -24,22 +24,13 @@
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Boyer-Moore Horspool algorithm adapted from http://www-igm.univ-mlv.fr/~lecroq/string/node18.html#SECTION00180
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
|
||||
//Common data types
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
typedef volatile u8 vu8;
|
||||
typedef volatile u16 vu16;
|
||||
typedef volatile u32 vu32;
|
||||
typedef volatile u64 vu64;
|
||||
|
||||
struct fb {
|
||||
u8 *top_left;
|
||||
u8 *top_right;
|
||||
u8 *bottom;
|
||||
};
|
||||
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize);
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -39,7 +39,10 @@
|
||||
#include "memory.h"
|
||||
#include "config.h"
|
||||
#include "utils.h"
|
||||
#include "../build/bundled.h"
|
||||
#include "arm9_exception_handlers.h"
|
||||
#include "large_patches.h"
|
||||
|
||||
#define K11EXT_VA 0x70000000
|
||||
|
||||
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
|
||||
{
|
||||
@@ -78,8 +81,8 @@ u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 *
|
||||
return arm11SvcTable;
|
||||
}
|
||||
|
||||
// For ARM prologs in the form of: push {regs} ... sub sp, #off (this obviously doesn't intend to cover all cases)
|
||||
static inline u32 computeARMFrameSize(const u32 *prolog)
|
||||
// For Arm prologs in the form of: push {regs} ... sub sp, #off (this obviously doesn't intend to cover all cases)
|
||||
static inline u32 computeArmFrameSize(const u32 *prolog)
|
||||
{
|
||||
const u32 *off;
|
||||
|
||||
@@ -100,17 +103,19 @@ static inline u32 *getKernel11HandlerVAPos(u8 *pos, u32 *arm11ExceptionsPage, u3
|
||||
return (u32 *)(pos + pointedInstructionVA - baseK11VA + 8);
|
||||
}
|
||||
|
||||
u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space)
|
||||
u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space)
|
||||
{
|
||||
//The parameters to be passed on to the kernel ext
|
||||
//Please keep that in sync with the definition in k11_extension/source/main.c
|
||||
struct KExtParameters
|
||||
{
|
||||
u32 __attribute__((aligned(0x400))) L2MMUTableFor0x40000000[256];
|
||||
u32 basePA;
|
||||
u32 stolenSystemMemRegionSize;
|
||||
void *originalHandlers[4];
|
||||
u32 L1MMUTableAddrs[4];
|
||||
|
||||
volatile bool done;
|
||||
|
||||
struct CfwInfo
|
||||
{
|
||||
char magic[4];
|
||||
@@ -126,6 +131,7 @@ u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
|
||||
u32 config, multiConfig, bootConfig;
|
||||
u64 hbldr3dsxTitleId;
|
||||
u32 rosalinaMenuCombo;
|
||||
u32 rosalinaFlags;
|
||||
} info;
|
||||
};
|
||||
|
||||
@@ -134,8 +140,9 @@ u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
|
||||
static const u8 patternHook3_4[] = {0x00, 0x00, 0xA0, 0xE1, 0x03, 0xF0, 0x20, 0xE3, 0xFD, 0xFF, 0xFF, 0xEA}; //SGI0 setup code, etc.
|
||||
|
||||
//Our kernel11 extension is initially loaded in VRAM
|
||||
u32 kextTotalSize = *(u32 *)0x18000020 - 0x40000000;
|
||||
u32 dstKextPA = (ISN3DS ? 0x2E000000 : 0x26C00000) - kextTotalSize;
|
||||
u32 kextTotalSize = *(u32 *)0x18000020 - K11EXT_VA;
|
||||
u32 stolenSystemMemRegionSize = kextTotalSize; // no need to steal any more mem on N3DS. Currently, everything fits in BASE on O3DS too (?)
|
||||
u32 dstKextPA = (ISN3DS ? 0x2E000000 : 0x26C00000) - stolenSystemMemRegionSize; // start of BASE memregion (note: linear heap ---> <--- the rest)
|
||||
|
||||
u32 *hookVeneers = (u32 *)*freeK11Space;
|
||||
u32 relocBase = 0xFFFF0000 + (*freeK11Space - (u8 *)arm11ExceptionsPage);
|
||||
@@ -143,11 +150,11 @@ u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
|
||||
hookVeneers[0] = 0xE51FF004; //ldr pc, [pc, #-8+4]
|
||||
hookVeneers[1] = 0x18000004;
|
||||
hookVeneers[2] = 0xE51FF004;
|
||||
hookVeneers[3] = 0x40000000;
|
||||
hookVeneers[3] = K11EXT_VA;
|
||||
hookVeneers[4] = 0xE51FF004;
|
||||
hookVeneers[5] = 0x40000008;
|
||||
hookVeneers[5] = K11EXT_VA + 8;
|
||||
hookVeneers[6] = 0xE51FF004;
|
||||
hookVeneers[7] = 0x4000000C;
|
||||
hookVeneers[7] = K11EXT_VA + 0xC;
|
||||
|
||||
(*freeK11Space) += 32;
|
||||
|
||||
@@ -175,14 +182,16 @@ u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
|
||||
off += 4;
|
||||
*off = MAKE_BRANCH_LINK(baseK11VA + ((u8 *)off - pos), relocBase + 24);
|
||||
|
||||
struct KExtParameters *p = (struct KExtParameters *)(*(u32 *)0x18000024 - 0x40000000 + 0x18000000);
|
||||
struct KExtParameters *p = (struct KExtParameters *)(*(u32 *)0x18000024 - K11EXT_VA + 0x18000000);
|
||||
p->basePA = dstKextPA;
|
||||
p->done = false;
|
||||
p->stolenSystemMemRegionSize = stolenSystemMemRegionSize;
|
||||
|
||||
for(u32 i = 0; i < 4; i++)
|
||||
{
|
||||
u32 *handlerPos = getKernel11HandlerVAPos(pos, arm11ExceptionsPage, baseK11VA, 1 + i);
|
||||
p->originalHandlers[i] = (void *)*handlerPos;
|
||||
*handlerPos = 0x40000010 + 4 * i;
|
||||
*handlerPos = K11EXT_VA + 0x10 + 4 * i;
|
||||
}
|
||||
|
||||
struct CfwInfo *info = &p->info;
|
||||
@@ -195,13 +204,14 @@ u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
|
||||
info->bootConfig = configData.bootConfig;
|
||||
info->hbldr3dsxTitleId = configData.hbldr3dsxTitleId;
|
||||
info->rosalinaMenuCombo = configData.rosalinaMenuCombo;
|
||||
info->rosalinaFlags = configData.rosalinaFlags;
|
||||
info->versionMajor = VERSION_MAJOR;
|
||||
info->versionMinor = VERSION_MINOR;
|
||||
info->versionBuild = VERSION_BUILD;
|
||||
|
||||
if(ISRELEASE) info->flags = 1;
|
||||
if(ISN3DS) info->flags |= 1 << 4;
|
||||
if(isSafeMode) info->flags |= 1 << 5;
|
||||
if(needToInitSd) info->flags |= 1 << 5;
|
||||
if(isSdMode) info->flags |= 1 << 6;
|
||||
|
||||
return 0;
|
||||
@@ -221,6 +231,10 @@ u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm
|
||||
u8 *ControlMemoryPos = instrPos + 8 + displ;
|
||||
u32 *off;
|
||||
|
||||
// Patch ControlMemory bounds checks for mem mapping
|
||||
for (off = (u32 *)ControlMemoryPos; *off != 0xE0E01BF5; ++off);
|
||||
*off = 0;
|
||||
|
||||
/*
|
||||
Here we replace currentProcess->processID == 1 by additionnalParameter == 1.
|
||||
This patch should be generic enough to work even on firmware version 5.0.
|
||||
@@ -230,7 +244,7 @@ u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm
|
||||
*/
|
||||
for(off = (u32 *)ControlMemoryPos; (off[0] & 0xFFF0FFFF) != 0xE3500001 || (off[1] & 0xFFFF0FFF) != 0x13A00000; off++);
|
||||
off -= 2;
|
||||
*off = 0xE59D0000 | (*off & 0x0000F000) | (8 + computeARMFrameSize((u32 *)ControlMemoryPos)); // ldr r0, [sp, #(frameSize + 8)]
|
||||
*off = 0xE59D0000 | (*off & 0x0000F000) | (8 + computeArmFrameSize((u32 *)ControlMemoryPos)); // ldr r0, [sp, #(frameSize + 8)]
|
||||
|
||||
//Patch DebugActiveProcess
|
||||
for(off = (u32 *)(pos + (arm11SvcTable[0x60] - baseK11VA)); *off != 0xE3110001; off++);
|
||||
@@ -248,14 +262,14 @@ u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm
|
||||
|
||||
//Redirect enableUserExceptionHandlersForCPUExc (= true)
|
||||
for(off = arm11ExceptionsPage; *off != 0x96007F9; off++);
|
||||
off[1] = 0x40000028;
|
||||
off[1] = K11EXT_VA + 0x28;
|
||||
|
||||
off = (u32 *)memsearch(pos, patternKThreadDebugReschedule, size, sizeof(patternKThreadDebugReschedule));
|
||||
if(off == NULL)
|
||||
return 1;
|
||||
|
||||
off[-5] = 0xE51FF004;
|
||||
off[-4] = 0x4000002C;
|
||||
off[-4] = K11EXT_VA + 0x2C;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -302,7 +316,7 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
|
||||
static const u8 pattern[] = {0xE2, 0x20, 0x20, 0x90};
|
||||
|
||||
u32 pathLen;
|
||||
for(pathLen = 0; pathLen < 41 && launchedPath[pathLen] != 0; pathLen++);
|
||||
for(pathLen = 0; pathLen < sizeof(launchedPath)/2 && launchedPath[pathLen] != 0; pathLen++);
|
||||
|
||||
if(launchedPath[pathLen] != 0) return 1;
|
||||
|
||||
@@ -312,18 +326,17 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
|
||||
|
||||
off -= 0x13;
|
||||
|
||||
//Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
|
||||
//Firmlaunch function offset - offset in BLX opcode (A4-16 - Arm DDI 0100E) + 1
|
||||
u32 fOpenOffset = (u32)(off + 9 - (-((*(u32 *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - pos + process9MemAddr);
|
||||
|
||||
//Copy firmlaunch code
|
||||
memcpy(off, reboot_bin, reboot_bin_size);
|
||||
|
||||
//Put the fOpen offset in the right location
|
||||
u32 *pos_fopen = (u32 *)memsearch(off, "OPEN", reboot_bin_size, 4);
|
||||
*pos_fopen = fOpenOffset;
|
||||
rebootPatchFopenPtr = fOpenOffset;
|
||||
|
||||
u16 *fname = (u16 *)memsearch(off, "FILE", reboot_bin_size, 8);
|
||||
memcpy(fname, launchedPath, 2 * (1 + pathLen));
|
||||
//Copy the launched path
|
||||
memcpy(rebootPatchFileName, launchedPath, 2 * (1 + pathLen));
|
||||
|
||||
//Copy firmlaunch code
|
||||
memcpy(off, rebootPatch, rebootPatchSize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -373,7 +386,7 @@ u32 patchTitleInstallMinVersionChecks(u8 *pos, u32 size, u32 firmVersion)
|
||||
off++;
|
||||
|
||||
//Zero out the first TitleID in the list
|
||||
memset32(off, 0, 8);
|
||||
memset(off, 0, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -435,7 +448,7 @@ u32 patchK11ModuleLoading(u32 section0size, u32 modulesSize, u8 *pos, u32 size)
|
||||
off32 += 2;
|
||||
off32[1] = off32[0] + modulesSize;
|
||||
for(; *off32 != section0size; off32++);
|
||||
*off32 += ((modulesSize + 0x1FF) >> 9) << 9;
|
||||
*off32 = ((modulesSize + 0x1FF) >> 9) << 9;
|
||||
|
||||
off = memsearch(pos, modulePidPattern, size, 4);
|
||||
|
||||
@@ -501,20 +514,20 @@ u32 patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address)
|
||||
addr[0] = 0xE1A0800D;
|
||||
addr[1] = 0xE12FFF7F;
|
||||
|
||||
*(vu32 *)0x01FF8004 = arm9SvcTable[0x3C]; //BreakPtr
|
||||
arm9ExceptionHandlerSvcBreakAddress = arm9SvcTable[0x3C]; //BreakPtr
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 patchKernel9Panic(u8 *pos, u32 size)
|
||||
{
|
||||
static const u8 pattern[] = {0xFF, 0xEA, 0x04, 0xD0};
|
||||
static const u8 pattern[] = {0x00, 0x20, 0x92, 0x15};
|
||||
|
||||
u8 *temp = memsearch(pos, pattern, size, sizeof(pattern));
|
||||
|
||||
if(temp == NULL) return 1;
|
||||
|
||||
u32 *off = (u32 *)(temp - 0x12);
|
||||
u32 *off = (u32 *)(temp - 0x34);
|
||||
*off = 0xE12FFF7E;
|
||||
|
||||
return 0;
|
||||
@@ -550,6 +563,34 @@ u32 patchUnitInfoValueSet(u8 *pos, u32 size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 patchP9AMTicketWrapperZeroKeyIV(u8 *pos, u32 size, u32 firmVersion)
|
||||
{
|
||||
static const u8 __rt_memclr_pattern[] = {0x00, 0x20, 0xA0, 0xE3, 0x04, 0x00, 0x51, 0xE3, 0x07, 0x00, 0x00, 0x3A};
|
||||
static const u8 pattern[] = {0x20, 0x21, 0xA6, 0xA8};
|
||||
|
||||
u32 function = (u32)memsearch(pos, __rt_memclr_pattern, size, sizeof(__rt_memclr_pattern));
|
||||
u16 *off = (u16 *)memsearch(pos, pattern, size, sizeof(pattern));
|
||||
|
||||
if(function == 0 || off == NULL) return firmVersion == 0xFFFFFFFF ? 0 : 1;
|
||||
|
||||
//After the found code it's a BL call (at &off[2]), that will be replaced
|
||||
//From Thumb, op distance for setting in BLX can be got with,
|
||||
//(Destination_offset - blx_op_offset+2) / 2
|
||||
s32 opjumpdistance = (s32)(function - ((u32)&off[3])) / 2;
|
||||
|
||||
//Beyond limit
|
||||
if(opjumpdistance < -0x1fffff || opjumpdistance > 0x1fffff) return 1;
|
||||
|
||||
//r0 and r1 for old call are already correct for this one
|
||||
//BLX __rt_memclr
|
||||
u32 op = (0xE800F000U | (((u32)opjumpdistance & 0x7FF) << 16) | (((u32)opjumpdistance >> 11) & 0x3FF) | (((u32)opjumpdistance >> 21) & 0x400)) & ~(1<<16);
|
||||
|
||||
off[2] = op;
|
||||
off[3] = op >> 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 patchLgySignatureChecks(u8 *pos, u32 size)
|
||||
{
|
||||
static const u8 pattern[] = {0x47, 0xC1, 0x17, 0x49};
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
|
||||
u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage);
|
||||
u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space);
|
||||
u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space);
|
||||
u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm11ExceptionsPage);
|
||||
u32 patchSignatureChecks(u8 *pos, u32 size);
|
||||
u32 patchOldSignatureChecks(u8 *pos, u32 size);
|
||||
@@ -56,6 +56,7 @@ u32 patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address);
|
||||
u32 patchKernel9Panic(u8 *pos, u32 size);
|
||||
u32 patchP9AccessChecks(u8 *pos, u32 size);
|
||||
u32 patchUnitInfoValueSet(u8 *pos, u32 size);
|
||||
u32 patchP9AMTicketWrapperZeroKeyIV(u8 *pos, u32 size, u32 firmVersion);
|
||||
u32 patchLgySignatureChecks(u8 *pos, u32 size);
|
||||
u32 patchTwlInvalidSignatureChecks(u8 *pos, u32 size);
|
||||
u32 patchTwlNintendoLogoChecks(u8 *pos, u32 size);
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -69,7 +69,7 @@ void newPin(bool allowSkipping, u32 pinMode)
|
||||
{
|
||||
if(reset)
|
||||
{
|
||||
for(u32 i = 0; i < cnt; i++)
|
||||
for(u32 i = 0; i < cnt; i++)
|
||||
drawCharacter(true, 10 + (16 + 2 * i) * SPACING_X, 10 + 3 * SPACING_Y, COLOR_BLACK, (char)enteredPassword[i]);
|
||||
|
||||
cnt = 0;
|
||||
@@ -154,7 +154,7 @@ bool verifyPin(u32 pinMode)
|
||||
drawFormattedString(true, 10, 10 + 3 * SPACING_Y, COLOR_WHITE, "PIN (%u digits): ", lengthBlock[0]);
|
||||
|
||||
bool isBottomSplashValid = getFileSize("splashpin.bin") == SCREEN_BOTTOM_FBSIZE;
|
||||
if(isBottomSplashValid)
|
||||
if(isBottomSplashValid)
|
||||
{
|
||||
isBottomSplashValid = fileRead(fbs[0].bottom, "splashpin.bin", SCREEN_BOTTOM_FBSIZE) == SCREEN_BOTTOM_FBSIZE;
|
||||
}
|
||||
@@ -184,7 +184,7 @@ bool verifyPin(u32 pinMode)
|
||||
{
|
||||
if(reset)
|
||||
{
|
||||
for(u32 i = 0; i < cnt; i++)
|
||||
for(u32 i = 0; i < cnt; i++)
|
||||
drawCharacter(true, 10 + (16 + 2 * i) * SPACING_X, 10 + 3 * SPACING_Y, COLOR_BLACK, '*');
|
||||
|
||||
cnt = 0;
|
||||
@@ -225,7 +225,7 @@ bool verifyPin(u32 pinMode)
|
||||
{
|
||||
reset = true;
|
||||
|
||||
drawString(true, 10, 10 + 5 * SPACING_Y, COLOR_RED, "Wrong PIN, try again");
|
||||
drawString(true, 10, 10 + 5 * SPACING_Y, COLOR_RED, "Wrong PIN, try again");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "i2c.h"
|
||||
#include "utils.h"
|
||||
|
||||
bool needToSetupScreens = true;
|
||||
|
||||
struct fb fbs[2] =
|
||||
{
|
||||
{
|
||||
@@ -57,7 +59,7 @@ static void invokeArm11Function(Arm11Operation op)
|
||||
{
|
||||
while(*operation != ARM11_READY);
|
||||
*operation = op;
|
||||
while(*operation != ARM11_READY);
|
||||
while(*operation != ARM11_READY);
|
||||
}
|
||||
|
||||
void prepareArm11ForFirmlaunch(void)
|
||||
@@ -92,18 +94,17 @@ void clearScreens(bool isAlternate)
|
||||
|
||||
void initScreens(void)
|
||||
{
|
||||
static bool needToSetup = true;
|
||||
|
||||
if(needToSetup)
|
||||
if(needToSetupScreens)
|
||||
{
|
||||
if(!ARESCREENSINITIALIZED)
|
||||
if(!ARESCREENSINITIALIZED || bootType == FIRMLAUNCH)
|
||||
{
|
||||
*(vu32 *)ARM11_PARAMETERS_ADDRESS = brightness[MULTICONFIG(BRIGHTNESS)];
|
||||
memcpy((void *)(ARM11_PARAMETERS_ADDRESS + 4), fbs, sizeof(fbs));
|
||||
invokeArm11Function(INIT_SCREENS);
|
||||
|
||||
//Turn on backlight
|
||||
i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
|
||||
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x2A);
|
||||
wait(5);
|
||||
}
|
||||
else updateBrightness(MULTICONFIG(BRIGHTNESS));
|
||||
|
||||
@@ -111,7 +112,7 @@ void initScreens(void)
|
||||
invokeArm11Function(SETUP_FRAMEBUFFERS);
|
||||
|
||||
clearScreens(true);
|
||||
needToSetup = false;
|
||||
needToSetupScreens = false;
|
||||
}
|
||||
|
||||
clearScreens(false);
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -33,9 +33,9 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
|
||||
#define PDN_GPU_CNT (*(vu32 *)0x10141200)
|
||||
|
||||
#define ARESCREENSINITIALIZED (PDN_GPU_CNT != 1)
|
||||
#define ARESCREENSINITIALIZED ((PDN_GPU_CNT & 0xFF) != 1)
|
||||
|
||||
#define ARM11_PARAMETERS_ADDRESS 0x1FFFF000
|
||||
|
||||
@@ -65,6 +65,8 @@ typedef enum
|
||||
|
||||
extern struct fb fbs[2];
|
||||
|
||||
extern bool needToSetupScreens;
|
||||
|
||||
void prepareArm11ForFirmlaunch(void);
|
||||
void deinitScreens(void);
|
||||
void swapFramebuffers(bool isAlternate);
|
||||
@@ -1,5 +1,5 @@
|
||||
@ This file is part of Luma3DS
|
||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
@
|
||||
@ 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
|
||||
@@ -22,7 +22,7 @@
|
||||
@ or requiring that modified versions of such material be marked in
|
||||
@ reasonable ways as different from the original version.
|
||||
|
||||
.section .text.start
|
||||
.section .text.start, "ax", %progbits
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
@@ -77,7 +77,7 @@ _start:
|
||||
ldr r1, =0xFFF0001B @ fff00000 16k | dtcm
|
||||
ldr r2, =0x01FF801D @ 01ff8000 32k | itcm
|
||||
ldr r3, =0x08000027 @ 08000000 1M | arm9 mem
|
||||
ldr r4, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB)
|
||||
ldr r4, =0x10000029 @ 10000000 2M | io mem (Arm9 / first 2MB)
|
||||
ldr r5, =0x20000035 @ 20000000 128M | fcram
|
||||
ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram
|
||||
ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB)
|
||||
@@ -109,13 +109,58 @@ _start:
|
||||
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
||||
|
||||
@ Clear BSS
|
||||
ldr r0, =__bss_start
|
||||
ldr r0, =__bss_start__
|
||||
mov r1, #0
|
||||
ldr r2, =__bss_end
|
||||
ldr r2, =__bss_end__
|
||||
sub r2, r0
|
||||
bl memset32
|
||||
bl memset
|
||||
|
||||
bl __libc_init_array
|
||||
|
||||
mov r0, r9
|
||||
mov r1, r10
|
||||
mov r2, r11
|
||||
b main
|
||||
.pool
|
||||
|
||||
.section .chainloader.text.start, "ax", %progbits
|
||||
.align 4
|
||||
.global chainload
|
||||
.type chainload, %function
|
||||
chainload:
|
||||
ldr sp, =__itcm_stack_top__
|
||||
b chainloader_main
|
||||
.pool
|
||||
|
||||
.global disableMpuAndJumpToEntrypoints
|
||||
.type disableMpuAndJumpToEntrypoints, %function
|
||||
disableMpuAndJumpToEntrypoints:
|
||||
mov r4, r0
|
||||
mov r5, r1
|
||||
mov r6, r2
|
||||
mov r7, r3
|
||||
|
||||
@ Flush caches
|
||||
ldr r12, =0xFFFF0830
|
||||
blx r12
|
||||
ldr r12, =0xFFFF0AB4
|
||||
blx r12
|
||||
|
||||
@ Disable caches / MPU
|
||||
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
||||
bic r0, #(1<<12) @ - instruction cache disable
|
||||
bic r0, #(1<<2) @ - data cache disable
|
||||
bic r0, #(1<<0) @ - MPU disable
|
||||
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
||||
|
||||
@ Set the Arm11 entrypoint
|
||||
mov r0, #0x20000000
|
||||
str r7, [r0, #-4]
|
||||
|
||||
@ Jump to the Arm9 entrypoint
|
||||
mov r0, r4
|
||||
mov r1, r5
|
||||
ldr r2, =0x3BEEF
|
||||
bx r6
|
||||
|
||||
.pool
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -25,25 +25,6 @@
|
||||
*/
|
||||
|
||||
#include "strings.h"
|
||||
#include "memory.h"
|
||||
|
||||
u32 strlen(const char *string)
|
||||
{
|
||||
char *stringEnd = (char *)string;
|
||||
|
||||
while(*stringEnd != 0) stringEnd++;
|
||||
|
||||
return stringEnd - string;
|
||||
}
|
||||
|
||||
u32 strnlen(const char *string, u32 maxlen)
|
||||
{
|
||||
u32 size;
|
||||
|
||||
for(size = 0; size < maxlen && *string; string++, size++);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
u32 hexAtoi(const char *in, u32 digits)
|
||||
{
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -28,7 +28,5 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
u32 strlen(const char *string);
|
||||
u32 strnlen(const char *string, u32 maxlen);
|
||||
u32 hexAtoi(const char *in, u32 digits);
|
||||
u32 decAtoi(const char *in, u32 digits);
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -61,7 +61,7 @@ typedef volatile s64 vs64;
|
||||
#define ISN3DS (CFG11_SOCINFO & 2)
|
||||
#define ISDEVUNIT (CFG_UNITINFO != 0)
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct __attribute__((packed, aligned(4)))
|
||||
{
|
||||
char magic[4];
|
||||
u16 formatVersionMajor, formatVersionMinor;
|
||||
@@ -69,9 +69,10 @@ typedef struct __attribute__((packed))
|
||||
u32 config, multiConfig, bootConfig;
|
||||
u64 hbldr3dsxTitleId;
|
||||
u32 rosalinaMenuCombo;
|
||||
u32 rosalinaFlags;
|
||||
} CfgData;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
char magic[4];
|
||||
u16 formatVersionMajor, formatVersionMinor;
|
||||
@@ -80,7 +81,7 @@ typedef struct __attribute__((packed))
|
||||
u8 hash[32];
|
||||
} PinData;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
u32 magic[2];
|
||||
u16 versionMinor, versionMajor;
|
||||
@@ -129,4 +130,4 @@ extern bool isSdMode;
|
||||
extern BootType bootType;
|
||||
|
||||
extern u16 launchedFirmTidLow[8];
|
||||
extern u16 launchedPath[41];
|
||||
extern u16 launchedPath[80+1];
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "draw.h"
|
||||
#include "cache.h"
|
||||
#include "fmt.h"
|
||||
#include "strings.h"
|
||||
#include "memory.h"
|
||||
#include "fs.h"
|
||||
|
||||
static void startChrono(void)
|
||||
@@ -86,8 +86,17 @@ u32 waitInput(bool isMenu)
|
||||
|
||||
if(!key)
|
||||
{
|
||||
if((!(i2cReadRegister(I2C_DEV_MCU, 0xF) & 2) && shouldShellShutdown) ||
|
||||
(i2cReadRegister(I2C_DEV_MCU, 0x10) & 1) == 1) mcuPowerOff();
|
||||
if(shouldShellShutdown)
|
||||
{
|
||||
u8 shellState = I2C_readReg(I2C_DEV_MCU, 0xF);
|
||||
wait(5);
|
||||
if(!(shellState & 2)) mcuPowerOff();
|
||||
}
|
||||
|
||||
u8 intStatus = I2C_readReg(I2C_DEV_MCU, 0x10);
|
||||
wait(5);
|
||||
if(intStatus & 1) mcuPowerOff(); //Power button pressed
|
||||
|
||||
oldKey = 0;
|
||||
dPadDelay = 0;
|
||||
continue;
|
||||
@@ -106,15 +115,15 @@ u32 waitInput(bool isMenu)
|
||||
|
||||
void mcuPowerOff(void)
|
||||
{
|
||||
if(bootType != FIRMLAUNCH && ARESCREENSINITIALIZED) clearScreens(false);
|
||||
if(!needToSetupScreens) clearScreens(false);
|
||||
|
||||
//Shutdown LCD
|
||||
if(ARESCREENSINITIALIZED) i2cWriteRegister(I2C_DEV_MCU, 0x22, 1 << 0);
|
||||
if(ARESCREENSINITIALIZED) I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0);
|
||||
|
||||
//Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||
flushEntireDCache();
|
||||
|
||||
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0);
|
||||
I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 0);
|
||||
while(true);
|
||||
}
|
||||
|
||||
@@ -136,17 +145,12 @@ void error(const char *fmt, ...)
|
||||
vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if(bootType != FIRMLAUNCH)
|
||||
{
|
||||
initScreens();
|
||||
initScreens();
|
||||
drawString(true, 10, 10, COLOR_RED, "An error has occurred:");
|
||||
u32 posY = drawString(true, 10, 30, COLOR_WHITE, buf);
|
||||
drawString(true, 10, posY + 2 * SPACING_Y, COLOR_WHITE, "Press any button to shutdown");
|
||||
|
||||
drawString(true, 10, 10, COLOR_RED, "An error has occurred:");
|
||||
u32 posY = drawString(true, 10, 30, COLOR_WHITE, buf);
|
||||
drawString(true, 10, posY + 2 * SPACING_Y, COLOR_WHITE, "Press any button to shutdown");
|
||||
|
||||
waitInput(false);
|
||||
}
|
||||
else fileWrite(buf, "firmlauncherror.txt", strlen(buf));
|
||||
waitInput(false);
|
||||
|
||||
mcuPowerOff();
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -1,44 +0,0 @@
|
||||
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/base_tools
|
||||
|
||||
name := $(shell basename $(CURDIR))
|
||||
|
||||
dir_source := source
|
||||
dir_build := build
|
||||
dir_out := ../$(dir_build)
|
||||
|
||||
ASFLAGS := -mcpu=arm946e-s
|
||||
CFLAGS := -Wall -Wextra -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||
LDFLAGS := -nostartfiles -Wl,--nmagic
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
|
||||
.PHONY: all
|
||||
all: $(dir_out)/$(name).bin
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@rm -rf $(dir_build)
|
||||
|
||||
$(dir_out)/$(name).bin: $(dir_build)/$(name).elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
$(dir_build)/$(name).elf: $(objects)
|
||||
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
||||
$(dir_build)/memory.o: CFLAGS += -O3
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||
@@ -1,21 +0,0 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x01FF9000;
|
||||
|
||||
__start__ = ABSOLUTE(.);
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
__end__ = ABSOLUTE(.);
|
||||
|
||||
__stack_top__ = 0x01FFB800;
|
||||
__stack_bottom__ = 0x01FFA800;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
@ This file is part of Luma3DS
|
||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
@
|
||||
@ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
@
|
||||
@ Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
@ * Requiring preservation of specified reasonable legal notices or
|
||||
@ author attributions in that material or in the Appropriate Legal
|
||||
@ Notices displayed by works containing it.
|
||||
@ * Prohibiting misrepresentation of the origin of that material,
|
||||
@ or requiring that modified versions of such material be marked in
|
||||
@ reasonable ways as different from the original version.
|
||||
|
||||
.text
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
.global flushCaches
|
||||
.type flushCaches, %function
|
||||
flushCaches:
|
||||
@ Clean and flush both the data cache and instruction caches
|
||||
|
||||
@ Adpated from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html ,
|
||||
@ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well
|
||||
@ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has)
|
||||
|
||||
@ Implemented in bootROM at addresses 0xffff0830 (DCache) and 0xffff0ab4 (ICache)
|
||||
|
||||
mov r1, #0 @ segment counter
|
||||
outer_loop:
|
||||
mov r0, #0 @ line counter
|
||||
|
||||
inner_loop:
|
||||
orr r2, r1, r0 @ generate segment and line address
|
||||
mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line
|
||||
add r0, #0x20 @ increment to next line
|
||||
cmp r0, #0x400
|
||||
bne inner_loop
|
||||
|
||||
add r1, #0x40000000
|
||||
cmp r1, #0
|
||||
bne outer_loop
|
||||
|
||||
mcr p15, 0, r1, c7, c10, 4 @ drain write buffer
|
||||
|
||||
@ Flush instruction cache
|
||||
mcr p15, 0, r1, c7, c5, 0
|
||||
|
||||
bx lr
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
* * Requiring preservation of specified reasonable legal notices or
|
||||
* author attributions in that material or in the Appropriate Legal
|
||||
* Notices displayed by works containing it.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#include "firm.h"
|
||||
#include "memory.h"
|
||||
#include "cache.h"
|
||||
|
||||
void disableMpuAndJumpToEntrypoints(int argc, char **argv, void *arm11Entry, void *arm9Entry);
|
||||
|
||||
void launchFirm(Firm *firm, int argc, char **argv)
|
||||
{
|
||||
//Copy FIRM sections to respective memory locations
|
||||
for(u32 sectionNum = 0; sectionNum < 4; sectionNum++)
|
||||
memcpy(firm->section[sectionNum].address, (u8 *)firm + firm->section[sectionNum].offset, firm->section[sectionNum].size);
|
||||
|
||||
disableMpuAndJumpToEntrypoints(argc, argv, firm->arm9Entry, firm->arm11Entry);
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
* * Requiring preservation of specified reasonable legal notices or
|
||||
* author attributions in that material or in the Appropriate Legal
|
||||
* Notices displayed by works containing it.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
/*
|
||||
* memcpy adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
void memcpy(void *dest, const void *src, u32 size)
|
||||
{
|
||||
u8 *destc = (u8 *)dest;
|
||||
const u8 *srcc = (const u8 *)src;
|
||||
|
||||
for(u32 i = 0; i < size; i++)
|
||||
destc[i] = srcc[i];
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/base_tools
|
||||
|
||||
name := arm9_exceptions
|
||||
|
||||
dir_source := source
|
||||
dir_build := build
|
||||
dir_out := ../../$(dir_build)
|
||||
|
||||
ASFLAGS := -mcpu=arm946e-s
|
||||
CFLAGS := -Wall -Wextra -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -Os -ffast-math
|
||||
LDFLAGS := -nostartfiles -Wl,--nmagic
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
|
||||
.PHONY: all
|
||||
all: $(dir_out)/$(name).bin
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@rm -rf $(dir_build)
|
||||
|
||||
$(dir_out)/$(name).bin: $(dir_build)/$(name).elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
$(dir_build)/$(name).elf: $(objects)
|
||||
$(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||
@@ -1,14 +0,0 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x01FF8000;
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
|
||||
|
||||
. = ALIGN(4);
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
* * Requiring preservation of specified reasonable legal notices or
|
||||
* author attributions in that material or in the Appropriate Legal
|
||||
* Notices displayed by works containing it.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u32 magic[2];
|
||||
u16 versionMinor, versionMajor;
|
||||
|
||||
u16 processor, core;
|
||||
u32 type;
|
||||
|
||||
u32 totalSize;
|
||||
u32 registerDumpSize;
|
||||
u32 codeDumpSize;
|
||||
u32 stackDumpSize;
|
||||
u32 additionalDataSize;
|
||||
} ExceptionDumpHeader;
|
||||
|
||||
void FIQHandler(void);
|
||||
void undefinedInstructionHandler(void);
|
||||
void dataAbortHandler(void);
|
||||
void prefetchAbortHandler(void);
|
||||
|
||||
u32 safecpy(void *dst, const void *src, u32 len);
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
* * Requiring preservation of specified reasonable legal notices or
|
||||
* author attributions in that material or in the Appropriate Legal
|
||||
* Notices displayed by works containing it.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Thanks to whoever contributed in the development of this file
|
||||
*/
|
||||
|
||||
#include "i2c.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static const struct { u8 bus_id, reg_addr; } dev_data[] = {
|
||||
{0, 0x4A}, {0, 0x7A}, {0, 0x78},
|
||||
{1, 0x4A}, {1, 0x78}, {1, 0x2C},
|
||||
{1, 0x2E}, {1, 0x40}, {1, 0x44},
|
||||
{2, 0xD6}, {2, 0xD0}, {2, 0xD2},
|
||||
{2, 0xA4}, {2, 0x9A}, {2, 0xA0},
|
||||
};
|
||||
|
||||
static inline u8 i2cGetDeviceBusId(u8 device_id)
|
||||
{
|
||||
return dev_data[device_id].bus_id;
|
||||
}
|
||||
|
||||
static inline u8 i2cGetDeviceRegAddr(u8 device_id)
|
||||
{
|
||||
return dev_data[device_id].reg_addr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static vu8 *reg_data_addrs[] = {
|
||||
(vu8 *)(I2C1_REG_OFF + I2C_REG_DATA),
|
||||
(vu8 *)(I2C2_REG_OFF + I2C_REG_DATA),
|
||||
(vu8 *)(I2C3_REG_OFF + I2C_REG_DATA),
|
||||
};
|
||||
|
||||
static inline vu8 *i2cGetDataReg(u8 bus_id)
|
||||
{
|
||||
return reg_data_addrs[bus_id];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static vu8 *reg_cnt_addrs[] = {
|
||||
(vu8 *)(I2C1_REG_OFF + I2C_REG_CNT),
|
||||
(vu8 *)(I2C2_REG_OFF + I2C_REG_CNT),
|
||||
(vu8 *)(I2C3_REG_OFF + I2C_REG_CNT),
|
||||
};
|
||||
|
||||
static inline vu8 *i2cGetCntReg(u8 bus_id)
|
||||
{
|
||||
return reg_cnt_addrs[bus_id];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static inline void i2cWaitBusy(u8 bus_id)
|
||||
{
|
||||
while (*i2cGetCntReg(bus_id) & 0x80);
|
||||
}
|
||||
|
||||
static inline bool i2cGetResult(u8 bus_id)
|
||||
{
|
||||
i2cWaitBusy(bus_id);
|
||||
|
||||
return (*i2cGetCntReg(bus_id) >> 4) & 1;
|
||||
}
|
||||
|
||||
static void i2cStop(u8 bus_id, u8 arg0)
|
||||
{
|
||||
*i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0;
|
||||
i2cWaitBusy(bus_id);
|
||||
*i2cGetCntReg(bus_id) = 0xC5;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static bool i2cSelectDevice(u8 bus_id, u8 dev_reg)
|
||||
{
|
||||
i2cWaitBusy(bus_id);
|
||||
*i2cGetDataReg(bus_id) = dev_reg;
|
||||
*i2cGetCntReg(bus_id) = 0xC2;
|
||||
|
||||
return i2cGetResult(bus_id);
|
||||
}
|
||||
|
||||
static bool i2cSelectRegister(u8 bus_id, u8 reg)
|
||||
{
|
||||
i2cWaitBusy(bus_id);
|
||||
*i2cGetDataReg(bus_id) = reg;
|
||||
*i2cGetCntReg(bus_id) = 0xC0;
|
||||
|
||||
return i2cGetResult(bus_id);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data)
|
||||
{
|
||||
u8 bus_id = i2cGetDeviceBusId(dev_id);
|
||||
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
|
||||
|
||||
for(u32 i = 0; i < 8; i++)
|
||||
{
|
||||
if(i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg))
|
||||
{
|
||||
i2cWaitBusy(bus_id);
|
||||
*i2cGetDataReg(bus_id) = data;
|
||||
*i2cGetCntReg(bus_id) = 0xC1;
|
||||
i2cStop(bus_id, 0);
|
||||
|
||||
if(i2cGetResult(bus_id)) return true;
|
||||
}
|
||||
*i2cGetCntReg(bus_id) = 0xC5;
|
||||
i2cWaitBusy(bus_id);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
@ This file is part of Luma3DS
|
||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
@
|
||||
@ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
@
|
||||
@ Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
@ * Requiring preservation of specified reasonable legal notices or
|
||||
@ author attributions in that material or in the Appropriate Legal
|
||||
@ Notices displayed by works containing it.
|
||||
@ * Prohibiting misrepresentation of the origin of that material,
|
||||
@ or requiring that modified versions of such material be marked in
|
||||
@ reasonable ways as different from the original version.
|
||||
|
||||
.section .text.start
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
add pc, r0, #(handlers - .) @ Dummy instruction
|
||||
|
||||
.global BreakPtr
|
||||
BreakPtr: .word 0
|
||||
|
||||
.global handlers
|
||||
handlers:
|
||||
.word FIQHandler
|
||||
.word undefinedInstructionHandler
|
||||
.word prefetchAbortHandler
|
||||
.word dataAbortHandler
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
* * Requiring preservation of specified reasonable legal notices or
|
||||
* author attributions in that material or in the Appropriate Legal
|
||||
* Notices displayed by works containing it.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
//Common data types
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
typedef volatile u8 vu8;
|
||||
typedef volatile u16 vu16;
|
||||
typedef volatile u32 vu32;
|
||||
typedef volatile u64 vu64;
|
||||
|
||||
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
|
||||
|
||||
#define ARESCREENSINITIALIZED (PDN_GPU_CNT != 1)
|
||||
@@ -1,188 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Requires Python >= 3.2 or >= 2.7
|
||||
|
||||
# This file is part of Luma3DS
|
||||
# Copyright (C) 2016 Aurora Wright, TuxSH
|
||||
#
|
||||
# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified
|
||||
# reasonable legal notices or author attributions in that material or in the Appropriate Legal
|
||||
# Notices displayed by works containing it.
|
||||
|
||||
__author__ = "TuxSH"
|
||||
__copyright__ = "Copyright (c) 2016 TuxSH"
|
||||
__license__ = "GPLv3"
|
||||
__version__ = "v1.2"
|
||||
|
||||
"""
|
||||
Parses Luma3DS exception dumps
|
||||
"""
|
||||
|
||||
import argparse
|
||||
from struct import unpack_from
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
# Source of hexdump: https://gist.github.com/ImmortalPC/c340564823f283fe530b
|
||||
# Credits for hexdump go to the original authors
|
||||
# Slightly edited by TuxSH
|
||||
|
||||
def hexdump(addr, src, length=16, sep='.' ):
|
||||
'''
|
||||
@brief Return {src} in hex dump.
|
||||
@param[in] length {Int} Nb Bytes by row.
|
||||
@param[in] sep {Char} For the text part, {sep} will be used for non ASCII char.
|
||||
@return {Str} The hexdump
|
||||
@note Full support for python2 and python3 !
|
||||
'''
|
||||
result = []
|
||||
|
||||
# Python3 support
|
||||
try:
|
||||
xrange(0,1)
|
||||
except NameError:
|
||||
xrange = range
|
||||
|
||||
for i in xrange(0, len(src), length):
|
||||
subSrc = src[i:i+length]
|
||||
hexa = ''
|
||||
isMiddle = False
|
||||
for h in xrange(0,len(subSrc)):
|
||||
if h == length/2:
|
||||
hexa += ' '
|
||||
h = subSrc[h]
|
||||
if not isinstance(h, int):
|
||||
h = ord(h)
|
||||
h = hex(h).replace('0x','')
|
||||
if len(h) == 1:
|
||||
h = '0'+h
|
||||
hexa += h+' '
|
||||
hexa = hexa.strip(' ')
|
||||
text = ''
|
||||
for c in subSrc:
|
||||
if not isinstance(c, int):
|
||||
c = ord(c)
|
||||
if 0x20 <= c < 0x7F:
|
||||
text += chr(c)
|
||||
else:
|
||||
text += sep
|
||||
result.append(('%08x: %-'+str(length*(2+1)+1)+'s |%s|') % (addr + i, hexa, text))
|
||||
|
||||
return '\n'.join(result)
|
||||
|
||||
|
||||
def makeRegisterLine(A, rA, B, rB):
|
||||
return "{0:<15}{1:<20}{2:<15}{3:<20}".format(A, "{0:08x}".format(rA), B, "{0:08x}".format(rB))
|
||||
|
||||
handledExceptionNames = ("FIQ", "undefined instruction", "prefetch abort", "data abort")
|
||||
registerNames = tuple("r{0}".format(i) for i in range(13)) + ("sp", "lr", "pc", "cpsr") + ("dfsr", "ifsr", "far") + ("fpexc", "fpinst", "fpinst2")
|
||||
svcBreakReasons = ("(svcBreak: panic)", "(svcBreak: assertion failed)", "(svcBreak: user-related)")
|
||||
faultStatusSources = {
|
||||
0b1:'Alignment', 0b100:'Instruction cache maintenance operation fault',
|
||||
0b1100:'External Abort on translation - First-level', 0b1110:'External Abort on translation - Second-level',
|
||||
0b101:'Translation - Section', 0b111:'Translation - Page', 0b11:'Access bit - Section', 0b110:'Access bit - Page',
|
||||
0b1001:'Domain - Section', 0b1011:'Domain - Page', 0b1101:'Permission - Section', 0b1111:'Permission - Page',
|
||||
0b1000:'Precise External Abort', 0b10110:'Imprecise External Abort', 0b10:'Debug event'
|
||||
}
|
||||
|
||||
def main(args=None):
|
||||
parser = argparse.ArgumentParser(description="Parse Luma3DS exception dumps")
|
||||
parser.add_argument("filename")
|
||||
args = parser.parse_args()
|
||||
data = b""
|
||||
with open(args.filename, "rb") as f: data = f.read()
|
||||
if unpack_from("<2I", data) != (0xdeadc0de, 0xdeadcafe):
|
||||
raise SystemExit("Invalid file format")
|
||||
|
||||
version, processor, exceptionType, _, nbRegisters, codeDumpSize, stackDumpSize, additionalDataSize = unpack_from("<8I", data, 8)
|
||||
nbRegisters //= 4
|
||||
|
||||
if version < (1 << 16) | 2:
|
||||
raise SystemExit("Incompatible format version, please use the appropriate parser.")
|
||||
|
||||
registers = unpack_from("<{0}I".format(nbRegisters), data, 40)
|
||||
codeOffset = 40 + 4 * nbRegisters
|
||||
codeDump = data[codeOffset : codeOffset + codeDumpSize]
|
||||
stackOffset = codeOffset + codeDumpSize
|
||||
stackDump = data[stackOffset : stackOffset + stackDumpSize]
|
||||
addtionalDataOffset = stackOffset + stackDumpSize
|
||||
additionalData = data[addtionalDataOffset : addtionalDataOffset + additionalDataSize]
|
||||
|
||||
if processor == 9: print("Processor: ARM9")
|
||||
else: print("Processor: ARM11 (core {0})".format(processor >> 16))
|
||||
|
||||
typeDetailsStr = ""
|
||||
if exceptionType == 2:
|
||||
if (registers[16] & 0x20) == 0 and codeDumpSize >= 4:
|
||||
instr = unpack_from("<I", codeDump[-4:])[0]
|
||||
if instr == 0xe12fff7e:
|
||||
typeDetailsStr = " (kernel panic)"
|
||||
elif instr == 0xef00003c:
|
||||
typeDetailsStr = " " + (svcBreakReasons[registers[0]] if registers[0] < 3 else "(svcBreak)")
|
||||
elif (registers[16] & 0x20) == 1 and codeDumpSize >= 2:
|
||||
instr = unpack_from("<I", codeDump[-4:])[0]
|
||||
if instr == 0xdf3c:
|
||||
typeDetailsStr = " " + (svcBreakReasons[registers[0]] if registers[0] < 3 else "(svcBreak)")
|
||||
|
||||
elif processor != 9 and (registers[20] & 0x80000000) != 0:
|
||||
typeDetailsStr = " (VFP exception)"
|
||||
|
||||
print("Exception type: {0}{1}".format("unknown" if exceptionType >= len(handledExceptionNames) else handledExceptionNames[exceptionType], typeDetailsStr))
|
||||
|
||||
if processor == 11 and exceptionType >= 2:
|
||||
xfsr = registers[18] if exceptionType == 2 else registers[17]
|
||||
print("Fault status: " + faultStatusSources[xfsr & 0xf])
|
||||
|
||||
if additionalDataSize != 0:
|
||||
print("Current process: {0} ({1:016x})".format(additionalData[:8].decode("ascii"), unpack_from("<Q", additionalData, 8)[0]))
|
||||
|
||||
print("\nRegister dump:\n")
|
||||
for i in range(0, nbRegisters - (nbRegisters % 2), 2):
|
||||
if i == 16: print("")
|
||||
print(makeRegisterLine(registerNames[i], registers[i], registerNames[i+1], registers[i+1]))
|
||||
if nbRegisters % 2 == 1: print("{0:<15}{1:<20}".format(registerNames[nbRegisters - 1], "{0:08x}".format(registers[nbRegisters - 1])))
|
||||
|
||||
if processor == 11 and exceptionType == 3:
|
||||
print("{0:<15}{1:<20}Access type: {2}".format("FAR", "{0:08x}".format(registers[19]), "Write" if registers[17] & (1 << 11) != 0 else "Read"))
|
||||
|
||||
thumb = registers[16] & 0x20 != 0
|
||||
addr = registers[15] - codeDumpSize + (2 if thumb else 4)
|
||||
|
||||
print("\nCode dump:\n")
|
||||
|
||||
objdump_res = ""
|
||||
try:
|
||||
path = os.path.join(os.environ["DEVKITARM"], "bin", "arm-none-eabi-objdump")
|
||||
|
||||
if os.name == "nt" and path[0] == '/':
|
||||
path = ''.join((path[1], ':', path[2:]))
|
||||
|
||||
objdump_res = subprocess.check_output((
|
||||
path, "-marm", "-b", "binary",
|
||||
"--adjust-vma="+hex(addr - codeOffset), "--start-address="+hex(addr),
|
||||
"--stop-address="+hex(addr + codeDumpSize), "-D", "-z", "-M",
|
||||
"reg-names-std" + (",force-thumb" if thumb else ""), args.filename
|
||||
)).decode("utf-8")
|
||||
objdump_res = '\n'.join(objdump_res[objdump_res.find('<.data+'):].split('\n')[1:])
|
||||
except: objdump_res = ""
|
||||
|
||||
print(objdump_res if objdump_res != "" else hexdump(addr, codeDump))
|
||||
|
||||
print("\nStack dump:\n")
|
||||
print(hexdump(registers[13], stackDump))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,13 +0,0 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name='luma3ds_exception_dump_parser',
|
||||
version='1.2',
|
||||
url='https://github.com/AuroraWright/Luma3DS',
|
||||
author='TuxSH',
|
||||
license='GPLv3',
|
||||
description='Parses Luma3DS exception dumps',
|
||||
install_requires=[''],
|
||||
packages=find_packages(),
|
||||
entry_points={'console_scripts': ['luma3ds_exception_dump_parser=luma3ds_exception_dump_parser.__main__:main']},
|
||||
)
|
||||
@@ -1,47 +1,143 @@
|
||||
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/base_tools
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/base_rules
|
||||
|
||||
name := k11_extension
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source source/svc
|
||||
DATA := data
|
||||
INCLUDES := include include/svc
|
||||
|
||||
dir_source := source
|
||||
dir_include := include
|
||||
dir_build := build
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
|
||||
DEFINES := -DARM11 -D_3DS
|
||||
|
||||
ARCH := -mcpu=mpcore -mfpu=vfp
|
||||
ASFLAGS := $(ARCH)
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -I$(dir_include) -fno-builtin -std=c11 -Wno-main -g -flto -O2 -ffast-math \
|
||||
-mword-relocations -ffunction-sections -fdata-sections
|
||||
LDFLAGS := -nostdlib -Wl,--gc-sections,--nmagic $(ARCH)
|
||||
CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections -fdata-sections \
|
||||
-Wno-main $(ARCH) $(DEFINES)
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
CFLAGS += $(INCLUDE)
|
||||
|
||||
.PHONY: all
|
||||
all: ../$(dir_build)/$(name).bin
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
.PHONY: clean
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS :=
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
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)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
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)
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@rm -rf $(dir_build)
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).elf
|
||||
|
||||
../$(dir_build)/$(name).bin: $(dir_build)/$(name).elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
$(dir_build)/$(name).elf: $(objects)
|
||||
$(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
.PHONY: all
|
||||
|
||||
$(dir_build)/memory.o : CFLAGS += -O3 -marm
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).elf
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||
include $(call rwildcard, $(dir_build), *.d)
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
%.elf: $(OFILES)
|
||||
@echo linking $(notdir $@)
|
||||
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
@$(NM) -CSn $@ > $(notdir $*.lst)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
||||
@@ -33,5 +33,6 @@ enum singleOptions
|
||||
PATCHVERSTRING,
|
||||
SHOWGBABOOT,
|
||||
PATCHUNITINFO,
|
||||
DISABLEARM11EXCHANDLERS
|
||||
DISABLEARM11EXCHANDLERS,
|
||||
ENABLESAFEFIRMROSALINA,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -36,7 +36,7 @@ void undefinedInstructionHandler(void);
|
||||
void prefetchAbortHandler(void);
|
||||
void dataAbortHandler(void);
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
typedef struct
|
||||
{
|
||||
u32 magic[2];
|
||||
u16 versionMinor, versionMajor;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -44,8 +44,12 @@ extern KAutoObject * (*KProcessHandleTable__ToKAutoObject)(KProcessHandleTable *
|
||||
extern void (*KSynchronizationObject__Signal)(KSynchronizationObject *this, bool isPulse);
|
||||
extern Result (*WaitSynchronization1)(void *this_unused, KThread *thread, KSynchronizationObject *syncObject, s64 timeout);
|
||||
extern Result (*KProcessHandleTable__CreateHandle)(KProcessHandleTable *this, Handle *out, KAutoObject *obj, u8 token);
|
||||
extern Result (*KProcessHwInfo__QueryMemory)(KProcessHwInfo *this, MemoryInfo *memoryInfo, PageInfo *pageInfo, void *address);
|
||||
extern Result (*KProcessHwInfo__MapProcessMemory)(KProcessHwInfo *this, KProcessHwInfo *other, void *dst, void *src, u32 nbPages);
|
||||
extern Result (*KProcessHwInfo__UnmapProcessMemory)(KProcessHwInfo *this, void *addr, u32 nbPages);
|
||||
extern Result (*KProcessHwInfo__CheckVaState)(KProcessHwInfo *hwInfo, u32 va, u32 size, u32 state, u32 perm);
|
||||
extern Result (*KProcessHwInfo__GetListOfKBlockInfoForVA)(KProcessHwInfo *hwInfo, KLinkedList *list, u32 va, u32 sizeInPage);
|
||||
extern Result (*KProcessHwInfo__MapListOfKBlockInfo)(KProcessHwInfo *this, u32 va, KLinkedList *list, u32 state, u32 perm, u32 sbz);
|
||||
extern Result (*KEvent__Clear)(KEvent *this);
|
||||
extern void (*KObjectMutex__WaitAndAcquire)(KObjectMutex *this);
|
||||
extern void (*KObjectMutex__ErrorOccured)(void);
|
||||
@@ -53,8 +57,11 @@ extern void (*KObjectMutex__ErrorOccured)(void);
|
||||
extern void (*KScheduler__AdjustThread)(KScheduler *this, KThread *thread, u32 oldSchedulingMask);
|
||||
extern void (*KScheduler__AttemptSwitchingThreadContext)(KScheduler *this);
|
||||
|
||||
extern void (*KLinkedList_KBlockInfo__Clear)(KLinkedList *list);
|
||||
|
||||
extern Result (*ControlMemory)(u32 *addrOut, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm, bool isLoader);
|
||||
extern void (*SleepThread)(s64 ns);
|
||||
extern Result (*CreateEvent)(Handle *out, ResetType resetType);
|
||||
extern Result (*CloseHandle)(Handle handle);
|
||||
extern Result (*GetHandleInfo)(s64 *out, Handle handle, u32 type);
|
||||
extern Result (*GetSystemInfo)(s64 *out, s32 type, s32 param);
|
||||
@@ -65,6 +72,7 @@ extern Result (*SendSyncRequest)(Handle handle);
|
||||
extern Result (*OpenProcess)(Handle *out, u32 processId);
|
||||
extern Result (*GetProcessId)(u32 *out, Handle process);
|
||||
extern Result (*DebugActiveProcess)(Handle *out, u32 processId);
|
||||
extern Result (*SignalEvent)(Handle event);
|
||||
extern Result (*UnmapProcessMemory)(Handle processHandle, void *dst, u32 size);
|
||||
extern Result (*KernelSetState)(u32 type, u32 varg1, u32 varg2, u32 varg3);
|
||||
|
||||
@@ -129,9 +137,14 @@ typedef struct CfwInfo
|
||||
u32 config, multiConfig, bootConfig;
|
||||
u64 hbldr3dsxTitleId;
|
||||
u32 rosalinaMenuCombo;
|
||||
u32 rosalinaFlags;
|
||||
} CfwInfo;
|
||||
|
||||
extern CfwInfo cfwInfo;
|
||||
extern u32 kextBasePa;
|
||||
extern u32 stolenSystemMemRegionSize;
|
||||
|
||||
extern vu32 rosalinaState;
|
||||
extern bool hasStartedRosalinaNetworkFuncsOnce;
|
||||
|
||||
KLinkedList* KLinkedList__Initialize(KLinkedList *list);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -57,5 +57,4 @@ void SessionInfo_Add(KSession *session, const char *name);
|
||||
void SessionInfo_Remove(KSession *session);
|
||||
|
||||
bool doLangEmu(Result *res, u32 *cmdbuf);
|
||||
Result doPublishToProcessHook(Handle handle, u32 *cmdbuf);
|
||||
bool doErrfThrowHook(u32 *cmdbuf);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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
|
||||
@@ -105,6 +105,14 @@ typedef struct ALIGN(4) KMutex
|
||||
union KProcess *owner;
|
||||
} KMutex;
|
||||
|
||||
typedef struct KAddressArbiter
|
||||
{
|
||||
KAutoObject autoObject;
|
||||
struct KThread *first;
|
||||
struct KThread *last;
|
||||
union KProcess *owner;
|
||||
} KAddressArbiter;
|
||||
|
||||
/* 92 */
|
||||
typedef struct KMutexLinkedList
|
||||
{
|
||||
@@ -112,6 +120,30 @@ typedef struct KMutexLinkedList
|
||||
KMutex *last;
|
||||
} KMutexLinkedList;
|
||||
|
||||
enum
|
||||
{
|
||||
TOKEN_KAUTOOBJECT = 0,
|
||||
TOKEN_KSYNCHRONIZATIONOBJECT = 1,
|
||||
TOKEN_KEVENT = 0x1F,
|
||||
TOKEN_KSEMAPHORE = 0x2F,
|
||||
TOKEN_KTIMER = 0x35,
|
||||
TOKEN_KMUTEX = 0x39,
|
||||
TOKEN_KDEBUG = 0x4D,
|
||||
TOKEN_KSERVERPORT = 0x55,
|
||||
TOKEN_KDMAOBJECT = 0x59,
|
||||
TOKEN_KCLIENTPORT = 0x65,
|
||||
TOKEN_KCODESET = 0x68,
|
||||
TOKEN_KSESSION = 0x70,
|
||||
TOKEN_KTHREAD = 0x8D,
|
||||
TOKEN_KSERVERSESSION = 0x95,
|
||||
TOKEN_KADDRESSARBITER = 0x98,
|
||||
TOKEN_KCLIENTSESSION = 0xA5,
|
||||
TOKEN_KPORT = 0xA8,
|
||||
TOKEN_KSHAREDMEMORY = 0xB0,
|
||||
TOKEN_KPROCESS = 0xC5,
|
||||
TOKEN_KRESOURCELIMIT = 0xC8
|
||||
};
|
||||
|
||||
/* 45 */
|
||||
typedef struct KClassToken
|
||||
{
|
||||
@@ -540,6 +572,20 @@ typedef struct KBlockInfo
|
||||
u32 pageCount;
|
||||
} KBlockInfo;
|
||||
|
||||
typedef struct KSharedMemory
|
||||
{
|
||||
KAutoObject autoObject;
|
||||
KLinkedList ownedKBlockInfo;
|
||||
union KProcess *owner;
|
||||
u32 ownerPermissions;
|
||||
u32 otherPermissions;
|
||||
u8 isBlockInfoGenerated;
|
||||
s8 allBlockInfoGenerated;
|
||||
u8 unknown_1;
|
||||
u8 unknown_2;
|
||||
u32 address;
|
||||
} KSharedMemory;
|
||||
|
||||
/* 25 */
|
||||
typedef struct KMemoryBlock
|
||||
{
|
||||
@@ -1037,10 +1083,26 @@ typedef struct KProcess##sys\
|
||||
KThread *mainThread;\
|
||||
u32 interruptEnabledFlags[4];\
|
||||
KProcessHandleTable handleTable;\
|
||||
u8 gap234[52];\
|
||||
/* Custom fields for plugin system
|
||||
{ */ \
|
||||
u32 customFlags; /* see KProcess_CustomFlags enum below */ \
|
||||
Handle onMemoryLayoutChangeEvent;\
|
||||
Handle onProcessExitEvent;\
|
||||
Handle resumeProcessExitEvent;\
|
||||
/* } */ \
|
||||
u8 gap234[36];\
|
||||
u64 unused;\
|
||||
} KProcess##sys;
|
||||
|
||||
enum KProcess_CustomFlags
|
||||
{
|
||||
ForceRWXPages = 1 << 0,
|
||||
SignalOnMemLayoutChanges = 1 << 1,
|
||||
SignalOnExit = 1 << 2,
|
||||
|
||||
MemLayoutChanged = 1 << 16
|
||||
};
|
||||
|
||||
INSTANCIATE_KPROCESS(N3DS);
|
||||
INSTANCIATE_KPROCESS(O3DS8x);
|
||||
INSTANCIATE_KPROCESS(O3DSPre8x);
|
||||
@@ -1126,11 +1188,11 @@ typedef union KCacheMaintenanceInterruptEvent
|
||||
|
||||
typedef struct FcramLayout
|
||||
{
|
||||
void *applicationAddr;
|
||||
u32 applicationAddr;
|
||||
u32 applicationSize;
|
||||
void *systemAddr;
|
||||
u32 systemAddr;
|
||||
u32 systemSize;
|
||||
void *baseAddr;
|
||||
u32 baseAddr;
|
||||
u32 baseSize;
|
||||
} FcramLayout;
|
||||
|
||||
@@ -1138,15 +1200,15 @@ extern bool isN3DS;
|
||||
extern void *officialSVCs[0x7E];
|
||||
|
||||
#define KPROCESSRELATED_OFFSETOFF(classname, field) (isN3DS ? offsetof(classname##N3DS, field) :\
|
||||
((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? offsetof(classname##O3DS8x, field) :\
|
||||
((GET_VERSION_MINOR(kernelVersion) >= 44) ? offsetof(classname##O3DS8x, field) :\
|
||||
offsetof(classname##O3DSPre8x, field)))
|
||||
|
||||
#define KPROCESSRELATED_GET_PTR(obj, field) (isN3DS ? &(obj)->N3DS.field :\
|
||||
((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? &(obj)->O3DS8x.field :\
|
||||
((GET_VERSION_MINOR(kernelVersion) >= 44) ? &(obj)->O3DS8x.field :\
|
||||
&(obj)->O3DSPre8x.field))
|
||||
|
||||
#define KPROCESSRELATED_GET_PTR_TYPE(type, obj, field) (isN3DS ? (type *)(&(obj)->N3DS.field) :\
|
||||
((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? (type *)(&(obj)->O3DS8x.field) :\
|
||||
((GET_VERSION_MINOR(kernelVersion) >= 44) ? (type *)(&(obj)->O3DS8x.field) :\
|
||||
(type *)(&(obj)->O3DSPre8x.field)))
|
||||
|
||||
#define KPROCESS_OFFSETOF(field) KPROCESSRELATED_OFFSETOFF(KProcess, field)
|
||||
@@ -1189,7 +1251,7 @@ static inline KDebug *debugOfProcess(KProcess *process)
|
||||
static inline const char *classNameOfAutoObject(KAutoObject *object)
|
||||
{
|
||||
const char *name;
|
||||
if(kernelVersion >= SYSTEM_VERSION(2, 46, 0))
|
||||
if(GET_VERSION_MINOR(kernelVersion) >= 46)
|
||||
{
|
||||
KClassToken tok;
|
||||
object->vtable->GetClassToken(&tok, object);
|
||||
@@ -1205,7 +1267,7 @@ extern Result (*KProcessHandleTable__CreateHandle)(KProcessHandleTable *this, Ha
|
||||
static inline Result createHandleForProcess(Handle *out, KProcess *process, KAutoObject *obj)
|
||||
{
|
||||
u8 token;
|
||||
if(kernelVersion >= SYSTEM_VERSION(2, 46, 0))
|
||||
if(GET_VERSION_MINOR(kernelVersion) >= 46)
|
||||
{
|
||||
KClassToken tok;
|
||||
obj->vtable->GetClassToken(&tok, obj);
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
* * Requiring preservation of specified reasonable legal notices or
|
||||
* author attributions in that material or in the Appropriate Legal
|
||||
* Notices displayed by works containing it.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
void *memcpy(void *dest, const void *src, u32 size) USED;
|
||||
int memcmp(const void *buf1, const void *buf2, u32 size) USED;
|
||||
void *memset(void *dest, u32 value, u32 size) USED; // thanks binutils for the nice bug involving memset.
|
||||
void *memset32(void *dest, u32 value, u32 size);
|
||||
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize);
|
||||
char *strcpy(char *dest, const char *src);
|
||||
char *strncpy(char *dest, const char *src, u32 size);
|
||||
s32 strnlen(const char *string, s32 maxlen);
|
||||
s32 strlen(const char *string);
|
||||
s32 strcmp(const char *str1, const char *str2);
|
||||
s32 strncmp(const char *str1, const char *str2, u32 size);
|
||||
void hexItoa(u64 number, char *out, u32 digits, bool uppercase);
|
||||
129
k11_extension/include/mmu.h
Normal file
129
k11_extension/include/mmu.h
Normal file
@@ -0,0 +1,129 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "kernel.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 bits1_0 : 2; ///< 0b00
|
||||
} Desc_TranslationFault;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 bits1_0 : 2; ///< 0b01
|
||||
u32 sbz : 3;
|
||||
u32 domain : 4;
|
||||
u32 p : 1;
|
||||
u32 addr : 21;
|
||||
} Desc_CoarsePageTable;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 bits1_0 : 2; ///< 0b10
|
||||
u32 b : 1;
|
||||
u32 c : 1;
|
||||
u32 xn : 1;
|
||||
u32 domain : 4;
|
||||
u32 p : 1;
|
||||
u32 ap : 2;
|
||||
u32 tex : 3;
|
||||
u32 apx : 1;
|
||||
u32 s : 1;
|
||||
u32 ng : 1;
|
||||
u32 bit18 : 1; ///< 0
|
||||
u32 sbz : 1;
|
||||
u32 addr : 12;
|
||||
} Desc_Section;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 bits1_0 : 2; ///< 0b10
|
||||
u32 b : 1;
|
||||
u32 c : 1;
|
||||
u32 xn : 1;
|
||||
u32 domain : 4;
|
||||
u32 p : 1;
|
||||
u32 ap : 2;
|
||||
u32 tex : 3;
|
||||
u32 sbz : 3;
|
||||
u32 bit18 : 1; ///< 1
|
||||
u32 sbz2 : 5;
|
||||
u32 addr : 8;
|
||||
} Desc_Supersection;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 bits1_0 : 2; ///< 0b11
|
||||
} Desc_Reserved;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 bits1_0 : 2; ///< 0b01
|
||||
u32 b : 1;
|
||||
u32 c : 1;
|
||||
u32 ap : 2;
|
||||
u32 sbz : 3;
|
||||
u32 apx : 1;
|
||||
u32 s : 1;
|
||||
u32 ng : 1;
|
||||
u32 tex : 3;
|
||||
u32 xn : 1;
|
||||
u32 addr : 16;
|
||||
} Desc_LargePage;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 xn : 1;
|
||||
u32 bit1 : 1; ///< 1
|
||||
u32 b : 1;
|
||||
u32 c : 1;
|
||||
u32 ap : 2;
|
||||
u32 tex : 3;
|
||||
u32 apx : 1;
|
||||
u32 s : 1;
|
||||
u32 ng : 1;
|
||||
u32 addr : 20;
|
||||
} Desc_SmallPage;
|
||||
|
||||
typedef union
|
||||
{
|
||||
u32 raw;
|
||||
|
||||
Desc_TranslationFault translationFault;
|
||||
Desc_CoarsePageTable coarsePageTable;
|
||||
Desc_Section section;
|
||||
Desc_Supersection supersection;
|
||||
Desc_Reserved reserved;
|
||||
|
||||
} L1Descriptor;
|
||||
|
||||
typedef union
|
||||
{
|
||||
u32 raw;
|
||||
|
||||
Desc_TranslationFault translationFault;
|
||||
Desc_LargePage largePage;
|
||||
Desc_SmallPage smallPage;
|
||||
} L2Descriptor;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
Descriptor_TranslationFault,
|
||||
Descriptor_CoarsePageTable,
|
||||
Descriptor_Section,
|
||||
Descriptor_Supersection,
|
||||
Descriptor_Reserved,
|
||||
Descriptor_LargePage,
|
||||
Descriptor_SmallPage
|
||||
} DescType;
|
||||
|
||||
void L1MMUTable__RWXForAll(u32 *table);
|
||||
void L2MMUTable__RWXForAll(u32 *table);
|
||||
u32 L1MMUTable__GetPAFromVA(u32 *table, u32 va);
|
||||
u32 L2MMUTable__GetPAFromVA(u32 *table, u32 va);
|
||||
u32 L1MMUTable__GetAddressUserPerm(u32 *table, u32 va);
|
||||
u32 L2MMUTable__GetAddressUserPerm(u32 *table, u32 va);
|
||||
|
||||
void KProcessHwInfo__SetMMUTableToRWX(KProcessHwInfo *hwInfo);
|
||||
u32 KProcessHwInfo__GetPAFromVA(KProcessHwInfo *hwInfo, u32 va);
|
||||
u32 KProcessHwInfo__GetAddressUserPerm(KProcessHwInfo *hwInfo, u32 va);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user