Compare commits

..

269 Commits

Author SHA1 Message Date
Aurora
1182d3a627 Fix #1050 2018-03-23 02:49:16 +01:00
TuxSH
938cb6492f Revert "Revert "Switched from mapping target process memory to svcReadProcessMemory & svcWriteProcessMemory functions.""
This reverts commit 1fd689f5da.
2018-03-20 01:11:49 +01:00
TuxSH
fed62855cb Merge pull request #1000 from duckbill007/master
Gateshark cheats support
2018-03-20 01:00:25 +01:00
Mikaela Szekely
4f54596658 Implement #940 (#1043)
Thanks @Qyriad ^^
2018-03-04 00:45:47 +01:00
Aurora Wright
0b41ed04d5 Simplify loadNintendoFirm after the previous commit 2018-02-09 05:09:43 +01:00
Aurora Wright
9509a86998 Force using the external FIRM if CTRNAND couldn't be mounted or the CTRNAND FIRM has issues 2018-02-05 03:47:43 +01:00
Duckbill
6d4d80a798 Merge remote-tracking branch 'upstream/master' 2018-01-19 17:38:57 +03:00
TuxSH
76d274cfe2 getmemregions: userland never exceeds 0x40000000 2018-01-19 01:42:53 +01:00
TuxSH
ccf13be964 Merge pull request #1010 from Nanquitas/input-redirection-sockupdate
InputRedirection: check service existence instead of using OpenProcessByName
2018-01-19 01:30:15 +01:00
TuxSH
e36b27ccf0 Merge pull request #1012 from Nanquitas/rosalina-freeze-fix
Rosalina: fix freeze when attempting to open Rosalina before the syst…
2018-01-19 01:29:58 +01:00
TuxSH
34c80ad476 Merge pull request #1009 from Nanquitas/gdb-list-memregion
gdb: new getmemregions command
2018-01-19 01:28:53 +01:00
TuxSH
97ae106d8e Merge pull request #1011 from Nanquitas/patch-2
sock_util: remove unneeded check
2018-01-19 01:28:08 +01:00
Nanquitas
7cb74b74d7 Rosalina: fix freeze when attempting to open Rosalina before the system finished to boot 2018-01-18 23:39:47 +01:00
Nanquitas
337205eb08 sock_util: remove unneeded check
We loop while (server_sockfd == -1) so it's safe to assume that (server_sockfd != -1) once out of the loop.
2018-01-18 22:57:46 +01:00
Nanquitas
f36977017b InputRedirection: check service existence instead of using OpenProcessByName 2018-01-18 20:44:54 +01:00
Nanquitas
e40b547bb6 gdb: new getmemregions command 2018-01-18 17:23:43 +01:00
Duckbill
1fd689f5da Revert "Switched from mapping target process memory to svcReadProcessMemory & svcWriteProcessMemory functions."
This reverts commit c5c8dca14c.
2018-01-16 09:54:55 +03:00
Duckbill
c5c8dca14c Switched from mapping target process memory to svcReadProcessMemory & svcWriteProcessMemory functions. 2018-01-15 21:29:05 +03:00
TuxSH
11f820efa7 Check service existence before GetServiceHandle 2018-01-15 02:52:50 +01:00
TuxSH
9074688491 Make srvGetServiceHandle non-blocking if service port is full in all cases 2018-01-15 02:27:07 +01:00
Duckbill
1de27c54f1 Fix range checks 2018-01-13 16:02:54 +03:00
Duckbill
3e67e64faa Fixes after review on github 2018-01-13 13:51:28 +03:00
TuxSH
553f8d2533 Remove lto for sysmodules 2018-01-12 11:20:17 +01:00
Duckbill
ec7ae35da1 Fixes for masked 16-bit cheat opcodes, based on existing cheats. 2018-01-12 10:46:50 +03:00
Duckbill
7e8da0d236 Possible out of bounds fix 2018-01-10 09:53:36 +03:00
Duckbill
b3e6561072 Merge remote-tracking branch 'upstream/master' 2018-01-06 12:29:08 +03:00
Aurora Wright
41f32ed983 Remove the need for hardcoding the horizontal positions for the "x"s in multiple choice options 2018-01-05 19:38:58 +01:00
TuxSH
bbadf840ef struct fb shouldn't be packed 2018-01-04 22:12:31 +01:00
TuxSH
acc50aae46 Merge branch 'master' of github.com:AuroraWright/Luma3DS 2018-01-04 18:41:14 +01:00
TuxSH
6a68a77973 Rewrite the ARM9 exception handlers, ...
- Fix patchArm9ExceptionHandlersInstall for older versions

- Fix some bugs in the ARM11 exception handlers

- Other, minor, changes
2018-01-04 18:40:11 +01:00
Duckbill
0f4d66dd61 Try to load cheats if there aren't any on every open of cheats menu. 2018-01-03 11:48:10 +03:00
Duckbill
d28642d2c3 More range checks and separate code and heap allocation 2018-01-03 00:27:44 +03:00
Duckbill
ca4685cc42 Range checks added 2018-01-02 14:23:45 +03:00
Aurora
522f10582d Merge pull request #995 from joel16/master
Update MCU::HWC functions with latest changes from ctrulib
2018-01-01 18:07:32 +01:00
Joel16
239d113177 Update mcu functions with changes from ctrulib 2018-01-01 11:05:22 -06:00
Duckbill
fd80294bf2 Fix buffer overflow in case of very long cheats.txt file 2017-12-31 11:26:18 +03:00
Duckbill
b379d83469 Merge remote-tracking branch 'upstream/master' 2017-12-31 11:16:44 +03:00
Aurora
27f352fdf1 Merge pull request #991 from Qyriad/master
Implement #989: Add configurable splash duration
2017-12-29 05:08:22 +01:00
Mikaela RJ Szekely
bfec874a7c Add colon in option that I forgot 2017-12-28 22:02:06 -05:00
Mikaela RJ Szekely
93561003e8 Implement #989: Add configurable splash duration 2017-12-28 21:50:06 -05:00
TuxSH
1572bfd989 [sm] Fix process unregistering logic bug (fixes #984)
In this case pm+sm were supposed to automatically unregister ro's services (the kernel can close a dying process's handle automatically). Not doing this apparently induced a reference leak of DevMenu's as a process, preventing it to be destroyed and the memory allocation reslimit counter to be updated by KProcess's destructor accordingly.
2017-12-27 19:30:57 +01:00
Duckbill
cb945612a3 Remove ast empty cheat from list 2017-12-25 14:16:57 +03:00
Duckbill
1b440f7f3b Skip empty cheats 2017-12-25 13:57:20 +03:00
Duckbill
78791f7b66 Paging fixes 2017-12-25 13:45:09 +03:00
Duckbill
5def0c18e2 Cheat file format changed from binary to plaintext 2017-12-22 14:46:46 +03:00
Duckbill
0e67b0f026 Moved key combo calculation to loading cheat phase 2017-12-22 12:39:09 +03:00
Duckbill
8052946517 Cheats array repleced by continous buffer 2017-12-22 12:17:45 +03:00
Duckbill
b6d6cc9750 Cheat implementations 2017-12-21 20:14:04 +03:00
TuxSH
2a840f2c79 Minor date/time conversion loop style fixes 2017-12-19 02:32:51 +01:00
TuxSH
4eaf791849 Merge pull request #937 from Hayleia/timestamped-screenshots
screenshots use timestamps as name
2017-12-19 02:15:07 +01:00
Aurora Wright
be0f50b19c Disable poweroff when shell closed on NTRboothax altogether to prevent issues with unstable magnets 2017-12-18 21:02:41 +01:00
Aurora Wright
f30b7b9fb3 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-12-18 20:56:45 +01:00
Aurora Wright
6a0f332e3c Shutdown when waiting for button presses if the shell is closed, except when coming from a NTRboothax boot 2017-12-18 20:56:32 +01:00
TuxSH
16530d3a52 Merge pull request #972 from LiquidFenrir/ramviewer-fix
fix mistake, processes viewed were attached even if debugger was off
2017-12-18 07:13:13 +01:00
Aurora Wright
20af9c6750 Fix issue reported in
f27cdb4543\#commitcomment-24611141, simplify 56e54cd110
2017-12-18 04:27:11 +01:00
LiquidFenrir
fee9f6b427 forgot to return, made processes viewed attached even though the debugger wasnt enabled 2017-12-17 19:31:05 +01:00
TuxSH
57d03d6333 Merge pull request #916 from LiquidFenrir/ramviewer-fix
Several ramviewer improvements
2017-12-17 03:31:36 +01:00
LiquidFenrir
0075fe2aa0 work with processes with code starting at 0x14000000 2017-12-16 19:26:55 +01:00
LiquidFenrir
d54417ac0a explicit casting 2017-12-16 19:26:27 +01:00
LiquidFenrir
648801d432 make pressing X accidentally twice less punitive 2017-12-16 04:30:40 +01:00
LiquidFenrir
2be2826b0b detect jumping address and change mode accordingly 2017-12-16 04:14:21 +01:00
LiquidFenrir
37a9fa1bf4 work again with heapless processes, and show wether you're currently viewing heap or code on screen (apart from the address) 2017-12-14 17:03:13 +01:00
LiquidFenrir
65af93c8ce other display for entering goto 2017-12-07 22:07:53 +01:00
LiquidFenrir
8353b84944 fix dump filename 2017-12-07 20:07:44 +01:00
LiquidFenrir
d6a89db495 make use of values defined in draw.h 2017-12-07 19:56:36 +01:00
LiquidFenrir
f156aa8cdb add dumper
mostly a copy of the screenshotting function/from #937
2017-12-07 19:53:44 +01:00
LiquidFenrir
f9adbcc9d9 fix same-name variables 2017-12-07 18:23:29 +01:00
TuxSH
cf8696ac70 Disable non-process memory access by default (see below), remove IDA 6.8 support...
The physical memory access "bit31" mapping (0--0x30000000 => 0x80000000--0xB0000000) as well as privileged (kernel) mappings confuse debugger clients like IDA's which interpret the value of the registers.
Access to those mappings can be toggled using "monitor toggleextmemaccess" instead (issue reported by @Nanquitas). Closes #943.

Additionally, support for the buggy IDA 6.8's buggy gdb client was removed. Please use IDA 7.0 or higher.

