Compare commits

...

531 Commits

Author SHA1 Message Date
TuxSH
e35972ea82 rosalina: fix volume slider override value calculation
Below 50%, the volume slider moves the dB value twice as fast. When
linearly interpolating the value in dB (lerp in log-scale), we need to
account for that fact to match how the MCU firmware handles the actual
volume slider.
2026-02-11 02:41:03 +01:00
fangrong
21f0d64ee8 rosalina: Further fix for ReturnToHomeMenu 2026-01-21 22:41:35 +01:00
TuxSH
7f1dd962af Bump ini output buffer size and add checks 2026-01-19 18:26:59 +01:00
TuxSH
a608ad8241 Add patch that removes the Year 2050 limit in System Settings date picker
This restriction was completely artificial, rest of system supports 01
Jan 2000 - 31 Dec 2099 just fine.

NNID user's year-of-birth seems to have a similar Year 2050 restriction,
I'm not removing that as long as any NNID stuff is still active.
2026-01-06 01:23:38 +01:00
fangrong
c04c7254ed plgloader: Code cleanup 2025-12-26 23:40:25 +01:00
Angel Martin
db639a80c9
Add "Return to Home Menu" button for consoles with broken Home Buttons (#2143) 2025-12-12 21:39:16 +01:00
fangrong
4cfca3c55d Optimize the ASM code of romfsredir, saving 2 bytes so that it does not exceed the size of throwFatalError function 2025-12-12 21:09:47 +01:00
fangrong
d3d9a63bf2 lfs: Call UnMountArchive before Mount, Prevent potential issues in the RegisterArchive interface 2025-12-12 21:09:47 +01:00
PabloMK7
407c18e6fd
plugin_loader: Make plugin reply timeout configurable (#2183) 2025-09-26 17:34:31 +02:00
TuxSH
456a6b4ad7 arm9/util: use hardcoded crc luts 2025-09-08 03:29:23 +02:00
TuxSH
b3282abbf7 Patch lgy k11 to avoid allocating unused pages (bug) which was preventing 2 threads to be created 2025-08-04 18:01:14 +02:00
TuxSH
119499d28d Patch lgy k11 to skip devunit check on kernelpanic, allowing red screens to be displayed on panic
L+R+Start+Select to remove LCD fill
2025-08-04 18:00:47 +02:00
TuxSH
12b15812f2 rosalina: make sure pixel data is aligned in screenshots 2025-07-30 12:53:46 +02:00
TuxSH
55d694fbdd rosalina: we are in 2025 - update credits 2025-07-15 02:44:55 +02:00
TuxSH
1c980b95dc rosalina: fix display bug in MiscellaneousMenu_UpdateTimeDateNtp 2025-07-15 02:44:48 +02:00
TuxSH
da66af3f8a sysmenu: fix luminance calculation, and allow going above preset 5 in many cases.
Unlike SetLuminanceLevel, SetLuminance doesn't check if preset <= 5, and actually allows the lumiance levels provisioned for the "brightness boost mode" (brighter when adapter is plugged in), even when the feature is disabled (it is disabled for anything but the OG model, iirc).
2025-07-04 00:19:09 +02:00
TuxSH
97cc70d35d Fix issue with screen init causing brightness flickering and burn-in when booting HM after a splash on IPS panels
- previously, we left brightness voltage and LCD panel voltage on even though we disabled PWM and output signal, causing GSP to misdetect screen state in turn. Fix that (this fixes the issue mentioned above)

- Initialize the LCD controller over I2C, this fixes some rare sync issues some screen have with other Arm9 homebrew

This may not fix 100% of the issues, only the most egregious/dangerous
ones. There's still a lot of tech debt in Luma's baremetal code, that
necessitate a full rewrite to fix (not planned for this year)
2025-07-03 21:05:18 +02:00
TuxSH
59543da23d bootloader: zerofill N3DS ABL regs when autobooting DSi title
Closes #2137.

Even though (when running TWL/AGB FIRM) the SoC is in O3DS mode, and the GPU also is,
as well as most other components behaving as such (external RAM, L2C not usable, etc.),
this is NOT the case for the LCD and adaptive backlight logic which retains FULL N3DS
functionality, including a feature where the window is blended with a given color depending
on the overall relative luminance of that window.

However, Nintendo's own code mistakenly assumes the opposite, and clearly so ("if GPU in N3DS mode"
checks, not passing N3DS extra adaptive backlight (ABL) to TWL/AGB_FIRM). This has implications:

- Powersaving (ABL) settings in TWL/AGB_FIRM is inconsistent with *both* O3DS (because the new RGB blend
LUT has been set to its current value by NATIVE_FIRM) and N3DS (because "pwn_cnt" and "inertia" are missing
their N3DS-only bits)
- "rave party" when booting into TWL/AGB_FIRM or O3DS NATIVE_FIRM without these regs (well, the LUT)
initialized. Easiest way to do so is by leveraging the "DSi autooboot" feature Luma provides. It is worth
noting at least the LUT survives hardware reboots (if Nintendo were using DSi software that was using
TLNC-based reboots, they wouldn't have noticed).

Only touch the autoboot path, for now
2025-05-12 03:10:52 +02:00
TuxSH
581e591070 arm9: fix loadDeliverArg bug 2025-05-11 22:24:34 +02:00
TuxSH
8a6b766894 loader: fix nonstring warnings 2025-05-02 20:40:37 +02:00
TuxSH
5f848124c4 Fix undefined function issue in plgldr.c 2025-03-19 03:11:27 +01:00
TuxSH
b4273f9569 Fix regression introduced by latest release
As it turns out, neither f_mkdir nor fs.c function create directories recursively, only the last one
2025-03-10 19:37:27 +01:00
PabloMK7
856a4b3acf Put essential files in subfolder with console ID 2025-03-04 22:39:42 +01:00
TuxSH
043e2d2497 Fix bug in loadNintendoFirm 2024-12-30 14:29:32 +01:00
TuxSH
b15e5fa8d6 loader: change defaults when kext not present
E.g. if ran through emulation
2024-12-29 20:30:38 +01:00
PabloMK7
1399d7ef3b plgldr: Allow loading plugins on homebrew if flag set in 3gx 2024-12-23 16:36:50 +01:00
TuxSH
60b244d6a3 Add emunand support for prototype NFIRM (by @Wack0) 2024-12-22 23:14:26 +01:00
PabloMK7
92e586cb3c Add basic support for prototype firmware
* Installs arm9 exception handlers
* Disables NAND signature checks, allowing the firmware to boot on retail devices
2024-12-08 02:00:31 +01:00
TuxSH
9b8a95a1de Fix volume override for applets (i2s2/csnd)
This feature repurposes the functionality used for the camera shutter sound.
As such, it interferes with it:
    - shutter volume is set to the override instead of its default 100% value
    - due to implementation details, having the shutter sound effect play will
      make this feature stop working until the volume override is reapplied by
      going back to this menu

Closes #2072
2024-10-20 19:37:02 +02:00
TuxSH
684c95c7e8 rosalina: in volume override menu, add support for CPAD too 2024-10-01 23:31:22 +02:00
TuxSH
2a7caa366e Prepare for v13.2.1 2024-10-01 23:16:57 +02:00
TuxSH
d2bf10733b Rewrite README, add screenshots 2024-10-01 20:41:32 +02:00
TuxSH
78fe559eb6 Rename LICENSE (same GPLv3 terms, prune history) 2024-10-01 17:47:24 +02:00
TuxSH
0d0a549967 Prepare LICENSE for rename 2024-10-01 17:46:48 +02:00
TuxSH
e96f2efc7e rosalina: add bottom screen color curve that was thought to be incorrect
Use separate toggle in the same submenu as top screen
2024-10-01 01:52:14 +02:00
TuxSH
d299558b09 Update bug-report.md in accordance to the release about to be made 2024-09-27 22:36:05 +02:00
PabloMK7
3253fdb255
Allow plugins to use PRIVATE memory instead of SHARED on requests (#2086)
- Modify the svcMapProcessMemoryEx svc so that it takes an extra flags argument. This change was made in a way that shouldn't break existing plugins or applications.
- Add MAPEXFLAGS_PRIVATE flag, which maps the specified memory as PRIVATE instead of SHARED.
- Allow plugins to be mapped with PRIVATE memory instead of SHARED with a flag in the .3gx header. This allows plugins to use socket and http services without additional hacks.

---------

Co-authored-by: LittleCube <littlecubehax@gmail.com>
2024-09-27 22:31:03 +02:00
PabloMK7
e0e86c46a7 rosalina: Add debug flag to dump gdb communications 2024-09-27 22:18:34 +02:00
TuxSH
902f306ab3 rosalina: remove unused lut, add attribution 2024-09-27 22:01:29 +02:00
TuxSH
ef1773ef4a rosalina: add ability to menu to take screenshot of itself (default combo: L+Up+Select)
Only for documentation purposes, via compile-time flag.

And fix some resource leak bugs, etc.
2024-09-23 00:35:22 +02:00
R-YaTian
7e4a106787
rosalina: Improve misc NTP menu drawing (#2075) 2024-09-22 01:36:19 +02:00
TuxSH
2ae3c4d4ce rosalina: fix handling of more than 1 hidden option in a row
Reported by @cooolgamer
2024-09-22 01:20:53 +02:00
TuxSH
946eb94f02 rosalina: clean up code in N3DSMenu_UpdateStatus 2024-09-22 00:59:57 +02:00
TuxSH
0a11d29d8b rosalina: move power off/reboot back, in a single menu entry this time 2024-09-18 22:36:04 +02:00
TuxSH
1c737d499f rosalina: add qtm calibration submenu
Also steal qtm handle b/c of limitiations (max 3 sessions total)
2024-09-15 23:44:44 +02:00
TuxSH
2aa2013318 rosalina: add SS3D toggle option
Closes #2062
2024-09-15 23:44:36 +02:00
TuxSH
a7bd3208a5 Declutter main rosalina menu & reorder
"Change screen brightness" (due to limitations), "Power Off", "Reboot" moved to sysconfig menu
2024-09-09 00:44:48 +02:00
TuxSH
14e462be20 Clarify that the color curve fixing is intended for IPS top screen only (with stellar results)
And that bottom screen curve doesn't actually match (I don't have bottom IPS New 3DSes but I have asked people who do).
2024-09-03 20:33:21 +02:00
fangrong
9f933954a0 rosalina: fix wrong args in svcControlMemoryEx 2024-08-24 19:48:09 +02:00
TuxSH
ab7e8676b5 rosalina: fix regression in menuReadScreenTypes 2024-08-18 20:42:31 +02:00
TuxSH
f0be624792 rosalina: add system info menu with TN/IPS screen detection in it 2024-08-14 22:48:33 +02:00
TuxSH
85c1997f2b rosalina: use correct srgb filter order 2024-08-04 23:14:29 +02:00
TuxSH
2c49a04516 rosalina: add battery info in debug info 2024-08-02 17:22:53 +02:00
TuxSH
2ddf5d334c Create payloads directory during upgrade process
Closes #2058
2024-08-01 12:39:21 +02:00
TuxSH
db4564a3f5 rosalina: implement full color space correction (to sRGB)
Add option to make the 3DS screens look like sRGB monitors. While this
is not perfect (due to screen variance, and it may make dark tones
slightly darker), this significantly improves the color fidelity of
homebrew and custon HOME Menu themes, removing that "blueish, washed-out
look".

Do note that first-party party 3DS games are designed around the 3DS's
"washed-out" color curve, and may not need that adjustment.

(done in collaboration with @profi200)
2024-07-31 23:22:48 +02:00
TuxSH
7a259a5792 Update super-outdated bug_report.md 2024-07-15 22:44:48 +02:00
TuxSH
988ec17ebf Screenshots: when dealing with 800px mode, produce 800x480 instead of 800x240 images for more faithful output
Each line is duplicated in this case (integer scaling 2)
2024-06-22 01:22:22 +02:00
TuxSH
52a1f4ae60 Patch lgy k11 for agb_firm, too 2024-06-22 00:26:55 +02:00
TuxSH
1c7a2b6135 Remove debug #if 0 that was accidentally left in 2024-06-13 19:37:22 +02:00
TuxSH
cc46e16d66 Fix hb autoboot stuck in exception at boot after a forced shutdown
Closes #1882.

Whenever power button is held long enough ("force shutdown"), mcu sysmodule
stores a flag in free reg 0. It will clear it next boot.

During that next boot, if that flag was set and if CFG_BOOTENV.bit0 is set
(warmboot/firm chainload, i.e. not coldbooting), then main() will simulate
a "power button held" interrupt (after upgrading mcu fw if necessary -- it
will reboot console after if it has upgraded mcu fw, I guess that's one of
the reasons the flag is there). This obviously cause other processes to initiate
a shutdown.

In the case of autoboot, ns will panic when this happens.
2024-06-12 22:44:38 +02:00
TuxSH
725823a9d9 loadTitleLocaleConfig: add Bermuda ("BM") 2024-06-08 19:47:58 +02:00
TuxSH
41dd8bd226 Fix #2034 2024-05-25 17:50:22 +02:00
TuxSH
6c324e0ed0 Force wifi menu: handle unconfigured wifi slots correctly 2024-05-11 17:38:16 +02:00
PabloMK7
45dce14f23
rosalina: fix wireless connection option replacing volume override (#2028) 2024-05-09 21:57:49 +02:00
PabloMK7
2df3c389c1
plugin loader: add persistent plugin user load parameters (#2027) 2024-05-09 21:52:49 +02:00
PabloMK7
175e184089
plugin loader: allow loading user defined plugin for any title (#2026) 2024-05-09 19:59:03 +02:00
TuxSH
df1f9dbfc2 Update RosalinaMenu_ShowCredits (we are in 2024) 2024-05-01 23:49:33 +02:00
TuxSH
64293f8942 Config changes and fixes, see description
- Remove allow_updown_leftright_dsi (option was unused and useless)
- Hide enable_dsi_external_filter. Do not mention out-of-date wiki,
  fixes #1992
- Limit gamma to a more reasonable value of 8, fixes #1989
2024-05-01 17:58:15 +02:00
TuxSH
23e478d67a Update release archive rules in Makefile
Closes #1981
2024-05-01 13:31:04 +02:00
PabloMK7
5928eefe95
plugin_loader: Add new flags to 3gx files (#2021) 2024-05-01 00:31:23 +02:00
Anonymous941
63fbc37426 Fix graphical glitches in volume adjustment menu
Due to the waitInputWithTimeout call taking up to 1 second, the framebuffer must be flushed. Also added padding where it was needed
2024-04-30 23:30:48 +02:00
PabloMK7
85e0257289 loader: Add custom LOADER_GetLastApplicationProgramInfo command 2024-04-26 22:39:51 +02:00
TuxSH
35a7ca25b1 Reword README.md 2024-03-18 00:59:15 +01:00
PabloMK7
36df6d6a98 Bump version number 2024-02-07 01:07:37 +01:00
PabloMK7
bef642c04f Add volume slider override 2024-02-06 23:53:28 +01:00
Jade Herd
8cc294b3cb config: Boot chainloader menu option 2024-02-05 23:10:24 +01:00
CyberYoshi64
a3c5746e06
Add more mountpoint names for LayeredFS updates (#1994)
* Add more mountpoint names for LayeredFS updates

* Move `pat1` to the bottom of the list

* Isolate Mario Kart 7 mountpoint

* Apply suggestions from code review

Co-authored-by: PabloMK7 <hackyglitch2@gmail.com>

---------

Co-authored-by: PabloMK7 <hackyglitch2@gmail.com>
2024-02-02 14:42:57 +01:00
PabloMK7
e2778a45cf Fix macro change in libctru 2023-10-31 18:38:40 +01:00
TuxSH
3b64e25402 rosalina: display SSID in force-wifi-connection menu 2023-09-16 21:30:23 +02:00
TuxSH
6a2e1d4aa3 Patch legacy k11 to allow exception dispatching 2023-09-16 19:45:06 +02:00
TuxSH
c0e0f02443 Fix a LGY K11 bug where user TLS was not accessible to user mode 2023-09-14 00:28:37 +02:00
TuxSH
a9fcca52d0 Fix issue where luma screeninit would result in two white screens or wrong colors 2023-09-14 00:18:26 +02:00
TuxSH
035c50c625 Fix support for all older versions
- Move emuNAND hook to ITCM, fixing previously untested emuNAND support
  for 5.0 (and possibly more versions). This was a very long-standing
  bug
- Fix booting on versions 4.x to 8.x, and restore full support for 5.x
  to 8.x. All Arm11 custom sysmodules and k11ext have been disabled on
  4.x because the Luma3DS v13.0 changes couldn't be ported (this means
  no Rosalina and no region-free and such, and while I could restore
  some of the functionality, you should just update *after* installing
  Luma, like you've been instructed to)
2023-08-12 18:00:08 +02:00
TuxSH
5989d9d61d hbldr: fix DSPmem cacheability attrib regression 2023-08-10 16:41:40 +02:00
TuxSH
37572f3a48 Fix svcbreak detection 2023-08-10 00:40:39 +02:00
TuxSH
41eccacd51 hbldr: fix DSPmem mapping and give access to all Arm11 IO regs 2023-08-09 23:52:16 +02:00
PabloMK7
0f09900a2a Fix luma config softlock (#1931) 2023-07-25 20:42:18 +02:00
PabloMK7
dd22a0cd93 Fix plugin home menu event notification. 2023-07-24 15:53:08 +02:00
lifehackerhansol
3ecce3fc3e Don't copy to CTRNAND if building for exploit mode
While the copy to NAND process is generally a good idea for end users,
this can quickly get annoying for actual developers looking to test
low level stuff or contribute to Luma3DS if a testing FIRM gets sent to
the NAND.
2023-07-24 15:52:37 +02:00
TuxSH
f40a1cc47b Fix external module loading for firm modules such as TwlBg
Closes #1919 and #1921
2023-07-21 11:30:55 +02:00
TuxSH
11be450894 Use different error for /luma folder creation failure 2023-07-20 19:11:24 +02:00
TuxSH
a03988b05d Fix rare race condition issue causing white screens 2023-07-18 00:47:57 +02:00
PabloMK7
497e1904d5 Add an option to save an exit in the config menu. 2023-07-17 18:35:57 +02:00
TuxSH
41edcde5c0 Add enable_dsi_external_filter and allow_updown_leftright_dsi 2023-07-17 01:11:43 +02:00
TuxSH
cf3cf12414 Add mechanism to patch TwlBg on the fly 2023-07-15 20:05:48 +02:00
PabloMK7
c055fb6f5e
Merge 3GX plugin loader fork (#1916)
This commit adds all the changes made to the 3GX plugin loader fork of Luma3DS. The most important features are:

- Add 3GX plugin loader support. New service added to rosalina: plg:ldr
- Add svcControlProcess, svcControlMemoryUnsafe and improve svcMapProcessMemoryEx (breaking change)
- Allow applications to override certain configurations depending on their needs:
    - Disable core2 thread redirection
    - Disable game patching for the next app
    - Force New 3DS speedup
    - Force next application in a specific memory mode
    - Block the opening of the Rosalina menu
- Add GDB commands to list all process handles and catch all SVC (latter is for IDA Pro as gdb client supports it)
- Other changes necessary for plugins to work properly. Please check changed files in this PR for more details. 

---------

Co-authored-by: PabloMK7 <hackyglitch@gmail.com>
Co-authored-by: Nanquitas <nath.doidi@gmail.com>
Co-authored-by: TuxSH <1922548+TuxSH@users.noreply.github.com>
2023-07-14 20:08:07 +02:00
TuxSH
b20c79eda4 Revert some recent change wrt. remounting due to driver issues 2023-07-14 19:23:49 +02:00
TuxSH
97418ca9a1 Properly support arbitrarily-sized and uncompressed TwlBg/AgbBg
As we forgot to patch LGY k11, we were limited by the current size of the KIP.
That is not the case anymore and LGY k11 does support uncompressed KIPs.
2023-07-11 00:33:32 +02:00
TuxSH
9fa1d42aa8 Loader: make it simpler to load ext. modules by clearing N3DS bit
And also move the location of IPS/BPS patches for (non-KIP) sysmodules
to /luma/sysmodules/<titleId>.<ips/bps> and only require "Load ext
firm/modules" option for it.
2023-07-09 22:00:51 +02:00
TuxSH
5b417189db Remove "Use EmuNAND FIRM with R" option
This is a leftover from the Gateway era that has long lost its utility
and that unnecessarily complicated the code base.

Please just load an external FIRM from SD card if you need something
similar.

Also refactor the multi-EmuNAND code and CTRNAND mounting code.
2023-07-09 00:28:17 +02:00
PabloMK7
06c3215546 Add svcGetSystemInfo option to get booted firm path 2023-07-07 14:13:24 +02:00
TuxSH
82d689b485 Fix build issues
Closes #1894
2023-06-16 21:28:08 +02:00
TuxSH
631dddeff8 Fix config text wrapping for hb autoboot 2023-03-28 22:24:07 +02:00
TuxSH
64eda63132 Update singleOptionsText 2023-03-28 19:53:11 +02:00
TuxSH
3e6399490c Hide "force audio output" option 2023-03-28 00:40:30 +02:00
TuxSH
4025f252c7 boot menu: clarify autoboot hb is meant to launch hbmenu 2023-03-27 23:44:18 +02:00
TuxSH
985380c0d8 loader: break when failing to load process (e.g. missing boot.3dsx) 2023-03-27 21:49:00 +02:00
TuxSH
dc7edbd44f Fix handling negative screen filters values 2023-03-27 21:35:51 +02:00
TuxSH
ef1072f996 Add option to force audio routing to speakers, closes #1837
Also refactor ini file a little bit
2023-02-10 01:02:01 +00:00
TuxSH
89f77db986 rosalina: clarify name of default screen filter 2023-02-09 00:20:38 +00:00
TuxSH
2e08b7b44f libctru svcCreateCodeSet changes 2023-02-08 18:25:03 +00:00
TuxSH
1d7cca25d1 Fix long-standing bug affecting hbldr TID change option
This was a long-standing bug since Luma3DS v8.0.

If you changed the homebrew title and didn't immediately reboot, then
the ExHeader during termination would not match the ExHeader that was
was used for loading the process, and thus sysmodule process refcounts
would get all messed up.

The obvious solution to this is to ensure no application is running
while changing the hbldr titleID (hence the changes in custom PM).

This was quite possibly one of the cause of homebrew failing to load
when using N3DS H&S.
2023-02-08 16:14:59 +00:00
TuxSH
1888e17b22 Add ability to force routing audio to headphones...
... even when HPs aren't inserted.

This is aimed at people using Bluetooth audio hw mods.

There are some software limitations, please read the INI/option
description.

Closes #1828.
2023-02-08 00:52:57 +00:00
TuxSH
dfeda19451 Fix #1821 2023-02-06 01:27:25 +00:00
TuxSH
5a5332a212 Do not always reboot to HM when autobooting HB
Also fix CRC calculation
2023-02-05 22:08:15 +00:00
TuxSH
9957d6db1a rosalina: move "save settings" to top-level menu 2023-02-05 16:34:37 +00:00
TuxSH
e7a4003f06 rosalina: fix shell open notif. handling at boot
Was causing boot failure with recent commits.
2023-02-05 01:13:02 +00:00
TuxSH
faa4a0d4f9 rosalina: always try to display battery percentage
Even when apps like 3dsident and mGBA open but never relinquish their
mcu::HWC handle.
2023-01-31 17:14:18 +00:00
TuxSH
777b43b285 rosalina: allow setting top and bot screen filters separately 2023-01-31 00:32:16 +00:00
TuxSH
35e6c5ace9 hbldr: fix dependency list (and launch mp)...
Also fix handling of HBLDR_DEFAULT_3DSX_TITLE_NAME, and always display
process creation time in process list on non-release builds.
2023-01-29 19:25:32 +00:00
TuxSH
088cf6b673 hbldr: add act/cecd/friends to deplist
And make WiFi usable earlier when autobooting homebrew
2023-01-25 22:07:21 +00:00
TuxSH
7b97af473a Add ability to redirect app core1 threads to core2
N3DS-only option. See config.ini for details and context. This should
make very demanding games (those which already use 3x clockrate and L2C
by default, like Pokémon US/UM) between 5 to 15% faster. Not widely
tested, and can potentially break some games and other apps.
2023-01-24 22:05:57 +00:00
TuxSH
ceea6afa05 loader: add external CXI loading.
When "load external firms and modules" is enabled, Loader will load the
sysmodule from /luma/sysmodule/<titleid>.cxi (all uppercase, and with
the N3DS title ID bit if relevant) and skip patching. Note that this is
a title ID here, not a process name (unlike what we do for KIPs).

While this is aimed at enabling people to easily load replacements for
official sysmodules, you can load your own custom sysmodules that don't
correspond to anything installed. You can use gdb to do so:

  set remote exec-file <tid>
  run
2023-01-23 19:53:01 +00:00
TuxSH
eb6d8523d1 loader: enable layeredfs+locale emu for all applets
Not tested (except for HM which is known to work).

And restrict code.bin and exheader.bin to when *both* "external firm
and modules" and "game patching" are enabled.
2023-01-22 18:45:47 +00:00
TuxSH
ee9f283d4d rosalina: fix rare screen filter race condition 2023-01-21 20:32:57 +00:00
TuxSH
8dd40158ca Add config persistence for new screen filters stuff 2023-01-21 18:28:53 +00:00
TuxSH
e2e38d9b9f rosalina: refactor screen filter stuff again & add invert 2023-01-20 18:41:16 +00:00
TuxSH
7397c85434 rosalina: add color gamma control, and more
This commits adds an "Advanced configuration" option to screen filters,
where CCT, color gamma, contrast and "brightness" can be fine-tuned,
instead of just using a preset.

Persistence in config.ini TBD in a later commit.
2023-01-20 02:10:14 +00:00
TuxSH
6592b516a4 rosalina: refactor screen filter code
https://i.kym-cdn.com/photos/images/original/001/264/842/220.png
2023-01-17 23:48:07 +00:00
TuxSH
571592ca7c pm: fix handling of "force next app debug" when autobooting homebrew 2023-01-17 00:06:02 +00:00
TuxSH
19f7ef372b errdisp: properly handle game medium being removed
- transform some error codes into "NAND damaged" or "Gamecard removed"
like official errdisp does
- fix bug in SetUserString
- add more info to logfile (/luma/errdisp.txt)
2023-01-11 23:24:59 +00:00
TuxSH
635235c86c pm: fix racecond regression introduced by 7074ac1
It prevented games such as Mario & Luigi: Bowser's Inside Story from booting.

g_manager.runningApplicationData needs to be accessed through the lock.
2023-01-09 14:22:37 +00:00
TuxSH
a812990f0d pm: mitigate libctru race condition+kernel bug
(when doing dirty hb chainload)
2023-01-08 19:39:38 +00:00
TuxSH
d09bfaf348 hbldr: grant full RW access to DSP RAM
This makes testing custom DSP firmware binaries much easier.
2023-01-07 22:36:01 +00:00
TuxSH
5cdbfab54b Add build options to Makefile
For stuff like testing PASLR, *hax2x, khc3ds, etc.

Also fix a corner-case bug when changing the 3dsx app from itself to
itself, if its TID corresponds to the default.
2023-01-07 15:38:36 +00:00
TuxSH
da0b1a1389 Revert force-setting SysNAND when launching TWL Mode
This being said, neither legacy FIRM nor DSiWare actually support
EmuNAND; installing the same TWL title on both SysNAND and EmuNAND and
then launch it from EmuNAND will work though.

It is only when exiting AGB firm that we want to boot SysNAND no matter
what, because the save file has been written on a partition in SysNAND.

This is mainly to ensure we reboot to the proper NAND in case we reboot.
2023-01-03 21:31:37 +01:00
TuxSH
fe4bb0857b Implement autobooting into homebrew (3DS and DSi modes)
Add config option to autoboot into 3DS and DSi homebrew menu, without
going through Home Menu (nor launching it).

For 3DS homebrew, this requires homebrew built with libctru v2.0.0 or
later (v2.0.0 was released 2.5y ago).

We simulate a "reboot into title" to achieve this. This being said, when
launching stuff like Pokemon US/UM on O3DS, Home Menu reboots into
itself and not the game directly. This will cause Home Menu to crash if
you use this feature and configure it to use a non-default memory layout
(but if you don't, Home Menu will work just fine).
2023-01-03 15:30:07 +01:00
TuxSH
0a6b6865ca loader: always reload ExHeader for hb, after all
Caching exheader for applications launched through Home Menu has very
little benefit, as UnregisterProgram is called a lot, and, for 3DSX,
boot.3dsx/target 3DSX can be changed at any time.
2022-12-29 18:47:43 +01:00
TuxSH
ffbd8554d5 loader: implement PASLR (disabled by default)
Faithfully implement the PASLR algorithm official Loader
uses (it's not very good). Physical address space layout
randomization means that the layout of the pages in physical
memory are randomized, but doens't randomize the virtual addresses.

Also refactor some parts of our Loader impl a little more.
2022-12-29 00:23:45 +01:00
TuxSH
7074ac1166 Move hb:ldr from Rosalina to Loader
Let's not pretend in 2022 that it needed things from rosalina sysmodule
- it did not.

This moves 3DSX loading from Rosalina to Loader, and also removes all
the dependencies Loader had to other Luma3DS components (if kernel ext.
is missing, a default config will be used). This means that, as long as
you replace Loader to the one in here, you will be able to properly load
3DSX files.

Changes:
- hb:ldr is now hosted in loader
- hb:ldr LoadProcess, PatchExHeaderInfo, DebugNextApplicationByForce:
  all removed
- fix a bug where some malformed 3DSX files were not rejected
- grant access to CONFIG11 registers to 3DSX homebrew
- move dirty homebrew chainload (when HM. isn't loaded nor loadable) to
  pm
- pm:dbg (ext.) PrepareToChainloadHomebrew: removed
2022-12-25 23:27:48 +01:00
TuxSH
6fa80c959d Update FatFS from R0.13c to R0.15 2022-12-23 19:25:23 +01:00
TuxSH
a7b840e531 Fix upgrade process possibly copying non-Luma firms
Upgrade process always copied sdmc:/boot.firm to nand:/boot.firm even if
Luma3DS was chainloaded from another path.

Fix this by copying from argv[0], if Luma3DS was launched from the SD
card.

Also use "sdmc:" and "nand:" instead of "0:" and "1:" when using FatFS.

Closes #1776.
2022-12-23 14:48:35 +01:00
TuxSH
fcd08d6614 Patch kernel11 to remove checks on core2/3 thread creation
This stubs checks in SvcCreateThread and SvcSetProcessIdealProcessor
that applied when creating threads on core2 and core3. This allows
non-sysmodules to create threads on core3.

Please note, core2 access was already being automatically granted to
3dsx apps for a long time (this is controlled through a kernel flag),
and other apps that needed it had that flag too.
This commit thus changes nothing for all these applications.

Do not create threads on core3 unless you know exactly what you're doing.
On N3DS, gsp (GPU sysmodule) depends on qtm (head-tracking sysmodule) which
runs many threads at very high priority on core3. Running code that needs the
GPU (including printf) on core3 can thus result in thread starvation /
deadlock.

If you just need an extra application core, just use core2 as it is intended
for that exact purpose and is by default completely idle.

Closes #1668
2022-12-17 23:47:19 +01:00
PabloMK7
71cf677b00 config: Ignore rest of pressed buttons (fixes #1769) 2022-09-25 23:01:21 +01:00
Bent
0c3f51815e Rosalina: Fix crash for external PMDBG_DebugNextApplicationByForce 2022-09-25 22:59:02 +01:00
TuxSH
80aee6fdc1 Fix mcu firmware version check (byte order was inverted) 2022-06-10 22:55:18 +01:00
TuxSH
2c184cf7a3 Update chainloader version number 2022-06-04 22:27:31 +01:00
TuxSH
3227b2ea4b Fix battery voltage calculation (thanks nocash) 2022-06-03 23:53:07 +01:00
TuxSH
e5e09c1e13 gdb: use 'swbreak' for bkpt too 2022-06-03 22:18:10 +01:00
TuxSH
4de0375bde kext: fix bug in rosalinaThreadLockPredicate (thanks @hax0kartik) 2022-05-21 20:19:36 +01:00
TuxSH
ea8f9f4667 loader: refactor part around HIO 2022-05-06 19:53:27 +01:00
TuxSH
6573fc4247 k11ext: fix wrong condition bug 2022-05-02 15:57:59 +01:00
TuxSH
65825020ab bootdiag: add process list dumping 2022-04-23 23:55:48 +02:00
TuxSH
e17ff09713 rosalina: Add define to print process creation time 2022-04-23 13:03:30 +02:00
TuxSH
b79717e848 ruh roh 2022-04-16 00:02:04 +01:00
TuxSH
c0eaf1ea3c Add option to toggle power to card slot.
Fixes #1202. This option is meant to be used when you have something like e.g. a flashcard that is misbehaving.
2022-04-15 21:41:23 +01:00
TuxSH
0e16e4c5fc config init: disable patch games by default; alter system settings version string by default 2022-04-13 21:56:07 +01:00
TuxSH
32d13dc117 Add boot9/boot11 dumping 2022-04-13 21:56:02 +01:00
TuxSH
d957494d45 kext: even more perf improvements
Turns out the undef handler path is quite hot, as only one thread per core can have VFP enabled at a time.
2022-04-12 23:55:08 +01:00
TuxSH
1e95344588 bootdiag: forgot #else 2022-04-11 13:36:14 +01:00
TuxSH
cb398f1e4a ldr => ldrb 2022-04-11 01:06:59 +01:00
TuxSH
ef842dda2a Fix extremely obnoxious race-cond+uninit handle bug
This is mostly a libctru bug (well, sort of).

This can only happen to built-in sysmodules, and to
processes waiting for err:f, that fail to obtain
handles through svcConnectToPort first try; and only
prior to 11.0.

Prior to fw 11.0, kernel didn't zero-initialize output
handles, and thus the output handle gets filled with
junk (leaked kernel stack data) in case of failure.
Libctru does not account for this, and closes such
handles anyway (in srvInit, errfInit, and possibly
more).

The problem is that, in our case, that garbage was
equal to 0x8000, actually a valid handle, in fact
the first handle to be created (and not closed) in
a process... a handle to KAddressArbiter.

Accidentally closing this handle resulted in one or
more KIPs spin-waiting and starving core1, resulting
in an inability to boot.

We fix this simply by replicating what recent k11 does,
in kext (for svcConnectToPort). For srvGetServiceHandle,
add two layers of safety.
2022-04-10 22:19:32 +01:00
TuxSH
56be46b4bd rosalina: introduce bootdiag, tool to dump state of a process in early init 2022-04-10 21:43:19 +01:00
TuxSH
f32f3a4854 Fix config yet again 2022-04-10 01:31:56 +01:00
TuxSH
859b11a27d Fix k11ext regression 2022-04-10 00:05:36 +01:00
TuxSH
97ec1298e3 derp 2022-04-09 23:26:28 +01:00
TuxSH
188d86cb7f gdb: always pass current thread ID when stopping 2022-04-09 21:26:47 +01:00
TuxSH
01ebbf114c Restore extended-remote support & map <GDB PID>-><1 + 3DS PID> (breaking change)
Once more, the "official" gdb client is the one than is the least compliant to its very own stub specs (compared to, say, IDA)
2022-04-09 19:28:33 +01:00
TuxSH
2b5da40a1d arm9: util: make chrono non-static 2022-04-06 02:03:04 +01:00
TuxSH
c64f94bc82 kernel ext: perf improvements 2022-04-05 22:23:09 +01:00
TuxSH
3463effeae rosalina: add "time to boot to HM" in debug menu 2022-04-05 18:33:12 +01:00
TuxSH
c71474a668 Fix #1737 (screen filters CCT was OOB) 2022-03-31 01:16:02 +01:00
TuxSH
90d6420f38 Fix typo in swapFramebuffer, closes #1726 2022-03-28 21:21:41 +01:00
TuxSH
676bbf0d88 Moved config file to INI, and more
- Add support for saving screen filters color temperature and NTP timezone offset (you still need to go to misc->save config)
- some advanced options moved to "in ini file only"; "patch games" is now enabled by default
- ntp: fix support for UTC+12 to +14
- remove deprecated custom svc 0x2e
2022-03-28 20:30:02 +01:00
TuxSH
d798ff0efc Move bootconfig to mcu free regs & copy boot.firm to NAND with each upgrade 2022-03-27 21:04:23 +01:00
TuxSH
fcdb6a7ab5 Add code to backup essential files 2022-03-26 23:09:55 +00:00
TuxSH
bc6e14ada7 ntp: more precise & also set system time
System time is what System Settings (only) changes; user time seems to be set periodically by HM.
2022-03-16 22:19:49 +00:00
TuxSH
44c1711805 Update copyright years 2022-03-13 18:00:00 +00:00
aspargas2
ee16c0b104 fix reading emunand sector 0 2022-03-13 16:26:08 +00:00
TuxSH
26ea031f0e
Merge pull request #1623 from s5bug/master
Fix various things about the cheat system
2022-03-08 23:50:20 +00:00
TuxSH
8c3ae4a2fe Wait for B release before exiting rosalina menu
Closes #1701
2022-03-08 23:42:52 +00:00
Margen67
8cfc0bc709 Makefile: curl improvements
-f: Doesn't output a file on error.
-O: Gets filename from URL.
2022-03-07 22:22:14 +00:00
Gabe Cook
fd4d54a2cc Allow patches in the home menu 2022-03-07 22:19:43 +00:00
George-lewis
e9b8b0daef
Add ASCII View to Rosalina Process List (#1703) 2022-03-07 20:47:06 +00:00
Kookies
b83a0abb9d
Updated sysmodule Defines for latest libctru (#1669) 2021-08-27 06:46:36 +02:00
TuxSH
689de1b9f0
Merge pull request #1657 from mariohackandglitch/master
rosalina: fix temperature display
2021-07-16 17:39:20 +01:00
PabloMK7
352a59fd29
rosalina: fix temperature display
Added 3 leading spaces to the temperature display format string.
2021-07-16 18:23:50 +02:00
TuxSH
01661bb1e6
Merge pull request #1646 from mariohackandglitch/master
loader: fix fileOpen argument order
2021-06-29 00:38:51 +01:00
PabloMK7
caadb3ae5d
loader: fix fileOpen argument order 2021-06-29 01:20:38 +02:00
TuxSH
8e9a3bfc74 Fix #1638 2021-06-14 23:41:43 +01:00
TuxSH
99a2b8e3b2 Disable gcc 11 false positives 2021-04-30 19:08:50 +01:00
TuxSH
50c81f8165 loader: use fsMakePath 2021-04-30 19:01:13 +01:00
Aly
84e64220ab Actually check whether float instructions should execute 2021-04-10 13:49:48 -07:00
Aly
a3be4673b1 Fix float mode checking for arithmetic operators 2021-04-10 12:38:37 -07:00
Aly
9e3e01b6ac Fix conditional mode checking for the conditional operators 2021-04-10 12:17:41 -07:00
TuxSH
4ae4d16dba rosalina: print sdmmc speed info in debug menu 2021-02-01 02:51:14 +00:00
TuxSH
3afecb064c rosalina: fix #1573 2021-01-27 23:22:09 +00:00
TuxSH
7a0ff659a8 rosalina: simplify SysConfigMenu_ToggleWireless 2021-01-27 23:14:59 +00:00
TuxSH
18f3783f52 Revert "Fix a few MCU-related bugs, gm9 should boot properly now"
This reverts commit 36ea48b4dc4e91b94f2cab81e54a56e9da259a9e.
2021-01-26 13:42:47 +00:00
TuxSH
36ea48b4dc Fix a few MCU-related bugs, gm9 should boot properly now
- Stop spamming mcu reads... use the GPIO pin to know if there's a MCU interrupt, instead
- Wait for the MCU interrupts to be raised when powering up LCD+backlights
- Also turn off LCD+backlight when needed
2021-01-26 13:38:37 +00:00
TuxSH
b5b5db6e8c Do not initialize the screens in the very common case where the user has only one payload, etc. 2021-01-26 13:38:37 +00:00
TuxSH
be6d64260c rosalina: fix bug where config file wasn't closed nor truncated 2021-01-16 21:26:37 +00:00
TuxSH
505a17bba1 rosalina: add DSP firm dumping option 2021-01-16 21:16:32 +00:00
TuxSH
883c5e25dd sysmodules: update ifile, process_patches 2021-01-16 21:16:06 +00:00
TuxSH
2a947b5c42 rosalina: split ntp and timeoffset nullification
- NTP option doesn't require a reboot to take effect anymore and behaves as if you'd used System Settings, taking effect immediately. This is the proper way to do it, and is easier to use.
- Timeoffset nullification kept as a separate option for compatibility. RTC is supposed to be somehwat monotonic; using this option causes issues with SpotPass. IMHO GodMode9 should parse the cfg save file and do things *properly*
2021-01-13 23:55:55 +00:00
TuxSH
a9c021d1c9 rosalina: use mcu optimization trick 2021-01-11 01:02:12 +00:00
TuxSH
57c4d022ab rosalina: fix screen flickering regression 2021-01-08 01:26:17 +00:00
TuxSH
12ed3ae65f rosalina: add kernel&mcu fw ver. to debug info menu 2021-01-07 01:38:40 +00:00
TuxSH
f54c709f64 rosalina: add extra battery info
- Battery percentage now has a resolution of 0.1%
- Battery temperature and battery voltage are now displayed
2021-01-07 01:32:29 +00:00
TuxSH
168647e0f8 Indicate how to boot safe_firm from 1.x/2.x 2020-12-18 23:59:51 +00:00
TuxSH
2fcd2d862d Add small debug helper for sysmodule reimpls 2020-12-07 20:17:30 +00:00
TuxSH
cb4a23a2ba gdb: fix handling of bkpt instructions 2020-12-03 21:48:16 +00:00
TuxSH
87fa35ccfd arm9 exception handlers: add arm9 mem dumping feature 2020-11-22 00:00:12 +00:00
TuxSH
df62e1901e arm9: mark drawFormattedString as printf-like function 2020-11-21 21:45:36 +00:00
TuxSH
c058e3f446
Merge pull request #1466 from Nanquitas/black-fillcolor
Rosalina: ignore fillcolor when opening the menu
2020-11-17 01:30:24 +00:00
Michael Scire
94b5113b17 pm: Fix argument truncation to be compatible with 11.14 ABI 2020-11-16 17:10:45 -08:00
Chris Feger
ebeef7ab7f
Special case for final line read (#1473)
Fixes cheat files without a trailing newline
2020-07-30 05:22:57 +02:00
Nanquitas
804268916a
rosalina: restore fillcolor reg 2020-07-27 06:50:12 +02:00
TuxSH
b15becb37a
Merge pull request #1461 from Pixel-Pop/master
Patch DLP client region check
2020-07-27 01:43:59 +01:00
Nanquitas
8c7f31bb4d Rosalina: disable black fillcolor 2020-07-23 20:04:42 +02:00
Pixel-Pop
a7ce156f59
Update dlp client region free
Allows all dlp versions to have region free by patching necessary instruction after locating it with pattern.
2020-07-18 15:25:53 -07:00
Pixel-Pop
67ad6d425a
Patch DLP client region check 2020-07-17 14:07:45 -07:00
TuxSH
738a242e3c rosalina: work around gsp bug 2020-07-17 13:50:00 +01:00
TuxSH
5fd6dc6dd4
Merge pull request #1459 from iomintz/patch-1
fix typo in screen filters menu
2020-07-17 11:40:12 +01:00
iomintz
3fd9cacb6d
fix typo in screen filters menu
Ember is 1200K, not 2700K.
2020-07-17 08:56:10 +00:00
TuxSH
bb07a7334f update gitignore and makefile 2020-07-16 18:06:14 +01:00
TuxSH
748b771618 rosalina: ndm + shutdown issue workaround 2020-07-16 17:55:31 +01:00
TuxSH
d6e72080d9 rosalina: ndm doesn't exist on SAFE_FIRM 2020-07-16 16:56:59 +01:00
TuxSH
70109fed2c Update bug-report.md, etc 2020-07-16 16:25:56 +01:00
TuxSH
cf36d21daf rosalina: forgot float suffix in luminance.c 2020-07-16 01:24:22 +01:00
TuxSH
781cd85b00 rosalina: display min/max luminance 2020-07-16 00:50:05 +01:00
TuxSH
514537a983 hbloader: allow homebrew to write to the shared config page 2020-07-15 23:04:35 +01:00
TuxSH
184f4587fb rosalina: minor menu changes 2020-07-15 22:24:08 +01:00
TuxSH
e096aaabc4 rosalina/sm: properly interact with ndm 2020-07-15 18:57:53 +01:00
TuxSH
ba26ae0f1c k11ext: refactor ndm:u workaround 2020-07-15 17:33:47 +01:00
TuxSH
786adf0268 k11ext: fix oops 2020-07-15 00:56:25 +01:00
TuxSH
2af05220c2 rosalina: properly rewrite luminance-setting menu, etc. 2020-07-14 22:10:13 +01:00
TuxSH
362c4ffff1 sysmodules: use libctru configmem defs 2020-07-12 21:26:02 +01:00
Death Mask Salesman
95fd4e763b
Fix release building (#1454)
`boot.3dsx` is downloaded from a static URL via `curl`.

Fixes #1453
2020-07-12 19:39:03 +01:00
TuxSH
768e587b76 sysmodules: introduce "luma shared config", rewrite ndmu workaround 2020-07-12 19:36:18 +01:00
TuxSH
e3bb1c1b63 rosalina: autoclose menu on sleep mode/shell closed to prevent lockup 2020-07-11 22:04:13 +01:00
TuxSH
4c01bb453c rosalina: prevent disconnect when shell is closed
Fuck ndm, fuck StreetPass
2020-07-11 21:39:36 +01:00
TuxSH
dc67d438dc rosalina: properly restore screen filters when lid is reopened 2020-07-10 22:58:07 +01:00
TuxSH
2d58ec4c86 rosalina: prevent sleep mode entry if debugger/input redir is enabled to prevent lockup 2020-07-09 22:20:29 +01:00
TuxSH
555286ea47 Separate exception dump parser in another repo, add boot.3dsx to release command
https://github.com/LumaTeam/luma3ds_exception_dump_parser
2020-07-09 19:52:55 +01:00
TuxSH
b17eb66d55 rosalina inputredir: Use ir patch from @Nanquitas ; also refactor the code
Fixes #1428, #1438 (I think)
2020-07-08 22:08:57 +01:00
TuxSH
9ca52054cf rosalina: bump FS priority 2020-07-07 23:27:26 +01:00
TuxSH
991f51831d kext: add hid/ir thread locking 2020-07-07 23:27:15 +01:00
TuxSH
e69f89a0d4 Change screen filters presets (adding more) menu & print CCT. Fixes #1442.
Most new presets come from 8bitwonder
2020-07-05 20:54:27 +01:00
TuxSH
9411a8c186 rosalina: implement 800px top-screen screenshot, etc. Fixes #1443 2020-07-05 18:44:41 +01:00
TuxSH
dc4de4ce6f rosalina: fix for latest libctru changes 2020-06-26 09:43:42 +01:00
TuxSH
4e12453fff pm: fix critical bugs where 1.0(?) titles not in the list have scheduling mode misconfigured
Also fix the comments.
Thanks @fincs
2020-06-26 01:04:12 +01:00
Aurora Wright
3a0418e279 loader: revert to use the NS patch due to a Nintendo bug: https://www.3dbrew.org/wiki/NCCH/Extended_Header#Flag1 2020-05-29 23:31:05 +02:00
Aurora Wright
1899bf377b loader: replace NS N3DS CPU patch with exheader override, fix overriding exheader with homebrew 2020-05-29 20:57:05 +02:00
TuxSH
0471002d4c rosalina: ntp: use PTMSYSM_SetRtcTime 2020-05-18 22:43:00 +01:00
TuxSH
704e08dc23 revert the memory map to the old one (mostly) 2020-05-18 22:15:34 +01:00
TuxSH
905837468c fix module loading 2020-05-18 21:05:36 +01:00
TuxSH
19d95782e1 kext: fix outer memory cacheability on newer versions 2020-05-18 20:48:54 +01:00
TuxSH
adda19ecb2 so bascially rosalina's image...
was in BASE (hardcoded by kernel) while its heaps were in SYSTEM. Fix this; also put the kext where BASE was.
2020-05-18 01:15:44 +01:00
TuxSH
b02d0346fd rosalina: add hidden debug info menu 2020-05-17 22:48:26 +01:00
TuxSH
9097276a06 rosalina: refactor menu handling 2020-05-17 16:42:44 +01:00
TuxSH
e99ab11c6f rosalina: rephrase brightness warning 2020-05-16 18:31:30 +01:00
TuxSH
a564d8536a rosalina: add brightness control menu 2020-05-16 02:37:47 +01:00
TuxSH
a21eee9207 rosalina/pm: remove fs patch, use pm instead 2020-05-15 22:15:55 +01:00
TuxSH
71cddef78f rosalina: cleanup variable names 2020-05-15 20:00:13 +01:00
TuxSH
9ae913064c rosalina: reorder menus 2020-05-15 02:29:17 +01:00
TuxSH
a2313d1c03 Fix latest commit 2020-05-15 02:06:52 +01:00
TuxSH
22db3445a0 rosalina menu: add scrolling, cpad and inputredir support (note: no ZL/ZR due to technical reasons) 2020-05-14 21:05:27 +01:00
TuxSH
6417720d7d stuff 2020-05-11 10:25:33 +01:00
TuxSH
8b10906d90 newlib... 2020-05-10 18:54:51 +01:00
TuxSH
0c55324d11 rosalina shutdown/reboot: fix a few things 2020-05-10 15:35:39 +01:00
TuxSH
0b4fdc6e66 Revert "Shutdown via rosalina menu is now much faster; similar thing for reboot"
This reverts commit 9942e8b29987587924d16463877bfce1538a0d49.
2020-05-10 15:08:13 +01:00
TuxSH
d3e62df769 rosalina: implement dirty hb chainload 2020-05-10 02:58:21 +01:00
Aurora
04bd881cfa
Update README.md
Reflect move to the Organization
2020-05-09 20:07:07 +02:00
TuxSH
96799455cb rosalina: allow booting homebrew w/o having to reboot if using a different memory mode 2020-05-09 02:25:33 +01:00
TuxSH
814792eb91 pm: fix handling of PMLAUNCHFLAG_FORCE_USE_O3DS_MAX_APP_MEM 2020-05-09 01:37:09 +01:00
TuxSH
2834bae318 rosalina screenshots: improve conversion time by another 10% 2020-05-08 20:51:41 +01:00
TuxSH
037fae99d6 rosalina: use kernel cached RAM mapping for pixel conversion
Conversion time goes down by 90% with this
2020-05-08 20:20:51 +01:00
TuxSH
49c8888948 rosalina: put screenshot loop inside same TU 2020-05-08 18:19:17 +01:00
TuxSH
1875556f81
Merge pull request #1417 from mtheall/master
Add printf attrtibute to Draw_DrawFormattedString
2020-05-08 16:52:52 +01:00
TuxSH
00850bf691 rosalina: fast screenshots (10s -> 0.3s on my end) 2020-05-08 16:44:30 +01:00
TuxSH
09fd199487 rosalina: Dynamically alloc/free fb cache, exempt rosalina from reslimiting 2020-05-08 01:17:46 +01:00
Michael Theall
32c53578e0 Add printf attrtibute to Draw_DrawFormattedString 2020-05-06 22:34:09 -05:00
TuxSH
0da90f61fc Fix ODR bugs 2020-05-05 18:13:32 +01:00
TuxSH
9942e8b299 Shutdown via rosalina menu is now much faster; similar thing for reboot 2020-05-05 02:01:30 +01:00
TuxSH
daaeb97834 Don't do firmlaunch patches on safe_firm (because of USM) 2020-05-03 01:53:35 +01:00
TuxSH
92da214066 loader: add dsp patch for safe_firm 2020-05-02 23:50:04 +01:00
TuxSH
0f05dd5c0a Revert "rosalina draw.c: remove wait for cmd, gpu processing engine is prone to crashes"
This reverts commit 7dc2b7123b3e40ea773b5df44a9ff731fb866e2d.
2020-05-02 23:36:27 +01:00
TuxSH
166bdbeb7d Add option to run rosalina on N3DS SAFE_FIRM.
Also enables a qtm error bypass
2020-05-02 23:32:21 +01:00
TuxSH
7dc2b7123b rosalina draw.c: remove wait for cmd, gpu processing engine is prone to crashes 2020-05-02 22:38:03 +01:00
TuxSH
3d0ec9b785 Make 3dsx feature compatible with n3ds safe_firm, HOWEVER apps that actually use the GPU won't work 2020-05-02 22:37:15 +01:00
TuxSH
85cfa5cba6 loader: enable secureinfo patch on safe_firm 2020-05-02 18:26:58 +01:00
TuxSH
fdc1eaa16c pm: quick safe_firm fixes 2020-05-02 18:08:24 +01:00
TuxSH
d4dcf1a3e9 k11ext: support SAFE_FIRM in rosalinaThreadLockPredicate 2020-05-02 14:44:39 +01:00
TuxSH
43fd137d55 Use kernel version minor 2020-05-02 12:35:44 +01:00
TuxSH
6931eadc34 update bug report template again 2020-04-29 23:09:20 +01:00
TuxSH
3143e7e1d0 ntp: stop overwriting rtc hwcal cfg backup 2020-04-29 20:18:02 +01:00
TuxSH
d03396d272 pxi: stop putting thread structures on the stack 2020-04-29 16:58:52 +01:00
TuxSH
c8aa2e8a89 change notification 0x1001=>0x2000 2020-03-28 10:58:36 +00:00
TuxSH
c7a3a0278c add quick luma detection getinfo 2020-04-28 10:42:30 +01:00
TuxSH
5924f60d06 gbd: fix address lookup limit on lower fw 2020-04-28 02:45:48 +01:00
TuxSH
cd68b66c03 change kext base address to 0x70000000 2020-04-28 02:39:57 +01:00
TuxSH
44cd3928fb rosalina & pm: properly shutdown when debugger, input redir (but not both) and force connection are enabled 2020-04-28 01:31:29 +01:00
TuxSH
8c54613e44 rosalina/sysconfig: fix handling of disconnected routers in wifi forcing + handle leak 2020-04-28 00:05:55 +01:00
TuxSH
7dfa83b8c0 rosalina: fix gdb/input redir hanging if no internet & fix recovering from failures 2020-04-27 21:58:40 +01:00
TuxSH
b551061264 rosalina/sysconfig: fix wifi forcing, including a regression from v10.1.1 2020-04-27 20:00:41 +01:00
TuxSH
3e228c33c9 here we go again 2020-04-27 18:11:42 +01:00
TuxSH
2b23be8f44 rosalina/cheats: fix v10.1.1 regression where cheats were not working at all. Fixes #1404 2020-04-27 17:59:51 +01:00
TuxSH
ced78cb072 use -wrap for exit 2020-04-27 01:07:57 +01:00
TuxSH
fb17850c3d Update issue template 2020-04-27 01:00:01 +01:00
TuxSH
7f7c4852cc hbloader: raise the maximum time share APT_SetAppCpuTimeLimit can set from 30% to 89%...
... now that we understand both PM and the kernel better.

89% is the maximum value supported for this preemption mode.
2020-04-27 00:57:00 +01:00
TuxSH
f334e3b951 loader/pm: move "force init SD" code to pm. Greatly reduces the number of Arm9 svcBreak with 0xC8804465 2020-04-27 00:47:16 +01:00
TuxSH
9d62995799 rosalina: make the task runner thread actually exit 2020-04-26 21:37:18 +01:00
TuxSH
1d8b793cf7 rosalina: don't keep an ac:u handle. Partially fixes the shutdown issue 2020-04-26 20:55:52 +01:00
TuxSH
33431cb939 pm/kext: make pm terminate Rosalina, removing the need for a dodgy kext hook 2020-04-26 20:33:24 +01:00
TuxSH
e677e0142c rosalina: lower thread prios & make task runner take termination into account 2020-04-26 19:36:59 +01:00
TuxSH
b313a4aa2f rosalina: remove all remaining refs to __syscalls (which we don't init) 2020-04-26 12:07:17 +01:00
TuxSH
37c5c6f049 cheats: don't use rand() 2020-04-26 11:47:15 +01:00
TuxSH
a6d92ed8fe cheats: use pm:dbg new commands to get the application's title ID 2020-04-26 11:27:55 +01:00
TuxSH
eb37ac4142 redefine exit methods for sysmodules. Partially fixes the shutdown issue 2020-04-26 01:50:47 +01:00
TuxSH
a0d4b96915 Fix stack overflow in ProcessListMenu_DumpMemory 2020-04-25 22:48:31 +01:00
TuxSH
31891efbca Current year is 2020 2020-04-25 13:42:10 +01:00
TuxSH
58f3edda12 ARM => Arm 2020-04-25 13:17:23 +01:00
TuxSH
4a655384e2 Add .gitattributes, update README and issue template 2020-04-25 13:03:46 +01:00
TuxSH
0543c208fd Fix #1375 properly this time
Thanks @muhmuhten
2020-04-24 22:52:05 +01:00
TuxSH
0e834ec004 hbloader: allow launching 3dsx apps on < 8.x where Rosalina is supported (4.x+)
Fix kernel caps
2020-04-19 18:22:09 +01:00
TuxSH
26454dc832 loader/patcher.c: make gcc stop sometimes complaining 2020-04-19 18:03:45 +01:00
TuxSH
5c16836626 ntp: change ip to time.windows.com, apparently not blocked in China 2020-04-18 00:29:37 +01:00
TuxSH
67e28b2a82 arm9: check for combos again after the PIN has been entered/splash has been displayed 2020-04-17 01:01:35 +01:00
TuxSH
c2a2893b5c
Merge pull request #1284 from izzy84075/toggle-power-button
Add a Rosalina System Configuration option to disable the power button short press
2020-04-17 00:37:59 +02:00
TuxSH
68b670f94f
Merge branch 'master' into toggle-power-button 2020-04-17 00:36:07 +02:00
TuxSH
5a83a46423
Merge pull request #1349 from leoetlino/bps
loader: Add support for BPS patches
2020-04-16 23:35:14 +02:00
TuxSH
8785fd0236 Use -Os for rosalina, pm, sm. Decrease gdb buffer sizes, etc. 2020-04-16 21:05:33 +01:00
TuxSH
a67e8e60c6 rosalina: screen_filter: save up around 10K using this simple trick 2020-04-16 19:50:18 +01:00
TuxSH
c7551a731c rosalina: revert errdisp ipc handling 2020-04-16 00:16:25 +01:00
TuxSH
d9c5437902 rosalina: revert menu thread stack size now that screen filters LUT is in .bss 2020-04-15 23:15:14 +01:00
TuxSH
55d51217d8 Fix hex parsing in patcher.c (langemu). Fixes #1375
Thanks @Lizardon1
2020-04-15 22:28:38 +01:00
TuxSH
11c9caaf13
Merge pull request #1348 from mariohackandglitch/patch-1
Fix stack overflow on screen filters
2020-04-15 22:36:21 +02:00
TuxSH
c4711e5e3a
Merge pull request #1388 from Margen67/readme
README: Formatting
2020-04-15 22:33:47 +02:00
Margen67
d34f0a8eca README: Formatting
Update Project CTR makerom link.
2020-04-02 17:00:22 -07:00
Léo Lam
8233d4e226 loader: Add support for BPS patches
The BPS format allows distributing patches that are smaller and that do
not contain copyrighted content if data is relocated
(unlike non-trivial IPS patches).

This is essential for games such as Majora's Mask 3D that have three
barely different code revisions. Supporting all three versions would
demand an unreasonable amount of work; with BPS patches only one
version has to be supported.

The patcher is written in C++ in order to make it possible to share the
implementation with Citra and because a C version would be a lot more
ugly and tedious to write. The patcher is non-intrusive for the rest of
the codebase and self-contained so hopefully that isn't an issue.

This adds roughly ~0x500 bytes of code to the loader sysmodule.
Code looks reasonably optimised (in IDA). Tested and works on an o3DS.
2019-12-21 18:32:18 +01:00
Léo Lam
ca49956219 loader: Compile C++ code with -std=gnu++17 2019-12-21 17:49:58 +01:00
PabloMK7
5edfbfc1f7
Fix stack overflow on screen filters 2019-12-17 15:00:37 +01:00
TuxSH
dfd50d9d75
Merge pull request #1298 from LiquidFenrir/force-wifi
add wifi connection forcing to rosalina
2019-11-05 00:15:41 +00:00
TuxSH
1946941340
Merge pull request #1306 from lioncash/null
rosalina/gdb/server: Prevent potential null dereference case
2019-11-05 00:15:07 +00:00
TuxSH
31dae90dcd
Merge pull request #1307 from lioncash/null2
sm/notifications: Prevent potential null pointer dereference in ReceiveNotification
2019-11-05 00:14:49 +00:00
TuxSH
da8df54649
Merge pull request #1308 from lioncash/uninit
rosalina/errdisp: Correct uninitialized variable usage in ERRF_HandleCommands
2019-11-05 00:14:28 +00:00
TuxSH
0e1415299a
Merge pull request #1332 from Oreo639/errdisp
rosilina: save errdisp info before doing anything else
2019-11-05 00:14:07 +00:00
TuxSH
93f770888d
Merge pull request #1320 from nathanhitch/master
Add ability to offset ntp by any amount of minutes
2019-11-05 00:13:22 +00:00
oreo639
0886b10619 rosilina: save errdisp info before doing anything else 2019-10-23 12:12:08 -07:00
nathan hitch
e8493d18c5 Add ability to offset ntp by any amount of minutes 2019-09-16 17:13:23 +09:30
Lioncash
60a8bf56c6 rosalina/errdisp: Correct uninitialized variable usage in ERRF_HandleCommands
This was previously using the value of the uninitialized sz variable
before it was actually assigned a value, rather than assigning the size
indicated within the command buffer.
2019-08-13 03:11:47 -04:00
Lioncash
c95b59c72e sm/notifications: Prevent potential null pointer dereference in ReceiveNotification
Based off the conditions, this is a potential null pointer dereference
that can occur. We need to check for null before accessing
nbPendingNotifications.

This is unlikely to occur in common usage, however it's a fairly
straightforward amendment.
2019-08-13 03:04:03 -04:00
Lioncash
7e14c83bdd rosalina/gdb/server: Prevent potential null dereference case
While unlikely to commonly occur, this is a trivially avoidable case.
2019-08-13 02:54:12 -04:00
TuxSH
a2e46919c1
Merge pull request #1305 from piepie62/master
Fix off-by-one error with extra cheat page
2019-08-12 21:11:21 +02:00
piepie62
a4befc29c8 Fix off-by-one error with extra cheat page 2019-08-12 00:58:16 -04:00
LiquidFenrir
93e87284aa follow changes in ctrulib PR 2019-07-23 00:13:17 +02:00
LiquidFenrir
236dbb043c add wifi connection forcing to rosalina
breaks regular auto connect until reboot
allows connecting to a wifi without internet (for example, for transferring stuff with 3dslink or ftpd/3DShell)
2019-07-21 19:05:37 +02:00
TuxSH
77f0295a04
Merge pull request #1287 from leoetlino/logic
loader: Fix boolean logic error
2019-07-09 00:39:39 +02:00
Léo Lam
c3b97999f5 loader: Fix boolean logic error 2019-07-07 15:06:15 +02:00
selabnayr
3061001fb1 Switch to updating all 4 bytes of the IRQ mask, on the suggestion of profi200. 2019-07-05 15:37:54 -07:00
selabnayr
0bc51d5c34 Add an entry to the System Configuration menu to toggle disabling a short press of the power button triggering a software closure. 2019-07-05 15:04:38 -07:00
TuxSH
c913de1e67 Fix layeredfs, fix #1280 #1275 #1262 & others 2019-07-03 22:19:38 +02:00
TuxSH
c9a578734e Fix N3DS applications not closing properly (fix #1271, #1270, etc.) 2019-06-30 22:59:44 +02:00
TuxSH
37544a0eb9 Fix process list 2019-06-30 13:54:41 +02:00
TuxSH
3ad314a5ac Fix ntp menu (if user pressed A multiple times) 2019-06-29 17:05:43 +02:00
TuxSH
58a6a25eb3 ntp: also zero field 0x30001 2019-06-29 16:53:31 +02:00
TuxSH
6ed93a1f09
Merge pull request #1266 from luigoalma/master
Properly create BLX instruction
2019-06-29 16:51:57 +02:00
luigoalma
76dbdf45cf
Properly create BLX instruction
Rethinked and revised this function.
This previous one worked by "accident".
More a sheer luck of offsets on current firmware (as of writing)
But now, this is more mathematically correct way of creating a
THUMB -> ARM BLX instruction.
Also setting the new op in a set of 2 u16,
because patching code is in thumb.
2019-06-29 15:22:33 +01:00
TuxSH
d4e1da0174 Update Rosalina credits 2019-06-29 12:21:25 +02:00
TuxSH
fde3b70d03 Fix info os cfwversion/memory by adding null terminator to xml files (thanks @fincs) 2019-06-28 23:44:09 +02:00
TuxSH
8c03702c7d pm: fix uninitialized variable bug (thanks @fincs !) 2019-06-28 20:43:06 +02:00
TuxSH
31c6ead2ad Fix bug-report.md name 2019-06-28 20:12:44 +02:00
TuxSH
454fa16b3a
Update bug-report.md.md 2019-06-28 20:01:06 +02:00
TuxSH
301e84f1ca
Merge pull request #1194 from noirscape/patch-2
Taking advantage of GitHubs new issue templates.
2019-06-28 19:51:57 +02:00
TuxSH
69634fdbd5
Merge pull request #1264 from piepie62/master
Use bitflags
2019-06-28 19:44:09 +02:00
piepie62
10e823a9d5 Use bitflags 2019-06-24 15:42:32 -04:00
TuxSH
f4851cd533 fixed inverted condition in hio.c 2019-06-18 23:58:47 +02:00
TuxSH
39287d43e3 Fix null deref when connecting to port 4003 but force debug next app hasn't been selected 2019-06-18 00:02:32 +02:00
TuxSH
09b2bf5fb1 fix build with newer gcc 2019-06-16 23:20:40 +02:00
TuxSH
e989309771 Fix "disable debugger" finally 2019-06-16 22:06:05 +02:00
TuxSH
d989c45c3d Failed attempt w/ next app 2019-06-14 01:32:50 +02:00
TuxSH
84c5cf0661 Failed attempt at fixing disable debugger when 1+ sessions are open 2019-06-14 00:40:41 +02:00
Chromaryu
648541bb1f Add NTP_IP dynamic changes via -D or #define (#1261)
* Add define option on Makefile to change NTP_IP dynamically

* Remove Makefile -D option
2019-06-03 23:24:21 +02:00
TuxSH
2cf04e8a83 Make Luma arm9 code properly write date when touching files 2019-06-03 23:15:30 +02:00
TuxSH
af10782500 Merge branch 'ntp' 2019-06-03 00:58:37 +02:00
TuxSH
fe0e5ae83d Fix #1259 2019-06-03 00:58:07 +02:00
TuxSH
8e4af5c823 Add ntp client & rtc sync 2019-06-03 00:54:20 +02:00
Chris Feger
570a8d5222 CTRPF-AR Codes (#1259)
* Add most extended CTRPF codes

* Fix some stuff

* FIx a couple more things

* Make the loop break actually work

* Make break work properyly v2

* Clean up a bit

* Get rid of redundant assignment

* Fix off-by-one error

* Fix possible out-of-bounds

* Switch to statically allocated cheat page

* Style changes.
Awaiting further input for the last couple

* Use more booleans
2019-06-03 00:50:27 +02:00
TuxSH
2c8a1eb5c6 gdb hio: lseek returns 64-bit 2019-05-04 17:08:32 +02:00
TuxSH
23c40aeb8e gdb hio: add type l 2019-05-04 16:30:34 +02:00
TuxSH
c7c832a0dd Relicense gdbstub (with permission of contributors) 2019-05-03 21:06:10 +02:00
TuxSH
6423d0c1b3 gdb: fix hang when "debug next application" is used more than once 2019-05-01 19:37:46 +02:00
TuxSH
8b56098d64 Fix TIO encoding bug 2019-04-28 15:04:42 +02:00
TuxSH
2927bd5aa3 gdb: double packet size 2019-04-28 02:15:46 +02:00
TuxSH
d357db25f2 gdb TIO: fix mode and flags being swapped 2019-04-28 02:06:31 +02:00
TuxSH
9b3cc5391b tio fixes 2019-04-27 23:23:36 +02:00
TuxSH
54eeb97b24 Add GDB target IO support (called Host I/O by gdb), not working yet 2019-04-27 16:50:47 +02:00
TuxSH
593f50de91
Merge pull request #1246 from piepie62/Debuffer
Remove cheat file buffer and use buffered reading
2019-04-23 23:04:34 +02:00
piepie62
85af8d9fa4 Merge branch 'Debuffer' of https://github.com/piepie62/Luma3DS into Debuffer 2019-04-23 08:25:10 -07:00
piepie62
58ff96dc83 Merge origin into this branch 2019-04-23 08:24:50 -07:00
TuxSH
a5803d1b62
Merge pull request #1245 from piepie62/IFile-Fix
IFile: Fix reading past the end of file
2019-04-23 11:29:54 +02:00
TuxSH
eddb0988a0
Merge pull request #1243 from piepie62/master
Improve cheat execution parameters and handle CRLF properly
2019-04-23 11:29:04 +02:00
TuxSH
5d3585a33d fix gdb control C regression 2019-04-21 18:00:29 +02:00
TuxSH
4285736286 fix layeredfs regression 2019-04-21 12:15:50 +02:00
piepie62
32b8cf6172 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS into Debuffer 2019-04-19 11:36:19 -07:00
TuxSH
3e724e88a8 Fix crash dumps not saving properly 2019-04-19 10:01:00 +02:00
TuxSH
687dfddd9f HBLDR_DebugNextApplicationByForce changes 2019-04-19 00:37:20 +02:00
piepie62
90a43089ba Debuffer cheat reading and strip whitespace
Effectively doubles the amount of cheats possible, while also getting rid of that annoying line limit
2019-04-18 14:01:46 -07:00
piepie62
1e0baeb30e Fix reading past the end of a file 2019-04-18 14:01:02 -07:00
piepie62
353f7d1705 Add bounds checking 2019-04-18 14:01:02 -07:00
piepie62
f5f3764f99 Improve cheat execution parameters and handle CRLF properly 2019-04-18 14:01:02 -07:00
TuxSH
eef22f8701 Fix "debug next process" with hbldr homebrew 2019-04-18 22:58:53 +02:00
TuxSH
9e1a9f2842 Implement HBLDR_DebugNextApplicationByForce
also prevent port 4003 (next application) from being extended-remote
2019-04-18 22:28:23 +02:00
TuxSH
0b33134f6c Loader services refactor 2019-04-18 19:48:01 +02:00
TuxSH
5c4d6c68b2 gdb: fix GDB_AttachToProcess returning success even when the process doesn't exist 2019-04-18 00:40:20 +02:00
TuxSH
89e42a457c gdb: hio: fix error parsing 2019-04-17 23:53:27 +02:00
TuxSH
17ca09346d gdb: fix multiple extended-remote issues, also fix possible race condtions 2019-04-17 23:12:29 +02:00
TuxSH
54de645dc3 pm: fix inverted condition 2019-04-17 02:03:02 +02:00
TuxSH
da6c02068b pm: fix reslimit bug 2019-04-17 01:31:03 +02:00
TuxSH
06bcb39721 always save errdisp to file; hio changes 2019-04-17 00:18:12 +02:00
piepie62
2b31a4ab5c Merge master into Debuffer 2019-04-15 15:19:46 -07:00
piepie62
3b4ef682fe Debuffer cheat reading and strip whitespace
Effectively doubles the amount of cheats possible, while also getting rid of that annoying line limit
2019-04-15 15:14:53 -07:00
piepie62
eab9a31dff Fix reading past the end of a file 2019-04-15 13:08:53 -07:00
piepie62
ff86ed2e77 Add bounds checking 2019-04-15 03:41:25 -07:00
piepie62
2fe1169423 Improve cheat execution parameters and handle CRLF properly 2019-04-14 23:12:14 -07:00
TuxSH
4c9fe186d7 gdb: hio support (untested yet) 2019-04-14 21:48:15 +02:00
TuxSH
e11cc090b2 gdb: add support to run new processes
Only titleId [mediaType [launchFlags]] is supported, and the launched title shouldn't rely on APT and all 3 parameters should be hex-encoded.

usage example, with titleId+mediaType:
(gdb) set remote file-exec 0004013000003702
(gdb) r 0
2019-04-13 19:18:47 +02:00
TuxSH
763a1de8d3 gdb: add extended-remote support, implement vAttach 2019-04-12 23:40:51 +02:00
TuxSH
e57b546dd4 gdb: rework meaning of selected/used 2019-04-10 23:38:10 +02:00
TuxSH
bd670cf87c gdb: add GDB_FindAllocatedContextByPid 2019-04-10 23:17:49 +02:00
TuxSH
1e0996c395 gdb: simply gdbstate 2019-04-09 23:59:05 +02:00
TuxSH
5f295c4227 increase i2c timeout 2019-04-07 16:13:14 +02:00
Aurora Wright
4f699ccb81 Fix external firm booting with old firms, minor style changes 2019-04-06 21:32:06 +07:00
TuxSH
70757e564d refactor latest commit 2019-04-05 00:55:13 +02:00
TuxSH
af822e5af5 Fix n3ds IPS screen issues/regression, closes #1236 2019-04-05 00:04:38 +02:00
TuxSH
63736d7873 Refactor process detaching code 2019-03-31 22:58:36 +02:00
TuxSH
fb800bd4c9 Add support to force-debug applications before they start running code 2019-03-31 20:01:16 +02:00
TuxSH
219f38169f Update drawString (rosalina) 2019-03-31 17:04:07 +02:00
TuxSH
c688600d33 PMDBG_GetCurrentAppTitleId => PMDBG_GetCurrentAppTitleIdAndPid 2019-03-31 16:12:31 +02:00
TuxSH
ea14d8a186 gdb: avoid race conditions 2019-03-31 01:14:40 +01:00
TuxSH
cd18b85632 gdb: refactor port/ctx alloc 2019-03-31 00:24:45 +01:00
TuxSH
22ec031495 Add client code for new custom pm commands, use them, fix pm race conditions 2019-03-30 18:12:54 +01:00
TuxSH
43b998d37d Add new pmdbg commands: GetCurrentAppTitleId, DebugNextApplicationByForce, LaunchTitleDebug 2019-03-30 15:36:49 +01:00
TuxSH
127101a683 Fix debug bug 2019-03-30 15:05:49 +01:00
TuxSH
5955ca6957 Increase max number of sessions for pmdbg 2019-03-30 14:15:23 +01:00
TuxSH
dcddcfc94d Allow PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION for non-apps 2019-03-29 23:22:16 +01:00
TuxSH
1453d9adac cubic ninja users rejoice 2019-03-29 23:01:55 +01:00
TuxSH
ef034a87d4 revert fsldr change, fix null deref in pm 2019-03-29 22:40:54 +01:00
TuxSH
e688ec9257 move patches to pm 2019-03-29 19:07:24 +01:00
TuxSH
ae1f85d341 K11Ext: add GetSystemInfo k11extSize 2019-03-29 18:23:52 +01:00
TuxSH
7177799021 Rosalina: delete "auto screenfilter restore on wakeup" functionality.
It was causing sleep mode wakeup issues and/or interfering with gsp in a
bad way.
2019-03-29 18:23:52 +01:00
TuxSH
1041d7c438 Add custom pm sysmodule 2019-03-29 00:32:45 +01:00
TuxSH
e57abad52f ctrulib changes 2019-03-29 00:09:59 +01:00
TuxSH
74bbfb95d3 service_manager: auto subscribe 2019-03-28 22:56:13 +01:00
TuxSH
8345f31c2a Fix wrong result code returned in GetServiceHandle 2019-03-27 21:56:13 +01:00
TuxSH
d44055d232 sm: simplify main loop logic 2019-03-27 20:36:40 +01:00
TuxSH
4a431b8fdf Fix bug in port closed handling 2019-03-26 23:15:37 +01:00
TuxSH
e2ed200509 Fix doPublishNotification bug 2019-03-26 20:53:48 +01:00
TuxSH
4e5f6e1eff Fix #1232
Thanks @profi200
2019-03-23 23:14:23 +01:00
TuxSH
474eb3001b Introduce service_manager, also fix hb:ldr pm/pm race condition 2019-03-16 23:40:43 +01:00
TuxSH
f72d99d9b0 Fix wrong number of menus 2019-03-16 23:34:51 +01:00
TuxSH
a9a569c79d Remove useless rules 2019-03-16 18:11:46 +01:00
TuxSH
68b8c99ad0 Fix parallel building 2019-03-16 13:10:30 +01:00
TuxSH
d8c6f94887 Fix config title 2019-03-15 23:21:12 +01:00
TuxSH
8b51141f54 Fix latest commit 2019-03-15 23:03:25 +01:00
TuxSH
0195ab34e9 Fix itcm sections overwriting argv 2019-03-15 23:03:25 +01:00
TuxSH
0bb82feb81 Fix string format case in exceptions.c 2019-03-15 23:03:25 +01:00
TuxSH
6199f598e5 Add -nocodepadding to cxis as it ought to be 2019-03-15 23:03:25 +01:00
TuxSH
b92406afe2 Fix rebase 2019-03-15 23:03:25 +01:00
TuxSH
244409fc98 Change k11 mapping logic again 2019-03-15 23:03:24 +01:00
TuxSH
f3b2a6c30d Fix some of the bugs 2019-03-15 23:03:24 +01:00
TuxSH
a65f7fbf88 Fix the linker scripts again 2019-03-15 23:03:24 +01:00
TuxSH
35ad240018 Rewrite k11ext mmu mapping func + linker script 2019-03-15 23:03:23 +01:00
TuxSH
e64f267e4c Fix section declarations in .s files 2019-03-15 23:03:23 +01:00
TuxSH
d28e961adc Use <string.h> & <3ds/exheader.h>, fix some bugs, etc.
also fix all warnings and use -Werror
2019-03-15 23:03:23 +01:00
TuxSH
e6b7dc1dc5 Add top-level Makefile + @fincs 's linker script fixes 2019-03-15 23:03:22 +01:00
TuxSH
9e7e967a5f Fix bss being PROGBITS, etc. 2019-03-15 23:03:22 +01:00
TuxSH
33d40b491e Fix firm.c sysmodule merging loop 2019-03-15 23:03:21 +01:00
TuxSH
7cb50d38b9 Fix linker script bug, see details
LD interprets "a.o b.o c.o(sectionexpr)" as 3 separate input commands, i.e. it will copy all the sections from a.o, then b.o and the sections matching (sectionexpr) from c.o in that order; (a.o b.o c.o)(sectionexpr) results in a syntax error.
2019-03-15 23:03:21 +01:00
TuxSH
d6d440a47e Sanitize arm9 build system... however link script overflows itcm 2019-03-15 23:03:21 +01:00
TuxSH
52cd950ca6 source => arm9/source 2019-03-15 23:03:20 +01:00
TuxSH
9fad2dff21 Add top-level Makefile for sysmodules 2019-03-15 23:03:20 +01:00
TuxSH
4b40dd52f4 Give a proper build system for each sysmodule, k11ext, arm11.
Previously, these Makefiles didn't correctly track header changes.
The project doesn't build as a whole, future commits will fix it.
2019-03-15 23:03:19 +01:00
TuxSH
6bd7070d38 Do the same for romfs redit => get rid of armips; update README.md 2019-03-15 23:03:18 +01:00
TuxSH
0c9365bcb7 Do the same for large patches (emunand, reboot). This greatly simplifies logic. 2019-03-15 23:03:18 +01:00
TuxSH
c0bd69309a Do the same for arm9 exceptions 2019-03-15 23:03:18 +01:00
TuxSH
55bd62d7a9 Merge the chainloader into the main ARM9 folder 2019-03-15 23:03:18 +01:00
TuxSH
020236742f Fix gdbstub UB with IO 2019-03-15 22:37:04 +01:00
TuxSH
faeb0d9395 Fix strict-aliasing-related UB 2019-03-15 22:23:44 +01:00
TuxSH
b05f993221 Fix wrong memset size in screen_filters 2019-03-15 17:04:15 +01:00
TuxSH
e796abb155 Also use alignedseqmemcpy for sha_hash 2019-03-15 16:17:57 +01:00
TuxSH
3d2c12cf09 Revert sdmmc driver, fixes regression #1225. Also fix a logic bug 2019-03-13 17:33:53 +01:00
TuxSH
8ff5111e30 Use better i2c driver from fb3ds 2019-03-13 16:34:11 +01:00
TuxSH
673ec9fc51 Fix memcpy into fifo UB 2019-03-13 13:53:29 +01:00
TuxSH
a7100a1e7f Fix implicit fallthrough in debug.c 2019-02-28 19:08:39 +01:00
TuxSH
710ad11819 Upgrade fatfs and sdmmc driver 2019-02-28 19:04:11 +01:00
TuxSH
f718297591 Fix screens not working on firmlaunch
- LCD fill was not unset
- Still needs to do screeninit on firmlaunch even though PDN_GPU_CNT is 0x1007F
2019-02-26 20:19:52 +01:00
BuildTools
1c7b55ee1e Bump copyright year 2019-02-24 18:04:32 -07:00
TuxSH
f437d92374
Merge pull request #1065 from panicbit/screen_filter
Implement blue light filters
2019-02-21 19:48:07 +01:00
TuxSH
47916b2831
Fix menu thread stack overflow
sizeof(menuThreadStack) not matching 0x3000
2019-02-21 19:47:35 +01:00
noirscape
0791aabbf8 Taking advantage of GitHubs new issue templates. 2018-10-13 17:29:35 +02:00
Aurora
bd15f51af3
Fix incomplete commit (3903ac6409) 2018-09-28 03:08:35 +02:00
TuxSH
932ed4222f
Merge pull request #1142 from luigoalma/master
Added Patch to Process9 11.8 to the new AMPXI function
2018-09-20 09:44:36 +02:00
luigoalma
1052e04679
Added Patch to Process9 11.8 to the new AMPXI function
Patch it to call __rt_memclr instead of internal PRNG when generating Key
and IV.
Only if UNITINFO is set, preventing on regular console usage NIM sending
to nintendo a 0 Key and IV, and allowing nintendo to know who has a
patched console.
2018-09-10 19:57:14 +01:00
Aurora Wright
3903ac6409 Implement https://github.com/AuroraWright/Luma3DS/issues/470 2018-08-21 22:07:18 +02:00
Aurora Wright
53622d777b Fix https://github.com/AuroraWright/Luma3DS/issues/1095 and https://github.com/AuroraWright/Luma3DS/issues/1118 2018-08-21 18:57:45 +02:00
tstambaugh92
2219b19d5f Fixed cheat functionality (#1117) 2018-08-09 14:21:16 +02:00
tstambaugh92
bc06b17823 Fixed cheat functionality (#1116)
Fixed functionality of BXXXXXXX codes
2018-08-07 12:50:48 +02:00
Aurora Wright
89cc6ede1a Fix patchKernel9Panic on 11.8 NATIVE_FIRM (pattern tested down to 3.0) 2018-07-31 04:32:29 +02:00
Nanquitas
dd6e071dde socAccept: Fix an omitted comment, which masked a condition 2018-07-05 23:33:34 +02:00
TuxSH
2127271b33 Double-license the gdbstub. 2018-06-14 18:33:09 +02:00
TuxSH
1600171ffa Bump copyright year 2018-06-14 18:13:57 +02:00
Yuuki Hikari
7f7a9fab2d
Merge pull request #1088 from ev1l0rd/patch-1
Remove AUR package from prebuilds.
2018-05-28 15:10:32 -04:00
Valentijn
b15d86f31d
Remove AUR package from prebuilds.
Ater discussion with @Hikari-chin (and some other people), I've come to the conclusion that it's not a wise idea to link to an AUR package in the README.

That said, it might still be useful to provide a compiled version of armips for Linux as Windows builds are also provided. To this extent I've compiled armips for both x86 and x86_64 architectures (available in the zip file linked in the commit, or [here](https://ev1l0rd.s-ul.eu/mEIk4atQ) if you dont wish to open the commit). (It's possible to identify the binary arch with the `file` command if one wishes to verify I did this properly).
2018-05-22 20:18:39 +02:00
TuxSH
89a3dc8643
Merge pull request #1084 from ev1l0rd/patch-1
Removed links to compiled armips and makerom
2018-05-22 10:05:00 +02:00
TuxSH
3477beb05c
Merge pull request #1086 from Nanquitas/patch-1
Fix GPU_PSC1_CNT address
2018-05-21 00:00:22 +02:00
Nanquitas
8447c209a7
Fix GPU_PSC1_CNT address 2018-05-13 10:58:07 +02:00
Valentijn
e78f706c1a
Removed links to compiled armips and makerom
The mega link for linux armips 404's and makerom is no longer supplied in buildtools due to a change by steveice10.

Removed the compiled makerom links entirely and replaced linux armips with a link to the armips-git package on the AUR.
2018-05-12 20:12:52 +02:00
TuxSH
f776c56cd4
Merge pull request #1069 from Nanquitas/patch-1
Fix KProcessHandleTable__ToKThread on latest fw
2018-04-26 19:33:03 +02:00
Nanquitas
dc195dffad
Fix KProcessHandleTable__ToKThread on latest fw 2018-04-26 19:30:50 +02:00
panicbit
74a0b2feae Simplify color LUT writes 2018-04-16 01:28:57 +02:00
panicbit
71039fc248 Remove unnecassary permission declarations 2018-04-15 17:15:06 +02:00
panicbit
d0306609c3 Apply screen filter when waking up from standby 2018-04-15 16:26:20 +02:00
panicbit
d13cde3d7b Implement blue light filters in rosalina 2018-04-15 04:55:20 +02:00
panicbit
38f54fd2b6 Add parts of redshift to rosalina 2018-04-15 04:55:20 +02:00
panicbit
b5728e9c11 Add gpu color LUT registers to rosalina 2018-04-15 04:55:14 +02:00
TuxSH
a2177c0510 Fix menu entries (again) 2018-04-05 23:40:18 +02:00
TuxSH
356a94cc2e Double the size of launchedPath 2018-04-05 23:20:30 +02:00
Yuuki Hikari
9d507e046c
Merge pull request #1054 from LegoFigure11/master
Update links to the Plailect's Guide
2018-04-04 20:34:54 -04:00
LegoFigure11
47c47f967a Update links to the Plailect's Guide 2018-04-01 01:29:25 +11:00
417 changed files with 30939 additions and 14369 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
*.xml text eol=lf
*.ini text eol=lf

View File

@ -1,14 +1,19 @@
---
name: Bug report
about: Use this to report bugs you encounter with Luma3DS. Make sure you upload the crash dumps if Luma3DS crashes.
---
<!--
-- THIS IS NOT A SUPPORT FORUM! For support go here:
-- Nintendo Homebrew: https://discord.gg/MjzatM8
--
-- Rosalina feature requests go here: https://github.com/AuroraWright/Luma3DS/issues/752
-- Rosalina feature requests go here: https://github.com/LumaTeam/Luma3DS/issues/752
--
-- Also check the Wiki (https://github.com/AuroraWright/Luma3DS/wiki) before making an issue.
-- Also check the Wiki (https://github.com/LumaTeam/Luma3DS/wiki) before making an issue.
--
-- For GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: https://3ds.guide/troubleshooting
-- For GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: use https://github.com/MechanicalDragon0687/TWLFix-CFW and update your system.
-- If you're using an emu/redNAND try installing anything on it to sysNAND.
-- Please make sure to read "Enable game patching" https://github.com/AuroraWright/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable game patching" option(s).
-- Please make sure to read "Enable game patching" https://github.com/LumaTeam/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable game patching" option(s).
--
-- Luma updaters that don't support Boot9Strap/Sighax won't work.
-- This is due to support for non-B9S/Sighax entrypoints being dropped.
@ -16,11 +21,12 @@
-- Please fill in the placeholders.-->
**System model:**
[e.g. 2DS, New 3DS, Old 3DS]
[New 2DS XL, New 3DS XL, New 3DS, Old 2DS, Old 3DS XL, Old 3DS]
**SysNAND version (+emu/redNAND version if applicable):**
[e.g. 11.6.0-39U SysNAND, 11.6.0-39J EmuNAND]
[e.g. 11.17.0-50U SysNAND, 11.17.0-50E EmuNAND]
<!--You can check which version you're on in System Settings. It will be on the bottom right of the top screen.-->
**Entrypoint (How/what you're using to boot Luma3DS):**
@ -28,28 +34,30 @@
**Luma3DS version:**
[e.g. 8.1.1 stable or if using nightly/hourly specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/9570e6cbeca53128433abbf5e3473cb8a07fe69e]
<!--You can check which version you're on in System Settings. It will be on the bottom right of the top screen.-->
[e.g. v13.2.1 stable or if using non-releases specify the commit like this https://github.com/LumaTeam/Luma3DS/commit/988ec17ebfce513fc4589f7b12e0d6e3894ae542]
**Luma3DS configuration/options:**
Default EmuNAND: ( )
<!--This option is only available if there's at least one EmuNAND.-->
Screen brightness: ( )
Splash: ( )
Splash duration: ( )
PIN lock: ( )
New 3DS CPU: ( )
<!--This option is only available for New 3DS/2DS.-->
<!--This option is only available on New 3DS (XL)/New 2DS XL.-->
Hbmenu autoboot: ( )
--
Autoboot EmuNAND: ( )
Use EmuNAND FIRM if booting with R: ( )
<!--This option is only available if there's at least one EmuNAND.-->
Enable loading external FIRMs and modules: ( )
<!--Firmware (.bin) files are not required by Luma, or NTR CFW anymore.
@ -57,16 +65,13 @@ Enable loading external FIRMs and modules: ( )
Enable game patching: ( )
Redirect app. syscore threads to core2: ( )
<!--This option is only available on New 3DS (XL)/New 2DS XL.-->
Show NAND or user string in System Settings: ( )
Show GBA boot screen in patched AGB_FIRM: ( )
Patch ARM9 access: ( )
Set developer UNITINFO: ( )
Disable ARM11 exception handlers: ( )
--
@ -84,7 +89,8 @@ Disable ARM11 exception handlers: ( )
2.
**Dump file:**
<!--If the issue leads to a crash you must uncheck the "Disable ARM11 exception handlers" option.
**Dump file (if applicable):**
<!--If the issue leads to a crash you must ensure the "Disable Arm11 exception handlers"
-- option is not disabled in config.ini.
-- The error message will tell you where the dump is.
-- Zip the dmp file and drag & drop it below.-->

4
.gitignore vendored
View File

@ -13,8 +13,12 @@ exceptions/arm11/build
*.d
*.elf
*.cxi
*.3dsx
.DS_Store
*.dmp
.project
.cproject
.settings
Luma3DS*.zip
hbmenu.zip

189
Makefile
View File

@ -1,177 +1,48 @@
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
ifneq ($(strip $(shell firmtool -v 2>&1 | grep usage)),)
$(error "Please install firmtool v1.1 or greater")
endif
include $(DEVKITARM)/base_tools
# Disable kext and firmlaunch patches, all custom sysmodules except Loader, enable PASLR.
# Dangerous. Don't enable this unless you know what you're doing!
export BUILD_FOR_EXPLOIT_DEV ?= 0
name := Luma3DS
revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/')
version_major := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f1 -d.)
version_minor := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f2 -d.)
version_build := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f3 -d.)
commit := $(shell git rev-parse --short=8 HEAD)
is_release := 0
# Build with O0 & frame pointer information for use with GDB
export BUILD_FOR_GDB ?= 0
ifeq ($(strip $(revision)),)
revision := v0.0.0-0
version_major := 0
version_minor := 0
version_build := 0
endif
# Default 3DSX TitleID for hb:ldr
export HBLDR_DEFAULT_3DSX_TID ?= 000400000D921E00
ifeq ($(strip $(commit)),)
commit := 0
endif
# What to call the title corresponding to HBLDR_DEFAULT_3DSX_TID
export HBLDR_DEFAULT_3DSX_TITLE_NAME ?= "hblauncher_loader"
ifeq ($(strip $(version_build)),)
version_build := 0
endif
NAME := $(notdir $(CURDIR))
REVISION := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/')
ifeq ($(strip $(shell git describe --tags --match v[0-9]* | grep -)),)
is_release := 1
endif
SUBFOLDERS := sysmodules arm11 arm9 k11_extension
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
.PHONY: all release clean $(SUBFOLDERS)
ASFLAGS := -mcpu=arm946e-s
CFLAGS := -Wall -Wextra $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
LDFLAGS := -nostartfiles -Wl,--nmagic
all: boot.firm
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
$(call rwildcard, $(dir_source), *.s *.c)))
release: $(NAME)$(REVISION).zip
bundled = $(dir_build)/reboot.bin.o $(dir_build)/emunand.bin.o $(dir_build)/chainloader.bin.o $(dir_build)/arm9_exceptions.bin.o
modules = $(dir_build)/loader.cxi $(dir_build)/rosalina.cxi $(dir_build)/sm.cxi $(dir_build)/pxi.cxi
define bin2o
bin2s $< | $(AS) -o $(@)
endef
.PHONY: all
all: firm
.PHONY: release
release: $(dir_out)/$(name)$(revision).7z
.PHONY: firm
firm: $(dir_out)/boot.firm
.PHONY: clean
clean:
@$(MAKE) -C $(dir_arm11) clean
@$(MAKE) -C $(dir_chainloader) clean
@$(MAKE) -C $(dir_arm9_exceptions) clean
@$(MAKE) -C $(dir_k11_extension) clean
@$(MAKE) -C $(dir_loader) clean
@$(MAKE) -C $(dir_rosalina) clean
@$(MAKE) -C $(dir_sm) clean
@$(MAKE) -C $(dir_pxi) clean
@rm -rf $(dir_out) $(dir_build)
@$(foreach dir, $(SUBFOLDERS), $(MAKE) -C $(dir) clean &&) true
@rm -rf *.firm *.zip *.3dsx
.PRECIOUS: $(dir_build)/%.bin
# boot.3dsx comes from https://github.com/fincs/new-hbmenu/releases
$(NAME)$(REVISION).zip: hbmenu.zip boot.firm
@cp $< $@
@zip $@ boot.firm -x "*.DS_Store*" "*__MACOSX*"
.PHONY: $(dir_arm11)
.PHONY: $(dir_chainloader)
.PHONY: $(dir_arm9_exceptions)
.PHONY: $(dir_k11_extension)
.PHONY: $(dir_loader)
.PHONY: $(dir_rosalina)
.PHONY: $(dir_sm)
.PHONY: $(dir_pxi)
boot.firm: $(SUBFOLDERS)
@firmtool build $@ -D sysmodules/sysmodules.bin arm11/arm11.elf arm9/arm9.elf k11_extension/k11_extension.elf \
-A 0x18180000 -C XDMA XDMA NDMA XDMA
@echo built... $(notdir $@)
hbmenu.zip:
@curl -sSfL $(shell curl -s https://api.github.com/repos/devkitPro/3ds-hbmenu/releases/latest | grep 'browser_' | cut -d\" -f4) -o $@
@echo downloaded... $(notdir $@)
$(dir_out)/$(name)$(revision).7z: all
@mkdir -p "$(@D)"
@[ -f "$@" ] || 7z a -mx $@ ./$(@D)/* ./$(dir_exceptions)/exception_dump_parser -xr!.DS_Store
$(dir_out)/boot.firm: $(dir_build)/modules.bin $(dir_build)/arm11.elf $(dir_build)/main.elf $(dir_build)/k11_extension.bin
@mkdir -p "$(@D)"
@firmtool build $@ -D $^ -A 0x18180000 0x18000000 -C XDMA XDMA NDMA XDMA
$(dir_build)/modules.bin: $(modules)
@mkdir -p "$(@D)"
cat $^ > $@
$(dir_build)/arm11.elf: $(dir_arm11)
@mkdir -p "$(@D)"
@$(MAKE) -C $<
$(dir_build)/main.elf: $(bundled) $(objects)
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
$(dir_build)/k11_extension.bin: $(dir_k11_extension)
@mkdir -p "$(@D)"
@$(MAKE) -C $<
$(dir_build)/loader.cxi: $(dir_loader)
@mkdir -p "$(@D)"
@$(MAKE) -C $<
$(dir_build)/rosalina.cxi: $(dir_rosalina)
@mkdir -p "$(@D)"
@$(MAKE) -C $<
$(dir_build)/sm.cxi: $(dir_sm)
@mkdir -p "$(@D)"
@$(MAKE) -C $<
$(dir_build)/pxi.cxi: $(dir_pxi)
@mkdir -p "$(@D)"
@$(MAKE) -C $<
$(dir_build)/%.bin.o: $(dir_build)/%.bin
@$(bin2o)
$(dir_build)/chainloader.bin: $(dir_chainloader)
@mkdir -p "$(@D)"
@$(MAKE) -C $<
$(dir_build)/arm9_exceptions.bin: $(dir_arm9_exceptions)
@mkdir -p "$(@D)"
@$(MAKE) -C $<
$(dir_build)/%.bin: $(dir_patches)/%.s
@mkdir -p "$(@D)"
@armips $<
$(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3
$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configuration\""
$(dir_build)/patches.o: CFLAGS += -DVERSION_MAJOR="$(version_major)" -DVERSION_MINOR="$(version_minor)"\
-DVERSION_BUILD="$(version_build)" -DISRELEASE="$(is_release)" -DCOMMIT_HASH="0x$(commit)"
$(dir_build)/firm.o: $(dir_build)/modules.bin
$(dir_build)/firm.o: CFLAGS += -DLUMA_SECTION0_SIZE="$(shell wc -c $(dir_build)/modules.bin | tr -d [:space:][:alpha:][:punct:])"
$(dir_build)/bundled.h: $(bundled)
@$(foreach f, $(bundled),\
echo "extern const u8" `(echo $(basename $(notdir $(f))) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> $@;\
echo "extern const u32" `(echo $(basename $(notdir $(f)))| sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> $@;\
)
$(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/bundled.h
@mkdir -p "$(@D)"
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(dir_build)/%.o: $(dir_source)/%.s
@mkdir -p "$(@D)"
$(COMPILE.s) $(OUTPUT_OPTION) $<
$(SUBFOLDERS):
@$(MAKE) -C $@ all

122
README.md
View File

@ -1,40 +1,112 @@
# Luma3DS
*Noob-proof (N)3DS "Custom Firmware"*
## What it is
![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/LumaTeam/Luma3DS/total)
![License](https://img.shields.io/badge/License-GPLv3-blue.svg)
**Luma3DS** is a program to patch the system software of (New) Nintendo 3DS handheld consoles "on the fly", adding features (such as per-game language settings and debugging capabilities for developers) and removing restrictions enforced by Nintendo (such as the region lock).
It also allows you to run unauthorized ("homebrew") content by removing signature checks.
To use it, you will need a console capable of running homebrew software on the ARM9 processor. We recommend [Plailect's guide](https://3ds.guide/) for details on how to get your system ready.
*Nintendo 3DS "Custom Firmware"*
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)).
![Boot menu screenshot](img/boot_menu_v1321.png)
![Rosalina menu screenshot](img/rosalina_menu_v1321.png)
---
## Description
**Luma3DS** patches and reimplements significant parts of the system software running on all models of the Nintendo 3DS family of consoles. It aims to greatly improve the user experience and support the 3DS far beyond its end-of-life. Features include:
## Compiling
* **First-class support for homebrew applications**
* **Rosalina**, an overlay menu (triggered by <kbd>L+Down+Select</kbd> by default), allowing things like:
* Taking screenshots while in game
* Blue light filters and other screen filters
* Input redirection to play with external devices, such as controllers
* Using cheat codes
* Setting time and date accurately from the network (NTP)
* ... and much more!
* **Many game modding features**, such as, but not limited to:
* Game plugins (in 3GX format)
* Per-game language overrides ("locale emulation")
* Asset content path redirection ("LayeredFS")
* **Support for user-provided patches and/or full "system modules" replacements**, an essential feature for Nintendo Network replacements (amongst other projects)
* A **fully-fledged GDB stub**, allowing homebrew developers and reverse-engineers alike to work much more efficiently
* Ability to chainload other firmware files, including other versions of itself
* ... and much more!
First you need to clone the repository with: `git clone https://github.com/AuroraWright/Luma3DS.git`
To compile, you'll need [armips](https://github.com/Kingcom/armips) and a build of a recent commit of [makerom](https://github.com/profi200/Project_CTR) added to your PATH. You'll also need to install [firmtool](https://github.com/TuxSH/firmtool), its README contains installation instructions.
You'll also need to update your [libctru](https://github.com/smealum/ctrulib) install, building from the latest commit.
Here are [Windows](https://buildbot.orphis.net/armips/) and [Linux](https://mega.nz/#!uQ1T1IAD!Q91O0e12LXKiaXh_YjXD3D5m8_W3FuMI-hEa6KVMRDQ) builds of armips (thanks to who compiled them!) and [makerom](https://github.com/Steveice10/buildtools/tree/master/3ds) (thanks @Steveice10!).
Run `make` and everything should work!
You can find the compiled files in the `out` folder.
## Installation and upgrade
Luma3DS requires [boot9strap](https://github.com/SciresM/boot9strap) to run.
---
Once boot9strap has been installed, simply download the [latest release archive](https://github.com/LumaTeam/Luma3DS/releases/latest) and extract the archive onto the root of your SD card to "install" or to upgrade Luma3DS alongside the [homebrew menu and certs bundle](https://github.com/devkitPro/3ds-hbmenu) shipped with it. Replace existing files and merge existing folders if necessary.
## Setup / Usage / Features
## Basic usage
**The main Luma3DS configuration menu** can be accessed by pressing <kbd>Select</kbd> at boot. The configuration file is stored in `/luma/config.ini` on the SD card (or `/rw/luma/config.ini` on the CTRNAND partition if Luma3DS has been launched from the CTRNAND partition, which happens when SD card is missing).
See https://github.com/AuroraWright/Luma3DS/wiki
**The chainloader menu** is accessed by pressing <kbd>Start</kbd> at boot, or from the configuration menu. Payloads are expected to be located in `/luma/payloads` with the `.firm` extension; if there is only one such payload, the aforementionned selection menu will be skipped. Hotkeys can be assigned to payload, for example `x_test.firm` will be chainloaded when <kbd>X</kbd> is pressed at boot.
---
**The overlay menu, Rosalina**, has a default button combination: <kbd>L+Down+Select</kbd>. For greater flexbility, most Rosalina menu settings aren't saved automatically, hence the "Save settings" option.
**GDB ports**, when enabled, are `4000-4002` for the normal ports. Use of `attach` in "extended-remote" mode, alongside `info os processes` is supported and encouraged (for reverse-engineering, also check out `monitor getmemregions`). The port for the break-on-start feature is `4003` without "extended-remote". Both devkitARM-patched GDB and IDA Pro (without "stepping support" enabled) are actively supported.
We have a wiki, however it is currently very outdated.
## Components
Luma3DS consists of multiple components. While the code style within each component is mostly consistent, these components have been written over many years and may not reflect how maintainers would write new code in new components/projects:
* **arm9**, **arm11**: baremetal main settings menu, chainloader and firmware loader. Aside from showing settings and chainloading to other homebrew firmware files on demand, it is responsible for patching the official firmware to modify `Process9` code and to inject all other custom components. This was the first component ever written for this project, in 2015
* **k11_extension**: code extending the Arm11 `NATIVE_FIRM` kernel (`Kernel11`). It is injected by the above mentioned baremetal loader into the kernel by hooking its startup code, then hooks itself into the rest of the kernel. Its features include hooking system calls (SVCs), introducing new SVCs and hooking into interprocess communications, to bypass limitations in Nintendo's system design. This is the component that allows Rosalina to pause other processes on overlay menu entry, for example. This was written at a time when we didn't fully reverse-engineer the kernel, and originally released in 2017 alongside Rosalina. Further hooks for "game plugin" support have been merged in 2023
* **sysmodules**: reimplementation of "system modules" (processes) of the 3DS's OS (except for Rosalina being custom), currently only initial processes loaded directly in-memory by the kernel ("kernel initial process", or KIP in short)
* **loader**: process that loads non-KIP processes from storage. Because this is the perfect place to patch/replace executable code, this is where all process patches are done, enabling in particular "game modding" features. This is also the sysmodule handling 3DSX homebrew loading. Introduced in 2016
* _**rosalina**_: the most important component of Luma3DS and custom KIP: overlay menu, GDB server, `err:f` (fatal error screen) reimplementation, and much more. Introduced in mid-2017, and has continuously undergone changes and received many external contributions ever since
* **pxi**: Arm11<>Arm9 communication KIP, reimplemented just for the sake of it. Introduced late 2017
* **sm**: service manager KIP, reimplemented to remove service access control restrictions. Introduced late 2017
* **pm**: process manager KIP reponsible of starting/terminating processes and instructing `loader` to load them. The reimplemention allows for break-on-start GDB feature in Rosalina, as well as lifting FS access control restrictions the proper way. Introduced in 2019
## Maintainers
* **[@TuxSH](https://github.com/TuxSH)**: lead developer, created and maintains most features of the project. Joined in 2016
* **[@AuroraWright](https://github.com/AuroraWright)**: author of the project, implemented the core features (most of the baremetal boot settings menu and firmware loading code) with successful design decisions that made the project popular. Created the project in 2015, currently inactive
* **[@PabloMK7](https://github.com/PabloMK7)**: maintainer of the plugin loader feature merged for the v13.0 release. Joined in 2023
## Roadmap
There are still a lot more features and consolidation planned for Luma3DS! Here is a list of what is currently in store:
* Full reimplementation of `TwlBg` and `AgbBg`. This will allow much better, and more configurable, upscaling for top screen in DS and GBA games (except on Old 2DS). This is currently being developed privately in C++23 (no ETA). While this is quite a difficult endeavor as this requires rewriting the entire driver stack in semi-bare-metal (limited kernel with no IPC), this is the most critical feature for Luma3DS to have and will make driver sysmodule reimpelementation trivial
* Reimplementation of `Process9` for `TWL_FIRM` and `AGB_FIRM` to allow for more features in DS and GBA compatibility mode (ones that require file access)
* Eventually, a full `Kernel11` reimplementation
## Known issues
* **Cheat engine crashes with some applications, in particular Pokémon games**: there is a race condition in Nintendo's `Kernel11` pertaining to attaching a new `KDebugThread` to a `KThread` on thread creation, and another thread null-dereferencing `thread->debugThread`. This causes the cheat engine to crashes games that create and destroy many threads all the time (like Pokémon).
* For these games, having a **dedicated "game plugin"** is the only alternative until `Kernel11` is reimplemented.
* **Applications reacting to Rosalina menu button combo**: Rosalina merely polls button input at an interval to know when to show the menu. This means that the Rosalina menu combo can sometimes be processed by the game/process that is going to be paused.
* You can **change the menu combo** in the "Miscellaneous options" submenu (then save it with "Save settings" in the main menu) to work around this.
## Building from source
To build Luma3DS, the following is needed:
* git
* [makerom](https://github.com/jakcron/Project_CTR) in `$PATH`
* [firmtool](https://github.com/TuxSH/firmtool) installed
* up-to-date devkitARM and libctru:
* install `dkp-pacman` (or, for distributions that already provide pacman, add repositories): https://devkitpro.org/wiki/devkitPro_pacman
* install packages from `3ds-dev` metapackage: `sudo dkp-pacman -S 3ds-dev --needed`
* while libctru and Luma3DS releases are kept in sync, you may have to build libctru from source for non-release Luma3DS commits
While Luma3DS releases are bundled with `3ds-hbmenu`, Luma3DS actually compiles into one single file: `boot.firm`. Just copy it over to the root of your SD card ([ftpd](https://github.com/mtheall/ftpd) is the easiest way to do so), and you're done.
## Licensing
This software is licensed under the terms of the GPLv3. You can find a copy of the license in the LICENSE.txt file.
Files in the GDB stub are instead triple-licensed as MIT or "GPLv2 or any later version", in which case it's specified in the file header. PM, SM, PXI reimplementations are also licensed under MIT.
## Credits
See https://github.com/AuroraWright/Luma3DS/wiki/Credits
Luma3DS would not be what it is without the contributions and constructive feedback of many. We would like to thanks in particular:
---
## Licensing
This software is licensed under the terms of the GPLv3.
You can find a copy of the license in the LICENSE.txt file.
* **[@devkitPro](https://github.com/devkitPro)** (especially **[@fincs](https://github.com/fincs)**, **[@WinterMute](https://github.com/WinterMute)** and **[@mtheall](https://github.com/mtheall)**) for providing quality and easy-to-use toolchains with bleeding-edge GCC, and for their continued technical advice
* **[@Nanquitas](https://github.com/Nanquitas)** for the initial version of the game plugin loader code as well as very useful contributions to the GDB stub
* **[@piepie62](https://github.com/piepie62)** for the current implementation of the Rosalina cheat engine, **Duckbill** for its original implementation
* **[@panicbit](https://github.com/panicbit)** for the original implementation of screen filters in Rosalina
* **[@jasondellaluce](https://github.com/jasondellaluce)** for LayeredFS
* **[@LiquidFenrir](https://github.com/LiquidFenrir)** for the memory viewer inside Rosalina's "Process List"
* **ChaN** for [FatFs](http://elm-chan.org/fsw/ff/00index_e.html)
* Everyone who has contributed to the Luma3DS repository
* Everyone who has assisted with troubleshooting end-users
* Everyone who has provided constructive feedback to Luma3DS

View File

@ -1,39 +1,147 @@
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/base_tools
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/base_rules
name := $(shell basename $(CURDIR))
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source source/svc
DATA := data
INCLUDES := include include/svc
dir_source := source
dir_build := build
dir_out := ../$(dir_build)
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
DEFINES := -DARM11 -D__3DS__
ASFLAGS := -mcpu=mpcore
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
LDFLAGS := -nostartfiles -Wl,--nmagic
CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \
-fomit-frame-pointer -ffunction-sections -fdata-sections \
-Wno-main -fno-builtin $(ARCH) $(DEFINES)
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
$(call rwildcard, $(dir_source), *.s *.c)))
CFLAGS += $(INCLUDE)
.PHONY: all
all: $(dir_out)/$(name).elf
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
.PHONY: clean
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@rm -rf $(dir_build)
@echo clean ...
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
$(dir_out)/$(name).elf: $(objects)
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
$(dir_build)/%.o: $(dir_source)/%.c
@mkdir -p "$(@D)"
$(COMPILE.c) $(OUTPUT_OPTION) $<
#---------------------------------------------------------------------------------
else
.PHONY: all
$(dir_build)/%.o: $(dir_source)/%.s
@mkdir -p "$(@D)"
$(COMPILE.s) $(OUTPUT_OPTION) $<
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT).bin
$(OUTPUT).bin : $(OUTPUT).elf
$(OBJCOPY) -S -O binary $< $@
@echo built ... $(notdir $@)
$(OUTPUT).elf : $(OFILES)
%.elf: $(OFILES)
@echo linking $(notdir $@)
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
@$(NM) -CSn $@ > $(notdir $*.lst)
$(OFILES_SRC) : $(HFILES_BIN)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -1,16 +1,158 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */
PHDRS
{
main PT_LOAD;
}
SECTIONS
{
. = 0x1FF80000;
PROVIDE(__start__ = 0x1FF80000);
PROVIDE(__stack_top__ = 0x1FFFE000);
PROVIDE(__stack_bottom__ = 0x1FFFD000);
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.data : ALIGN(4) { *(.data*); . = ALIGN(4); }
.bss : ALIGN(8) { __bss_start = .; *(.bss* COMMON); . = ALIGN(8); __bss_end = .; }
. = __start__;
__stack_top__ = 0x1FFFE000;
. = ALIGN(4);
.text :
{
KEEP( *(.text.start) )
KEEP( *(.init) )
/* .text */
*(.text)
*(.text.*)
*(.glue_7)
*(.glue_7t)
*(.stub)
*(.gnu.warning)
*(.gnu.linkonce.t*)
/* .fini */
KEEP( *(.fini) )
. = ALIGN(32);
} :main
.rodata :
{
*(.rodata)
*(.roda)
*(.rodata.*)
*all.rodata*(*)
*(.gnu.linkonce.r*)
SORT(CONSTRUCTORS)
. = ALIGN(8);
}
.preinit_array :
{
PROVIDE (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE (__preinit_array_end = .);
}
.init_array :
{
PROVIDE (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE (__init_array_end = .);
}
.fini_array :
{
PROVIDE (__fini_array_start = .);
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
PROVIDE (__fini_array_end = .);
}
.ctors :
{
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
}
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = .;}
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = .;}
.data :
{
*(.data)
*(.data.*)
KEEP (*(.large_patch*))
*(.gnu.linkonce.d*)
CONSTRUCTORS
. = ALIGN(32);
}
.bss (NOLOAD) :
{
. = ALIGN(32);
PROVIDE (__bss_start__ = ABSOLUTE(.));
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b*)
*(COMMON)
. = ALIGN(8);
PROVIDE (__bss_end__ = ABSOLUTE(.));
} :NONE
PROVIDE (__end__ = ABSOLUTE(.));
/* ==================
==== Metadata ====
================== */
/* Discard sections that difficult post-processing */
/DISCARD/ : { *(.group .comment .note) }
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
}

7
arm11/linker.specs Normal file
View File

@ -0,0 +1,7 @@
%rename link old_link
*link:
%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections --no-warn-rwx-segments
*startfile:
crti%O%s crtbegin%O%s

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -40,6 +40,10 @@ extern volatile Arm11Operation operation;
static void initScreens(u32 brightnessLevel, struct fb *fbs)
{
*(vu32 *)0x10141200 = 0x1007F;
*(vu32 *)0x10202204 = 0x01000000; //set LCD fill black to hide potential garbage -- NFIRM does it before firmlaunching
*(vu32 *)0x10202A04 = 0x01000000;
*(vu32 *)0x10202014 = 0x00000001;
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
*(vu32 *)0x10202240 = brightnessLevel;
@ -80,7 +84,8 @@ static void initScreens(u32 brightnessLevel, struct fb *fbs)
*(vu32 *)0x10400490 = 0x000002D0;
*(vu32 *)0x1040049C = 0x00000000;
//Disco register
// Color LUT
*(vu32 *)0x10400480 = 0;
for(u32 i = 0; i < 256; i++)
*(vu32 *)0x10400484 = 0x10101 * i;
@ -115,19 +120,37 @@ static void initScreens(u32 brightnessLevel, struct fb *fbs)
*(vu32 *)0x10400590 = 0x000002D0;
*(vu32 *)0x1040059C = 0x00000000;
//Disco register
// Color LUT
*(vu32 *)0x10400580 = 0;
for(u32 i = 0; i < 256; i++)
*(vu32 *)0x10400584 = 0x10101 * i;
*(vu32 *)0x10202204 = 0x00000000; //unset LCD fill
*(vu32 *)0x10202A04 = 0x00000000;
}
static void setupFramebuffers(struct fb *fbs)
{
*(vu32 *)0x10202204 = 0x01000000; //set LCD fill black to hide potential garbage -- NFIRM does it before firmlaunching
*(vu32 *)0x10202A04 = 0x01000000;
*(vu32 *)0x10400468 = (u32)fbs[0].top_left;
*(vu32 *)0x1040046c = (u32)fbs[1].top_left;
*(vu32 *)0x10400494 = (u32)fbs[0].top_right;
*(vu32 *)0x10400498 = (u32)fbs[1].top_right;
*(vu32 *)0x10400568 = (u32)fbs[0].bottom;
*(vu32 *)0x1040056c = (u32)fbs[1].bottom;
//Set framebuffer format, framebuffer select and stride
*(vu32 *)0x10400470 = 0x80341;
*(vu32 *)0x10400478 = 0;
*(vu32 *)0x10400490 = 0x2D0;
*(vu32 *)0x10400570 = 0x80301;
*(vu32 *)0x10400578 = 0;
*(vu32 *)0x10400590 = 0x2D0;
*(vu32 *)0x10202204 = 0x00000000; //unset LCD fill
*(vu32 *)0x10202A04 = 0x00000000;
}
static void clearScreens(struct fb *fb)
@ -154,7 +177,7 @@ static void swapFramebuffers(bool isAlternate)
{
u32 isAlternateTmp = isAlternate ? 1 : 0;
*(vu32 *)0x10400478 = (*(vu32 *)0x10400478 & 0xFFFFFFFE) | isAlternateTmp;
*(vu32 *)0x10400578 = (*(vu32 *)0x10400478 & 0xFFFFFFFE) | isAlternateTmp;
*(vu32 *)0x10400578 = (*(vu32 *)0x10400578 & 0xFFFFFFFE) | isAlternateTmp;
}
static void updateBrightness(u32 brightnessLevel)
@ -172,6 +195,28 @@ static void deinitScreens(void)
*(vu32 *)0x10202014 = 0;
}
static void zerofillN3dsAblRegisters(void)
{
// It should be fine to write to these regs even on O3DS as they
// are RAZ/WI
// TODO: read from calibration, but null values should do just
// fine. From testing, LUT explicitly ignores null values, and
// it is probably the case of reg @ 0x54 as well.
*(vu32 *)0x10202250 = 0; // unknown 24-bit value, seen: 0
*(vu32 *)0x10202254 = 0; // unknown 24-bit value, seen: nonzero
*(vu32 *)0x10202A50 = 0; // unknown 24-bit value, seen: 0
*(vu32 *)0x10202A54 = 0; // unknown 24-bit value, seen: nonzero
for (u32 i = 0; i < 64; i++) {
// Blend colors (w/ color multiplication) for each group
// of 4 relative-luminance Rs
*(vu32 *)(0x10202300 + 4*i) = 0;
*(vu32 *)(0x10202B00 + 4*i) = 0;
}
}
void main(void)
{
operation = ARM11_READY;
@ -200,6 +245,9 @@ void main(void)
case DEINIT_SCREENS:
deinitScreens();
break;
case ZEROFILL_N3DS_ABL_REGISTERS:
zerofillN3dsAblRegisters();
break;
case PREPARE_ARM11_FOR_FIRMLAUNCH:
memcpy((void *)0x1FFFFC00, (void *)prepareForFirmlaunch, prepareForFirmlaunchSize);
*(vu32 *)0x1FFFFFFC = 0;

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
@ This file is part of Luma3DS
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
@
@ This program is free software: you can redistribute it and/or modify
@ it under the terms of the GNU General Public License as published by
@ -22,7 +22,7 @@
@ or requiring that modified versions of such material be marked in
@ reasonable ways as different from the original version.
.section .text.start
.section .text.start, "ax", %progbits
.align 4
.global _start
.type _start, %function
@ -53,20 +53,25 @@ start:
mcr p15, 0, r0, c7, c7, 0
mcr p15, 0, r0, c7, c10, 4
@ Clear BSS
ldr r0, =__bss_start
mov r1, #0
ldr r2, =__bss_end
sub r2, r0
bl memset32
ldr sp, =__stack_top__
mov fp, #0
@ Clear BSS
ldr r0, =__bss_start__
mov r1, #0
ldr r2, =__bss_end__
sub r2, r0
bl memset
@ Call the init array
bl __libc_init_array
b main
.global prepareForFirmlaunch
.type prepareForFirmlaunch, %function
prepareForFirmlaunch:
str r0, [r1] @ tell ARM9 we're done
str r0, [r1] @ tell Arm9 we're done
mov r0, #0x20000000
_wait_for_core0_entrypoint_loop:

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -60,6 +60,7 @@ typedef enum
SWAP_FRAMEBUFFERS,
UPDATE_BRIGHTNESS,
DEINIT_SCREENS,
ZEROFILL_N3DS_ABL_REGISTERS,
PREPARE_ARM11_FOR_FIRMLAUNCH,
ARM11_READY,
} Arm11Operation;

191
arm9/Makefile Normal file
View File

@ -0,0 +1,191 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/base_rules
export REVISION := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/')
export VERSION_MAJOR := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f1 -d.)
export VERSION_MINOR := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f2 -d.)
export VERSION_BUILD := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f3 -d.)
export COMMIT := $(shell git rev-parse --short=8 HEAD)
export IS_RELEASE := 0
ifeq ($(strip $(REVISION)),)
export REVISION := v0.0.0-0
export VERSION_MAJOR := 0
export VERSION_MINOR := 0
export VERSION_BUILD := 0
endif
ifeq ($(strip $(COMMIT)),)
export COMMIT := 0
endif
ifeq ($(strip $(VERSION_BUILD)),)
export VERSION_BUILD := 0
endif
ifeq ($(strip $(shell git describe --tags --match v[0-9]* | grep -)),)
export IS_RELEASE := 1
endif
# Default 3DSX TitleID for hb:ldr (note: also defined in top-level Makefile)
export HBLDR_DEFAULT_3DSX_TID ?= 000400000D921E00
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
APP_TITLE := Luma3DS
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source source/fatfs source/fatfs/sdmmc
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -marm -march=armv5te -mtune=arm946e-s
ifeq ($(BUILD_FOR_EXPLOIT_DEV),1)
DEFINES := -DARM9 -D__3DS__ -DHBLDR_DEFAULT_3DSX_TID="0x$(HBLDR_DEFAULT_3DSX_TID)ULL" -DBUILD_FOR_EXPLOIT_DEV=1
else
DEFINES := -DARM9 -D__3DS__ -DHBLDR_DEFAULT_3DSX_TID="0x$(HBLDR_DEFAULT_3DSX_TID)ULL"
endif
FALSEPOSITIVES := -Wno-array-bounds -Wno-stringop-overflow -Wno-stringop-overread
CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \
-fomit-frame-pointer -ffunction-sections -fdata-sections \
-Wno-main $(FALSEPOSITIVES) $(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE)
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
export APP_TITLE := $(notdir $(TOPDIR)/..)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
#---------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)
%.elf: $(OFILES)
@echo linking $(notdir $@)
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
@$(NM) -CSn $@ > $(notdir $*.lst)
$(OFILES_SRC) : $(HFILES_BIN)
memory.o strings.o: CFLAGS += -O3
patches.o config.o: CFLAGS += -DCONFIG_TITLE="\"$(APP_TITLE) $(REVISION) configuration\""\
-DVERSION_MAJOR="$(VERSION_MAJOR)" -DVERSION_MINOR="$(VERSION_MINOR)"\
-DVERSION_BUILD="$(VERSION_BUILD)" -DISRELEASE="$(IS_RELEASE)" -DCOMMIT_HASH="0x$(COMMIT)"
config.o ini.o: CFLAGS += -DINI_HANDLER_LINENO=1 -DINI_STOP_ON_FIRST_ERROR=1
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
%.ini.o %_ini.h: %.ini
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

Binary file not shown.

210
arm9/linker.ld Normal file
View File

@ -0,0 +1,210 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
PHDRS
{
crt0 PT_LOAD;
itcm PT_LOAD;
main PT_LOAD;
}
/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */
MEMORY
{
main : ORIGIN = 0x08006000, LENGTH = 0x080F0000 - 0x08006000
itcm : ORIGIN = 0x01FF8000, LENGTH = 0x01FFB800 - 0x01FF8000 /* Unused ITCM slice. */
}
SECTIONS
{
PROVIDE(__start__ = 0x08006000);
PROVIDE(__stack_top__ = 0x08100000);
PROVIDE(__stack_bottom__ = 0x080F0000);
PROVIDE(__itcm_stack_top__ = 0x01FFB800);
PROVIDE(__itcm_stack_bottom__ = 0x01FFA800);
. = __start__;
.crt0 :
{
KEEP( *(.text.start) )
KEEP( *(.init) )
. = ALIGN(32);
} >main :crt0
.itcm_loadable :
{
PROVIDE (__itcm_start__ = ABSOLUTE(.));
PROVIDE (__itcm_lma__ = LOADADDR(.itcm_loadable));
KEEP(*(.arm9_exception_handlers.text))
*(.arm9_exception_handlers.text*)
KEEP(*(.chainloader.text.start))
chainloader.o(.text*)
i2c.o(.text*)
arm9_exception_handlers.o(.text*)
KEEP (*(.emunand_patch))
*(.arm9_exception_handlers.rodata*)
chainloader.o(.rodata*)
i2c.o(.rodata*)
arm9_exception_handlers.o(.rodata*)
*(.arm9_exception_handlers.data*)
chainloader.o(.data*)
i2c.o(.data*)
arm9_exception_handlers.o(.data*)
. = ALIGN(32);
} >itcm AT>main :itcm
.itcm_bss (NOLOAD) :
{
. = ALIGN(32);
PROVIDE (__itcm_bss_start__ = ABSOLUTE(.));
*(.arm9_exception_handlers.bss*)
chainloader.o(.bss* COMMON)
i2c.o(.bss* COMMON)
arm9_exception_handlers.o(.bss* COMMON)
. = ALIGN(32);
PROVIDE (__itcm_end__ = ABSOLUTE(.));
} >itcm :NONE
.text :
{
/* .text */
*(.text)
*(.text.*)
*(.glue_7)
*(.glue_7t)
*(.stub)
*(.gnu.warning)
*(.gnu.linkonce.t*)
/* .fini */
KEEP( *(.fini) )
. = ALIGN(8);
} >main :main
.rodata :
{
*(.rodata)
*(.roda)
*(.rodata.*)
*all.rodata*(*)
*(.gnu.linkonce.r*)
SORT(CONSTRUCTORS)
. = ALIGN(8);
} >main
.preinit_array :
{
PROVIDE (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE (__preinit_array_end = .);
} >main
.init_array ALIGN(4) :
{
PROVIDE (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE (__init_array_end = .);
} >main
.fini_array ALIGN(4) :
{
PROVIDE (__fini_array_start = .);
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
PROVIDE (__fini_array_end = .);
} >main
.ctors ALIGN(4) :
{
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >main
.dtors ALIGN(4) :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >main
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = ABSOLUTE(.);} >main
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = ABSOLUTE(.);} >main
.data :
{
*(.data)
*(.data.*)
KEEP (*(.large_patch*))
*(.gnu.linkonce.d*)
CONSTRUCTORS
. = ALIGN(32);
} >main
.bss (NOLOAD) :
{
. = ALIGN(32);
PROVIDE (__bss_start__ = ABSOLUTE(.));
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b*)
*(COMMON)
. = ALIGN(8);
PROVIDE (__bss_end__ = ABSOLUTE(.));
} >main :NONE
__end__ = ABSOLUTE(.) ;
/* ==================
==== Metadata ====
================== */
/* Discard sections that difficult post-processing */
/DISCARD/ : { *(.group .comment .note) }
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
}

7
arm9/linker.specs Normal file
View File

@ -0,0 +1,7 @@
%rename link old_link
*link:
%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections --no-warn-rwx-segments
*startfile:
crti%O%s crtbegin%O%s

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -30,21 +30,21 @@
#pragma once
typedef struct __attribute__((packed))
typedef struct
{
u32 address;
u32 phyRegionSize;
u32 size;
} CodeSetInfo;
typedef struct __attribute__((packed))
typedef struct
{
u32 saveDataSize[2];
u32 jumpID[2];
u8 reserved[0x30];
} SystemInfo;
typedef struct __attribute__((packed))
typedef struct
{
char appTitle[8];
u8 reserved1[5];
@ -60,7 +60,7 @@ typedef struct __attribute__((packed))
SystemInfo systemInfo;
} SystemControlInfo;
typedef struct __attribute__((packed))
typedef struct
{
SystemControlInfo systemControlInfo;
u8 aci[0x200];
@ -69,7 +69,7 @@ typedef struct __attribute__((packed))
u8 aciLim[0x200];
} ExHeader;
typedef struct __attribute__((packed))
typedef struct
{
u8 sig[0x100]; //RSA-2048 signature of the NCCH header, using SHA-256
char magic[4]; //NCCH
@ -102,13 +102,27 @@ typedef struct __attribute__((packed))
u8 romFsHash[0x20]; //RomFS superblock SHA-256 hash
} Ncch;
typedef struct __attribute__((packed))
typedef struct ExeFsFileHeader
{
char name[8];
u32 offset;
u32 size;
} ExeFsFileHeader;
typedef struct ExeFsHeader
{
ExeFsFileHeader fileHeaders[10];
u8 _reserved_0xa0[0xC0 - 0xA0];
u8 fileHashes[10][32];
} ExeFsHeader;
typedef struct
{
Ncch ncch;
ExHeader exHeader;
} Cxi;
typedef struct __attribute__((packed))
typedef struct
{
char sigIssuer[0x40];
u8 eccPubKey[0x3C];
@ -134,7 +148,7 @@ typedef struct __attribute__((packed))
u8 contentIndex[0xAC];
} Ticket;
typedef struct __attribute__((packed))
typedef struct
{
u32 offset;
u8 *address;
@ -143,7 +157,7 @@ typedef struct __attribute__((packed))
u8 hash[0x20];
} FirmSection;
typedef struct __attribute__((packed))
typedef struct
{
char magic[4];
u32 reserved1;
@ -153,7 +167,7 @@ typedef struct __attribute__((packed))
FirmSection section[4];
} Firm;
typedef struct __attribute__((packed))
typedef struct
{
u8 keyX[0x10];
u8 keyY[0x10];

View File

@ -0,0 +1,28 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#include "types.h"
void *alignedseqmemcpy(void *dst, const void *src, u32 len);

View File

@ -1,5 +1,5 @@
@ This file is part of Luma3DS
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
@
@ This program is free software: you can redistribute it and/or modify
@ it under the terms of the GNU General Public License as published by
@ -21,40 +21,45 @@
@ * Prohibiting misrepresentation of the origin of that material,
@ or requiring that modified versions of such material be marked in
@ reasonable ways as different from the original version.
.section .text.alignedseqmemcpy, "ax", %progbits
.arm
@ Align on cache line boundaries & make sure the loops don't cross them.
.align 5
.global alignedseqmemcpy
.type alignedseqmemcpy, %function
alignedseqmemcpy:
@ src=r1 and dst=r0 are expected to be 4-byte-aligned
push {r4-r10, lr}
.section .text.start
.align 4
.global _start
_start:
ldr sp, =__stack_top__
b main
lsrs r12, r2, #5
sub r2, r2, r12, lsl #5
beq 2f
.text
.balign 4
.global disableMpuAndJumpToEntrypoints
.type disableMpuAndJumpToEntrypoints, %function
disableMpuAndJumpToEntrypoints:
mov r4, r0
mov r5, r1
mov r6, r2
mov r7, r3
1:
ldmia r1!, {r3-r10}
stmia r0!, {r3-r10}
subs r12, #1
bne 1b
bl flushCaches
2:
lsrs r12, r2, #2
sub r2, r2, r12, lsl #2
beq 4f
@ Disable caches / MPU
mrc p15, 0, r0, c1, c0, 0 @ read control register
bic r0, #(1<<12) @ - instruction cache disable
bic r0, #(1<<2) @ - data cache disable
bic r0, #(1<<0) @ - MPU disable
mcr p15, 0, r0, c1, c0, 0 @ write control register
3:
ldr r3, [r1], #4
str r3, [r0], #4
subs r12, #1
bne 3b
@ Set the ARM11 entrypoint
mov r0, #0x20000000
str r7, [r0, #-4]
4:
tst r2, #2
ldrneh r3, [r1], #2
strneh r3, [r0], #2
@ Jump to the ARM9 entrypoint
mov r0, r4
mov r1, r5
ldr r2, =0x3BEEF
bx r6
tst r2, #1
ldrneb r3, [r1], #1
strneb r3, [r0], #1
pop {r4-r10, pc}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -24,15 +24,26 @@
* reasonable ways as different from the original version.
*/
#include "arm9_exception_handlers.h"
#include "i2c.h"
#include "handlers.h"
#include "screen.h"
#define FINAL_BUFFER 0x25000000
#define REG_DUMP_SIZE 4 * 17
#define CODE_DUMP_SIZE 48
void __attribute__((noreturn)) mainHandler(u32 *registerDump, u32 type)
static inline void dumpArm9Memory(ExceptionDumpHeader *dumpHeader, u8 *buf)
{
// Check if n3ds extra arm9 mem is enabled (if it's possible to read CFG9_EXTMEMCNT9)
u8 extmemcnt9 = 0;
safecpy(&extmemcnt9, (const void *)0x10000200, 1);
u32 size = (extmemcnt9 & 1) ? 0x180000 : 0x100000;
dumpHeader->additionalDataSize += safecpy(buf, (const void *)0x08000000, size);
}
void __attribute__((noreturn)) arm9ExceptionHandlerMain(u32 *registerDump, u32 type)
{
ExceptionDumpHeader dumpHeader;
@ -41,7 +52,7 @@ void __attribute__((noreturn)) mainHandler(u32 *registerDump, u32 type)
dumpHeader.magic[0] = 0xDEADC0DE;
dumpHeader.magic[1] = 0xDEADCAFE;
dumpHeader.versionMajor = 1;
dumpHeader.versionMinor = 2;
dumpHeader.versionMinor = 3;
dumpHeader.processor = 9;
dumpHeader.core = 0;
@ -67,16 +78,35 @@ void __attribute__((noreturn)) mainHandler(u32 *registerDump, u32 type)
//Dump stack in place
dumpHeader.stackDumpSize = safecpy(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF));
final += dumpHeader.stackDumpSize;
// See if we need to copy Arm9 memory (check for bkpt 0xFFFD / bkpt 0xFD)
if(dumpHeader.codeDumpSize > 0)
{
if(cpsr & 0x20)
{
// Thumb
u16 instr;
safecpy(&instr, codeDump + dumpHeader.codeDumpSize - 2, 2);
if(instr == 0xBEFD) dumpArm9Memory(&dumpHeader, final);
}
else
{
u32 instr;
safecpy(&instr, codeDump + dumpHeader.codeDumpSize - 4, 4);
if(instr == 0xE12FFF7D) dumpArm9Memory(&dumpHeader, final);
}
}
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
if(ARESCREENSINITIALIZED) I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0); //Shutdown LCD
((void (*)())0xFFFF0830)(); //Ensure that all memory transfers have completed and that the data cache has been flushed
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot
I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot
while(true);
}

View File

@ -0,0 +1,32 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#include "types.h"
extern const u32 arm9ExceptionHandlerAddressTable[6];
extern u32 arm9ExceptionHandlerSvcBreakAddress;
u32 safecpy(void *dst, const void *src, u32 len);

View File

@ -1,5 +1,5 @@
@ This file is part of Luma3DS
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
@
@ This program is free software: you can redistribute it and/or modify
@ it under the terms of the GNU General Public License as published by
@ -28,16 +28,16 @@
stmia sp, {r0-r7}
mov r0, #\index
b _commonHandler
b _arm9ExceptionHandlerCommon
.endm
.text
.section .arm9_exception_handlers.text, "ax", %progbits
.arm
.balign 4
.align 4
.global _commonHandler
.type _commonHandler, %function
_commonHandler:
.global _arm9ExceptionHandlerCommon
.type _arm9ExceptionHandlerCommon, %function
_arm9ExceptionHandlerCommon:
mov r1, r0
mov r0, sp
mrs r2, spsr
@ -60,7 +60,7 @@ _commonHandler:
msr cpsr_cxsf, #0xdf @ finally, switch to system mode, mask interrupts and clear flags (in case of double faults)
ldr sp, =0x02000000
b mainHandler
b arm9ExceptionHandlerMain
.global FIQHandler
@ -80,7 +80,7 @@ prefetchAbortHandler:
cmp sp, #0x13
bne _prefetchAbortNormalHandler
ldr sp, =BreakPtr
ldr sp, =arm9ExceptionHandlerSvcBreakAddress
ldr sp, [sp]
cmp sp, #0
beq _prefetchAbortNormalHandler
@ -147,6 +147,22 @@ safecpy:
_safecpy_end:
.bss
.balign 4
.section .arm9_exception_handlers.rodata, "a", %progbits
.align 4
.global arm9ExceptionHandlerAddressTable
arm9ExceptionHandlerAddressTable:
.word 0 @ IRQ
.word FIQHandler @ FIQ
.word 0 @ SVC
.word undefinedInstructionHandler @ Undefined instruction
.word prefetchAbortHandler @ Prefetch abort
.word dataAbortHandler @ Data abort
.section .arm9_exception_handlers.bss, "aw", %nobits
.align 4
.global arm9ExceptionHandlerSvcBreakAddress
arm9ExceptionHandlerSvcBreakAddress:
.skip 4
_regs: .skip (4 * 17)

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -33,7 +33,7 @@
The data cache and/or the instruction cache MUST be flushed before doing one of the following:
- rebooting
- powering down
- setting the ARM11 entrypoint to execute a function
- setting the Arm11 entrypoint to execute a function
- jumping to a payload
***/

View File

@ -1,5 +1,5 @@
@ This file is part of Luma3DS
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
@
@ This program is free software: you can redistribute it and/or modify
@ it under the terms of the GNU General Public License as published by
@ -22,7 +22,7 @@
@ or requiring that modified versions of such material be marked in
@ reasonable ways as different from the original version.
.text
.section .text.cache, "ax", %progbits
.arm
.align 4
@ -31,7 +31,7 @@
flushEntireDCache:
@ Adapted from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html,
@ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well
@ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has)
@ Note: Arm's example is actually for a 8KB DCache (which is what the 3DS has)
@ Implemented in bootROM at address 0xffff0830
mov r1, #0 @ segment counter

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -24,11 +24,37 @@
* reasonable ways as different from the original version.
*/
#include "memory.h"
#include "cache.h"
#include "firm.h"
#include "chainloader.h"
#include "screen.h"
void main(int argc, char **argv, Firm *firm)
void disableMpuAndJumpToEntrypoints(int argc, char **argv, void *arm11Entry, void *arm9Entry);
#pragma GCC optimize (3)
static void *xmemcpy(void *dst, const void *src, u32 len)
{
const u8 *src8 = (const u8 *)src;
u8 *dst8 = (u8 *)dst;
for (u32 i = 0; i < len; i++) {
dst8[i] = src8[i];
}
return dst;
}
static void doLaunchFirm(Firm *firm, int argc, char **argv)
{
//Copy FIRM sections to respective memory locations
for(u32 sectionNum = 0; sectionNum < 4; sectionNum++)
xmemcpy(firm->section[sectionNum].address, (u8 *)firm + firm->section[sectionNum].offset, firm->section[sectionNum].size);
disableMpuAndJumpToEntrypoints(argc, argv, firm->arm9Entry, firm->arm11Entry);
__builtin_unreachable();
}
void chainloader_main(int argc, char **argv, Firm *firm)
{
char *argvPassed[2],
absPath[24 + 255];
@ -54,5 +80,5 @@ void main(int argc, char **argv, Firm *firm)
argvPassed[1] = (char *)&fbs;
}
launchFirm(firm, argc, argvPassed);
doLaunchFirm(firm, argc, argvPassed);
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -26,10 +26,7 @@
#pragma once
#include "utils.h"
#include "kernel.h"
#include "svc.h"
#include "globals.h"
#include "types.h"
#include "firm.h"
// DEPRECATED
Result GetCFWInfo(CfwInfo *out);
void chainload(int argc, char **argv, Firm *firm);

1209
arm9/source/config.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -28,39 +28,46 @@
#include "types.h"
#define AUTOBOOT_DEFAULT_TWL_TID 0x0003000448424C41ull
#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 2
#define CONFIG_VERSIONMINOR 3
#define CONFIG_FILE "config.ini"
#define CONFIG_VERSIONMAJOR 3
#define CONFIG_VERSIONMINOR 13
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
#define BOOTCFG_NOFORCEFLAG BOOTCONFIG(6, 1)
#define BOOTCFG_NTRCARDBOOT BOOTCONFIG(7, 1)
#define BOOTCFG_NAND BOOTCONFIG(0, 1)
#define BOOTCFG_EMUINDEX BOOTCONFIG(1, 3)
#define BOOTCFG_NOFORCEFLAG BOOTCONFIG(3, 1)
#define BOOTCFG_NTRCARDBOOT BOOTCONFIG(4, 1)
enum multiOptions
{
DEFAULTEMU = 0,
BRIGHTNESS,
SPLASH,
SPLASH_DURATION,
PIN,
NEWCPU
NEWCPU,
AUTOBOOTMODE,
FORCEAUDIOOUTPUT,
};
enum singleOptions
{
AUTOBOOTEMU = 0,
USEEMUFIRM,
LOADEXTFIRMSANDMODULES,
PATCHGAMES,
REDIRECTAPPTHREADS,
PATCHVERSTRING,
SHOWGBABOOT,
PATCHUNITINFO,
DISABLEARM11EXCHANDLERS
ENABLEDSIEXTFILTER,
DISABLEARM11EXCHANDLERS,
ENABLESAFEFIRMROSALINA,
NUMCONFIGURABLE = PATCHUNITINFO,
};
typedef enum ConfigurationStatus

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2021 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -34,8 +34,9 @@
#include "crypto.h"
#include "memory.h"
#include "emunand.h"
#include "strings.h"
#include "utils.h"
#include "alignedseqmemcpy.h"
#include "strings.h"
#include "fatfs/sdmmc/sdmmc.h"
/****************************************************************
@ -288,24 +289,18 @@ void sha(void *res, const void *src, u32 size, u32 mode)
sha_wait_idle();
*REG_SHA_CNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND;
const u32 *src32 = (const u32 *)src;
int i;
const u8 *src8 = (const u8 *)src;
while(size >= 0x40)
{
sha_wait_idle();
for(i = 0; i < 4; ++i)
{
*REG_SHA_INFIFO = *src32++;
*REG_SHA_INFIFO = *src32++;
*REG_SHA_INFIFO = *src32++;
*REG_SHA_INFIFO = *src32++;
}
alignedseqmemcpy((void *)REG_SHA_INFIFO, src8, 0x40);
src8 += 0x40;
size -= 0x40;
}
sha_wait_idle();
memcpy((void *)REG_SHA_INFIFO, src32, size);
alignedseqmemcpy((void *)REG_SHA_INFIFO, src8, size);
*REG_SHA_CNT = (*REG_SHA_CNT & ~SHA_NORMAL_ROUND) | SHA_FINAL_ROUND;
@ -318,7 +313,7 @@ void sha(void *res, const void *src, u32 size, u32 mode)
else if(mode == SHA_1_MODE)
hashSize = SHA_1_HASH_SIZE;
memcpy(res, (void *)REG_SHA_HASH, hashSize);
alignedseqmemcpy(res, (void *)REG_SHA_HASH, hashSize);
}
/*****************************************************************/
@ -327,7 +322,7 @@ __attribute__((aligned(4))) static u8 nandCtr[AES_BLOCK_SIZE];
static u8 nandSlot;
static u32 fatStart = 0;
FirmwareSource firmSource = FIRMWARE_SYSNAND;
FirmwareSource ctrNandLocation = 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},
@ -353,7 +348,7 @@ int ctrNandInit(void)
u8 __attribute__((aligned(4))) temp[0x200];
//Read NCSD header
result = firmSource == FIRMWARE_SYSNAND ? sdmmc_nand_readsectors(0, 1, temp) : sdmmc_sdcard_readsectors(emuHeader, 1, temp);
result = ctrNandLocation == FIRMWARE_SYSNAND ? sdmmc_nand_readsectors(0, 1, temp) : sdmmc_sdcard_readsectors(emuOffset + emuHeader, 1, temp);
if(!result)
{
@ -380,7 +375,7 @@ int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf)
//Read
int result;
if(firmSource == FIRMWARE_SYSNAND)
if(ctrNandLocation == FIRMWARE_SYSNAND)
result = sdmmc_nand_readsectors(sector + fatStart, sectorCount, outbuf);
else
{
@ -586,6 +581,9 @@ void kernel9Loader(Arm9Bin *arm9Section)
u8 arm9BinSlot = k9lVersion == 0 ? 0x15 : 0x16;
// Get size
u32 arm9SectionSize = decAtoi(arm9Section->size, 8);
//Set keyX
__attribute__((aligned(4))) u8 keyX[AES_BLOCK_SIZE];
aes_use_keyslot(0x11);
@ -601,11 +599,11 @@ void kernel9Loader(Arm9Bin *arm9Section)
__attribute__((aligned(4))) u8 arm9BinCtr[AES_BLOCK_SIZE];
memcpy(arm9BinCtr, arm9Section->ctr, sizeof(arm9BinCtr));
//Decrypt ARM9 binary
//Decrypt Arm9 binary
aes_use_keyslot(arm9BinSlot);
aes(startOfArm9Bin, startOfArm9Bin, decAtoi(arm9Section->size, sizeof(arm9Section->size)) / AES_BLOCK_SIZE, arm9BinCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
aes(startOfArm9Bin, startOfArm9Bin, arm9SectionSize / AES_BLOCK_SIZE, arm9BinCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the ARM9 binary.");
if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the Arm9 binary.");
}
void computePinHash(u8 *outbuf, const u8 *inbuf)
@ -614,7 +612,7 @@ void computePinHash(u8 *outbuf, const u8 *inbuf)
cipherText[AES_BLOCK_SIZE];
sdmmc_get_cid(1, (u32 *)cid);
aes_use_keyslot(0x04); //Console-unique keyslot whose keys are set by the ARM9 bootROM
aes_use_keyslot(0x04); //Console-unique keyslot whose keys are set by the Arm9 bootROM
aes(cipherText, inbuf, 1, cid, AES_CBC_ENCRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
sha(outbuf, cipherText, sizeof(cipherText), SHA_256_MODE);
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -110,7 +110,7 @@
#define SHA_224_HASH_SIZE (224 / 8)
#define SHA_1_HASH_SIZE (160 / 8)
extern FirmwareSource firmSource;
extern FirmwareSource ctrNandLocation;
void sha(void *res, const void *src, u32 size, u32 mode);

279
arm9/source/deliver_arg.c Normal file
View File

@ -0,0 +1,279 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2022 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 "deliver_arg.h"
#include "utils.h"
#include "memory.h"
#include "config.h"
#include "fs.h"
#include "i2c.h"
#include "screen.h"
u8 *loadDeliverArg(void)
{
static __attribute__((aligned(8))) u8 deliverArg[0x1000] = {0};
static bool deliverArgLoaded = false;
if (!deliverArgLoaded)
{
u32 bootenv = CFG_BOOTENV; // this register is preserved across reboots
if ((bootenv & 1) == 0) // true coldboot
{
memset(deliverArg, 0, 0x1000);
}
else
{
u32 mode = bootenv >> 1;
if (mode == 0) // CTR mode
{
memcpy(deliverArg, (const void *)0x20000000, 0x1000);
// Validate deliver arg
u32 testPattern = *(u32 *)(deliverArg + 0x438);
u32 *crcPtr = (u32 *)(deliverArg + 0x43C);
u32 crc = *crcPtr;
*crcPtr = 0; // clear crc field before calculation
u32 expectedCrc = crc32(deliverArg + 0x400, 0x140, 0xFFFFFFFF);
*crcPtr = crc;
if (testPattern != 0xFFFF || crc != expectedCrc)
memset(deliverArg, 0, 0x1000);
}
else // Legacy modes
{
// Copy TWL deliver arg stuff as-is (0...0x300)
copyFromLegacyModeFcram(deliverArg, (const void *)0x20000000, 0x400);
// Validate TLNC (TWL launcher params) block
// Note: Nintendo doesn't do crcLen bound check
u8 *tlnc = deliverArg + 0x300;
bool hasMagic = memcmp(tlnc, "TLNC", 4) == 0;
u8 crcLen = tlnc[5];
u16 crc = *(u16 *)(tlnc + 6);
if (!hasMagic || (8 + crcLen) > 0x100 || crc != crc16(tlnc + 8, crcLen, 0xFFFF))
memset(tlnc, 0, 0x100);
memset(deliverArg + 0x400, 0, 0xC00);
}
}
deliverArgLoaded = true;
}
return deliverArg;
}
void commitDeliverArg(void)
{
u8 *deliverArg = loadDeliverArg();
u32 bootenv = CFG_BOOTENV;
if ((bootenv & 1) == 0) // if true coldboot, set bootenv to "CTR mode reboot"
{
bootenv = 1;
CFG_BOOTENV = 1;
}
u32 mode = bootenv >> 1;
if (mode == 0) // CTR mode
{
*(u32 *)(deliverArg + 0x438) = 0xFFFF;
*(u32 *)(deliverArg + 0x43C) = 0; // clear CRC field before calculating it
*(u32 *)(deliverArg + 0x43C) = crc32(deliverArg + 0x400, 0x140, 0xFFFFFFFF);
memcpy((void *)0x20000000, deliverArg, 0x1000);
}
else // Legacy modes (just TWL mode, really)
{
copyToLegacyModeFcram((void *)0x20000000, deliverArg, 0x400);
}
}
bool hasValidTlncAutobootParams(void)
{
u8 *tlnc = loadDeliverArg() + 0x300; // loadDeliverArg clears invalid TLNC blocks
return memcmp(tlnc, "TLNC", 4) == 0 && (*(u16 *)(tlnc + 0x18) & 1) != 0;
}
bool isTwlToCtrLaunch(void)
{
// assumes TLNC block is valid
u8 *tlnc = loadDeliverArg() + 0x300; // loadDeliverArg clears invalid TLNC blocks
u64 twlTid = *(u64 *)(tlnc + 0x10);
switch (twlTid & ~0xFFull)
{
case 0x0000000000000000ull: // TWL Launcher -> Home menu (note: NS checks full TID)
case 0x00030015484E4200ull: // TWL System Settings -> CTR System Settings (mset)
return true;
default:
return false;
}
}
static bool configureHomebrewAutobootCtr(u8 *deliverArg)
{
static const u8 appmemtypesO3ds[] = { 0, 2, 3, 4, 5 };
static const u8 appmemtypesN3ds[] = { 6, 7, 7, 7, 7 };
u64 hbldrTid = configData.hbldr3dsxTitleId;
hbldrTid = hbldrTid == 0 ? HBLDR_DEFAULT_3DSX_TID : hbldrTid; // replicate Loader's behavior
if ((hbldrTid >> 46) != 0x10) // Not a CTR titleId. Bail out
return false;
u8 memtype = configData.autobootCtrAppmemtype;
// autobootCtrAppmemtype already checked, but it doesn't hurt to check again
memtype = memtype >= 5 ? 0 : memtype;
deliverArg[0x400] = ISN3DS ? appmemtypesN3ds[memtype] : appmemtypesO3ds[memtype];
// Determine whether to load from the SD card or from NAND. We don't support gamecards for this
u32 category = (hbldrTid >> 32) & 0xFFFF;
bool isSdApp = (category & 0x10) == 0 && category != 1; // not a system app nor a DLP child
*(u64 *)(deliverArg + 0x440) = hbldrTid;
*(u64 *)(deliverArg + 0x448) = isSdApp ? 1 : 0;
// Tell NS to run the title, and that it's not a title jump from legacy mode
*(u32 *)(deliverArg + 0x460) = (0 << 1) | (1 << 0);
// Whenever power button is held long enough ("force shutdown"), mcu sysmodule
// stores a flag in free reg 0. It will clear it next boot.
// During that next boot, if that flag was set and if CFG_BOOTENV.bit0 is set
// (warmboot/firm chainload, i.e. not coldbooting), then main() will simulate
// a "power button held" interrupt (after upgrading mcu fw if necessary -- it
// will reboot console after if it has upgraded mcu fw, I guess that's one of
// the reasons the flag is there). This obviously cause other processes to initiate
// a shutdown, and it also sets that flag again.
// In the case of autoboot, ns will panic when this happens. This caused
// hb autoboot to keep failing over and over again.
// Select free reg 0, read it, select it again, write it (clearing force shutdown flag)
I2C_writeReg(I2C_DEV_MCU, 0x60, 0);
u8 flags = I2C_readReg(I2C_DEV_MCU, 0x61);
flags &= ~4;
I2C_writeReg(I2C_DEV_MCU, 0x60, 0);
I2C_writeReg(I2C_DEV_MCU, 0x61, flags);
CFG_BOOTENV = 1;
return true;
}
static bool configureHomebrewAutobootTwl(u8 *deliverArg)
{
// Here, we pretend to be a TWL app rebooting into another TWL app.
// We get NS to do all the heavy lifting (starting NWM and AM, etc.) this way.
memset(deliverArg + 0x000, 0, 0x300); // zero TWL deliver arg params
// Now onto TLNC (launcher params):
u8 *tlnc = deliverArg + 0x300;
memset(tlnc, 0, 0x100);
memcpy(tlnc, "TLNC", 4);
tlnc[4] = 1; // version
tlnc[5] = 0x18; // length of data to calculate CRC over
*(u64 *)(tlnc + 8) = 0; // old title ID
*(u64 *)(tlnc + 0x10) = configData.autobootTwlTitleId; // new title ID
// bit4: "skip logo" ; bits2:1: NAND boot ; bit0: valid
*(u16 *)(tlnc + 0x18) = (1 << 4) | (3 << 1) | (1 << 0);
*(u16 *)(tlnc + 6) = crc16(tlnc + 8, 0x18, 0xFFFF);
// Even though (when running TWL/AGB FIRM) the SoC is in O3DS mode, and the GPU also is,
// as well as most other components behaving as such (external RAM, L2C not usable, etc.),
// this is NOT the case for the LCD and adaptive backlight logic which retains FULL N3DS
// functionality, including a feature where the window is blended with a given color depending
// on the overall relative luminance of that window.
// However, Nintendo's own code mistakenly assumes the opposite, and clearly so ("if GPU in N3DS mode"
// checks, not passing N3DS extra adaptive backlight (ABL) to TWL/AGB_FIRM). This has implications:
// - Powersaving (ABL) settings in TWL/AGB_FIRM is inconsistent with *both* O3DS (because the new RGB blend LUT
// has been set to its current value by NATIVE_FIRM) and N3DS (because "pwn_cnt" and "inertia" are missing
// their N3DS-only bits)
// - "rave party" when booting into TWL/AGB_FIRM or O3DS NATIVE_FIRM without these regs (well, the LUT) initialized.
// Easiest way to do so is by leveraging the "DSi autooboot" feature Luma provides. It is worth noting at least
// the LUT survives hardware reboots (if Nintendo were using DSi software that was using TLNC-based reboots,
// they wouldn't have noticed).
// As such, zerofill these registers (from testing, hardware explicitly discards null values, so this
// should be fine). For now, only touch the Luma-initiated autoboot path
if (ISN3DS)
zerofillN3dsAblRegisters();
CFG_BOOTENV = 3;
return true;
}
bool configureHomebrewAutoboot(void)
{
bool ret;
u8 *deliverArg = loadDeliverArg();
u32 bootenv = CFG_BOOTENV;
u32 mode = bootenv >> 1;
// NS always writes a valid deliver arg on reboot, no matter what.
// Check if it is empty, and, of course, bail out if we aren't rebooting from
// NATIVE_FIRM.
// Checking if it is empty is necessary to let us reboot from autobooted hbmenu
// to hbmenu.
if (mode != 0)
return false;
else if (bootenv == 1)
{
for (u32 i = 0; i < 0x410; i++)
{
if (deliverArg[i] != 0)
return false;
}
for (u32 i = 0x440; i < 0x1000; i++)
{
if (deliverArg[i] != 0)
return false;
}
}
switch (MULTICONFIG(AUTOBOOTMODE))
{
case 1:
ret = configureHomebrewAutobootCtr(deliverArg);
break;
case 2:
ret = configureHomebrewAutobootTwl(deliverArg);
break;
case 0:
default:
ret = false;
break;
}
if (ret)
commitDeliverArg();
return ret;
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2022 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -24,12 +24,14 @@
* reasonable ways as different from the original version.
*/
/*
* memcpy adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
*/
#pragma once
#include "types.h"
void memcpy(void *dest, const void *src, u32 size);
u8 *loadDeliverArg(void);
void commitDeliverArg(void);
bool hasValidTlncAutobootParams(void);
bool isTwlToCtrLaunch(void); // assumes TLNC block is valid
bool configureHomebrewAutoboot(void);

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -30,7 +30,7 @@
*/
#include "draw.h"
#include "strings.h"
#include "memory.h"
#include "screen.h"
#include "utils.h"
#include "fs.h"
@ -58,8 +58,7 @@ bool loadSplash(void)
swapFramebuffers(true);
u32 durationIndex = MULTICONFIG(SPLASH_DURATION);
wait(1000ULL + (durationIndex * 2000ULL));
wait(configData.splashDurationMsec);
return true;
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -39,6 +39,7 @@
#define COLOR_TITLE 0xFF9900
#define COLOR_WHITE 0xFFFFFF
#define COLOR_RED 0x0000FF
#define COLOR_GREEN 0x00FF00
#define COLOR_BLACK 0x000000
#define COLOR_YELLOW 0x00FFFF
@ -47,4 +48,6 @@
bool loadSplash(void);
void drawCharacter(bool isTopScreen, u32 posX, u32 posY, u32 color, char character);
u32 drawString(bool isTopScreen, u32 posX, u32 posY, u32 color, const char *string);
__attribute__((format(printf,5,6)))
u32 drawFormattedString(bool isTopScreen, u32 posX, u32 posY, u32 color, const char *fmt, ...);

338
arm9/source/emunand.c Normal file
View File

@ -0,0 +1,338 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2021 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.
*/
/*
* Code for locating the SDMMC struct by Normmatt
*/
#include "emunand.h"
#include "memory.h"
#include "utils.h"
#include "fatfs/sdmmc/sdmmc.h"
#include "large_patches.h"
u32 emuOffset,
emuHeader;
void locateEmuNand(FirmwareSource *nandType, u32 *emunandIndex, bool configureCtrNandParams)
{
static u8 __attribute__((aligned(4))) temp[0x200];
static u32 nandSize = 0,
fatStart;
if(!nandSize)
{
nandSize = getMMCDevice(0)->total_size;
sdmmc_sdcard_readsectors(0, 1, temp);
fatStart = *(u32 *)(temp + 0x1C6); //First sector of the FAT partition
}
/*if (*nandType == FIRMWARE_SYSNAND)
return;*/
for(u32 i = 0; i < 3; i++) // Test the different kinds of multi-EmuNAND there are, unless we are looking for the first one
{
static const u32 roundedMinsizes[] = {0x1D8000, 0x26E000};
u32 nandOffset;
switch(i)
{
case 1:
nandOffset = ROUND_TO_4MB(nandSize + 1); //"Default" layout
break;
case 2:
nandOffset = roundedMinsizes[ISN3DS ? 1 : 0]; //"Minsize" layout
break;
case 0:
nandOffset = nandSize > 0x200000 ? 0x400000 : 0x200000; //"Legacy" layout
break;
}
nandOffset *= *emunandIndex; // always 0 for 1st EmuNAND
if(fatStart >= nandOffset + roundedMinsizes[ISN3DS ? 1 : 0])
{
//Check for RedNAND
if(!sdmmc_sdcard_readsectors(nandOffset + 1, 1, temp) && memcmp(temp + 0x100, "NCSD", 4) == 0)
{
if (configureCtrNandParams)
{
emuOffset = nandOffset + 1;
emuHeader = 0;
}
return;
}
//Check for Gateway EmuNAND
else if(i != 2 && !sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) && memcmp(temp + 0x100, "NCSD", 4) == 0)
{
if (configureCtrNandParams)
{
emuOffset = nandOffset;
emuHeader = nandSize;
}
return;
}
}
if(*emunandIndex == 0) break; // See above comments
}
//Fallback to the first EmuNAND if there's no second/third/fourth one, or to SysNAND if there isn't any
if(*emunandIndex != 0)
{
*emunandIndex = 0;
locateEmuNand(nandType, emunandIndex, configureCtrNandParams);
}
else *nandType = FIRMWARE_SYSNAND;
}
static inline u32 getProtoSdmmc(u32 *sdmmc, u32 firmVersion)
{
switch(firmVersion)
{
case 243: // SDK 0.9.x (0.9.7?)
*sdmmc = (0x080AAA28 + 0x4e0);
break;
case 238: // SDK 0.10
*sdmmc = (0x080BEA70 + 0x690);
break;
default:
return 1;
}
return 0;
}
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
static const u8 pattern[] = {0x21, 0x20, 0x18, 0x20};
const u8 *off = memsearch(pos, pattern, size, sizeof(pattern));
if(off == NULL) return 1;
*sdmmc = *(u32 *)(off + 9) + *(u32 *)(off + 0xD);
return 0;
}
static inline u32 patchNandRw(u8 *pos, u32 size, u32 hookAddr)
{
//Look for read/write code
static const u8 pattern[] = {0x1E, 0x00, 0xC8, 0x05};
u16 *readOffset = (u16 *)memsearch(pos, pattern, size, sizeof(pattern));
if(readOffset == NULL) return 1;
readOffset -= 3;
u16 *writeOffset = (u16 *)memsearch((u8 *)(readOffset + 5), pattern, 0x100, sizeof(pattern));
if(writeOffset == NULL) return 1;
writeOffset -= 3;
*readOffset = *writeOffset = 0x4C00;
readOffset[1] = writeOffset[1] = 0x47A0;
((u32 *)writeOffset)[1] = ((u32 *)readOffset)[1] = hookAddr;
return 0;
}
static inline u32 patchProtoNandRw(u8 *pos, u32 size, u32 hookAddr, u32 hookCidAddr)
{
//Look for read/write code
static const u8 pattern[] = {
0x03, 0x00, 0x51, 0xE3, // cmp r1, #3
0x02, 0xC0, 0xA0, 0xE1, // mov r12, r2
0x04, 0x00, 0x80, 0xE2, // add r0, r0, #4
};
u32 *writeOffset = (u32 *)memsearch(pos, pattern, size, sizeof(pattern));
if(writeOffset == NULL) return 1;
u32 *readOffset = (u32 *)memsearch((u8 *)(writeOffset + 3), pattern, 0x400, sizeof(pattern));
if(readOffset == NULL) return 1;
// Find the sdmmc mount/init(?) function
static const u8 mount_pattern[] = {
0x20, 0x00, 0x84, 0xE2, // add r0, r4, 0x20
0x01, 0x20, 0xA0, 0xE3, // mov r2, #1
0x00, 0x10, 0xA0, 0xE3, // mov r1, #0
};
u32* mountOffset = (u32*) memsearch(pos, mount_pattern, size, sizeof(mount_pattern));
if (mountOffset == NULL) return 1;
// Find the sdmmc read cid function.
static const u8 readcid_pattern[] = {
0x31, 0xFF, 0x2F, 0xE1, // blx r1
0x20, 0x60, 0x9F, 0xE5, // ldr r6, [pc, #0x20] // =failing_result
0x00, 0x00, 0x50, 0xE3, // cmp r0, #0
};
u32* readCidOffset = (u32*) memsearch(pos, readcid_pattern, size, sizeof(readcid_pattern));
if (readCidOffset == NULL) return 1;
readCidOffset -= 5;
mountOffset[1] = 0xe3a02000; // mov r2, #0 // sd-card
readOffset[0] = writeOffset[0] = 0xe52de004; // push {lr}
readOffset[1] = writeOffset[1] = 0xe59fc000; // ldr r12, [pc, #0]
readOffset[2] = writeOffset[2] = 0xe12fff3c; // blx r12
readOffset[3] = writeOffset[3] = hookAddr;
readCidOffset[0] = 0xe59fc000; // ldr r12, [pc, #0]
readCidOffset[1] = 0xe12fff3c; // blx r12
readCidOffset[2] = hookCidAddr;
// Read the emmc cid into the place hook will copy it from
sdmmc_get_cid(1, emunandPatchNandCid);
return 0;
}
static inline u32 patchProtoNandRw238(u8 *pos, u32 size, u32 hookAddr, u32 hookCidAddr)
{
//Look for read/write code
static const u8 pattern[] = {
0x03, 0x00, 0x50, 0xE3, // cmp r0, #3
0x00, 0x00, 0xA0, 0x13, // movne r0, #0
0x01, 0x00, 0xA0, 0x03, // moveq r0, #1
};
u32 *writeOffset = (u32 *)memsearch(pos, pattern, size, sizeof(pattern));
if(writeOffset == NULL) return 1;
u32 *readOffset = (u32 *)memsearch((u8 *)(writeOffset + 3), pattern, 0x400, sizeof(pattern));
if(readOffset == NULL) return 1;
// Find the mmc static ctor...
static const u8 mount_pattern[] = {
0x08, // last byte of some ptr to something in P9
0x01, 0x01, 0x00, 0x00, // emmc controller id
};
u8* mountOffset = (u8*) memsearch(pos, mount_pattern, size, sizeof(mount_pattern));
if (mountOffset == NULL) return 1;
mountOffset++;
// Find the sdmmc read cid function.
static const u8 readcid_pattern[] = {
0x31, 0xFF, 0x2F, 0xE1, // blx r1
0x20, 0x60, 0x9F, 0xE5, // ldr r6, [pc, #0x20] // =failing_result
0x00, 0x00, 0x50, 0xE3, // cmp r0, #0
};
u32* readCidOffset = (u32*) memsearch(pos, readcid_pattern, size, sizeof(readcid_pattern));
if (readCidOffset == NULL) return 1;
readCidOffset -= 5;
*(u32*)mountOffset = 0x300; // sd card
readOffset[0] = writeOffset[0] = 0xe59fc000; // ldr r12, [pc, #0]
readOffset[1] = writeOffset[1] = 0xe12fff3c; // blx r12
readOffset[2] = writeOffset[2] = hookAddr;
readCidOffset[0] = 0xe59fc000; // ldr r12, [pc, #0]
readCidOffset[1] = 0xe12fff3c; // blx r12
readCidOffset[2] = hookCidAddr;
// Read the emmc cid into the place hook will copy it from
sdmmc_get_cid(1, emunandPatchNandCid);
return 0;
}
u32 patchEmuNand(u8 *process9Offset, u32 process9Size, u32 firmVersion)
{
u32 ret = 0;
//Add the data of the found EmuNAND
emunandPatchNandOffset = emuOffset;
emunandPatchNcsdHeaderOffset = emuHeader;
//Find and add the SDMMC struct
u32 sdmmc;
ret += !ISN3DS && firmVersion < 0x25 ? getOldSdmmc(&sdmmc, firmVersion) : getSdmmc(process9Offset, process9Size, &sdmmc);
if(!ret) emunandPatchSdmmcStructPtr = sdmmc;
//Add EmuNAND hooks
ret += patchNandRw(process9Offset, process9Size, (u32)emunandPatch);
return ret;
}
u32 patchProtoEmuNand(u8 *process9Offset, u32 process9Size)
{
extern u32 firmProtoVersion;
u32 ret = 0;
// Add the data of the found EmuNAND
emunandPatchNandOffset = emuOffset;
emunandPatchNcsdHeaderOffset = emuHeader;
// Find and add the SDMMC struct
u32 sdmmc;
ret += getProtoSdmmc(&sdmmc, firmProtoVersion);
if(!ret) emunandPatchSdmmcStructPtr = sdmmc;
// Add EmuNAND hooks
switch (firmProtoVersion) {
case 243: // SDK 0.9.x (0.9.7?)
ret += patchProtoNandRw(process9Offset, process9Size, (u32)emunandProtoPatch, (u32)emunandProtoCidPatch);
break;
case 238: // SDK 0.10.x
ret += patchProtoNandRw238(process9Offset, process9Size, (u32)emunandProtoPatch238, (u32)emunandProtoCidPatch);
break;
default:
ret++;
break;
}
return ret;
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -37,5 +37,6 @@
extern u32 emuOffset,
emuHeader;
void locateEmuNand(FirmwareSource *nandType);
u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address, u32 firmVersion);
void locateEmuNand(FirmwareSource *nandType, u32 *emunandIndex, bool configureCtrNandParams);
u32 patchEmuNand(u8 *process9Offset, u32 process9Size, u32 firmVersion);
u32 patchProtoEmuNand(u8 *process9Offset, u32 process9Size);

194
arm9/source/emunand_patch.s Normal file
View File

@ -0,0 +1,194 @@
.section .emunand_patch, "aw", %progbits
.arm
.align 4
@ Code originally by Normmatt
.global emunandPatch
emunandPatch:
@ Original code that still needs to be executed
mov r4, r0
mov r5, r1
mov r7, r2
mov r6, r3
@ End
@ If we're already trying to access the SD, return
ldr r2, [r0, #4]
ldr r1, emunandPatchSdmmcStructPtr
cmp r2, r1
beq out
str r1, [r0, #4] @ Set object to be SD
ldr r2, [r0, #8] @ Get sector to read
cmp r2, #0 @ For GW compatibility, see if we're trying to read the ncsd header (sector 0)
ldr r3, emunandPatchNandOffset
add r2, r3 @ Add the offset to the NAND in the SD
ldreq r3, emunandPatchNcsdHeaderOffset
addeq r2, r3 @ If we're reading the ncsd header, add the offset of that sector
str r2, [r0, #8] @ Store sector to read
out:
@ Restore registers.
mov r1, r5
mov r2, r7
mov r3, r6
@ Return 4 bytes behind where we got called,
@ due to the offset of this function being stored there
mov r0, lr
add r0, #4
bx r0
.pool
_emunandPatchEnd:
.global emunandProtoPatch
emunandProtoPatch:
@ Save registers
push {r0-r3}
@ If we're already trying to access the SD, return
ldr r2, [r0, #4]
ldr r1, emunandPatchSdmmcStructPtr
cmp r2, r1
beq _out
ldrb r2, [r1, #0xc] @ Get sdmc->m_isInitialised
cmp r2, #0 @ Is initialised?
beq _pastSdmc @ if not, use "NAND" object, patched elsewhere to access SD
str r1, [r0, #4] @ Set object to be SD
_pastSdmc:
ldr r2, [r0, #8] @ Get sector to read
cmp r2, #0 @ For GW compatibility, see if we're trying to read the ncsd header (sector 0)
ldr r3, emunandPatchNandOffset
add r2, r3 @ Add the offset to the NAND in the SD
ldreq r3, emunandPatchNcsdHeaderOffset
addeq r2, r3 @ If we're reading the ncsd header, add the offset of that sector
str r2, [r0, #8] @ Store sector to read
_out:
@ Restore registers
pop {r0-r3}
@ Execute original code that got patched.
cmp r1, #3
mov r12, r2
add r0, r0, #4
movne r1, #0
moveq r1, #1
@ r2 about to be overwritten, so it's free to use here.
@ Save off our return address and restore lr.
mov r2, lr
pop {lr}
@ r2+0 is return address (patched movne r1, #0)
@ r2+4 is moveq r1, #1
@ r2+8 is the following instruction (mov r2, r3)
add r2, #8
bx r2
.global emunandProtoCidPatch
emunandProtoCidPatch:
@ If we're already trying to access the SD, return
ldr r4, emunandPatchSdmmcStructPtr
cmp r0, r4
beq _cid_return
@ Trying to access nand, so copy the NAND cid into r1
adr r4, emunandPatchNandCid
ldr r2, [r4, #0]
ldr r3, [r4, #4]
ldr r5, [r4, #8]
ldr r6, [r4, #0xc]
str r2, [r1, #0]
str r3, [r1, #4]
str r5, [r1, #8]
str r6, [r1, #0xc]
@ And return from whence we came
mov r0, #0
pop {r4-r6, pc}
_cid_return:
@ Execute original code that got patched.
mov r4, r0
ldr r0, [r0]
mov r5, r1
@ lr+0 is return address (patched mov r5, r1)
@ lr+4 is following instruction (ldr r1, [r0,#8])
add lr, #4
bx lr
.global emunandProtoPatch238
emunandProtoPatch238:
@ Save registers
push {r0-r3}
@ If we're already trying to access the SD, return
ldr r2, [r4, #4]
ldr r1, emunandPatchSdmmcStructPtr
cmp r2, r1
beq _out238
ldr r2, [r1, #0x24] @ Get sdmc->m_someObjInitedLater
cmp r2, #0 @ Is initialised?
beq _pastSdmc238 @ if not, use "NAND" object, patched elsewhere to access SD
str r1, [r4, #4] @ Set object to be SD
_pastSdmc238:
ldr r2, [r4, #8] @ Get sector to read
cmp r2, #0 @ For GW compatibility, see if we're trying to read the ncsd header (sector 0)
ldr r3, emunandPatchNandOffset
add r2, r3 @ Add the offset to the NAND in the SD
ldreq r3, emunandPatchNcsdHeaderOffset
addeq r2, r3 @ If we're reading the ncsd header, add the offset of that sector
str r2, [r4, #8] @ Store sector to read
_out238:
@ Restore registers
pop {r0-r3}
@ Execute original code that got patched.
cmp r0, #3
movne r0, #0
moveq r0, #1
@ r1 about to be overwritten, so it's free to use here.
@ Save off our return address.
mov r1, lr
@ r1+0 is return address (patched moveq r1, #1)
@ r1+4 is tst r0, #0xff or sub sp, sp, #0xc
add r1, #4
bx r1
.pool
.global emunandPatchSdmmcStructPtr
.global emunandPatchNandOffset
.global emunandPatchNcsdHeaderOffset
.global emunandPatchNandCid
_emunandPatchBssStart:
emunandPatchSdmmcStructPtr: .word 0 @ Pointer to sdmmc struct
emunandPatchNandOffset: .word 0 @ For rednand this should be 1
emunandPatchNcsdHeaderOffset: .word 0 @ Depends on nand manufacturer + emunand type (GW/RED)
emunandPatchNandCid: @ Store emmc cid here, to override "sdmc's" when trying to read emmc's
.word 0,0,0,0
_emunandPatchBssEnd:
.pool
.balign 4
.global emunandPatchSize
emunandPatchSize:
.word _emunandPatchEnd - emunandPatch
.global emunandPatchBssSize
emunandPatchBssSize:
.word _emunandPatchBssEnd - _emunandPatchBssStart

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -26,31 +26,28 @@
#include "exceptions.h"
#include "fs.h"
#include "strings.h"
#include "memory.h"
#include "screen.h"
#include "draw.h"
#include "utils.h"
#include "fmt.h"
#include "buttons.h"
#include "../build/bundled.h"
#include "arm9_exception_handlers.h"
// See https://github.com/LumaTeam/luma3ds_exception_dump_parser
void installArm9Handlers(void)
{
memcpy((void *)0x01FF8000, arm9_exceptions_bin, arm9_exceptions_bin_size);
vu32 *dstVeneers = (vu32 *)0x08000000;
/* IRQHandler is at 0x08000000, but we won't handle it for some reasons
svcHandler is at 0x08000010, but we won't handle svc either */
static const u32 offsets[] = {0x08, 0x18, 0x20, 0x28};
for(u32 i = 0; i < 4; i++)
for(u32 i = 0; i < 6; i++)
{
*(vu32 *)(0x08000000 + offsets[i]) = 0xE51FF004;
*(vu32 *)(0x08000000 + offsets[i] + 4) = *(vu32 *)(0x01FF8008 + 4 * i);
if(arm9ExceptionHandlerAddressTable[i] != 0)
{
dstVeneers[2 * i] = 0xE51FF004;
dstVeneers[2 * i + 1] = arm9ExceptionHandlerAddressTable[i];
}
}
*(vu32 *)0x01FF8004 = 0; //BreakPtr
}
void detectAndProcessExceptionDumps(void)
@ -90,8 +87,8 @@ void detectAndProcessExceptionDumps(void)
drawString(true, 10, 10, COLOR_RED, "An exception occurred");
u32 posY;
if(dumpHeader->processor == 11) posY = drawFormattedString(true, 10, 30, COLOR_WHITE, "Processor: ARM11 (core %u)", dumpHeader->core);
else posY = drawString(true, 10, 30, COLOR_WHITE, "Processor: ARM9");
if(dumpHeader->processor == 11) posY = drawFormattedString(true, 10, 30, COLOR_WHITE, "Processor: Arm11 (core %u)", dumpHeader->core);
else posY = drawString(true, 10, 30, COLOR_WHITE, "Processor: Arm9");
if(dumpHeader->type == 2)
{
@ -132,22 +129,29 @@ void detectAndProcessExceptionDumps(void)
}
if(dumpHeader->additionalDataSize != 0)
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE,
"Current process: %.8s (%016llX)", (const char *)additionalData, *(vu64 *)(additionalData + 8));
{
u32 size = dumpHeader->additionalDataSize;
if(dumpHeader->processor == 11)
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE,
"Current process: %.8s (%016llX)", (const char *)additionalData, *(vu64 *)(additionalData + 8));
else
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE,
"Arm9 memory dump at offset %X size %lX", (uintptr_t)additionalData - (uintptr_t)dumpHeader, size);
}
posY += SPACING_Y;
for(u32 i = 0; i < 17; i += 2)
{
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08X", registerNames[i], regs[i]);
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08lX", registerNames[i], regs[i]);
if(i != 16)
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08X", registerNames[i + 1], regs[i + 1]);
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08lX", registerNames[i + 1], regs[i + 1]);
else if(dumpHeader->processor == 11)
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08X", registerNames[i + 1], regs[20]);
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08lX", registerNames[i + 1], regs[20]);
}
if(dumpHeader->processor == 11 && dumpHeader->type == 3)
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08X Access type: %s", "FAR", regs[19], regs[17] & (1u << 11) ? "Write" : "Read");
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08lX Access type: %s", "FAR", regs[19], regs[17] & (1u << 11) ? "Write" : "Read");
posY += SPACING_Y;
@ -159,7 +163,7 @@ void detectAndProcessExceptionDumps(void)
for(u32 line = 0; line < 19 && stackDump < additionalData; line++)
{
posYBottom = drawFormattedString(false, 10, posYBottom + SPACING_Y, COLOR_WHITE, "%08X:", regs[13] + 8 * line);
posYBottom = drawFormattedString(false, 10, posYBottom + SPACING_Y, COLOR_WHITE, "%08lX:", regs[13] + 8 * line);
for(u32 i = 0; i < 8 && stackDump < additionalData; i++, stackDump++)
drawFormattedString(false, 10 + 10 * SPACING_X + 3 * i * SPACING_X, posYBottom, COLOR_WHITE, "%02X", *stackDump);
@ -175,9 +179,9 @@ void detectAndProcessExceptionDumps(void)
drawString(true, 10, posY + SPACING_Y, COLOR_BLACK, choiceMessage[0]);
drawString(true, 10, posY + SPACING_Y + SPACING_Y , COLOR_BLACK, choiceMessage[1]);
char folderPath[12],
path[36],
fileName[24];
char folderPath[32],
path[128],
fileName[32];
sprintf(folderPath, "dumps/arm%u", dumpHeader->processor);
findDumpFile(folderPath, fileName);
@ -195,6 +199,6 @@ void detectAndProcessExceptionDumps(void)
waitInput(false);
exit:
memset32((void *)dumpHeader, 0, dumpHeader->totalSize);
memset((void *)dumpHeader, 0, dumpHeader->totalSize);
mcuPowerOff();
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -300,3 +300,70 @@ R0.13 (May 21, 2017)
Fixed exFAT FAT entry can be collapsed when write or lseek operation to the existing file is done. (appeared at R0.12c)
Fixed creating a file can fail when a new cluster allocation to the exFAT directory occures. (appeared at R0.12c)
R0.13a (October 14, 2017)
Added support for UTF-8 encoding on the API. (FF_LFN_UNICODE = 2)
Added options for file name output buffer. (FF_LFN_BUF, FF_SFN_BUF).
Added dynamic memory allocation option for working buffer of f_mkfs() and f_fdisk().
Fixed f_fdisk() and f_mkfs() create the partition table with wrong CHS parameters. (appeared at R0.09)
Fixed f_unlink() can cause lost clusters at fragmented file on the exFAT volume. (appeared at R0.12c)
Fixed f_setlabel() rejects some valid characters for exFAT volume. (appeared at R0.12)
R0.13b (April 07, 2018)
Added support for UTF-32 encoding on the API. (FF_LFN_UNICODE = 3)
Added support for Unix style volume ID. (FF_STR_VOLUME_ID = 2)
Fixed accesing any object on the exFAT root directory beyond the cluster boundary can fail. (appeared at R0.12c)
Fixed f_setlabel() does not reject some invalid characters. (appeared at R0.09b)
R0.13c (October 14, 2018)
Supported stdint.h for C99 and later. (integer.h was included in ff.h)
Fixed reading a directory gets infinite loop when the last directory entry is not empty. (appeared at R0.12)
Fixed creating a sub-directory in the fragmented sub-directory on the exFAT volume collapses FAT chain of the parent directory. (appeared at R0.12)
Fixed f_getcwd() cause output buffer overrun when the buffer has a valid drive number. (appeared at R0.13b)
R0.14 (October 14, 2019)
Added support for 64-bit LBA and GUID partition table (FF_LBA64 = 1)
Changed some API functions, f_mkfs() and f_fdisk().
Fixed f_open() function cannot find the file with file name in length of FF_MAX_LFN characters.
Fixed f_readdir() function cannot retrieve long file names in length of FF_MAX_LFN - 1 characters.
Fixed f_readdir() function returns file names with wrong case conversion. (appeared at R0.12)
Fixed f_mkfs() function can fail to create exFAT volume in the second partition. (appeared at R0.12)
R0.14a (December 5, 2020)
Limited number of recursive calls in f_findnext().
Fixed old floppy disks formatted with MS-DOS 2.x and 3.x cannot be mounted.
Fixed some compiler warnings.
R0.14b (April 17, 2021)
Made FatFs uses standard library <string.h> for copy, compare and search instead of built-in string functions.
Added support for long long integer and floating point to f_printf(). (FF_STRF_LLI and FF_STRF_FP)
Made path name parser ignore the terminating separator to allow "dir/".
Improved the compatibility in Unix style path name feature.
Fixed the file gets dead-locked when f_open() failed with some conditions. (appeared at R0.12a)
Fixed f_mkfs() can create wrong exFAT volume due to a timing dependent error. (appeared at R0.12)
Fixed code page 855 cannot be set by f_setcp().
Fixed some compiler warnings.
R0.15 (November 6, 2022)
Changed user provided synchronization functions in order to completely eliminate the platform dependency from FatFs code.
FF_SYNC_t is removed from the configuration options.
Fixed a potential error in f_mount when FF_FS_REENTRANT.
Fixed file lock control FF_FS_LOCK is not mutal excluded when FF_FS_REENTRANT && FF_VOLUMES > 1 is true.
Fixed f_mkfs() creates broken exFAT volume when the size of volume is >= 2^32 sectors.
Fixed string functions cannot write the unicode characters not in BMP when FF_LFN_UNICODE == 2 (UTF-8).
Fixed a compatibility issue in identification of GPT header.

View File

@ -1,4 +1,4 @@
FatFs Module Source Files R0.13
FatFs Module Source Files R0.15
FILES
@ -10,7 +10,6 @@ FILES
ff.h Common include file for FatFs and application module.
diskio.h Common include file for FatFs and disk I/O module.
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
integer.h Integer type definitions for FatFs.
ffunicode.c Optional Unicode utility functions.
ffsystem.c An example of optional O/S related functions.

186
arm9/source/fatfs/diskio.c Normal file
View File

@ -0,0 +1,186 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module SKELETON for FatFs (C)ChaN, 2019 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various exsisting */
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#include "ff.h" /* Obtains integer types */
#include "diskio.h" /* Declarations of disk functions */
#include "sdmmc/sdmmc.h"
#include "../crypto.h"
#include "../i2c.h"
/* Definitions of physical drive number for each drive */
#define SDCARD 0
#define CTRNAND 1
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
(void)pdrv;
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
static u32 sdmmcInitResult = 4;
DSTATUS res = 0;
if(sdmmcInitResult == 4)
sdmmcInitResult = sdmmc_sdcard_init();
// Check physical drive initialized status
switch (pdrv)
{
case SDCARD:
res = (sdmmcInitResult & 2) == 0 ? 0 : STA_NOINIT;
break;
case CTRNAND:
// Always update CTRNAND parameters when remounting
res = (sdmmcInitResult & 1) == 0 && ctrNandInit() == 0 ? 0 : STA_NOINIT;
break;
default:
res = STA_NODISK;
break;
}
return res;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res = RES_OK;
switch (pdrv)
{
case SDCARD:
res = sdmmc_sdcard_readsectors(sector, count, buff) == 0 ? RES_OK : RES_PARERR;
break;
case CTRNAND:
res = ctrNandRead(sector, count, buff) == 0 ? RES_OK : RES_PARERR;
break;
default:
res = RES_NOTRDY;
break;
}
return res;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if FF_FS_READONLY == 0
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res = RES_OK;
switch (pdrv)
{
case SDCARD:
{
if ((*(vu16 *)(SDMMC_BASE + REG_SDSTATUS0) & TMIO_STAT0_WRPROTECT) == 0) // why == 0?
res = RES_WRPRT;
else
res = sdmmc_sdcard_writesectors(sector, count, buff) == 0 ? RES_OK : RES_PARERR;
break;
}
case CTRNAND:
res = ctrNandWrite(sector, count, buff) == 0 ? RES_OK : RES_PARERR;
break;
default:
res = RES_NOTRDY;
break;
}
return res;
}
#endif
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
(void)pdrv;
(void)buff;
return cmd == CTRL_SYNC ? RES_OK : RES_PARERR;
}
// From GodMode9
#define BCDVALID(b) (((b)<=0x99)&&(((b)&0xF)<=0x9)&&((((b)>>4)&0xF)<=0x9))
#define BCD2NUM(b) (BCDVALID(b) ? (((b)&0xF)+((((b)>>4)&0xF)*10)) : 0xFF)
#define NUM2BCD(n) ((n<99) ? (((n/10)*0x10)|(n%10)) : 0x99)
#define DSTIMEGET(bcd,n) (BCD2NUM((bcd)->n))
// see: http://3dbrew.org/wiki/I2C_Registers#Device_3 (register 30)
typedef struct DsTime {
u8 bcd_s;
u8 bcd_m;
u8 bcd_h;
u8 weekday;
u8 bcd_D;
u8 bcd_M;
u8 bcd_Y;
u8 leap_count;
} DsTime;
/*-----------------------------------------------------------------------*/
/* Get current FAT time */
/*-----------------------------------------------------------------------*/
DWORD get_fattime( void ) {
DsTime dstime;
I2C_readRegBuf(I2C_DEV_MCU, 0x30, (u8 *)&dstime, sizeof(DsTime));
DWORD fattime =
((DSTIMEGET(&dstime, bcd_s)&0x3F) >> 1 ) |
((DSTIMEGET(&dstime, bcd_m)&0x3F) << 5 ) |
((DSTIMEGET(&dstime, bcd_h)&0x3F) << 11) |
((DSTIMEGET(&dstime, bcd_D)&0x1F) << 16) |
((DSTIMEGET(&dstime, bcd_M)&0x0F) << 21) |
(((DSTIMEGET(&dstime, bcd_Y)+(2000-1980))&0x7F) << 25);
return fattime;
}

View File

@ -1,5 +1,5 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2014 /
/ Low level disk interface modlue include file (C)ChaN, 2019 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
@ -9,12 +9,6 @@
extern "C" {
#endif
#define _USE_WRITE 1 /* 1: Enable disk_write function */
#define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */
#include "integer.h"
/* Status of Disk Functions */
typedef BYTE DSTATUS;
@ -34,8 +28,8 @@ typedef enum {
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
@ -49,11 +43,11 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
@ -67,6 +61,9 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem module R0.13 /
/ FatFs - Generic FAT Filesystem module R0.15 /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2017, ChaN, all right reserved.
/ Copyright (C) 2022, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
@ -20,13 +20,12 @@
#ifndef FF_DEFINED
#define FF_DEFINED 87030 /* Revision ID */
#define FF_DEFINED 80286 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if FF_DEFINED != FFCONF_DEF
@ -34,6 +33,81 @@ extern "C" {
#endif
/* Integer types used for FatFs API */
#if defined(_WIN32) /* Windows VC++ (for development only) */
#define FF_INTDEF 2
#include <windows.h>
typedef unsigned __int64 QWORD;
#include <float.h>
#define isnan(v) _isnan(v)
#define isinf(v) (!_finite(v))
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */
#define FF_INTDEF 2
#include <stdint.h>
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
typedef unsigned char BYTE; /* char must be 8-bit */
typedef uint16_t WORD; /* 16-bit unsigned integer */
typedef uint32_t DWORD; /* 32-bit unsigned integer */
typedef uint64_t QWORD; /* 64-bit unsigned integer */
typedef WORD WCHAR; /* UTF-16 character type */
#else /* Earlier than C99 */
#define FF_INTDEF 1
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
typedef unsigned char BYTE; /* char must be 8-bit */
typedef unsigned short WORD; /* 16-bit unsigned integer */
typedef unsigned long DWORD; /* 32-bit unsigned integer */
typedef WORD WCHAR; /* UTF-16 character type */
#endif
/* Type of file size and LBA variables */
#if FF_FS_EXFAT
#if FF_INTDEF != 2
#error exFAT feature wants C99 or later
#endif
typedef QWORD FSIZE_t;
#if FF_LBA64
typedef QWORD LBA_t;
#else
typedef DWORD LBA_t;
#endif
#else
#if FF_LBA64
#error exFAT needs to be enabled when enable 64-bit LBA
#endif
typedef DWORD FSIZE_t;
typedef DWORD LBA_t;
#endif
/* Type of path name strings on FatFs API (TCHAR) */
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8 ## x
#define _TEXT(x) u8 ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
typedef DWORD TCHAR;
#define _T(x) U ## x
#define _TEXT(x) U ## x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
/* Definitions of volume management */
@ -42,40 +116,13 @@ typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
#endif
/* Type of path name strings on FatFs API */
#if FF_LFN_UNICODE && FF_USE_LFN /* Unicode (UTF-16) string */
#ifndef _INC_TCHAR
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#define _INC_TCHAR
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
#endif
#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#define _INC_TCHAR
#endif
#endif
/* Type of file size variables */
#if FF_FS_EXFAT
#if !FF_USE_LFN
#error LFN must be enabled when enable exFAT
#endif
typedef QWORD FSIZE_t;
#else
typedef DWORD FSIZE_t;
#endif
@ -83,11 +130,12 @@ typedef DWORD FSIZE_t;
/* Filesystem object structure (FATFS) */
typedef struct {
BYTE fs_type; /* Filesystem type (0:N/A) */
BYTE pdrv; /* Physical drive number */
BYTE fs_type; /* Filesystem type (0:not mounted) */
BYTE pdrv; /* Volume hosting physical drive */
BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
BYTE wflag; /* win[] status (b0:dirty) */
BYTE fsi_flag; /* FSINFO status (b7:disabled, b0:dirty) */
WORD id; /* Volume mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
@ -100,9 +148,6 @@ typedef struct {
#if FF_FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */
#endif
#if FF_FS_REENTRANT
FF_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !FF_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
@ -116,12 +161,15 @@ typedef struct {
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
DWORD volbase; /* Volume base sector */
DWORD fatbase; /* FAT base sector */
DWORD dirbase; /* Root directory base sector/cluster */
DWORD database; /* Data base sector */
DWORD winsect; /* Current sector appearing in the win[] */
DWORD fsize; /* Number of sectors per FAT */
LBA_t volbase; /* Volume base sector */
LBA_t fatbase; /* FAT base sector */
LBA_t dirbase; /* Root directory base sector (FAT12/16) or cluster (FAT32/exFAT) */
LBA_t database; /* Data base sector */
#if FF_FS_EXFAT
LBA_t bitbase; /* Allocation bitmap base sector */
#endif
LBA_t winsect; /* Current sector appearing in the win[] */
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
@ -131,9 +179,9 @@ typedef struct {
typedef struct {
FATFS* fs; /* Pointer to the hosting volume of this object */
WORD id; /* Hosting volume mount ID */
WORD id; /* Hosting volume's mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if FF_FS_EXFAT
@ -158,9 +206,9 @@ typedef struct {
BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
LBA_t sect; /* Sector number appearing in buf[] (0:invalid) */
#if !FF_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
LBA_t dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */
#endif
#if FF_USE_FASTSEEK
@ -179,7 +227,7 @@ typedef struct {
FFOBJID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector (0:Read operation has terminated) */
LBA_t sect; /* Current sector (0:Read operation has terminated) */
BYTE* dir; /* Pointer to the directory item in the win[] */
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
#if FF_USE_LFN
@ -200,15 +248,27 @@ typedef struct {
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if FF_USE_LFN
TCHAR altname[13]; /* Altenative file name */
TCHAR fname[FF_MAX_LFN + 1]; /* Primary file name */
TCHAR altname[FF_SFN_BUF + 1];/* Alternative file name */
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
#else
TCHAR fname[13]; /* File name */
TCHAR fname[12 + 1]; /* File name */
#endif
} FILINFO;
/* Format parameter structure (MKFS_PARM) */
typedef struct {
BYTE fmt; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */
BYTE n_fat; /* Number of FATs */
UINT align; /* Data area alignment (sector) */
UINT n_root; /* Number of root directory entries */
DWORD au_size; /* Cluster size (byte) */
} MKFS_PARM;
/* File function return code (FRESULT) */
typedef enum {
@ -236,8 +296,10 @@ typedef enum {
/*--------------------------------------------------------------*/
/* FatFs Module Application Interface */
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
@ -264,16 +326,18 @@ FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get numbe
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
FRESULT f_mkfs (const TCHAR* path, const MKFS_PARM* opt, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const LBA_t ptbl[], void* work); /* Divide a physical drive into some partitions */
FRESULT f_setcp (WORD cp); /* Set current code page */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
/* Some API fucntions are implemented as macro */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
@ -283,46 +347,47 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil
#define f_rmdir(path) f_unlink(path)
#define f_unmount(path) f_mount(0, path, 0)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* Additional Functions */
/*--------------------------------------------------------------*/
/* RTC function */
/* RTC function (provided by user) */
#if !FF_FS_READONLY && !FF_FS_NORTC
DWORD get_fattime (void);
DWORD get_fattime (void); /* Get current time */
#endif
/* LFN support functions */
#if FF_USE_LFN /* Code conversion (defined in unicode.c) */
/* LFN support functions (defined in ffunicode.c) */
#if FF_USE_LFN >= 1
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
WCHAR ff_uni2oem (WCHAR uni, WORD cp); /* Unicode to OEM code conversion */
WCHAR ff_wtoupper (WCHAR uni); /* Unicode upper-case conversion */
#endif
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */
DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
#endif
/* Sync functions */
#if FF_FS_REENTRANT
int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
/* O/S dependent functions (samples available in ffsystem.c) */
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
#if FF_FS_REENTRANT /* Sync functions */
int ff_mutex_create (int vol); /* Create a sync object */
void ff_mutex_delete (int vol); /* Delete a sync object */
int ff_mutex_take (int vol); /* Lock sync object */
void ff_mutex_give (int vol); /* Unlock sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* Flags and Offset Address */
/*--------------------------------------------------------------*/
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01

View File

@ -1,8 +1,8 @@
/*---------------------------------------------------------------------------/
/ FatFs - Configuration file
/ Configurations of FatFs Module
/---------------------------------------------------------------------------*/
#define FFCONF_DEF 87030 /* Revision ID */
#define FFCONF_DEF 80286 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
@ -18,21 +18,13 @@
#define FF_FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.
/ 0: Basic functions are fully enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define FF_USE_STRFUNC 0
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define FF_USE_FIND 1
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
@ -64,6 +56,30 @@
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
#define FF_USE_STRFUNC 0
#define FF_PRINT_LLI 1
#define FF_PRINT_FLOAT 1
#define FF_STRF_ENCODE 3
/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and
/ f_printf().
/
/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion.
/
/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
/ makes f_printf() support floating point argument. These features want C99 or later.
/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character
/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
/ to be read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
@ -102,37 +118,39 @@
/* The FF_USE_LFN switches the support for LFN (long file name).
/
/ 0: Disable LFN. FF_MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
/ to the project. The working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
/ additional 608 bytes at exFAT enabled. FF_MAX_LFN can be in range from 12 to 255.
/ It should be set 255 to support full featured LFN operations.
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
/ be in range of 12 to 255. It is recommended to be set it 255 to fully support LFN
/ specification.
/ When use stack for the working buffer, take care on stack overflow. When use heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree(), must be added to the project. */
/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */
#define FF_LFN_UNICODE 0
/* This option switches character encoding on the API, 0:ANSI/OEM or 1:UTF-16,
/ when LFN is enabled. Also behavior of string I/O functions will be affected by
/ this option. When LFN is not enabled, this option has no effect.
*/
#define FF_STRF_ENCODE 3
/* When FF_LFN_UNICODE = 1 with LFN enabled, string I/O functions, f_gets(),
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
/ This option selects assumption of character encoding ON THE FILE to be
/ read/written via those functions.
#define FF_LFN_UNICODE 2
/* This option switches the character encoding on the API when LFN is enabled.
/
/ 0: ANSI/OEM
/ 1: UTF-16LE
/ 2: UTF-16BE
/ 3: UTF-8
*/
/ 0: ANSI/OEM in current CP (TCHAR = char)
/ 1: Unicode in UTF-16 (TCHAR = WCHAR)
/ 2: Unicode in UTF-8 (TCHAR = char)
/ 3: Unicode in UTF-32 (TCHAR = DWORD)
/
/ Also behavior of string I/O functions will be affected by this option.
/ When LFN is not enabled, this option has no effect. */
#define FF_LFN_BUF 255
#define FF_SFN_BUF 12
/* This set of options defines size of file name members in the FILINFO structure
/ which is used to read out directory items. These values should be suffcient for
/ the file names to read. The maximum possible length of the read file name depends
/ on character encoding. When LFN is not enabled, these options have no effect. */
#define FF_FS_RPATH 1
@ -152,13 +170,18 @@
/* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 0
#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
/* FF_STR_VOLUME_ID switches string support for volume ID.
/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each
/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for
/ the drive ID strings are: A-Z and 0-9. */
#define FF_STR_VOLUME_ID 1
#define FF_VOLUME_STRS "sdmc", "nand"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
/ not defined, a user defined volume string table is needed as:
/
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
*/
#define FF_MULTI_PARTITION 0
@ -167,37 +190,35 @@
/ number and only an FAT volume found on the physical drive will be mounted.
/ When this function is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ funciton will be available. */
/ function will be available. */
#define FF_MIN_SS 512
#define FF_MAX_SS 512
/* This set of options configures the range of sector size to be supported. (512,
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ harddisk, but a larger value may be required for on-board flash memory and some
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
/ for variable sector size mode and disk_ioctl() function needs to implement
/ GET_SECTOR_SIZE command. */
#define FF_LBA64 0
/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
#define FF_MIN_GPT 0x10000000
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
#define FF_USE_TRIM 0
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
#define FF_FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
/*---------------------------------------------------------------------------/
/ System Configurations
@ -212,22 +233,34 @@
#define FF_FS_EXFAT 0
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ When enable exFAT, also LFN needs to be enabled.
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
#define FF_FS_NORTC 1
#define FF_NORTC_MON 5
#define FF_FS_NORTC 0
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2017
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
#define FF_NORTC_YEAR 2022
/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
/ timestamp feature. Every object modified by FatFs will have a fixed timestamp
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */
/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */
#define FF_FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at the first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
#define FF_FS_LOCK 0
@ -244,25 +277,19 @@
#define FF_FS_REENTRANT 0
#define FF_FS_TIMEOUT 1000
#define FF_SYNC_t HANDLE
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/ to the same volume is under control of this featuer.
/
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give()
/ function, must be added to the project. Samples are available in ffsystem.c.
/
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/* #include <windows.h> // O/S definitions */
/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick.
*/

View File

@ -0,0 +1,208 @@
/*------------------------------------------------------------------------*/
/* A Sample Code of User Provided OS Dependent Functions for FatFs */
/*------------------------------------------------------------------------*/
#include "ff.h"
#if FF_USE_LFN == 3 /* Use dynamic memory allocation */
/*------------------------------------------------------------------------*/
/* Allocate/Free a Memory Block */
/*------------------------------------------------------------------------*/
#include <stdlib.h> /* with POSIX API */
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
UINT msize /* Number of bytes to allocate */
)
{
return malloc((size_t)msize); /* Allocate a new memory block */
}
void ff_memfree (
void* mblock /* Pointer to the memory block to free (no effect if null) */
)
{
free(mblock); /* Free the memory block */
}
#endif
#if FF_FS_REENTRANT /* Mutal exclusion */
/*------------------------------------------------------------------------*/
/* Definitions of Mutex */
/*------------------------------------------------------------------------*/
#define OS_TYPE 0 /* 0:Win32, 1:uITRON4.0, 2:uC/OS-II, 3:FreeRTOS, 4:CMSIS-RTOS */
#if OS_TYPE == 0 /* Win32 */
#include <windows.h>
static HANDLE Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */
#elif OS_TYPE == 1 /* uITRON */
#include "itron.h"
#include "kernel.h"
static mtxid Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */
#elif OS_TYPE == 2 /* uc/OS-II */
#include "includes.h"
static OS_EVENT *Mutex[FF_VOLUMES + 1]; /* Table of mutex pinter */
#elif OS_TYPE == 3 /* FreeRTOS */
#include "FreeRTOS.h"
#include "semphr.h"
static SemaphoreHandle_t Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */
#elif OS_TYPE == 4 /* CMSIS-RTOS */
#include "cmsis_os.h"
static osMutexId Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */
#endif
/*------------------------------------------------------------------------*/
/* Create a Mutex */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount function to create a new mutex
/ or semaphore for the volume. When a 0 is returned, the f_mount function
/ fails with FR_INT_ERR.
*/
int ff_mutex_create ( /* Returns 1:Function succeeded or 0:Could not create the mutex */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
Mutex[vol] = CreateMutex(NULL, FALSE, NULL);
return (int)(Mutex[vol] != INVALID_HANDLE_VALUE);
#elif OS_TYPE == 1 /* uITRON */
T_CMTX cmtx = {TA_TPRI,1};
Mutex[vol] = acre_mtx(&cmtx);
return (int)(Mutex[vol] > 0);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
Mutex[vol] = OSMutexCreate(0, &err);
return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 3 /* FreeRTOS */
Mutex[vol] = xSemaphoreCreateMutex();
return (int)(Mutex[vol] != NULL);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexDef(cmsis_os_mutex);
Mutex[vol] = osMutexCreate(osMutex(cmsis_os_mutex));
return (int)(Mutex[vol] != NULL);
#endif
}
/*------------------------------------------------------------------------*/
/* Delete a Mutex */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount function to delete a mutex or
/ semaphore of the volume created with ff_mutex_create function.
*/
void ff_mutex_delete ( /* Returns 1:Function succeeded or 0:Could not delete due to an error */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
CloseHandle(Mutex[vol]);
#elif OS_TYPE == 1 /* uITRON */
del_mtx(Mutex[vol]);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
OSMutexDel(Mutex[vol], OS_DEL_ALWAYS, &err);
#elif OS_TYPE == 3 /* FreeRTOS */
vSemaphoreDelete(Mutex[vol]);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexDelete(Mutex[vol]);
#endif
}
/*------------------------------------------------------------------------*/
/* Request a Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on enter file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_mutex_take ( /* Returns 1:Succeeded or 0:Timeout */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
return (int)(WaitForSingleObject(Mutex[vol], FF_FS_TIMEOUT) == WAIT_OBJECT_0);
#elif OS_TYPE == 1 /* uITRON */
return (int)(tloc_mtx(Mutex[vol], FF_FS_TIMEOUT) == E_OK);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
OSMutexPend(Mutex[vol], FF_FS_TIMEOUT, &err));
return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 3 /* FreeRTOS */
return (int)(xSemaphoreTake(Mutex[vol], FF_FS_TIMEOUT) == pdTRUE);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
return (int)(osMutexWait(Mutex[vol], FF_FS_TIMEOUT) == osOK);
#endif
}
/*------------------------------------------------------------------------*/
/* Release a Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leave file functions to unlock the volume.
*/
void ff_mutex_give (
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
ReleaseMutex(Mutex[vol]);
#elif OS_TYPE == 1 /* uITRON */
unl_mtx(Mutex[vol]);
#elif OS_TYPE == 2 /* uC/OS-II */
OSMutexPost(Mutex[vol]);
#elif OS_TYPE == 3 /* FreeRTOS */
xSemaphoreGive(Mutex[vol]);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexRelease(Mutex[vol]);
#endif
}
#endif /* FF_FS_REENTRANT */

View File

@ -1,13 +1,13 @@
/*------------------------------------------------------------------------*/
/* Unicode handling functions for FatFs R0.13+ */
/* Unicode Handling Functions for FatFs R0.13 and Later */
/*------------------------------------------------------------------------*/
/* This module will occupy a huge memory in the .rodata section when the */
/* FatFs is configured for LFN with DBCS. If the system has a Unicode */
/* library for the code conversion, this module should be modified to use */
/* it to avoid silly memory consumption. */
/*------------------------------------------------------------------------*/
/* This module will occupy a huge memory in the .const section when the /
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
/ utilitiy for the code conversion, this module should be modified to use /
/ that function to avoid silly memory consumption. /
/-------------------------------------------------------------------------*/
/*
/ Copyright (C) 2017, ChaN, all right reserved.
/ Copyright (C) 2022, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
@ -25,7 +25,7 @@
#include "ff.h"
#if FF_USE_LFN
#if FF_USE_LFN != 0 /* This module will be blanked if in non-LFN configuration */
#define MERGE2(a, b) a ## b
#define CVTBL(tbl, cp) MERGE2(tbl, cp)
@ -36,8 +36,7 @@
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE == 932 || FF_CODE_PAGE == 0 /* Japanese */
static
const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */
static const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */
0x00A7, 0x8198, 0x00A8, 0x814E, 0x00B0, 0x818B, 0x00B1, 0x817D, 0x00B4, 0x814C, 0x00B6, 0x81F7, 0x00D7, 0x817E, 0x00F7, 0x8180,
0x0391, 0x839F, 0x0392, 0x83A0, 0x0393, 0x83A1, 0x0394, 0x83A2, 0x0395, 0x83A3, 0x0396, 0x83A4, 0x0397, 0x83A5, 0x0398, 0x83A6,
0x0399, 0x83A7, 0x039A, 0x83A8, 0x039B, 0x83A9, 0x039C, 0x83AA, 0x039D, 0x83AB, 0x039E, 0x83AC, 0x039F, 0x83AD, 0x03A0, 0x83AE,
@ -964,8 +963,7 @@ const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */
0xFFE1, 0x8192, 0xFFE2, 0x81CA, 0xFFE3, 0x8150, 0xFFE4, 0xFA55, 0xFFE5, 0x818F, 0, 0
};
static
const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */
static const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */
0x00A1, 0xFF61, 0x00A2, 0xFF62, 0x00A3, 0xFF63, 0x00A4, 0xFF64, 0x00A5, 0xFF65, 0x00A6, 0xFF66, 0x00A7, 0xFF67, 0x00A8, 0xFF68,
0x00A9, 0xFF69, 0x00AA, 0xFF6A, 0x00AB, 0xFF6B, 0x00AC, 0xFF6C, 0x00AD, 0xFF6D, 0x00AE, 0xFF6E, 0x00AF, 0xFF6F, 0x00B0, 0xFF70,
0x00B1, 0xFF71, 0x00B2, 0xFF72, 0x00B3, 0xFF73, 0x00B4, 0xFF74, 0x00B5, 0xFF75, 0x00B6, 0xFF76, 0x00B7, 0xFF77, 0x00B8, 0xFF78,
@ -1894,8 +1892,7 @@ const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */
#endif
#if FF_CODE_PAGE == 936 || FF_CODE_PAGE == 0 /* Simplified Chinese */
static
const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */
static const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */
0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3, 0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4,
0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA, 0x00EC, 0xA8AC, 0x00ED, 0xA8AA, 0x00F2, 0xA8B0, 0x00F3, 0xA8AE,
0x00F7, 0xA1C2, 0x00F9, 0xA8B4, 0x00FA, 0xA8B2, 0x00FC, 0xA8B9, 0x0101, 0xA8A1, 0x0113, 0xA8A5, 0x011B, 0xA8A7, 0x012B, 0xA8A9,
@ -4623,8 +4620,7 @@ const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */
0, 0
};
static
const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */
static const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */
0x0080, 0x20AC, 0x8140, 0x4E02, 0x8141, 0x4E04, 0x8142, 0x4E05, 0x8143, 0x4E06, 0x8144, 0x4E0F, 0x8145, 0x4E12, 0x8146, 0x4E17,
0x8147, 0x4E1F, 0x8148, 0x4E20, 0x8149, 0x4E21, 0x814A, 0x4E23, 0x814B, 0x4E26, 0x814C, 0x4E29, 0x814D, 0x4E2E, 0x814E, 0x4E2F,
0x814F, 0x4E31, 0x8150, 0x4E33, 0x8151, 0x4E35, 0x8152, 0x4E37, 0x8153, 0x4E3C, 0x8154, 0x4E40, 0x8155, 0x4E41, 0x8156, 0x4E42,
@ -7354,8 +7350,7 @@ const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */
#endif
#if FF_CODE_PAGE == 949 || FF_CODE_PAGE == 0 /* Korean */
static
const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */
static const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */
0x00A1, 0xA2AE, 0x00A4, 0xA2B4, 0x00A7, 0xA1D7, 0x00A8, 0xA1A7, 0x00AA, 0xA8A3, 0x00AD, 0xA1A9, 0x00AE, 0xA2E7, 0x00B0, 0xA1C6,
0x00B1, 0xA1BE, 0x00B2, 0xA9F7, 0x00B3, 0xA9F8, 0x00B4, 0xA2A5, 0x00B6, 0xA2D2, 0x00B7, 0xA1A4, 0x00B8, 0xA2AC, 0x00B9, 0xA9F6,
0x00BA, 0xA8AC, 0x00BC, 0xA8F9, 0x00BD, 0xA8F6, 0x00BE, 0xA8FA, 0x00BF, 0xA2AF, 0x00C6, 0xA8A1, 0x00D0, 0xA8A2, 0x00D7, 0xA1BF,
@ -9490,8 +9485,7 @@ const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */
0, 0
};
static
const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */
static const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */
0x8141, 0xAC02, 0x8142, 0xAC03, 0x8143, 0xAC05, 0x8144, 0xAC06, 0x8145, 0xAC0B, 0x8146, 0xAC0C, 0x8147, 0xAC0D, 0x8148, 0xAC0E,
0x8149, 0xAC0F, 0x814A, 0xAC18, 0x814B, 0xAC1E, 0x814C, 0xAC1F, 0x814D, 0xAC21, 0x814E, 0xAC22, 0x814F, 0xAC23, 0x8150, 0xAC25,
0x8151, 0xAC26, 0x8152, 0xAC27, 0x8153, 0xAC28, 0x8154, 0xAC29, 0x8155, 0xAC2A, 0x8156, 0xAC2B, 0x8157, 0xAC2E, 0x8158, 0xAC32,
@ -11628,8 +11622,7 @@ const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */
#endif
#if FF_CODE_PAGE == 950 || FF_CODE_PAGE == 0 /* Traditional Chinese */
static
const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */
static const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */
0x00A7, 0xA1B1, 0x00AF, 0xA1C2, 0x00B0, 0xA258, 0x00B1, 0xA1D3, 0x00B7, 0xA150, 0x00D7, 0xA1D1, 0x00F7, 0xA1D2, 0x02C7, 0xA3BE,
0x02C9, 0xA3BC, 0x02CA, 0xA3BD, 0x02CB, 0xA3BF, 0x02CD, 0xA1C5, 0x02D9, 0xA3BB, 0x0391, 0xA344, 0x0392, 0xA345, 0x0393, 0xA346,
0x0394, 0xA347, 0x0395, 0xA348, 0x0396, 0xA349, 0x0397, 0xA34A, 0x0398, 0xA34B, 0x0399, 0xA34C, 0x039A, 0xA34D, 0x039B, 0xA34E,
@ -13320,8 +13313,7 @@ const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */
0xFF5C, 0xA155, 0xFF5D, 0xA162, 0xFF5E, 0xA1E3, 0xFFE0, 0xA246, 0xFFE1, 0xA247, 0xFFE3, 0xA1C3, 0xFFE5, 0xA244, 0, 0
};
static
const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */
static const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */
0xA140, 0x3000, 0xA141, 0xFF0C, 0xA142, 0x3001, 0xA143, 0x3002, 0xA144, 0xFF0E, 0xA145, 0x2027, 0xA146, 0xFF1B, 0xA147, 0xFF1A,
0xA148, 0xFF1F, 0xA149, 0xFF01, 0xA14A, 0xFE30, 0xA14B, 0x2026, 0xA14C, 0x2025, 0xA14D, 0xFE50, 0xA14E, 0xFE51, 0xA14F, 0xFE52,
0xA150, 0x00B7, 0xA151, 0xFE54, 0xA152, 0xFE55, 0xA153, 0xFE56, 0xA154, 0xFE57, 0xA155, 0xFF5C, 0xA156, 0x2013, 0xA157, 0xFE31,
@ -15014,8 +15006,7 @@ const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */
#endif
#if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0
static
const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */
static const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -15027,8 +15018,7 @@ const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0
static
const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */
static const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
@ -15040,8 +15030,7 @@ const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0
static
const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */
static const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
@ -15053,8 +15042,7 @@ const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0
static
const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */
static const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
@ -15066,8 +15054,7 @@ const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0
static
const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */
static const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
@ -15079,8 +15066,7 @@ const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0
static
const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */
static const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -15092,8 +15078,7 @@ const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0
static
const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */
static const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
@ -15105,8 +15090,7 @@ const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0
static
const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */
static const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
@ -15118,8 +15102,7 @@ const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0
static
const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */
static const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -15131,8 +15114,7 @@ const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0
static
const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */
static const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2,
0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -15144,8 +15126,7 @@ const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0
static
const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */
static const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -15157,8 +15138,7 @@ const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0
static
const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */
static const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
@ -15170,8 +15150,7 @@ const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0
static
const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */
static const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0,
0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192,
0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB,
@ -15183,8 +15162,7 @@ const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table *
};
#endif
#if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0
static
const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */
static const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */
0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518,
0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000,
0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5,
@ -15196,8 +15174,7 @@ const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0
static
const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */
static const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4,
@ -15209,8 +15186,7 @@ const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0
static
const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */
static const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
@ -15222,8 +15198,7 @@ const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */
};
#endif
#if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0
static
const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */
static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */
0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389,
0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF,
0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB,
@ -15239,42 +15214,43 @@ const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for static code page configuration */
/* SBCS fixed code page */
/* OEM <==> Unicode Conversions for Static Code Page Configuration with */
/* SBCS Fixed Code Page */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
WCHAR uni, /* Unicode character to be converted */
DWORD uni, /* UTF-16 encoded character to be converted */
WORD cp /* Code page for the conversion */
)
{
WCHAR c = 0;
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
const WCHAR* p = CVTBL(uc, FF_CODE_PAGE);
if (uni < 0x80) { /* ASCII char */
c = uni;
if (uni < 0x80) { /* ASCII? */
c = (WCHAR)uni;
} else { /* Non-ASCII char */
if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
} else { /* Non-ASCII */
if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */
for (c = 0; c < 0x80 && uni != p[c]; c++) ;
c = (c + 0x80) & 0xFF;
}
}
return c;
}
WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */
WCHAR oem, /* OEM code to be converted */
WORD cp /* Code page for the conversion */
)
{
WCHAR c = 0;
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
const WCHAR* p = CVTBL(uc, FF_CODE_PAGE);
if (oem < 0x80) { /* ASCII char */
if (oem < 0x80) { /* ASCII? */
c = oem;
} else { /* Extended char */
@ -15282,6 +15258,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
if (oem < 0x100) c = p[oem - 0x80];
}
}
return c;
}
@ -15290,33 +15267,34 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for static code page configuration */
/* DBCS fixed code page */
/* OEM <==> Unicode Conversions for Static Code Page Configuration with */
/* DBCS Fixed Code Page */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE != 0 && FF_CODE_PAGE >= 900
#if FF_CODE_PAGE >= 900
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
WCHAR uni, /* Unicode character to be converted */
DWORD uni, /* UTF-16 encoded character to be converted */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
WCHAR c = 0;
UINT i, n, li, hi;
const WCHAR* p;
WCHAR c = 0, uc;
UINT i = 0, n, li, hi;
if (uni < 0x80) { /* ASCII char */
c = uni;
if (uni < 0x80) { /* ASCII? */
c = (WCHAR)uni;
} else { /* Non-ASCII char */
if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
} else { /* Non-ASCII */
if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */
uc = (WCHAR)uni;
p = CVTBL(uni2oem, FF_CODE_PAGE);
hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1;
li = 0;
for (n = 16; n; n--) {
i = li + (hi - li) / 2;
if (uni == p[i * 2]) break;
if (uni > p[i * 2]) {
if (uc == p[i * 2]) break;
if (uc > p[i * 2]) {
li = i;
} else {
hi = i;
@ -15325,25 +15303,26 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
if (n != 0) c = p[i * 2 + 1];
}
}
return c;
}
WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */
WCHAR oem, /* OEM code to be converted */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
const WCHAR* p;
WCHAR c = 0;
UINT i, n, li, hi;
UINT i = 0, n, li, hi;
if (oem < 0x80) { /* ASCII char */
if (oem < 0x80) { /* ASCII? */
c = oem;
} else { /* Extended char */
if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
if (cp == FF_CODE_PAGE) { /* Is it valid code page? */
p = CVTBL(oem2uni, FF_CODE_PAGE);
hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1;
li = 0;
@ -15359,6 +15338,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
if (n != 0) c = p[i * 2 + 1];
}
}
return c;
}
#endif
@ -15366,74 +15346,78 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for dynamic code page configuration */
/* OEM <==> Unicode Conversions for Dynamic Code Page Configuration */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE == 0
static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0};
static const WCHAR *const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0};
static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0};
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
WCHAR uni, /* Unicode character to be converted */
DWORD uni, /* UTF-16 encoded character to be converted */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
WCHAR c = 0;
const WCHAR* p;
WCHAR c = 0, uc;
UINT i, n, li, hi;
if (uni < 0x80) { /* ASCII char */
c = uni;
if (uni < 0x80) { /* ASCII? */
c = (WCHAR)uni;
} else { /* Non-ASCII char */
p = 0;
if (cp < 900) { /* SBCS */
for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */
p = cp_table[i];
if (p) { /* Is it a valid CP ? */
for (c = 0; c < 0x80 && uni != p[c]; c++) ; /* Find OEM code in the table */
c = (c + 0x80) & 0xFF;
}
} else { /* DBCS */
switch (cp) {
case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break;
case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break;
case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break;
case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break;
}
if (p) { /* Is it a valid code page? */
li = 0;
for (n = 16; n; n--) { /* Find OEM code */
i = li + (hi - li) / 2;
if (uni == p[i * 2]) break;
if (uni > p[i * 2]) {
li = i;
} else {
hi = i;
}
} else { /* Non-ASCII */
if (uni < 0x10000) { /* Is it in BMP? */
uc = (WCHAR)uni;
p = 0;
if (cp < 900) { /* SBCS */
for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get conversion table */
p = cp_table[i];
if (p) { /* Is it valid code page ? */
for (c = 0; c < 0x80 && uc != p[c]; c++) ; /* Find OEM code in the table */
c = (c + 0x80) & 0xFF;
}
} else { /* DBCS */
switch (cp) { /* Get conversion table */
case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break;
case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break;
case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break;
case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break;
}
if (p) { /* Is it valid code page? */
li = 0;
for (n = 16; n; n--) { /* Find OEM code */
i = li + (hi - li) / 2;
if (uc == p[i * 2]) break;
if (uc > p[i * 2]) {
li = i;
} else {
hi = i;
}
}
if (n != 0) c = p[i * 2 + 1];
}
if (n != 0) c = p[i * 2 + 1];
}
}
}
return c;
}
WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
WCHAR oem, /* OEM code to be converted */
WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */
WCHAR oem, /* OEM code to be converted (DBC if >=0x100) */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
const WCHAR* p;
WCHAR c = 0;
UINT i, n, li, hi;
if (oem < 0x80) { /* ASCII char */
if (oem < 0x80) { /* ASCII? */
c = oem;
} else { /* Extended char */
@ -15466,6 +15450,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
}
}
}
return c;
}
#endif
@ -15473,57 +15458,97 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
/*------------------------------------------------------------------------*/
/* Unicode up-case conversion */
/* Unicode Up-case Conversion */
/*------------------------------------------------------------------------*/
WCHAR ff_wtoupper ( /* Returns up-converted character */
WCHAR uni /* Unicode character to be upper converted (BMP only) */
DWORD ff_wtoupper ( /* Returns up-converted code point */
DWORD uni /* Unicode code point to be up-converted */
)
{
/* Compressed upper conversion table */
static const WCHAR cvt1[] = { /* U+0000 - U+0FFF */
const WORD* p;
WORD uc, bc, nc, cmd;
static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */
/* Basic Latin */
0x0061,0x031A,
/* Latin-1 Supplement */
0x00E0,0x0317, 0x00F8,0x0307, 0x00FF,0x0001,0x0178,
0x00E0,0x0317,
0x00F8,0x0307,
0x00FF,0x0001,0x0178,
/* Latin Extended-A */
0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106,
0x0100,0x0130,
0x0132,0x0106,
0x0139,0x0110,
0x014A,0x012E,
0x0179,0x0106,
/* Latin Extended-B */
0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA,
0x01CD,0x0110, 0x01DD,0x0001,0x018E, 0x01DE,0x0112, 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, 0x01F8,0x0128,
0x0222,0x0112, 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, 0x0246,0x010A,
0x01CD,0x0110,
0x01DD,0x0001,0x018E,
0x01DE,0x0112,
0x01F3,0x0003,0x01F1,0x01F4,0x01F4,
0x01F8,0x0128,
0x0222,0x0112,
0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241,
0x0246,0x010A,
/* IPA Extensions */
0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7,
/* Greek, Coptic */
0x037B,0x0003,0x03FD,0x03FE,0x03FF, 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, 0x03B1,0x0311,
0x03C2,0x0002,0x03A3,0x03A3, 0x03C4,0x0308, 0x03CC,0x0003,0x038C,0x038E,0x038F, 0x03D8,0x0118,
0x037B,0x0003,0x03FD,0x03FE,0x03FF,
0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A,
0x03B1,0x0311,
0x03C2,0x0002,0x03A3,0x03A3,
0x03C4,0x0308,
0x03CC,0x0003,0x038C,0x038E,0x038F,
0x03D8,0x0118,
0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA,
/* Cyrillic */
0x0430,0x0320, 0x0450,0x0710, 0x0460,0x0122, 0x048A,0x0136, 0x04C1,0x010E, 0x04CF,0x0001,0x04C0, 0x04D0,0x0144,
0x0430,0x0320,
0x0450,0x0710,
0x0460,0x0122,
0x048A,0x0136,
0x04C1,0x010E,
0x04CF,0x0001,0x04C0,
0x04D0,0x0144,
/* Armenian */
0x0561,0x0426,
0x0000
0x0000 /* EOT */
};
static const WCHAR cvt2[] = { /* U+1000 - U+FFFF */
static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */
/* Phonetic Extensions */
0x1D7D,0x0001,0x2C63,
/* Latin Extended Additional */
0x1E00,0x0196, 0x1EA0,0x015A,
0x1E00,0x0196,
0x1EA0,0x015A,
/* Greek Extended */
0x1F00,0x0608, 0x1F10,0x0606, 0x1F20,0x0608, 0x1F30,0x0608, 0x1F40,0x0606,
0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, 0x1F60,0x0608,
0x1F00,0x0608,
0x1F10,0x0606,
0x1F20,0x0608,
0x1F30,0x0608,
0x1F40,0x0606,
0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F,
0x1F60,0x0608,
0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB,
0x1F80,0x0608, 0x1F90,0x0608, 0x1FA0,0x0608, 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
0x1FCC,0x0001,0x1FC3, 0x1FD0,0x0602, 0x1FE0,0x0602, 0x1FE5,0x0001,0x1FEC, 0x1FF3,0x0001,0x1FFC,
0x1F80,0x0608,
0x1F90,0x0608,
0x1FA0,0x0608,
0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
0x1FCC,0x0001,0x1FC3,
0x1FD0,0x0602,
0x1FE0,0x0602,
0x1FE5,0x0001,0x1FEC,
0x1FF3,0x0001,0x1FFC,
/* Letterlike Symbols */
0x214E,0x0001,0x2132,
/* Number forms */
0x2170,0x0210, 0x2184,0x0001,0x2183,
0x2170,0x0210,
0x2184,0x0001,0x2183,
/* Enclosed Alphanumerics */
0x24D0,0x051A, 0x2C30,0x042F,
0x24D0,0x051A,
0x2C30,0x042F,
/* Latin Extended-C */
0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102,
0x2C60,0x0102,
0x2C67,0x0106, 0x2C75,0x0102,
/* Coptic */
0x2C80,0x0164,
/* Georgian Supplement */
@ -15531,36 +15556,38 @@ WCHAR ff_wtoupper ( /* Returns up-converted character */
/* Full-width */
0xFF41,0x031A,
0x0000
0x0000 /* EOT */
};
const WCHAR *p;
WCHAR bc, nc, cmd;
p = uni < 0x1000 ? cvt1 : cvt2;
for (;;) {
bc = *p++; /* Get block base */
if (!bc || uni < bc) break;
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
if (uni < bc + nc) { /* In the block? */
switch (cmd) {
case 0: uni = p[uni - bc]; break; /* Table conversion */
case 1: uni -= (uni - bc) & 1; break; /* Case pairs */
case 2: uni -= 16; break; /* Shift -16 */
case 3: uni -= 32; break; /* Shift -32 */
case 4: uni -= 48; break; /* Shift -48 */
case 5: uni -= 26; break; /* Shift -26 */
case 6: uni += 8; break; /* Shift +8 */
case 7: uni -= 80; break; /* Shift -80 */
case 8: uni -= 0x1C60; break; /* Shift -0x1C60 */
if (uni < 0x10000) { /* Is it in BMP? */
uc = (WORD)uni;
p = uc < 0x1000 ? cvt1 : cvt2;
for (;;) {
bc = *p++; /* Get the block base */
if (bc == 0 || uc < bc) break; /* Not matched? */
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
if (uc < bc + nc) { /* In the block? */
switch (cmd) {
case 0: uc = p[uc - bc]; break; /* Table conversion */
case 1: uc -= (uc - bc) & 1; break; /* Case pairs */
case 2: uc -= 16; break; /* Shift -16 */
case 3: uc -= 32; break; /* Shift -32 */
case 4: uc -= 48; break; /* Shift -48 */
case 5: uc -= 26; break; /* Shift -26 */
case 6: uc += 8; break; /* Shift +8 */
case 7: uc -= 80; break; /* Shift -80 */
case 8: uc -= 0x1C60; break; /* Shift -0x1C60 */
}
break;
}
break;
if (cmd == 0) p += nc; /* Skip table if needed */
}
if (!cmd) p += nc;
uni = uc;
}
return uni;
}
#endif /* #if _USE_LFN */
#endif /* #if FF_USE_LFN != 0 */

View File

@ -476,7 +476,7 @@ u32 sdmmc_sdcard_init()
{
u32 ret = 0;
InitSD();
if(Nand_Init() != 0) ret &= 1;
if(SD_Init() != 0) ret &= 2;
if(Nand_Init() != 0) ret |= 1;
if(SD_Init() != 0) ret |= 2;
return ret;
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2021 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -31,15 +31,15 @@
#include "exceptions.h"
#include "patches.h"
#include "memory.h"
#include "strings.h"
#include "cache.h"
#include "emunand.h"
#include "crypto.h"
#include "screen.h"
#include "fmt.h"
#include "../build/bundled.h"
#include "chainloader.h"
static Firm *firm = (Firm *)0x20001000;
u32 firmProtoVersion = 0;
static __attribute__((noinline)) bool overlaps(u32 as, u32 ae, u32 bs, u32 be)
{
@ -59,7 +59,7 @@ static __attribute__((noinline)) bool inRange(u32 as, u32 ae, u32 bs, u32 be)
static bool checkFirm(u32 firmSize)
{
if(memcmp(firm->magic, "FIRM", 4) != 0 || firm->arm9Entry == NULL) //Allow for the ARM11 entrypoint to be zero in which case nothing is done on the ARM11 side
if(memcmp(firm->magic, "FIRM", 4) != 0 || firm->arm9Entry == NULL) //Allow for the Arm11 entrypoint to be zero in which case nothing is done on the Arm11 side
return false;
bool arm9EpFound = false,
@ -152,10 +152,24 @@ static inline u32 loadFirmFromStorage(FirmwareType firmType)
u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode)
{
u32 firmVersion,
u32 firmVersion = 0xFFFFFFFF,
firmSize;
bool ctrNandError = isSdMode && !mountFs(false, false);
bool ctrNandError = true;
bool loadedFromStorage = false;
bool storageLoadError = false;
// Try loading FIRM from sdmc first if specified.
if (loadFromStorage) {
firmSize = loadFirmFromStorage(*firmType);
if (firmSize != 0) loadedFromStorage = true;
else storageLoadError = true;
}
// Remount ctrnand and load FIRM from it if loading from sdmc failed.
if (!loadedFromStorage) {
ctrNandError = isSdMode && !remountCtrNandPartition(false);
}
if(!ctrNandError)
{
@ -170,10 +184,8 @@ u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadF
if(!firmSize || !checkFirm(firmSize)) ctrNandError = true;
}
}
bool loadedFromStorage = false;
if(loadFromStorage || ctrNandError)
// If CTRNAND load failed, and it wasn't tried yet, load FIRM from sdmc.
if (ctrNandError && !storageLoadError)
{
u32 result = loadFirmFromStorage(*firmType);
@ -182,11 +194,69 @@ u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadF
loadedFromStorage = true;
firmSize = result;
}
else if(ctrNandError) error("Unable to mount CTRNAND or load the CTRNAND FIRM.\nPlease use an external one.");
else storageLoadError = true;
}
// If all attempts failed, panic.
if(ctrNandError && storageLoadError) error("Unable to mount CTRNAND or load the CTRNAND FIRM.\nPlease use an external one.");
//Check that the FIRM is right for the console from the Arm9 section address
bool isO3dsFirm = firm->section[3].offset == 0 && firm->section[2].address == (u8 *)0x8006800;
if(loadedFromStorage || ISDEVUNIT)
{
firmVersion = 0xFFFFFFFF;
if(isO3dsFirm && (*firmType == NATIVE_FIRM || *firmType == NATIVE_FIRM1X2X))
{
__attribute__((aligned(4))) static const u8 hashes[5][0x20] = {
{0xD7, 0x43, 0x0F, 0x27, 0x8D, 0xC9, 0x3F, 0x4C, 0x96, 0xB5, 0xA8, 0x91, 0x48, 0xDB, 0x08, 0x8A,
0x7E, 0x46, 0xB3, 0x95, 0x65, 0xA2, 0x05, 0xF1, 0xF2, 0x41, 0x21, 0xF1, 0x0C, 0x59, 0x6A, 0x9D},
{0x93, 0xDF, 0x49, 0xA1, 0x24, 0x86, 0xBB, 0x6F, 0xAF, 0x49, 0x99, 0x2D, 0xD0, 0x8D, 0xB1, 0x88,
0x8A, 0x00, 0xB6, 0xDD, 0x36, 0x89, 0xC0, 0xE2, 0xC9, 0xA9, 0x99, 0x62, 0x57, 0x5E, 0x6C, 0x23},
{0x39, 0x75, 0xB5, 0x28, 0x24, 0x5E, 0x8B, 0x56, 0xBC, 0x83, 0x79, 0x41, 0x09, 0x2C, 0x42, 0xE6,
0x26, 0xB6, 0x80, 0x59, 0xA5, 0x56, 0xF9, 0xF9, 0x6E, 0xF3, 0x63, 0x05, 0x58, 0xDF, 0x35, 0xEF},
{0x81, 0x9E, 0x71, 0x58, 0xE5, 0x44, 0x73, 0xF7, 0x48, 0x78, 0x7C, 0xEF, 0x5E, 0x30, 0xE2, 0x28,
0x78, 0x0B, 0x21, 0x23, 0x94, 0x63, 0xE8, 0x4E, 0x06, 0xBB, 0xD6, 0x8D, 0xA0, 0x99, 0xAE, 0x98},
{0x1D, 0xD5, 0xB0, 0xC2, 0xD9, 0x4A, 0x4A, 0xF3, 0x23, 0xDD, 0x2F, 0x65, 0x21, 0x95, 0x9B, 0x7E,
0xF2, 0x71, 0x7E, 0xB6, 0x7A, 0x3A, 0x74, 0x78, 0x0D, 0xE3, 0xB5, 0x0C, 0x2B, 0x7F, 0x85, 0x37},
};
u32 i;
for(i = 0; i < sizeof(hashes)/sizeof(hashes[0]); i++)
{
if(memcmp(firm->section[1].hash, hashes[i], 0x20) == 0) break;
}
switch(i)
{
// Beta
case 0:
firmVersion = 0x0;
firmProtoVersion = 243;
*firmType = NATIVE_PROTOTYPE;
break;
case 1:
firmVersion = 0x0;
firmProtoVersion = 238;
*firmType = NATIVE_PROTOTYPE;
break;
// Release
case 2:
firmVersion = 0x18;
break;
case 3:
firmVersion = 0x1D;
break;
case 4:
firmVersion = 0x1F;
break;
default:
break;
}
}
}
//Check that the FIRM is right for the console from the ARM9 section address
if((firm->section[3].offset != 0 ? firm->section[3].address : firm->section[2].address) != (ISN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800))
if(*firmType != NATIVE_PROTOTYPE && (firm->section[3].offset != 0 ? firm->section[3].address : firm->section[2].address) != (ISN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800))
error("The %s FIRM is not for this console.", loadedFromStorage ? "external" : "CTRNAND");
if(!ISN3DS && *firmType == NATIVE_FIRM && firm->section[0].address == (u8 *)0x1FF80000)
@ -194,51 +264,20 @@ u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadF
//We can't boot < 3.x EmuNANDs
if(nandType != FIRMWARE_SYSNAND) error("An old unsupported EmuNAND has been detected.\nLuma3DS is unable to boot it.");
//If you want to use SAFE_FIRM on 1.0, use Luma from NAND & comment this line:
if(isSafeMode) error("SAFE_MODE is not supported on 1.x/2.x FIRM.");
*firmType = NATIVE_FIRM1X2X;
}
if(loadedFromStorage || ISDEVUNIT)
{
firmVersion = 0xFFFFFFFF;
if(!ISN3DS && *firmType == NATIVE_FIRM)
{
__attribute__((aligned(4))) static const u8 hashes[3][0x20] = {
{0x39, 0x75, 0xB5, 0x28, 0x24, 0x5E, 0x8B, 0x56, 0xBC, 0x83, 0x79, 0x41, 0x09, 0x2C, 0x42, 0xE6,
0x26, 0xB6, 0x80, 0x59, 0xA5, 0x56, 0xF9, 0xF9, 0x6E, 0xF3, 0x63, 0x05, 0x58, 0xDF, 0x35, 0xEF},
{0x81, 0x9E, 0x71, 0x58, 0xE5, 0x44, 0x73, 0xF7, 0x48, 0x78, 0x7C, 0xEF, 0x5E, 0x30, 0xE2, 0x28,
0x78, 0x0B, 0x21, 0x23, 0x94, 0x63, 0xE8, 0x4E, 0x06, 0xBB, 0xD6, 0x8D, 0xA0, 0x99, 0xAE, 0x98},
{0x1D, 0xD5, 0xB0, 0xC2, 0xD9, 0x4A, 0x4A, 0xF3, 0x23, 0xDD, 0x2F, 0x65, 0x21, 0x95, 0x9B, 0x7E,
0xF2, 0x71, 0x7E, 0xB6, 0x7A, 0x3A, 0x74, 0x78, 0x0D, 0xE3, 0xB5, 0x0C, 0x2B, 0x7F, 0x85, 0x37}
};
u32 i;
for(i = 0; i < 3; i++) if(memcmp(firm->section[1].hash, hashes[i], 0x20) == 0) break;
switch(i)
{
case 0:
firmVersion = 0x18;
break;
case 1:
firmVersion = 0x1D;
break;
case 2:
firmVersion = 0x1F;
break;
}
}
}
return firmVersion;
}
void loadHomebrewFirm(u32 pressed)
{
char path[10 + 255];
bool found = !pressed ? payloadMenu(path) : findPayload(path, pressed);
bool hasDisplayedMenu = false;
bool found = !pressed ? payloadMenu(path, &hasDisplayedMenu) : findPayload(path, pressed);
if(!found) return;
@ -253,17 +292,156 @@ void loadHomebrewFirm(u32 pressed)
else sprintf(absPath, "nand:/rw/luma/%s", path);
char *argv[2] = {absPath, (char *)fbs};
bool wantsScreenInit = (firm->reserved2[0] & 1) != 0;
initScreens();
if(!hasDisplayedMenu && wantsScreenInit)
initScreens(); // Don't init the screens unless we have to, if not already done
launchFirm((firm->reserved2[0] & 1) ? 2 : 1, argv);
launchFirm(wantsScreenInit ? 2 : 1, argv);
}
static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool loadFromStorage)
static int lzss_decompress(u8 *end)
{
unsigned int v1; // r1@2
u8 *v2; // r2@2
u8 *v3; // r3@2
u8 *v4; // r1@2
char v5; // r5@4
char v6; // t1@4
signed int v7; // r6@4
int v9; // t1@7
u8 *v11; // r3@8
int v12; // r12@8
int v13; // t1@8
int v14; // t1@8
unsigned int v15; // r7@8
int v16; // r12@8
int ret;
ret = 0;
if ( end )
{
v1 = *((u32 *)end - 2);
v2 = &end[*((u32 *)end - 1)];
v3 = &end[-(v1 >> 24)];
v4 = &end[-(v1 & 0xFFFFFF)];
while ( v3 > v4 )
{
v6 = *(v3-- - 1);
v5 = v6;
v7 = 8;
while ( 1 )
{
if ( (v7-- < 1) )
break;
if ( v5 & 0x80 )
{
v13 = *(v3 - 1);
v11 = v3 - 1;
v12 = v13;
v14 = *(v11 - 1);
v3 = v11 - 1;
v15 = ((v14 | (v12 << 8)) & 0xFFFF0FFF) + 2;
v16 = v12 + 32;
do
{
ret = v2[v15];
*(v2-- - 1) = ret;
v16 -= 16;
}
while ( !(v16 < 0) );
}
else
{
v9 = *(v3-- - 1);
ret = v9;
*(v2-- - 1) = v9;
}
v5 *= 2;
if ( v3 <= v4 )
return ret;
}
}
}
return ret;
}
typedef struct CopyKipResult {
u32 cxiSize;
u8 *codeDstAddr;
u32 codeSize;
} CopyKipResult;
// Copy a KIP, decompressing it in place if necessary (TwlBg)
static CopyKipResult copyKip(u8 *dst, const u8 *src, u32 maxSize, bool decompress)
{
const char *extModuleSizeError = "The external FIRM modules are too large.";
CopyKipResult res = { 0 };
Cxi *dstCxi = (Cxi *)dst;
const Cxi *srcCxi = (const Cxi *)src;
u32 mediaUnitShift = 9 + srcCxi->ncch.flags[6];
u32 totalSizeCompressed = srcCxi->ncch.contentSize << mediaUnitShift;
if (totalSizeCompressed > maxSize)
error(extModuleSizeError);
// First, copy the compressed KIP to the destination
memcpy(dst, src, totalSizeCompressed);
ExHeader *exh = &dstCxi->exHeader;
bool isCompressed = (exh->systemControlInfo.flag & 1) != 0;
ExeFsHeader *exefs = (ExeFsHeader *)(dst + (dstCxi->ncch.exeFsOffset << mediaUnitShift));
ExeFsFileHeader *fh = &exefs->fileHeaders[0];
u8 *codeAddr = (u8 *)exefs + sizeof(ExeFsHeader) + fh->offset;
if (memcmp(fh->name, ".code\0\0\0", 8) != 0 || fh->offset != 0 || exefs->fileHeaders[1].size != 0)
error("One of the external FIRM modules have invalid layout.");
// If it's already decompressed or we don't need to, there is not much left to do
if (!decompress || !isCompressed)
{
res.cxiSize = totalSizeCompressed;
res.codeDstAddr = codeAddr;
res.codeSize = fh->size;
}
else
{
u32 codeSize = exh->systemControlInfo.textCodeSet.size;
codeSize += exh->systemControlInfo.roCodeSet.size;
codeSize += exh->systemControlInfo.dataCodeSet.size;
u32 codeSizePadded = ((codeSize + (1 << mediaUnitShift) - 1) >> mediaUnitShift) << mediaUnitShift;
u32 newTotalSize = (codeAddr + codeSizePadded) - dst;
if (newTotalSize > maxSize)
error(extModuleSizeError);
// Decompress in place
lzss_decompress(codeAddr + fh->size);
// Fill padding just in case
memset(codeAddr + codeSize, 0, codeSizePadded - codeSize);
// Fix fields
fh->size = codeSize;
dstCxi->ncch.exeFsSize = codeSizePadded >> mediaUnitShift;
exh->systemControlInfo.flag &= ~1;
dstCxi->ncch.contentSize = newTotalSize >> mediaUnitShift;
res.cxiSize = newTotalSize;
res.codeDstAddr = codeAddr;
res.codeSize = codeSize;
}
return res;
}
static void mergeSection0(FirmwareType firmType, u32 firmVersion, bool loadFromStorage)
{
u32 srcModuleSize,
nbModules = 0;
bool isLgyFirm = firmType == TWL_FIRM || firmType == AGB_FIRM;
struct
{
char name[8];
@ -279,10 +457,11 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo
srcModuleSize = moduleList[nbModules].size = ((Cxi *)src)->ncch.contentSize * 0x200;
}
if(firmType == NATIVE_FIRM && (ISN3DS || firmVersion >= 0x1D))
// SAFE_FIRM only for N3DS and only if ENABLESAFEFIRMROSALINA is on
if((firmType == NATIVE_FIRM || firmType == SAFE_FIRM) && (ISN3DS || firmVersion >= 0x25))
{
//2) Merge that info with our own modules'
for(u8 *src = (u8 *)0x18180000; src < (u8 *)(0x18180000 + LUMA_SECTION0_SIZE); src += srcModuleSize)
for(u8 *src = (u8 *)0x18180000; memcmp(((Cxi *)src)->ncch.magic, "NCCH", 4) == 0; src += srcModuleSize)
{
const char *name = ((Cxi *)src)->exHeader.systemControlInfo.appTitle;
@ -304,7 +483,10 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo
//3) Read or copy the modules
u8 *dst = firm->section[0].address;
const char *extModuleSizeError = "The external FIRM modules are too large.";
for(u32 i = 0, dstModuleSize, maxModuleSize = firmType == NATIVE_FIRM ? 0x80000 : 0x600000; i < nbModules; i++, dst += dstModuleSize, maxModuleSize -= dstModuleSize)
// SAFE_FIRM only for N3DS and only if ENABLESAFEFIRMROSALINA is on
u32 maxModuleSize = !isLgyFirm ? 0x80000 : 0x600000;
u32 dstModuleSize = 0;
for(u32 i = 0; i < nbModules; i++)
{
if(loadFromStorage)
{
@ -325,33 +507,50 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo
memcmp(moduleList[i].name, ((Cxi *)dst)->exHeader.systemControlInfo.appTitle, sizeof(((Cxi *)dst)->exHeader.systemControlInfo.appTitle)) != 0)
error("An external FIRM module is invalid or corrupted.");
dst += dstModuleSize;
maxModuleSize -= dstModuleSize;
continue;
}
}
dstModuleSize = moduleList[i].size;
// If not successfully loaded from storage, then...
if(dstModuleSize > maxModuleSize) error(extModuleSizeError);
// Decompress stock TwlBg so that we can patch it
bool isStockTwlBg = firmType == TWL_FIRM && strcmp(moduleList[i].name, "TwlBg") == 0;
memcpy(dst, moduleList[i].src, dstModuleSize);
CopyKipResult copyRes = copyKip(dst, moduleList[i].src, maxModuleSize, isStockTwlBg);
if (isStockTwlBg)
patchTwlBg(copyRes.codeDstAddr, copyRes.codeSize);
dst += copyRes.cxiSize;
maxModuleSize -= copyRes.cxiSize;
}
//4) Patch NATIVE_FIRM if necessary
if(nbModules == 6)
//4) Patch kernel to take module size into account
u32 newKipSectionSize = dst - firm->section[0].address;
u32 oldKipSectionSize = firm->section[0].size;
u8 *kernel11Addr = (u8 *)firm + firm->section[1].offset;
u32 kernel11Size = firm->section[1].size;
if (isLgyFirm)
{
if(patchK11ModuleLoading(firm->section[0].size, dst - firm->section[0].address, (u8 *)firm + firm->section[1].offset, firm->section[1].size) != 0)
error("Failed to inject custom sysmodule");
if (patchK11ModuleLoadingLgy(newKipSectionSize, kernel11Addr, kernel11Size) != 0)
error("Failed to load sysmodules");
}
else
{
if (patchK11ModuleLoading(oldKipSectionSize, newKipSectionSize, nbModules, kernel11Addr, kernel11Size) != 0)
error("Failed to load sysmodules");
}
}
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isFirmProtEnabled, bool isSafeMode, bool doUnitinfoPatch)
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isFirmProtEnabled, bool needToInitSd, bool doUnitinfoPatch)
{
u8 *arm9Section = (u8 *)firm + firm->section[2].offset,
*arm11Section1 = (u8 *)firm + firm->section[1].offset;
u8 *arm9Section = (u8 *)firm + firm->section[2].offset;
if(ISN3DS)
{
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
//Decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader
kernel9Loader((Arm9Bin *)arm9Section);
firm->arm9Entry = (u8 *)0x801B01C;
}
@ -361,34 +560,41 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
process9MemAddr;
u8 *process9Offset = getProcess9Info(arm9Section, firm->section[2].size, &process9Size, &process9MemAddr);
//Find the Kernel11 SVC table and handler, exceptions page and free space locations
u32 baseK11VA;
u8 *freeK11Space;
u32 *arm11SvcHandler,
*arm11ExceptionsPage,
*arm11SvcTable = getKernel11Info(arm11Section1, firm->section[1].size, &baseK11VA, &freeK11Space, &arm11SvcHandler, &arm11ExceptionsPage);
u32 kernel9Size = (u32)(process9Offset - arm9Section) - sizeof(Cxi) - 0x200,
ret = 0;
//Skip on FIRMs < 4.0
if(ISN3DS || firmVersion >= 0x1D)
#ifndef BUILD_FOR_EXPLOIT_DEV
//Skip on FIRMs < 5.0
if(ISN3DS || firmVersion >= 0x25)
{
ret += installK11Extension(arm11Section1, firm->section[1].size, isSafeMode, baseK11VA, arm11ExceptionsPage, &freeK11Space);
//Find the Kernel11 SVC table and handler, exceptions page and free space locations
u8 *arm11Section1 = (u8 *)firm + firm->section[1].offset;
u32 baseK11VA;
u8 *freeK11Space;
u32 *arm11SvcHandler,
*arm11ExceptionsPage,
*arm11SvcTable = getKernel11Info(arm11Section1, firm->section[1].size, &baseK11VA, &freeK11Space, &arm11SvcHandler, &arm11ExceptionsPage);
ret += installK11Extension(arm11Section1, firm->section[1].size, needToInitSd, baseK11VA, arm11ExceptionsPage, &freeK11Space);
ret += patchKernel11(arm11Section1, firm->section[1].size, baseK11VA, arm11SvcTable, arm11ExceptionsPage);
}
#else
(void)needToInitSd;
#endif
//Apply signature patches
ret += patchSignatureChecks(process9Offset, process9Size);
//Apply EmuNAND patches
if(nandType != FIRMWARE_SYSNAND) ret += patchEmuNand(arm9Section, kernel9Size, process9Offset, process9Size, firm->section[2].address, firmVersion);
if(nandType != FIRMWARE_SYSNAND) ret += patchEmuNand(process9Offset, process9Size, firmVersion);
//Apply FIRM0/1 writes patches on SysNAND to protect A9LH
else if(isFirmProtEnabled) ret += patchFirmWrites(process9Offset, process9Size);
#ifndef BUILD_FOR_EXPLOIT_DEV
//Apply firmlaunch patches
ret += patchFirmlaunches(process9Offset, process9Size, process9MemAddr);
#endif
//Apply dev unit check patches related to NCCH encryption
if(!ISDEVUNIT)
@ -400,6 +606,9 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
//Apply anti-anti-DG patches on 11.0+
if(firmVersion >= (ISN3DS ? 0x21 : 0x52)) ret += patchTitleInstallMinVersionChecks(process9Offset, process9Size, firmVersion);
//Patch P9 AM ticket wrapper on 11.8+ to use 0 Key and IV, only with UNITINFO patch on to prevent NIM from actually sending any
if(doUnitinfoPatch && firmVersion >= (ISN3DS ? 0x35 : 0x64)) ret += patchP9AMTicketWrapperZeroKeyIV(process9Offset, process9Size, firmVersion);
//Apply UNITINFO patches
if(doUnitinfoPatch)
{
@ -407,7 +616,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
if(!ISDEVUNIT) ret += patchCheckForDevCommonKey(process9Offset, process9Size);
}
//ARM9 exception handlers
//Arm9 exception handlers
ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size);
ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address);
ret += patchKernel9Panic(arm9Section, kernel9Size);
@ -422,9 +631,18 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch)
{
u8 *section1 = (u8 *)firm + firm->section[1].offset;
u32 section1Size = firm->section[1].size;
u8 *section2 = (u8 *)firm + firm->section[2].offset;
u32 section2Size = firm->section[2].size;
u8 *arm9Section = (u8 *)firm + firm->section[3].offset;
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
// Below 3.0, do not actually do anything.
if(!ISN3DS && firmVersion < 0xC)
return 0;
//On N3DS, decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader
if(ISN3DS)
{
kernel9Loader((Arm9Bin *)arm9Section);
@ -450,11 +668,11 @@ u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch)
//Apply UNITINFO patch
if(doUnitinfoPatch) ret += patchUnitInfoValueSet(arm9Section, kernel9Size);
if(loadFromStorage)
{
mergeSection0(TWL_FIRM, 0, true);
firm->section[0].size = 0;
}
ret += patchLgyK11(section1, section1Size, section2, section2Size);
// Also patch TwlBg here
mergeSection0(TWL_FIRM, 0, loadFromStorage);
firm->section[0].size = 0;
return ret;
}
@ -463,7 +681,12 @@ u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch)
{
u8 *arm9Section = (u8 *)firm + firm->section[3].offset;
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
u8 *section1 = (u8 *)firm + firm->section[1].offset;
u32 section1Size = firm->section[1].size;
u8 *section2 = (u8 *)firm + firm->section[2].offset;
u32 section2Size = firm->section[2].size;
//On N3DS, decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader
if(ISN3DS)
{
kernel9Loader((Arm9Bin *)arm9Section);
@ -480,6 +703,7 @@ u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch)
ret += patchLgySignatureChecks(process9Offset, process9Size);
if(CONFIG(SHOWGBABOOT)) ret += patchAgbBootSplash(process9Offset, process9Size);
ret += patchLgyK11(section1, section1Size, section2, section2Size);
//Apply UNITINFO patch
if(doUnitinfoPatch) ret += patchUnitInfoValueSet(arm9Section, kernel9Size);
@ -499,7 +723,7 @@ u32 patch1x2xNativeAndSafeFirm(void)
if(ISN3DS)
{
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
//Decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader
kernel9Loader((Arm9Bin *)arm9Section);
firm->arm9Entry = (u8 *)0x801B01C;
}
@ -516,21 +740,64 @@ u32 patch1x2xNativeAndSafeFirm(void)
ret += ISN3DS ? patchSignatureChecks(process9Offset, process9Size) : patchOldSignatureChecks(process9Offset, process9Size);
//ARM9 exception handlers
//Arm9 exception handlers
ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size);
ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address);
//Apply firmlaunch patches
//Doesn't work here if Luma is on SD. If you want to use SAFE_FIRM on 1.0, use Luma from NAND & uncomment this line:
//ret += patchFirmlaunches(process9Offset, process9Size, process9MemAddr);
if(ISN3DS && CONFIG(ENABLESAFEFIRMROSALINA))
{
u8 *arm11Section1 = (u8 *)firm + firm->section[1].offset;
//Find the Kernel11 SVC table and handler, exceptions page and free space locations
u32 baseK11VA;
u8 *freeK11Space;
u32 *arm11SvcHandler,
*arm11ExceptionsPage,
*arm11SvcTable = getKernel11Info(arm11Section1, firm->section[1].size, &baseK11VA, &freeK11Space, &arm11SvcHandler, &arm11ExceptionsPage);
ret += installK11Extension(arm11Section1, firm->section[1].size, false, baseK11VA, arm11ExceptionsPage, &freeK11Space);
ret += patchKernel11(arm11Section1, firm->section[1].size, baseK11VA, arm11SvcTable, arm11ExceptionsPage);
// Add some other patches to the mix, as we can now launch homebrew on SAFE_FIRM:
ret += patchKernel9Panic(arm9Section, kernel9Size);
ret += patchP9AccessChecks(process9Offset, process9Size);
mergeSection0(NATIVE_FIRM, 0x45, false); // may change in the future
firm->section[0].size = 0;
}
return ret;
}
u32 patchPrototypeNative(FirmwareSource nandType)
{
u8 *arm9Section = (u8 *)firm + firm->section[2].offset;
//Find the Process9 .code location, size and memory address
u32 process9Size,
process9MemAddr;
u8 *process9Offset = getProcess9Info(arm9Section, firm->section[2].size, &process9Size, &process9MemAddr);
u32 kernel9Size = (u32)(process9Offset - arm9Section) - sizeof(Cxi) - 0x200,
ret = 0;
ret += patchProtoNandSignatureCheck(process9Offset, process9Size);
//Arm9 exception handlers
ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size);
//Apply EmuNAND patches
if(nandType != FIRMWARE_SYSNAND) ret += patchProtoEmuNand(process9Offset, process9Size);
return ret;
}
void launchFirm(int argc, char **argv)
{
u32 *chainloaderAddress = (u32 *)0x01FF9000;
prepareArm11ForFirmlaunch();
memcpy(chainloaderAddress, chainloader_bin, chainloader_bin_size);
// No need to flush caches here, the chainloader is in ITCM
((void (*)(int, char **, Firm *))chainloaderAddress)(argc, argv, firm);
chainload(argc, argv, firm);
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -31,8 +31,9 @@
u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode);
void loadHomebrewFirm(u32 pressed);
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isFirmProtEnabled, bool isSafeMode, bool doUnitinfoPatch);
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isFirmProtEnabled, bool needToInitSd, bool doUnitinfoPatch);
u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch);
u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch);
u32 patch1x2xNativeAndSafeFirm(void);
u32 patchPrototypeNative(FirmwareSource nandType);
void launchFirm(int argc, char **argv);

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -59,7 +59,7 @@ This code is based on a file that contains the following:
//TuxSH's changes: add support for 64-bit numbers, remove floating-point code
#include "strings.h"
#include "memory.h"
#include "fmt.h"
#define ZEROPAD (1<<0) //Pad with zero
@ -148,7 +148,7 @@ static char *processNumber(char *str, s64 num, bool isHex, s32 size, s32 precisi
return str;
}
u32 vsprintf(char *buf, const char *fmt, va_list args)
int vsprintf(char *buf, const char *fmt, va_list args)
{
char *str;
@ -306,14 +306,14 @@ u32 vsprintf(char *buf, const char *fmt, va_list args)
}
*str = 0;
return str - buf;
return (int)(str - buf);
}
u32 sprintf(char *buf, const char *fmt, ...)
int sprintf(char *buf, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
u32 res = vsprintf(buf, fmt, args);
int res = vsprintf(buf, fmt, args);
va_end(args);
return res;
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -28,5 +28,5 @@
#include "memory.h"
#include <stdarg.h>
u32 vsprintf(char *buf, const char *fmt, va_list args);
u32 sprintf(char *buf, const char *fmt, ...);
int vsprintf(char *buf, const char *fmt, va_list args);
int sprintf(char *buf, const char *fmt, ...);

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2021 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -26,7 +26,6 @@
#include "fs.h"
#include "memory.h"
#include "strings.h"
#include "fmt.h"
#include "crypto.h"
#include "cache.h"
@ -37,7 +36,9 @@
#include "buttons.h"
#include "firm.h"
#include "crypto.h"
#include "../build/bundled.h"
#include "strings.h"
#include "alignedseqmemcpy.h"
#include "i2c.h"
static FATFS sdFs,
nandFs;
@ -51,16 +52,50 @@ static bool switchToMainDir(bool isSd)
case FR_OK:
return true;
case FR_NO_PATH:
return f_mkdir(mainDir) == FR_OK && switchToMainDir(isSd);
{
if (f_mkdir(mainDir) != FR_OK)
{
error("Failed to create luma directory.");
return false;
}
return switchToMainDir(isSd);
}
default:
return false;
}
}
bool mountFs(bool isSd, bool switchToCtrNand)
bool mountSdCardPartition(bool switchMainDir)
{
return isSd ? f_mount(&sdFs, "0:", 1) == FR_OK && switchToMainDir(true) :
f_mount(&nandFs, "1:", 1) == FR_OK && (!switchToCtrNand || (f_chdrive("1:") == FR_OK && switchToMainDir(false)));
static bool sdInitialized = false;
if (!sdInitialized)
sdInitialized = f_mount(&sdFs, "sdmc:", 1) == FR_OK;
if (sdInitialized && switchMainDir)
return f_chdrive("sdmc:") == FR_OK && switchToMainDir(true);
return sdInitialized;
}
bool remountCtrNandPartition(bool switchMainDir)
{
static bool nandInitialized = false;
int res = FR_OK;
if (!nandInitialized)
{
res = f_mount(&nandFs, "nand:", 1);
nandInitialized = res == FR_OK;
}
if (nandInitialized && switchMainDir)
return f_chdrive("nand:") == FR_OK && switchToMainDir(false);
return nandInitialized;
}
void unmountPartitions(void)
{
f_unmount("nand:");
f_unmount("sdmc:");
}
u32 fileRead(void *dest, const char *path, u32 maxSize)
@ -88,7 +123,7 @@ u32 getFileSize(const char *path)
bool fileWrite(const void *buffer, const char *path, u32 size)
{
FIL file;
FRESULT result;
FRESULT result = FR_OK;
switch(f_open(&file, path, FA_WRITE | FA_OPEN_ALWAYS))
{
@ -102,6 +137,7 @@ bool fileWrite(const void *buffer, const char *path, u32 size)
return result == FR_OK && (u32)written == size;
}
case FR_NO_PATH:
// Only create the last dir in the hierarchy
for(u32 i = 1; path[i] != 0; i++)
if(path[i] == '/')
{
@ -122,6 +158,86 @@ bool fileDelete(const char *path)
return f_unlink(path) == FR_OK;
}
bool fileCopy(const char *pathSrc, const char *pathDst, bool replace, void *tmpBuffer, size_t bufferSize)
{
FIL fileSrc, fileDst;
FRESULT res;
res = f_open(&fileSrc, pathSrc, FA_READ);
if (res != FR_OK)
return true; // Succeed if the source file doesn't exist
size_t szSrc = f_size(&fileSrc), rem = szSrc;
res = f_open(&fileDst, pathDst, FA_WRITE | (replace ? FA_CREATE_ALWAYS : FA_CREATE_NEW));
if (res == FR_EXIST)
{
// We did not fail
f_close(&fileSrc);
return true;
}
else if (res == FR_NO_PATH)
{
// Only create the last dir in the hierarchy
const char *c;
for (c = pathDst + strlen(pathDst); *c != '/' && c >= pathDst; --c);
if (c >= pathDst && c - pathDst <= FF_MAX_LFN && *c != '\0')
{
char path[FF_MAX_LFN + 1];
strncpy(path, pathDst, c - pathDst);
path[c - pathDst] = '\0';
res = f_mkdir(path);
}
if (res == FR_OK)
res = f_open(&fileDst, pathDst, FA_WRITE | (replace ? FA_CREATE_ALWAYS : FA_CREATE_NEW));
}
if (res != FR_OK)
{
f_close(&fileSrc);
return false;
}
while (rem > 0)
{
size_t sz = rem >= bufferSize ? bufferSize : rem;
UINT n = 0;
res = f_read(&fileSrc, tmpBuffer, sz, &n);
if (n != sz)
res = FR_INT_ERR; // should not happen
if (res == FR_OK)
{
res = f_write(&fileDst, tmpBuffer, sz, &n);
if (n != sz)
res = FR_DENIED; // disk full
}
if (res != FR_OK)
{
f_close(&fileSrc);
f_close(&fileDst);
f_unlink(pathDst); // oops, failed
return false;
}
rem -= sz;
}
f_close(&fileSrc);
f_close(&fileDst);
return true;
}
bool createDir(const char *path)
{
FRESULT res = f_mkdir(path);
return res == FR_OK || res == FR_EXIST;
}
bool findPayload(char *path, u32 pressed)
{
const char *pattern;
@ -155,10 +271,11 @@ bool findPayload(char *path, u32 pressed)
return true;
}
bool payloadMenu(char *path)
bool payloadMenu(char *path, bool *hasDisplayedMenu)
{
DIR dir;
*hasDisplayedMenu = false;
if(f_opendir(&dir, "payloads") != FR_OK) return false;
FILINFO info;
@ -190,6 +307,7 @@ bool payloadMenu(char *path)
if(payloadNum != 1)
{
initScreens();
*hasDisplayedMenu = true;
drawString(true, 10, 10, COLOR_TITLE, "Luma3DS chainloader");
drawString(true, 10, 10 + SPACING_Y, COLOR_TITLE, "Press A to select, START to quit");
@ -256,10 +374,10 @@ u32 firmRead(void *dest, u32 firmType)
{"00000003", "20000003"},
{"00000001", "20000001"}};
char folderPath[35],
path[48];
char folderPath[64],
path[128];
sprintf(folderPath, "1:/title/00040138/%s/content", firmFolders[firmType][ISN3DS ? 1 : 0]);
sprintf(folderPath, "nand:/title/00040138/%s/content", firmFolders[firmType][ISN3DS ? 1 : 0]);
DIR dir;
u32 firmVersion = 0xFFFFFFFF;
@ -283,7 +401,7 @@ u32 firmRead(void *dest, u32 firmType)
if(f_closedir(&dir) != FR_OK || firmVersion == 0xFFFFFFFF) goto exit;
//Complete the string with the .app name
sprintf(path, "%s/%08x.app", folderPath, firmVersion);
sprintf(path, "%s/%08lx.app", folderPath, firmVersion);
if(fileRead(dest, path, 0x400000 + sizeof(Cxi) + 0x200) <= sizeof(Cxi) + 0x400) firmVersion = 0xFFFFFFFF;
@ -300,7 +418,7 @@ void findDumpFile(const char *folderPath, char *fileName)
{
FILINFO info;
sprintf(fileName, "crash_dump_%08u.dmp", n);
sprintf(fileName, "crash_dump_%08lu.dmp", n);
result = f_findfirst(&dir, &info, folderPath, fileName);
if(result != FR_OK || !info.fname[0]) break;
@ -308,3 +426,104 @@ void findDumpFile(const char *folderPath, char *fileName)
if(result == FR_OK) f_closedir(&dir);
}
static u8 fileCopyBuffer[0x10000];
static const u8 boot9Sha256[32] = {
0x2F, 0x88, 0x74, 0x4F, 0xEE, 0xD7, 0x17, 0x85, 0x63, 0x86, 0x40, 0x0A, 0x44, 0xBB, 0xA4, 0xB9,
0xCA, 0x62, 0xE7, 0x6A, 0x32, 0xC7, 0x15, 0xD4, 0xF3, 0x09, 0xC3, 0x99, 0xBF, 0x28, 0x16, 0x6F
};
static const u8 boot11Sha256[32] = {
0x74, 0xDA, 0xAC, 0xE1, 0xF8, 0x06, 0x7B, 0x66, 0xCC, 0x81, 0xFC, 0x30, 0x7A, 0x3F, 0xDB, 0x50,
0x9C, 0xBE, 0xDC, 0x32, 0xF9, 0x03, 0xAE, 0xBE, 0x90, 0x61, 0x44, 0xDE, 0xA7, 0xA0, 0x75, 0x12
};
static bool backupEssentialFiles(void)
{
size_t sz = sizeof(fileCopyBuffer);
u32 deviceID = *(vu32*)0x01FFB804;
char pathStart[0x20];
sprintf(pathStart, "backups/%08lX/", deviceID);
char fullPath[0x80];
// Since the other funcs in this file don't create directories recursively (only the last one),
// and nor does f_mkdir, create the directories anyway and ignore the result
f_mkdir("backups");
f_mkdir(pathStart);
bool ok = true;
sprintf(fullPath, "%sHWCAL0.dat", pathStart);
ok = ok && fileCopy("nand:/ro/sys/HWCAL0.dat", fullPath, false, fileCopyBuffer, sz);
sprintf(fullPath, "%sHWCAL1.dat", pathStart);
ok = ok && fileCopy("nand:/ro/sys/HWCAL1.dat", fullPath, false, fileCopyBuffer, sz);
sprintf(fullPath, "%sLocalFriendCodeSeed_A", pathStart);
ok = ok && fileCopy("nand:/rw/sys/LocalFriendCodeSeed_A", fullPath, false, fileCopyBuffer, sz); // often doesn't exist
sprintf(fullPath, "%sLocalFriendCodeSeed_B", pathStart);
ok = ok && fileCopy("nand:/rw/sys/LocalFriendCodeSeed_B", fullPath, false, fileCopyBuffer, sz);
sprintf(fullPath, "%sSecureInfo_A", pathStart);
ok = ok && fileCopy("nand:/rw/sys/SecureInfo_A", fullPath, false, fileCopyBuffer, sz);
sprintf(fullPath, "%sSecureInfo_B", pathStart);
ok = ok && fileCopy("nand:/rw/sys/SecureInfo_B", fullPath, false, fileCopyBuffer, sz); // often doesn't exist
if (!ok) return false;
alignedseqmemcpy(fileCopyBuffer, (const void *)0x10012000, 0x100);
sprintf(fullPath, "%sotp.bin", pathStart);
if (getFileSize(fullPath) != 0x100)
ok = ok && fileWrite(fileCopyBuffer, fullPath, 0x100);
if (!ok) return false;
// On dev boards, but not O3DS IS_DEBUGGER, hwcal is on an EEPROM chip accessed via I2C
u8 c = mcuConsoleInfo[0];
if (c == 2 || c == 4 || (ISN3DS && c == 5) || c == 6)
{
sprintf(fullPath, "%sHWCAL_01_EEPROM.dat", pathStart);
I2C_readRegBuf(I2C_DEV_EEPROM, 0, fileCopyBuffer, 0x1000); // Up to two instances of hwcal, with the second one @0x800
if (getFileSize(fullPath) != 0x1000)
ok = ok && fileWrite(fileCopyBuffer, fullPath, 0x1000);
}
// B9S bootrom backups
u32 hash[32/4];
sha(hash, (const void *)0x08080000, 0x10000, SHA_256_MODE);
sprintf(fullPath, "%sboot9.bin", pathStart);
if (memcmp(hash, boot9Sha256, 32) == 0 && getFileSize(fullPath) != 0x10000)
ok = ok && fileWrite((const void *)0x08080000, fullPath, 0x10000);
sha(hash, (const void *)0x08090000, 0x10000, SHA_256_MODE);
sprintf(fullPath, "%sboot11.bin", pathStart);
if (memcmp(hash, boot11Sha256, 32) == 0 && getFileSize(fullPath) != 0x10000)
ok = ok && fileWrite((const void *)0x08090000, fullPath, 0x10000);
return ok;
}
bool doLumaUpgradeProcess(void)
{
bool ok = true, ok2 = true;
// Ensure CTRNAND is mounted
remountCtrNandPartition(false);
// Try to boot.firm to CTRNAND, when applicable
#ifndef BUILD_FOR_EXPLOIT_DEV
if (isSdMode && memcmp(launchedPathForFatfs, "sdmc:", 5) == 0)
ok = fileCopy(launchedPathForFatfs, "nand:/boot.firm", true, fileCopyBuffer, sizeof(fileCopyBuffer));
#endif
// Try to backup essential files
ok2 = backupEssentialFiles();
// Clean up some of the old files
fileDelete("sdmc:/luma/config.bin");
fileDelete("nand:/rw/luma/config.bin");
createDir("sdmc:/luma/payloads");
createDir("nand:/rw/luma/payloads");
return ok && ok2;
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2021 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -30,12 +30,19 @@
#define PATTERN(a) a "_*.firm"
bool mountFs(bool isSd, bool switchToCtrNand);
bool mountSdCardPartition(bool switchMainDir);
bool remountCtrNandPartition(bool switchMainDir);
void unmountPartitions(void);
u32 fileRead(void *dest, const char *path, u32 maxSize);
u32 getFileSize(const char *path);
bool fileWrite(const void *buffer, const char *path, u32 size);
bool fileDelete(const char *path);
bool fileCopy(const char *pathSrc, const char *pathDst, bool replace, void *tmpBuffer, size_t bufferSize);
bool createDir(const char *path);
bool findPayload(char *path, u32 pressed);
bool payloadMenu(char *path);
bool payloadMenu(char *path, bool *hasDisplayedMenu);
u32 firmRead(void *dest, u32 firmType);
void findDumpFile(const char *folderPath, char *fileName);
bool doLumaUpgradeProcess(void);

225
arm9/source/i2c.c Normal file
View File

@ -0,0 +1,225 @@
/*
* This file is part of fastboot 3DS
* Copyright (C) 2017 derrek, profi200
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include "types.h"
#include "i2c.h"
#include "utils.h"
#define I2C1_REGS_BASE (0x10161000)
#define I2C2_REGS_BASE (0x10144000)
#define I2C3_REGS_BASE (0x10148000)
typedef struct
{
vu8 REG_I2C_DATA;
vu8 REG_I2C_CNT;
vu16 REG_I2C_CNTEX;
vu16 REG_I2C_SCL;
} I2cRegs;
static const struct
{
u8 busId;
u8 devAddr;
} i2cDevTable[] =
{
{0, 0x4A},
{0, 0x7A},
{0, 0x78},
{1, 0x4A},
{1, 0x78},
{1, 0x2C},
{1, 0x2E},
{1, 0x40},
{1, 0x44},
{2, 0xA6}, // TODO: Find out if 0xA6 or 0xD6 is correct
{2, 0xD0},
{2, 0xD2},
{2, 0xA4},
{2, 0x9A},
{2, 0xA0},
{1, 0xEE},
{0, 0x40},
{2, 0x54}
};
static void i2cWaitBusy(I2cRegs *const regs)
{
while(regs->REG_I2C_CNT & I2C_ENABLE);
}
static I2cRegs* i2cGetBusRegsBase(u8 busId)
{
I2cRegs *base;
switch(busId)
{
case 0:
base = (I2cRegs*)I2C1_REGS_BASE;
break;
case 1:
base = (I2cRegs*)I2C2_REGS_BASE;
break;
case 2:
base = (I2cRegs*)I2C3_REGS_BASE;
break;
default:
base = NULL;
}
return base;
}
void I2C_init(void)
{
I2cRegs *regs = i2cGetBusRegsBase(0); // Bus 1
i2cWaitBusy(regs);
regs->REG_I2C_CNTEX = 2; // ?
regs->REG_I2C_SCL = 1280; // ?
regs = i2cGetBusRegsBase(1); // Bus 2
i2cWaitBusy(regs);
regs->REG_I2C_CNTEX = 2; // ?
regs->REG_I2C_SCL = 1280; // ?
regs = i2cGetBusRegsBase(2); // Bus 3
i2cWaitBusy(regs);
regs->REG_I2C_CNTEX = 2; // ?
regs->REG_I2C_SCL = 1280; // ?
}
static bool i2cStartTransfer(I2cDevice devId, u8 regAddr, bool read, I2cRegs *const regs)
{
const u8 devAddr = i2cDevTable[devId].devAddr;
u32 i = 0;
for(; i < 8; i++)
{
i2cWaitBusy(regs);
// Select device and start.
regs->REG_I2C_DATA = devAddr;
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_START;
i2cWaitBusy(regs);
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
{
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
continue;
}
// Select register and change direction to write.
regs->REG_I2C_DATA = regAddr;
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE;
i2cWaitBusy(regs);
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
{
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
continue;
}
// Select device in read mode for read transfer.
if(read)
{
regs->REG_I2C_DATA = devAddr | 1u; // Set bit 0 for read.
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_START;
i2cWaitBusy(regs);
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
{
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
continue;
}
}
break;
}
if(i < 8) return true;
else return false;
}
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
{
const u8 busId = i2cDevTable[devId].busId;
I2cRegs *const regs = i2cGetBusRegsBase(busId);
if(!i2cStartTransfer(devId, regAddr, true, regs)) return false;
while(--size)
{
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_ACK;
i2cWaitBusy(regs);
*out++ = regs->REG_I2C_DATA;
}
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_STOP;
i2cWaitBusy(regs);
*out = regs->REG_I2C_DATA; // Last byte
return true;
}
bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size)
{
const u8 busId = i2cDevTable[devId].busId;
I2cRegs *const regs = i2cGetBusRegsBase(busId);
if(!i2cStartTransfer(devId, regAddr, false, regs)) return false;
while(--size)
{
regs->REG_I2C_DATA = *in++;
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE;
i2cWaitBusy(regs);
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
{
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
return false;
}
}
regs->REG_I2C_DATA = *in;
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE | I2C_STOP;
i2cWaitBusy(regs);
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
{
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
return false;
}
return true;
}
u8 I2C_readReg(I2cDevice devId, u8 regAddr)
{
u8 data;
if(!I2C_readRegBuf(devId, regAddr, &data, 1)) return 0xFF;
return data;
}
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data)
{
return I2C_writeRegBuf(devId, regAddr, &data, 1);
}

104
arm9/source/i2c.h Normal file
View File

@ -0,0 +1,104 @@
#pragma once
/*
* This file is part of fastboot 3DS
* Copyright (C) 2017 derrek, profi200
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include "types.h"
#define I2C_STOP (1u)
#define I2C_START (1u<<1)
#define I2C_ERROR (1u<<2)
#define I2C_ACK (1u<<4)
#define I2C_DIRE_WRITE (0u)
#define I2C_DIRE_READ (1u<<5)
#define I2C_IRQ_ENABLE (1u<<6)
#define I2C_ENABLE (1u<<7)
#define I2C_GET_ACK(reg) ((bool)((reg)>>4 & 1u))
typedef enum
{
I2C_DEV_POWER = 0, // Unconfirmed
I2C_DEV_CAMERA = 1, // Unconfirmed
I2C_DEV_CAMERA2 = 2, // Unconfirmed
I2C_DEV_MCU = 3,
I2C_DEV_LCD_TOP = 5,
I2C_DEV_LCD_BOT = 6,
I2C_DEV_GYRO = 10,
I2C_DEV_DEBUG_PAD = 12,
I2C_DEV_IR = 13,
I2C_DEV_EEPROM = 14, // Unconfirmed
I2C_DEV_NFC = 15,
I2C_DEV_QTM = 16,
I2C_DEV_N3DS_HID = 17
} I2cDevice;
/**
* @brief Initializes the I2C buses. Call this only once.
*/
void I2C_init(void);
/**
* @brief Reads data from a I2C register to a buffer.
*
* @param[in] devId The device ID. Use the enum above.
* @param[in] regAddr The register address.
* @param out The output buffer pointer.
* @param[in] size The read size.
*
* @return Returns true on success and false on failure.
*/
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size);
/**
* @brief Writes a buffer to a I2C register.
*
* @param[in] devId The device ID. Use the enum above.
* @param[in] regAddr The register address.
* @param[in] in The input buffer pointer.
* @param[in] size The write size.
*
* @return Returns true on success and false on failure.
*/
bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size);
/**
* @brief Reads a byte from a I2C register.
*
* @param[in] devId The device ID. Use the enum above.
* @param[in] regAddr The register address.
*
* @return Returns the value read on success otherwise 0xFF.
*/
u8 I2C_readReg(I2cDevice devId, u8 regAddr);
/**
* @brief Writes a byte to a I2C register.
*
* @param[in] devId The device ID. Use the enum above.
* @param[in] regAddr The register address.
* @param[in] data The data to write.
*
* @return Returns true on success and false on failure.
*/
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data);

298
arm9/source/ini.c Normal file
View File

@ -0,0 +1,298 @@
/* inih -- simple .INI file parser
SPDX-License-Identifier: BSD-3-Clause
Copyright (C) 2009-2020, Ben Hoyt
inih is released under the New BSD license (see LICENSE.txt). Go to the project
home page for more info:
https://github.com/benhoyt/inih
*/
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "ini.h"
#if !INI_USE_STACK
#if INI_CUSTOM_ALLOCATOR
#include <stddef.h>
void* ini_malloc(size_t size);
void ini_free(void* ptr);
void* ini_realloc(void* ptr, size_t size);
#else
#include <stdlib.h>
#define ini_malloc malloc
#define ini_free free
#define ini_realloc realloc
#endif
#endif
#define MAX_SECTION 50
#define MAX_NAME 50
/* Used by ini_parse_string() to keep track of string parsing state. */
typedef struct {
const char* ptr;
size_t num_left;
} ini_parse_string_ctx;
/* Strip whitespace chars off end of given string, in place. Return s. */
static char* rstrip(char* s)
{
char* p = s + strlen(s);
while (p > s && isspace((unsigned char)(*--p)))
*p = '\0';
return s;
}
/* Return pointer to first non-whitespace char in given string. */
static char* lskip(const char* s)
{
while (*s && isspace((unsigned char)(*s)))
s++;
return (char*)s;
}
/* Return pointer to first char (of chars) or inline comment in given string,
or pointer to NUL at end of string if neither found. Inline comment must
be prefixed by a whitespace character to register as a comment. */
static char* find_chars_or_comment(const char* s, const char* chars)
{
#if INI_ALLOW_INLINE_COMMENTS
int was_space = 0;
while (*s && (!chars || !strchr(chars, *s)) &&
!(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) {
was_space = isspace((unsigned char)(*s));
s++;
}
#else
while (*s && (!chars || !strchr(chars, *s))) {
s++;
}
#endif
return (char*)s;
}
/* Similar to strncpy, but ensures dest (size bytes) is
NUL-terminated, and doesn't pad with NULs. */
static char* strncpy0(char* dest, const char* src, size_t size)
{
/* Could use strncpy internally, but it causes gcc warnings (see issue #91) */
size_t i;
for (i = 0; i < size - 1 && src[i]; i++)
dest[i] = src[i];
dest[i] = '\0';
return dest;
}
/* See documentation in header file. */
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
void* user)
{
/* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
char line[INI_MAX_LINE];
int max_line = INI_MAX_LINE;
#else
char* line;
size_t max_line = INI_INITIAL_ALLOC;
#endif
#if INI_ALLOW_REALLOC && !INI_USE_STACK
char* new_line;
size_t offset;
#endif
char section[MAX_SECTION] = "";
char prev_name[MAX_NAME] = "";
char* start;
char* end;
char* name;
char* value;
int lineno = 0;
int error = 0;
#if !INI_USE_STACK
line = (char*)ini_malloc(INI_INITIAL_ALLOC);
if (!line) {
return -2;
}
#endif
#if INI_HANDLER_LINENO
#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno)
#else
#define HANDLER(u, s, n, v) handler(u, s, n, v)
#endif
/* Scan through stream line by line */
while (reader(line, (int)max_line, stream) != NULL) {
#if INI_ALLOW_REALLOC && !INI_USE_STACK
offset = strlen(line);
while (offset == max_line - 1 && line[offset - 1] != '\n') {
max_line *= 2;
if (max_line > INI_MAX_LINE)
max_line = INI_MAX_LINE;
new_line = ini_realloc(line, max_line);
if (!new_line) {
ini_free(line);
return -2;
}
line = new_line;
if (reader(line + offset, (int)(max_line - offset), stream) == NULL)
break;
if (max_line >= INI_MAX_LINE)
break;
offset += strlen(line + offset);
}
#endif
lineno++;
start = line;
#if INI_ALLOW_BOM
if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
(unsigned char)start[1] == 0xBB &&
(unsigned char)start[2] == 0xBF) {
start += 3;
}
#endif
start = lskip(rstrip(start));
if (strchr(INI_START_COMMENT_PREFIXES, *start)) {
/* Start-of-line comment */
}
#if INI_ALLOW_MULTILINE
else if (*prev_name && *start && start > line) {
/* Non-blank line with leading whitespace, treat as continuation
of previous name's value (as per Python configparser). */
if (!HANDLER(user, section, prev_name, start) && !error)
error = lineno;
}
#endif
else if (*start == '[') {
/* A "[section]" line */
end = find_chars_or_comment(start + 1, "]");
if (*end == ']') {
*end = '\0';
strncpy0(section, start + 1, sizeof(section));
*prev_name = '\0';
#if INI_CALL_HANDLER_ON_NEW_SECTION
if (!HANDLER(user, section, NULL, NULL) && !error)
error = lineno;
#endif
}
else if (!error) {
/* No ']' found on section line */
error = lineno;
}
}
else if (*start) {
/* Not a comment, must be a name[=:]value pair */
end = find_chars_or_comment(start, "=:");
if (*end == '=' || *end == ':') {
*end = '\0';
name = rstrip(start);
value = end + 1;
#if INI_ALLOW_INLINE_COMMENTS
end = find_chars_or_comment(value, NULL);
if (*end)
*end = '\0';
#endif
value = lskip(value);
rstrip(value);
/* Valid name[=:]value pair found, call handler */
strncpy0(prev_name, name, sizeof(prev_name));
if (!HANDLER(user, section, name, value) && !error)
error = lineno;
}
else if (!error) {
/* No '=' or ':' found on name[=:]value line */
#if INI_ALLOW_NO_VALUE
*end = '\0';
name = rstrip(start);
if (!HANDLER(user, section, name, NULL) && !error)
error = lineno;
#else
error = lineno;
#endif
}
}
#if INI_STOP_ON_FIRST_ERROR
if (error)
break;
#endif
}
#if !INI_USE_STACK
ini_free(line);
#endif
return error;
}
/* See documentation in header file. */
int ini_parse_file(FILE* file, ini_handler handler, void* user)
{
return ini_parse_stream((ini_reader)fgets, file, handler, user);
}
/* See documentation in header file. */
int ini_parse(const char* filename, ini_handler handler, void* user)
{
FILE* file;
int error;
file = fopen(filename, "r");
if (!file)
return -1;
error = ini_parse_file(file, handler, user);
fclose(file);
return error;
}
/* An ini_reader function to read the next line from a string buffer. This
is the fgets() equivalent used by ini_parse_string(). */
static char* ini_reader_string(char* str, int num, void* stream) {
ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream;
const char* ctx_ptr = ctx->ptr;
size_t ctx_num_left = ctx->num_left;
char* strp = str;
char c;
if (ctx_num_left == 0 || num < 2)
return NULL;
while (num > 1 && ctx_num_left != 0) {
c = *ctx_ptr++;
ctx_num_left--;
*strp++ = c;
if (c == '\n')
break;
num--;
}
*strp = '\0';
ctx->ptr = ctx_ptr;
ctx->num_left = ctx_num_left;
return str;
}
/* See documentation in header file. */
int ini_parse_string(const char* string, ini_handler handler, void* user) {
ini_parse_string_ctx ctx;
ctx.ptr = string;
ctx.num_left = strlen(string);
return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler,
user);
}

157
arm9/source/ini.h Normal file
View File

@ -0,0 +1,157 @@
/* inih -- simple .INI file parser
SPDX-License-Identifier: BSD-3-Clause
Copyright (C) 2009-2020, Ben Hoyt
inih is released under the New BSD license (see LICENSE.txt). Go to the project
home page for more info:
https://github.com/benhoyt/inih
*/
#ifndef INI_H
#define INI_H
/* Make this header file easier to include in C++ code */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
/* Nonzero if ini_handler callback should accept lineno parameter. */
#ifndef INI_HANDLER_LINENO
#define INI_HANDLER_LINENO 0
#endif
/* Typedef for prototype of handler function. */
#if INI_HANDLER_LINENO
typedef int (*ini_handler)(void* user, const char* section,
const char* name, const char* value,
int lineno);
#else
typedef int (*ini_handler)(void* user, const char* section,
const char* name, const char* value);
#endif
/* Typedef for prototype of fgets-style reader function. */
typedef char* (*ini_reader)(char* str, int num, void* stream);
/* Parse given INI-style file. May have [section]s, name=value pairs
(whitespace stripped), and comments starting with ';' (semicolon). Section
is "" if name=value pair parsed before any section heading. name:value
pairs are also supported as a concession to Python's configparser.
For each name=value pair parsed, call handler function with given user
pointer as well as section, name, and value (data only valid for duration
of handler call). Handler should return nonzero on success, zero on error.
Returns 0 on success, line number of first error on parse error (doesn't
stop on first error), -1 on file open error, or -2 on memory allocation
error (only when INI_USE_STACK is zero).
*/
int ini_parse(const char* filename, ini_handler handler, void* user);
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
close the file when it's finished -- the caller must do that. */
int ini_parse_file(FILE* file, ini_handler handler, void* user);
/* Same as ini_parse(), but takes an ini_reader function pointer instead of
filename. Used for implementing custom or string-based I/O (see also
ini_parse_string). */
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
void* user);
/* Same as ini_parse(), but takes a zero-terminated string with the INI data
instead of a file. Useful for parsing INI data from a network socket or
already in memory. */
int ini_parse_string(const char* string, ini_handler handler, void* user);
/* Nonzero to allow multi-line value parsing, in the style of Python's
configparser. If allowed, ini_parse() will call the handler with the same
name for each subsequent line parsed. */
#ifndef INI_ALLOW_MULTILINE
#define INI_ALLOW_MULTILINE 1
#endif
/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
the file. See https://github.com/benhoyt/inih/issues/21 */
#ifndef INI_ALLOW_BOM
#define INI_ALLOW_BOM 1
#endif
/* Chars that begin a start-of-line comment. Per Python configparser, allow
both ; and # comments at the start of a line by default. */
#ifndef INI_START_COMMENT_PREFIXES
#define INI_START_COMMENT_PREFIXES ";#"
#endif
/* Nonzero to allow inline comments (with valid inline comment characters
specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match
Python 3.2+ configparser behaviour. */
#ifndef INI_ALLOW_INLINE_COMMENTS
#define INI_ALLOW_INLINE_COMMENTS 1
#endif
#ifndef INI_INLINE_COMMENT_PREFIXES
#define INI_INLINE_COMMENT_PREFIXES ";"
#endif
/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */
#ifndef INI_USE_STACK
#define INI_USE_STACK 1
#endif
/* Maximum line length for any line in INI file (stack or heap). Note that
this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */
#ifndef INI_MAX_LINE
#define INI_MAX_LINE 200
#endif
/* Nonzero to allow heap line buffer to grow via realloc(), zero for a
fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is
zero. */
#ifndef INI_ALLOW_REALLOC
#define INI_ALLOW_REALLOC 0
#endif
/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK
is zero. */
#ifndef INI_INITIAL_ALLOC
#define INI_INITIAL_ALLOC 200
#endif
/* Stop parsing on first error (default is to keep parsing). */
#ifndef INI_STOP_ON_FIRST_ERROR
#define INI_STOP_ON_FIRST_ERROR 0
#endif
/* Nonzero to call the handler at the start of each new section (with
name and value NULL). Default is to only call the handler on
each name=value pair. */
#ifndef INI_CALL_HANDLER_ON_NEW_SECTION
#define INI_CALL_HANDLER_ON_NEW_SECTION 0
#endif
/* Nonzero to allow a name without a value (no '=' or ':' on the line) and
call the handler with value NULL in this case. Default is to treat
no-value lines as an error. */
#ifndef INI_ALLOW_NO_VALUE
#define INI_ALLOW_NO_VALUE 0
#endif
/* Nonzero to use custom ini_malloc, ini_free, and ini_realloc memory
allocation functions (INI_USE_STACK must also be 0). These functions must
have the same signatures as malloc/free/realloc and behave in a similar
way. ini_realloc is only needed if INI_ALLOW_REALLOC is set. */
#ifndef INI_CUSTOM_ALLOCATOR
#define INI_CUSTOM_ALLOCATOR 0
#endif
#ifdef __cplusplus
}
#endif
#endif /* INI_H */

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -28,23 +28,13 @@
#include "types.h"
typedef struct __attribute__((packed))
{
u32 offset;
u8 *address;
u32 size;
u32 procType;
u8 hash[0x20];
} FirmSection;
extern const u8 emunandPatch[], emunandProtoPatch[], emunandProtoCidPatch[];
extern const u8 emunandProtoPatch238[];
extern const u32 emunandPatchSize, emunandPatchBssSize;
extern u32 emunandPatchSdmmcStructPtr, emunandPatchNandOffset, emunandPatchNcsdHeaderOffset;
extern u32 emunandPatchNandCid[4];
typedef struct __attribute__((packed))
{
char magic[4];
u32 reserved1;
u8 *arm11Entry;
u8 *arm9Entry;
u8 reserved2[0x30];
FirmSection section[4];
} Firm;
void launchFirm(Firm *firm, int argc, char **argv);
extern const u8 rebootPatch[];
extern const u32 rebootPatchSize;
extern u32 rebootPatchFopenPtr;
extern u16 rebootPatchFileName[80+1];

View File

@ -1,26 +1,30 @@
; Code originally from delebile and mid-kid
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.arm.little
@ Code originally from delebile and mid-kid
copy_launch_stub_stack_top equ 0x01FFB800
copy_launch_stub_stack_bottom equ 0x01FFA800
copy_launch_stub_addr equ 0x01FF9000
argv_addr equ (copy_launch_stub_stack_bottom - 0x100)
fname_addr equ (copy_launch_stub_stack_bottom - 0x200)
low_tid_addr equ (copy_launch_stub_stack_bottom - 0x300)
firm_addr equ 0x20001000
firm_maxsize equ 0x07FFF000
.create "build/reboot.bin", 0
.section .large_patch.reboot, "aw", %progbits
.arm
; Interesting registers and locations to keep in mind, set just before this code is ran:
; - r1: FIRM path in exefs.
; - r7 (or r8): pointer to file object
; - *r7: vtable
; - *(vtable + 0x28): fread function
; - *(r7 + 8): file handle
.align 4
#define copy_launch_stub_stack_top 0x01FFB800
#define copy_launch_stub_stack_bottom 0x01FFA800
#define copy_launch_stub_addr 0x01FF9000
#define argv_addr (copy_launch_stub_stack_bottom - 0x100)
#define fname_addr (copy_launch_stub_stack_bottom - 0x200)
#define low_tid_addr (copy_launch_stub_stack_bottom - 0x300)
#define firm_addr 0x20001000
#define firm_maxsize 0x07FFF000
.global rebootPatch
rebootPatch:
@ Interesting registers and locations to keep in mind, set just before this code is ran:
@ - r1: FIRM path in exefs.
@ - r7 (or r8): pointer to file object
@ - *r7: vtable
@ - *(vtable + 0x28): fread function
@ - *(r7 + 8): file handle
sub r7, r0, #8
mov r8, r1
@ -36,17 +40,18 @@ firm_maxsize equ 0x07FFF000
cmp r0, r2
bne pxi_wait_recv
; Open file
@ Open file
add r0, r7, #8
adr r1, fname
adr r1, rebootPatchFileName
mov r2, #1
ldr r6, [fopen]
orr r6, 1
adr r6, rebootPatchFopenPtr
ldr r6, [r6]
orr r6, #1
blx r6
cmp r0, #0
bne panic
; Read file
@ Read file
mov r0, r7
adr r1, bytes_read
ldr r2, =firm_addr
@ -55,15 +60,15 @@ firm_maxsize equ 0x07FFF000
ldr r6, [r6, #0x28]
blx r6
; Copy the low TID (in UTF-16) of the wanted firm
@ Copy the low TID (in UTF-16) of the wanted firm
ldr r0, =low_tid_addr
add r1, r8, #0x1A
mov r2, #0x10
bl memcpy16
; Copy argv[0]
@ Copy argv[0]
ldr r0, =fname_addr
adr r1, fname
adr r1, rebootPatchFileName
mov r2, #82
bl memcpy16
@ -72,18 +77,18 @@ firm_maxsize equ 0x07FFF000
ldr r2, =low_tid_addr
stmia r0, {r1, r2}
; Set kernel state
@ Set kernel state
mov r0, #0
mov r1, #0
mov r2, #0
mov r3, #0
swi 0x7C
svc 0x7C
goto_reboot:
; Jump to reboot code
ldr r0, =(kernelcode_start - goto_reboot - 12)
add r0, pc ; pc is two instructions ahead of the instruction being executed (12 = 2*4 + 4)
swi 0x7B
@ Jump to reboot code
ldr r0, kernel_func_displ
add r0, pc @ pc is two instructions ahead of the instruction being executed (12 = 2*4 + 4)
svc 0x7B
die:
b die
@ -100,23 +105,31 @@ firm_maxsize equ 0x07FFF000
bx lr
panic:
mov r1, r0 ; unused register
mov r1, r0 @ unused register
mov r0, #0
swi 0x3C ; svcBreak(USERBREAK_PANIC)
svc 0x3C @ svcBreak(USERBREAK_PANIC)
b die
bytes_read: .word 0
fopen: .ascii "OPEN"
kernel_func_displ:
.word kernelcode_start - goto_reboot - 12
bytes_read:
.word 0
.global rebootPatchFopenPtr
rebootPatchFopenPtr:
.word 0
.pool
.area 82, 0
fname: .ascii "FILE"
.endarea
.global rebootPatchFileName
rebootPatchFileName:
.skip 2*(80+1)
.align 4
.balign 4
kernelcode_start:
msr cpsr_cxsf, #0xD3 ; disable interrupts and clear flags
msr cpsr_cxsf, #0xD3 @ disable interrupts and clear flags
ldr sp, =copy_launch_stub_stack_top
@ -125,8 +138,8 @@ fname: .ascii "FILE"
mov r2, #(copy_launch_stub_end - copy_launch_stub)
bl memcpy32
; Disable MPU
ldr r0, =0x42078 ; alt vector select, enable itcm
@ Disable MPU
ldr r0, =0x42078 @ alt vector select, enable itcm
mcr p15, 0, r0, c1, c0, 0
bl flushCaches
@ -140,7 +153,7 @@ fname: .ascii "FILE"
mov r5, #0
load_section_loop:
; Such checks. Very ghetto. Wow.
@ Such checks. Very ghetto. Wow.
add r3, r4, #0x40
add r3, r5,lsl #5
add r3, r5,lsl #4
@ -154,13 +167,13 @@ fname: .ascii "FILE"
cmp r5, #4
blo load_section_loop
mov r0, #2 ; argc
ldr r1, =argv_addr ; argv
ldr r2, =0xBABE ; magic word
mov r0, #2 @ argc
ldr r1, =argv_addr @ argv
ldr r2, =0xBABE @ magic word
mov r5, #0x20000000
ldr r6, [r4, #0x08]
str r6, [r5, #-4] ; store arm11 entrypoint
str r6, [r5, #-4] @ store arm11 entrypoint
ldr lr, [r4, #0x0c]
bx lr
@ -180,15 +193,15 @@ fname: .ascii "FILE"
flushCaches:
; Clean and flush data cache
mov r1, #0 ; segment counter
@ Clean and flush data cache
mov r1, #0 @ segment counter
outer_loop:
mov r0, #0 ; line counter
mov r0, #0 @ line counter
inner_loop:
orr r2, r1, r0 ; generate segment and line address
mcr p15, 0, r2, c7, c14, 2 ; clean and flush the line
add r0, #0x20 ; increment to next line
orr r2, r1, r0 @ generate segment and line address
mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line
add r0, #0x20 @ increment to next line
cmp r0, #0x400
bne inner_loop
@ -196,12 +209,19 @@ fname: .ascii "FILE"
cmp r1, #0
bne outer_loop
; Drain write buffer
@ Drain write buffer
mcr p15, 0, r1, c7, c10, 4
; Flush instruction cache
@ Flush instruction cache
mcr p15, 0, r1, c7, c5, 0
bx lr
.close
.pool
.balign 4
_rebootPatchEnd:
.global rebootPatchSize
rebootPatchSize:
.word _rebootPatchEnd - rebootPatch

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2023 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -31,32 +31,44 @@
#include "utils.h"
#include "exceptions.h"
#include "draw.h"
#include "strings.h"
#include "buttons.h"
#include "pin.h"
#include "crypto.h"
#include "memory.h"
#include "deliver_arg.h"
#include "screen.h"
#include "i2c.h"
#include "fmt.h"
#include "fatfs/sdmmc/sdmmc.h"
extern u8 __itcm_start__[], __itcm_lma__[], __itcm_bss_start__[], __itcm_end__[];
extern CfgData configData;
extern ConfigurationStatus needConfig;
extern FirmwareSource firmSource;
bool isSdMode;
u16 launchedPath[41];
char launchedPathForFatfs[256];
u16 launchedPath[80+1];
BootType bootType;
u16 mcuFwVersion;
u8 mcuConsoleInfo[9];
void main(int argc, char **argv, u32 magicWord)
{
bool isFirmProtEnabled,
bool isFirmProtEnabled = true,
isSafeMode = false,
needToInitSd = false,
isNoForceFlagSet = false,
isNtrBoot;
FirmwareType firmType;
FirmwareSource nandType;
isInvalidLoader = false,
isNtrBoot = false;
FirmwareType firmType = NATIVE_FIRM;
FirmwareSource nandType = FIRMWARE_SYSNAND;
u32 emunandIndex = 0;
const vu8 *bootMediaStatus = (const vu8 *)0x1FFFE00C;
const vu32 *bootPartitionsStatus = (const vu32 *)0x1FFFE010;
u32 firmlaunchTidLow = 0;
//Shell closed, no error booting NTRCARD, NAND paritions not even considered
isNtrBoot = bootMediaStatus[3] == 2 && !bootMediaStatus[1] && !bootPartitionsStatus[0] && !bootPartitionsStatus[1];
@ -64,9 +76,11 @@ void main(int argc, char **argv, u32 magicWord)
if((magicWord & 0xFFFF) == 0xBEEF && argc >= 1) //Normal (B9S) boot
{
bootType = isNtrBoot ? B9SNTR : B9S;
strncpy(launchedPathForFatfs, argv[0], sizeof(launchedPathForFatfs) - 1);
launchedPathForFatfs[sizeof(launchedPathForFatfs) - 1] = 0;
u32 i;
for(i = 0; i < 40 && argv[0][i] != 0; i++) //Copy and convert the path to UTF-16
for(i = 0; i < sizeof(launchedPath)/2 - 1 && argv[0][i] != 0; i++) //Copy and convert the path to UTF-16
launchedPath[i] = argv[0][i];
launchedPath[i] = 0;
}
@ -76,9 +90,15 @@ void main(int argc, char **argv, u32 magicWord)
u32 i;
u16 *p = (u16 *)argv[0];
for(i = 0; i < 40 && p[i] != 0; i++)
for(i = 0; i < sizeof(launchedPath)/2 - 1 && p[i] != 0; i++)
{
launchedPath[i] = p[i];
launchedPathForFatfs[i] = (u8)p[i]; // UCS-2 to ascii. Meh.
}
launchedPath[i] = 0;
for(i = 0; i < 8; i++)
firmlaunchTidLow = (argv[1][2 * i] > '9' ? argv[1][2 * i] - 'a' + 10 : argv[1][2 * i] - '0') | (firmlaunchTidLow << 4);
}
else if(magicWord == 0xB002) //FIRM/NTRCARD boot
{
@ -99,26 +119,45 @@ void main(int argc, char **argv, u32 magicWord)
for(u32 i = 0; i < 7; i++) //Copy and convert the path to UTF-16
launchedPath[i] = path[i];
strcpy(launchedPathForFatfs, path);
}
setupKeyslots();
}
else error("Launched using an unsupported loader.");
else isInvalidLoader = true;
// Set up the additional sections, overwrites argc
memcpy(__itcm_start__, __itcm_lma__, __itcm_bss_start__ - __itcm_start__);
memset(__itcm_bss_start__, 0, __itcm_end__ - __itcm_bss_start__);
I2C_init();
u8 mcuFwVerHi = I2C_readReg(I2C_DEV_MCU, 0) - 0x10;
u8 mcuFwVerLo = I2C_readReg(I2C_DEV_MCU, 1);
mcuFwVersion = ((u16)mcuFwVerHi << 16) | mcuFwVerLo;
// Check if fw is older than factory. See https://www.3dbrew.org/wiki/MCU_Services#MCU_firmware_versions for a table
if (mcuFwVerHi < 1) error("Unsupported MCU FW version %d.%d.", (int)mcuFwVerHi, (int)mcuFwVerLo);
I2C_readRegBuf(I2C_DEV_MCU, 0x7F, mcuConsoleInfo, 9);
if(isInvalidLoader) error("Launched using an unsupported loader.");
installArm9Handlers();
if(memcmp(launchedPath, u"sdmc", 8) == 0)
{
if(!mountFs(true, false)) error("Failed to mount SD.");
if(!mountSdCardPartition(true)) error("Failed to mount SD.");
isSdMode = true;
}
else if(memcmp(launchedPath, u"nand", 8) == 0)
{
if(!mountFs(false, true)) error("Failed to mount CTRNAND.");
if(!remountCtrNandPartition(true)) error("Failed to mount CTRNAND.");
isSdMode = false;
}
else if(bootType == NTR || memcmp(launchedPath, u"firm", 8) == 0)
{
if(mountFs(true, false)) isSdMode = true;
else if(mountFs(false, true)) isSdMode = false;
if(mountSdCardPartition(true)) isSdMode = true;
else if(remountCtrNandPartition(true)) isSdMode = false;
else error("Failed to mount SD and CTRNAND.");
if(bootType == NTR)
@ -140,6 +179,8 @@ void main(int argc, char **argv, u32 magicWord)
error("Launched from an unsupported location: %s.", mountPoint);
}
detectAndProcessExceptionDumps();
//Attempt to read the configuration file
needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
@ -148,29 +189,26 @@ void main(int argc, char **argv, u32 magicWord)
{
if(needConfig == CREATE_CONFIGURATION) mcuPowerOff();
switch(argv[1][14])
switch(firmlaunchTidLow & 0xF)
{
case '2':
firmType = (FirmwareType)(argv[1][10] - '0');
case 2:
firmType = (FirmwareType)((firmlaunchTidLow >> 8) & 0xF);
break;
case '3':
case 3:
firmType = SAFE_FIRM;
break;
case '1':
case 1:
firmType = SYSUPDATER_FIRM;
break;
}
nandType = (FirmwareSource)BOOTCFG_NAND;
firmSource = (FirmwareSource)BOOTCFG_FIRM;
emunandIndex = BOOTCFG_EMUINDEX;
isFirmProtEnabled = !BOOTCFG_NTRCARDBOOT;
goto boot;
}
detectAndProcessExceptionDumps();
installArm9Handlers();
firmType = NATIVE_FIRM;
isFirmProtEnabled = bootType != NTR;
@ -180,35 +218,57 @@ void main(int argc, char **argv, u32 magicWord)
//If it's a MCU reboot, try to force boot options
if(CFG_BOOTENV && needConfig != CREATE_CONFIGURATION)
{
u32 bootenv = CFG_BOOTENV;
bool validTlnc = bootenv == 3 && hasValidTlncAutobootParams();
if (validTlnc)
needToInitSd = true;
//Always force a SysNAND boot when quitting AGB_FIRM
if(CFG_BOOTENV == 7)
if(bootenv == 7)
{
nandType = FIRMWARE_SYSNAND;
firmSource = (BOOTCFG_NAND != 0) == (BOOTCFG_FIRM != 0) ? FIRMWARE_SYSNAND : (FirmwareSource)BOOTCFG_FIRM;
//Prevent multiple boot options-forcing
if(nandType != BOOTCFG_NAND || firmSource != BOOTCFG_FIRM) isNoForceFlagSet = true;
// Prevent multiple boot options-forcing
// This bit is a bit weird. Basically, as you return to Home Menu by pressing either
// the HOME or POWER button, nandType will be overridden to "SysNAND" (needed). But,
// if you reboot again (e.g. via Rosalina menu), it'll use your default settings.
if(nandType != BOOTCFG_NAND) isNoForceFlagSet = true;
goto boot;
}
/* Else, force the last used boot options unless a button is pressed
// Configure homebrew autoboot (if deliver arg ends up not containing anything)
if (bootenv == 1 && MULTICONFIG(AUTOBOOTMODE) != 0)
configureHomebrewAutoboot();
/* Force the last used boot options if doing autolaunch from TWL, or unless a button is pressed
or the no-forcing flag is set */
if(!pressed && !BOOTCFG_NOFORCEFLAG)
if(validTlnc || !(pressed || BOOTCFG_NOFORCEFLAG))
{
nandType = (FirmwareSource)BOOTCFG_NAND;
firmSource = (FirmwareSource)BOOTCFG_FIRM;
emunandIndex = BOOTCFG_EMUINDEX;
goto boot;
}
}
u32 pinMode = MULTICONFIG(PIN);
bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT);
bool pinExists = pinMode != 0 && verifyPin(pinMode);
//If no configuration file exists or SELECT is held or if booted from NTRCARD, load configuration menu
bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT);
/* If the PIN has been verified, wait to make it easier to press the SAFE_MODE combo or the configuration menu button
(if not already pressed, for the latter) */
if(pinExists && !shouldLoadConfigMenu)
{
while(HID_PAD & PIN_BUTTONS);
wait(2000ULL);
//Update pressed buttons
pressed = HID_PAD;
}
shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT);
if(shouldLoadConfigMenu)
{
configMenu(pinExists, pinMode);
@ -220,16 +280,9 @@ void main(int argc, char **argv, u32 magicWord)
if(!CFG_BOOTENV && pressed == SAFE_MODE)
{
nandType = FIRMWARE_SYSNAND;
firmSource = FIRMWARE_SYSNAND;
isSafeMode = true;
//If the PIN has been verified, wait to make it easier to press the SAFE_MODE combo
if(pinExists && !shouldLoadConfigMenu)
{
while(HID_PAD & PIN_BUTTONS);
wait(2000ULL);
}
needToInitSd = true;
goto boot;
}
@ -248,55 +301,48 @@ void main(int argc, char **argv, u32 magicWord)
else if((((pressed & SINGLE_PAYLOAD_BUTTONS) || (!autoBootEmu && (pressed & DPAD_BUTTONS))) && !(pressed & (BUTTON_L1 | BUTTON_R1))) ||
(((pressed & L_PAYLOAD_BUTTONS) || (autoBootEmu && (pressed & DPAD_BUTTONS))) && (pressed & BUTTON_L1))) loadHomebrewFirm(pressed);
if(splashMode == 2) loadSplash();
if(splashMode == 2 && loadSplash()) pressed = HID_PAD;
//Check SAFE_MODE combo again
if(!CFG_BOOTENV && pressed == SAFE_MODE)
{
nandType = FIRMWARE_SYSNAND;
isSafeMode = true;
needToInitSd = true;
goto boot;
}
// Set-up autoboot
if (MULTICONFIG(AUTOBOOTMODE) != 0)
configureHomebrewAutoboot();
//If booting from CTRNAND, always use SysNAND
if(!isSdMode) nandType = FIRMWARE_SYSNAND;
//If R is pressed, boot the non-updated NAND with the FIRM of the opposite one
else if(pressed & BUTTON_R1)
{
if(CONFIG(USEEMUFIRM))
{
nandType = FIRMWARE_SYSNAND;
firmSource = FIRMWARE_EMUNAND;
}
else
{
nandType = FIRMWARE_EMUNAND;
firmSource = FIRMWARE_SYSNAND;
}
}
/* Else, boot the NAND the user set to autoboot or the opposite one, depending on L,
with their own FIRM */
else firmSource = nandType = (autoBootEmu == ((pressed & BUTTON_L1) == BUTTON_L1)) ? FIRMWARE_SYSNAND : FIRMWARE_EMUNAND;
else nandType = (autoBootEmu == ((pressed & BUTTON_L1) == BUTTON_L1)) ? FIRMWARE_SYSNAND : FIRMWARE_EMUNAND;
//If we're booting EmuNAND or using EmuNAND FIRM, determine which one from the directional pad buttons, or otherwise from the config
if(nandType == FIRMWARE_EMUNAND || firmSource == FIRMWARE_EMUNAND)
if(nandType == FIRMWARE_EMUNAND)
{
FirmwareSource tempNand;
switch(pressed & DPAD_BUTTONS)
{
case BUTTON_UP:
tempNand = FIRMWARE_EMUNAND;
emunandIndex = 0;
break;
case BUTTON_RIGHT:
tempNand = FIRMWARE_EMUNAND2;
emunandIndex = 1;
break;
case BUTTON_DOWN:
tempNand = FIRMWARE_EMUNAND3;
emunandIndex = 2;
break;
case BUTTON_LEFT:
tempNand = FIRMWARE_EMUNAND4;
emunandIndex = 3;
break;
default:
tempNand = (FirmwareSource)(1 + MULTICONFIG(DEFAULTEMU));
emunandIndex = MULTICONFIG(DEFAULTEMU);
break;
}
if(nandType == FIRMWARE_EMUNAND) nandType = tempNand;
else firmSource = tempNand;
}
boot:
@ -304,32 +350,31 @@ boot:
//If we need to boot EmuNAND, make sure it exists
if(nandType != FIRMWARE_SYSNAND)
{
locateEmuNand(&nandType);
if(nandType == FIRMWARE_SYSNAND) firmSource = FIRMWARE_SYSNAND;
else if((*(vu16 *)(SDMMC_BASE + REG_SDSTATUS0) & TMIO_STAT0_WRPROTECT) == 0) //Make sure the SD card isn't write protected
locateEmuNand(&nandType, &emunandIndex, true);
if(nandType == FIRMWARE_EMUNAND && (*(vu16 *)(SDMMC_BASE + REG_SDSTATUS0) & TMIO_STAT0_WRPROTECT) == 0) //Make sure the SD card isn't write protected
error("The SD card is locked, EmuNAND can not be used.\nPlease turn the write protection switch off.");
}
//Same if we're using EmuNAND as the FIRM source
else if(firmSource != FIRMWARE_SYSNAND)
locateEmuNand(&firmSource);
ctrNandLocation = nandType; // for CTRNAND partition
if(bootType != FIRMLAUNCH)
{
configData.bootConfig = ((bootType == NTR ? 1 : 0) << 7) | ((u32)isNoForceFlagSet << 6) | ((u32)firmSource << 3) | (u32)nandType;
configData.bootConfig = ((bootType == NTR ? 1 : 0) << 4) | ((u32)isNoForceFlagSet << 3) | ((u32)emunandIndex << 1) | (u32)nandType;
writeConfig(false);
}
bool loadFromStorage = CONFIG(LOADEXTFIRMSANDMODULES);
u32 firmVersion = loadNintendoFirm(&firmType, firmSource, loadFromStorage, isSafeMode);
u32 firmVersion = loadNintendoFirm(&firmType, nandType, loadFromStorage, isSafeMode);
bool doUnitinfoPatch = CONFIG(PATCHUNITINFO);
u32 res;
u32 res = 0;
switch(firmType)
{
case NATIVE_FIRM:
res = patchNativeFirm(firmVersion, nandType, loadFromStorage, isFirmProtEnabled, isSafeMode, doUnitinfoPatch);
{
res = patchNativeFirm(firmVersion, nandType, loadFromStorage, isFirmProtEnabled, needToInitSd, doUnitinfoPatch);
break;
}
case TWL_FIRM:
res = patchTwlFirm(firmVersion, loadFromStorage, doUnitinfoPatch);
break;
@ -341,10 +386,14 @@ boot:
case NATIVE_FIRM1X2X:
res = patch1x2xNativeAndSafeFirm();
break;
case NATIVE_PROTOTYPE:
res = patchPrototypeNative(nandType);
break;
}
if(res != 0) error("Failed to apply %u FIRM patch(es).", res);
unmountPartitions();
if(bootType != FIRMLAUNCH) deinitScreens();
launchFirm(0, NULL);
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -26,50 +26,11 @@
/*
* Boyer-Moore Horspool algorithm adapted from http://www-igm.univ-mlv.fr/~lecroq/string/node18.html#SECTION00180
* memcpy, memset32 and memcmp adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
* memcpy, memset and memcmp adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
*/
#include "memory.h"
void memcpy(void *dest, const void *src, u32 size)
{
u8 *destc = (u8 *)dest;
const u8 *srcc = (const u8 *)src;
for(u32 i = 0; i < size; i++)
destc[i] = srcc[i];
}
void memset(void *dest, u32 filler, u32 size)
{
u8 *destc = (u8 *)dest;
for(u32 i = 0; i < size; i++)
destc[i] = (u8)filler;
}
void memset32(void *dest, u32 filler, u32 size)
{
u32 *dest32 = (u32 *)dest;
for(u32 i = 0; i < size / 4; i++)
dest32[i] = filler;
}
int memcmp(const void *buf1, const void *buf2, u32 size)
{
const u8 *buf1c = (const u8 *)buf1,
*buf2c = (const u8 *)buf2;
for(u32 i = 0; i < size; i++)
{
int cmp = buf1c[i] - buf2c[i];
if(cmp != 0) return cmp;
}
return 0;
}
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize)
{
const u8 *patternc = (const u8 *)pattern;
@ -93,3 +54,27 @@ u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize)
return NULL;
}
void *copyFromLegacyModeFcram(void *dst, const void *src, size_t size)
{
// Copy 2 bytes with a stride of 8
const u16 *src16 = (const u16 *)src;
u16 *dst16 = (u16 *)dst;
for (size_t i = 0; i < size / 2; i++)
dst16[i] = src16[4 * i];
return dst;
}
void *copyToLegacyModeFcram(void *dst, const void *src, size_t size)
{
// Copy 2 bytes with a stride of 8
const u16 *src16 = (const u16 *)src;
u16 *dst16 = (u16 *)dst;
for (size_t i = 0; i < size / 2; i++)
dst16[4 * i] = src16[i];
return dst;
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -26,15 +26,13 @@
/*
* Boyer-Moore Horspool algorithm adapted from http://www-igm.univ-mlv.fr/~lecroq/string/node18.html#SECTION00180
* memcpy, memset32 and memcmp adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
*/
#pragma once
#include <string.h>
#include "types.h"
void memcpy(void *dest, const void *src, u32 size);
void memset(void *dest, u32 filler, u32 size) __attribute__((used));
void memset32(void *dest, u32 filler, u32 size);
int memcmp(const void *buf1, const void *buf2, u32 size);
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize);
void *copyFromLegacyModeFcram(void *dst, const void *src, size_t size);
void *copyToLegacyModeFcram(void *dst, const void *src, size_t size);

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -39,7 +39,13 @@
#include "memory.h"
#include "config.h"
#include "utils.h"
#include "../build/bundled.h"
#include "arm9_exception_handlers.h"
#include "large_patches.h"
#define K11EXT_VA 0x70000000
extern u16 launchedPath[];
extern u32 firmProtoVersion;
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
{
@ -49,10 +55,20 @@ u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
Cxi *off = (Cxi *)(temp - 0x100);
*process9Size = (off->ncch.exeFsSize - 1) * 0x200;
*process9MemAddr = off->exHeader.systemControlInfo.textCodeSet.address;
return (u8 *)off + (off->ncch.exeFsOffset + 1) * 0x200;
// Prototype FW has a different NCCH format
if (firmProtoVersion && firmProtoVersion <= 243)
{
*process9Size = off->ncch.exeFsSize;
return (u8 *)off + off->ncch.exeFsOffset;
}
else
{
*process9Size = (off->ncch.exeFsSize - 1) * 0x200;
return (u8 *)off + (off->ncch.exeFsOffset + 1) * 0x200;
}
}
u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage)
@ -78,8 +94,8 @@ u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 *
return arm11SvcTable;
}
// For ARM prologs in the form of: push {regs} ... sub sp, #off (this obviously doesn't intend to cover all cases)
static inline u32 computeARMFrameSize(const u32 *prolog)
// For Arm prologs in the form of: push {regs} ... sub sp, #off (this obviously doesn't intend to cover all cases)
static inline u32 computeArmFrameSize(const u32 *prolog)
{
const u32 *off;
@ -100,17 +116,19 @@ static inline u32 *getKernel11HandlerVAPos(u8 *pos, u32 *arm11ExceptionsPage, u3
return (u32 *)(pos + pointedInstructionVA - baseK11VA + 8);
}
u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space)
u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space)
{
//The parameters to be passed on to the kernel ext
//Please keep that in sync with the definition in k11_extension/source/main.c
struct KExtParameters
{
u32 __attribute__((aligned(0x400))) L2MMUTableFor0x40000000[256];
u32 basePA;
u32 stolenSystemMemRegionSize;
void *originalHandlers[4];
u32 L1MMUTableAddrs[4];
volatile bool done;
struct CfwInfo
{
char magic[4];
@ -124,8 +142,20 @@ u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
u16 configFormatVersionMajor, configFormatVersionMinor;
u32 config, multiConfig, bootConfig;
u32 splashDurationMsec;
s8 volumeSliderOverride;
u64 hbldr3dsxTitleId;
u32 rosalinaMenuCombo;
u32 pluginLoaderFlags;
s16 ntpTzOffetMinutes;
ScreenFiltersCfgData topScreenFilter;
ScreenFiltersCfgData bottomScreenFilter;
u64 autobootTwlTitleId;
u8 autobootCtrAppmemtype;
u16 launchedPath[80+1];
} info;
};
@ -134,8 +164,9 @@ u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
static const u8 patternHook3_4[] = {0x00, 0x00, 0xA0, 0xE1, 0x03, 0xF0, 0x20, 0xE3, 0xFD, 0xFF, 0xFF, 0xEA}; //SGI0 setup code, etc.
//Our kernel11 extension is initially loaded in VRAM
u32 kextTotalSize = *(u32 *)0x18000020 - 0x40000000;
u32 dstKextPA = (ISN3DS ? 0x2E000000 : 0x26C00000) - kextTotalSize;
u32 kextTotalSize = *(u32 *)0x18000020 - K11EXT_VA;
u32 stolenSystemMemRegionSize = kextTotalSize; // no need to steal any more mem on N3DS. Currently, everything fits in BASE on O3DS too (?)
u32 dstKextPA = (ISN3DS ? 0x2E000000 : 0x26C00000) - stolenSystemMemRegionSize; // start of BASE memregion (note: linear heap ---> <--- the rest)
u32 *hookVeneers = (u32 *)*freeK11Space;
u32 relocBase = 0xFFFF0000 + (*freeK11Space - (u8 *)arm11ExceptionsPage);
@ -143,11 +174,11 @@ u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
hookVeneers[0] = 0xE51FF004; //ldr pc, [pc, #-8+4]
hookVeneers[1] = 0x18000004;
hookVeneers[2] = 0xE51FF004;
hookVeneers[3] = 0x40000000;
hookVeneers[3] = K11EXT_VA;
hookVeneers[4] = 0xE51FF004;
hookVeneers[5] = 0x40000008;
hookVeneers[5] = K11EXT_VA + 8;
hookVeneers[6] = 0xE51FF004;
hookVeneers[7] = 0x4000000C;
hookVeneers[7] = K11EXT_VA + 0xC;
(*freeK11Space) += 32;
@ -175,14 +206,16 @@ u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
off += 4;
*off = MAKE_BRANCH_LINK(baseK11VA + ((u8 *)off - pos), relocBase + 24);
struct KExtParameters *p = (struct KExtParameters *)(*(u32 *)0x18000024 - 0x40000000 + 0x18000000);
struct KExtParameters *p = (struct KExtParameters *)(*(u32 *)0x18000024 - K11EXT_VA + 0x18000000);
p->basePA = dstKextPA;
p->done = false;
p->stolenSystemMemRegionSize = stolenSystemMemRegionSize;
for(u32 i = 0; i < 4; i++)
{
u32 *handlerPos = getKernel11HandlerVAPos(pos, arm11ExceptionsPage, baseK11VA, 1 + i);
p->originalHandlers[i] = (void *)*handlerPos;
*handlerPos = 0x40000010 + 4 * i;
*handlerPos = K11EXT_VA + 0x10 + 4 * i;
}
struct CfwInfo *info = &p->info;
@ -193,17 +226,27 @@ u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
info->config = configData.config;
info->multiConfig = configData.multiConfig;
info->bootConfig = configData.bootConfig;
info->splashDurationMsec = configData.splashDurationMsec;
info->volumeSliderOverride = configData.volumeSliderOverride;
info->hbldr3dsxTitleId = configData.hbldr3dsxTitleId;
info->rosalinaMenuCombo = configData.rosalinaMenuCombo;
info->pluginLoaderFlags = configData.pluginLoaderFlags;
info->ntpTzOffetMinutes = configData.ntpTzOffetMinutes;
info->topScreenFilter = configData.topScreenFilter;
info->bottomScreenFilter = configData.bottomScreenFilter;
info->autobootTwlTitleId = configData.autobootTwlTitleId;
info->autobootCtrAppmemtype = configData.autobootCtrAppmemtype;
info->versionMajor = VERSION_MAJOR;
info->versionMinor = VERSION_MINOR;
info->versionBuild = VERSION_BUILD;
if(ISRELEASE) info->flags = 1;
if(ISN3DS) info->flags |= 1 << 4;
if(isSafeMode) info->flags |= 1 << 5;
if(needToInitSd) info->flags |= 1 << 5;
if(isSdMode) info->flags |= 1 << 6;
memcpy(info->launchedPath, launchedPath, sizeof(info->launchedPath));
return 0;
}
@ -230,7 +273,7 @@ u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm
*/
for(off = (u32 *)ControlMemoryPos; (off[0] & 0xFFF0FFFF) != 0xE3500001 || (off[1] & 0xFFFF0FFF) != 0x13A00000; off++);
off -= 2;
*off = 0xE59D0000 | (*off & 0x0000F000) | (8 + computeARMFrameSize((u32 *)ControlMemoryPos)); // ldr r0, [sp, #(frameSize + 8)]
*off = 0xE59D0000 | (*off & 0x0000F000) | (8 + computeArmFrameSize((u32 *)ControlMemoryPos)); // ldr r0, [sp, #(frameSize + 8)]
//Patch DebugActiveProcess
for(off = (u32 *)(pos + (arm11SvcTable[0x60] - baseK11VA)); *off != 0xE3110001; off++);
@ -248,14 +291,31 @@ u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm
//Redirect enableUserExceptionHandlersForCPUExc (= true)
for(off = arm11ExceptionsPage; *off != 0x96007F9; off++);
off[1] = 0x40000028;
off[1] = K11EXT_VA + 0x28;
off = (u32 *)memsearch(pos, patternKThreadDebugReschedule, size, sizeof(patternKThreadDebugReschedule));
if(off == NULL)
return 1;
off[-5] = 0xE51FF004;
off[-4] = 0x4000002C;
off[-4] = K11EXT_VA + 0x2C;
if (ISN3DS)
{
// Patch SvcSetProcessIdealProcessor and SvcCreate thread to always allow
// for core2 and core3 to be used. Normally, processes with the 0x2000 kernel flag
// have access to core2, and BASE processes have access to both core2 and core3.
// We're patching the if (memory region == BASE) check to be always true.
off = (u32 *)pos;
for (u32 i = 0; i < 2 && (u8 *)off < pos + size; i++)
{
// cmp r2, #0x300; beq...
for (; (off[0] != 0xE3520C03 || off[1] != 0x0A000003) && (u8 *)off < pos + size; off++);
if ((u8 *)off > pos + size)
return 1;
off[1] = 0xEA000003;
}
}
return 0;
}
@ -302,7 +362,7 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
static const u8 pattern[] = {0xE2, 0x20, 0x20, 0x90};
u32 pathLen;
for(pathLen = 0; pathLen < 41 && launchedPath[pathLen] != 0; pathLen++);
for(pathLen = 0; pathLen < sizeof(launchedPath)/2 && launchedPath[pathLen] != 0; pathLen++);
if(launchedPath[pathLen] != 0) return 1;
@ -312,18 +372,17 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
off -= 0x13;
//Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
//Firmlaunch function offset - offset in BLX opcode (A4-16 - Arm DDI 0100E) + 1
u32 fOpenOffset = (u32)(off + 9 - (-((*(u32 *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - pos + process9MemAddr);
//Copy firmlaunch code
memcpy(off, reboot_bin, reboot_bin_size);
//Put the fOpen offset in the right location
u32 *pos_fopen = (u32 *)memsearch(off, "OPEN", reboot_bin_size, 4);
*pos_fopen = fOpenOffset;
rebootPatchFopenPtr = fOpenOffset;
u16 *fname = (u16 *)memsearch(off, "FILE", reboot_bin_size, 8);
memcpy(fname, launchedPath, 2 * (1 + pathLen));
//Copy the launched path
memcpy(rebootPatchFileName, launchedPath, 2 * (1 + pathLen));
//Copy firmlaunch code
memcpy(off, rebootPatch, rebootPatchSize);
return 0;
}
@ -373,7 +432,7 @@ u32 patchTitleInstallMinVersionChecks(u8 *pos, u32 size, u32 firmVersion)
off++;
//Zero out the first TitleID in the list
memset32(off, 0, 8);
memset(off, 0, 8);
return 0;
}
@ -419,7 +478,7 @@ u32 patchCheckForDevCommonKey(u8 *pos, u32 size)
return 0;
}
u32 patchK11ModuleLoading(u32 section0size, u32 modulesSize, u8 *pos, u32 size)
u32 patchK11ModuleLoading(u32 oldKipSectionSize, u32 newKipSectionSize, u32 numKips, u8 *pos, u32 size)
{
static const u8 moduleLoadingPattern[] = {0xE2, 0x05, 0x00, 0x57},
modulePidPattern[] = {0x06, 0xA0, 0xE1, 0xF2}; //GetSystemInfo
@ -428,20 +487,44 @@ u32 patchK11ModuleLoading(u32 section0size, u32 modulesSize, u8 *pos, u32 size)
if(off == NULL) return 1;
off[1]++;
off[1] = (u8)numKips;
u32 *off32;
for(off32 = (u32 *)(off - 3); *off32 != 0xE59F0000; off32++);
off32 += 2;
off32[1] = off32[0] + modulesSize;
for(; *off32 != section0size; off32++);
*off32 += ((modulesSize + 0x1FF) >> 9) << 9;
off32[1] = off32[0] + newKipSectionSize;
for(; *off32 != oldKipSectionSize; off32++);
*off32 = ((newKipSectionSize + 0x1FF) >> 9) << 9;
off = memsearch(pos, modulePidPattern, size, 4);
if(off == NULL) return 1;
off[0xB] = 6;
off[0xB] = (u8)numKips;
return 0;
}
u32 patchK11ModuleLoadingLgy(u32 newKipSectionSize, u8 *pos, u32 size)
{
// Patch the function where TwlBg/AgbBg is copied from 18000000 (VRAM) to 21000000 (FCRAM).
// This is where we can also automatically obtain the section size
u16 *off = (u16 *)pos;
for (; (u8 *)off < pos + size && (off[0] != 0x06C9 || off[1] != 0x0600); off++);
if ((u8 *)off >= pos + size)
return 3;
off += 7;
u32 oldKipSectionSize = *(u32 *)off;
*(u32 *)off = newKipSectionSize;
off += 2;
u32 *off2 = (u32 *)off;
for (; (u8 *)off2 < pos + size && *off2 != oldKipSectionSize; off2++);
if ((u8 *)off2 >= pos + size)
return 4;
*off2 = newKipSectionSize;
return 0;
}
@ -501,20 +584,20 @@ u32 patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address)
addr[0] = 0xE1A0800D;
addr[1] = 0xE12FFF7F;
*(vu32 *)0x01FF8004 = arm9SvcTable[0x3C]; //BreakPtr
arm9ExceptionHandlerSvcBreakAddress = arm9SvcTable[0x3C]; //BreakPtr
return 0;
}
u32 patchKernel9Panic(u8 *pos, u32 size)
{
static const u8 pattern[] = {0xFF, 0xEA, 0x04, 0xD0};
static const u8 pattern[] = {0x00, 0x20, 0x92, 0x15};
u8 *temp = memsearch(pos, pattern, size, sizeof(pattern));
if(temp == NULL) return 1;
u32 *off = (u32 *)(temp - 0x12);
u32 *off = (u32 *)(temp - 0x34);
*off = 0xE12FFF7E;
return 0;
@ -550,6 +633,34 @@ u32 patchUnitInfoValueSet(u8 *pos, u32 size)
return 0;
}
u32 patchP9AMTicketWrapperZeroKeyIV(u8 *pos, u32 size, u32 firmVersion)
{
static const u8 __rt_memclr_pattern[] = {0x00, 0x20, 0xA0, 0xE3, 0x04, 0x00, 0x51, 0xE3, 0x07, 0x00, 0x00, 0x3A};
static const u8 pattern[] = {0x20, 0x21, 0xA6, 0xA8};
u32 function = (u32)memsearch(pos, __rt_memclr_pattern, size, sizeof(__rt_memclr_pattern));
u16 *off = (u16 *)memsearch(pos, pattern, size, sizeof(pattern));
if(function == 0 || off == NULL) return firmVersion == 0xFFFFFFFF ? 0 : 1;
//After the found code it's a BL call (at &off[2]), that will be replaced
//From Thumb, op distance for setting in BLX can be got with,
//(Destination_offset - blx_op_offset+2) / 2
s32 opjumpdistance = (s32)(function - ((u32)&off[3])) / 2;
//Beyond limit
if(opjumpdistance < -0x1fffff || opjumpdistance > 0x1fffff) return 1;
//r0 and r1 for old call are already correct for this one
//BLX __rt_memclr
u32 op = (0xE800F000U | (((u32)opjumpdistance & 0x7FF) << 16) | (((u32)opjumpdistance >> 11) & 0x3FF) | (((u32)opjumpdistance >> 21) & 0x400)) & ~(1<<16);
off[2] = op;
off[3] = op >> 16;
return 0;
}
u32 patchLgySignatureChecks(u8 *pos, u32 size)
{
static const u8 pattern[] = {0x47, 0xC1, 0x17, 0x49};
@ -668,3 +779,120 @@ u32 patchAgbBootSplash(u8 *pos, u32 size)
return 0;
}
void patchTwlBg(u8 *pos, u32 size)
{
// You can use the following Python code to convert something like below
// into twl_upscaling_filter.bin:
// import struct; open("twl_upscaling_filter.bin", "wb+").write(struct.pack("<30H", [array contents]))
static const u16 nintendoFilterTwl[] = {
0x0000, 0x004E, 0x011D, 0x01E3, 0x01C1,
0x0000, 0xFCA5, 0xF8D0, 0xF69D, 0xF873,
0x0000, 0x0D47, 0x1E35, 0x2F08, 0x3B6F,
0x4000, 0x3B6F, 0x2F08, 0x1E35, 0x0D47,
0x0000, 0xF873, 0xF69D, 0xF8D0, 0xFCA5,
0x0000, 0x01C1, 0x01E3, 0x011D, 0x004E,
};
// "error" func doesn't seem to work here
if (CONFIG(ENABLEDSIEXTFILTER))
{
u16 filter[5*6] = { 0 };
u32 rd = fileRead(filter, "twl_upscaling_filter.bin", sizeof(filter));
if (rd == sizeof(filter))
{
// else error("Failed to apply enable_dsi_external_filter:\n\ntwl_upscaling_filter.bin is missing or invalid.");
u8 *off = memsearch(pos, nintendoFilterTwl, size, sizeof(nintendoFilterTwl));
if (off != NULL)
memcpy(off, filter, sizeof(filter));
// else error("Failed to apply enable_dsi_external_filter.");
}
}
}
u32 patchLgyK11(u8 *section1, u32 section1Size, u8 *section2, u32 section2Size)
{
u32 *off;
// Fix a bug where Legacy K11 maps user TLS with "user no access" permissions
// Map it as RWX (just like the rest of other user-accessible pages) instead
for (off = (u32 *)section1; (u8 *)off <= section1 + section1Size && *off != 0xE0100000; off++);
if ((u8 *)off >= section1 + section1Size)
return 1;
++off;
*off &= ~0x231; // clear APX mask and XN
*off |= 0x030; // re-set APX (to user/kernel RW)
// Patch two pointer-to-bool to point to a non-zero byte, enabling user exception handling.
// It is impossible to enable it by normal means, otherwise
for (off = (u32 *)section2; (u8 *)off <= section2 + section2Size && *off != 0x100021F; off++);
if ((u8 *)off >= section2 + section2Size)
return 1;
off[1] = 0xFFFF0F00;
off[2] = 0xFFFF0F04;
// Dispatch-to-user code checks for memory block type and permissions (etc.), but
// LGY K11 doesn't do any memory management, so these checks will always fail.
// Patch with b +0x38 to skip all those checks
u16 *off2;
for (off2 = (u16 *)section2; (u8 *)off2 <= section2 + section2Size && (off2[0] != 0xDB1F || off2[1] != 0x4915); off2++);
if ((u8 *)off2 >= section2 + section2Size)
return 1;
*off2 = 0xE01A;
// Patch kernelpanic to skip devunit check, so that it sets the LCD fill regs
// which are useful to detect such panics
u16 *off3;
for (off3 = (u16 *)section1; (u8 *)off3 <= section1 + section1Size && (off3[0] != 0x481D || off3[1] != 0xB570); off3++);
if ((u8 *)off3 >= section1 + section1Size)
return 1;
off3[2] = 0x2001; // movs r0, #1
// Patch kernel to avoid allocating the two "configuration memory" pages, freeing
// 0x2000 bytes of kernel "heap" (which is 0xD000 AXIWRAM bytes on LGY K11 instead
// of the entire FCRAM on NFIRM). This is indeed a bug because if prevents two of the
// 12 KThread objects from being created
u16 *off4;
for (off4 = (u16 *)section1; (u8 *)off4 <= section1 + section1Size && (off4[0] != 0xB570 || off4[1] != 0x2200); off4++);
if ((u8 *)off4 >= section1 + section1Size)
return 1;
*off4 = 0x4770; // bx lr
return 0;
}
u32 patchProtoNandSignatureCheck(u8 *pos, u32 size) {
if (firmProtoVersion == 243) {
static const u8 pattern[] = {0x08, 0x31, 0x9F, 0xE5};
// Signature check function returns 0 if failed and 1 if succeeded.
// Proc9 breaks if the returned value is 0, change it to break if
// the returned value is 2 (never).
u8 *off = memsearch(pos, pattern, size, sizeof(pattern));
if (!off)
return 1;
off[0x20] = 2;
}
else if (firmProtoVersion == 238) { // SDK 0.10
// Same patch as for v243 ported to the different ncsd_read() function
static const u8 pattern[] = {
0x00, 0x11, 0x9f, 0xe5,
0x00, 0x51, 0x9f, 0xe5,
};
u8 *off = memsearch(pos, pattern, size, sizeof(pattern));
if (!off)
return 1;
off[0x20] = 2;
}
else return 1;
return 0;
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -31,6 +31,7 @@
* FIRM partition writes patches by delebile
* Idea for svcBreak patches from yellows8 and others on #3dsdev
* TWL_FIRM patches by Steveice10 and others
* Signature patches for prototype FW by PabloMK7
*/
#pragma once
@ -39,7 +40,7 @@
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage);
u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space);
u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space);
u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm11ExceptionsPage);
u32 patchSignatureChecks(u8 *pos, u32 size);
u32 patchOldSignatureChecks(u8 *pos, u32 size);
@ -50,12 +51,14 @@ u32 patchTitleInstallMinVersionChecks(u8 *pos, u32 size, u32 firmVersion);
u32 patchZeroKeyNcchEncryptionCheck(u8 *pos, u32 size);
u32 patchNandNcchEncryptionCheck(u8 *pos, u32 size);
u32 patchCheckForDevCommonKey(u8 *pos, u32 size);
u32 patchK11ModuleLoading(u32 section0size, u32 modulesSize, u8 *startPos, u32 size);
u32 patchK11ModuleLoading(u32 oldKipSectionSize, u32 newKipSectionSize, u32 numKips, u8 *pos, u32 size);
u32 patchK11ModuleLoadingLgy(u32 newKipSectionSize, u8 *pos, u32 size);
u32 patchArm9ExceptionHandlersInstall(u8 *pos, u32 size);
u32 patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address);
u32 patchKernel9Panic(u8 *pos, u32 size);
u32 patchP9AccessChecks(u8 *pos, u32 size);
u32 patchUnitInfoValueSet(u8 *pos, u32 size);
u32 patchP9AMTicketWrapperZeroKeyIV(u8 *pos, u32 size, u32 firmVersion);
u32 patchLgySignatureChecks(u8 *pos, u32 size);
u32 patchTwlInvalidSignatureChecks(u8 *pos, u32 size);
u32 patchTwlNintendoLogoChecks(u8 *pos, u32 size);
@ -64,3 +67,6 @@ u32 patchTwlFlashcartChecks(u8 *pos, u32 size, u32 firmVersion);
u32 patchOldTwlFlashcartChecks(u8 *pos, u32 size);
u32 patchTwlShaHashChecks(u8 *pos, u32 size);
u32 patchAgbBootSplash(u8 *pos, u32 size);
void patchTwlBg(u8 *pos, u32 size); // silently fails
u32 patchLgyK11(u8 *section1, u32 section1Size, u8 *section2, u32 section2Size);
u32 patchProtoNandSignatureCheck(u8 *pos, u32 size);

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -35,6 +35,8 @@
#include "i2c.h"
#include "utils.h"
bool needToSetupScreens = true;
struct fb fbs[2] =
{
{
@ -68,6 +70,14 @@ void prepareArm11ForFirmlaunch(void)
void deinitScreens(void)
{
if(ARESCREENSINITIALIZED) invokeArm11Function(DEINIT_SCREENS);
// Backlight voltage off
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x14);
wait(50);
// LCD panel voltage off
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x01);
wait(50);
}
void updateBrightness(u32 brightnessIndex)
@ -92,18 +102,40 @@ void clearScreens(bool isAlternate)
void initScreens(void)
{
static bool needToSetup = true;
if(needToSetup)
if(needToSetupScreens)
{
if(!ARESCREENSINITIALIZED)
if(!ARESCREENSINITIALIZED || bootType == FIRMLAUNCH)
{
*(vu32 *)ARM11_PARAMETERS_ADDRESS = brightness[MULTICONFIG(BRIGHTNESS)];
memcpy((void *)(ARM11_PARAMETERS_ADDRESS + 4), fbs, sizeof(fbs));
invokeArm11Function(INIT_SCREENS);
//Turn on backlight
i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
// Fragile code, needs proper fix/total rewrite of the baremetal components anyway
// Assume controller revision is not 0x00 for either screen (this revision is extremely
// old and shouldn't be seen in retail units nor normal devunits)
// Controller reset off
I2C_writeReg(I2C_DEV_LCD_TOP, 0xFE, 0xAA);
I2C_writeReg(I2C_DEV_LCD_BOT, 0xFE, 0xAA);
wait(5);
// Controller power on
I2C_writeReg(I2C_DEV_LCD_TOP, 0x01, 0x10);
I2C_writeReg(I2C_DEV_LCD_BOT, 0x01, 0x10);
wait(5);
// Clear error flag
I2C_writeReg(I2C_DEV_LCD_TOP, 0x60, 0x00);
I2C_writeReg(I2C_DEV_LCD_BOT, 0x60, 0x00);
wait(5);
// LCD panel (bias ?) voltage on
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x02);
wait(50);
// Backlight voltage on
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x28);
wait(5);
}
else updateBrightness(MULTICONFIG(BRIGHTNESS));
@ -111,9 +143,14 @@ void initScreens(void)
invokeArm11Function(SETUP_FRAMEBUFFERS);
clearScreens(true);
needToSetup = false;
needToSetupScreens = false;
}
clearScreens(false);
swapFramebuffers(false);
}
void zerofillN3dsAblRegisters(void)
{
invokeArm11Function(ZEROFILL_N3DS_ABL_REGISTERS);
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -33,9 +33,9 @@
#include "types.h"
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
#define PDN_GPU_CNT (*(vu32 *)0x10141200)
#define ARESCREENSINITIALIZED (PDN_GPU_CNT != 1)
#define ARESCREENSINITIALIZED ((PDN_GPU_CNT & 0xFF) != 1)
#define ARM11_PARAMETERS_ADDRESS 0x1FFFF000
@ -59,15 +59,19 @@ typedef enum
SWAP_FRAMEBUFFERS,
UPDATE_BRIGHTNESS,
DEINIT_SCREENS,
ZEROFILL_N3DS_ABL_REGISTERS,
PREPARE_ARM11_FOR_FIRMLAUNCH,
ARM11_READY,
} Arm11Operation;
extern struct fb fbs[2];
extern bool needToSetupScreens;
void prepareArm11ForFirmlaunch(void);
void deinitScreens(void);
void swapFramebuffers(bool isAlternate);
void updateBrightness(u32 brightnessIndex);
void clearScreens(bool isAlternate);
void initScreens(void);
void zerofillN3dsAblRegisters(void);

View File

@ -1,5 +1,5 @@
@ This file is part of Luma3DS
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
@
@ This program is free software: you can redistribute it and/or modify
@ it under the terms of the GNU General Public License as published by
@ -22,7 +22,7 @@
@ or requiring that modified versions of such material be marked in
@ reasonable ways as different from the original version.
.section .text.start
.section .text.start, "ax", %progbits
.align 4
.global _start
_start:
@ -77,7 +77,7 @@ _start:
ldr r1, =0xFFF0001B @ fff00000 16k | dtcm
ldr r2, =0x01FF801D @ 01ff8000 32k | itcm
ldr r3, =0x08000027 @ 08000000 1M | arm9 mem
ldr r4, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB)
ldr r4, =0x10000029 @ 10000000 2M | io mem (Arm9 / first 2MB)
ldr r5, =0x20000035 @ 20000000 128M | fcram
ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram
ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB)
@ -109,13 +109,58 @@ _start:
mcr p15, 0, r0, c1, c0, 0 @ write control register
@ Clear BSS
ldr r0, =__bss_start
ldr r0, =__bss_start__
mov r1, #0
ldr r2, =__bss_end
ldr r2, =__bss_end__
sub r2, r0
bl memset32
bl memset
bl __libc_init_array
mov r0, r9
mov r1, r10
mov r2, r11
b main
.pool
.section .chainloader.text.start, "ax", %progbits
.align 4
.global chainload
.type chainload, %function
chainload:
ldr sp, =__itcm_stack_top__
b chainloader_main
.pool
.global disableMpuAndJumpToEntrypoints
.type disableMpuAndJumpToEntrypoints, %function
disableMpuAndJumpToEntrypoints:
mov r4, r0
mov r5, r1
mov r6, r2
mov r7, r3
@ Flush caches
ldr r12, =0xFFFF0830
blx r12
ldr r12, =0xFFFF0AB4
blx r12
@ Disable caches / MPU
mrc p15, 0, r0, c1, c0, 0 @ read control register
bic r0, #(1<<12) @ - instruction cache disable
bic r0, #(1<<2) @ - data cache disable
bic r0, #(1<<0) @ - MPU disable
mcr p15, 0, r0, c1, c0, 0 @ write control register
@ Set the Arm11 entrypoint
mov r0, #0x20000000
str r7, [r0, #-4]
@ Jump to the Arm9 entrypoint
mov r0, r4
mov r1, r5
ldr r2, =0x4BEEF
bx r6
.pool

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -25,25 +25,6 @@
*/
#include "strings.h"
#include "memory.h"
u32 strlen(const char *string)
{
char *stringEnd = (char *)string;
while(*stringEnd != 0) stringEnd++;
return stringEnd - string;
}
u32 strnlen(const char *string, u32 maxlen)
{
u32 size;
for(size = 0; size < maxlen && *string; string++, size++);
return size;
}
u32 hexAtoi(const char *in, u32 digits)
{

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -28,7 +28,5 @@
#include "types.h"
u32 strlen(const char *string);
u32 strnlen(const char *string, u32 maxlen);
u32 hexAtoi(const char *in, u32 digits);
u32 decAtoi(const char *in, u32 digits);

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -61,17 +61,43 @@ typedef volatile s64 vs64;
#define ISN3DS (CFG11_SOCINFO & 2)
#define ISDEVUNIT (CFG_UNITINFO != 0)
typedef struct __attribute__((packed))
{
char magic[4];
typedef struct ScreenFiltersCfgData {
u16 cct;
bool invert;
u8 colorCurveCorrection;
s64 gammaEnc;
s64 contrastEnc;
s64 brightnessEnc;
} ScreenFiltersCfgData;
typedef struct CfgData {
u16 formatVersionMajor, formatVersionMinor;
u32 config, multiConfig, bootConfig;
u32 splashDurationMsec;
s8 volumeSliderOverride;
u64 hbldr3dsxTitleId;
u32 rosalinaMenuCombo;
u32 pluginLoaderFlags;
s16 ntpTzOffetMinutes;
ScreenFiltersCfgData topScreenFilter;
ScreenFiltersCfgData bottomScreenFilter;
u64 autobootTwlTitleId;
u8 autobootCtrAppmemtype;
} CfgData;
typedef struct __attribute__((packed))
typedef struct
{
u16 lumaVersion;
u8 bootCfg;
u8 reserved[2];
u8 checksum;
} CfgDataMcu;
typedef struct
{
char magic[4];
u16 formatVersionMajor, formatVersionMinor;
@ -80,7 +106,7 @@ typedef struct __attribute__((packed))
u8 hash[32];
} PinData;
typedef struct __attribute__((packed))
typedef struct
{
u32 magic[2];
u16 versionMinor, versionMajor;
@ -99,9 +125,6 @@ typedef enum FirmwareSource
{
FIRMWARE_SYSNAND = 0,
FIRMWARE_EMUNAND,
FIRMWARE_EMUNAND2,
FIRMWARE_EMUNAND3,
FIRMWARE_EMUNAND4
} FirmwareSource;
typedef enum FirmwareType
@ -111,7 +134,8 @@ typedef enum FirmwareType
AGB_FIRM,
SAFE_FIRM,
SYSUPDATER_FIRM,
NATIVE_FIRM1X2X
NATIVE_FIRM1X2X,
NATIVE_PROTOTYPE,
} FirmwareType;
typedef enum bootType
@ -128,5 +152,9 @@ extern bool isSdMode;
extern BootType bootType;
extern char launchedPathForFatfs[256];
extern u16 launchedFirmTidLow[8];
extern u16 launchedPath[41];
extern u16 launchedPath[80+1];
extern u16 mcuFwVersion;
extern u8 mcuConsoleInfo[9];

251
arm9/source/utils.c Normal file
View File

@ -0,0 +1,251 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2022 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.
*/
/*
* waitInput function based on code by d0k3 https://github.com/d0k3/Decrypt9WIP/blob/master/source/hid.c
*/
#include "utils.h"
#include "i2c.h"
#include "buttons.h"
#include "screen.h"
#include "draw.h"
#include "cache.h"
#include "fmt.h"
#include "memory.h"
#include "fs.h"
void startChrono(void)
{
static bool isChronoStarted = false;
if(isChronoStarted) return;
REG_TIMER_CNT(0) = 0; //67MHz
for(u32 i = 1; i < 4; i++) REG_TIMER_CNT(i) = 4; //Count-up
for(u32 i = 0; i < 4; i++) REG_TIMER_VAL(i) = 0;
REG_TIMER_CNT(0) = 0x80; //67MHz; enabled
for(u32 i = 1; i < 4; i++) REG_TIMER_CNT(i) = 0x84; //Count-up; enabled
isChronoStarted = true;
}
u64 chrono(void)
{
u64 res = 0;
for(u32 i = 0; i < 4; i++) res |= REG_TIMER_VAL(i) << (16 * i);
res /= (TICKS_PER_SEC / 1000);
return res;
}
u32 waitInput(bool isMenu)
{
static u64 dPadDelay = 0ULL;
u64 initialValue = 0ULL;
u32 key,
oldKey = HID_PAD;
bool shouldShellShutdown = bootType != B9SNTR && bootType != NTR;
if(isMenu)
{
dPadDelay = dPadDelay > 0ULL ? 87ULL : 143ULL;
startChrono();
initialValue = chrono();
}
while(true)
{
key = HID_PAD;
if(!key)
{
if(shouldShellShutdown)
{
u8 shellState = I2C_readReg(I2C_DEV_MCU, 0xF);
wait(5);
if(!(shellState & 2)) mcuPowerOff();
}
u8 intStatus = I2C_readReg(I2C_DEV_MCU, 0x10);
wait(5);
if(intStatus & 1) mcuPowerOff(); //Power button pressed
oldKey = 0;
dPadDelay = 0;
continue;
}
if(key == oldKey && (!isMenu || (!(key & DPAD_BUTTONS) || chrono() - initialValue < dPadDelay))) continue;
//Make sure the key is pressed
u32 i;
for(i = 0; i < 0x13000 && key == HID_PAD; i++);
if(i == 0x13000) break;
}
return key;
}
__attribute__((noreturn)) void mcuPowerOff(void)
{
// Unmount partitions
unmountPartitions();
if(!needToSetupScreens) clearScreens(false);
//Shutdown LCD
if(ARESCREENSINITIALIZED) I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0);
//Ensure that all memory transfers have completed and that the data cache has been flushed
flushEntireDCache();
I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 0);
while(true);
}
void wait(u64 amount)
{
startChrono();
u64 initialValue = chrono();
while(chrono() - initialValue < amount);
}
void error(const char *fmt, ...)
{
char buf[DRAW_MAX_FORMATTED_STRING_SIZE + 1];
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
initScreens();
drawString(true, 10, 10, COLOR_RED, "An error has occurred:");
u32 posY = drawString(true, 10, 30, COLOR_WHITE, buf);
drawString(true, 10, posY + 2 * SPACING_Y, COLOR_WHITE, "Press any button to shutdown");
waitInput(false);
mcuPowerOff();
}
// CRC-16/MODBUS
u16 crc16(const void *data, size_t size, u16 initialValue)
{
static const u16 lut[256] = {
0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,
0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,
0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,
0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,
0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,
0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,
0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,
0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,
0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,
0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,
0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,
0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,
0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,
0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,
0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,
0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,
0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,
0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,
0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,
0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,
0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,
0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,
0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,
0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,
0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,
0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,
0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,
0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,
0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,
0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,
0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,
0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040,
};
u16 r = initialValue;
const u8 *data8 = (const u8 *)data;
for (size_t i = 0; i < size; i++)
r = (r >> 8) ^ lut[(r ^ data8[i]) & 0xFF];
return r;
}
u32 crc32(const void *data, size_t size, u32 initialValue)
{
static const u32 lut[256] = {
0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,
0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,
0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,
0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,
0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,
0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,
0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,
0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,
0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,
0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,
0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,
0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,
0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,
0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,
0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,
0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,
0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,
0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,
0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,
0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,
0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,
0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,
0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,
0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D,
};
u32 r = initialValue;
const u8 *data8 = (const u8 *)data;
for (size_t i = 0; i < size; i++)
r = (r >> 8) ^ lut[(r ^ data8[i]) & 0xFF];
return ~r;
}

View File

@ -1,6 +1,6 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
* Copyright (C) 2016-2022 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -39,7 +39,13 @@
#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 startChrono(void);
u64 chrono(void);
u32 waitInput(bool isMenu);
void mcuPowerOff(void);
void wait(u64 amount);
void error(const char *fmt, ...);
u16 crc16(const void *data, size_t size, u16 initialValue);
u32 crc32(const void *data, size_t size, u32 initialValue);

View File

@ -1,44 +0,0 @@
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/base_tools
name := $(shell basename $(CURDIR))
dir_source := source
dir_build := build
dir_out := ../$(dir_build)
ASFLAGS := -mcpu=arm946e-s
CFLAGS := -Wall -Wextra -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
LDFLAGS := -nostartfiles -Wl,--nmagic
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
$(call rwildcard, $(dir_source), *.s *.c)))
.PHONY: all
all: $(dir_out)/$(name).bin
.PHONY: clean
clean:
@rm -rf $(dir_build)
$(dir_out)/$(name).bin: $(dir_build)/$(name).elf
$(OBJCOPY) -S -O binary $< $@
$(dir_build)/$(name).elf: $(objects)
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
$(dir_build)/memory.o: CFLAGS += -O3
$(dir_build)/%.o: $(dir_source)/%.c
@mkdir -p "$(@D)"
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(dir_build)/%.o: $(dir_source)/%.s
@mkdir -p "$(@D)"
$(COMPILE.s) $(OUTPUT_OPTION) $<

View File

@ -1,21 +0,0 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x01FF9000;
__start__ = ABSOLUTE(.);
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
. = ALIGN(4);
__end__ = ABSOLUTE(.);
__stack_top__ = 0x01FFB800;
__stack_bottom__ = 0x01FFA800;
}

View File

@ -1,60 +0,0 @@
@ This file is part of Luma3DS
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
@
@ This program is free software: you can redistribute it and/or modify
@ it under the terms of the GNU General Public License as published by
@ the Free Software Foundation, either version 3 of the License, or
@ (at your option) any later version.
@
@ This program is distributed in the hope that it will be useful,
@ but WITHOUT ANY WARRANTY; without even the implied warranty of
@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@ GNU General Public License for more details.
@
@ You should have received a copy of the GNU General Public License
@ along with this program. If not, see <http://www.gnu.org/licenses/>.
@
@ Additional Terms 7.b and 7.c of GPLv3 apply to this file:
@ * Requiring preservation of specified reasonable legal notices or
@ author attributions in that material or in the Appropriate Legal
@ Notices displayed by works containing it.
@ * Prohibiting misrepresentation of the origin of that material,
@ or requiring that modified versions of such material be marked in
@ reasonable ways as different from the original version.
.text
.arm
.align 4
.global flushCaches
.type flushCaches, %function
flushCaches:
@ Clean and flush both the data cache and instruction caches
@ Adpated from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html ,
@ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well
@ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has)
@ Implemented in bootROM at addresses 0xffff0830 (DCache) and 0xffff0ab4 (ICache)
mov r1, #0 @ segment counter
outer_loop:
mov r0, #0 @ line counter
inner_loop:
orr r2, r1, r0 @ generate segment and line address
mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line
add r0, #0x20 @ increment to next line
cmp r0, #0x400
bne inner_loop
add r1, #0x40000000
cmp r1, #0
bne outer_loop
mcr p15, 0, r1, c7, c10, 4 @ drain write buffer
@ Flush instruction cache
mcr p15, 0, r1, c7, c5, 0
bx lr

View File

@ -1,42 +0,0 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#include "firm.h"
#include "memory.h"
#include "cache.h"
void disableMpuAndJumpToEntrypoints(int argc, char **argv, void *arm11Entry, void *arm9Entry);
void launchFirm(Firm *firm, int argc, char **argv)
{
//Copy FIRM sections to respective memory locations
for(u32 sectionNum = 0; sectionNum < 4; sectionNum++)
memcpy(firm->section[sectionNum].address, (u8 *)firm + firm->section[sectionNum].offset, firm->section[sectionNum].size);
disableMpuAndJumpToEntrypoints(argc, argv, firm->arm9Entry, firm->arm11Entry);
__builtin_unreachable();
}

View File

@ -1,45 +0,0 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#pragma once
#include <stdint.h>
//Common data types
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef volatile u8 vu8;
typedef volatile u16 vu16;
typedef volatile u32 vu32;
typedef volatile u64 vu64;
struct fb {
u8 *top_left;
u8 *top_right;
u8 *bottom;
};

View File

@ -1,42 +0,0 @@
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/base_tools
name := arm9_exceptions
dir_source := source
dir_build := build
dir_out := ../../$(dir_build)
ASFLAGS := -mcpu=arm946e-s
CFLAGS := -Wall -Wextra -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -Os -ffast-math
LDFLAGS := -nostartfiles -Wl,--nmagic
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
$(call rwildcard, $(dir_source), *.s *.c)))
.PHONY: all
all: $(dir_out)/$(name).bin
.PHONY: clean
clean:
@rm -rf $(dir_build)
$(dir_out)/$(name).bin: $(dir_build)/$(name).elf
$(OBJCOPY) -S -O binary $< $@
$(dir_build)/$(name).elf: $(objects)
$(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
$(dir_build)/%.o: $(dir_source)/%.c
@mkdir -p "$(@D)"
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(dir_build)/%.o: $(dir_source)/%.s
@mkdir -p "$(@D)"
$(COMPILE.s) $(OUTPUT_OPTION) $<

View File

@ -1,14 +0,0 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x01FF8000;
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
. = ALIGN(4);
}

View File

@ -1,143 +0,0 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
/*
* Thanks to whoever contributed in the development of this file
*/
#include "i2c.h"
//-----------------------------------------------------------------------------
static const struct { u8 bus_id, reg_addr; } dev_data[] = {
{0, 0x4A}, {0, 0x7A}, {0, 0x78},
{1, 0x4A}, {1, 0x78}, {1, 0x2C},
{1, 0x2E}, {1, 0x40}, {1, 0x44},
{2, 0xD6}, {2, 0xD0}, {2, 0xD2},
{2, 0xA4}, {2, 0x9A}, {2, 0xA0},
};
static inline u8 i2cGetDeviceBusId(u8 device_id)
{
return dev_data[device_id].bus_id;
}
static inline u8 i2cGetDeviceRegAddr(u8 device_id)
{
return dev_data[device_id].reg_addr;
}
//-----------------------------------------------------------------------------
static vu8 *reg_data_addrs[] = {
(vu8 *)(I2C1_REG_OFF + I2C_REG_DATA),
(vu8 *)(I2C2_REG_OFF + I2C_REG_DATA),
(vu8 *)(I2C3_REG_OFF + I2C_REG_DATA),
};
static inline vu8 *i2cGetDataReg(u8 bus_id)
{
return reg_data_addrs[bus_id];
}
//-----------------------------------------------------------------------------
static vu8 *reg_cnt_addrs[] = {
(vu8 *)(I2C1_REG_OFF + I2C_REG_CNT),
(vu8 *)(I2C2_REG_OFF + I2C_REG_CNT),
(vu8 *)(I2C3_REG_OFF + I2C_REG_CNT),
};
static inline vu8 *i2cGetCntReg(u8 bus_id)
{
return reg_cnt_addrs[bus_id];
}
//-----------------------------------------------------------------------------
static inline void i2cWaitBusy(u8 bus_id)
{
while (*i2cGetCntReg(bus_id) & 0x80);
}
static inline bool i2cGetResult(u8 bus_id)
{
i2cWaitBusy(bus_id);
return (*i2cGetCntReg(bus_id) >> 4) & 1;
}
static void i2cStop(u8 bus_id, u8 arg0)
{
*i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0;
i2cWaitBusy(bus_id);
*i2cGetCntReg(bus_id) = 0xC5;
}
//-----------------------------------------------------------------------------
static bool i2cSelectDevice(u8 bus_id, u8 dev_reg)
{
i2cWaitBusy(bus_id);
*i2cGetDataReg(bus_id) = dev_reg;
*i2cGetCntReg(bus_id) = 0xC2;
return i2cGetResult(bus_id);
}
static bool i2cSelectRegister(u8 bus_id, u8 reg)
{
i2cWaitBusy(bus_id);
*i2cGetDataReg(bus_id) = reg;
*i2cGetCntReg(bus_id) = 0xC0;
return i2cGetResult(bus_id);
}
//-----------------------------------------------------------------------------
bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data)
{
u8 bus_id = i2cGetDeviceBusId(dev_id);
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
for(u32 i = 0; i < 8; i++)
{
if(i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg))
{
i2cWaitBusy(bus_id);
*i2cGetDataReg(bus_id) = data;
*i2cGetCntReg(bus_id) = 0xC1;
i2cStop(bus_id, 0);
if(i2cGetResult(bus_id)) return true;
}
*i2cGetCntReg(bus_id) = 0xC5;
i2cWaitBusy(bus_id);
}
return false;
}

View File

@ -1,48 +0,0 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
/*
* Thanks to whoever contributed in the development of this file
*/
#pragma once
#include "types.h"
#define I2C1_REG_OFF 0x10161000
#define I2C2_REG_OFF 0x10144000
#define I2C3_REG_OFF 0x10148000
#define I2C_REG_DATA 0
#define I2C_REG_CNT 1
#define I2C_REG_CNTEX 2
#define I2C_REG_SCL 4
#define I2C_DEV_MCU 3
#define I2C_DEV_GYRO 10
#define I2C_DEV_IR 13
bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data);

View File

@ -1,39 +0,0 @@
@ This file is part of Luma3DS
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
@
@ This program is free software: you can redistribute it and/or modify
@ it under the terms of the GNU General Public License as published by
@ the Free Software Foundation, either version 3 of the License, or
@ (at your option) any later version.
@
@ This program is distributed in the hope that it will be useful,
@ but WITHOUT ANY WARRANTY; without even the implied warranty of
@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@ GNU General Public License for more details.
@
@ You should have received a copy of the GNU General Public License
@ along with this program. If not, see <http://www.gnu.org/licenses/>.
@
@ Additional Terms 7.b and 7.c of GPLv3 apply to this file:
@ * Requiring preservation of specified reasonable legal notices or
@ author attributions in that material or in the Appropriate Legal
@ Notices displayed by works containing it.
@ * Prohibiting misrepresentation of the origin of that material,
@ or requiring that modified versions of such material be marked in
@ reasonable ways as different from the original version.
.section .text.start
.align 4
.global _start
_start:
add pc, r0, #(handlers - .) @ Dummy instruction
.global BreakPtr
BreakPtr: .word 0
.global handlers
handlers:
.word FIQHandler
.word undefinedInstructionHandler
.word prefetchAbortHandler
.word dataAbortHandler

View File

@ -1,45 +0,0 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#pragma once
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
//Common data types
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef volatile u8 vu8;
typedef volatile u16 vu16;
typedef volatile u32 vu32;
typedef volatile u64 vu64;
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
#define ARESCREENSINITIALIZED (PDN_GPU_CNT != 1)

View File

@ -1,188 +0,0 @@
#!/usr/bin/env python
# Requires Python >= 3.2 or >= 2.7
# This file is part of Luma3DS
# Copyright (C) 2016 Aurora Wright, TuxSH
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified
# reasonable legal notices or author attributions in that material or in the Appropriate Legal
# Notices displayed by works containing it.
__author__ = "TuxSH"
__copyright__ = "Copyright (c) 2016 TuxSH"
__license__ = "GPLv3"
__version__ = "v1.2"
"""
Parses Luma3DS exception dumps
"""
import argparse
from struct import unpack_from
import os
import subprocess
# Source of hexdump: https://gist.github.com/ImmortalPC/c340564823f283fe530b
# Credits for hexdump go to the original authors
# Slightly edited by TuxSH
def hexdump(addr, src, length=16, sep='.' ):
'''
@brief Return {src} in hex dump.
@param[in] length {Int} Nb Bytes by row.
@param[in] sep {Char} For the text part, {sep} will be used for non ASCII char.
@return {Str} The hexdump
@note Full support for python2 and python3 !
'''
result = []
# Python3 support
try:
xrange(0,1)
except NameError:
xrange = range
for i in xrange(0, len(src), length):
subSrc = src[i:i+length]
hexa = ''
isMiddle = False
for h in xrange(0,len(subSrc)):
if h == length/2:
hexa += ' '
h = subSrc[h]
if not isinstance(h, int):
h = ord(h)
h = hex(h).replace('0x','')
if len(h) == 1:
h = '0'+h
hexa += h+' '
hexa = hexa.strip(' ')
text = ''
for c in subSrc:
if not isinstance(c, int):
c = ord(c)
if 0x20 <= c < 0x7F:
text += chr(c)
else:
text += sep
result.append(('%08x: %-'+str(length*(2+1)+1)+'s |%s|') % (addr + i, hexa, text))
return '\n'.join(result)
def makeRegisterLine(A, rA, B, rB):
return "{0:<15}{1:<20}{2:<15}{3:<20}".format(A, "{0:08x}".format(rA), B, "{0:08x}".format(rB))
handledExceptionNames = ("FIQ", "undefined instruction", "prefetch abort", "data abort")
registerNames = tuple("r{0}".format(i) for i in range(13)) + ("sp", "lr", "pc", "cpsr") + ("dfsr", "ifsr", "far") + ("fpexc", "fpinst", "fpinst2")
svcBreakReasons = ("(svcBreak: panic)", "(svcBreak: assertion failed)", "(svcBreak: user-related)")
faultStatusSources = {
0b1:'Alignment', 0b100:'Instruction cache maintenance operation fault',
0b1100:'External Abort on translation - First-level', 0b1110:'External Abort on translation - Second-level',
0b101:'Translation - Section', 0b111:'Translation - Page', 0b11:'Access bit - Section', 0b110:'Access bit - Page',
0b1001:'Domain - Section', 0b1011:'Domain - Page', 0b1101:'Permission - Section', 0b1111:'Permission - Page',
0b1000:'Precise External Abort', 0b10110:'Imprecise External Abort', 0b10:'Debug event'
}
def main(args=None):
parser = argparse.ArgumentParser(description="Parse Luma3DS exception dumps")
parser.add_argument("filename")
args = parser.parse_args()
data = b""
with open(args.filename, "rb") as f: data = f.read()
if unpack_from("<2I", data) != (0xdeadc0de, 0xdeadcafe):
raise SystemExit("Invalid file format")
version, processor, exceptionType, _, nbRegisters, codeDumpSize, stackDumpSize, additionalDataSize = unpack_from("<8I", data, 8)
nbRegisters //= 4
if version < (1 << 16) | 2:
raise SystemExit("Incompatible format version, please use the appropriate parser.")
registers = unpack_from("<{0}I".format(nbRegisters), data, 40)
codeOffset = 40 + 4 * nbRegisters
codeDump = data[codeOffset : codeOffset + codeDumpSize]
stackOffset = codeOffset + codeDumpSize
stackDump = data[stackOffset : stackOffset + stackDumpSize]
addtionalDataOffset = stackOffset + stackDumpSize
additionalData = data[addtionalDataOffset : addtionalDataOffset + additionalDataSize]
if processor == 9: print("Processor: ARM9")
else: print("Processor: ARM11 (core {0})".format(processor >> 16))
typeDetailsStr = ""
if exceptionType == 2:
if (registers[16] & 0x20) == 0 and codeDumpSize >= 4:
instr = unpack_from("<I", codeDump[-4:])[0]
if instr == 0xe12fff7e:
typeDetailsStr = " (kernel panic)"
elif instr == 0xef00003c:
typeDetailsStr = " " + (svcBreakReasons[registers[0]] if registers[0] < 3 else "(svcBreak)")
elif (registers[16] & 0x20) == 1 and codeDumpSize >= 2:
instr = unpack_from("<I", codeDump[-4:])[0]
if instr == 0xdf3c:
typeDetailsStr = " " + (svcBreakReasons[registers[0]] if registers[0] < 3 else "(svcBreak)")
elif processor != 9 and (registers[20] & 0x80000000) != 0:
typeDetailsStr = " (VFP exception)"
print("Exception type: {0}{1}".format("unknown" if exceptionType >= len(handledExceptionNames) else handledExceptionNames[exceptionType], typeDetailsStr))
if processor == 11 and exceptionType >= 2:
xfsr = registers[18] if exceptionType == 2 else registers[17]
print("Fault status: " + faultStatusSources[xfsr & 0xf])
if additionalDataSize != 0:
print("Current process: {0} ({1:016x})".format(additionalData[:8].decode("ascii"), unpack_from("<Q", additionalData, 8)[0]))
print("\nRegister dump:\n")
for i in range(0, nbRegisters - (nbRegisters % 2), 2):
if i == 16: print("")
print(makeRegisterLine(registerNames[i], registers[i], registerNames[i+1], registers[i+1]))
if nbRegisters % 2 == 1: print("{0:<15}{1:<20}".format(registerNames[nbRegisters - 1], "{0:08x}".format(registers[nbRegisters - 1])))
if processor == 11 and exceptionType == 3:
print("{0:<15}{1:<20}Access type: {2}".format("FAR", "{0:08x}".format(registers[19]), "Write" if registers[17] & (1 << 11) != 0 else "Read"))
thumb = registers[16] & 0x20 != 0
addr = registers[15] - codeDumpSize + (2 if thumb else 4)
print("\nCode dump:\n")
objdump_res = ""
try:
path = os.path.join(os.environ["DEVKITARM"], "bin", "arm-none-eabi-objdump")
if os.name == "nt" and path[0] == '/':
path = ''.join((path[1], ':', path[2:]))
objdump_res = subprocess.check_output((
path, "-marm", "-b", "binary",
"--adjust-vma="+hex(addr - codeOffset), "--start-address="+hex(addr),
"--stop-address="+hex(addr + codeDumpSize), "-D", "-z", "-M",
"reg-names-std" + (",force-thumb" if thumb else ""), args.filename
)).decode("utf-8")
objdump_res = '\n'.join(objdump_res[objdump_res.find('<.data+'):].split('\n')[1:])
except: objdump_res = ""
print(objdump_res if objdump_res != "" else hexdump(addr, codeDump))
print("\nStack dump:\n")
print(hexdump(registers[13], stackDump))
if __name__ == "__main__":
main()

View File

@ -1,13 +0,0 @@
from setuptools import setup, find_packages
setup(
name='luma3ds_exception_dump_parser',
version='1.2',
url='https://github.com/AuroraWright/Luma3DS',
author='TuxSH',
license='GPLv3',
description='Parses Luma3DS exception dumps',
install_requires=[''],
packages=find_packages(),
entry_points={'console_scripts': ['luma3ds_exception_dump_parser=luma3ds_exception_dump_parser.__main__:main']},
)

BIN
img/boot_menu_v1321.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
img/rosalina_menu_v1321.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1,47 +1,145 @@
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/base_tools
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/base_rules
name := k11_extension
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source source/svc
DATA := data
INCLUDES := include include/svc
dir_source := source
dir_include := include
dir_build := build
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
# -mgeneral-regs-only so that the C code is guaranteed not to use FPU regs
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft -mgeneral-regs-only
DEFINES := -DARM11 -D__3DS__
ARCH := -mcpu=mpcore -mfpu=vfp
ASFLAGS := $(ARCH)
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -I$(dir_include) -fno-builtin -std=c11 -Wno-main -g -flto -O2 -ffast-math \
-mword-relocations -ffunction-sections -fdata-sections
LDFLAGS := -nostdlib -Wl,--gc-sections,--nmagic $(ARCH)
FALSEPOSITIVES := -Wno-array-bounds -Wno-stringop-overflow -Wno-stringop-overread
CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \
-fomit-frame-pointer -ffunction-sections -fdata-sections \
-Wno-main $(FALSEPOSITIVES) $(ARCH) $(DEFINES)
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
$(call rwildcard, $(dir_source), *.s *.c)))
CFLAGS += $(INCLUDE)
.PHONY: all
all: ../$(dir_build)/$(name).bin
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
.PHONY: clean
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@rm -rf $(dir_build)
@echo clean ...
@rm -fr $(BUILD) $(TARGET).elf
../$(dir_build)/$(name).bin: $(dir_build)/$(name).elf
$(OBJCOPY) -S -O binary $< $@
$(dir_build)/$(name).elf: $(objects)
$(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
#---------------------------------------------------------------------------------
else
.PHONY: all
$(dir_build)/memory.o : CFLAGS += -O3 -marm
DEPENDS := $(OFILES:.o=.d)
$(dir_build)/%.o: $(dir_source)/%.c
@mkdir -p "$(@D)"
$(COMPILE.c) $(OUTPUT_OPTION) $<
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT).elf
$(dir_build)/%.o: $(dir_source)/%.s
@mkdir -p "$(@D)"
$(COMPILE.s) $(OUTPUT_OPTION) $<
include $(call rwildcard, $(dir_build), *.d)
$(OUTPUT).elf : $(OFILES)
%.elf: $(OFILES)
@echo linking $(notdir $@)
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
@$(NM) -CSn $@ > $(notdir $*.lst)
$(OFILES_SRC) : $(HFILES_BIN)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

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