P.S: IDA 7.0 added client support for no-ack mode (Debugging options > Set specific options), which should be enabled to make debugging twice as smooth. "Use stepping support" should be unchecked.
2017-11-26 02:18:59 +01:00
Yuuki Hikari
9c5766f649 Merge pull request #945 from astronautlevel2/master
Switch to APT_ResetHardwareAsync() for reboot (Closes #831), fix #831
2017-11-23 20:46:01 -05:00
Alex Taber
c9701f93b9 Switch to APT_ResetHardwareAsync() for reboot (Closes #831) 2017-11-23 20:32:26 -05:00
Aurora Wright
56e54cd110 Fix https://github.com/AuroraWright/Luma3DS/issues/921 2017-11-22 19:03:39 +01:00
TuxSH
55836b48af Merge pull request #942 from Nanquitas/watchpoint-fix
Fix the impossibility to set a second watchpoint
2017-11-22 16:17:53 +01:00
Asuka Amari
09bfdb9ee1 removed unused variable 2017-11-22 07:03:00 +01:00
Nanquitas
1c2e8dec11 Fix the impossibility to set a second watchpoint 2017-11-22 03:37:23 +01:00
TuxSH
506b16db37 Fix watchpoints handling (huge thanks to @Nanquitas) 2017-11-22 01:24:35 +01:00
Asuka Amari
8f03234e58 screenshots now use timestamps as name
Instead of being called top_XXXX.bmp where XXXX means nothing,
screenshots are now called YYYY-MM-DD_HH-MM-SS.mmm_top.bmp (and same
idea for bot and top_right).

First obvious consequence, this is easier to manage in a file browser.
Now you have screenshots grouped by time, and you also have the 2 or 3
related screenshots (top, bot, top_right) close one to another.

Another consequence is that there is no need to go through existing
screenshots to find an unused number. Now osGetTime takes care of
everything. And going through files was a very time consuming process.
Now screenshots only need 4 (or 6 if 3D) seconds to be saved (instead of
40 seconds if you had 200 screenshots in your directory already).

Conflicts may happen when people change the date and time on their 3DS,
but that's why I even included milliseconds in the timestamp. People
don't set date and time everyday and they'd be unlucky to take a
screenshot at the exact time, milliseconds included, as another
screenshot right after setting the time one hour earlier...

Source for converting seconds since 1970 (or 1900...) to date and time:
https://stackoverflow.com/questions/21593692/
2017-11-18 16:37:35 +01:00
TuxSH
44b5e10323 Fix N3DS menu entry 2017-11-10 20:51:52 +01:00
LiquidFenrir
48303604b0 show address instead of offset when jumping 2017-11-05 06:56:54 +01:00
LiquidFenrir
ab2ddbc2ee fix visible blank
if jumping too close to the end, the cursor won't be at the top to avoid the blank
2017-11-05 06:48:56 +01:00
LiquidFenrir
9495bf30bf make jumping put the cursor at the top row
downside: when jumping near the end, a blank is visible
2017-11-05 06:30:41 +01:00
TuxSH
a4899a1bec Remove redundant variables in Makefile 2017-11-03 19:03:17 +01:00
LiquidFenrir
882c6cf0d4 show the "main" address to distinguish between heap and code 2017-11-03 02:19:15 +01:00
LiquidFenrir
a5e18c82d1 reset scrolling when changing modes to avoid problems when the sizes dont match 2017-11-03 02:15:28 +01:00
TuxSH
22a8661fe1 Always patch FS and P9, remove SM service checks 2017-11-02 21:52:14 +01:00
TuxSH
8258a98647 Integrate 3ds_pxi and 3ds_sm 2017-11-02 15:11:55 +01:00
LiquidFenrir
76dde0e6db Add ram viewer/editor (#877)
Huge thanks to @LiquidFenrir
2017-10-24 18:35:15 +02:00
Ian Burgwin
1a39cb27e4 fix discord invite link 2017-10-14 10:10:03 -07:00
Aurora Wright
95d2d0a6bd Update makefile 2017-10-12 20:56:47 +02:00
Aurora Wright
98d4345858 Remove unneeded check 2017-10-07 23:04:55 +02:00
Aurora Wright
1e4431dcc9 Fix ARM9 exceptions displaying ARM11-specific info 2017-10-07 20:59:21 +02:00
Aurora Wright
348b175994 Fix some fault statuses overlapping to a new line 2017-10-05 19:55:21 +02:00
Aurora Wright
76f057dafb Remove friends patch as it's useless 2017-10-05 18:45:06 +02:00
Aurora Wright
188400c5a9 Use ctrulib functions for mcu/battery level 2017-10-05 18:41:11 +02:00
Aurora
a74d9c6d3e Merge pull request #878 from Margen67/master
Update README.md
2017-10-03 01:19:26 +02:00
Margen67
f8bcfb2f58 Update README.md
Add armips buildbot link.
Other minor changes.
2017-09-26 14:44:14 -07:00
TuxSH
d63fc2bc82 Fix latest commit 2017-09-24 19:31:38 +02:00
TuxSH
8e31784996 Fix thumb breakpoint handling 2017-09-24 17:58:23 +02:00
Aurora Wright
f27cdb4543 Also fix RBGA4 (untested) 2017-09-23 22:34:28 +02:00
Aurora
a39adc8ac1 Merge pull request #869 from Streetwalrus/pxfmt
Fix RGB5_A1 conversion
2017-09-23 22:27:24 +02:00
Dan Elkouby
97bef66018 Fix RGB5_A1 conversion 2017-09-23 15:01:11 +03:00
Aurora Wright
bb5518b0f6 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-09-22 18:05:10 +02:00
Aurora Wright
ac73a96ce2 Set default firmSource for CTRNAND mounting in crypto.c, move CTRNAND mounting for SD mode to firm.c 2017-09-22 18:05:03 +02:00
Ian Burgwin
7075004e58 Merge pull request #866 from Margen67/master
Update ISSUE_TEMPLATE.md
2017-09-21 14:04:38 -07:00
Margen67
ddf8ba5116 Update ISSUE_TEMPLATE.md 2017-09-21 14:02:09 -07:00
Aurora Wright
f46773ba64 Stub isTitleAllowed 2017-09-20 01:36:02 +02:00
Aurora Wright
f67d333457 Update fpdver 2017-09-19 14:46:42 +02:00
Aurora Wright
4116c1e00f Update FIRM loading magic, only deinit LCDs if they are inited, fix ntrboot naming 2017-09-07 05:24:43 +02:00
Aurora Wright
bc1aa15dd7 Add more checks, make the emuNAND SD check only occur when emuNAND is being booted 2017-08-28 14:46:18 +02:00
Aurora Wright
ecd27f7eaa Fix diskio indentation 2017-08-28 02:54:56 +02:00
Aurora Wright
618ce671ac Fix previous commit, deinit screens on ARM9 exception, add check for write protect switch on writing operations 2017-08-28 02:43:12 +02:00
Hikari-chin
2a6a655804 Error if emuNAND is booted while the SD card is write protected 2017-08-27 16:20:17 -04:00
Aurora Wright
33436ae2a6 Fix derp with previous commit 2017-08-27 16:24:04 +02:00
Aurora Wright
9f2b66ac51 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-08-27 16:20:52 +02:00
Aurora Wright
df93e4797e Refactor boot mode/firmlaunch detection, fix firmlaunch from FIRM boots 2017-08-27 16:20:41 +02:00
Aurora Wright
538d1dec77 Minor style stuff 2017-08-21 19:33:31 +02:00
TuxSH
2492c8273a Fix exception display 2017-08-21 19:26:17 +02:00
Aurora Wright
d358df48a6 Wait for ntrboot buttons not to be held 2017-08-20 18:23:50 +02:00
Aurora Wright
f619dafff1 Added displaying boot source and loader on the bottom screen in the config 2017-08-20 17:00:47 +02:00
Aurora Wright
0419fc4e30 Reinstate ntrboot display in config 2017-08-20 16:16:20 +02:00
Aurora Wright
13317b9548 Change ntrboot behavior, turn Luma into a chainloader when used as ntrboot FIRM as it can not be functional, disable FIRM protection when ran from ntrboot B9S 2017-08-20 16:08:54 +02:00
Aurora Wright
18db70a669 Minor style stuff 2017-08-19 02:54:38 +02:00
TuxSH
f79923814d Detect NTRCARD and FIRM1 boot sources properly...
Always display the configuration menu if booted from NTRCARD (because it's painful to get to otherwise -- even if b9s has a 2s delay), with the mention "Booted from NTRCARD" in the title.
2017-08-19 01:40:55 +02:00
Aurora Wright
c92de03a5f Always erase exception dump in memory 2017-08-17 17:38:42 +02:00
Aurora Wright
3f356da879 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-08-17 17:33:37 +02:00
Aurora Wright
9efac01c86 Fix derp 2017-08-17 17:33:18 +02:00
TuxSH
ca2622af7c Fix #778 2017-08-16 23:46:36 +02:00
Aurora Wright
aa8e0bda8c Update FatFs to R0.13 2017-08-16 19:37:39 +02:00
TuxSH
c79f11ee99 Change exception dump parser directory structure 2017-08-16 19:23:04 +02:00
Aurora Wright
04d0770b90 Add missing info for data aborts in the exception parser and turn it into a pip module 2017-08-16 18:59:12 +02:00
Aurora Wright
fbf8a1b6d9 Minor code syntax stuff 2017-08-16 18:04:22 +02:00
Aurora Wright
a3cb6a622d Merge https://github.com/AuroraWright/Luma3DS/pull/793 , clarify the exception dumps' paths 2017-08-16 16:55:07 +02:00
Aurora Wright
0790a3ceb3 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-08-16 15:50:06 +02:00
Aurora Wright
4fa12f90fc Fix derp 2017-08-16 15:49:57 +02:00
TuxSH
d5d56e7634 Merge pull request #790 from WinterMute/windows-path-fix
Don't fix already transformed $DEVKITARM variable
2017-08-15 15:20:27 +02:00
TuxSH
a964089df4 Merge pull request #792 from Nanquitas/master
Exceptions: display more infos on screen (status, far, access type)
2017-08-15 15:20:17 +02:00
Dave Murphy
5fd5b4da89 Don't fix already transformed $DEVKITARM variable 2017-08-15 14:15:34 +01:00
Hikari-chin
322a7050aa Fix #791 2017-08-15 09:01:48 -04:00
Nanquitas
b7f4ac02c8 Exceptions: display more infos on screen (status, far, access type) 2017-08-15 14:09:14 +02:00
TuxSH
009f61a8b6 Merge pull request #787 from Nanquitas/master
exception_parser.py: display the fault status source
2017-08-15 02:44:18 +02:00
Nanquitas
26d0cafb39 exception_parser.py: display the fault status source 2017-08-15 00:51:20 +02:00
TuxSH
bd1d4a77fe Merge pull request #783 from Nanquitas/patch-1
Watchpoints: fix read DSCR to enable MonitorMode
2017-08-14 19:04:15 +02:00
Nanquitas
f235bc83a8 Watchpoints: fix read DSCR to enable MonitorMode 2017-08-14 16:10:50 +02:00
Aurora Wright
9c6b540905 Do not hardcode FBs in ARM11, do not set FBs twice on screen init 2017-08-13 17:36:31 +02:00
TuxSH
d2e911a58e Merge pull request #781 from profi200/master
Revert 9273a88d and make it not freeze the GPU/LCD hardware.
2017-08-13 16:00:45 +02:00
TuxSH
9344a7b434 Fix default FB addresses 2017-08-13 16:00:35 +02:00
profi200
cd194fa5b2 Revert 9273a88d and make it not freeze the GPU/LCD hardware. 2017-08-13 14:50:14 +02:00
Aurora Wright
49c0ab65df Check r0 and r1 too for firm0 detection 2017-08-11 23:54:28 +02:00
Aurora Wright
8f9c1305e4 Reinstate unsupported loader error 2017-08-11 23:48:32 +02:00
TuxSH
d4193ec11d Attempt to detect booting from firm 2017-08-11 23:33:21 +02:00
TuxSH
6b9b0472bc Merge pull request #775 from LiquidFenrir/nwmcheck
Add a warning when nwm isn't running
2017-08-11 23:00:07 +02:00
LiquidFenrir
7e74258363 check if nwm is running to fix https://github.com/AuroraWright/Luma3DS/issues/774 2017-08-11 04:29:38 +02:00
Aurora Wright
f6483ec602 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-08-07 21:20:18 +02:00
Aurora Wright
36c1da1d61 Add mention of exheaders in the Enable game patching description 2017-08-07 21:20:08 +02:00
Stary 2001
6bcb1f8679 Merge pull request #763 from Streetwalrus/ir-title
Fix input redirection title index in the menu
2017-08-06 22:15:21 +01:00
Dan Elkouby
62932a9639 Fix input redirection title index in the menu
This option is the third, not the fourth, and toggling it will override
the "save settings" option's title instead.
2017-08-06 23:56:00 +03:00
Hikari-chin
a4629e4b65 Cleaned up and rearranged the Rosalina menu in preparation for future features 2017-08-01 17:38:48 +02:00
Aurora Wright
a0c2b43b34 Implement loading of exheaders from SD/CTRNAND (must be called luma/titles/TITLEID/exheader.bin), thanks to @HiddenRambler! 2017-08-01 17:38:23 +02:00
TuxSH
3907c46980 Follow ARM's documentation on hw watchpoints to the letter 2017-07-20 00:56:08 +02:00
TuxSH
7e7ab124a3 Log "logged" errdisp messages in /luma/errdisp.txt, fixes #707 2017-07-19 00:59:47 +02:00
TuxSH
cfc6cf24bf Some kext refactoring 2017-07-16 18:58:20 +02:00
TuxSH
46e9cb6b23 Fix fallthrough bug 2017-07-16 13:29:02 +02:00
TuxSH
ba14efe1f4 Suppress future -Wimplicit-fallthrough=3 warnings 2017-07-15 00:41:42 +02:00
TuxSH
3d8f62d38f Fix MaxCpuTime for 3dsx 2017-07-09 22:14:00 +02:00
Hikari-chin
3edaf0af64 Whoops 2017-07-09 14:36:06 -04:00
Aurora Wright
9273a88db7 It seems FB setup needs to be done first 2017-07-09 19:21:12 +02:00
Aurora Wright
37ba2c15de Reinstate framebuffer setup on initScreens to allow old Luma to be chainloaded if FB address changes in b9s/new Luma, remove useless clearScreens for the alternate FBs after the first init 2017-07-09 19:06:42 +02:00
Aurora Wright
557f2057f7 Fix spacing 2017-07-06 18:09:18 +02:00
Aurora Wright
6b5cc93780 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-07-06 17:29:43 +02:00
Aurora Wright
9760191af8 Fix conflict between emunand selection and payload booting when "Autoboot EmuNAND" is checked, you now need to press L + DPad to boot payloads if that option is checked 2017-07-06 17:29:38 +02:00
TuxSH
8845e4dd20 Merge pull request #704 from Hikari-chin/master
LED toggle switch in Rosalina's misc menu + updated README
2017-07-05 19:26:56 +02:00
Yuuki Hikari
8cf823f548 Update README.md 2017-07-05 02:13:03 -04:00
Hikari-chin
2538769f3a Added LED toggling from the Rosalina misc. menu 2017-07-04 23:50:40 -04:00
Aurora Wright
89fca38807 Merge master into local branch 2017-07-05 01:37:36 +02:00
Aurora Wright
dcc0eed69c Fix LayeredFS for games like Pokemon Art Academy which mistakenly use two forward slashes after the mountpoint 2017-07-05 01:31:04 +02:00
Yuuki Hikari
817475257e Merge pull request #700 from LiquidFenrir/wifi-toggle
Add wireless toggling in rosalina
2017-07-04 15:09:16 -04:00
LiquidFenrir
f2861058ba add wireless toggling in rosalina
https://github.com/AuroraWright/Luma3DS/issues/619#issuecomment-309239178

ligne 353: CFG11_WIFICNT, nothing includes it in rosalina so I hardcoded it here
ligne 363: could also use svc 0x5A (SetWifiEnabled) but not sure how
2017-07-04 18:35:55 +02:00
TuxSH
5d2a7315d5 Fix SetWifiEnabled 2017-07-03 19:28:34 +02:00
TuxSH
1520ab7555 Update ISSUE_TEMPLATE.md
7.1 => 8.1
2017-07-02 22:52:49 +02:00
Aurora Wright
d4d0fbd73b Re-add dir_build variable 2017-07-02 00:46:57 +02:00
Aurora Wright
ddb8e98e95 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-07-02 00:44:29 +02:00
Aurora Wright
fd69b4169f Use GNU/BSD agnostic syntax instead of detecting the OS (thanks @smartperson) 2017-07-02 00:44:14 +02:00
TuxSH
b48e0b5c5b Update ISSUE_TEMPLATE.md 2017-06-30 23:52:44 +02:00
TuxSH
31e2243c5c Update description for "enable game patching" 2017-06-28 21:59:57 +02:00
Aurora Wright
da0ee2e442 Fix external 3.x and 4.x FIRMs, fix 1.x and 2.x booting on dev units 2017-06-28 20:28:14 +02:00
Aurora Wright
b88dc9ac6a Only check in .text 2017-06-28 18:14:05 +02:00
Aurora Wright
9f78d7f62b Add region-free manuals patch 2017-06-28 17:37:12 +02:00
Aurora Wright
e67c6ed3ee Change pattern 2017-06-26 23:42:41 +02:00
Aurora Wright
2e111ca91b Revert "Revert "Merge pull request #662 from MerryMage/dsp-sig""
This reverts commit 62d51fd99d.
2017-06-26 23:39:28 +02:00
Aurora Wright
62d51fd99d Revert "Merge pull request #662 from MerryMage/dsp-sig"
This reverts commit a9289b1f21, reversing
changes made to d42e938232.
2017-06-26 22:06:10 +02:00
TuxSH
a9289b1f21 Merge pull request #662 from MerryMage/dsp-sig
Add a patch to disable DSP firmware signature check
2017-06-26 20:51:16 +02:00
Aurora Wright
d42e938232 Restore 7.1 max module size for NATIVE_FIRM 2017-06-26 19:03:57 +02:00
MerryMage
3d3dcb1f28 Add DSP signature check patch 2017-06-26 17:34:43 +01:00
Aurora Wright
82143212ce Remove the need for Homebrew and GNU tools on macOS 2017-06-26 18:32:33 +02:00
TuxSH
7246a2664e Move section0 to second quarter of VRAM 2017-06-26 17:41:40 +02:00
Aurora Wright
1291f2520a Fix derp 2017-06-26 17:11:00 +02:00
TuxSH
042ecf5343 Fix write-only hw watchpoint handling 2017-06-26 16:57:25 +02:00
Aurora Wright
6e54dcc24c Add macOS building support (you need to install coreutils and gnu-sed with homebrew) 2017-06-26 16:29:04 +02:00
TuxSH
91378ef3c1 Fix menu display bugs 2017-06-25 00:14:07 +02:00
Aurora Wright
0377cbd2b4 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-06-22 15:49:31 +02:00
Aurora Wright
786ecf4fe4 Remove some configbit math 2017-06-22 15:49:23 +02:00
TuxSH
0fbdee313f Merge branch 'master' of github.com:AuroraWright/Luma3DS 2017-06-20 21:24:52 +02:00
Aurora Wright
9b8e2b933d Add missing checks in getFreeK9Space 2017-06-20 19:56:34 +02:00
TuxSH
cc64ef9670 Take fb stride into account 2017-06-20 18:29:30 +02:00
TuxSH
31ff6a1da8 Clarify option 2017-06-20 17:39:11 +02:00
TuxSH
94532e9cea Halve the time necessary to take a screenshot 2017-06-20 16:14:36 +02:00
Aurora Wright
3f93bc5988 Support 3.x+ EmuNANDs and 3.x SysNANDs (partially), external FIRMs coming soonŧ 2017-06-19 18:13:59 +02:00
TuxSH
39ca23d609 Add qGetTLSAddr 2017-06-19 16:04:19 +02:00
TuxSH
47a9c1b576 Fix FS patch for 4.x 2017-06-19 15:34:51 +02:00
TuxSH
d819cfd58f Remove useless files 2017-06-19 15:21:15 +02:00
TuxSH
17828273a5 Revamp config format, add saving of Rosalina opt.
(menu combo & 3dsx title ID)
2017-06-18 22:31:21 +02:00
TuxSH
2363817265 Fix grey strides issue (maybe) 2017-06-17 01:52:08 +02:00
TuxSH
b31018ab17 Lower the priority of the Rosalina menu 2017-06-17 00:15:36 +02:00
TuxSH
c610ec3319 Virtually full support for 4.x sysNAND
(see also: previous commit)
2017-06-16 22:37:04 +02:00
TuxSH
b71dedccfc Full support for fw >= 6.x (tested)
Virtually full support for 5.x except that svcUnmapProcessMemoryEx will be forwarded to svcUnmapProcessMemory (both are equivalent for up to 64MB chunks)
2017-06-16 04:21:48 +02:00
TuxSH
9ccfacd06d Display IP in menus when either gdb/inputredir is enabled 2017-06-15 17:38:45 +02:00
TuxSH
12b561a27d Remove unused variables 2017-06-15 01:57:57 +02:00
TuxSH
cc41003e1c Fix exheader.h 2017-06-15 01:53:34 +02:00
TuxSH
3d534c9a81 Unschedule threads properly...
...instead of using a shitty yield when opening the Rosalina menu
2017-06-14 19:35:03 +02:00
TuxSH
24de7c5272 Fix indentation of gdb.c 2017-06-14 10:04:09 +02:00
TuxSH
a1b2ea2c5b Fix firmlaunch payload path bug 2017-06-14 02:05:32 +02:00
TuxSH
19d68b6df4 Adjust config mem values 2017-06-14 01:29:55 +02:00
TuxSH
2ab41dbd01 Fix firmlaunch bug 2017-06-13 23:08:32 +02:00
TuxSH
da30c0b0f0 Fix dfsr being displayed instead of fpexc 2017-06-13 02:53:53 +02:00
TuxSH
005684d865 Fix loader bugs
new-hbmenu now works with H&S, etc.
2017-06-13 02:37:27 +02:00
TuxSH
da1eff82ba Remove debugging line 2017-06-13 02:29:01 +02:00
TuxSH
a17311c955 Merge branch 'memregion-test' 2017-06-13 02:28:38 +02:00
TuxSH
e1d0602f25 Move the kext outside Rosalina
- Stability (tm)
- Boots 1s faster on N3DS
- (∩ ͡° ͜ʖ ͡°)⊃━☆゚
2017-06-13 02:00:41 +02:00
TuxSH
2ff9718510 Merge pull request #595 from Hikari-chin/master
Fix #593
2017-06-12 18:00:22 +02:00
Hikari-chin
33af9cfe09 Fix #593 2017-06-12 01:45:38 +00:00
Aurora
79709a7ae7 Merge pull request #594 from Margen67/master
Update issue template
2017-06-11 21:01:48 +02:00
Margen67
a796a70d01 Update issue template 2017-06-11 12:00:06 -07:00
TuxSH
53e2ef24f1 Refactor pattern for ir hook 2017-06-11 17:16:14 +01:00
Ezekiel Bethel
c0059c83ac inputredirection hook in ir:user cpp emulation => c-stick works in games now, also hook refactoring 2017-06-11 17:16:13 +01:00
Ezekiel Bethel
37eb21d297 poweroff/reboot for Rosalina misc. menu 2017-06-11 17:06:43 +01:00
Aurora Wright
52a18831a7 Minor style changes (2) 2017-06-10 03:06:16 +02:00
Aurora Wright
0d7cca7b20 Minor style changes 2017-06-10 02:55:55 +02:00
Aurora Wright
bea73c51ae Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-06-10 02:39:08 +02:00
Aurora Wright
0c68750056 Refactor payload loading, fix messy externs, add safety checks to Nintendo FIRMs, fix some Nintendo FIRMs not being loaded as payloads 2017-06-10 02:39:00 +02:00
TuxSH
ae8ea7da16 Revert PR due to breakage for a totally unrelated reason
(will be added back later)
2017-06-10 01:39:11 +02:00
TuxSH
69762c5dce Revert "Attempt fixing svcConnectToPortInitHook.s again"
This reverts commit 901d4992c0.
2017-06-09 20:48:01 +02:00
TuxSH
901d4992c0 Attempt fixing svcConnectToPortInitHook.s again 2017-06-09 18:10:02 +02:00
Aurora Wright
4d47d891d1 Fix max module size check, static-ify more strings 2017-06-09 17:29:26 +02:00
TuxSH
a7046909ec Use static const when appropriate 2017-06-09 14:26:51 +02:00
Aurora Wright
4bc95979de Revert #949d219c726e41cca84c873e7e200be14af13f63 (breaks building on *nix) 2017-06-09 13:44:04 +02:00
TuxSH
949d219c72 lolwut this fixes building on WSL
maybe memsearch is flasky on unaligned patterns, dunno
2017-06-09 05:00:38 +02:00
TuxSH
9a3d9aed30 Always enable ARM9 exceptions, update .gitignore 2017-06-09 02:31:14 +02:00
TuxSH
4d99143da0 Merge pull request #561 from SciresM/master
Add config option to disable exception vectors.
2017-06-09 00:17:14 +02:00
TuxSH
461035b212 Fix bug(s), refactor svcConnectToPortInitHook.s, cleanup 2017-06-08 21:35:41 +02:00
Michael Scire
0694ea8367 Add config option to disable exception vectors. 2017-06-07 17:48:30 -07:00
TuxSH
427a05997d Revert "Refactor fatalExceptionHandlers.s a bit"
This reverts commit 84d736c2eb.
2017-06-08 02:02:49 +02:00
TuxSH
84d736c2eb Refactor fatalExceptionHandlers.s a bit 2017-06-07 23:58:29 +02:00
TuxSH
a16d1ebe33 Refactor k11 main hook
Much less error-prone now.
2017-06-07 22:13:05 +02:00
Aurora Wright
43f3c84316 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-06-07 19:16:13 +02:00
Aurora Wright
44cafe3f46 Fix mismerges 2017-06-07 19:15:51 +02:00
TuxSH
76d7a035bd Fix country/state id spoofing 2017-06-07 01:06:39 +02:00
TuxSH
a5b638ae7b Fix uninitialized variable bugs 2017-06-06 21:04:13 +02:00
TuxSH
174089e4f3 Fix langemu bugs 2017-06-06 19:37:16 +02:00
TuxSH
4d219813fe Merge pull request #519 from sora10pls/master
Reference release notes in README.md
2017-06-06 02:52:32 +02:00
Aurora Wright
a798f453d2 Update gitignore 2017-06-06 02:17:58 +02:00
Aurora Wright
6ec21611c0 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-06-06 02:13:02 +02:00
Aurora Wright
31f4419eec Refactor screen functions, completely fix config not saving bug 2017-06-06 02:12:18 +02:00
Aurora Wright
60d136f9b5 Fix #491 2017-06-06 01:22:17 +02:00
TuxSH
0ba7f9dba0 Fix chainloader 2017-06-05 21:24:18 +02:00
TuxSH
0ac6db006a Work around a GDB bug (w/r/t packet size) 2017-06-05 21:23:17 +02:00
TuxSH
26dd61e4e6 Fix (work around) Nintendo own HM bug, GG Ninty 2017-06-05 20:28:44 +02:00
TuxSH
dda11206db Fix bug in fatalExceptionHandlers.s 2017-06-05 19:32:37 +02:00
Matt
e8565d30a9 Reference release notes in README.md 2017-06-05 10:15:49 -04:00
TuxSH
2d4c103854 Merge pull request #510 from T3CHNOLOG1C/master
fix typo in readme
2017-06-05 14:46:21 +02:00
T3CHNOLOG1C
d0b9e36908 fix typo in readme 2017-06-05 06:58:19 -04:00
216 changed files with 25113 additions and 3906 deletions

View File

@@ -1,12 +1,13 @@
<!--
-- THIS IS NOT A SUPPORT FORUM! For support go here:
-- Luma3DS GBATemp thread: https://gbatemp.net/threads/luma3ds-noob-proof-3ds-custom-firmware.411110/
-- Nintendo Hacking: https://discord.gg/MjzatM8y
-- Nintendo Homebrew: https://discord.gg/MjzatM8
--
-- Rosalina feature requests go here: https://github.com/AuroraWright/Luma3DS/issues/752
--
-- Also check the Wiki (https://github.com/AuroraWright/Luma3DS/wiki) before making an issue.
--
-- For GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: https://3ds.guide/troubleshooting
-- If you're using an emu/redNAND anything related to that must also be installed to sysNAND.
-- 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).
--
-- Luma updaters that don't support Boot9Strap/Sighax won't work.
@@ -19,7 +20,7 @@
**SysNAND version (+emu/redNAND version if applicable):**
[e.g. 11.4.0-37U SysNAND, 11.4.0-37J EmuNAND]
[e.g. 11.6.0-39U SysNAND, 11.6.0-39J EmuNAND]
**Entrypoint (How/what you're using to boot Luma3DS):**
@@ -27,7 +28,7 @@
**Luma3DS version:**
[e.g. 7.1 stable or if using nightly/hourly specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/9570e6cbeca53128433abbf5e3473cb8a07fe69e]
[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.-->
@@ -52,9 +53,7 @@ Use EmuNAND FIRM if booting with R: ( )
Enable loading external FIRMs and modules: ( )
<!--Firmware (.bin) files are not required by Luma, or NTR CFW anymore.
-- If you're having issues with this option enabled try deleting them from the luma folder on the root of the SD card and disabling this option.-->
Use custom path: ( )
-- If you're having issues with this option enabled try deleting them from the luma folder on the root of the SD card or /rw/luma on CTRNAND and disabling this option.-->
Enable game patching: ( )
@@ -66,6 +65,8 @@ Patch ARM9 access: ( )
Set developer UNITINFO: ( )
Disable ARM11 exception handlers: ( )
--
@@ -84,6 +85,6 @@ Set developer UNITINFO: ( )
**Dump file:**
<!--If the issue leads to a crash you can generate a crash dump by checking the "Enable 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.-->

10
.gitignore vendored
View File

@@ -1,18 +1,20 @@
.vscode
out
build
arm11/build
sysmodules/loader/build
sysmodules/rosalina/build
chainloader/build
rosalina/build
exceptions/arm9/build
exceptions/arm11/build
.vscode
.vscode/**
*.bin
*.firm
*.o
*.d
*.elf
*.cxi
*.bmp
.DS_Store
*.dmp
.project
.cproject
.settings

View File

@@ -11,26 +11,44 @@ endif
include $(DEVKITARM)/base_tools
name := Luma3DS
revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/i')
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
ifeq ($(strip $(revision)),)
revision := v0.0.0-0
version_major := 0
version_minor := 0
version_build := 0
endif
ifeq ($(strip $(commit)),)
commit := 0
endif
ifeq ($(strip $(version_build)),)
version_build := 0
endif
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
@@ -42,10 +60,9 @@ 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)/mmuHook.bin.o $(dir_build)/k11MainHook.bin.o $(dir_build)/svcConnectToPortInitHook.bin.o $(dir_build)/svcCustomBackdoor.bin.o\
$(dir_build)/chainloader.bin.o $(dir_build)/arm9_exceptions.bin.o
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
modules = $(dir_build)/loader.cxi $(dir_build)/rosalina.cxi $(dir_build)/sm.cxi $(dir_build)/pxi.cxi
define bin2o
bin2s $< | $(AS) -o $(@)
@@ -65,8 +82,11 @@ 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)
.PRECIOUS: $(dir_build)/%.bin
@@ -74,21 +94,25 @@ clean:
.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)
$(dir_out)/$(name)$(revision).7z: all
@mkdir -p "$(@D)"
@7z a -mx $@ ./$(@D)/* ./$(dir_exceptions)/exception_dump_parser.py
@[ -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_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 0x1FF60000 -C XDMA XDMA NDMA
@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 $<
@@ -96,6 +120,10 @@ $(dir_build)/arm11.elf: $(dir_arm11)
$(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 $<
@@ -104,6 +132,14 @@ $(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)
@@ -121,9 +157,10 @@ $(dir_build)/%.bin: $(dir_patches)/%.s
$(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 += -DREVISION=\"$(revision)\" -DCOMMIT_HASH="0x$(commit)"
$(dir_build)/firm.o: $(dir_build)/modules.bin
$(dir_build)/firm.o: CFLAGS += -DLUMA_SECTION0_SIZE="$(shell du -b $(dir_build)/modules.bin | cut -f1)"
$(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),\

View File

@@ -7,7 +7,7 @@
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.
Since Luma3DS v8.0, Luma3DS has its own in-game menu, triggerable by `L+Start+Select` (see the release notes).
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)).
---
@@ -15,9 +15,9 @@ Since Luma3DS v8.0, Luma3DS has its own in-game menu, triggerable by `L+Start+Se
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.
For now, you'll also need to update your [libctru](https://github.com/smealum/ctrulib) install, building from the latest commit.
For your convenience, here are [Windows](http://www91.zippyshare.com/v/ePGpjk9r/file.html) and [Linux](https://mega.nz/#!uQ1T1IAD!Q91O0e12LXKiaXh_YjXD3D5m8_W3FuMI-hEa6KVMRDQ) builds of armips (thanks to who compiled them!).
Finally just run `make` and everything should work!
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.
---

View File

@@ -11,6 +11,6 @@ SECTIONS
.data : ALIGN(4) { *(.data*); . = ALIGN(4); }
.bss : ALIGN(8) { __bss_start = .; *(.bss* COMMON); . = ALIGN(8); __bss_end = .; }
__stack_top__ = 0x1FFFF000;
__stack_top__ = 0x1FFFE000;
. = ALIGN(4);
}

View File

@@ -37,7 +37,7 @@ extern u32 prepareForFirmlaunchSize;
extern volatile Arm11Operation operation;
static void initScreensSequence(u32 brightnessLevel)
static void initScreens(u32 brightnessLevel, struct fb *fbs)
{
*(vu32 *)0x10141200 = 0x1007F;
*(vu32 *)0x10202014 = 0x00000001;
@@ -70,10 +70,13 @@ static void initScreensSequence(u32 brightnessLevel)
*(vu32 *)0x1040045C = 0x00f00190;
*(vu32 *)0x10400460 = 0x01c100d1;
*(vu32 *)0x10400464 = 0x01920002;
*(vu32 *)0x10400468 = 0x18300000;
*(vu32 *)0x10400468 = (u32)fbs[0].top_left;
*(vu32 *)0x1040046C = (u32)fbs[1].top_left;
*(vu32 *)0x10400470 = 0x80341;
*(vu32 *)0x10400474 = 0x00010501;
*(vu32 *)0x10400478 = 0;
*(vu32 *)0x10400494 = (u32)fbs[0].top_right;
*(vu32 *)0x10400498 = (u32)fbs[1].top_right;
*(vu32 *)0x10400490 = 0x000002D0;
*(vu32 *)0x1040049C = 0x00000000;
@@ -104,7 +107,8 @@ static void initScreensSequence(u32 brightnessLevel)
*(vu32 *)0x1040055C = 0x00f00140;
*(vu32 *)0x10400560 = 0x01c100d1;
*(vu32 *)0x10400564 = 0x01920052;
*(vu32 *)0x10400568 = 0x18300000 + 0x46500;
*(vu32 *)0x10400568 = (u32)fbs[0].bottom;
*(vu32 *)0x1040056C = (u32)fbs[1].bottom;
*(vu32 *)0x10400570 = 0x80301;
*(vu32 *)0x10400574 = 0x00010501;
*(vu32 *)0x10400578 = 0;
@@ -178,8 +182,8 @@ void main(void)
{
case ARM11_READY:
continue;
case INIT_SCREENS_SEQUENCE:
initScreensSequence(*(vu32 *)ARM11_PARAMETERS_ADDRESS);
case INIT_SCREENS:
initScreens(*(vu32 *)ARM11_PARAMETERS_ADDRESS, (struct fb *)(ARM11_PARAMETERS_ADDRESS + 4));
break;
case SETUP_FRAMEBUFFERS:
setupFramebuffers((struct fb *)ARM11_PARAMETERS_ADDRESS);

View File

@@ -50,11 +50,11 @@ struct fb {
u8 *top_left;
u8 *top_right;
u8 *bottom;
} __attribute__((packed));
};
typedef enum
{
INIT_SCREENS_SEQUENCE = 0,
INIT_SCREENS = 0,
SETUP_FRAMEBUFFERS,
CLEAR_SCREENS,
SWAP_FRAMEBUFFERS,

View File

@@ -28,9 +28,8 @@
#include "cache.h"
#include "firm.h"
void main(int argc, char **argv)
void main(int argc, char **argv, Firm *firm)
{
Firm *firm = (Firm *)0x20001000;
char *argvPassed[2],
absPath[24 + 255];
struct fb fbs[2];

View File

@@ -56,5 +56,5 @@ disableMpuAndJumpToEntrypoints:
@ Jump to the ARM9 entrypoint
mov r0, r4
mov r1, r5
ldr r2, =0x1BEEF
ldr r2, =0x3BEEF
bx r6

View File

@@ -42,4 +42,4 @@ struct fb {
u8 *top_left;
u8 *top_right;
u8 *bottom;
} __attribute__((packed));
};

View File

@@ -13,8 +13,8 @@ dir_build := build
dir_out := ../../$(dir_build)
ASFLAGS := -mcpu=arm946e-s
CFLAGS := -Wall -Wextra -mthumb $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
LDFLAGS := -nostdlib
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, \

View File

@@ -4,7 +4,7 @@ OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x01FF7FE0;
. = 0x01FF8000;
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }

View File

@@ -43,8 +43,9 @@ typedef struct __attribute__((packed))
u32 additionalDataSize;
} ExceptionDumpHeader;
u32 readMPUConfig(u32 *regionSettings);
void FIQHandler(void);
void undefinedInstructionHandler(void);
void dataAbortHandler(void);
void prefetchAbortHandler(void);
u32 safecpy(void *dst, const void *src, u32 len);

View File

@@ -22,92 +22,131 @@
@ or requiring that modified versions of such material be marked in
@ reasonable ways as different from the original version.
.macro GEN_HANDLER name
.global \name
.type \name, %function
\name:
ldr sp, =#0x02000000 @ We make the (full descending) stack point to the end of ITCM for our exception handlers.
@ It doesn't matter if we're overwriting stuff here, since we're going to reboot.
.macro GEN_USUAL_HANDLER name, index
\name\()Handler:
ldr sp, =_regs
stmia sp, {r0-r7}
stmfd sp!, {r0-r7} @ FIQ has its own r8-r14 regs
ldr r1, =\@ @ macro expansion counter
mov r0, #\index
b _commonHandler
.size \name, . - \name
.endm
.text
.arm
.align 4
.balign 4
.global _commonHandler
.type _commonHandler, %function
_commonHandler:
mov r1, r0
mov r0, sp
mrs r2, spsr
mov r6, sp
mrs r3, cpsr
add r6, r0, #(8 * 4)
orr r3, #0x1c0 @ disable Imprecise Aborts, IRQ and FIQ (equivalent to "cpsid aif" on arm11)
orr r3, #0xc0 @ mask interrupts
msr cpsr_cx, r3
tst r2, #0x20
bne noSvcBreak
cmp r1, #2
bne noSvcBreak
sub r0, lr, #4 @ calling cannotAccessAddress cause more problems that it actually solves... (I've to save a lot of regs and that's a pain tbh)
lsr r0, #20 @ we'll just do some address checks (to see if it's in ARM9 internal memory)
cmp r0, #0x80
bne noSvcBreak
ldr r4, [lr, #-4]
ldr r5, =#0xe12fff7f
cmp r4, r5
bne noSvcBreak
bic r5, r3, #0xf
orr r5, #0x3
msr cpsr_c, r5 @ switch to supervisor mode
ldmfd sp, {r8-r11}^
ldr r2, [sp, #0x1c] @ implementation details of the official svc handler
ldr r4, [sp, #0x18]
msr cpsr_c, r3 @ restore processor mode
tst r2, #0x20
addne lr, r4, #2 @ adjust address for later
moveq lr, r4
noSvcBreak:
ands r4, r2, #0xf @ get the mode that triggered the exception
moveq r4, #0xf @ usr => sys
bic r5, r3, #0xf
orr r5, r4
msr cpsr_c, r5 @ change processor mode
stmfd r6!, {r8-lr}
stmia r6!, {r8-lr}
msr cpsr_c, r3 @ restore processor mode
mov sp, r6
stmfd sp!, {r2,lr} @ it's a bit of a mess, but we will fix that later
@ order of saved regs now: cpsr, pc + (2/4/8), r8-r14, r0-r7
mov r0, sp
str lr, [r6], #4
str r2, [r6]
msr cpsr_cxsf, #0xdf @ finally, switch to system mode, mask interrupts and clear flags (in case of double faults)
ldr sp, =0x02000000
b mainHandler
GEN_HANDLER FIQHandler
GEN_HANDLER undefinedInstructionHandler
GEN_HANDLER prefetchAbortHandler
GEN_HANDLER dataAbortHandler
.global readMPUConfig
.type readMPUConfig, %function
readMPUConfig:
stmfd sp!, {r4-r8, lr}
mrc p15,0,r1,c6,c0,0
mrc p15,0,r2,c6,c1,0
mrc p15,0,r3,c6,c2,0
mrc p15,0,r4,c6,c3,0
mrc p15,0,r5,c6,c4,0
mrc p15,0,r6,c6,c5,0
mrc p15,0,r7,c6,c6,0
mrc p15,0,r8,c6,c7,0
stmia r0, {r1-r8}
mrc p15,0,r0,c5,c0,2 @ read data access permission bits
ldmfd sp!, {r4-r8, pc}
.global FIQHandler
.type FIQHandler, %function
GEN_USUAL_HANDLER FIQ, 0
.global undefinedInstructionHandler
.type undefinedInstructionHandler, %function
GEN_USUAL_HANDLER undefinedInstruction, 1
.global prefetchAbortHandler
.type prefetchAbortHandler, %function
prefetchAbortHandler:
msr cpsr_cx, #0xd7 @ mask interrupts (abort mode)
mrs sp, spsr
and sp, #0x3f
cmp sp, #0x13
bne _prefetchAbortNormalHandler
ldr sp, =BreakPtr
ldr sp, [sp]
cmp sp, #0
beq _prefetchAbortNormalHandler
add sp, #(1*4 + 4)
cmp lr, sp
bne _prefetchAbortNormalHandler
mov sp, r8
pop {r8-r11}
ldr lr, [sp, #8]!
ldr sp, [sp, #4]
msr spsr_cxsf, sp
tst sp, #0x20
addne lr, #2 @ adjust address for later
GEN_USUAL_HANDLER _prefetchAbortNormal, 2
.global dataAbortHandler
.type dataAbortHandler, %function
dataAbortHandler:
msr cpsr_cx, #0xd7 @ mask interrupts (abort mode)
mrs sp, spsr
and sp, #0x3f
cmp sp, #0x1f
bne _dataAbortNormalHandler
sub lr, #8
adr sp, safecpy
cmp lr, sp
blo _j_dataAbortNormalHandler
adr sp, _safecpy_end
cmp lr, sp
bhs _j_dataAbortNormalHandler
msr spsr_f, #(1 << 30)
mov r12, #0
adds pc, lr, #4
_j_dataAbortNormalHandler:
add lr, #8
GEN_USUAL_HANDLER _dataAbortNormal, 3
.global safecpy
.type safecpy, %function
safecpy:
push {r4, lr}
mov r3, #0
movs r12, #1
_safecpy_loop:
ldrb r4, [r1, r3]
cmp r12, #0
beq _safecpy_loop_end
strb r4, [r0, r3]
add r3, #1
cmp r3, r2
blo _safecpy_loop
_safecpy_loop_end:
mov r0, r3
pop {r4, pc}
_safecpy_end:
.bss
.balign 4
_regs: .skip (4 * 17)

View File

@@ -32,48 +32,10 @@
#define REG_DUMP_SIZE 4 * 17
#define CODE_DUMP_SIZE 48
bool cannotAccessAddress(const void *address)
{
u32 regionSettings[8];
u32 addr = (u32)address;
u32 dataAccessPermissions = readMPUConfig(regionSettings);
for(u32 i = 0; i < 8; i++)
{
if((dataAccessPermissions & 0xF) == 0 || (regionSettings[i] & 1) == 0)
continue; //No access / region not enabled
u32 regionAddrBase = regionSettings[i] & ~0xFFF;
u32 regionSize = 1 << (((regionSettings[i] >> 1) & 0x1F) + 1);
if(addr >= regionAddrBase && addr < regionAddrBase + regionSize)
return false;
dataAccessPermissions >>= 4;
}
return true;
}
static u32 __attribute__((noinline)) copyMemory(void *dst, const void *src, u32 size, u32 alignment)
{
u8 *out = (u8 *)dst;
const u8 *in = (const u8 *)src;
if(((u32)src & (alignment - 1)) != 0 || cannotAccessAddress(src) || (size != 0 && cannotAccessAddress((u8 *)src + size - 1)))
return 0;
for(u32 i = 0; i < size; i++)
*out++ = *in++;
return size;
}
void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type)
void __attribute__((noreturn)) mainHandler(u32 *registerDump, u32 type)
{
ExceptionDumpHeader dumpHeader;
u32 registerDump[REG_DUMP_SIZE / 4];
u8 codeDump[CODE_DUMP_SIZE];
dumpHeader.magic[0] = 0xDEADC0DE;
@@ -89,34 +51,32 @@ void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type)
dumpHeader.codeDumpSize = CODE_DUMP_SIZE;
dumpHeader.additionalDataSize = 0;
//Dump registers
//Current order of saved regs: cpsr, pc, r8-r14, r0-r7
u32 cpsr = regs[0];
u32 pc = regs[1] - (type < 3 ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 8);
u32 cpsr = registerDump[16];
u32 pc = registerDump[15] - (type < 3 ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 8);
registerDump[15] = pc;
registerDump[16] = cpsr;
for(u32 i = 0; i < 7; i++) registerDump[8 + i] = regs[2 + i];
for(u32 i = 0; i < 8; i++) registerDump[i] = regs[9 + i];
//Dump code
u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //Doesn't work well on 32-bit Thumb instructions, but it isn't much of a problem
dumpHeader.codeDumpSize = copyMemory(codeDump, instr, dumpHeader.codeDumpSize, ((cpsr & 0x20) != 0) ? 2 : 4);
u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //wouldn't work well on 32-bit Thumb instructions, but it isn't much of a problem
dumpHeader.codeDumpSize = ((u32)instr & (((cpsr & 0x20) != 0) ? 1 : 3)) != 0 ? 0 : safecpy(codeDump, instr, dumpHeader.codeDumpSize);
//Copy register dump and code dump
//Copy register dump and code dump
u8 *final = (u8 *)(FINAL_BUFFER + sizeof(ExceptionDumpHeader));
final += copyMemory(final, registerDump, dumpHeader.registerDumpSize, 1);
final += copyMemory(final, codeDump, dumpHeader.codeDumpSize, 1);
final += safecpy(final, registerDump, dumpHeader.registerDumpSize);
final += safecpy(final, codeDump, dumpHeader.codeDumpSize);
//Dump stack in place
dumpHeader.stackDumpSize = copyMemory(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF), 1);
dumpHeader.stackDumpSize = safecpy(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF));
dumpHeader.totalSize = sizeof(ExceptionDumpHeader) + dumpHeader.registerDumpSize + dumpHeader.codeDumpSize + dumpHeader.stackDumpSize + dumpHeader.additionalDataSize;
//Copy header (actually optimized by the compiler)
*(ExceptionDumpHeader *)FINAL_BUFFER = dumpHeader;
if(ARESCREENSINITIALIZED) i2cWriteRegister(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
while(true);
}

View File

@@ -26,8 +26,12 @@
.align 4
.global _start
_start:
add pc, r0, #(handlers - .) @ Dummy instruction to prevent compiler optimizations
add pc, r0, #(handlers - .) @ Dummy instruction
.global BreakPtr
BreakPtr: .word 0
.global handlers
handlers:
.word FIQHandler
.word undefinedInstructionHandler

View File

@@ -39,3 +39,7 @@ 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)

View File

@@ -90,8 +90,15 @@ def makeRegisterLine(A, rA, B, 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'
}
if __name__ == "__main__":
def main(args=None):
parser = argparse.ArgumentParser(description="Parse Luma3DS exception dumps")
parser.add_argument("filename")
args = parser.parse_args()
@@ -134,6 +141,11 @@ if __name__ == "__main__":
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]))
@@ -143,6 +155,9 @@ if __name__ == "__main__":
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)
@@ -151,8 +166,9 @@ if __name__ == "__main__":
objdump_res = ""
try:
path = os.path.join(os.environ["DEVKITARM"], "bin", "arm-none-eabi-objdump")
if os.name == "nt":
path = ''.join((path[1], ':', path[2:])).replace('/', '\\')
if os.name == "nt" and path[0] == '/':
path = ''.join((path[1], ':', path[2:]))
objdump_res = subprocess.check_output((
path, "-marm", "-b", "binary",
@@ -167,3 +183,6 @@ if __name__ == "__main__":
print("\nStack dump:\n")
print(hexdump(registers[13], stackDump))
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,13 @@
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']},
)

View File

@@ -6,7 +6,7 @@ endif
include $(DEVKITARM)/base_tools
name := kernel_extension
name := k11_extension
dir_source := source
dir_include := include
@@ -14,9 +14,9 @@ dir_build := build
ARCH := -mcpu=mpcore -mfpu=vfp
ASFLAGS := $(ARCH)
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -I$(dir_include) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math \
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 $(ARCH)
LDFLAGS := -nostdlib -Wl,--gc-sections,--nmagic $(ARCH)
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \

View File

@@ -0,0 +1,37 @@
#pragma once
#include "types.h"
#define MAKE_BRANCH(src,dst) (0xEA000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
#define MAKE_BRANCH_LINK(src,dst) (0xEB000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
#define CONFIG(a) (((cfwInfo.config >> (a)) & 1) != 0)
#define MULTICONFIG(a) ((cfwInfo.multiConfig >> (2 * (a))) & 3)
#define BOOTCONFIG(a, b) ((cfwInfo.bootConfig >> (a)) & (b))
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
#define BOOTCFG_NOFORCEFLAG BOOTCONFIG(6, 1)
#define BOOTCFG_NTRCARDBOOT BOOTCONFIG(7, 1)
enum multiOptions
{
DEFAULTEMU = 0,
BRIGHTNESS,
SPLASH,
SPLASH_DURATION,
PIN,
NEWCPU
};
enum singleOptions
{
AUTOBOOTEMU = 0,
USEEMUFIRM,
LOADEXTFIRMSANDMODULES,
PATCHGAMES,
PATCHVERSTRING,
SHOWGBABOOT,
PATCHUNITINFO,
DISABLEARM11EXCHANDLERS
};

View File

@@ -24,18 +24,16 @@
* reasonable ways as different from the original version.
*/
#include "synchronization.h"
#include "utils.h"
#pragma once
#include "types.h"
#include "globals.h"
#include "kernel.h"
#include "utils.h"
extern SGI0Handler_t SGI0Handler;
extern KRecursiveLock dbgParamsLock;
extern u32 dbgParamWatchpointId, dbgParamDVA, dbgParamWCR, dbgParamContextId;
void executeFunctionOnCores(SGI0Handler_t handler, u8 targetList, u8 targetListFilter)
{
u32 coreID = getCurrentCoreID();
SGI0Handler = handler;
if(targetListFilter == 0 && (targetListFilter & (1 << coreID)) != 0)
__asm__ volatile("cpsie i"); // make sure interrupts aren't masked
MPCORE_GID_SGI = (targetListFilter << 24) | (targetList << 16) | 0;
}
KSchedulableInterruptEvent *enableMonitorModeDebugging(KBaseInterruptEvent *this, u32 interruptID);
KSchedulableInterruptEvent *disableWatchpoint(KBaseInterruptEvent *this, u32 interruptID);
KSchedulableInterruptEvent *setWatchpointWithContextId(KBaseInterruptEvent *this, u32 interruptID);

View File

@@ -28,10 +28,9 @@
#include "types.h"
bool isExceptionFatal(u32 spsr);
bool isExceptionFatal(u32 spsr, u32 *regs, u32 index);
bool isDataAbortExceptionRangeControlled(u32 spsr, u32 addr);
void FIQHandler(void);
void undefinedInstructionHandler(void);
void prefetchAbortHandler(void);

View File

@@ -26,6 +26,7 @@
#pragma once
#include "config.h"
#include "kernel.h"
extern KRecursiveLock *criticalSectionLock;
@@ -55,6 +56,7 @@ extern void (*KScheduler__AttemptSwitchingThreadContext)(KScheduler *this);
extern Result (*ControlMemory)(u32 *addrOut, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm, bool isLoader);
extern void (*SleepThread)(s64 ns);
extern Result (*CloseHandle)(Handle handle);
extern Result (*GetHandleInfo)(s64 *out, Handle handle, u32 type);
extern Result (*GetSystemInfo)(s64 *out, s32 type, s32 param);
extern Result (*GetProcessInfo)(s64 *out, Handle processHandle, u32 type);
extern Result (*GetThreadInfo)(s64 *out, Handle threadHandle, u32 type);
@@ -63,6 +65,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 (*UnmapProcessMemory)(Handle processHandle, void *dst, u32 size);
extern Result (*KernelSetState)(u32 type, u32 varg1, u32 varg2, u32 varg3);
extern void (*flushDataCacheRange)(void *addr, u32 len);
@@ -75,11 +78,9 @@ extern bool (*kernelToUsrMemcpy8)(void *dst, const void *src, u32 len);
extern bool (*kernelToUsrMemcpy32)(u32 *dst, const u32 *src, u32 len);
extern s32 (*kernelToUsrStrncpy)(char *dst, const char *src, u32 len);
extern Result (*CustomBackdoor)(void *function, ...);
extern void (*svcFallbackHandler)(u8 svcId);
extern void (*kernelpanic)(void);
extern void (*PostprocessSvc)(void);
extern void (*officialPostProcessSvc)(void);
extern Result (*SignalDebugEvent)(DebugEventType type, u32 info, ...);
@@ -89,11 +90,23 @@ extern u32 *exceptionStackTop;
extern u32 TTBCR;
extern u32 L1MMUTableAddrs[4];
extern u32 kernelVersion;
extern void *kernelUsrCopyFuncsStart, *kernelUsrCopyFuncsEnd;
extern bool *isDevUnit;
extern vu8 *configPage;
extern u32 kernelVersion;
extern FcramLayout fcramLayout;
extern KCoreContext *coreCtxs;
extern void *originalHandlers[8];
extern u32 nbSection0Modules;
extern u8 __start__[], __end__[], __bss_start__[], __bss_end__[];
extern Result (*InterruptManager__MapInterrupt)(InterruptManager *manager, KBaseInterruptEvent *iEvent, u32 interruptID,
u32 coreID, u32 priority, bool disableUponReceipt, bool levelHighActive);
extern InterruptManager *interruptManager;
extern KBaseInterruptEvent *customInterruptEvent;
@@ -101,7 +114,7 @@ extern void (*initFPU)(void);
extern void (*mcuReboot)(void);
extern void (*coreBarrier)(void);
typedef struct PACKED CfwInfo
typedef struct CfwInfo
{
char magic[4];
@@ -112,10 +125,13 @@ typedef struct PACKED CfwInfo
u32 commitHash;
u32 config;
u16 configFormatVersionMajor, configFormatVersionMinor;
u32 config, multiConfig, bootConfig;
u64 hbldr3dsxTitleId;
u32 rosalinaMenuCombo;
} CfwInfo;
extern CfwInfo cfwInfo;
extern u32 rosalinaState;
extern bool hasStartedRosalinaNetworkFuncsOnce;
extern vu32 rosalinaState;
extern bool hasStartedRosalinaNetworkFuncsOnce;

View File

@@ -56,6 +56,6 @@ void SessionInfo_ChangeVtable(KSession *session);
void SessionInfo_Add(KSession *session, const char *name);
void SessionInfo_Remove(KSession *session);
bool doLangEmu(Result *res, Handle handle, u32 *cmdbuf);
bool doLangEmu(Result *res, u32 *cmdbuf);
Result doPublishToProcessHook(Handle handle, u32 *cmdbuf);
bool doErrfThrowHook(u32 *cmdbuf);

View File

@@ -28,6 +28,8 @@
#include "types.h"
extern u32 kernelVersion;
struct KMutex;
struct KProcessO3DS;
struct KProcessN3DS;
@@ -204,7 +206,7 @@ typedef struct PACKED ALIGN(4) KThread
KMutexLinkedList *mutexList;
KLinkedList mutexesUsed;
s32 dynamicPriority;
u32 processor;
u32 coreId;
KPreemptionTimer *preemptionTimer;
u32 unknown_1;
bool isAlive;
@@ -948,6 +950,7 @@ typedef struct KCoreContext
} KCoreContext;
static KCoreContext * const currentCoreContext = (KCoreContext *)0xFFFF1000;
extern KCoreContext *coreCtxs;
#define DEFINE_CONSOLE_SPECIFIC_STRUCTS(console, nbCores)
/* 60 */
@@ -1121,25 +1124,42 @@ typedef union KCacheMaintenanceInterruptEvent
KCacheMaintenanceInterruptEventO3DS O3DS;
} KCacheMaintenanceInterruptEvent;
typedef struct FcramLayout
{
void *applicationAddr;
u32 applicationSize;
void *systemAddr;
u32 systemSize;
void *baseAddr;
u32 baseSize;
} FcramLayout;
extern bool isN3DS;
extern void *officialSVCs[0x7E];
extern u32 kernelVersion;
#define KPROCESS_OFFSETOF(field) (isN3DS ? offsetof(KProcessN3DS, field) :\
((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? offsetof(KProcessO3DS8x, field) :\
offsetof(KProcessO3DSPre8x, field)))
#define KPROCESSRELATED_OFFSETOFF(classname, field) (isN3DS ? offsetof(classname##N3DS, field) :\
((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? offsetof(classname##O3DS8x, field) :\
offsetof(classname##O3DSPre8x, field)))
#define KPROCESS_GET_PTR(obj, field) (isN3DS ? &(obj)->N3DS.field :\
#define KPROCESSRELATED_GET_PTR(obj, field) (isN3DS ? &(obj)->N3DS.field :\
((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? &(obj)->O3DS8x.field :\
&(obj)->O3DSPre8x.field ))
&(obj)->O3DSPre8x.field))
#define KPROCESS_GET_PTR_TYPE(type, obj, field) (isN3DS ? (type *)(&(obj)->N3DS.field) :\
#define KPROCESSRELATED_GET_PTR_TYPE(type, obj, field) (isN3DS ? (type *)(&(obj)->N3DS.field) :\
((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? (type *)(&(obj)->O3DS8x.field) :\
(type *)(&(obj)->O3DSPre8x.field) ))
(type *)(&(obj)->O3DSPre8x.field)))
#define KPROCESS_GET_RVALUE(obj, field) *(KPROCESS_GET_PTR(obj, field))
#define KPROCESS_OFFSETOF(field) KPROCESSRELATED_OFFSETOFF(KProcess, field)
#define KPROCESS_GET_PTR(obj, field) KPROCESSRELATED_GET_PTR(obj, field)
#define KPROCESS_GET_PTR_TYPE(type, obj, field) KPROCESSRELATED_GET_PTR_TYPE(type, obj, field)
#define KPROCESS_GET_RVALUE(obj, field) *(KPROCESS_GET_PTR(obj, field))
#define KPROCESS_GET_RVALUE_TYPE(type, obj, field) *(KPROCESS_GET_PTR_TYPE(type, obj, field))
#define KPROCESS_GET_RVALUE_TYPE(type, obj, field) *(KPROCESS_GET_PTR(type, obj, field))
#define KPROCESSHWINFO_OFFSETOF(field) KPROCESSRELATED_OFFSETOFF(KProcessHwInfo, field)
#define KPROCESSHWINFO_GET_PTR(obj, field) KPROCESSRELATED_GET_PTR(obj, field)
#define KPROCESSHWINFO_GET_PTR_TYPE(type, obj, field) KPROCESSRELATED_GET_PTR_TYPE(type, obj, field)
#define KPROCESSHWINFO_GET_RVALUE(obj, field) *(KPROCESSHWINFO_GET_PTR(obj, field))
#define KPROCESSHWINFO_GET_RVALUE_TYPE(type, obj, field) *(KPROCESSHWINFO_GET_PTR_TYPE(type, obj, field))
static inline u32 idOfProcess(KProcess *process)
{
@@ -1166,6 +1186,20 @@ static inline KDebug *debugOfProcess(KProcess *process)
return KPROCESS_GET_RVALUE(process, debug);
}
static inline const char *classNameOfAutoObject(KAutoObject *object)
{
const char *name;
if(kernelVersion >= SYSTEM_VERSION(2, 46, 0))
{
KClassToken tok;
object->vtable->GetClassToken(&tok, object);
name = tok.name;
}
else
name = object->vtable->GetClassName(object);
return name;
}
extern Result (*KProcessHandleTable__CreateHandle)(KProcessHandleTable *this, Handle *out, KAutoObject *obj, u8 token);
static inline Result createHandleForProcess(Handle *out, KProcess *process, KAutoObject *obj)

View File

@@ -33,5 +33,6 @@
extern void *officialSVCs[0x7E];
void postprocessSvc(void);
void svcDefaultHandler(u8 svcId);
void *svcHook(u8 *pageEnd);

View File

@@ -25,6 +25,9 @@
*/
#pragma once
#include <3ds/types.h>
void installKernelExtension(void);
#include "utils.h"
#include "kernel.h"
#include "svc.h"
void CustomBackdoor(void *function, ...);

View File

@@ -26,13 +26,9 @@
#pragma once
#define PA_FROM_VA_PTR(addr) PA_PTR(convertVAToPA(addr))
#include "utils.h"
#include "kernel.h"
#include "svc.h"
Result svc0x2F(void *function, ...); // custom backdoor before kernel ext. is installed (and only before!)
void *convertVAToPA(const void *VA);
extern u8 kernel_extension[];
extern u32 kernel_extension_size;
Result GetHandleInfoHookWrapper(u32 dummy, Handle handle, u32 type);
Result GetHandleInfoHook(s64 *out, Handle handle, u32 type);

View File

@@ -30,6 +30,5 @@
#include "kernel.h"
#include "svc.h"
extern u32 rosalinaState;
bool shouldSignalSyscallDebugEvent(KProcess *process, u8 svcId);
Result KernelSetStateHook(u32 type, u32 varg1, u32 varg2, u32 varg3);

View File

@@ -30,4 +30,4 @@
#include "kernel.h"
#include "svc.h"
void SetWifiEnabled(bool enable);
Result SetWifiEnabled(bool enable);

View File

@@ -34,6 +34,14 @@ typedef KSchedulableInterruptEvent* (*SGI0Handler_t)(KBaseInterruptEvent *this,
// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0360f/CCHDIFIJ.html
void executeFunctionOnCores(SGI0Handler_t func, u8 targetList, u8 targetListFilter);
void KScheduler__TriggerCrossCoreInterrupt(KScheduler *this);
void KThread__DebugReschedule(KThread *this, bool lock);
bool rosalinaThreadLockPredicate(KThread *thread);
void rosalinaRescheduleThread(KThread *thread, bool lock);
void rosalinaLockThread(KThread *thread);
void rosalinaLockAllThreads(void);
void rosalinaUnlockAllThreads(void);
// Taken from ctrulib:
static inline void __dsb(void)
@@ -59,3 +67,53 @@ static inline bool __strex(s32* addr, s32 val)
__asm__ __volatile__("strex %[res], %[val], %[addr]" : [res] "=&r" (res) : [val] "r" (val), [addr] "Q" (*addr));
return res;
}
static inline s8 __ldrex8(s8* addr)
{
s8 val;
__asm__ __volatile__("ldrexb %[val], %[addr]" : [val] "=r" (val) : [addr] "Q" (*addr));
return val;
}
static inline bool __strex8(s8* addr, s8 val)
{
bool res;
__asm__ __volatile__("strexb %[res], %[val], %[addr]" : [res] "=&r" (res) : [val] "r" (val), [addr] "Q" (*addr));
return res;
}
static inline s16 __ldrex16(s16* addr)
{
s16 val;
__asm__ __volatile__("ldrexh %[val], %[addr]" : [val] "=r" (val) : [addr] "Q" (*addr));
return val;
}
static inline bool __strex16(s16* addr, s16 val)
{
bool res;
__asm__ __volatile__("strexh %[res], %[val], %[addr]" : [res] "=&r" (res) : [val] "r" (val), [addr] "Q" (*addr));
return res;
}
static inline u32 __get_cpsr(void)
{
u32 cpsr;
__asm__ __volatile__("mrs %0, cpsr" : "=r"(cpsr));
return cpsr;
}
static inline void __set_cpsr_cx(u32 cpsr)
{
__asm__ __volatile__("msr cpsr_cx, %0" :: "r"(cpsr));
}
static inline void __enable_irq(void)
{
__asm__ __volatile__("cpsie i");
}
static inline void __disable_irq(void)
{
__asm__ __volatile__("cpsid i");
}

19
k11_extension/linker.ld Normal file
View File

@@ -0,0 +1,19 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x40000000;
__start__ = .;
.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__ = .; }
. = ALIGN(0x1000);
__end__ = .;
}

View File

@@ -0,0 +1,147 @@
/*
* 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 "debug.h"
#include "memory.h"
#include "synchronization.h"
KRecursiveLock dbgParamsLock = { NULL };
u32 dbgParamWatchpointId, dbgParamDVA, dbgParamWCR, dbgParamContextId;
KSchedulableInterruptEvent *enableMonitorModeDebugging(KBaseInterruptEvent *this UNUSED, u32 interruptID UNUSED)
{
coreBarrier();
u32 DSCR;
__asm__ __volatile__("mrc p14, 0, %[val], c0, c1, 0" : [val] "=r" (DSCR));
DSCR |= 0x8000;
__asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 0" :: [val] "r" (DSCR));
__dsb();
coreBarrier();
return NULL;
}
static void disableWatchpoint0(void)
{
u32 control;
// WCR0
__asm__ __volatile__("mrc p14, 0, %[val], c0, c0, 7" : [val] "=r" (control));
control &= ~1;
__asm__ __volatile__("mcr p14, 0, %[val], c0, c0, 7" :: [val] "r" (control));
// BCR4
__asm__ __volatile__("mrc p14, 0, %[val], c0, c4, 5" : [val] "=r" (control));
control &= ~1;
__asm__ __volatile__("mcr p14, 0, %[val], c0, c4, 5" :: [val] "r" (control));
}
static void disableWatchpoint1(void)
{
u32 control;
// WCR1
__asm__ __volatile__("mrc p14, 0, %[val], c0, c1, 7" : [val] "=r" (control));
control &= ~1;
__asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 7" :: [val] "r" (control));
// BCR5
__asm__ __volatile__("mrc p14, 0, %[val], c0, c5, 5" : [val] "=r" (control));
control &= ~1;
__asm__ __volatile__("mcr p14, 0, %[val], c0, c5, 5" :: [val] "r" (control));
}
KSchedulableInterruptEvent *disableWatchpoint(KBaseInterruptEvent *this UNUSED, u32 interruptID UNUSED)
{
coreBarrier();
if(dbgParamWatchpointId == 0)
disableWatchpoint0();
else
disableWatchpoint1();
__dsb();
coreBarrier();
return NULL;
}
static void setWatchpoint0WithContextId(u32 DVA, u32 WCR, u32 contextId)
{
// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0360f/CEGCFFDF.html
u32 BCR =
(1 << 21) | /* compare with context ID */
(1 << 20) | /* linked (with a WRP in our case) */
(0xf << 5) | /* byte address select, +0 to +3 as mandated when linking with a WRP */
(3 << 1) | /* either privileged modes or user mode, as mandated when linking with a WRP */
(1 << 0) ; /* enabled */
disableWatchpoint0();
__asm__ __volatile__("mcr p14, 0, %[val], c0, c0, 6" :: [val] "r" (DVA));
__asm__ __volatile__("mcr p14, 0, %[val], c0, c4, 4" :: [val] "r" (contextId));
__asm__ __volatile__("mcr p14, 0, %[val], c0, c0, 7" :: [val] "r" (WCR));
__asm__ __volatile__("mcr p14, 0, %[val], c0, c4, 5" :: [val] "r" (BCR));
__asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 5" :: [val] "r" (0) : "memory"); // DMB
}
static void setWatchpoint1WithContextId(u32 DVA, u32 WCR, u32 contextId)
{
// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0360f/CEGCFFDF.html
u32 BCR =
(1 << 21) | /* compare with context ID */
(1 << 20) | /* linked (with a WRP in our case) */
(0xf << 5) | /* byte address select, +0 to +3 as mandated when linking with a WRP */
(3 << 1) | /* either privileged modes or user mode, as mandated when linking with a WRP */
(1 << 0) ; /* enabled */
disableWatchpoint1();
__asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 6" :: [val] "r" (DVA));
__asm__ __volatile__("mcr p14, 0, %[val], c0, c5, 4" :: [val] "r" (contextId));
__asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 7" :: [val] "r" (WCR));
__asm__ __volatile__("mcr p14, 0, %[val], c0, c5, 5" :: [val] "r" (BCR));
__asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 5" :: [val] "r" (0) : "memory"); // DMB
}
KSchedulableInterruptEvent *setWatchpointWithContextId(KBaseInterruptEvent *this UNUSED, u32 interruptID UNUSED)
{
coreBarrier();
if(dbgParamWatchpointId == 0)
setWatchpoint0WithContextId(dbgParamDVA, dbgParamWCR, dbgParamContextId);
else
setWatchpoint1WithContextId(dbgParamDVA, dbgParamWCR, dbgParamContextId);
__dsb();
coreBarrier();
return NULL;
}

View File

@@ -47,6 +47,8 @@
push {r0-r12, lr}
mrs r0, spsr
mov r1, sp
mov r2, #\index
bl isExceptionFatal
cmp r0, #0
pop {r0-r12, lr}
@@ -138,7 +140,7 @@ _commonHandler:
mcr p15, 0, r0, c7, c10, 4 @ Drain Synchronization Barrier
ldr r0, =isN3DS
ldr r0, [r0]
ldrb r0, [r0]
cmp r0, #0
beq _no_L2C
ldr r0, =(0x17e10100 | 1 << 31)
@@ -157,7 +159,7 @@ _commonHandler:
_no_L2C:
cps #0x1F
msr cpsr_cxsf, #0xdf @ finally, switch to system mode, mask interrupts and clear flags (in case of double faults)
ldr sp, =exceptionStackTop
ldr sp, [sp]
sub sp, #0x100
@@ -219,7 +221,8 @@ prefetchAbortHandler:
pop {r8-r11}
ldr lr, [sp, #8]!
ldr sp, [sp, #4]
msr spsr, sp
msr spsr_cxsf, sp
tst sp, #0x20
addne lr, #2 @ adjust address for later
GEN_USUAL_HANDLER _prefetchAbortNormal, 2, 12

View File

@@ -33,9 +33,11 @@
#define REG_DUMP_SIZE 4 * 23
#define CODE_DUMP_SIZE 48
bool isExceptionFatal(u32 spsr)
bool isExceptionFatal(u32 spsr, u32 *regs, u32 index)
{
if((spsr & 0x1f) != 0x10) return true;
if(CONFIG(DISABLEARM11EXCHANDLERS)) return false;
if((spsr & 0x1F) != 0x10) return true;
KThread *thread = currentCoreContext->objectContext.currentThread;
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
@@ -51,6 +53,10 @@ bool isExceptionFatal(u32 spsr)
thread = KPROCESS_GET_RVALUE(currentProcess, mainThread);
if(thread != NULL && thread->threadLocalStorage != NULL && *((vu32 *)thread->threadLocalStorage + 0x10) != 0)
return false;
if(index == 3 && strcmp(codeSetOfProcess(currentProcess)->processName, "menu") == 0 && // workaround a Home Menu bug leading to a dabort
regs[0] == 0x3FFF && regs[2] == 0 && regs[5] == 2 && regs[7] == 1)
return false;
}
return true;
@@ -59,7 +65,7 @@ bool isExceptionFatal(u32 spsr)
extern u32 safecpy_sz;
bool isDataAbortExceptionRangeControlled(u32 spsr, u32 addr)
{
return ((spsr & 0x1F) != 0x10) && (
return (!(spsr & 0x20) && (spsr & 0x1F) != 0x10) && (
((u32)kernelUsrCopyFuncsStart <= addr && addr < (u32)kernelUsrCopyFuncsEnd) ||
((u32)safecpy <= addr && addr < (u32)safecpy + safecpy_sz)
);
@@ -90,7 +96,7 @@ void fatalExceptionHandlersMain(u32 *registerDump, u32 type, u32 cpuId)
registerDump[15] = pc;
//Dump code
u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //Doesn't work well on 32-bit Thumb instructions, but it isn't much of a problem
u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //wouldn't work well on 32-bit Thumb instructions, but it isn't much of a problem
dumpHeader.codeDumpSize = ((u32)instr & (((cpsr & 0x20) != 0) ? 1 : 3)) != 0 ? 0 : safecpy(codeDump, instr, dumpHeader.codeDumpSize);
//Copy register dump and code dump

View File

@@ -52,6 +52,7 @@ void (*KScheduler__AttemptSwitchingThreadContext)(KScheduler *this);
Result (*ControlMemory)(u32 *addrOut, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm, bool isLoader);
void (*SleepThread)(s64 ns);
Result (*CloseHandle)(Handle handle);
Result (*GetHandleInfo)(s64 *out, Handle handle, u32 type);
Result (*GetSystemInfo)(s64 *out, s32 type, s32 param);
Result (*GetProcessInfo)(s64 *out, Handle processHandle, u32 type);
Result (*GetThreadInfo)(s64 *out, Handle threadHandle, u32 type);
@@ -60,6 +61,7 @@ Result (*SendSyncRequest)(Handle handle);
Result (*OpenProcess)(Handle *out, u32 processId);
Result (*GetProcessId)(u32 *out, Handle process);
Result (*DebugActiveProcess)(Handle *out, u32 processId);
Result (*UnmapProcessMemory)(Handle processHandle, void *dst, u32 size);
Result (*KernelSetState)(u32 type, u32 varg1, u32 varg2, u32 varg3);
void (*flushDataCacheRange)(void *addr, u32 len);
@@ -72,11 +74,9 @@ bool (*kernelToUsrMemcpy8)(void *dst, const void *src, u32 len);
bool (*kernelToUsrMemcpy32)(u32 *dst, const u32 *src, u32 len);
s32 (*kernelToUsrStrncpy)(char *dst, const char *src, u32 len);
Result (*CustomBackdoor)(void *function, ...);
void (*svcFallbackHandler)(u8 svcId);
void (*kernelpanic)(void);
void (*PostprocessSvc)(void);
void (*officialPostProcessSvc)(void);
Result (*SignalDebugEvent)(DebugEventType type, u32 info, ...);
@@ -86,11 +86,21 @@ u32 *exceptionStackTop;
u32 TTBCR;
u32 L1MMUTableAddrs[4];
u32 kernelVersion;
void *kernelUsrCopyFuncsStart, *kernelUsrCopyFuncsEnd;
bool *isDevUnit;
vu8 *configPage;
u32 kernelVersion;
FcramLayout fcramLayout;
KCoreContext *coreCtxs;
void *originalHandlers[8] = {NULL};
u32 nbSection0Modules;
Result (*InterruptManager__MapInterrupt)(InterruptManager *manager, KBaseInterruptEvent *iEvent, u32 interruptID,
u32 coreID, u32 priority, bool disableUponReceipt, bool levelHighActive);
InterruptManager *interruptManager;
KBaseInterruptEvent *customInterruptEvent;
@@ -100,5 +110,5 @@ void (*coreBarrier)(void);
CfwInfo cfwInfo;
u32 rosalinaState;
vu32 rosalinaState;
bool hasStartedRosalinaNetworkFuncsOnce;

View File

@@ -182,7 +182,7 @@ void SessionInfo_ChangeVtable(KSession *session)
session->autoObject.vtable = (Vtable__KAutoObject *)customSessionVtable;
}
bool doLangEmu(Result *res, Handle handle, u32 *cmdbuf)
bool doLangEmu(Result *res, u32 *cmdbuf)
{
KRecursiveLock__Lock(criticalSectionLock);
KRecursiveLock__Lock(&processLangemuLock);
@@ -220,15 +220,12 @@ bool doLangEmu(Result *res, Handle handle, u32 *cmdbuf)
else if(cmdbuf[1] == 4 && cmdbuf[2] == 0xB0000 && cmdbuf[3] == 0x4C && (attribs->mask & 0xC))
{
u8 *ptr = (u8 *)cmdbuf[4];
*res = SendSyncRequest(handle);
flushEntireDataCache(); // looks like it's needed. WTF?!
if(*res == 0)
{
if(attribs->mask & 4)
ptr[3] = attribs->country;
if(attribs->mask & 8)
ptr[2] = attribs->state;
}
if(attribs->mask & 4)
ptr[3] = attribs->country;
if(attribs->mask & 8)
ptr[2] = attribs->state;
ptr[0] = ptr[1] = 0;
}
else
skip = false;
@@ -260,7 +257,7 @@ Result doPublishToProcessHook(Handle handle, u32 *cmdbuf)
((KAutoObject *)process)->vtable->DecrementReferenceCount((KAutoObject *)process);
}
if(terminateRosalina)
if(terminateRosalina && nbSection0Modules == 6)
{
Handle rosalinaProcessHandle;
res = OpenProcess(&rosalinaProcessHandle, 5);

View File

@@ -33,79 +33,93 @@
#include "svcHandler.h"
#include "memory.h"
static const u32 *const exceptionsPage = (const u32 *)0xFFFF0000;
void *originalHandlers[8] = {NULL};
enum VECTORS { RESET = 0, UNDEFINED_INSTRUCTION, SVC, PREFETCH_ABORT, DATA_ABORT, RESERVED, IRQ, FIQ };
static void setupSGI0Handler(void)
struct KExtParameters
{
for(u32 i = 0; i < getNumberOfCores(); i++)
interruptManager->N3DS.privateInterrupts[i][0].interruptEvent = customInterruptEvent;
u32 ALIGN(0x400) L2MMUTableFor0x40000000[256];
u32 basePA;
void *originalHandlers[4];
u32 L1MMUTableAddrs[4];
CfwInfo cfwInfo;
} kExtParameters = { .basePA = 0x12345678 }; // place this in .data
void relocateAndSetupMMU(u32 coreId, u32 *L1Table)
{
struct KExtParameters *p0 = (struct KExtParameters *)((u32)&kExtParameters - 0x40000000 + 0x18000000);
struct KExtParameters *p = (struct KExtParameters *)((u32)&kExtParameters - 0x40000000 + p0->basePA);
if(coreId == 0)
{
// Relocate ourselves, and clear BSS
memcpy((void *)p0->basePA, (const void *)0x18000000, __bss_start__ - __start__);
memset32((u32 *)(p0->basePA + (__bss_start__ - __start__)), 0, __bss_end__ - __bss_start__);
// Map the kernel ext to 0x40000000
// 4KB extended small pages: [SYS:RW USR:-- X TYP:NORMAL SHARED OUTER NOCACHE, INNER CACHED WB WA]
for(u32 offset = 0; offset < (u32)(__end__ - __start__); offset += 0x1000)
p->L2MMUTableFor0x40000000[offset >> 12] = (p0->basePA + offset) | 0x516;
__asm__ __volatile__ ("sev");
}
else
__asm__ __volatile__ ("wfe");
// bit31 idea thanks to SALT
// Maps physmem so that, if addr is in physmem(0, 0x30000000), it can be accessed uncached&rwx as addr|(1<<31)
u32 attribs = 0x40C02; // supersection (rwx for all) of strongly ordered memory, shared
for(u32 PA = 0; PA < 0x30000000; PA += 0x01000000)
{
u32 VA = (1 << 31) | PA;
for(u32 i = 0; i < 16; i++)
L1Table[i + (VA >> 20)] = PA | attribs;
}
L1Table[0x40000000 >> 20] = (u32)p->L2MMUTableFor0x40000000 | 1;
p->L1MMUTableAddrs[coreId] = (u32)L1Table;
}
static inline void **getHandlerDestination(enum VECTORS vector)
void bindSGI0Hook(void)
{
u32 *branch_dst = (u32 *)decodeARMBranch((u32 *)exceptionsPage + (u32)vector);
return (void **)(branch_dst + 2);
if(InterruptManager__MapInterrupt(interruptManager, customInterruptEvent, 0, getCurrentCoreID(), 0, false, false) != 0)
__asm__ __volatile__ ("bkpt 0xdead");
}
static inline void swapHandlerInVeneer(enum VECTORS vector, void *handler)
void configHook(vu8 *cfgPage)
{
void **dst = getHandlerDestination(vector);
originalHandlers[(u32)vector] = *dst;
if(handler != NULL)
*(void**)PA_FROM_VA_PTR(dst) = handler;
}
configPage = cfgPage;
static u32 *trampo_;
static bool **enableUserExceptionHandlersForCPUExcLoc;
static bool enableUserExceptionHandlersForCPUExc = true;
static void setupSvcHandler(void)
{
swapHandlerInVeneer(SVC, svcHandler);
void **arm11SvcTable = (void**)originalHandlers[(u32)SVC];
while(*arm11SvcTable != NULL) arm11SvcTable++; //Look for SVC0 (NULL)
memcpy(officialSVCs, arm11SvcTable, 4 * 0x7E);
u32 *off;
for(off = (u32 *)officialSVCs[0x2D]; *off != 0x65736162; off++);
*(void **)PA_FROM_VA_PTR(arm11SvcTable + 0x2D) = officialSVCs[0x2D] = (void *)off[1];
trampo_ = (u32 *)PA_FROM_VA_PTR(off + 3);
CustomBackdoor = (Result (*)(void *, ...))((u32 *)officialSVCs[0x2F] + 2);
*(void **)PA_FROM_VA_PTR(arm11SvcTable + 0x2F) = officialSVCs[0x2F] = (void *)*((u32 *)officialSVCs[0x2F] + 1);
off = (u32 *)originalHandlers[(u32) SVC];
while(*off++ != 0xE1A00009);
svcFallbackHandler = (void (*)(u8))decodeARMBranch(off);
for(; *off != 0xE92D000F; off++);
PostprocessSvc = (void (*)(void))decodeARMBranch(off + 1);
}
static void setupExceptionHandlers(void)
{
swapHandlerInVeneer(FIQ, FIQHandler);
swapHandlerInVeneer(UNDEFINED_INSTRUCTION, undefinedInstructionHandler);
swapHandlerInVeneer(PREFETCH_ABORT, prefetchAbortHandler);
swapHandlerInVeneer(DATA_ABORT, dataAbortHandler);
setupSvcHandler();
kernelVersion = *(vu32 *)configPage;
*(vu32 *)(configPage + 0x40) = fcramLayout.applicationSize;
*(vu32 *)(configPage + 0x44) = fcramLayout.systemSize;
*(vu32 *)(configPage + 0x48) = fcramLayout.baseSize;
*isDevUnit = true; // enable debug features
}
static void findUsefulSymbols(void)
{
u32 *off;
for(off = (u32 *)0xFFFF0000; *off != 0xE1A0D002; off++);
off += 3;
initFPU = (void (*) (void))off;
for(; *off != 0xE3A0A0C2; off++);
mcuReboot = (void (*) (void))--off;
coreBarrier = (void (*) (void))decodeARMBranch(off - 4);
for(off = (u32 *)originalHandlers[2]; *off != 0xE1A00009; off++);
svcFallbackHandler = (void (*)(u8))decodeARMBranch(off + 1);
for(; *off != 0xE92D000F; off++);
officialPostProcessSvc = (void (*)(void))decodeARMBranch(off + 1);
KProcessHandleTable__ToKProcess = (KProcess * (*)(KProcessHandleTable *, Handle))decodeARMBranch(5 + (u32 *)officialSVCs[0x76]);
for(off = (u32 *)KProcessHandleTable__ToKProcess; *off != 0xE28DD014; off++);
KAutoObject__AddReference = (void (*)(KAutoObject *))decodeARMBranch(off - 1);
for(off = (u32 *)KProcessHandleTable__ToKProcess; *off != 0xE1A00004; off++);
KAutoObject__AddReference = (void (*)(KAutoObject *))decodeARMBranch(off + 1);
for(; *off != 0xE8BD80F0; off++);
KProcessHandleTable__ToKAutoObject = (KAutoObject * (*)(KProcessHandleTable *, Handle))decodeARMBranch(off + 2);
for(; *off != 0xE320F000; off++);
KProcessHandleTable__ToKAutoObject = (KAutoObject * (*)(KProcessHandleTable *, Handle))decodeARMBranch(off + 1);
for(off = (u32 *)decodeARMBranch(3 + (u32 *)officialSVCs[9]); /* KThread::Terminate */ *off != 0xE5D42034; off++);
off -= 2;
@@ -121,26 +135,30 @@ static void findUsefulSymbols(void)
for(off = (u32 *)officialSVCs[0x19]; *off != 0xE1A04005; off++);
KEvent__Clear = (Result (*)(KEvent *))decodeARMBranch(off + 1);
for(off = (u32 *)KEvent__Clear; *off != 0xE8BD8070; off++)
for(off = (u32 *)KEvent__Clear; *off != 0xE8BD8070; off++);
synchronizationMutex = *(KObjectMutex **)(off + 1);
for(off = (u32 *)officialSVCs[0x24]; *off != 0xE59F004C; off++);
WaitSynchronization1 = (Result (*)(void *, KThread *, KSynchronizationObject *, s64))decodeARMBranch(off + 6);
for(off = (u32 *)decodeARMBranch(3 + (u32 *)officialSVCs[0x33]) /* OpenProcess */ ; *off != 0xE20030FF; off++);
KProcessHandleTable__CreateHandle = (Result (*)(KProcessHandleTable *, Handle *, KAutoObject *, u8))decodeARMBranch(off + 2);
for(off = (u32 *)decodeARMBranch(3 + (u32 *)officialSVCs[0x33]) /* OpenProcess */ ; *off != 0xE1A05000; off++);
KProcessHandleTable__CreateHandle = (Result (*)(KProcessHandleTable *, Handle *, KAutoObject *, u8))decodeARMBranch(off - 1);
for(off = (u32 *)decodeARMBranch(3 + (u32 *)officialSVCs[0x34]) /* OpenThread */; *off != 0xD9001BF7; off++);
threadList = *(KObjectList **)(off + 1);
KProcessHandleTable__ToKThread = (KThread * (*)(KProcessHandleTable *, Handle))decodeARMBranch((u32 *)decodeARMBranch((u32 *)officialSVCs[0x37] + 3) /* GetThreadId */ + 5);
for(off = (u32 *)officialSVCs[0x50]; off[0] != 0xE1A05000 || off[1] != 0xE2100102 || off[2] != 0x5A00000B; off++);
InterruptManager__MapInterrupt = (Result (*)(InterruptManager *, KBaseInterruptEvent *, u32, u32, u32, bool, bool))decodeARMBranch(--off);
interruptManager = *(InterruptManager **)(off - 4 + (off[-6] & 0xFFF) / 4);
for(off = (u32 *)officialSVCs[0x54]; *off != 0xE8BD8008; off++);
flushDataCacheRange = (void (*)(void *, u32))(*(u32 **)(off[1]) + 3);
for(off = (u32 *)officialSVCs[0x71]; *off != 0xE2101102; off++);
KProcessHwInfo__MapProcessMemory = (Result (*)(KProcessHwInfo *, KProcessHwInfo *, void *, void *, u32))decodeARMBranch(off - 1);
// From 4.x to 6.x the pattern will match but the result will be wrong
for(off = (u32 *)officialSVCs[0x72]; *off != 0xE2041102; off++);
KProcessHwInfo__UnmapProcessMemory = (Result (*)(KProcessHwInfo *, void *, u32))decodeARMBranch(off - 1);
@@ -149,7 +167,7 @@ static void findUsefulSymbols(void)
for(; *off != 0xE320F000; off++);
KObjectMutex__ErrorOccured = (void (*)(void))decodeARMBranch(off + 1);
for(off = (u32 *)originalHandlers[(u32) DATA_ABORT]; *off != (u32)exceptionStackTop; off++);
for(off = (u32 *)originalHandlers[4]; *off != (u32)exceptionStackTop; off++);
kernelUsrCopyFuncsStart = (void *)off[1];
kernelUsrCopyFuncsEnd = (void *)off[2];
@@ -190,6 +208,7 @@ static void findUsefulSymbols(void)
decodeARMBranch((u32 *)officialSVCs[0x01] + 5);
SleepThread = (void (*)(s64))officialSVCs[0x0A];
CloseHandle = (Result (*)(Handle))officialSVCs[0x23];
GetHandleInfo = (Result (*)(s64 *, Handle, u32))decodeARMBranch((u32 *)officialSVCs[0x29] + 3);
GetSystemInfo = (Result (*)(s64 *, s32, s32))decodeARMBranch((u32 *)officialSVCs[0x2A] + 3);
GetProcessInfo = (Result (*)(s64 *, Handle, u32))decodeARMBranch((u32 *)officialSVCs[0x2B] + 3);
GetThreadInfo = (Result (*)(s64 *, Handle, u32))decodeARMBranch((u32 *)officialSVCs[0x2C] + 3);
@@ -198,26 +217,25 @@ static void findUsefulSymbols(void)
OpenProcess = (Result (*)(Handle *, u32))decodeARMBranch((u32 *)officialSVCs[0x33] + 3);
GetProcessId = (Result (*)(u32 *, Handle))decodeARMBranch((u32 *)officialSVCs[0x35] + 3);
DebugActiveProcess = (Result (*)(Handle *, u32))decodeARMBranch((u32 *)officialSVCs[0x60] + 3);
UnmapProcessMemory = (Result (*)(Handle, void *, u32))officialSVCs[0x72];
KernelSetState = (Result (*)(u32, u32, u32, u32))((u32 *)officialSVCs[0x7C] + 1);
for(off = (u32 *)svcFallbackHandler; *off != 0xE8BD4010; off++);
kernelpanic = (void (*)(void))off;
kernelpanic = (void (*)(void))decodeARMBranch(off + 1);
for(off = (u32 *)0xFFFF0000; off[0] != 0xE3A01002 || off[1] != 0xE3A00004; off++);
SignalDebugEvent = (Result (*)(DebugEventType type, u32 info, ...))decodeARMBranch(off + 2);
for(; *off != 0x96007F9; off++);
isDevUnit = *(bool **)(off - 1);
enableUserExceptionHandlersForCPUExcLoc = (bool **)(off + 1);
///////////////////////////////////////////
// Shitty/lazy heuristic but it works on even 4.5, so...
u32 textStart = ((u32)originalHandlers[(u32) SVC]) & ~0xFFFF;
u32 rodataStart = (u32)(interruptManager->N3DS.privateInterrupts[0][6].interruptEvent->vtable) & ~0xFFF;
u32 textStart = ((u32)originalHandlers[2]) & ~0xFFFF;
u32 rodataStart = (u32)(interruptManager->N3DS.privateInterrupts[1][0x1D].interruptEvent->vtable) & ~0xFFF;
u32 textSize = rodataStart - textStart;
for(off = (u32 *)textStart; off < (u32 *)(textStart + textSize) - 3; off++)
for(off = (u32 *)textStart; off < (u32 *)(textStart + textSize - 12); off++)
{
if(off[0] == 0xE5D13034 && off[1] == 0xE1530002)
KScheduler__AdjustThread = (void (*)(KScheduler *, KThread *, u32))off;
@@ -232,79 +250,33 @@ static void findUsefulSymbols(void)
}
}
struct Parameters
void main(FcramLayout *layout, KCoreContext *ctxs)
{
void (*SGI0HandlerCallback)(struct Parameters *, u32 *);
InterruptManager *interruptManager;
u32 *L2MMUTable; // bit31 mapping
struct KExtParameters *p = &kExtParameters;
u32 TTBCR_;
s64 nb;
void (*initFPU)(void);
void (*mcuReboot)(void);
void (*coreBarrier)(void);
layout->systemSize -= __end__ - __start__;
fcramLayout = *layout;
coreCtxs = ctxs;
u32 TTBCR;
u32 L1MMUTableAddrs[4];
u32 kernelVersion;
CfwInfo cfwInfo;
};
static void enableDebugFeatures(void)
{
*isDevUnit = true; // for debug SVCs and user exc. handlers, etc.
*(bool **)PA_FROM_VA_PTR(enableUserExceptionHandlersForCPUExcLoc) = &enableUserExceptionHandlersForCPUExc;
u32 *off;
for(off = (u32 *)officialSVCs[0x7C]; off[0] != 0xE5D00001 || off[1] != 0xE3500000; off++);
*(u32 *)PA_FROM_VA_PTR(off + 2) = 0xE1A00000; // in case 6: beq -> nop
for(off = (u32 *)DebugActiveProcess; *off != 0xE3110001; off++);
*(u32 *)PA_FROM_VA_PTR(off) = 0xE3B01001; // tst r1, #1 -> movs r1, #1
}
static void doOtherPatches(void)
{
u32 *kpanic = (u32 *)kernelpanic;
*(u32 *)PA_FROM_VA_PTR(kpanic) = 0xE12FFF7E; // bkpt 0xFFFE
u32 *off;
for(off = (u32 *)ControlMemory; (off[0] & 0xFFF0FFFF) != 0xE3500001 || (off[1] & 0xFFFF0FFF) != 0x13A00000; off++);
off -= 2;
/*
Here we replace currentProcess->processID == 1 by additionnalParameter == 1.
This patch should be generic enough to work even on firmware version 5.0.
It effectively changes the prototype of the ControlMemory function which
only caller is the svc 0x01 handler on OFW.
*/
*(u32 *)PA_FROM_VA_PTR(off) = 0xE59D0000 | (*off & 0x0000F000) | (8 + computeARMFrameSize((u32 *)ControlMemory)); // ldr r0, [sp, #(frameSize + 8)]
}
void main(volatile struct Parameters *p)
{
__asm__ __volatile__("mrc p15, 0, %0, c2, c0, 2" : "=r"(TTBCR_));
TTBCR = TTBCR_;
isN3DS = getNumberOfCores() == 4;
interruptManager = p->interruptManager;
initFPU = p->initFPU;
mcuReboot = p->mcuReboot;
coreBarrier = p->coreBarrier;
TTBCR = p->TTBCR;
memcpy(L1MMUTableAddrs, (const void *)p->L1MMUTableAddrs, 16);
exceptionStackTop = (u32 *)0xFFFF2000 + (1 << (32 - TTBCR - 20));
kernelVersion = p->kernelVersion;
cfwInfo = p->cfwInfo;
setupSGI0Handler();
setupExceptionHandlers();
memcpy(originalHandlers + 1, p->originalHandlers, 16);
void **arm11SvcTable = (void**)originalHandlers[2];
while(*arm11SvcTable != NULL) arm11SvcTable++; //Look for SVC0 (NULL)
memcpy(officialSVCs, arm11SvcTable, 4 * 0x7E);
findUsefulSymbols();
enableDebugFeatures();
doOtherPatches();
GetSystemInfo(&nb, 26, 0);
nbSection0Modules = (u32)nb;
rosalinaState = 0;
hasStartedRosalinaNetworkFuncsOnce = false;
*trampo_ = (u32)ConnectToPortHookWrapper;
}

View File

@@ -22,40 +22,51 @@
@ or requiring that modified versions of such material be marked in
@ reasonable ways as different from the original version.
.text
.arm
.section .text.start
.balign 4
.global _start
_start:
b start
b startPhys
.global svc0x2F
.type svc0x2F, %function
svc0x2F:
@ custom backdoor before kernel ext. is installed
svc 0x2F
b _bindSGI0Hook
b configHook
b undefinedInstructionHandler
b svcHandler
b prefetchAbortHandler
b dataAbortHandler
.word __end__
.word kExtParameters
.word 1 @ enableUserExceptionHandlersForCPUExc
b KThread__DebugReschedule
start:
@ Only core0 executes this, the other cores are running coreBarrier
@ Skipped instruction:
str r1, [r4, #0x8]
push {r0-r12, lr}
sub r0, r4, #8
sub r1, r8, #0x8000
bl main
pop {r0-r12, pc}
startPhys:
push {r0-r12, lr}
mrc p15, 0, r0, c0, c0, 5 @ CPUID register
and r0, #3
mov r1, r2
bl relocateAndSetupMMU
pop {r0-r12, lr}
mov r12, #0x20000000 @ instruction that has been patched
bx lr
.global convertVAToPA
.type convertVAToPA, %function
convertVAToPA:
@ needs to be executed in supervisor mode
mov r1, #0x1000
sub r1, #1
and r2, r0, r1
bic r0, r1
mcr p15, 0, r0, c7, c8, 0 @ VA to PA translation with privileged read permission check
mrc p15, 0, r0, c7, c4, 0 @ read PA register
tst r0, #1 @ failure bit
bic r0, r1
addeq r0, r2
movne r0, #0
bx lr
.section .data
.p2align 12
.global kernel_extension
kernel_extension: .incbin "build/kernel_extension.bin"
.p2align 12
kernel_extension_end:
.global kernel_extension_size
kernel_extension_size: .word kernel_extension_end - kernel_extension
_bindSGI0Hook:
push {r0-r12, lr}
bl bindSGI0Hook
pop {r0-r12, pc}

View File

@@ -24,11 +24,14 @@
* reasonable ways as different from the original version.
*/
#include "memory.h"
#include "synchronization.h"
#include "svc.h"
#include "svc/ControlMemory.h"
#include "svc/GetHandleInfo.h"
#include "svc/GetSystemInfo.h"
#include "svc/GetProcessInfo.h"
#include "svc/GetThreadInfo.h"
#include "svc/GetSystemInfo.h"
#include "svc/GetCFWInfo.h"
#include "svc/ConnectToPort.h"
#include "svc/SendSyncRequest.h"
@@ -37,6 +40,7 @@
#include "svc/SetWifiEnabled.h"
#include "svc/Backdoor.h"
#include "svc/KernelSetState.h"
#include "svc/CustomBackdoor.h"
#include "svc/MapProcessMemoryEx.h"
#include "svc/UnmapProcessMemoryEx.h"
#include "svc/ControlService.h"
@@ -45,24 +49,11 @@
void *officialSVCs[0x7E] = {NULL};
static inline void yieldDuringRosalinaMenu(void)
{
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
u64 titleId = codeSetOfProcess(currentProcess)->titleId;
u32 highTitleId = (u32)(titleId >> 32), lowTitleId = (u32)titleId;
while((rosalinaState & 1) && idOfProcess(currentProcess) >= 6 &&
(highTitleId != 0x00040130 || (highTitleId == 0x00040130 && (lowTitleId == 0x1A02 || lowTitleId == 0x1C02))))
SleepThread(25 * 1000 * 1000LL);
}
void signalSvcEntry(u8 *pageEnd)
{
u32 svcId = (u32) *(u8 *)(pageEnd - 0xB5);
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
yieldDuringRosalinaMenu();
if(svcId == 0xFE)
svcId = *(u32 *)(pageEnd - 0x110 + 8 * 4); // r12 ; note: max theortical SVC atm: 0x3FFFFFFF. We don't support catching svcIds >= 0x100 atm either
@@ -76,8 +67,6 @@ void signalSvcReturn(u8 *pageEnd)
u32 svcId = (u32) *(u8 *)(pageEnd - 0xB5);
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
yieldDuringRosalinaMenu();
if(svcId == 0xFE)
svcId = *(u32 *)(pageEnd - 0x110 + 8 * 4); // r12 ; note: max theortical SVC atm: 0x1FFFFFFF. We don't support catching svcIds >= 0x100 atm either
@@ -86,6 +75,17 @@ void signalSvcReturn(u8 *pageEnd)
SignalDebugEvent(DBGEVENT_OUTPUT_STRING, 0xFFFFFFFF, svcId);
}
void postprocessSvc(void)
{
KThread *currentThread = currentCoreContext->objectContext.currentThread;
if(!currentThread->shallTerminate && rosalinaThreadLockPredicate(currentThread))
rosalinaRescheduleThread(currentThread, true);
officialPostProcessSvc();
}
static bool doingVeryShittyPmResLimitWorkaround = false; // I feel dirty
void *svcHook(u8 *pageEnd)
{
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
@@ -97,6 +97,15 @@ void *svcHook(u8 *pageEnd)
{
case 0x01:
return ControlMemoryHookWrapper;
case 0x17:
if(strcmp(codeSetOfProcess(currentProcess)->processName, "pm") == 0) // only called twice in pm, by the same function
{
*(vu32 *)(configPage + 0x44) += __end__ - __start__;
doingVeryShittyPmResLimitWorkaround = true;
}
return officialSVCs[0x17];
case 0x29:
return GetHandleInfoHookWrapper;
case 0x2A:
return GetSystemInfoHookWrapper;
case 0x2B:
@@ -115,6 +124,13 @@ void *svcHook(u8 *pageEnd)
return SetGpuProt;
case 0x5A:
return SetWifiEnabled;
case 0x79:
if(doingVeryShittyPmResLimitWorkaround)
{
*(vu32 *)(configPage + 0x44) -= __end__ - __start__;
doingVeryShittyPmResLimitWorkaround = false;
}
return officialSVCs[0x79];
case 0x7B:
return Backdoor;
case 0x7C:

View File

@@ -42,20 +42,12 @@ Result ControlService(ServiceOp op, u32 varg1, u32 varg2)
KAutoObject *obj = KProcessHandleTable__ToKAutoObject(handleTable, (Handle)varg2);
if(obj == NULL)
return 0xD8E007F7; // invalid handle
else if(kernelVersion >= SYSTEM_VERSION(2, 46, 0))
{
KClassToken tok;
obj->vtable->GetClassToken(&tok, obj);
if(tok.flags == 0x95)
session = ((KServerSession *)obj)->parentSession;
else if(tok.flags == 0xA5)
session = ((KClientSession *)obj)->parentSession;
}
else
{ // not the exact same tests but it should work
if(strcmp(obj->vtable->GetClassName(obj), "KServerSession") == 0)
{
// not the exact same tests but it should work
if(strcmp(classNameOfAutoObject(obj), "KServerSession") == 0)
session = ((KServerSession *)obj)->parentSession;
else if(strcmp(obj->vtable->GetClassName(obj), "KClientSession") == 0)
else if(strcmp(classNameOfAutoObject(obj), "KClientSession") == 0)
session = ((KClientSession *)obj)->parentSession;
}

View File

@@ -22,34 +22,17 @@
@ or requiring that modified versions of such material be marked in
@ reasonable ways as different from the original version.
.section .text.start
.text
.arm
.balign 4
.global _start
_start:
.global CustomBackdoor
.type CustomBackdoor, %function
CustomBackdoor:
push {r4, lr}
mrc p15, 0, r4, c0, c0, 5 @ CPUID register
and r4, #3
cmp r4, #1
beq _core1_only
_waitLoop:
wfe
ldr r0, =_setupFinished
ldr r0, [r0]
cmp r0, #0
beq _waitLoop
b end
_core1_only:
bl main
ldr r0, =_setupFinished
str r4, [r0]
sev
end:
mov r4, r0
mov r0, r1
mov r1, r2
mov r2, r3
blx r4
pop {r4, pc}
.bss
.balign 4
_setupFinished: .word 0

View File

@@ -0,0 +1,62 @@
/*
* 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 "svc/GetThreadInfo.h"
#include "memory.h"
Result GetHandleInfoHook(s64 *out, Handle handle, u32 type)
{
if(type == 0x10000) // KDebug and KProcess: get context ID
{
KProcessHwInfo *hwInfo;
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
KAutoObject *obj;
if(handle == CUR_PROCESS_HANDLE)
{
obj = (KAutoObject *)(currentCoreContext->objectContext.currentProcess);
KAutoObject__AddReference(obj);
}
else
obj = KProcessHandleTable__ToKAutoObject(handleTable, handle);
if(obj == NULL)
return 0xD8E007F7;
if(strcmp(classNameOfAutoObject(obj), "KDebug") == 0)
hwInfo = hwInfoOfProcess(((KDebug *)obj)->owner);
else if(strcmp(classNameOfAutoObject(obj), "KProcess") == 0)
hwInfo = hwInfoOfProcess((KProcess *)obj);
else
hwInfo = NULL;
*out = hwInfo != NULL ? KPROCESSHWINFO_GET_RVALUE(hwInfo, contextId) : -1;
obj->vtable->DecrementReferenceCount(obj);
return 0;
}
else
return GetHandleInfo(out, handle, type);
}

View File

@@ -73,12 +73,12 @@ Result GetProcessInfoHook(s64 *out, Handle processHandle, u32 type)
*out = (s64)(u64)(u32)codeSetOfProcess(process)->dataSection.section.loadAddress;
break;
case 0x10008:
*out = (isN3DS ? hwInfoOfProcess(process)->N3DS.translationTableBase :
(kernelVersion >= SYSTEM_VERSION(2, 44, 6)
? hwInfoOfProcess(process)->O3DS8x.translationTableBase
: hwInfoOfProcess(process)->O3DSPre8x.translationTableBase)
) & ~((1 << (14 - TTBCR)) - 1);
{
KProcessHwInfo *hwInfo = hwInfoOfProcess(process);
u32 ttb = KPROCESSHWINFO_GET_RVALUE(hwInfo, translationTableBase);
*out = ttb & ~((1 << (14 - TTBCR)) - 1);
break;
}
default:
res = 0xD8E007ED; // invalid enum value
break;

View File

@@ -46,18 +46,35 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param)
*out = cfwInfo.commitHash;
break;
case 2:
*out = (cfwInfo.configFormatVersionMajor << 16) | cfwInfo.configFormatVersionMinor;
break;
case 3:
*out = cfwInfo.config;
break;
case 3: // isRelease
case 4:
*out = cfwInfo.multiConfig;
break;
case 5:
*out = cfwInfo.bootConfig;
break;
case 0x100:
*out = (s64)cfwInfo.hbldr3dsxTitleId;
break;
case 0x101:
*out = cfwInfo.rosalinaMenuCombo;
break;
case 0x200: // isRelease
*out = cfwInfo.flags & 1;
break;
case 4: // isN3DS
case 0x201: // isN3DS
*out = (cfwInfo.flags >> 4) & 1;
break;
case 5: // isSafeMode
case 0x202: // isSafeMode
*out = (cfwInfo.flags >> 5) & 1;
break;
case 6: // isSdMode
case 0x203: // isSdMode
*out = (cfwInfo.flags >> 6) & 1;
break;
default:

View File

@@ -27,6 +27,7 @@
#include "svc/KernelSetState.h"
#include "synchronization.h"
#include "ipc.h"
#include "debug.h"
#include "memory.h"
#define MAX_DEBUG 3
@@ -107,6 +108,11 @@ Result KernelSetStateHook(u32 type, u32 varg1, u32 varg2, u32 varg3)
if(rosalinaState & 2)
hasStartedRosalinaNetworkFuncsOnce = true;
if(rosalinaState & 1)
rosalinaLockAllThreads();
else if(varg1 & 1)
rosalinaUnlockAllThreads();
break;
}
case 0x10001:
@@ -122,7 +128,7 @@ Result KernelSetStateHook(u32 type, u32 varg1, u32 varg2, u32 varg3)
processLangemuAttributes[i].state = (u8)(varg1 >> 24);
processLangemuAttributes[i].country = (u8)(varg1 >> 16);
processLangemuAttributes[i].language = (u8)(varg1 >> 8);
processLangemuAttributes[i].region = (u8)(varg1 >> 4);
processLangemuAttributes[i].region = (u8)((varg1 >> 4) & 0xf);
processLangemuAttributes[i].mask = (u8)(varg1 & 0xf);
}
else
@@ -137,7 +143,41 @@ Result KernelSetStateHook(u32 type, u32 varg1, u32 varg2, u32 varg3)
res = SetSyscallDebugEventMask(varg1, (bool)varg2, (const u32 *)varg3);
break;
}
case 0x10003:
{
executeFunctionOnCores(enableMonitorModeDebugging, 0xF, 0);
break;
}
case 0x10004:
{
KRecursiveLock__Lock(&dbgParamsLock);
dbgParamWatchpointId = varg1;
executeFunctionOnCores(disableWatchpoint, 0xF, 0);
KRecursiveLock__Unlock(&dbgParamsLock);
break;
}
case 0x10005:
{
KRecursiveLock__Lock(&dbgParamsLock);
dbgParamWatchpointId = 0;
dbgParamDVA = varg1;
dbgParamWCR = varg2;
dbgParamContextId = varg3;
executeFunctionOnCores(setWatchpointWithContextId, 0xF, 0);
KRecursiveLock__Unlock(&dbgParamsLock);
break;
}
case 0x10006:
{
KRecursiveLock__Lock(&dbgParamsLock);
dbgParamWatchpointId = 1;
dbgParamDVA = varg1;
dbgParamWCR = varg2;
dbgParamContextId = varg3;
executeFunctionOnCores(setWatchpointWithContextId, 0xF, 0);
KRecursiveLock__Unlock(&dbgParamsLock);
break;
}
default:
{
res = KernelSetState(type, varg1, varg2, varg3);

View File

@@ -37,15 +37,8 @@ Result SendSyncRequestHook(Handle handle)
bool skip = false;
Result res = 0;
bool isValidClientSession = false;
if(clientSession != NULL && kernelVersion >= SYSTEM_VERSION(2, 46, 0))
{
KClassToken tok;
clientSession->syncObject.autoObject.vtable->GetClassToken(&tok, &clientSession->syncObject.autoObject);
isValidClientSession = tok.flags == 0xA5;
}
else if(clientSession != NULL) // not the exact same test but it should work
isValidClientSession = strcmp(clientSession->syncObject.autoObject.vtable->GetClassName(&clientSession->syncObject.autoObject), "KClientSession");
// not the exact same test but it should work
bool isValidClientSession = clientSession != NULL && strcmp(classNameOfAutoObject(&clientSession->syncObject.autoObject), "KClientSession") == 0;
if(isValidClientSession)
{
@@ -54,7 +47,7 @@ Result SendSyncRequestHook(Handle handle)
case 0x10042:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "srv:pm") == 0)
if(info != NULL && kernelVersion >= SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0)
{
res = doPublishToProcessHook(handle, cmdbuf);
skip = true;
@@ -73,7 +66,7 @@ Result SendSyncRequestHook(Handle handle)
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && (strcmp(info->name, "cfg:u") == 0 || strcmp(info->name, "cfg:s") == 0 || strcmp(info->name, "cfg:i") == 0)) // GetConfigInfoBlk2
skip = doLangEmu(&res, handle, cmdbuf);
skip = doLangEmu(&res, cmdbuf);
break;
}
@@ -91,7 +84,7 @@ Result SendSyncRequestHook(Handle handle)
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && (strcmp(info->name, "cfg:u") == 0 || strcmp(info->name, "cfg:s") == 0 || strcmp(info->name, "cfg:i") == 0)) // SecureInfoGetRegion
skip = doLangEmu(&res, handle, cmdbuf);
skip = doLangEmu(&res, cmdbuf);
break;
}
@@ -112,7 +105,7 @@ Result SendSyncRequestHook(Handle handle)
case 0x50100:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "srv:") == 0)
if(info != NULL && (strcmp(info->name, "srv:") == 0 || (kernelVersion < SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0)))
{
char name[9] = { 0 };
memcpy(name, cmdbuf + 1, 8);
@@ -126,7 +119,8 @@ Result SendSyncRequestHook(Handle handle)
outClientSession = (KClientSession *)KProcessHandleTable__ToKAutoObject(handleTable, (Handle)cmdbuf[3]);
if(outClientSession != NULL)
{
SessionInfo_Add(outClientSession->parentSession, name);
if(strcmp(classNameOfAutoObject(&outClientSession->syncObject.autoObject), "KClientSession") == 0)
SessionInfo_Add(outClientSession->parentSession, name);
outClientSession->syncObject.autoObject.vtable->DecrementReferenceCount(&outClientSession->syncObject.autoObject);
}
}
@@ -163,7 +157,7 @@ Result SendSyncRequestHook(Handle handle)
case 0x4010042:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "srv:pm") == 0)
if(info != NULL && kernelVersion < SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0)
{
res = doPublishToProcessHook(handle, cmdbuf);
skip = true;
@@ -176,7 +170,7 @@ Result SendSyncRequestHook(Handle handle)
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && (strcmp(info->name, "cfg:s") == 0 || strcmp(info->name, "cfg:i") == 0)) // GetConfigInfoBlk4
skip = doLangEmu(&res, handle, cmdbuf);
skip = doLangEmu(&res, cmdbuf);
break;
}
@@ -185,7 +179,7 @@ Result SendSyncRequestHook(Handle handle)
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && (strcmp(info->name, "cfg:s") == 0 || strcmp(info->name, "cfg:i") == 0)) // GetConfigInfoBlk8
skip = doLangEmu(&res, handle, cmdbuf);
skip = doLangEmu(&res, cmdbuf);
break;
}
@@ -194,7 +188,7 @@ Result SendSyncRequestHook(Handle handle)
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && (strcmp(info->name, "cfg:s") == 0 || strcmp(info->name, "cfg:i") == 0)) // GetConfigInfoBlk4
skip = doLangEmu(&res, handle, cmdbuf);
skip = doLangEmu(&res, cmdbuf);
break;
}
@@ -203,7 +197,7 @@ Result SendSyncRequestHook(Handle handle)
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "cfg:i") == 0) // GetConfigInfoBlk8
skip = doLangEmu(&res, handle, cmdbuf);
skip = doLangEmu(&res, cmdbuf);
break;
}
@@ -212,7 +206,7 @@ Result SendSyncRequestHook(Handle handle)
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); // SecureInfoGetRegion
if(info != NULL && (strcmp(info->name, "cfg:s") == 0 || strcmp(info->name, "cfg:i") == 0))
skip = doLangEmu(&res, handle, cmdbuf);
skip = doLangEmu(&res, cmdbuf);
break;
}
@@ -221,7 +215,7 @@ Result SendSyncRequestHook(Handle handle)
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); // SecureInfoGetRegion
if(info != NULL && strcmp(info->name, "cfg:i") == 0)
skip = doLangEmu(&res, handle, cmdbuf);
skip = doLangEmu(&res, cmdbuf);
break;
}

View File

@@ -26,10 +26,12 @@
#include "svc/SetWifiEnabled.h"
void SetWifiEnabled(bool enable)
Result SetWifiEnabled(bool enable)
{
if(enable)
CFG11_WIFICNT |= 1;
else
CFG11_WIFICNT &= ~1;
return 0;
}

View File

@@ -50,14 +50,7 @@ Result TranslateHandle(u32 *outKAddr, char *outClassName, Handle handle)
if(obj == NULL)
return 0xD8E007F7; // invalid handle
if(kernelVersion >= SYSTEM_VERSION(2, 46, 0))
{
KClassToken tok;
obj->vtable->GetClassToken(&tok, obj);
name = tok.name;
}
else
name = obj->vtable->GetClassName(obj);
name = classNameOfAutoObject(obj);
if(name == NULL) // shouldn't happen
name = "KAutoObject";

View File

@@ -24,10 +24,14 @@
* reasonable ways as different from the original version.
*/
#include "globals.h"
#include "svc/MapProcessMemoryEx.h"
Result UnmapProcessMemoryEx(Handle processHandle UNUSED, void *dst, u32 size)
Result UnmapProcessMemoryEx(Handle processHandle, void *dst, u32 size)
{
if(kernelVersion < SYSTEM_VERSION(2, 37, 0)) // < 6.x
return UnmapProcessMemory(processHandle, dst, size); // equivalent when size <= 64MB
KProcessHwInfo *currentHwInfo = hwInfoOfProcess(currentCoreContext->objectContext.currentProcess);
Result res = KProcessHwInfo__UnmapProcessMemory(currentHwInfo, dst, size >> 12);

View File

@@ -37,6 +37,7 @@
pop {r1, r2, r12, pc}
.endm
GEN_GETINFO_WRAPPER Handle
GEN_GETINFO_WRAPPER System
GEN_GETINFO_WRAPPER Process
GEN_GETINFO_WRAPPER Thread

View File

@@ -113,9 +113,7 @@ svcHandler:
push {r0-r7, r12, lr}
push {r0-r3}
ldr r0, =PostprocessSvc
ldr r0, [r0]
blx r0
bl postprocessSvc
pop {r0-r3}
ldrb lr, [sp, #0x58+0] @ page end - 0xb8 + 0: scheduling flags

View File

@@ -0,0 +1,160 @@
/*
* 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 "synchronization.h"
#include "utils.h"
#include "kernel.h"
#include "globals.h"
extern SGI0Handler_t SGI0Handler;
void executeFunctionOnCores(SGI0Handler_t handler, u8 targetList, u8 targetListFilter)
{
u32 coreID = getCurrentCoreID();
SGI0Handler = handler;
if(targetListFilter == 0 && (targetListFilter & (1 << coreID)) != 0)
__enable_irq(); // make sure interrupts aren't masked
MPCORE_GID_SGI = (targetListFilter << 24) | (targetList << 16) | 0;
}
void KScheduler__TriggerCrossCoreInterrupt(KScheduler *this)
{
this->triggerCrossCoreInterrupt = false;
for(s16 i = 0; i < (s16)getNumberOfCores(); i++)
{
if(this->coreNumber != i)
MPCORE_GID_SGI = (1 << (16 + i)) | 8;
}
}
void KThread__DebugReschedule(KThread *this, bool lock)
{
KRecursiveLock__Lock(criticalSectionLock);
u32 oldSchedulingMask = this->schedulingMask;
if(lock) // the original k11 function discards the other flags
this->schedulingMask |= 0x80;
else
this->schedulingMask &= ~0x80;
KScheduler__AdjustThread(currentCoreContext->objectContext.currentScheduler, this, oldSchedulingMask);
KRecursiveLock__Unlock(criticalSectionLock);
}
bool rosalinaThreadLockPredicate(KThread *thread)
{
KProcess *process = thread->ownerProcess;
if(process == NULL)
return false;
u64 titleId = codeSetOfProcess(process)->titleId;
u32 highTitleId = (u32)(titleId >> 32), lowTitleId = (u32)titleId;
return
((rosalinaState & 1) && idOfProcess(process) >= nbSection0Modules &&
(highTitleId != 0x00040130 || (highTitleId == 0x00040130 && (lowTitleId == 0x1A02 || lowTitleId == 0x1C02))));
}
void rosalinaRescheduleThread(KThread *thread, bool lock)
{
KRecursiveLock__Lock(criticalSectionLock);
u32 oldSchedulingMask = thread->schedulingMask;
if(lock)
thread->schedulingMask |= 0x40;
else
thread->schedulingMask &= ~0x40;
KScheduler__AdjustThread(currentCoreContext->objectContext.currentScheduler, thread, oldSchedulingMask);
KRecursiveLock__Unlock(criticalSectionLock);
}
void rosalinaLockThread(KThread *thread)
{
KThread *syncThread = synchronizationMutex->owner;
if(syncThread == NULL || syncThread != thread)
rosalinaRescheduleThread(thread, true);
}
void rosalinaLockAllThreads(void)
{
bool currentThreadsFound = false;
KRecursiveLock__Lock(criticalSectionLock);
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
{
KThread *thread = (KThread *)node->key;
if(!rosalinaThreadLockPredicate(thread))
continue;
if(thread == coreCtxs[thread->coreId].objectContext.currentThread)
currentThreadsFound = true;
else
rosalinaLockThread(thread);
}
if(currentThreadsFound)
{
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
{
KThread *thread = (KThread *)node->key;
if(!rosalinaThreadLockPredicate(thread))
continue;
if(!(thread->schedulingMask & 0x40))
{
rosalinaLockThread(thread);
KRecursiveLock__Lock(criticalSectionLock);
if(thread->coreId != getCurrentCoreID())
{
u32 cpsr = __get_cpsr();
__disable_irq();
coreCtxs[thread->coreId].objectContext.currentScheduler->triggerCrossCoreInterrupt = true;
currentCoreContext->objectContext.currentScheduler->triggerCrossCoreInterrupt = true;
__set_cpsr_cx(cpsr);
}
KRecursiveLock__Unlock(criticalSectionLock);
}
}
KScheduler__TriggerCrossCoreInterrupt(currentCoreContext->objectContext.currentScheduler);
}
KRecursiveLock__Unlock(criticalSectionLock);
}
void rosalinaUnlockAllThreads(void)
{
for(KLinkedListNode *node = threadList->list.nodes.first; node != (KLinkedListNode *)&threadList->list.nodes; node = node->next)
{
KThread *thread = (KThread *)node->key;
if((thread->schedulingMask & 0xF) == 2) // thread is terminating
continue;
if(thread->schedulingMask & 0x40)
rosalinaRescheduleThread(thread, false);
}
}

View File

@@ -1,73 +0,0 @@
.arm.little
.create "build/k11MainHook.bin", 0
.arm
bindSGI0:
; hook __kernel_main to bind SGI0 for own purposes
push {r0-r4, lr}
sub sp, #16 ; 3 args passed through the stack + alignment
ldr r0, [interruptManager]
adr r1, interruptEvent
mov r2, #0
mrc p15, 0, r3, c0, c0, 5
and r3, #3
mov r4, #0
str r4, [sp]
str r4, [sp, #4]
str r4, [sp, #8]
ldr r12, [InterruptManager_mapInterrupt]
blx r12
cmp r0, #0
blt .
add sp, #16
pop {r0-r4, pc}
executeCustomHandler:
push {r4, lr}
mrs r4, cpsr
adr r0, customHandler
bl convertVAToPA
orr r0, #(1 << 31)
ldr r12, [r0]
blx r12
mov r0, #0
msr cpsr_cx, r4
pop {r4, pc}
convertVAToPA:
mov r1, #0x1000
sub r1, #1
and r2, r0, r1
bic r0, r1
mcr p15, 0, r0, c7, c8, 0 ; VA to PA translation with privileged read permission check
mrc p15, 0, r0, c7, c4, 0 ; read PA register
tst r0, #1 ; failure bit
bic r0, r1
addeq r0, r2
movne r0, #0
bx lr
.pool
; Result InterruptManager::mapInterrupt(InterruptManager *this, InterruptEvent *iEvent, u32 interruptID, u32 coreID, s32 priority, bool willBeMasked, bool isLevelHighActive);
InterruptManager_mapInterrupt: .ascii "bind"
_vtable: .word executeCustomHandler
interruptEvent: .word _vtable
parameters:
customHandler: .ascii "hdlr"
interruptManager: .word 0
L2MMUTable: .word 0
funcs: .word 0,0,0
TTBCR: .word 0
L1MMUTableAddrs: .word 0,0,0,0
kernelVersion: .word 0
CFWInfo: .word 0,0,0,0
.close

View File

@@ -1,36 +0,0 @@
.arm.little
.create "build/mmuHook.bin", 0
.arm
; r2 = L1 table
; Thanks @Dazzozo for giving me that idea
; Maps physmem so that, if addr is in physmem(0, 0x30000000), it can be accessed uncached&rwx as addr|(1<<31)
; Save the value of all registers
push {r0-r1, r3-r7}
mov r0, #0
mov r1, #0x30000000 ; end address
ldr r3, =#0x40C02 ; supersection (rwx for all) of strongly ordered memory, shared
loop:
orr r4, r0, #0x80000000
orr r5, r0, r3
mov r6, #0 ;
loop2:
add r7, r6, r4,lsr #20
str r5, [r2, r7,lsl #2]
add r6, #1
cmp r6, #16
blo loop2
add r0, #0x01000000
cmp r0, r1
blo loop
pop {r0-r1, r3-r7}
mov r3, #0xe0000000 ; instruction that has been patched
bx lr
.pool
.close

View File

@@ -64,7 +64,7 @@ firm_maxsize equ 0x07FFF000
; Copy argv[0]
ldr r0, =fname_addr
adr r1, fname
mov r2, #42
mov r2, #82
bl memcpy16
ldr r0, =argv_addr
@@ -116,9 +116,7 @@ fname: .ascii "FILE"
.align 4
kernelcode_start:
mrs r0, cpsr ; disable interrupts
orr r0, #0xC0
msr cpsr, r0
msr cpsr_cxsf, #0xD3 ; disable interrupts and clear flags
ldr sp, =copy_launch_stub_stack_top
@@ -153,7 +151,7 @@ fname: .ascii "FILE"
movne r2, r8
blne memcpy32
add r5, #1
cmp r5, #3
cmp r5, #4
blo load_section_loop
mov r0, #2 ; argc

View File

@@ -1,43 +0,0 @@
.arm.little
.create "build/svcConnectToPortInitHook.bin", 0
.arm
push {r0-r4, lr}
adr r0, jumpAddress
bl convertVAToPA
orr r4, r0, #(1 << 31)
loop:
ldr r12, [r4]
cmp r12, #0
bne loop_end
ldr r12, [SleepThread]
ldr r0, =(10 * 1000 * 1000)
mov r1, #0
blx r12
b loop
loop_end:
pop {r0-r4, lr}
bx r12
convertVAToPA:
mov r1, #0x1000
sub r1, #1
and r2, r0, r1
bic r0, r1
mcr p15, 0, r0, c7, c8, 0 ; VA to PA translation with privileged read permission check
mrc p15, 0, r0, c7, c4, 0 ; read PA register
tst r0, #1 ; failure bit
bic r0, r1
addeq r0, r2
movne r0, #0
bx lr
.pool
_base: .ascii "base"
jumpAddressOrig: .ascii "orig"
SleepThread: .ascii "SlpT"
jumpAddress: .word 0
.close

View File

@@ -1,20 +0,0 @@
.arm.little
.create "build/svcCustomBackdoor.bin", 0
.arm
; Result svcCustomBackdoor(void *func, ... <up to 3 args>)
svcCustomBackdoor:
b skip_orig
orig: .word 0
skip_orig:
push {r4, lr}
mov r4, r0
mov r0, r1
mov r1, r2
mov r2, r3
blx r4
pop {r4, pc}
.pool
.close

View File

@@ -45,7 +45,8 @@
#define DPAD_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN)
#define SAFE_MODE (BUTTON_R1 | BUTTON_L1 | BUTTON_A | BUTTON_UP)
#define SINGLE_PAYLOAD_BUTTONS (DPAD_BUTTONS | BUTTON_B | BUTTON_X | BUTTON_Y)
#define SINGLE_PAYLOAD_BUTTONS (BUTTON_B | BUTTON_X | BUTTON_Y)
#define L_PAYLOAD_BUTTONS (BUTTON_R1 | BUTTON_A | BUTTON_START | BUTTON_SELECT)
#define MENU_BUTTONS (DPAD_BUTTONS | BUTTON_A | BUTTON_START)
#define PIN_BUTTONS (BUTTON_A | BUTTON_B | BUTTON_X | BUTTON_Y | DPAD_BUTTONS | BUTTON_START | BUTTON_SELECT)
#define NTRBOOT_BUTTONS (BUTTON_START | BUTTON_SELECT | BUTTON_X)

View File

@@ -27,6 +27,7 @@
#include "config.h"
#include "memory.h"
#include "fs.h"
#include "strings.h"
#include "utils.h"
#include "screen.h"
#include "draw.h"
@@ -35,7 +36,7 @@
CfgData configData;
ConfigurationStatus needConfig;
static u32 oldConfig;
static CfgData oldConfig;
bool readConfig(void)
{
@@ -46,30 +47,30 @@ bool readConfig(void)
configData.formatVersionMajor != CONFIG_VERSIONMAJOR ||
configData.formatVersionMinor != CONFIG_VERSIONMINOR)
{
configData.config = 0;
memset(&configData, 0, sizeof(CfgData));
ret = false;
}
else ret = true;
oldConfig = configData.config;
oldConfig = configData;
return ret;
}
void writeConfig(bool isPayloadLaunch)
void writeConfig(bool isConfigOptions)
{
if(isPayloadLaunch) configData.config = (configData.config & 0xFFFFFF80) | (oldConfig & 0x7F);
/* If the configuration is different from previously, overwrite it.
Just the no-forcing flag being set is not enough */
if(needConfig != CREATE_CONFIGURATION && (configData.config & 0xFFFFFFBF) == oldConfig) return;
//If the configuration is different from previously, overwrite it.
if(needConfig != CREATE_CONFIGURATION && ((isConfigOptions && configData.config == oldConfig.config && configData.multiConfig == oldConfig.multiConfig) ||
(!isConfigOptions && configData.bootConfig == oldConfig.bootConfig))) return;
if(needConfig == CREATE_CONFIGURATION)
{
memcpy(configData.magic, "CONF", 4);
configData.formatVersionMajor = CONFIG_VERSIONMAJOR;
configData.formatVersionMinor = CONFIG_VERSIONMINOR;
needConfig = MODIFY_CONFIGURATION;
}
if(!fileWrite(&configData, CONFIG_FILE, sizeof(CfgData)))
@@ -78,115 +79,122 @@ void writeConfig(bool isPayloadLaunch)
void configMenu(bool oldPinStatus, u32 oldPinMode)
{
const char *multiOptionsText[] = { "Default EmuNAND: 1( ) 2( ) 3( ) 4( )",
"Screen brightness: 4( ) 3( ) 2( ) 1( )",
"Splash: Off( ) Before( ) After( ) payloads",
"PIN lock: Off( ) 4( ) 6( ) 8( ) digits",
"New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )",
};
static const char *multiOptionsText[] = { "Default EmuNAND: 1( ) 2( ) 3( ) 4( )",
"Screen brightness: 4( ) 3( ) 2( ) 1( )",
"Splash: Off( ) Before( ) After( ) payloads",
"Splash duration: 1( ) 3( ) 5( ) 7( ) seconds",
"PIN lock: Off( ) 4( ) 6( ) 8( ) digits",
"New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )",
};
const char *singleOptionsText[] = { "( ) Autoboot EmuNAND",
"( ) Use EmuNAND FIRM if booting with R",
"( ) Enable loading external FIRMs and modules",
"( ) Enable game patching",
"( ) Show NAND or user string in System Settings",
"( ) Show GBA boot screen in patched AGB_FIRM",
"( ) Patch ARM9 access",
"( ) Set developer UNITINFO",
};
static const char *singleOptionsText[] = { "( ) Autoboot EmuNAND",
"( ) Use EmuNAND FIRM if booting with R",
"( ) Enable loading external FIRMs and modules",
"( ) Enable game patching",
"( ) Show NAND or user string in System Settings",
"( ) Show GBA boot screen in patched AGB_FIRM",
"( ) Set developer UNITINFO",
"( ) Disable ARM11 exception handlers",
};
const char *optionsDescription[] = { "Select the default EmuNAND.\n\n"
"It will be booted when no\n"
"directional pad buttons are pressed.",
static const char *optionsDescription[] = { "Select the default EmuNAND.\n\n"
"It will be booted when no\n"
"directional pad buttons are pressed.",
"Select the screen brightness.",
"Select the screen brightness.",
"Enable splash screen support.\n\n"
"\t* 'Before payloads' displays it\n"
"before booting payloads\n"
"(intended for splashes that display\n"
"button hints).\n\n"
"\t* 'After payloads' displays it\n"
"afterwards.",
"Enable splash screen support.\n\n"
"\t* 'Before payloads' displays it\n"
"before booting payloads\n"
"(intended for splashes that display\n"
"button hints).\n\n"
"\t* 'After payloads' displays it\n"
"afterwards.",
"Activate a PIN lock.\n\n"
"The PIN will be asked each time\n"
"Luma3DS boots.\n\n"
"4, 6 or 8 digits can be selected.\n\n"
"The ABXY buttons and the directional\n"
"pad buttons can be used as keys.\n\n"
"A message can also be displayed\n"
"(refer to the wiki for instructions).",
"Select how long the splash screen\n"
"displays.\n\n"
"This has no effect if the splash\n"
"screen is not enabled.",
"Select the New 3DS CPU mode.\n\n"
"This won't apply to\n"
"New 3DS exclusive/enhanced games.\n\n"
"'Clock+L2' can cause issues with some\n"
"games.",
"Activate a PIN lock.\n\n"
"The PIN will be asked each time\n"
"Luma3DS boots.\n\n"
"4, 6 or 8 digits can be selected.\n\n"
"The ABXY buttons and the directional\n"
"pad buttons can be used as keys.\n\n"
"A message can also be displayed\n"
"(refer to the wiki for instructions).",
"If enabled, an EmuNAND\n"
"will be launched on boot.\n\n"
"Otherwise, SysNAND will.\n\n"
"Hold L on boot to switch NAND.\n\n"
"To use a different EmuNAND from the\n"
"default, hold a directional pad button\n"
"(Up/Right/Down/Left equal EmuNANDs\n"
"1/2/3/4).",
"Select the New 3DS CPU mode.\n\n"
"This won't apply to\n"
"New 3DS exclusive/enhanced games.\n\n"
"'Clock+L2' can cause issues with some\n"
"games.",
"If enabled, when holding R on boot\n"
"SysNAND will be booted with an\n"
"EmuNAND FIRM.\n\n"
"Otherwise, an EmuNAND will be booted\n"
"with the SysNAND FIRM.\n\n"
"To use a different EmuNAND from the\n"
"default, hold a directional pad button\n"
"(Up/Right/Down/Left equal EmuNANDs\n"
"1/2/3/4), also add A if you have\n"
"a matching payload.",
"If enabled, an EmuNAND\n"
"will be launched on boot.\n\n"
"Otherwise, SysNAND will.\n\n"
"Hold L on boot to switch NAND.\n\n"
"To use a different EmuNAND from the\n"
"default, hold a directional pad button\n"
"(Up/Right/Down/Left equal EmuNANDs\n"
"1/2/3/4).",
"Enable loading external FIRMs and\n"
"system modules.\n\n"
"This isn't needed in most cases.\n\n"
"Refer to the wiki for instructions.",
"If enabled, when holding R on boot\n"
"SysNAND will be booted with an\n"
"EmuNAND FIRM.\n\n"
"Otherwise, an EmuNAND will be booted\n"
"with the SysNAND FIRM.\n\n"
"To use a different EmuNAND from the\n"
"default, hold a directional pad button\n"
"(Up/Right/Down/Left equal EmuNANDs\n"
"1/2/3/4), also add A if you have\n"
"a matching payload.",
"Enable overriding the region and\n"
"language configuration and the usage\n"
"of patched code binaries,\n"
"IPS code patches and LayeredFS\n"
"for specific games.\n\n"
"Also makes certain DLCs\n"
"for out-of-region games work.\n\n"
"Enabling this requires the\n"
"archive patch to be applied.\n\n"
"Refer to the wiki for instructions.",
"Enable loading external FIRMs and\n"
"system modules.\n\n"
"This isn't needed in most cases.\n\n"
"Refer to the wiki for instructions.",
"Enable showing the current NAND/FIRM:\n\n"
"\t* Sys = SysNAND\n"
"\t* Emu = EmuNAND 1\n"
"\t* EmuX = EmuNAND X\n"
"\t* SysE = SysNAND with EmuNAND 1 FIRM\n"
"\t* SyEX = SysNAND with EmuNAND X FIRM\n"
"\t* EmuS = EmuNAND 1 with SysNAND FIRM\n"
"\t* EmXS = EmuNAND X with SysNAND FIRM\n\n"
"or a user-defined custom string in\n"
"System Settings.\n\n"
"Refer to the wiki for instructions.",
"Enable overriding the region and\n"
"language configuration and the usage\n"
"of patched code binaries, exHeaders,\n"
"IPS code patches and LayeredFS\n"
"for specific games.\n\n"
"Also makes certain DLCs\n"
"for out-of-region games work.\n\n"
"Refer to the wiki for instructions.",
"Enable showing the GBA boot screen\n"
"when booting GBA games.",
"Enable showing the current NAND/FIRM:\n\n"
"\t* Sys = SysNAND\n"
"\t* Emu = EmuNAND 1\n"
"\t* EmuX = EmuNAND X\n"
"\t* SysE = SysNAND with EmuNAND 1 FIRM\n"
"\t* SyEX = SysNAND with EmuNAND X FIRM\n"
"\t* EmuS = EmuNAND 1 with SysNAND FIRM\n"
"\t* EmXS = EmuNAND X with SysNAND FIRM\n\n"
"or a user-defined custom string in\n"
"System Settings.\n\n"
"Refer to the wiki for instructions.",
"Disable ARM9 exheader access checks.\n\n"
"Only select this if you know what you\n"
"are doing!",
"Enable showing the GBA boot screen\n"
"when booting GBA games.",
"Make the console be always detected\n"
"as a development unit, and conversely.\n"
"(which breaks online features, amiibo\n"
"and retail CIAs, but allows installing\n"
"and booting some developer software).\n\n"
"Only select this if you know what you\n"
"are doing!",
};
"Make the console be always detected\n"
"as a development unit, and conversely.\n"
"(which breaks online features, amiibo\n"
"and retail CIAs, but allows installing\n"
"and booting some developer software).\n\n"
"Only select this if you know what you\n"
"are doing!",
"Disables the fatal error exception\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!"
};
struct multiOption {
u32 posXs[4];
@@ -194,11 +202,12 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
u32 enabled;
bool visible;
} multiOptions[] = {
{ .posXs = {19, 24, 29, 34}, .visible = isSdMode },
{ .posXs = {21, 26, 31, 36}, .visible = true },
{ .posXs = {12, 22, 31, 0}, .visible = true },
{ .posXs = {14, 19, 24, 29}, .visible = true },
{ .posXs = {17, 26, 32, 44}, .visible = ISN3DS },
{ .visible = isSdMode },
{ .visible = true },
{ .visible = true },
{ .visible = true },
{ .visible = true },
{ .visible = ISN3DS },
};
struct singleOption {
@@ -226,14 +235,28 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
//Parse the existing options
for(u32 i = 0; i < multiOptionsAmount; i++)
{
//Detect the positions where the "x" should go
u32 optionNum = 0;
for(u32 j = 0; optionNum < 4 && j < strlen(multiOptionsText[i]); j++)
if(multiOptionsText[i][j] == '(') multiOptions[i].posXs[optionNum++] = j + 1;
while(optionNum < 4) multiOptions[i].posXs[optionNum++] = 0;
multiOptions[i].enabled = MULTICONFIG(i);
}
for(u32 i = 0; i < singleOptionsAmount; i++)
singleOptions[i].enabled = CONFIG(i);
initScreens();
static const char *bootTypes[] = { "B9S",
"B9S (ntrboot)",
"FIRM0",
"FIRM1" };
drawString(true, 10, 10, COLOR_TITLE, CONFIG_TITLE);
drawString(true, 10, 10 + SPACING_Y, COLOR_TITLE, "Press A to select, START to save");
drawFormattedString(false, 10, SCREEN_HEIGHT - 2 * SPACING_Y, COLOR_YELLOW, "Booted from %s via %s", isSdMode ? "SD" : "CTRNAND", bootTypes[(u32)bootType]);
//Character to display a selected option
char selected = 'x';
@@ -277,9 +300,9 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
u32 pressed;
do
{
pressed = waitInput(true);
pressed = waitInput(true) & MENU_BUTTONS;
}
while(!(pressed & MENU_BUTTONS));
while(!pressed);
if(pressed == BUTTON_START) break;
@@ -373,19 +396,25 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
else if(singleOptions[singleSelected].enabled) drawCharacter(true, 10 + SPACING_X, singleOptions[singleSelected].posY, COLOR_RED, selected);
}
//Preserve the last-used boot options (first 9 bits)
configData.config &= 0x7F;
//Parse and write the new configuration
configData.multiConfig = 0;
for(u32 i = 0; i < multiOptionsAmount; i++)
configData.config |= multiOptions[i].enabled << (i * 2 + 7);
configData.multiConfig |= multiOptions[i].enabled << (i * 2);
configData.config = 0;
for(u32 i = 0; i < singleOptionsAmount; i++)
configData.config |= (singleOptions[i].enabled ? 1 : 0) << (i + 17);
configData.config |= (singleOptions[i].enabled ? 1 : 0) << i;
writeConfig(true);
u32 newPinMode = MULTICONFIG(PIN);
if(newPinMode != 0) newPin(oldPinStatus && newPinMode == oldPinMode, newPinMode);
else if(oldPinStatus) fileDelete(PIN_FILE);
else if(oldPinStatus)
{
if(!fileDelete(PIN_FILE))
error("Unable to delete PIN file");
}
while(HID_PAD & PIN_BUTTONS);
wait(2000ULL);

View File

@@ -28,23 +28,25 @@
#include "types.h"
#define CONFIG(a) (((configData.config >> (a + 17)) & 1) != 0)
#define MULTICONFIG(a) ((configData.config >> (a * 2 + 7)) & 3)
#define BOOTCONFIG(a, b) ((configData.config >> a) & b)
#define CONFIG(a) (((configData.config >> (a)) & 1) != 0)
#define MULTICONFIG(a) ((configData.multiConfig >> (2 * (a))) & 3)
#define BOOTCONFIG(a, b) ((configData.bootConfig >> (a)) & (b))
#define CONFIG_FILE "config.bin"
#define CONFIG_VERSIONMAJOR 1
#define CONFIG_VERSIONMINOR 12
#define CONFIG_VERSIONMAJOR 2
#define CONFIG_VERSIONMINOR 3
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
#define BOOTCFG_NOFORCEFLAG BOOTCONFIG(6, 1)
#define BOOTCFG_NTRCARDBOOT BOOTCONFIG(7, 1)
enum multiOptions
{
DEFAULTEMU = 0,
BRIGHTNESS,
SPLASH,
SPLASH_DURATION,
PIN,
NEWCPU
};
@@ -57,8 +59,8 @@ enum singleOptions
PATCHGAMES,
PATCHVERSTRING,
SHOWGBABOOT,
PATCHACCESS,
PATCHUNITINFO
PATCHUNITINFO,
DISABLEARM11EXCHANDLERS
};
typedef enum ConfigurationStatus
@@ -68,6 +70,8 @@ typedef enum ConfigurationStatus
CREATE_CONFIGURATION
} ConfigurationStatus;
extern CfgData configData;
bool readConfig(void);
void writeConfig(bool isPayloadLaunch);
void writeConfig(bool isConfigOptions);
void configMenu(bool oldPinStatus, u32 oldPinMode);

View File

@@ -33,6 +33,7 @@
#include "crypto.h"
#include "memory.h"
#include "emunand.h"
#include "strings.h"
#include "utils.h"
#include "fatfs/sdmmc/sdmmc.h"
@@ -326,7 +327,7 @@ __attribute__((aligned(4))) static u8 nandCtr[AES_BLOCK_SIZE];
static u8 nandSlot;
static u32 fatStart = 0;
FirmwareSource firmSource;
FirmwareSource firmSource = FIRMWARE_SYSNAND;
__attribute__((aligned(4))) static const u8 key1s[2][AES_BLOCK_SIZE] = {
{0x07, 0x29, 0x44, 0x38, 0xF8, 0xC9, 0x75, 0x93, 0xAA, 0x0E, 0x4A, 0xB4, 0xAE, 0x84, 0xC1, 0xD8},
@@ -421,12 +422,17 @@ int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf)
return result;
}
bool decryptExeFs(Cxi *cxi)
u32 decryptExeFs(Cxi *cxi)
{
if(memcmp(cxi->ncch.magic, "NCCH", 4) != 0) return false;
if(memcmp(cxi->ncch.magic, "NCCH", 4) != 0) return 0;
u8 *exeFsOffset = (u8 *)cxi + (cxi->ncch.exeFsOffset + 1) * 0x200;
if(cxi->ncch.exeFsOffset != 5) return 0;
u8 *exeFsOffset = (u8 *)cxi + 6 * 0x200;
u32 exeFsSize = (cxi->ncch.exeFsSize - 1) * 0x200;
if(exeFsSize > 0x400000) return 0;
__attribute__((aligned(4))) u8 ncchCtr[AES_BLOCK_SIZE] = {0};
for(u32 i = 0; i < 8; i++)
@@ -438,14 +444,14 @@ bool decryptExeFs(Cxi *cxi)
aes_use_keyslot(0x2C);
aes(cxi, exeFsOffset, exeFsSize / AES_BLOCK_SIZE, ncchCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
return memcmp(cxi, "FIRM", 4) == 0;
return memcmp(cxi, "FIRM", 4) == 0 ? exeFsSize : 0;
}
bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize)
u32 decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize)
{
if(memcmp(ticket->sigIssuer, "Root", 4) != 0) return false;
if(memcmp(ticket->sigIssuer, "Root", 4) != 0) return 0;
__attribute__((aligned(4))) const u8 keyY0x3D[AES_BLOCK_SIZE] = {0x0C, 0x76, 0x72, 0x30, 0xF0, 0x99, 0x8F, 0x1C, 0x46, 0x82, 0x82, 0x02, 0xFA, 0xAC, 0xBE, 0x4C};
__attribute__((aligned(4))) static const u8 keyY0x3D[AES_BLOCK_SIZE] = {0x0C, 0x76, 0x72, 0x30, 0xF0, 0x99, 0x8F, 0x1C, 0x46, 0x82, 0x82, 0x02, 0xFA, 0xAC, 0xBE, 0x4C};
__attribute__((aligned(4))) u8 titleKey[AES_BLOCK_SIZE],
cetkIv[AES_BLOCK_SIZE] = {0};
memcpy(titleKey, ticket->titleKey, sizeof(titleKey));
@@ -484,8 +490,8 @@ static inline void twlConsoleInfoInit(void)
aes_setkey(2, (u8 *)0x01FFD398, AES_KEYX, AES_INPUT_TWLNORMAL);
if(CFG_TWLUNITINFO != 0)
{
__attribute__((aligned(4))) u8 key2YDev[AES_BLOCK_SIZE] = {0x3B, 0x06, 0x86, 0x57, 0x33, 0x04, 0x88, 0x11, 0x49, 0x04, 0x6B, 0x33, 0x12, 0x02, 0xAC, 0xF3},
key3YDev[AES_BLOCK_SIZE] = {0xAA, 0xBF, 0x76, 0xF1, 0x7A, 0xB8, 0xE8, 0x66, 0x97, 0x64, 0x6A, 0x26, 0x05, 0x00, 0xA0, 0xE1};
__attribute__((aligned(4))) static const u8 key2YDev[AES_BLOCK_SIZE] = {0x3B, 0x06, 0x86, 0x57, 0x33, 0x04, 0x88, 0x11, 0x49, 0x04, 0x6B, 0x33, 0x12, 0x02, 0xAC, 0xF3},
key3YDev[AES_BLOCK_SIZE] = {0xAA, 0xBF, 0x76, 0xF1, 0x7A, 0xB8, 0xE8, 0x66, 0x97, 0x64, 0x6A, 0x26, 0x05, 0x00, 0xA0, 0xE1};
k3X[1] = 0xEE7A4B1E;
k3X[2] = 0xAF42C08B;
@@ -510,15 +516,15 @@ static inline void twlConsoleInfoInit(void)
void setupKeyslots(void)
{
//Setup 0x24 KeyY
__attribute__((aligned(4))) u8 keyY0x24[AES_BLOCK_SIZE] = {0x74, 0xCA, 0x07, 0x48, 0x84, 0xF4, 0x22, 0x8D, 0xEB, 0x2A, 0x1C, 0xA7, 0x2D, 0x28, 0x77, 0x62};
__attribute__((aligned(4))) static const u8 keyY0x24[AES_BLOCK_SIZE] = {0x74, 0xCA, 0x07, 0x48, 0x84, 0xF4, 0x22, 0x8D, 0xEB, 0x2A, 0x1C, 0xA7, 0x2D, 0x28, 0x77, 0x62};
aes_setkey(0x24, keyY0x24, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
//Setup 0x25 KeyX and 0x2F KeyY
__attribute__((aligned(4))) const u8 keyX0x25s[2][AES_BLOCK_SIZE] = {
__attribute__((aligned(4))) static const u8 keyX0x25s[2][AES_BLOCK_SIZE] = {
{0xCE, 0xE7, 0xD8, 0xAB, 0x30, 0xC0, 0x0D, 0xAE, 0x85, 0x0E, 0xF5, 0xE3, 0x82, 0xAC, 0x5A, 0xF3},
{0x81, 0x90, 0x7A, 0x4B, 0x6F, 0x1B, 0x47, 0x32, 0x3A, 0x67, 0x79, 0x74, 0xCE, 0x4A, 0xD7, 0x1B}
},
keyY0x2Fs[2][AES_BLOCK_SIZE] = {
keyY0x2Fs[2][AES_BLOCK_SIZE] = {
{0xC3, 0x69, 0xBA, 0xA2, 0x1E, 0x18, 0x8A, 0x88, 0xA9, 0xAA, 0x94, 0xE5, 0x50, 0x6A, 0x9F, 0x16},
{0x73, 0x25, 0xC4, 0xEB, 0x14, 0x3A, 0x0D, 0x5F, 0x5D, 0xB6, 0xE5, 0xC5, 0x7A, 0x21, 0x95, 0xAC}
};
@@ -529,7 +535,7 @@ void setupKeyslots(void)
if(ISN3DS)
{
//Setup 0x05 KeyY
__attribute__((aligned(4))) u8 keyY0x5[AES_BLOCK_SIZE] = {0x4D, 0x80, 0x4F, 0x4E, 0x99, 0x90, 0x19, 0x46, 0x13, 0xA2, 0x04, 0xAC, 0x58, 0x44, 0x60, 0xBE};
__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};
aes_setkey(0x05, keyY0x5, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
}

View File

@@ -110,8 +110,6 @@
#define SHA_224_HASH_SIZE (224 / 8)
#define SHA_1_HASH_SIZE (160 / 8)
extern u32 emuOffset,
emuHeader;
extern FirmwareSource firmSource;
void sha(void *res, const void *src, u32 size, u32 mode);
@@ -119,8 +117,8 @@ void sha(void *res, const void *src, u32 size, u32 mode);
int ctrNandInit(void);
int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf);
int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf);
bool decryptExeFs(Cxi *cxi);
bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize);
u32 decryptExeFs(Cxi *cxi);
u32 decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize);
void setupKeyslots(void);
void kernel9Loader(Arm9Bin *arm9Section);
void computePinHash(u8 *outbuf, const u8 *inbuf);

View File

@@ -36,11 +36,12 @@
#include "fs.h"
#include "fmt.h"
#include "font.h"
#include "config.h"
bool loadSplash(void)
{
const char *topSplashFile = "splash.bin",
*bottomSplashFile = "splashbottom.bin";
static const char *topSplashFile = "splash.bin",
*bottomSplashFile = "splashbottom.bin";
bool isTopSplashValid = getFileSize(topSplashFile) == SCREEN_TOP_FBSIZE,
isBottomSplashValid = getFileSize(bottomSplashFile) == SCREEN_BOTTOM_FBSIZE;
@@ -49,7 +50,6 @@ bool loadSplash(void)
if(!isTopSplashValid && !isBottomSplashValid) return false;
initScreens();
clearScreens(true);
if(isTopSplashValid) isTopSplashValid = fileRead(fbs[1].top_left, topSplashFile, SCREEN_TOP_FBSIZE) == SCREEN_TOP_FBSIZE;
if(isBottomSplashValid) isBottomSplashValid = fileRead(fbs[1].bottom, bottomSplashFile, SCREEN_BOTTOM_FBSIZE) == SCREEN_BOTTOM_FBSIZE;
@@ -57,7 +57,9 @@ bool loadSplash(void)
if(!isTopSplashValid && !isBottomSplashValid) return false;
swapFramebuffers(true);
wait(3000ULL);
u32 durationIndex = MULTICONFIG(SPLASH_DURATION);
wait(1000ULL + (durationIndex * 2000ULL));
return true;
}

View File

@@ -28,8 +28,10 @@
* Code for locating the SDMMC struct by Normmatt
*/
#include "emunand.h"
#include "memory.h"
#include "utils.h"
#include "fatfs/sdmmc/sdmmc.h"
#include "../build/bundled.h"
@@ -102,22 +104,41 @@ void locateEmuNand(FirmwareSource *nandType)
static inline bool getFreeK9Space(u8 *pos, u32 size, u8 **freeK9Space)
{
const u8 pattern[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
static const u8 pattern[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
//Looking for the last free space before Process9
*freeK9Space = memsearch(pos, pattern, size, sizeof(pattern));
if(*freeK9Space == NULL) return false;
if(*freeK9Space == NULL || (u32)(pos + size - *freeK9Space) < 0x455 + emunand_bin_size ||
*(u32 *)(*freeK9Space + 0x455 + emunand_bin_size - 4) != 0xFFFFFFFF) return false;
*freeK9Space += 0x455;
return true;
}
static inline u32 getOldSdmmc(u32 *sdmmc, u32 firmVersion)
{
switch(firmVersion)
{
case 0x18:
*sdmmc = 0x080D91D8;
break;
case 0x1D:
case 0x1F:
*sdmmc = 0x080D8CD0;
break;
default:
return 1;
}
return 0;
}
static inline u32 getSdmmc(u8 *pos, u32 size, u32 *sdmmc)
{
//Look for struct code
const u8 pattern[] = {0x21, 0x20, 0x18, 0x20};
static const u8 pattern[] = {0x21, 0x20, 0x18, 0x20};
const u8 *off = memsearch(pos, pattern, size, sizeof(pattern));
@@ -131,7 +152,7 @@ static inline u32 getSdmmc(u8 *pos, u32 size, u32 *sdmmc)
static inline u32 patchNandRw(u8 *pos, u32 size, u32 branchOffset)
{
//Look for read/write code
const u8 pattern[] = {0x1E, 0x00, 0xC8, 0x05};
static const u8 pattern[] = {0x1E, 0x00, 0xC8, 0x05};
u16 *readOffset = (u16 *)memsearch(pos, pattern, size, sizeof(pattern));
@@ -154,7 +175,7 @@ static inline u32 patchNandRw(u8 *pos, u32 size, u32 branchOffset)
static inline u32 patchMpu(u8 *pos, u32 size)
{
//Look for MPU pattern
const u8 pattern[] = {0x03, 0x00, 0x24, 0x00};
static const u8 pattern[] = {0x03, 0x00, 0x24, 0x00};
u16 *off = (u16 *)memsearch(pos, pattern, size, sizeof(pattern));
@@ -166,7 +187,7 @@ static inline u32 patchMpu(u8 *pos, u32 size)
return 0;
}
u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address)
u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address, u32 firmVersion)
{
u8 *freeK9Space;
@@ -186,7 +207,7 @@ u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 proce
//Find and add the SDMMC struct
u32 *posSdmmc = (u32 *)memsearch(freeK9Space, "SDMC", emunand_bin_size, 4);
u32 sdmmc;
ret += getSdmmc(process9Offset, process9Size, &sdmmc);
ret += !ISN3DS && firmVersion < 0x25 ? getOldSdmmc(&sdmmc, firmVersion) : getSdmmc(process9Offset, process9Size, &sdmmc);
if(!ret) *posSdmmc = sdmmc;
//Add EmuNAND hooks

View File

@@ -34,5 +34,8 @@
#define ROUND_TO_4MB(a) (((a) + 0x2000 - 1) & (~(0x2000 - 1)))
extern u32 emuOffset,
emuHeader;
void locateEmuNand(FirmwareSource *nandType);
u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address);
u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address, u32 firmVersion);

View File

@@ -32,22 +32,25 @@
#include "draw.h"
#include "utils.h"
#include "fmt.h"
#include "buttons.h"
#include "../build/bundled.h"
void installArm9Handlers(void)
{
memcpy((void *)0x01FF8000, arm9_exceptions_bin + 32, arm9_exceptions_bin_size - 32);
memcpy((void *)0x01FF8000, arm9_exceptions_bin, arm9_exceptions_bin_size);
/* IRQHandler is at 0x08000000, but we won't handle it for some reasons
svcHandler is at 0x08000010, but we won't handle svc either */
const u32 offsets[] = {0x08, 0x18, 0x20, 0x28};
static const u32 offsets[] = {0x08, 0x18, 0x20, 0x28};
for(u32 i = 0; i < 4; i++)
{
*(vu32 *)(0x08000000 + offsets[i]) = 0xE51FF004;
*(vu32 *)(0x08000000 + offsets[i] + 4) = *((u32 *)arm9_exceptions_bin + 1 + i);
*(vu32 *)(0x08000000 + offsets[i] + 4) = *(vu32 *)(0x01FF8008 + 4 * i);
}
*(vu32 *)0x01FF8004 = 0; //BreakPtr
}
void detectAndProcessExceptionDumps(void)
@@ -60,17 +63,27 @@ void detectAndProcessExceptionDumps(void)
const vu8 *stackDump = (vu8 *)regs + dumpHeader->registerDumpSize + dumpHeader->codeDumpSize;
const vu8 *additionalData = stackDump + dumpHeader->stackDumpSize;
const char *handledExceptionNames[] = {
static const char *handledExceptionNames[] = {
"FIQ", "undefined instruction", "prefetch abort", "data abort"
};
const char *specialExceptions[] = {
},
*specialExceptions[] = {
"kernel panic", "svcBreak"
};
const char *registerNames[] = {
},
*registerNames[] = {
"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12",
"SP", "LR", "PC", "CPSR", "FPEXC"
},
*faultStatusNames[] = {
"Alignment", "Instr.cache maintenance op.",
"Ext.Abort on translation - Lv1", "Ext.Abort on translation - Lv2",
"Translation - Section", "Translation - Page", "Access bit - Section", "Access bit - Page",
"Domain - Section", "Domain - Page", "Permission - Section", "Permission - Page",
"Precise External Abort", "Imprecise External Abort", "Debug event"
};
static const u32 faultStatusValues[] = {
0b1, 0b100, 0b1100, 0b1110, 0b101, 0b111, 0b11, 0b110, 0b1001, 0b1011, 0b1101,
0b1111, 0b1000, 0b10110, 0b10
};
initScreens();
@@ -78,7 +91,7 @@ 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");
else posY = drawString(true, 10, 30, COLOR_WHITE, "Processor: ARM9");
if(dumpHeader->type == 2)
{
@@ -100,11 +113,25 @@ void detectAndProcessExceptionDumps(void)
else
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "Exception type: %s", handledExceptionNames[dumpHeader->type]);
}
else
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "Exception type: %s", handledExceptionNames[dumpHeader->type]);
}
else
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "Exception type: %s", handledExceptionNames[dumpHeader->type]);
if(dumpHeader->processor == 11 && dumpHeader->additionalDataSize != 0)
if(dumpHeader->processor == 11 && dumpHeader->type >= 2)
{
u32 xfsr = (dumpHeader->type == 2 ? regs[18] : regs[17]) & 0xF;
for(u32 i = 0; i < 15; i++)
if(xfsr == faultStatusValues[i])
{
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "Fault status: %s", faultStatusNames[i]);
break;
}
}
if(dumpHeader->additionalDataSize != 0)
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE,
"Current process: %.8s (%016llX)", (const char *)additionalData, *(vu64 *)(additionalData + 8));
posY += SPACING_Y;
@@ -113,10 +140,15 @@ void detectAndProcessExceptionDumps(void)
{
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08X", registerNames[i], regs[i]);
if(i != 16 || dumpHeader->processor != 9)
if(i != 16)
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08X", 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]);
}
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 += SPACING_Y;
u32 mode = regs[16] & 0xF;
@@ -133,6 +165,16 @@ void detectAndProcessExceptionDumps(void)
drawFormattedString(false, 10 + 10 * SPACING_X + 3 * i * SPACING_X, posYBottom, COLOR_WHITE, "%02X", *stackDump);
}
static const char *choiceMessage[] = {"Press A to save the crash dump", "Press any other button to shutdown"};
drawString(true, 10, posY + SPACING_Y, COLOR_WHITE, choiceMessage[0]);
drawString(true, 10, posY + SPACING_Y + SPACING_Y , COLOR_WHITE, choiceMessage[1]);
if(waitInput(false) != BUTTON_A) goto exit;
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];
@@ -143,15 +185,16 @@ void detectAndProcessExceptionDumps(void)
if(fileWrite((void *)dumpHeader, path, dumpHeader->totalSize))
{
posY = drawString(true, 10, posY + SPACING_Y, COLOR_WHITE, "You can find a dump in the following file:");
posY = drawString(true, 10, posY + SPACING_Y, COLOR_WHITE, path) + SPACING_Y;
posY = drawString(true, 10, posY + SPACING_Y, COLOR_WHITE, "You can find the dump in the following file:");
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%s:/luma/%s", isSdMode ? "SD" : "CTRNAND", path) + SPACING_Y;
}
else posY = drawString(true, 10, posY + SPACING_Y, COLOR_RED, "Error writing the dump file");
drawString(true, 10, posY + SPACING_Y, COLOR_WHITE, "Press any button to shutdown");
memset32((void *)dumpHeader, 0, dumpHeader->totalSize);
waitInput(false);
exit:
memset32((void *)dumpHeader, 0, dumpHeader->totalSize);
mcuPowerOff();
}

View File

@@ -28,9 +28,6 @@
#include "types.h"
#define MAKE_BRANCH(src,dst) (0xEA000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
#define MAKE_BRANCH_LINK(src,dst) (0xEB000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
void installArm9Handlers(void);
u32 installArm11Handlers(u32 *exceptionsPage, u32 stackAddress, u32 codeSetOffset, u32 *dAbtHandler, u32 dAbtHandlerMemAddress);
void detectAndProcessExceptionDumps(void);

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