Compare commits
698 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5ddc38477 | ||
|
|
8d102256a2 | ||
|
|
2e561f7ea9 | ||
|
|
9656fe1b6f | ||
|
|
48c23f2a43 | ||
|
|
6d82649c3c | ||
|
|
81dea35754 | ||
|
|
fdbe43421b | ||
|
|
0d71560785 | ||
|
|
108e8a0cd4 | ||
|
|
653e81c48e | ||
|
|
0dc0783094 | ||
|
|
13ef1bf6be | ||
|
|
7ea80353f6 | ||
|
|
07bbff7d11 | ||
|
|
2ff4fc3cdd | ||
|
|
c9456055ea | ||
|
|
2900f2d67b | ||
|
|
93c8c90804 | ||
|
|
36e54642d2 | ||
|
|
e04cb28711 | ||
|
|
ad1dc51e06 | ||
|
|
5b6bab7a58 | ||
|
|
9bd2fc659d | ||
|
|
f18633f65f | ||
|
|
1026bc7b4f | ||
|
|
f1dee68142 | ||
|
|
f7cc2d295c | ||
|
|
a6f254b5cf | ||
|
|
00dbbe1b28 | ||
|
|
7f33309903 | ||
|
|
c95808fa2d | ||
|
|
5b6bd048a9 | ||
|
|
28e6ad3372 | ||
|
|
9b128ebba5 | ||
|
|
71f49180c3 | ||
|
|
4a042241a8 | ||
|
|
0eab9127e3 | ||
|
|
9f11991410 | ||
|
|
fec0b95098 | ||
|
|
5081439f53 | ||
|
|
c44aebee4d | ||
|
|
706cd50f25 | ||
|
|
b1b81c87f2 | ||
|
|
bf7e30539e | ||
|
|
5f8a61201b | ||
|
|
ed8aee8b8c | ||
|
|
92ec2af587 | ||
|
|
7960c87579 | ||
|
|
700d572732 | ||
|
|
014a0d86f1 | ||
|
|
88db59405f | ||
|
|
ef2e008700 | ||
|
|
07101c053a | ||
|
|
6c5f6ac475 | ||
|
|
61ecd9a617 | ||
|
|
6f56a9bfe9 | ||
|
|
416875ee46 | ||
|
|
c875b506ea | ||
|
|
ff4517e583 | ||
|
|
92cc989dc9 | ||
|
|
6e5987e3ca | ||
|
|
f03e232b90 | ||
|
|
1eb18c1790 | ||
|
|
3076d56973 | ||
|
|
b35707edf9 | ||
|
|
dfbd0dc9e7 | ||
|
|
620ad7ba71 | ||
|
|
5e4fd53243 | ||
|
|
0ba7630354 | ||
|
|
028d0ec0d5 | ||
|
|
751fa05fcd | ||
|
|
f89845257e | ||
|
|
2f274e2f47 | ||
|
|
38088e80e1 | ||
|
|
14162828ea | ||
|
|
ab8507e09d | ||
|
|
0d25c07333 | ||
|
|
bfc8ba8447 | ||
|
|
a45f8293d9 | ||
|
|
f29b9d14d7 | ||
|
|
9c9fd2deef | ||
|
|
3bb01ffd68 | ||
|
|
bc6d9994dc | ||
|
|
e177f9e0fe | ||
|
|
c5d75d2de9 | ||
|
|
cc0cade4d2 | ||
|
|
1e3362250f | ||
|
|
db16e8d602 | ||
|
|
2a563eddd0 | ||
|
|
6b8474b7b9 | ||
|
|
b5336c81cc | ||
|
|
1fcab825bf | ||
|
|
0306556032 | ||
|
|
b093578046 | ||
|
|
9332b9eb33 | ||
|
|
141c7817a0 | ||
|
|
f155026d8f | ||
|
|
37e467ba60 | ||
|
|
3572b835b5 | ||
|
|
da4f3a72af | ||
|
|
2938bbd11f | ||
|
|
abf3017eb2 | ||
|
|
5c855ea52f | ||
|
|
c83edea7ad | ||
|
|
6d3113c8c3 | ||
|
|
48c48c7bbc | ||
|
|
e4093ed988 | ||
|
|
c79af52720 | ||
|
|
61eeaca6d5 | ||
|
|
320a79ba72 | ||
|
|
2e1b943805 | ||
|
|
bc167dde2d | ||
|
|
7d9a8b4211 | ||
|
|
0b16d88756 | ||
|
|
796cb31ed7 | ||
|
|
d7fd2f26c1 | ||
|
|
5adb8749de | ||
|
|
3474faa4a2 | ||
|
|
acd9c04ff6 | ||
|
|
833c9406b0 | ||
|
|
2f1253e27f | ||
|
|
53b847e31c | ||
|
|
7efa33dd7f | ||
|
|
4011970a57 | ||
|
|
a2cfa2be16 | ||
|
|
c4b691d688 | ||
|
|
72a7a8eee5 | ||
|
|
52d352385f | ||
|
|
c1f85650bd | ||
|
|
b830909504 | ||
|
|
4ad6b1c220 | ||
|
|
429488a4ba | ||
|
|
40c6cc11a5 | ||
|
|
594881c6ce | ||
|
|
1cc64a0fbc | ||
|
|
f492318e3c | ||
|
|
4b06bb7795 | ||
|
|
f7e570383a | ||
|
|
896a088199 | ||
|
|
f3322bd003 | ||
|
|
cef947d67d | ||
|
|
b6640d118d | ||
|
|
273d0b2ce9 | ||
|
|
9b724d776e | ||
|
|
3eaa706ccf | ||
|
|
b4c854dfe8 | ||
|
|
9cdadbe834 | ||
|
|
b3f38a8764 | ||
|
|
5d868284c6 | ||
|
|
035751980d | ||
|
|
6b80bc08d5 | ||
|
|
2089959d1b | ||
|
|
67b00ec28d | ||
|
|
127ae6b945 | ||
|
|
4f53b3ce35 | ||
|
|
c3092b482a | ||
|
|
080219f88d | ||
|
|
3fd783cd01 | ||
|
|
211cd964d7 | ||
|
|
04f42f0be4 | ||
|
|
e00ef893d0 | ||
|
|
858efa604e | ||
|
|
b63b17c54f | ||
|
|
f0e111c20e | ||
|
|
7339f57138 | ||
|
|
1e39c999f9 | ||
|
|
62f7a06192 | ||
|
|
a0531b7930 | ||
|
|
0619d04939 | ||
|
|
cd76476d26 | ||
|
|
53b6c17e33 | ||
|
|
3b7b66b272 | ||
|
|
a795a45c34 | ||
|
|
b58cbd228c | ||
|
|
fc994285f9 | ||
|
|
d5e74b91c7 | ||
|
|
c5eb2e1070 | ||
|
|
d613cb057e | ||
|
|
121792bebe | ||
|
|
e07c230106 | ||
|
|
d5ce3044c8 | ||
|
|
98ff43b4d2 | ||
|
|
1704fbcd62 | ||
|
|
014ac1cf72 | ||
|
|
b499c7ee75 | ||
|
|
2e069e326c | ||
|
|
e47d42da22 | ||
|
|
615e5dfaa7 | ||
|
|
fde2c371ef | ||
|
|
a0b4e7fd5d | ||
|
|
45c36bbcae | ||
|
|
66c041ad93 | ||
|
|
32d5c52b5f | ||
|
|
9cf5b01633 | ||
|
|
d4cf22d370 | ||
|
|
973640f023 | ||
|
|
248ea82f76 | ||
|
|
a868079a93 | ||
|
|
d270d5b9ca | ||
|
|
e9692a438b | ||
|
|
06ea123dbd | ||
|
|
85141d5eda | ||
|
|
fa13b8fbd0 | ||
|
|
5b4712644a | ||
|
|
aa422914bd | ||
|
|
22c453e297 | ||
|
|
e5f40cec5a | ||
|
|
50b24bf6c2 | ||
|
|
b575ee9e28 | ||
|
|
37030621ac | ||
|
|
f005da4d12 | ||
|
|
6295559d9c | ||
|
|
f36ff303d9 | ||
|
|
1a62e91c01 | ||
|
|
7f314dfe11 | ||
|
|
0caf9f4214 | ||
|
|
1ad600c81a | ||
|
|
bd6c7b7fdb | ||
|
|
5f93724845 | ||
|
|
ad60eac6ef | ||
|
|
b3e3a2937a | ||
|
|
d010038228 | ||
|
|
c28eada93e | ||
|
|
9d84a92b1f | ||
|
|
7884be106d | ||
|
|
5fe7c7e7e1 | ||
|
|
f244b95aad | ||
|
|
3b5a5759b8 | ||
|
|
528e7ee33b | ||
|
|
c1f55735fc | ||
|
|
185ea86284 | ||
|
|
618262f015 | ||
|
|
c0f41ac10e | ||
|
|
3010699f20 | ||
|
|
fb274538e1 | ||
|
|
1a5d953a98 | ||
|
|
2dd1baebb3 | ||
|
|
d46beac22a | ||
|
|
6ed8741006 | ||
|
|
6845e42f2c | ||
|
|
5196869634 | ||
|
|
083806bfc9 | ||
|
|
11d29368ce | ||
|
|
100c3d9e36 | ||
|
|
01fbf8c3a5 | ||
|
|
a36556d7e4 | ||
|
|
4f11162fae | ||
|
|
2cbaf39fd5 | ||
|
|
2cc46c618b | ||
|
|
a0325e91f9 | ||
|
|
e11edd5dee | ||
|
|
5e8990f571 | ||
|
|
a3fd55036a | ||
|
|
7a3d15c48b | ||
|
|
a5b52a2470 | ||
|
|
a8cd14dafd | ||
|
|
2b249bd496 | ||
|
|
c8586cfe26 | ||
|
|
f228cb241f | ||
|
|
fd33ef8496 | ||
|
|
ba1cf6473a | ||
|
|
f418dcdb7b | ||
|
|
f91c26d752 | ||
|
|
f7156f2ff2 | ||
|
|
e444b587cf | ||
|
|
a7fcc6a5cf | ||
|
|
872b1ccbb6 | ||
|
|
b7b3400296 | ||
|
|
420ccdcb82 | ||
|
|
eaa4d6323e | ||
|
|
4e7ac41a6c | ||
|
|
92f3a736a7 | ||
|
|
5a30b2b298 | ||
|
|
85aaae67bf | ||
|
|
efe66bc72e | ||
|
|
d7bdf3fc19 | ||
|
|
c4e5f4410c | ||
|
|
f5039dca56 | ||
|
|
de6f9789cb | ||
|
|
4376a1093f | ||
|
|
a413ed01f3 | ||
|
|
05bb831321 | ||
|
|
6e0f1e5235 | ||
|
|
2f915401dd | ||
|
|
14152b3072 | ||
|
|
8f3cba37b3 | ||
|
|
0853f6f7ad | ||
|
|
ae7a7ba365 | ||
|
|
724af0fdc4 | ||
|
|
550ea2116e | ||
|
|
7952271d61 | ||
|
|
ffaa5790c2 | ||
|
|
934c4bed0b | ||
|
|
6f040caa98 | ||
|
|
50e5c29b1c | ||
|
|
e0b5539b91 | ||
|
|
050f58a3bb | ||
|
|
c739ed8e48 | ||
|
|
a09fc6ebcb | ||
|
|
4367ea6afa | ||
|
|
da0adeb39e | ||
|
|
63160a22a6 | ||
|
|
2bc1927ebd | ||
|
|
66e0cfc185 | ||
|
|
7bd0e4f5b4 | ||
|
|
7271850df2 | ||
|
|
8c79285774 | ||
|
|
56a77ceac1 | ||
|
|
3034420ac2 | ||
|
|
99a157649d | ||
|
|
e6645554f0 | ||
|
|
0f83d1ffaa | ||
|
|
2286eb21a7 | ||
|
|
64c81aa5f8 | ||
|
|
29dcfca608 | ||
|
|
f1cb9630ec | ||
|
|
ebbea57400 | ||
|
|
6016dc14f8 | ||
|
|
dc8e4e5f14 | ||
|
|
72c8212a0e | ||
|
|
2cd2a081d6 | ||
|
|
b44ec544f4 | ||
|
|
063eae7e95 | ||
|
|
2552572904 | ||
|
|
b74dda42a2 | ||
|
|
6e178e2069 | ||
|
|
277d723992 | ||
|
|
2f6afe9932 | ||
|
|
edcc617780 | ||
|
|
5d39242b83 | ||
|
|
ddbe5fd27b | ||
|
|
deb91d1d02 | ||
|
|
63073ea07f | ||
|
|
a331fcd873 | ||
|
|
99654bd5b2 | ||
|
|
f10427287f | ||
|
|
5b6318ee3a | ||
|
|
98cdbe0784 | ||
|
|
e4eb3ae38d | ||
|
|
6686e4add7 | ||
|
|
96a274bf7d | ||
|
|
add17a7994 | ||
|
|
26e404c6a2 | ||
|
|
144de8b328 | ||
|
|
c0226e6fd9 | ||
|
|
57d728a9be | ||
|
|
b2e9f5377b | ||
|
|
d3d315784c | ||
|
|
942a371b6a | ||
|
|
66ffc78f60 | ||
|
|
a9570cef14 | ||
|
|
16bc08f046 | ||
|
|
024335e5cd | ||
|
|
8f32048774 | ||
|
|
33d3dd256d | ||
|
|
fc151f7595 | ||
|
|
9152884815 | ||
|
|
2b4e97bec5 | ||
|
|
a63393504f | ||
|
|
97ae8d2d44 | ||
|
|
6c59728516 | ||
|
|
201fe05a06 | ||
|
|
a78889523f | ||
|
|
5cd1a207c9 | ||
|
|
423f0ca631 | ||
|
|
7612e38d41 | ||
|
|
bf234950cb | ||
|
|
bd992fca15 | ||
|
|
45fee57abd | ||
|
|
a2bca96d47 | ||
|
|
9862256ca7 | ||
|
|
6afc8b3b5c | ||
|
|
9b4b4ec543 | ||
|
|
d412711868 | ||
|
|
0b33551d94 | ||
|
|
9c1b585054 | ||
|
|
fc3a69d9ca | ||
|
|
cce4a6d07f | ||
|
|
b16539408b | ||
|
|
eba56d0f64 | ||
|
|
f2181b1d3e | ||
|
|
c93a97f8d7 | ||
|
|
8fd2525cd1 | ||
|
|
62a70cfdac | ||
|
|
ca0a79fc89 | ||
|
|
104b8e859f | ||
|
|
a99b26ff8c | ||
|
|
9bc62ec12d | ||
|
|
84a6bb772f | ||
|
|
263a5eda56 | ||
|
|
7fb17ce52f | ||
|
|
631fad24c0 | ||
|
|
f1d77fa62a | ||
|
|
3bc247b43b | ||
|
|
3608799dff | ||
|
|
c0f042bc2a | ||
|
|
8982ff259a | ||
|
|
726b06b748 | ||
|
|
0057ab9c5a | ||
|
|
048bf0ee4d | ||
|
|
4da0708b51 | ||
|
|
4c529e3145 | ||
|
|
8ceeca372f | ||
|
|
4326ac9be1 | ||
|
|
697c64abe4 | ||
|
|
7e8cf84c42 | ||
|
|
b6d91375a5 | ||
|
|
61305688fd | ||
|
|
492ae4139f | ||
|
|
a84f393bd5 | ||
|
|
5de54d6f9f | ||
|
|
8fc797120f | ||
|
|
5406d648bc | ||
|
|
a2003fba95 | ||
|
|
a76c15d018 | ||
|
|
ae8caf3d3a | ||
|
|
f221915a95 | ||
|
|
7f93733107 | ||
|
|
e8b9e49f57 | ||
|
|
cb9576b10e | ||
|
|
06fe06f9f1 | ||
|
|
abf7c8e565 | ||
|
|
46227e6763 | ||
|
|
2ffe4a5451 | ||
|
|
18bd4bbcf6 | ||
|
|
8209433696 | ||
|
|
ad9e00acaa | ||
|
|
c96f96258f | ||
|
|
82699f3e00 | ||
|
|
e2d828a4a2 | ||
|
|
92328c6a7e | ||
|
|
3f8ad17e86 | ||
|
|
52999db43a | ||
|
|
760aa99709 | ||
|
|
51c514de84 | ||
|
|
317899b4bf | ||
|
|
4c93d2b1f9 | ||
|
|
71c5404bfe | ||
|
|
9c5248b87a | ||
|
|
83a0293af4 | ||
|
|
84f3eddaf8 | ||
|
|
a5c6b908b6 | ||
|
|
94f0d873df | ||
|
|
d6f66d24fa | ||
|
|
31458e9938 | ||
|
|
dca612ffd7 | ||
|
|
5177308d48 | ||
|
|
59ab44a8c7 | ||
|
|
c711ed6253 | ||
|
|
58c6be17eb | ||
|
|
259bcc686c | ||
|
|
356268eae5 | ||
|
|
2dd64b8a92 | ||
|
|
b5cddedb7d | ||
|
|
7afdc2b3b5 | ||
|
|
60c4956290 | ||
|
|
4c6a2f7ab1 | ||
|
|
76cee0d95b | ||
|
|
7331a919e4 | ||
|
|
27ea6b96c4 | ||
|
|
33238cee54 | ||
|
|
384dd2ad81 | ||
|
|
4885e0b8d8 | ||
|
|
2a84911d3b | ||
|
|
7f672fb417 | ||
|
|
a13fdeecf6 | ||
|
|
74ac76ba84 | ||
|
|
253e031f83 | ||
|
|
ef1ecf859c | ||
|
|
a302ad3bea | ||
|
|
0951260df7 | ||
|
|
b87dadbb72 | ||
|
|
1dd6a9821a | ||
|
|
50a2424001 | ||
|
|
61e5a4444f | ||
|
|
de3eb6ccd7 | ||
|
|
4f8c66b2b7 | ||
|
|
4d9cbc4e19 | ||
|
|
40369d44df | ||
|
|
ee3720f0b7 | ||
|
|
e5dcca1c2b | ||
|
|
ef8438a214 | ||
|
|
dfd699c16b | ||
|
|
a381c2a811 | ||
|
|
e4c87a59d0 | ||
|
|
eef30ceb3c | ||
|
|
76411387ba | ||
|
|
8d5d8d2100 | ||
|
|
802bce12a7 | ||
|
|
a1024c288e | ||
|
|
a4531b01d5 | ||
|
|
d445b20e90 | ||
|
|
24ddf5ca3d | ||
|
|
bb117d3d74 | ||
|
|
c101653077 | ||
|
|
5248b96f8a | ||
|
|
7ab59e420a | ||
|
|
83a849126a | ||
|
|
c9c373f607 | ||
|
|
aa7c2c0009 | ||
|
|
57fc4df86f | ||
|
|
75acdc8a98 | ||
|
|
070f7fcc68 | ||
|
|
4d48238fb1 | ||
|
|
9b304404f7 | ||
|
|
8e5ced8e3c | ||
|
|
95ef379ac5 | ||
|
|
915f9ccb0d | ||
|
|
3709ac301a | ||
|
|
3bc966f84e | ||
|
|
457b4cec13 | ||
|
|
88891ef6cd | ||
|
|
25811e2b52 | ||
|
|
f81c92e35b | ||
|
|
39b2aff627 | ||
|
|
905777466d | ||
|
|
4e21cf4f1c | ||
|
|
eccf9eab93 | ||
|
|
c36ad54bcb | ||
|
|
81e2b7c11c | ||
|
|
18b5cdcddf | ||
|
|
fe31114779 | ||
|
|
df30a2a320 | ||
|
|
cf7fa8ecbd | ||
|
|
389a169443 | ||
|
|
e01802e299 | ||
|
|
709aefba5d | ||
|
|
e4ed713fce | ||
|
|
d3c507b0d4 | ||
|
|
a68e14def3 | ||
|
|
8175642a2a | ||
|
|
8d1befea9e | ||
|
|
e7b8a0ef39 | ||
|
|
be6ee894f9 | ||
|
|
e0e8ed2113 | ||
|
|
c63e46b1a9 | ||
|
|
eb9c74a1ed | ||
|
|
efd83e063e | ||
|
|
ae23a1c84d | ||
|
|
fd1253caac | ||
|
|
a0e8bc1de3 | ||
|
|
004f0652c9 | ||
|
|
d5190cd788 | ||
|
|
2412faf033 | ||
|
|
72caad86cc | ||
|
|
7df9917a00 | ||
|
|
575adcbb9d | ||
|
|
2d6debddb9 | ||
|
|
53d2aac2ae | ||
|
|
96211813e3 | ||
|
|
153bbd6242 | ||
|
|
730e716f0f | ||
|
|
2238293c0f | ||
|
|
29d8e637d8 | ||
|
|
136e0d8974 | ||
|
|
0eb87df84f | ||
|
|
a9db998d84 | ||
|
|
fcb8edffdf | ||
|
|
61684ecb68 | ||
|
|
0ced86b55f | ||
|
|
159c9cb475 | ||
|
|
2943dcb2e9 | ||
|
|
984c3e549c | ||
|
|
edfd63e1f7 | ||
|
|
e593584a47 | ||
|
|
ef60c8ea4c | ||
|
|
e478908dca | ||
|
|
ca587692eb | ||
|
|
f78dd5365c | ||
|
|
f9d6cdccb0 | ||
|
|
35fdd470b3 | ||
|
|
edff11be7b | ||
|
|
bb230de72c | ||
|
|
2d7dde9cf9 | ||
|
|
b77d619873 | ||
|
|
ae1033d975 | ||
|
|
99d28c4f79 | ||
|
|
2424865fa1 | ||
|
|
6a280723f8 | ||
|
|
f85bbfff58 | ||
|
|
d239d82379 | ||
|
|
9017de6082 | ||
|
|
477414a636 | ||
|
|
5fac49447c | ||
|
|
30b3a51309 | ||
|
|
bafba1197e | ||
|
|
2fab0be5e8 | ||
|
|
7ea2a0a278 | ||
|
|
a3ae38520c | ||
|
|
c36fa01651 | ||
|
|
9aeac7af92 | ||
|
|
859944dc8e | ||
|
|
a6dc3c8fc7 | ||
|
|
61c02ed079 | ||
|
|
afc6f51ff2 | ||
|
|
c32eefaa51 | ||
|
|
b6969cf0d1 | ||
|
|
58a33ee6e9 | ||
|
|
050f433046 | ||
|
|
d48f6b62ce | ||
|
|
ffee64c67f | ||
|
|
8cbc535755 | ||
|
|
ca07af2fe9 | ||
|
|
2fe5da97eb | ||
|
|
6ffaeadd1b | ||
|
|
2c10b6bff2 | ||
|
|
76acfd9934 | ||
|
|
06cc4f7172 | ||
|
|
158659e5b0 | ||
|
|
7e46046e3b | ||
|
|
808c4b7361 | ||
|
|
03dc4fc425 | ||
|
|
b4029dcd73 | ||
|
|
1750b256eb | ||
|
|
d00d82ac89 | ||
|
|
edb5a82a89 | ||
|
|
f7552f7c32 | ||
|
|
4483b65b25 | ||
|
|
d2f53626ae | ||
|
|
ac01fe417e | ||
|
|
2fd8c7aace | ||
|
|
b90b138766 | ||
|
|
c3ad7eda08 | ||
|
|
02c6a3c214 | ||
|
|
8dd9c1a1af | ||
|
|
be54052b6d | ||
|
|
9e87679ee2 | ||
|
|
17964f8cd1 | ||
|
|
a63fb971d4 | ||
|
|
4b500349e6 | ||
|
|
8e554e17c9 | ||
|
|
1d77206ae4 | ||
|
|
4340c326dc | ||
|
|
c6cb97ae30 | ||
|
|
9d68c980e6 | ||
|
|
e2596a0a61 | ||
|
|
17d3c6491a | ||
|
|
f55fc421ea | ||
|
|
169b12fc20 | ||
|
|
905f816bbe | ||
|
|
fef48a449a | ||
|
|
95d06c115a | ||
|
|
113059e57c | ||
|
|
408c70b90c | ||
|
|
5b51574ebf | ||
|
|
1e6d7a5aee | ||
|
|
a28b50cee8 | ||
|
|
df112b550b | ||
|
|
85615d1916 | ||
|
|
c6d3158b56 | ||
|
|
4a4de608ec | ||
|
|
e651c3d9cc | ||
|
|
9c12496b30 | ||
|
|
bfc2448662 | ||
|
|
faa04b0309 | ||
|
|
ca1ea7fd6e | ||
|
|
57dc1b09ad | ||
|
|
5a9d0e2569 | ||
|
|
f6d3abbc11 | ||
|
|
041ca8451e | ||
|
|
9ab3a7c451 | ||
|
|
2382e6d82c | ||
|
|
f0e1937eeb | ||
|
|
efd08ff731 | ||
|
|
f9a1f1a79b | ||
|
|
a736e4602a | ||
|
|
5202ba8826 | ||
|
|
0f1bc98bb7 | ||
|
|
d40722af53 | ||
|
|
c9781ab626 | ||
|
|
4cbf4e93e7 | ||
|
|
1f68c2da42 | ||
|
|
d786c292f3 | ||
|
|
ada3e09784 | ||
|
|
c928b3b68b | ||
|
|
ae9c29629c | ||
|
|
3fd4603553 | ||
|
|
c14526068a | ||
|
|
180b2a6f4d | ||
|
|
b926ab7dd2 | ||
|
|
19d8861d27 | ||
|
|
70e82e627b | ||
|
|
67e229e5a9 | ||
|
|
d0d6baaa85 | ||
|
|
fd4352a1d6 | ||
|
|
08808da741 | ||
|
|
a11124a3d6 | ||
|
|
d2d6e786c7 | ||
|
|
a76c943c01 | ||
|
|
3c64a3a234 | ||
|
|
06060c67b5 | ||
|
|
0f64fd73ec | ||
|
|
2323528975 | ||
|
|
22b38a0f88 | ||
|
|
034c0f8d7c | ||
|
|
b4cd67cb8c | ||
|
|
be83d77187 |
19
.github/ISSUE_TEMPLATE.md
vendored
Normal file
19
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<!--
|
||||
#
|
||||
# THIS IS NOT A SUPPORT FORUM! For support please go to:
|
||||
# Luma3DS GBATemp thread: https://gbatemp.net/threads/luma3ds-noob-proof-3ds-custom-firmware.411110/
|
||||
# /r/3dshacks: http://reddit.com/r/3dshacks/
|
||||
# Nintendo Hacking: https://discordapp.com/invite/C29hYvh
|
||||
# IRC: #3dshacks@rizon
|
||||
#
|
||||
# Also check the Wiki (https://github.com/AuroraWright/Luma3DS/wiki) before making an issue.
|
||||
#
|
||||
# For those with GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: https://3ds.guide/troubleshooting
|
||||
#
|
||||
# Please make sure to read "Enable region/language emulation and external .code" https://github.com/AuroraWright/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable region/language emulation and external .code" option(s).
|
||||
# Keep in mind that Wiki page only applies to nightly builds. It will NOT WORK with 6.6 Stable Luma3DS.
|
||||
# As of 0.02 (https://github.com/Possum/LumaLocaleSwitcher/releases) LumaLocaleSwitcher's path(s) are for 6.6 Stable and won't work with Luma3DS nightly builds newer or equal to https://github.com/AuroraWright/Luma3DS/commit/b5336c81cc82b6c5e8115249342beb5b065cdce9.
|
||||
# Use this version for Luma3DS nightlies newer or equal to https://github.com/AuroraWright/Luma3DS/commit/b5336c81cc82b6c5e8115249342beb5b065cdce9 :
|
||||
# https://puu.sh/uC5zW/5470adc347.7z (from https://github.com/Possum/LumaLocaleSwitcher/issues/9#issuecomment-285564014)
|
||||
#
|
||||
-->
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,12 +1,13 @@
|
||||
out
|
||||
build
|
||||
loader/build
|
||||
screeninit/build
|
||||
injector/build
|
||||
exceptions/arm9/build
|
||||
exceptions/arm11/build
|
||||
haxloader/build
|
||||
*.bin
|
||||
*.3dsx
|
||||
*.smdh
|
||||
*.o
|
||||
*.d
|
||||
*.elf
|
||||
*.bat
|
||||
*.elf
|
||||
15
.gitmodules
vendored
15
.gitmodules
vendored
@@ -1,6 +1,9 @@
|
||||
[submodule "CakeBrah"]
|
||||
path = CakeBrah
|
||||
url = https://github.com/mid-kid/CakeBrah
|
||||
[submodule "CakeHax"]
|
||||
path = CakeHax
|
||||
url = https://github.com/mid-kid/CakeHax
|
||||
[submodule "haxloader/CakeBrah"]
|
||||
path = haxloader/CakeBrah
|
||||
url = https://github.com/mid-kid/CakeBrah.git
|
||||
[submodule "haxloader/CakeHax"]
|
||||
path = haxloader/CakeHax
|
||||
url = https://github.com/mid-kid/CakeHax.git
|
||||
[submodule "haxloader/CakesROP"]
|
||||
path = haxloader/CakesROP
|
||||
url = https://github.com/mid-kid/CakesROP.git
|
||||
|
||||
1
CakeBrah
1
CakeBrah
Submodule CakeBrah deleted from 42ebe0d0bc
1
CakeHax
1
CakeHax
Submodule CakeHax deleted from 6b8fca0b37
137
Makefile
137
Makefile
@@ -4,125 +4,114 @@ ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
include $(DEVKITARM)/base_tools
|
||||
|
||||
CC := arm-none-eabi-gcc
|
||||
AS := arm-none-eabi-as
|
||||
LD := arm-none-eabi-ld
|
||||
OC := arm-none-eabi-objcopy
|
||||
|
||||
name := AuReiNand
|
||||
version := $(shell git describe --abbrev=0 --tags)
|
||||
name := Luma3DS
|
||||
revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/i')
|
||||
commit := $(shell git rev-parse --short=8 HEAD)
|
||||
|
||||
dir_source := source
|
||||
dir_patches := patches
|
||||
dir_loader := loader
|
||||
dir_screeninit := screeninit
|
||||
dir_injector := injector
|
||||
dir_mset := CakeHax
|
||||
dir_ninjhax := CakeBrah
|
||||
dir_exceptions := exceptions
|
||||
dir_arm9_exceptions := $(dir_exceptions)/arm9
|
||||
dir_arm11_exceptions := $(dir_exceptions)/arm11
|
||||
dir_haxloader := haxloader
|
||||
dir_build := build
|
||||
dir_out := out
|
||||
|
||||
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||
ASFLAGS := -mcpu=arm946e-s
|
||||
CFLAGS := -Wall -Wextra $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||
LDFLAGS := -nostartfiles
|
||||
FLAGS := name=$(name).dat dir_out=$(abspath $(dir_out)) ICON=$(abspath icon.png) APP_DESCRIPTION="Noob-friendly 3DS CFW." APP_AUTHOR="Reisyukaku/Aurora Wright" --no-print-directory
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
|
||||
bundled = $(dir_build)/patches.h $(dir_build)/loader.h $(dir_build)/screeninit.h
|
||||
bundled = $(dir_build)/reboot.bin.o $(dir_build)/emunand.bin.o $(dir_build)/svcGetCFWInfo.bin.o $(dir_build)/k11modules.bin.o \
|
||||
$(dir_build)/injector.bin.o $(dir_build)/loader.bin.o $(dir_build)/arm9_exceptions.bin.o $(dir_build)/arm11_exceptions.bin.o
|
||||
|
||||
define bin2o
|
||||
bin2s $< | $(AS) -o $(@)
|
||||
endef
|
||||
|
||||
.PHONY: all
|
||||
all: launcher a9lh ninjhax
|
||||
all: a9lh haxloader
|
||||
|
||||
.PHONY: launcher
|
||||
launcher: $(dir_out)/$(name).dat
|
||||
.PHONY: release
|
||||
release: $(dir_out)/$(name)$(revision).7z
|
||||
|
||||
.PHONY: a9lh
|
||||
a9lh: $(dir_out)/arm9loaderhax.bin
|
||||
|
||||
.PHONY: ninjhax
|
||||
ninjhax: $(dir_out)/3ds/$(name)
|
||||
|
||||
.PHONY: release
|
||||
release: $(dir_out)/$(name).zip
|
||||
|
||||
.PHONY: pathchanger
|
||||
pathchanger: $(dir_out)/pathchanger
|
||||
.PHONY: haxloader
|
||||
haxloader: a9lh
|
||||
@$(MAKE) name=$(name) -C $(dir_haxloader)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
||||
@$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean
|
||||
@$(MAKE) -C $(dir_haxloader) clean
|
||||
@$(MAKE) -C $(dir_loader) clean
|
||||
@$(MAKE) -C $(dir_screeninit) clean
|
||||
@$(MAKE) -C $(dir_arm9_exceptions) clean
|
||||
@$(MAKE) -C $(dir_arm11_exceptions) clean
|
||||
@$(MAKE) -C $(dir_injector) clean
|
||||
@rm -rf $(dir_out) $(dir_build)
|
||||
|
||||
$(dir_out):
|
||||
@mkdir -p "$(dir_out)/aurei/payloads"
|
||||
.PRECIOUS: $(dir_build)/%.bin
|
||||
|
||||
$(dir_out)/pathchanger: $(dir_out)
|
||||
@cc pathchanger/pathchanger.c -o out/pathchanger
|
||||
.PHONY: $(dir_loader)
|
||||
.PHONY: $(dir_arm9_exceptions)
|
||||
.PHONY: $(dir_arm11_exceptions)
|
||||
.PHONY: $(dir_injector)
|
||||
|
||||
$(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out)
|
||||
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
|
||||
@dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
|
||||
$(dir_out) $(dir_build):
|
||||
@mkdir -p "$@"
|
||||
|
||||
$(dir_out)/$(name)$(revision).7z: all
|
||||
@7z a -mx $@ ./$(@D)/* ./$(dir_exceptions)/exception_dump_parser.py
|
||||
|
||||
$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out)
|
||||
@cp -a $(dir_build)/main.bin $@
|
||||
|
||||
$(dir_out)/3ds/$(name): $(dir_out)
|
||||
@mkdir -p "$@"
|
||||
@$(MAKE) $(FLAGS) -C $(dir_ninjhax)
|
||||
@mv $(dir_out)/$(name).3dsx $(dir_out)/$(name).smdh $@
|
||||
|
||||
$(dir_out)/$(name).zip: launcher a9lh ninjhax
|
||||
@cd "$(@D)" && zip -9 -r $(name) *
|
||||
|
||||
$(dir_build)/main.bin: $(dir_build)/main.elf
|
||||
$(OC) -S -O binary $< $@
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
$(dir_build)/main.elf: $(objects)
|
||||
$(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
$(dir_build)/main.elf: $(bundled) $(objects)
|
||||
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
||||
$(dir_build)/patches.h: $(dir_patches)/emunand.s $(dir_patches)/reboot.s $(dir_injector)/Makefile
|
||||
@mkdir -p "$(@D)"
|
||||
$(dir_build)/%.bin.o: $(dir_build)/%.bin
|
||||
@$(bin2o)
|
||||
|
||||
$(dir_build)/injector.bin: $(dir_injector) $(dir_build)
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/loader.bin: $(dir_loader) $(dir_build)
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/arm9_exceptions.bin: $(dir_arm9_exceptions) $(dir_build)
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/arm11_exceptions.bin: $(dir_arm11_exceptions) $(dir_build)
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/%.bin: $(dir_patches)/%.s $(dir_build)
|
||||
@armips $<
|
||||
@armips $(word 2,$^)
|
||||
@$(MAKE) -C $(dir_injector)
|
||||
@mv emunand.bin reboot.bin $(dir_injector)/injector.cxi $(@D)
|
||||
@bin2c -o $@ -n emunand $(@D)/emunand.bin -n reboot $(@D)/reboot.bin -n injector $(@D)/injector.cxi
|
||||
|
||||
$(dir_build)/loader.h: $(dir_loader)/Makefile
|
||||
@$(MAKE) -C $(dir_loader)
|
||||
@mv $(dir_loader)/loader.bin $(@D)
|
||||
@bin2c -o $@ -n loader $(@D)/loader.bin
|
||||
$(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3
|
||||
$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configuration\""
|
||||
$(dir_build)/patches.o: CFLAGS += -DREVISION=\"$(revision)\" -DCOMMIT_HASH="0x$(commit)"
|
||||
|
||||
$(dir_build)/screeninit.h: $(dir_screeninit)/Makefile
|
||||
@$(MAKE) -C $(dir_screeninit)
|
||||
@mv $(dir_screeninit)/screeninit.bin $(@D)
|
||||
@bin2c -o $@ -n screeninit $(@D)/screeninit.bin
|
||||
$(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)/memory.o : CFLAGS += -O3
|
||||
$(dir_build)/config.o : CFLAGS += -DCONFIG_TITLE="\"$(name) $(version) configuration\""
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.c $(bundled)
|
||||
$(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) $<
|
||||
|
||||
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||
include $(call rwildcard, $(dir_build), *.d)
|
||||
|
||||
46
README.md
46
README.md
@@ -1,36 +1,38 @@
|
||||
# AuReiNand
|
||||
*A modification of the ReiNand custom firmware*
|
||||
# Luma3DS
|
||||
*Noob-proof (N)3DS "Custom Firmware"*
|
||||
|
||||
**Compiling:**
|
||||
## What it is
|
||||
|
||||
You'll need armips and [bin2c](https://sourceforge.net/projects/bin2c/) added to your Path. [HERE](http://www91.zippyshare.com/v/ePGpjk9r/file.html) is a pre-compiled version of armips.
|
||||
**Luma3DS** is a program to patch the system software of (New) Nintendo 3DS handheld consoles "on the fly", adding features (such as per-game language settings and debugging capabilities for developers) and removing restrictions enforced by Nintendo (such as the region lock).
|
||||
It also allows you to run unauthorized ("homebrew") content by removing signature checks.
|
||||
To use it, you will need a console capable of running homebrew software on the ARM9 processor. We recommend [Plailect's guide](https://3ds.guide/) for details on how to get your system ready.
|
||||
|
||||
You also need to have a recent build of makerom in your path for the injector to be built.
|
||||
---
|
||||
|
||||
Lastly, just run Make and everything should work!
|
||||
## Compiling
|
||||
|
||||
Copy everything in 'out' folder to SD root and run!
|
||||
First you need to clone the repository recursively with: `git clone --recursive 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.
|
||||
For now, you'll also need to update your [libctru](https://github.com/smealum/ctrulib) install, building from the latest commit.
|
||||
For your convenience, here are [Windows](http://www91.zippyshare.com/v/ePGpjk9r/file.html) and [Linux](https://mega.nz/#!uQ1T1IAD!Q91O0e12LXKiaXh_YjXD3D5m8_W3FuMI-hEa6KVMRDQ) builds of armips (thanks to who compiled them!).
|
||||
Finally just run `make` and everything should work!
|
||||
You can find the compiled files in the `out` folder.
|
||||
|
||||
**Usage / Features:**
|
||||
---
|
||||
|
||||
See https://github.com/Reisyukaku/ReiNand and http://gbatemp.net/threads/reinand-mod-o3ds-n3ds-sysnand.411110
|
||||
## Setup / Usage / Features
|
||||
|
||||
The FIRMs you need are [HERE](http://www77.zippyshare.com/v/oXDn2Hes/file.html).
|
||||
See https://github.com/AuroraWright/Luma3DS/wiki
|
||||
|
||||
**Credits:**
|
||||
|
||||
Rei as this is mostly his code.
|
||||
---
|
||||
|
||||
The offset to detect the console, and to calculate the O3DS NAND CTR are from Decrypt9.
|
||||
## Credits
|
||||
|
||||
tiniVi suggested me a way to detect a A9LH environment, and figured out screen deinit.
|
||||
See https://github.com/AuroraWright/Luma3DS/wiki/Credits
|
||||
|
||||
Delebile provided me with the FIRM writes blocking patch.
|
||||
---
|
||||
|
||||
A skilled reverser gave me the new reboot patch.
|
||||
## Licensing
|
||||
|
||||
The screen init code is from dark_samus, bil1s, Normmatt, delebile and everyone who contributed.
|
||||
|
||||
The code for printing to the screen, and the heavy revision to the reboot patch to allow for AGB/TWL loading are from CakesFW.
|
||||
|
||||
ARM11 userland patching is only possible thanks to @yifanlu's 3ds_injector, which is bundled in the CFW.
|
||||
This software is licensed under the terms of the GPLv3.
|
||||
You can find a copy of the license in the LICENSE.txt file.
|
||||
|
||||
21
screeninit/Makefile → exceptions/arm11/Makefile
Executable file → Normal file
21
screeninit/Makefile → exceptions/arm11/Makefile
Executable file → Normal file
@@ -4,20 +4,16 @@ ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
include $(DEVKITARM)/base_tools
|
||||
|
||||
CC := arm-none-eabi-gcc
|
||||
AS := arm-none-eabi-as
|
||||
LD := arm-none-eabi-ld
|
||||
OC := arm-none-eabi-objcopy
|
||||
|
||||
name := $(shell basename $(CURDIR))
|
||||
name := arm11_exceptions
|
||||
|
||||
dir_source := source
|
||||
dir_build := build
|
||||
dir_out := ../../$(dir_build)
|
||||
|
||||
ASFLAGS := -mlittle-endian -mcpu=mpcore
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math -mthumb -mthumb-interwork
|
||||
ASFLAGS := -mcpu=mpcore -mfpu=vfp
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -mthumb $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||
LDFLAGS := -nostdlib
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
@@ -25,14 +21,14 @@ objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
|
||||
.PHONY: all
|
||||
all: $(name).bin
|
||||
all: $(dir_out)/$(name).bin
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@rm -rf $(dir_build)
|
||||
|
||||
$(name).bin: $(dir_build)/$(name).elf
|
||||
$(OC) -S -O binary $< $@
|
||||
$(dir_out)/$(name).bin: $(dir_build)/$(name).elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
$(dir_build)/$(name).elf: $(objects)
|
||||
$(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
@@ -44,4 +40,3 @@ $(dir_build)/%.o: $(dir_source)/%.c
|
||||
$(dir_build)/%.o: $(dir_source)/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||
include $(call rwildcard, $(dir_build), *.d)
|
||||
14
exceptions/arm11/linker.ld
Normal file
14
exceptions/arm11/linker.ld
Normal file
@@ -0,0 +1,14 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0;
|
||||
|
||||
.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);
|
||||
}
|
||||
48
exceptions/arm11/source/handlers.h
Normal file
48
exceptions/arm11/source/handlers.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u32 magic[2];
|
||||
u16 versionMinor, versionMajor;
|
||||
|
||||
u16 processor, core;
|
||||
u32 type;
|
||||
|
||||
u32 totalSize;
|
||||
u32 registerDumpSize;
|
||||
u32 codeDumpSize;
|
||||
u32 stackDumpSize;
|
||||
u32 additionalDataSize;
|
||||
} ExceptionDumpHeader;
|
||||
|
||||
void __attribute__((noreturn)) mcuReboot(void);
|
||||
void cleanInvalidateDCacheAndDMB(void);
|
||||
bool cannotAccessVA(const void *address);
|
||||
void FIQHandler(void);
|
||||
void undefinedInstructionHandler(void);
|
||||
void dataAbortHandler(void);
|
||||
void prefetchAbortHandler(void);
|
||||
151
exceptions/arm11/source/handlers.s
Normal file
151
exceptions/arm11/source/handlers.s
Normal file
@@ -0,0 +1,151 @@
|
||||
@ 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.
|
||||
|
||||
.macro GEN_HANDLER name
|
||||
.global \name
|
||||
.type \name, %function
|
||||
\name:
|
||||
ldr sp, =#0xffff3000
|
||||
stmfd sp!, {r0-r7}
|
||||
mov r1, #\@ @ macro expansion counter
|
||||
b _commonHandler
|
||||
|
||||
.size \name, . - \name
|
||||
.endm
|
||||
|
||||
.text
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
.global _commonHandler
|
||||
.type _commonHandler, %function
|
||||
_commonHandler:
|
||||
clrex
|
||||
cpsid aif
|
||||
mrs r2, spsr
|
||||
mov r6, sp
|
||||
mrs r3, cpsr
|
||||
|
||||
tst r2, #0x20
|
||||
bne noFPUInitNorSvcBreak
|
||||
sub r0, lr, #4
|
||||
stmfd sp!, {lr}
|
||||
bl cannotAccessVA
|
||||
ldmfd sp!, {lr}
|
||||
cmp r0, #0
|
||||
bne noFPUInitNorSvcBreak
|
||||
ldr r4, [lr, #-4]
|
||||
cmp r1, #1
|
||||
bne noFPUInit
|
||||
|
||||
lsl r4, #4
|
||||
sub r4, #0xc0000000
|
||||
cmp r4, #0x30000000
|
||||
bcs noFPUInitNorSvcBreak
|
||||
fmrx r0, fpexc
|
||||
tst r0, #0x40000000
|
||||
bne noFPUInitNorSvcBreak
|
||||
|
||||
sub lr, #4
|
||||
srsfd sp!, #0x13
|
||||
ldmfd sp!, {r0-r7} @ restore context
|
||||
cps #0x13 @ FPU init
|
||||
stmfd sp, {r0-r3, r11-lr}^
|
||||
sub sp, #0x20
|
||||
bl . @ will be replaced
|
||||
ldmfd sp, {r0-r3, r11-lr}^
|
||||
add sp, #0x20
|
||||
rfefd sp!
|
||||
|
||||
noFPUInit:
|
||||
cmp r1, #2
|
||||
bne noFPUInitNorSvcBreak
|
||||
ldr r5, =#0xe12fff7f
|
||||
cmp r4, r5
|
||||
bne noFPUInitNorSvcBreak
|
||||
cps #0x13 @ switch to supervisor mode
|
||||
cmp r10, #0
|
||||
addne sp, #0x28
|
||||
ldmfd sp, {r8-r11}^ @ implementation details of the official svc handler
|
||||
ldr r2, [sp, #0x1c]
|
||||
ldr r4, [sp, #0x18]
|
||||
msr cpsr_c, r3 @ restore processor mode
|
||||
tst r2, #0x20
|
||||
addne lr, r4, #2 @ adjust address for later
|
||||
moveq lr, r4
|
||||
|
||||
noFPUInitNorSvcBreak:
|
||||
ands r4, r2, #0xf @ get the mode that triggered the exception
|
||||
moveq r4, #0xf @ usr => sys
|
||||
bic r5, r3, #0xf
|
||||
orr r5, r4
|
||||
msr cpsr_c, r5 @ change processor mode
|
||||
stmfd r6!, {r8-lr}
|
||||
msr cpsr_c, r3 @ restore processor mode
|
||||
mov sp, r6
|
||||
|
||||
stmfd sp!, {r2,lr}
|
||||
|
||||
mrc p15,0,r4,c5,c0,0 @ dfsr
|
||||
mrc p15,0,r5,c5,c0,1 @ ifsr
|
||||
mrc p15,0,r6,c6,c0,0 @ far
|
||||
fmrx r7, fpexc
|
||||
fmrx r8, fpinst
|
||||
fmrx r9, fpinst2
|
||||
|
||||
stmfd sp!, {r4-r9} @ it's a bit of a mess, but we will fix that later
|
||||
@ order of saved regs now: dfsr, ifsr, far, fpexc, fpinst, fpinst2, cpsr, pc + (2/4/8), r8-r14, r0-r7
|
||||
|
||||
bic r3, #(1<<31)
|
||||
fmxr fpexc, r3 @ clear the VFP11 exception flag (if it's set)
|
||||
|
||||
mov r0, sp
|
||||
mrc p15,0,r2,c0,c0,5 @ CPU ID register
|
||||
|
||||
b mainHandler
|
||||
|
||||
GEN_HANDLER FIQHandler
|
||||
GEN_HANDLER undefinedInstructionHandler
|
||||
GEN_HANDLER prefetchAbortHandler
|
||||
GEN_HANDLER dataAbortHandler
|
||||
|
||||
.global mcuReboot
|
||||
.type mcuReboot, %function
|
||||
mcuReboot:
|
||||
b . @ will be replaced
|
||||
|
||||
.global cleanInvalidateDCacheAndDMB
|
||||
.type cleanInvalidateDCacheAndDMB, %function
|
||||
cleanInvalidateDCacheAndDMB:
|
||||
mov r0, #0
|
||||
mcr p15,0,r0,c7,c14,0 @ Clean and Invalidate Entire Data Cache
|
||||
mcr p15,0,r0,c7,c10,4 @ Drain Memory Barrier
|
||||
bx lr
|
||||
|
||||
.global cannotAccessVA
|
||||
.type cannotAccessVA, %function
|
||||
cannotAccessVA:
|
||||
@ Thanks yellows8 for the hint
|
||||
lsr r0, #12
|
||||
lsl r0, #12
|
||||
mcr p15,0,r0,c7,c8,0 @ VA to PA translation with privileged read permission check
|
||||
mrc p15,0,r0,c7,c4,0 @ read PA register
|
||||
and r0, #1 @ failure bit
|
||||
bx lr
|
||||
109
exceptions/arm11/source/mainHandler.c
Normal file
109
exceptions/arm11/source/mainHandler.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "handlers.h"
|
||||
|
||||
#define REG_DUMP_SIZE 4 * 23
|
||||
#define CODE_DUMP_SIZE 48
|
||||
|
||||
#define CODESET_OFFSET 0xBEEFBEEF
|
||||
|
||||
static u32 __attribute__((noinline)) copyMemory(void *dst, const void *src, u32 size, u32 alignment)
|
||||
{
|
||||
u8 *out = (u8 *)dst;
|
||||
const u8 *in = (const u8 *)src;
|
||||
|
||||
if(((u32)src & (alignment - 1)) != 0 || cannotAccessVA(src) || (size != 0 && cannotAccessVA((u8 *)src + size - 1)))
|
||||
return 0;
|
||||
|
||||
for(u32 i = 0; i < size; i++)
|
||||
*out++ = *in++;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type, u32 cpuId)
|
||||
{
|
||||
ExceptionDumpHeader dumpHeader;
|
||||
|
||||
u32 registerDump[REG_DUMP_SIZE / 4];
|
||||
u8 codeDump[CODE_DUMP_SIZE];
|
||||
u8 *finalBuffer = cannotAccessVA((void *)0xE5000000) ? (u8 *)0xF5000000 : (u8 *)0xE5000000; //VA for 0x25000000
|
||||
u8 *final = finalBuffer;
|
||||
|
||||
while(*(vu32 *)final == 0xDEADC0DE && *((vu32 *)final + 1) == 0xDEADCAFE);
|
||||
|
||||
dumpHeader.magic[0] = 0xDEADC0DE;
|
||||
dumpHeader.magic[1] = 0xDEADCAFE;
|
||||
dumpHeader.versionMajor = 1;
|
||||
dumpHeader.versionMinor = 2;
|
||||
|
||||
dumpHeader.processor = 11;
|
||||
dumpHeader.core = cpuId & 0xF;
|
||||
dumpHeader.type = type;
|
||||
|
||||
dumpHeader.registerDumpSize = REG_DUMP_SIZE;
|
||||
dumpHeader.codeDumpSize = CODE_DUMP_SIZE;
|
||||
|
||||
//Dump registers
|
||||
//Current order of saved regs: dfsr, ifsr, far, fpexc, fpinst, fpinst2, cpsr, pc, r8-r12, sp, lr, r0-r7
|
||||
u32 cpsr = regs[6];
|
||||
u32 pc = regs[7] - (type < 3 ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 0);
|
||||
|
||||
registerDump[15] = pc;
|
||||
registerDump[16] = cpsr;
|
||||
for(u32 i = 0; i < 6; i++) registerDump[17 + i] = regs[i];
|
||||
for(u32 i = 0; i < 7; i++) registerDump[8 + i] = regs[8 + i];
|
||||
for(u32 i = 0; i < 8; i++) registerDump[i] = regs[15 + i];
|
||||
|
||||
//Dump code
|
||||
u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //Doesn't work well on 32-bit Thumb instructions, but it isn't much of a problem
|
||||
dumpHeader.codeDumpSize = copyMemory(codeDump, instr, dumpHeader.codeDumpSize, ((cpsr & 0x20) != 0) ? 2 : 4);
|
||||
|
||||
//Copy register dump and code dump
|
||||
final = (u8 *)(finalBuffer + sizeof(ExceptionDumpHeader));
|
||||
final += copyMemory(final, registerDump, dumpHeader.registerDumpSize, 1);
|
||||
final += copyMemory(final, codeDump, dumpHeader.codeDumpSize, 1);
|
||||
|
||||
//Dump stack in place
|
||||
dumpHeader.stackDumpSize = copyMemory(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF), 1);
|
||||
final += dumpHeader.stackDumpSize;
|
||||
|
||||
if(!cannotAccessVA((void *)0xFFFF9004))
|
||||
{
|
||||
vu64 *additionalData = (vu64 *)final;
|
||||
dumpHeader.additionalDataSize = 16;
|
||||
vu8 *currentKCodeSet = *(vu8 **)(*(vu8 **)0xFFFF9004 + CODESET_OFFSET); //currentKProcess + CodeSet
|
||||
|
||||
additionalData[0] = *(vu64 *)(currentKCodeSet + 0x50); //Process name
|
||||
additionalData[1] = *(vu64 *)(currentKCodeSet + 0x5C); //Title ID
|
||||
}
|
||||
else dumpHeader.additionalDataSize = 0;
|
||||
|
||||
dumpHeader.totalSize = sizeof(ExceptionDumpHeader) + dumpHeader.registerDumpSize + dumpHeader.codeDumpSize + dumpHeader.stackDumpSize + dumpHeader.additionalDataSize;
|
||||
|
||||
//Copy header (actually optimized by the compiler)
|
||||
*(ExceptionDumpHeader *)finalBuffer = dumpHeader;
|
||||
|
||||
cleanInvalidateDCacheAndDMB();
|
||||
mcuReboot(); //Also contains DCache-cleaning code
|
||||
}
|
||||
31
exceptions/arm11/source/start.s
Normal file
31
exceptions/arm11/source/start.s
Normal file
@@ -0,0 +1,31 @@
|
||||
@ 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.
|
||||
|
||||
.section .text.start
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
add pc, r0, #(handlers - .) @ Dummy instruction to prevent compiler optimizations
|
||||
|
||||
handlers:
|
||||
.word FIQHandler
|
||||
.word undefinedInstructionHandler
|
||||
.word prefetchAbortHandler
|
||||
.word dataAbortHandler
|
||||
37
exceptions/arm11/source/types.h
Normal file
37
exceptions/arm11/source/types.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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;
|
||||
42
exceptions/arm9/Makefile
Normal file
42
exceptions/arm9/Makefile
Normal file
@@ -0,0 +1,42 @@
|
||||
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 -mthumb $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||
LDFLAGS := -nostdlib
|
||||
|
||||
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) $<
|
||||
14
exceptions/arm9/linker.ld
Normal file
14
exceptions/arm9/linker.ld
Normal file
@@ -0,0 +1,14 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x01FF7FE0;
|
||||
|
||||
.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);
|
||||
}
|
||||
46
exceptions/arm9/source/handlers.h
Normal file
46
exceptions/arm9/source/handlers.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u32 magic[2];
|
||||
u16 versionMinor, versionMajor;
|
||||
|
||||
u16 processor, core;
|
||||
u32 type;
|
||||
|
||||
u32 totalSize;
|
||||
u32 registerDumpSize;
|
||||
u32 codeDumpSize;
|
||||
u32 stackDumpSize;
|
||||
u32 additionalDataSize;
|
||||
} ExceptionDumpHeader;
|
||||
|
||||
u32 readMPUConfig(u32 *regionSettings);
|
||||
void FIQHandler(void);
|
||||
void undefinedInstructionHandler(void);
|
||||
void dataAbortHandler(void);
|
||||
void prefetchAbortHandler(void);
|
||||
109
exceptions/arm9/source/handlers.s
Normal file
109
exceptions/arm9/source/handlers.s
Normal file
@@ -0,0 +1,109 @@
|
||||
@ 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.
|
||||
|
||||
.macro GEN_HANDLER name
|
||||
.global \name
|
||||
.type \name, %function
|
||||
\name:
|
||||
ldr sp, =#0x02000000 @ We make the (full descending) stack point to the end of ITCM for our exception handlers.
|
||||
@ It doesn't matter if we're overwriting stuff here, since we're going to reboot.
|
||||
|
||||
stmfd sp!, {r0-r7} @ FIQ has its own r8-r14 regs
|
||||
ldr r1, =\@ @ macro expansion counter
|
||||
b _commonHandler
|
||||
|
||||
.size \name, . - \name
|
||||
.endm
|
||||
|
||||
.text
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
.global _commonHandler
|
||||
.type _commonHandler, %function
|
||||
_commonHandler:
|
||||
mrs r2, spsr
|
||||
mov r6, sp
|
||||
mrs r3, cpsr
|
||||
|
||||
orr r3, #0x1c0 @ disable Imprecise Aborts, IRQ and FIQ (equivalent to "cpsid aif" on arm11)
|
||||
msr cpsr_cx, r3
|
||||
|
||||
tst r2, #0x20
|
||||
bne noSvcBreak
|
||||
cmp r1, #2
|
||||
bne noSvcBreak
|
||||
|
||||
sub r0, lr, #4 @ calling cannotAccessAddress cause more problems that it actually solves... (I've to save a lot of regs and that's a pain tbh)
|
||||
lsr r0, #20 @ we'll just do some address checks (to see if it's in ARM9 internal memory)
|
||||
cmp r0, #0x80
|
||||
bne noSvcBreak
|
||||
ldr r4, [lr, #-4]
|
||||
ldr r5, =#0xe12fff7f
|
||||
cmp r4, r5
|
||||
bne noSvcBreak
|
||||
bic r5, r3, #0xf
|
||||
orr r5, #0x3
|
||||
msr cpsr_c, r5 @ switch to supervisor mode
|
||||
ldmfd sp, {r8-r11}^
|
||||
ldr r2, [sp, #0x1c] @ implementation details of the official svc handler
|
||||
ldr r4, [sp, #0x18]
|
||||
msr cpsr_c, r3 @ restore processor mode
|
||||
tst r2, #0x20
|
||||
addne lr, r4, #2 @ adjust address for later
|
||||
moveq lr, r4
|
||||
|
||||
noSvcBreak:
|
||||
ands r4, r2, #0xf @ get the mode that triggered the exception
|
||||
moveq r4, #0xf @ usr => sys
|
||||
bic r5, r3, #0xf
|
||||
orr r5, r4
|
||||
msr cpsr_c, r5 @ change processor mode
|
||||
stmfd r6!, {r8-lr}
|
||||
msr cpsr_c, r3 @ restore processor mode
|
||||
mov sp, r6
|
||||
|
||||
stmfd sp!, {r2,lr} @ it's a bit of a mess, but we will fix that later
|
||||
@ order of saved regs now: cpsr, pc + (2/4/8), r8-r14, r0-r7
|
||||
|
||||
mov r0, sp
|
||||
|
||||
b mainHandler
|
||||
|
||||
GEN_HANDLER FIQHandler
|
||||
GEN_HANDLER undefinedInstructionHandler
|
||||
GEN_HANDLER prefetchAbortHandler
|
||||
GEN_HANDLER dataAbortHandler
|
||||
|
||||
.global readMPUConfig
|
||||
.type readMPUConfig, %function
|
||||
readMPUConfig:
|
||||
stmfd sp!, {r4-r8, lr}
|
||||
mrc p15,0,r1,c6,c0,0
|
||||
mrc p15,0,r2,c6,c1,0
|
||||
mrc p15,0,r3,c6,c2,0
|
||||
mrc p15,0,r4,c6,c3,0
|
||||
mrc p15,0,r5,c6,c4,0
|
||||
mrc p15,0,r6,c6,c5,0
|
||||
mrc p15,0,r7,c6,c6,0
|
||||
mrc p15,0,r8,c6,c7,0
|
||||
stmia r0, {r1-r8}
|
||||
mrc p15,0,r0,c5,c0,2 @ read data access permission bits
|
||||
ldmfd sp!, {r4-r8, pc}
|
||||
139
exceptions/arm9/source/i2c.c
Normal file
139
exceptions/arm9/source/i2c.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Thanks to the everyone who 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;
|
||||
}
|
||||
44
exceptions/arm9/source/i2c.h
Normal file
44
exceptions/arm9/source/i2c.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Thanks to the everyone who 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);
|
||||
118
exceptions/arm9/source/mainHandler.c
Normal file
118
exceptions/arm9/source/mainHandler.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "i2c.h"
|
||||
#include "handlers.h"
|
||||
|
||||
#define FINAL_BUFFER 0x25000000
|
||||
|
||||
#define REG_DUMP_SIZE 4 * 17
|
||||
#define CODE_DUMP_SIZE 48
|
||||
|
||||
bool cannotAccessAddress(const void *address)
|
||||
{
|
||||
u32 regionSettings[8];
|
||||
u32 addr = (u32)address;
|
||||
|
||||
u32 dataAccessPermissions = readMPUConfig(regionSettings);
|
||||
for(u32 i = 0; i < 8; i++)
|
||||
{
|
||||
if((dataAccessPermissions & 0xF) == 0 || (regionSettings[i] & 1) == 0)
|
||||
continue; //No access / region not enabled
|
||||
|
||||
u32 regionAddrBase = regionSettings[i] & ~0xFFF;
|
||||
u32 regionSize = 1 << (((regionSettings[i] >> 1) & 0x1F) + 1);
|
||||
|
||||
if(addr >= regionAddrBase && addr < regionAddrBase + regionSize)
|
||||
return false;
|
||||
|
||||
dataAccessPermissions >>= 4;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static u32 __attribute__((noinline)) copyMemory(void *dst, const void *src, u32 size, u32 alignment)
|
||||
{
|
||||
u8 *out = (u8 *)dst;
|
||||
const u8 *in = (const u8 *)src;
|
||||
|
||||
if(((u32)src & (alignment - 1)) != 0 || cannotAccessAddress(src) || (size != 0 && cannotAccessAddress((u8 *)src + size - 1)))
|
||||
return 0;
|
||||
|
||||
for(u32 i = 0; i < size; i++)
|
||||
*out++ = *in++;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type)
|
||||
{
|
||||
ExceptionDumpHeader dumpHeader;
|
||||
|
||||
u32 registerDump[REG_DUMP_SIZE / 4];
|
||||
u8 codeDump[CODE_DUMP_SIZE];
|
||||
|
||||
dumpHeader.magic[0] = 0xDEADC0DE;
|
||||
dumpHeader.magic[1] = 0xDEADCAFE;
|
||||
dumpHeader.versionMajor = 1;
|
||||
dumpHeader.versionMinor = 2;
|
||||
|
||||
dumpHeader.processor = 9;
|
||||
dumpHeader.core = 0;
|
||||
dumpHeader.type = type;
|
||||
|
||||
dumpHeader.registerDumpSize = REG_DUMP_SIZE;
|
||||
dumpHeader.codeDumpSize = CODE_DUMP_SIZE;
|
||||
dumpHeader.additionalDataSize = 0;
|
||||
|
||||
//Dump registers
|
||||
//Current order of saved regs: cpsr, pc, r8-r14, r0-r7
|
||||
u32 cpsr = regs[0];
|
||||
u32 pc = regs[1] - (type < 3 ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 8);
|
||||
|
||||
registerDump[15] = pc;
|
||||
registerDump[16] = cpsr;
|
||||
for(u32 i = 0; i < 7; i++) registerDump[8 + i] = regs[2 + i];
|
||||
for(u32 i = 0; i < 8; i++) registerDump[i] = regs[9 + i];
|
||||
|
||||
//Dump code
|
||||
u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //Doesn't work well on 32-bit Thumb instructions, but it isn't much of a problem
|
||||
dumpHeader.codeDumpSize = copyMemory(codeDump, instr, dumpHeader.codeDumpSize, ((cpsr & 0x20) != 0) ? 2 : 4);
|
||||
|
||||
//Copy register dump and code dump
|
||||
u8 *final = (u8 *)(FINAL_BUFFER + sizeof(ExceptionDumpHeader));
|
||||
final += copyMemory(final, registerDump, dumpHeader.registerDumpSize, 1);
|
||||
final += copyMemory(final, codeDump, dumpHeader.codeDumpSize, 1);
|
||||
|
||||
//Dump stack in place
|
||||
dumpHeader.stackDumpSize = copyMemory(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF), 1);
|
||||
|
||||
dumpHeader.totalSize = sizeof(ExceptionDumpHeader) + dumpHeader.registerDumpSize + dumpHeader.codeDumpSize + dumpHeader.stackDumpSize + dumpHeader.additionalDataSize;
|
||||
|
||||
//Copy header (actually optimized by the compiler)
|
||||
*(ExceptionDumpHeader *)FINAL_BUFFER = dumpHeader;
|
||||
|
||||
((void (*)())0xFFFF0830)(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot
|
||||
while(true);
|
||||
}
|
||||
31
exceptions/arm9/source/start.s
Normal file
31
exceptions/arm9/source/start.s
Normal file
@@ -0,0 +1,31 @@
|
||||
@ 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.
|
||||
|
||||
.section .text.start
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
add pc, r0, #(handlers - .) @ Dummy instruction to prevent compiler optimizations
|
||||
|
||||
handlers:
|
||||
.word FIQHandler
|
||||
.word undefinedInstructionHandler
|
||||
.word prefetchAbortHandler
|
||||
.word dataAbortHandler
|
||||
37
exceptions/arm9/source/types.h
Normal file
37
exceptions/arm9/source/types.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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;
|
||||
169
exceptions/exception_dump_parser.py
Normal file
169
exceptions/exception_dump_parser.py
Normal file
@@ -0,0 +1,169 @@
|
||||
#!/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)")
|
||||
|
||||
if __name__ == "__main__":
|
||||
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 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])))
|
||||
|
||||
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":
|
||||
path = ''.join((path[1], ':', path[2:])).replace('/', '\\')
|
||||
|
||||
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))
|
||||
1
haxloader/CakeBrah
Submodule
1
haxloader/CakeBrah
Submodule
Submodule haxloader/CakeBrah added at 1efda4e894
1
haxloader/CakeHax
Submodule
1
haxloader/CakeHax
Submodule
Submodule haxloader/CakeHax added at 329212a8e0
1
haxloader/CakesROP
Submodule
1
haxloader/CakesROP
Submodule
Submodule haxloader/CakesROP added at b14debbd34
74
haxloader/Makefile
Normal file
74
haxloader/Makefile
Normal file
@@ -0,0 +1,74 @@
|
||||
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
|
||||
|
||||
dir_source := source
|
||||
dir_diffs := diffs
|
||||
dir_cakebrah := CakeBrah
|
||||
dir_cakehax := CakeHax
|
||||
dir_cakesrop := CakesROP
|
||||
dir_build := build
|
||||
dir_out := ../out
|
||||
|
||||
ASFLAGS := -mcpu=arm946e-s
|
||||
CFLAGS := -Wall -Wextra $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||
LDFLAGS := -nostartfiles
|
||||
FLAGS := name=$(name).dat dir_out=$(abspath $(dir_out)) ICON=$(abspath icon.png) APP_DESCRIPTION="Noob-friendly 3DS CFW." APP_AUTHOR="Aurora Wright/TuxSH" --no-print-directory
|
||||
ROPFLAGS := DATNAME=$(name).dat DISPNAME=$(name) GRAPHICS=../graphics/
|
||||
|
||||
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)/hax/3ds/$(name) $(dir_out)/menuhax/boot.3dsx $(dir_out)/mset-spider/$(name).dat $(dir_out)/mset/$(name).nds
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@cd $(dir_cakebrah); git reset --hard
|
||||
@$(MAKE) $(FLAGS) -C $(dir_cakebrah) clean
|
||||
@$(MAKE) $(FLAGS) -C $(dir_cakehax) clean
|
||||
@$(MAKE) $(ROPFLAGS) -C $(dir_cakesrop) clean
|
||||
@rm -rf $(dir_build)
|
||||
|
||||
$(dir_out)/mset-spider/$(name).dat: $(dir_build)/main.bin
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) $(FLAGS) -C $(dir_cakehax) launcher
|
||||
@dd if=$(dir_build)/main.bin of=$(dir_out)/$(name).dat bs=512 seek=144
|
||||
@mv $(dir_out)/$(name).dat $@
|
||||
|
||||
$(dir_out)/hax/3ds/$(name):
|
||||
@mkdir -p "$@"
|
||||
@cd $(dir_cakebrah); patch -p1 < ../$(dir_diffs)/1.diff; $(MAKE) $(FLAGS); git reset --hard
|
||||
@mv $(dir_out)/$(name).3dsx $(dir_out)/$(name).smdh $@
|
||||
|
||||
$(dir_out)/menuhax/boot.3dsx:
|
||||
@mkdir -p "$(@D)"
|
||||
@cd $(dir_cakebrah); patch -p1 < ../$(dir_diffs)/1.diff; patch -p1 < ../$(dir_diffs)/2.diff; $(MAKE) $(FLAGS); git reset --hard
|
||||
@mv $(dir_out)/$(name).3dsx $@
|
||||
@rm $(dir_out)/$(name).smdh
|
||||
|
||||
$(dir_out)/mset/$(name).nds:
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) $(ROPFLAGS) -C $(dir_cakesrop)
|
||||
@mv $(dir_cakesrop)/CakesROP.nds $@
|
||||
|
||||
$(dir_build)/main.bin: $(dir_build)/main.elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
$(dir_build)/main.elf: $(objects) ../$(dir_build)/loader.bin.o
|
||||
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
||||
$(dir_build)/memory.o: CFLAGS += -O3
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.c $(bundled)
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||
123
haxloader/diffs/1.diff
Normal file
123
haxloader/diffs/1.diff
Normal file
@@ -0,0 +1,123 @@
|
||||
diff -uNr a/include/brahma.h b/include/brahma.h
|
||||
--- a/include/brahma.h 2016-09-26 16:05:36.363067000 +0200
|
||||
+++ b/include/brahma.h 2016-09-26 21:35:14.800519000 +0200
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
u32 brahma_init (void);
|
||||
u32 brahma_exit (void);
|
||||
-s32 load_arm9_payload_offset (char *filename, u32 offset, u32 max_psize);
|
||||
+s32 load_arm9_payload_offset (void);
|
||||
s32 load_arm9_payload_from_mem (u8* data, u32 dsize);
|
||||
void redirect_codeflow (u32 *dst_addr, u32 *src_addr);
|
||||
s32 map_arm9_payload (void);
|
||||
@@ -13,8 +13,6 @@
|
||||
s32 get_exploit_data (struct exploit_data *data);
|
||||
s32 firm_reboot ();
|
||||
|
||||
-#define load_arm9_payload(filename) load_arm9_payload_offset(filename, 0, 0)
|
||||
-
|
||||
#define BRAHMA_NETWORK_PORT 80
|
||||
|
||||
#define ARM_JUMPOUT 0xE51FF004 // LDR PC, [PC, -#04]
|
||||
diff -uNr a/source/brahma.c b/source/brahma.c
|
||||
--- a/source/brahma.c 2016-09-26 16:05:36.363067000 +0200
|
||||
+++ b/source/brahma.c 2016-09-26 21:37:58.660516468 +0200
|
||||
@@ -179,39 +179,54 @@
|
||||
return g_ext_arm9_loaded;
|
||||
}
|
||||
|
||||
-/* reads ARM9 payload from a given path.
|
||||
- filename: full path of payload
|
||||
- offset: offset of the payload in the file
|
||||
- max_psize: the maximum size of the payload that should be loaded (if 0, ARM9_MAX_PAYLOAD_SIZE. Should be smaller than ARM9_MAX_PAYLOAD_SIZE)
|
||||
+/* reads Luma payload
|
||||
returns: 0 on failure, 1 on success */
|
||||
-s32 load_arm9_payload_offset (char *filename, u32 offset, u32 max_psize) {
|
||||
+s32 load_arm9_payload_offset (void) {
|
||||
s32 result = 0;
|
||||
u32 fsize = 0;
|
||||
u32 psize = 0;
|
||||
+ bool use_default = true;
|
||||
+ FILE *f;
|
||||
|
||||
- if (max_psize == 0 || max_psize > ARM9_PAYLOAD_MAX_SIZE)
|
||||
- max_psize = ARM9_PAYLOAD_MAX_SIZE;
|
||||
+ FILE *p = fopen("/luma/path.txt", "r");
|
||||
|
||||
- if (!filename)
|
||||
- return result;
|
||||
+ if (p) {
|
||||
+ fseek(p , 0, SEEK_END);
|
||||
+ psize = ftell(p);
|
||||
+ if (psize > 5 && psize < 58) {
|
||||
+ char path[57];
|
||||
+
|
||||
+ fseek(p, 0, SEEK_SET);
|
||||
+ u32 bytes_read = fread(path, 1, psize, p);
|
||||
+
|
||||
+ if (bytes_read == psize) {
|
||||
+ if (path[psize - 1] == 0xA) psize--;
|
||||
+ if (path[psize - 1] == 0xD) psize--;
|
||||
+ if (psize > 5 && psize < 56 && path[0] == '/' && memcmp(path + psize - 4, ".bin", 4)) {
|
||||
+ path[psize] = 0;
|
||||
+ f = fopen(path, "rb");
|
||||
+ if (f) use_default = false;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ fclose(p);
|
||||
+ }
|
||||
+
|
||||
+ if (use_default) f = fopen("/arm9loaderhax.bin", "rb");
|
||||
|
||||
- FILE *f = fopen(filename, "rb");
|
||||
if (f) {
|
||||
- fseek(f , 0, SEEK_END);
|
||||
+ fseek(f, 0, SEEK_END);
|
||||
fsize = ftell(f);
|
||||
|
||||
- if (offset < fsize) {
|
||||
- psize = fsize - offset;
|
||||
- if (psize > max_psize)
|
||||
- psize = max_psize;
|
||||
-
|
||||
- g_ext_arm9_size = psize;
|
||||
-
|
||||
- fseek(f, offset, SEEK_SET);
|
||||
- if (psize >= 8) {
|
||||
- u32 bytes_read = fread(g_ext_arm9_buf, 1, psize, f);
|
||||
- result = (g_ext_arm9_loaded = (bytes_read == psize));
|
||||
- }
|
||||
+ if (fsize > ARM9_PAYLOAD_MAX_SIZE)
|
||||
+ fsize = ARM9_PAYLOAD_MAX_SIZE;
|
||||
+
|
||||
+ g_ext_arm9_size = fsize;
|
||||
+
|
||||
+ fseek(f, 0, SEEK_SET);
|
||||
+ if (fsize >= 8) {
|
||||
+ u32 bytes_read = fread(g_ext_arm9_buf, 1, fsize, f);
|
||||
+ result = (g_ext_arm9_loaded = (bytes_read == fsize));
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
diff -uNr a/source/main.c b/source/main.c
|
||||
--- a/source/main.c 2016-09-26 16:05:36.363067000 +0200
|
||||
+++ b/source/main.c 2016-09-26 21:40:35.202513018 +0200
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
int main (void) {
|
||||
if (brahma_init()) {
|
||||
- if (load_arm9_payload_offset("/" LAUNCHER_PATH, 0x12000, 0x10000) != 1)
|
||||
+ if (load_arm9_payload_offset() != 1)
|
||||
goto error;
|
||||
firm_reboot();
|
||||
brahma_exit();
|
||||
@@ -50,7 +50,7 @@
|
||||
error:
|
||||
gfxInitDefault();
|
||||
consoleInit(GFX_BOTTOM, NULL);
|
||||
- printf("An error occurred while loading the payload.\nMake sure your launcher is located at:\n/" LAUNCHER_PATH);
|
||||
+ printf("An error occurred while loading the payload.");
|
||||
wait_any_key();
|
||||
|
||||
gfxExit();
|
||||
11
haxloader/diffs/2.diff
Normal file
11
haxloader/diffs/2.diff
Normal file
@@ -0,0 +1,11 @@
|
||||
diff -uNr a/source/main.c b/source/main.c
|
||||
--- a/source/main.c 2016-09-11 01:04:25.665231884 +0200
|
||||
+++ b/source/main.c 2016-09-14 12:36:28.601439550 +0200
|
||||
@@ -37,6 +37,7 @@
|
||||
}
|
||||
|
||||
int main (void) {
|
||||
+ svcSleepThread(2500 * 1000000ULL);
|
||||
if (brahma_init()) {
|
||||
if (load_arm9_payload_offset() != 1)
|
||||
goto error;
|
||||
11
haxloader/graphics/drunkenlogo.grit
Normal file
11
haxloader/graphics/drunkenlogo.grit
Normal file
@@ -0,0 +1,11 @@
|
||||
-W3
|
||||
# disable alpha and set opaque bit for all pixels
|
||||
-gT!
|
||||
|
||||
# use lz77 compression
|
||||
-gzl
|
||||
|
||||
# 16 bit bitmap
|
||||
-gB16
|
||||
|
||||
-gb
|
||||
BIN
haxloader/graphics/drunkenlogo.png
Normal file
BIN
haxloader/graphics/drunkenlogo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
BIN
haxloader/icon.png
Normal file
BIN
haxloader/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
14
haxloader/linker.ld
Normal file
14
haxloader/linker.ld
Normal file
@@ -0,0 +1,14 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x23F00000;
|
||||
|
||||
.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);
|
||||
}
|
||||
39
haxloader/source/cache.h
Normal file
39
haxloader/source/cache.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/***
|
||||
The following functions flush the data cache, then waits for all memory transfers to be finished.
|
||||
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
|
||||
- jumping to a payload
|
||||
***/
|
||||
|
||||
void flushEntireDCache(void); //actually: "clean and flush"
|
||||
void flushDCacheRange(void *startAddress, u32 size);
|
||||
void flushEntireICache(void);
|
||||
void flushICacheRange(void *startAddress, u32 size);
|
||||
89
haxloader/source/cache.s
Normal file
89
haxloader/source/cache.s
Normal file
@@ -0,0 +1,89 @@
|
||||
@ 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.
|
||||
|
||||
.text
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
.global flushEntireDCache
|
||||
.type flushEntireDCache, %function
|
||||
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)
|
||||
|
||||
@ Implemented in bootROM at address 0xffff0830
|
||||
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
|
||||
bx lr
|
||||
|
||||
.global flushDCacheRange
|
||||
.type flushDCacheRange, %function
|
||||
flushDCacheRange:
|
||||
@ Implemented in bootROM at address 0xffff08a0
|
||||
add r1, r0, r1 @ end address
|
||||
bic r0, #0x1f @ align source address to cache line size (32 bytes)
|
||||
|
||||
flush_dcache_range_loop:
|
||||
mcr p15, 0, r0, c7, c14, 1 @ clean and flush the line corresponding to the address r0 is holding
|
||||
add r0, #0x20
|
||||
cmp r0, r1
|
||||
blo flush_dcache_range_loop
|
||||
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
|
||||
bx lr
|
||||
|
||||
.global flushEntireICache
|
||||
.type flushEntireICache, %function
|
||||
flushEntireICache:
|
||||
@ Implemented in bootROM at address 0xffff0ab4
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0
|
||||
bx lr
|
||||
|
||||
.global flushICacheRange
|
||||
.type flushICacheRange, %function
|
||||
flushICacheRange:
|
||||
@ Implemented in bootROM at address 0xffff0ac0
|
||||
add r1, r0, r1 @ end address
|
||||
bic r0, #0x1f @ align source address to cache line size (32 bytes)
|
||||
|
||||
flush_icache_range_loop:
|
||||
mcr p15, 0, r0, c7, c5, 1 @ flush the line corresponding to the address r0 is holding
|
||||
add r0, #0x20
|
||||
cmp r0, r1
|
||||
blo flush_icache_range_loop
|
||||
|
||||
bx lr
|
||||
49
loader/source/fatfs/00history.txt → haxloader/source/fatfs/00history.txt
Executable file → Normal file
49
loader/source/fatfs/00history.txt → haxloader/source/fatfs/00history.txt
Executable file → Normal file
@@ -10,7 +10,7 @@ R0.00 (February 26, 2006)
|
||||
|
||||
R0.01 (April 29, 2006)
|
||||
|
||||
First stable version.
|
||||
The first release.
|
||||
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ R0.10 (October 02, 2013)
|
||||
Improved write throughput of f_puts() and f_printf().
|
||||
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
|
||||
Fixed f_write() can be truncated when the file size is close to 4GB.
|
||||
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect error code.
|
||||
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect value on error.
|
||||
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ R0.10a (January 15, 2014)
|
||||
R0.10b (May 19, 2014)
|
||||
|
||||
Fixed a hard error in the disk I/O layer can collapse the directory entry.
|
||||
Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN. (appeared at R0.07)
|
||||
Fixed LFN entry is not deleted when delete/rename an object with lossy converted SFN. (appeared at R0.07)
|
||||
|
||||
|
||||
|
||||
@@ -243,3 +243,46 @@ R0.11a (September 05, 2015)
|
||||
Fixed errors in the case conversion teble of Unicode (cc*.c).
|
||||
|
||||
|
||||
|
||||
R0.12 (April 12, 2016)
|
||||
|
||||
Added support for exFAT file system. (_FS_EXFAT)
|
||||
Added f_expand(). (_USE_EXPAND)
|
||||
Changed some members in FINFO structure and behavior of f_readdir().
|
||||
Added an option _USE_CHMOD.
|
||||
Removed an option _WORD_ACCESS.
|
||||
Fixed errors in the case conversion table of Unicode (cc*.c).
|
||||
|
||||
|
||||
|
||||
R0.12a (July 10, 2016)
|
||||
|
||||
Added support for creating exFAT volume with some changes of f_mkfs().
|
||||
Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed.
|
||||
f_forward() is available regardless of _FS_TINY.
|
||||
Fixed f_mkfs() creates wrong volume. (appeared at R0.12)
|
||||
Fixed wrong memory read in create_name(). (appeared at R0.12)
|
||||
Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD.
|
||||
|
||||
|
||||
|
||||
R0.12b (September 04, 2016)
|
||||
|
||||
Made f_rename() be able to rename objects with the same name but case.
|
||||
Fixed an error in the case conversion teble of code page 866. (ff.c)
|
||||
Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12)
|
||||
Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12)
|
||||
Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12)
|
||||
Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12)
|
||||
Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12)
|
||||
Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12)
|
||||
|
||||
|
||||
|
||||
R0.12c (March 04, 2017)
|
||||
|
||||
Improved write throughput at the fragmented file on the exFAT volume.
|
||||
Made memory usage for exFAT be able to be reduced as decreasing _MAX_LFN.
|
||||
Fixed successive f_getfree() can return wrong count on the FAT12/16 volume. (appeared at R0.12)
|
||||
Fixed configuration option _VOLUMES cannot be set 10. (appeared at R0.10c)
|
||||
|
||||
21
haxloader/source/fatfs/00readme.txt
Normal file
21
haxloader/source/fatfs/00readme.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
FatFs Module Source Files R0.12c
|
||||
|
||||
|
||||
FILES
|
||||
|
||||
00readme.txt This file.
|
||||
00history.txt Revision history.
|
||||
ff.c FatFs module.
|
||||
ffconf.h Configuration file of FatFs module.
|
||||
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.
|
||||
option Optional external modules.
|
||||
|
||||
|
||||
Low level disk I/O module is not included in this archive because the FatFs
|
||||
module is only a generic file system layer and it does not depend on any specific
|
||||
storage device. You have to provide a low level disk I/O module written to
|
||||
control the storage device that attached to the target system.
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "diskio.h" /* FatFs lower layer API */
|
||||
#include "sdmmc/sdmmc.h"
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Get Drive Status */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@@ -34,9 +33,7 @@ DSTATUS disk_initialize (
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
)
|
||||
{
|
||||
sdmmc_sdcard_init();
|
||||
|
||||
return RES_OK;
|
||||
return sdmmc_sdcard_init() ? RES_OK : RES_PARERR;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,10 +50,7 @@ DRESULT disk_read (
|
||||
UINT count /* Number of sectors to read */
|
||||
)
|
||||
{
|
||||
if(sdmmc_sdcard_readsectors(sector, count, buff))
|
||||
return RES_PARERR;
|
||||
|
||||
return RES_OK;
|
||||
return (!sdmmc_sdcard_readsectors(sector, count, buff)) ? RES_OK : RES_PARERR;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,15 +63,15 @@ DRESULT disk_read (
|
||||
DRESULT disk_write (
|
||||
__attribute__((unused))
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
__attribute__((unused))
|
||||
const BYTE *buff, /* Data to be written */
|
||||
__attribute__((unused))
|
||||
DWORD sector, /* Sector address in LBA */
|
||||
__attribute__((unused))
|
||||
UINT count /* Number of sectors to write */
|
||||
)
|
||||
{
|
||||
if(sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff))
|
||||
return RES_PARERR;
|
||||
|
||||
return RES_OK;
|
||||
return RES_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
6144
haxloader/source/fatfs/ff.c
Normal file
6144
haxloader/source/fatfs/ff.c
Normal file
File diff suppressed because it is too large
Load Diff
239
loader/source/fatfs/ff.h → haxloader/source/fatfs/ff.h
Executable file → Normal file
239
loader/source/fatfs/ff.h → haxloader/source/fatfs/ff.h
Executable file → Normal file
@@ -1,11 +1,13 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module include R0.11a (C)ChaN, 2015
|
||||
/----------------------------------------------------------------------------/
|
||||
/ FatFs module is a free software that opened under license policy of
|
||||
/ following conditions.
|
||||
/*----------------------------------------------------------------------------/
|
||||
/ FatFs - Generic FAT file system module R0.12c /
|
||||
/-----------------------------------------------------------------------------/
|
||||
/
|
||||
/ Copyright (C) 2015, ChaN, all right reserved.
|
||||
/ Copyright (C) 2017, ChaN, all right reserved.
|
||||
/
|
||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||
/ source and binary forms, with or without modification, are permitted provided
|
||||
/ that the following condition is met:
|
||||
|
||||
/ 1. Redistributions of source code must retain the above copyright notice,
|
||||
/ this condition and the following disclaimer.
|
||||
/
|
||||
@@ -13,11 +15,11 @@
|
||||
/ and any warranties related to this software are DISCLAIMED.
|
||||
/ The copyright owner or contributors be NOT LIABLE for any damages caused
|
||||
/ by use of this software.
|
||||
/---------------------------------------------------------------------------*/
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef _FATFS
|
||||
#define _FATFS 64180 /* Revision ID */
|
||||
#define _FATFS 68300 /* Revision ID */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -25,6 +27,7 @@ extern "C" {
|
||||
|
||||
#include "integer.h" /* Basic integer types */
|
||||
#include "ffconf.h" /* FatFs configuration options */
|
||||
|
||||
#if _FATFS != _FFCONF
|
||||
#error Wrong configuration file (ffconf.h).
|
||||
#endif
|
||||
@@ -39,21 +42,14 @@ typedef struct {
|
||||
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
|
||||
} PARTITION;
|
||||
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
|
||||
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
|
||||
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
|
||||
|
||||
#else /* Single partition configuration */
|
||||
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
|
||||
#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Type of path name strings on FatFs API */
|
||||
|
||||
#if _LFN_UNICODE /* Unicode string */
|
||||
#if !_USE_LFN
|
||||
#if _LFN_UNICODE /* Unicode (UTF-16) string */
|
||||
#if _USE_LFN == 0
|
||||
#error _LFN_UNICODE must be 0 at non-LFN cfg.
|
||||
#endif
|
||||
#ifndef _INC_TCHAR
|
||||
@@ -61,14 +57,25 @@ typedef WCHAR TCHAR;
|
||||
#define _T(x) L ## x
|
||||
#define _TEXT(x) L ## x
|
||||
#endif
|
||||
|
||||
#else /* ANSI/OEM string */
|
||||
#ifndef _INC_TCHAR
|
||||
typedef char TCHAR;
|
||||
#define _T(x) x
|
||||
#define _TEXT(x) x
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Type of file size variables */
|
||||
|
||||
#if _FS_EXFAT
|
||||
#if _USE_LFN == 0
|
||||
#error LFN must be enabled when enable exFAT
|
||||
#endif
|
||||
typedef QWORD FSIZE_t;
|
||||
#else
|
||||
typedef DWORD FSIZE_t;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -76,60 +83,88 @@ typedef char TCHAR;
|
||||
/* File system object structure (FATFS) */
|
||||
|
||||
typedef struct {
|
||||
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
|
||||
BYTE fs_type; /* File system type (0:N/A) */
|
||||
BYTE drv; /* Physical drive number */
|
||||
BYTE csize; /* Sectors per cluster (1,2,4...128) */
|
||||
BYTE n_fats; /* Number of FAT copies (1 or 2) */
|
||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||
BYTE wflag; /* win[] flag (b0:dirty) */
|
||||
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
||||
WORD id; /* File system mount ID */
|
||||
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
||||
WORD csize; /* Cluster size [sectors] */
|
||||
#if _MAX_SS != _MIN_SS
|
||||
WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
|
||||
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
|
||||
#endif
|
||||
#if _USE_LFN != 0
|
||||
WCHAR* lfnbuf; /* LFN working buffer */
|
||||
#endif
|
||||
#if _FS_EXFAT
|
||||
BYTE* dirbuf; /* Directory entry block scratchpad buffer */
|
||||
#endif
|
||||
#if _FS_REENTRANT
|
||||
_SYNC_t sobj; /* Identifier of sync object */
|
||||
#endif
|
||||
#if !_FS_READONLY
|
||||
DWORD last_clust; /* Last allocated cluster */
|
||||
DWORD free_clust; /* Number of free clusters */
|
||||
DWORD last_clst; /* Last allocated cluster */
|
||||
DWORD free_clst; /* Number of free clusters */
|
||||
#endif
|
||||
#if _FS_RPATH
|
||||
#if _FS_RPATH != 0
|
||||
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||
#if _FS_EXFAT
|
||||
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
|
||||
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
|
||||
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
|
||||
#endif
|
||||
DWORD n_fatent; /* Number of FAT entries, = number of clusters + 2 */
|
||||
DWORD fsize; /* Sectors per FAT */
|
||||
DWORD volbase; /* Volume start sector */
|
||||
DWORD fatbase; /* FAT start sector */
|
||||
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
|
||||
DWORD database; /* Data start sector */
|
||||
#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[] */
|
||||
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||
} FATFS;
|
||||
|
||||
|
||||
|
||||
/* Object ID and allocation information (_FDID) */
|
||||
|
||||
typedef struct {
|
||||
FATFS* fs; /* Pointer to the owner file system object */
|
||||
WORD id; /* Owner file system mount ID */
|
||||
BYTE attr; /* Object attribute */
|
||||
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:flagmented in this session, b2:sub-directory stretched) */
|
||||
DWORD sclust; /* Object start cluster (0:no cluster or root directory) */
|
||||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||
#if _FS_EXFAT
|
||||
DWORD n_cont; /* Size of first fragment, clusters - 1 (valid when stat == 3) */
|
||||
DWORD n_frag; /* Size of last fragment needs to be written (valid when not zero) */
|
||||
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
|
||||
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
|
||||
DWORD c_ofs; /* Offset in the containing directory (valid when sclust != 0 and non-directory object) */
|
||||
#endif
|
||||
#if _FS_LOCK != 0
|
||||
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
|
||||
#endif
|
||||
} _FDID;
|
||||
|
||||
|
||||
|
||||
/* File object structure (FIL) */
|
||||
|
||||
typedef struct {
|
||||
FATFS* fs; /* Pointer to the related file system object (**do not change order**) */
|
||||
WORD id; /* Owner file system mount ID (**do not change order**) */
|
||||
BYTE flag; /* Status flags */
|
||||
_FDID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE err; /* Abort flag (error code) */
|
||||
DWORD fptr; /* File read/write pointer (Zeroed on file open) */
|
||||
DWORD fsize; /* File size */
|
||||
DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */
|
||||
DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
|
||||
DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */
|
||||
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
|
||||
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
|
||||
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
|
||||
#if !_FS_READONLY
|
||||
DWORD dir_sect; /* Sector number containing the directory entry */
|
||||
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
|
||||
#endif
|
||||
#if _USE_FASTSEEK
|
||||
DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
|
||||
#endif
|
||||
#if _FS_LOCK
|
||||
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
|
||||
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
|
||||
#endif
|
||||
#if !_FS_TINY
|
||||
BYTE buf[_MAX_SS]; /* File private data read/write window */
|
||||
@@ -141,23 +176,17 @@ typedef struct {
|
||||
/* Directory object structure (DIR) */
|
||||
|
||||
typedef struct {
|
||||
FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */
|
||||
WORD id; /* Owner file system mount ID (**do not change order**) */
|
||||
WORD index; /* Current read/write index number */
|
||||
DWORD sclust; /* Table start cluster (0:Root dir) */
|
||||
_FDID obj; /* Object identifier */
|
||||
DWORD dptr; /* Current read/write offset */
|
||||
DWORD clust; /* Current cluster */
|
||||
DWORD sect; /* Current sector */
|
||||
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
|
||||
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
|
||||
#if _FS_LOCK
|
||||
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
|
||||
#endif
|
||||
#if _USE_LFN
|
||||
WCHAR* lfn; /* Pointer to the LFN working buffer */
|
||||
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
|
||||
DWORD sect; /* Current sector (0:Read operation has terminated) */
|
||||
BYTE* dir; /* Pointer to the directory item in the win[] */
|
||||
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
|
||||
#if _USE_LFN != 0
|
||||
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
|
||||
#endif
|
||||
#if _USE_FIND
|
||||
const TCHAR* pat; /* Pointer to the name matching pattern */
|
||||
const TCHAR* pat; /* Pointer to the name matching pattern */
|
||||
#endif
|
||||
} DIR;
|
||||
|
||||
@@ -166,14 +195,15 @@ typedef struct {
|
||||
/* File information structure (FILINFO) */
|
||||
|
||||
typedef struct {
|
||||
DWORD fsize; /* File size */
|
||||
WORD fdate; /* Last modified date */
|
||||
WORD ftime; /* Last modified time */
|
||||
BYTE fattrib; /* Attribute */
|
||||
TCHAR fname[13]; /* Short file name (8.3 format) */
|
||||
#if _USE_LFN
|
||||
TCHAR* lfname; /* Pointer to the LFN buffer */
|
||||
UINT lfsize; /* Size of LFN buffer in TCHAR */
|
||||
FSIZE_t fsize; /* File size */
|
||||
WORD fdate; /* Modified date */
|
||||
WORD ftime; /* Modified time */
|
||||
BYTE fattrib; /* File attribute */
|
||||
#if _USE_LFN != 0
|
||||
TCHAR altname[13]; /* Altenative file name */
|
||||
TCHAR fname[_MAX_LFN + 1]; /* Primary file name */
|
||||
#else
|
||||
TCHAR fname[13]; /* File name */
|
||||
#endif
|
||||
} FILINFO;
|
||||
|
||||
@@ -196,7 +226,7 @@ typedef enum {
|
||||
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
|
||||
FR_NOT_ENABLED, /* (12) The volume has no work area */
|
||||
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
|
||||
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
|
||||
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
|
||||
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
|
||||
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
|
||||
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
|
||||
@@ -211,12 +241,11 @@ typedef enum {
|
||||
|
||||
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
|
||||
FRESULT f_close (FIL* fp); /* Close an open file object */
|
||||
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */
|
||||
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */
|
||||
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
|
||||
FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */
|
||||
FRESULT f_truncate (FIL* fp); /* Truncate file */
|
||||
FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */
|
||||
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */
|
||||
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */
|
||||
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */
|
||||
FRESULT f_truncate (FIL* fp); /* Truncate the file */
|
||||
FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */
|
||||
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
|
||||
FRESULT f_closedir (DIR* dp); /* Close an open directory */
|
||||
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
|
||||
@@ -226,28 +255,31 @@ FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
|
||||
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
|
||||
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
|
||||
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
|
||||
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of the file/dir */
|
||||
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */
|
||||
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */
|
||||
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */
|
||||
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
|
||||
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
|
||||
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
|
||||
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
|
||||
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
|
||||
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
|
||||
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
|
||||
FRESULT f_expand (FIL* fp, FSIZE_t szf, 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 sfd, UINT au); /* Create a file system on the volume */
|
||||
FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */
|
||||
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 */
|
||||
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
|
||||
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
|
||||
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
|
||||
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
|
||||
|
||||
#define f_eof(fp) ((int)((fp)->fptr == (fp)->fsize))
|
||||
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
|
||||
#define f_error(fp) ((fp)->err)
|
||||
#define f_tell(fp) ((fp)->fptr)
|
||||
#define f_size(fp) ((fp)->fsize)
|
||||
#define f_size(fp) ((fp)->obj.objsize)
|
||||
#define f_rewind(fp) f_lseek((fp), 0)
|
||||
#define f_rewinddir(dp) f_readdir((dp), 0)
|
||||
#define f_rmdir(path) f_unlink(path)
|
||||
|
||||
#ifndef EOF
|
||||
#define EOF (-1)
|
||||
@@ -265,7 +297,7 @@ DWORD get_fattime (void);
|
||||
#endif
|
||||
|
||||
/* Unicode support functions */
|
||||
#if _USE_LFN /* Unicode - OEM code conversion */
|
||||
#if _USE_LFN != 0 /* Unicode - OEM code conversion */
|
||||
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
|
||||
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
|
||||
#if _USE_LFN == 3 /* Memory functions */
|
||||
@@ -289,60 +321,39 @@ int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
|
||||
/* Flags and offset address */
|
||||
|
||||
|
||||
/* File access control and file status flags (FIL.flag) */
|
||||
|
||||
/* File access mode and open method flags (3rd argument of f_open) */
|
||||
#define FA_READ 0x01
|
||||
#define FA_OPEN_EXISTING 0x00
|
||||
|
||||
#if !_FS_READONLY
|
||||
#define FA_WRITE 0x02
|
||||
#define FA_OPEN_EXISTING 0x00
|
||||
#define FA_CREATE_NEW 0x04
|
||||
#define FA_CREATE_ALWAYS 0x08
|
||||
#define FA_OPEN_ALWAYS 0x10
|
||||
#define FA__WRITTEN 0x20
|
||||
#define FA__DIRTY 0x40
|
||||
#endif
|
||||
#define FA_OPEN_APPEND 0x30
|
||||
|
||||
/* Fast seek controls (2nd argument of f_lseek) */
|
||||
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
|
||||
|
||||
/* FAT sub type (FATFS.fs_type) */
|
||||
/* Format options (2nd argument of f_mkfs) */
|
||||
#define FM_FAT 0x01
|
||||
#define FM_FAT32 0x02
|
||||
#define FM_EXFAT 0x04
|
||||
#define FM_ANY 0x07
|
||||
#define FM_SFD 0x08
|
||||
|
||||
/* Filesystem type (FATFS.fs_type) */
|
||||
#define FS_FAT12 1
|
||||
#define FS_FAT16 2
|
||||
#define FS_FAT32 3
|
||||
#define FS_EXFAT 4
|
||||
|
||||
|
||||
/* File attribute bits for directory entry */
|
||||
|
||||
/* File attribute bits for directory entry (FILINFO.fattrib) */
|
||||
#define AM_RDO 0x01 /* Read only */
|
||||
#define AM_HID 0x02 /* Hidden */
|
||||
#define AM_SYS 0x04 /* System */
|
||||
#define AM_VOL 0x08 /* Volume label */
|
||||
#define AM_LFN 0x0F /* LFN entry */
|
||||
#define AM_DIR 0x10 /* Directory */
|
||||
#define AM_ARC 0x20 /* Archive */
|
||||
#define AM_MASK 0x3F /* Mask of defined bits */
|
||||
|
||||
|
||||
/* Fast seek feature */
|
||||
#define CREATE_LINKMAP 0xFFFFFFFF
|
||||
|
||||
|
||||
|
||||
/*--------------------------------*/
|
||||
/* Multi-byte word access macros */
|
||||
|
||||
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
|
||||
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
|
||||
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
|
||||
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
|
||||
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
|
||||
#else /* Use byte-by-byte access to the FAT structure */
|
||||
#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
|
||||
#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
|
||||
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
|
||||
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
160
loader/source/fatfs/ffconf.h → haxloader/source/fatfs/ffconf.h
Executable file → Normal file
160
loader/source/fatfs/ffconf.h → haxloader/source/fatfs/ffconf.h
Executable file → Normal file
@@ -1,8 +1,8 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module configuration file R0.11a (C)ChaN, 2015
|
||||
/ FatFs - FAT file system module configuration file
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _FFCONF 64180 /* Revision ID */
|
||||
#define _FFCONF 68300 /* Revision ID */
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function Configurations
|
||||
@@ -19,8 +19,8 @@
|
||||
/* This option defines minimization level to remove some basic API functions.
|
||||
/
|
||||
/ 0: All basic functions are enabled.
|
||||
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(),
|
||||
/ f_truncate() and f_rename() function are removed.
|
||||
/ 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. */
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
|
||||
|
||||
#define _USE_FIND 0
|
||||
/* This option switches filtered directory read feature and related functions,
|
||||
/ f_findfirst() and f_findnext(). (0:Disable or 1:Enable) */
|
||||
/* This option switches filtered directory read functions, f_findfirst() and
|
||||
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
|
||||
|
||||
|
||||
#define _USE_MKFS 0
|
||||
@@ -44,7 +44,16 @@
|
||||
|
||||
|
||||
#define _USE_FASTSEEK 0
|
||||
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
|
||||
/* This option switches fast seek function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define _USE_EXPAND 0
|
||||
/* This option switches f_expand function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define _USE_CHMOD 0
|
||||
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
|
||||
/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
|
||||
|
||||
|
||||
#define _USE_LABEL 0
|
||||
@@ -53,8 +62,7 @@
|
||||
|
||||
|
||||
#define _USE_FORWARD 0
|
||||
/* This option switches f_forward() function. (0:Disable or 1:Enable)
|
||||
/ To enable it, also _FS_TINY need to be set to 1. */
|
||||
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
@@ -65,7 +73,7 @@
|
||||
/* This option specifies the OEM code page to be used on the target system.
|
||||
/ Incorrect setting of the code page can cause a file open failure.
|
||||
/
|
||||
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
|
||||
/ 1 - ASCII (No support of extended character. Non-LFN cfg. only)
|
||||
/ 437 - U.S.
|
||||
/ 720 - Arabic
|
||||
/ 737 - Greek
|
||||
@@ -92,28 +100,30 @@
|
||||
|
||||
#define _USE_LFN 2
|
||||
#define _MAX_LFN 255
|
||||
/* The _USE_LFN option switches the LFN feature.
|
||||
/* The _USE_LFN switches the support of long file name (LFN).
|
||||
/
|
||||
/ 0: Disable LFN feature. _MAX_LFN has no effect.
|
||||
/ 0: Disable support of LFN. _MAX_LFN has no effect.
|
||||
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
|
||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
||||
/
|
||||
/ When enable the LFN feature, Unicode handling functions (option/unicode.c) must
|
||||
/ be added to the project. The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes.
|
||||
/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
|
||||
/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
|
||||
/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
|
||||
/ It should be set 255 to support full featured LFN operations.
|
||||
/ 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. */
|
||||
|
||||
|
||||
#define _LFN_UNICODE 0
|
||||
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode)
|
||||
/ To use Unicode string for the path name, enable LFN feature and set _LFN_UNICODE
|
||||
/ to 1. This option also affects behavior of string I/O functions. */
|
||||
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:UTF-16)
|
||||
/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
|
||||
/ This option also affects behavior of string I/O functions. */
|
||||
|
||||
|
||||
#define _STRF_ENCODE 3
|
||||
/* When _LFN_UNICODE is 1, this option selects the character encoding on the file to
|
||||
/* When _LFN_UNICODE == 1, this option selects the character encoding ON THE FILE to
|
||||
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
|
||||
/
|
||||
/ 0: ANSI/OEM
|
||||
@@ -121,17 +131,16 @@
|
||||
/ 2: UTF-16BE
|
||||
/ 3: UTF-8
|
||||
/
|
||||
/ When _LFN_UNICODE is 0, this option has no effect. */
|
||||
/ This option has no effect when _LFN_UNICODE == 0. */
|
||||
|
||||
|
||||
#define _FS_RPATH 0
|
||||
/* This option configures relative path feature.
|
||||
/* This option configures support of relative path.
|
||||
/
|
||||
/ 0: Disable relative path feature and remove related functions.
|
||||
/ 1: Enable relative path feature. f_chdir() and f_chdrive() are available.
|
||||
/ 0: Disable relative path and remove related functions.
|
||||
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
|
||||
/ 2: f_getcwd() function is available in addition to 1.
|
||||
/
|
||||
/ Note that directory items read via f_readdir() are affected by this option. */
|
||||
*/
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
@@ -139,12 +148,12 @@
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _VOLUMES 1
|
||||
/* Number of volumes (logical drives) to be used. */
|
||||
/* Number of volumes (logical drives) to be used. (1-10) */
|
||||
|
||||
|
||||
#define _STR_VOLUME_ID 0
|
||||
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
|
||||
/* _STR_VOLUME_ID option switches string volume ID feature.
|
||||
#define _VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
|
||||
/* _STR_VOLUME_ID switches string support of volume ID.
|
||||
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
|
||||
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
|
||||
/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
|
||||
@@ -152,26 +161,27 @@
|
||||
|
||||
|
||||
#define _MULTI_PARTITION 0
|
||||
/* This option switches multi-partition feature. By default (0), each logical drive
|
||||
/ number is bound to the same physical drive number and only an FAT volume found on
|
||||
/ the physical drive will be mounted. When multi-partition feature is enabled (1),
|
||||
/ each logical drive number is bound to arbitrary physical drive and partition
|
||||
/ listed in the VolToPart[]. Also f_fdisk() funciton will be available. */
|
||||
/* This option switches support of multi-partition on a physical drive.
|
||||
/ By default (0), each logical drive number is bound to the same physical drive
|
||||
/ number and only an FAT volume found on the physical drive will be mounted.
|
||||
/ When multi-partition is enabled (1), each logical drive number can be bound to
|
||||
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
|
||||
/ funciton will be available. */
|
||||
|
||||
|
||||
#define _MIN_SS 512
|
||||
#define _MAX_SS 512
|
||||
/* These options configure the range of sector size to be supported. (512, 1024,
|
||||
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
|
||||
/ 2048 or 4096) Always set both 512 for most systems, generic memory card and
|
||||
/ harddisk. But a larger value may be required for on-board flash memory and some
|
||||
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
|
||||
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
|
||||
/ disk_ioctl() function. */
|
||||
/ to variable sector size and GET_SECTOR_SIZE command needs to be implemented to
|
||||
/ the disk_ioctl() function. */
|
||||
|
||||
|
||||
#define _USE_TRIM 0
|
||||
/* This option switches ATA-TRIM feature. (0:Disable or 1:Enable)
|
||||
/ To enable Trim feature, also CTRL_TRIM command should be implemented to the
|
||||
/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
|
||||
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
|
||||
/ disk_ioctl() function. */
|
||||
|
||||
|
||||
@@ -194,46 +204,51 @@
|
||||
|
||||
#define _FS_TINY 0
|
||||
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
|
||||
/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS
|
||||
/ bytes. Instead of private sector buffer eliminated from the file object,
|
||||
/ common sector buffer in the file system object (FATFS) is used for the file
|
||||
/ data transfer. */
|
||||
/ At the tiny configuration, size of file object (FIL) is shrinked _MAX_SS bytes.
|
||||
/ Instead of private sector buffer eliminated from the file object, common sector
|
||||
/ buffer in the file system object (FATFS) is used for the file data transfer. */
|
||||
|
||||
|
||||
#define _FS_EXFAT 0
|
||||
/* This option switches support of exFAT file system. (0:Disable or 1:Enable)
|
||||
/ When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1)
|
||||
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
||||
|
||||
|
||||
#define _FS_NORTC 1
|
||||
#define _NORTC_MON 1
|
||||
#define _NORTC_MDAY 1
|
||||
#define _NORTC_YEAR 2015
|
||||
/* The _FS_NORTC option switches timestamp feature. If the system does not have
|
||||
/ an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable
|
||||
/ the timestamp feature. All objects modified by FatFs will have a fixed timestamp
|
||||
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR.
|
||||
/ When timestamp feature is enabled (_FS_NORTC == 0), get_fattime() function need
|
||||
/ to be added to the project to read current time form RTC. _NORTC_MON,
|
||||
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
|
||||
/ These options have no effect at read-only configuration (_FS_READONLY == 1). */
|
||||
#define _NORTC_YEAR 2017
|
||||
/* The option _FS_NORTC switches timestamp functiton. If the system does not have
|
||||
/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
|
||||
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
|
||||
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
|
||||
/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
|
||||
/ added to the project to get current time form real-time clock. _NORTC_MON,
|
||||
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
|
||||
/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
|
||||
|
||||
|
||||
#define _FS_LOCK 0
|
||||
/* The _FS_LOCK option switches file lock feature to control duplicated file open
|
||||
/* The option _FS_LOCK switches file lock function to control duplicated file open
|
||||
/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
|
||||
/ is 1.
|
||||
/
|
||||
/ 0: Disable file lock feature. To avoid volume corruption, application program
|
||||
/ 0: Disable file lock function. To avoid volume corruption, application program
|
||||
/ should avoid illegal open, remove and rename to the open objects.
|
||||
/ >0: Enable file lock feature. The value defines how many files/sub-directories
|
||||
/ >0: Enable file lock function. The value defines how many files/sub-directories
|
||||
/ can be opened simultaneously under file lock control. Note that the file
|
||||
/ lock feature is independent of re-entrancy. */
|
||||
/ lock control is independent of re-entrancy. */
|
||||
|
||||
|
||||
#define _FS_REENTRANT 0
|
||||
#define _FS_TIMEOUT 1000
|
||||
#define _SYNC_t HANDLE
|
||||
/* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs
|
||||
/* The option _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 feature.
|
||||
/ to the same volume is under control of this function.
|
||||
/
|
||||
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
|
||||
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
|
||||
@@ -243,34 +258,11 @@
|
||||
/
|
||||
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
|
||||
/ The _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.c. */
|
||||
/ 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 */
|
||||
|
||||
|
||||
#define _WORD_ACCESS 0
|
||||
/* The _WORD_ACCESS option is an only platform dependent option. It defines
|
||||
/ which access method is used to the word data on the FAT volume.
|
||||
/
|
||||
/ 0: Byte-by-byte access. Always compatible with all platforms.
|
||||
/ 1: Word access. Do not choose this unless under both the following conditions.
|
||||
/
|
||||
/ * Address misaligned memory access is always allowed to ALL instructions.
|
||||
/ * Byte order on the memory is little-endian.
|
||||
/
|
||||
/ If it is the case, _WORD_ACCESS can also be set to 1 to reduce code size.
|
||||
/ Following table shows allowable settings of some type of processors.
|
||||
/
|
||||
/ ARM7TDMI 0 *2 ColdFire 0 *1 V850E 0 *2
|
||||
/ Cortex-M3 0 *3 Z80 0/1 V850ES 0/1
|
||||
/ Cortex-M0 0 *2 x86 0/1 TLCS-870 0/1
|
||||
/ AVR 0/1 RX600(LE) 0/1 TLCS-900 0/1
|
||||
/ AVR32 0 *1 RL78 0 *2 R32C 0 *2
|
||||
/ PIC18 0/1 SH-2 0 *1 M16C 0/1
|
||||
/ PIC24 0 *2 H8S 0 *1 MSP430 0 *2
|
||||
/ PIC32 0 *1 H8/300H 0 *1 8051 0/1
|
||||
/
|
||||
/ *1:Big-endian.
|
||||
/ *2:Unaligned memory access is not supported.
|
||||
/ *3:Some compilers generate LDM/STM for mem_cpy function.
|
||||
*/
|
||||
|
||||
/*--- End of configuration options ---*/
|
||||
15
loader/source/fatfs/integer.h → haxloader/source/fatfs/integer.h
Executable file → Normal file
15
loader/source/fatfs/integer.h → haxloader/source/fatfs/integer.h
Executable file → Normal file
@@ -5,13 +5,19 @@
|
||||
#ifndef _FF_INTEGER
|
||||
#define _FF_INTEGER
|
||||
|
||||
#ifdef _WIN32 /* Development platform */
|
||||
#ifdef _WIN32 /* FatFs development platform */
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
typedef unsigned __int64 QWORD;
|
||||
|
||||
|
||||
#else /* Embedded platform */
|
||||
|
||||
/* These types MUST be 16-bit or 32-bit */
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
|
||||
/* This type MUST be 8-bit */
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
@@ -20,14 +26,13 @@ typedef short SHORT;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned short WCHAR;
|
||||
|
||||
/* These types MUST be 16-bit or 32-bit */
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
|
||||
/* These types MUST be 32-bit */
|
||||
typedef long LONG;
|
||||
typedef unsigned long DWORD;
|
||||
|
||||
/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
|
||||
typedef unsigned long long QWORD;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
108
loader/source/fatfs/option/ccsbcs.c → haxloader/source/fatfs/option/ccsbcs.c
Executable file → Normal file
108
loader/source/fatfs/option/ccsbcs.c → haxloader/source/fatfs/option/ccsbcs.c
Executable file → Normal file
@@ -300,47 +300,87 @@ WCHAR ff_convert ( /* Converted character, Returns zero on error */
|
||||
|
||||
|
||||
|
||||
|
||||
WCHAR ff_wtoupper ( /* Returns upper converted character */
|
||||
WCHAR chr /* Unicode character to be upper converted */
|
||||
WCHAR chr /* Unicode character to be upper converted (BMP only) */
|
||||
)
|
||||
{
|
||||
static const WCHAR lower[] = { /* Lower case characters to be converted */
|
||||
/* Latin Supplement */ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
|
||||
/* Latin Extended-A */ 0x101,0x103,0x105,0x107,0x109,0x10B,0x10D,0x10F,0x111,0x113,0x115,0x117,0x119,0x11B,0x11D,0x11F,0x121,0x123,0x125,0x127,0x129,0x12B,0x12D,0x12F,0x131,0x133,0x135,0x137,0x13A,0x13C,0x13E,0x140,0x142,0x144,0x146,0x148,0x14B,0x14D,0x14F,0x151,0x153,0x155,0x157,0x159,0x15B,0x15D,0x15F,0x161,0x163,0x165,0x167,0x169,0x16B,0x16D,0x16F,0x171,0x173,0x175,0x177,0x17A,0x17C,0x17E,
|
||||
/* Latin Extended-B */ 0x183,0x185,0x188,0x18C,0x192,0x199,0x1A1,0x1A3,0x1A8,0x1AD,0x1B0,0x1B4,0x1B6,0x1B9,0x1BD,0x1C6,0x1C9,0x1CC,0x1CE,0x1D0,0x1D2,0x1D4,0x1D6,0x1D8,0x1DA,0x1DC,0x1DD,0x1DF,0x1E1,0x1E3,0x1E5,0x1E7,0x1E9,0x1EB,0x1ED,0x1EF,0x1F3,0x1F5,0x1FB,0x1FD,0x1FF,0x201,0x203,0x205,0x207,0x209,0x20B,0x20D,0x20F,0x211,0x213,0x215,0x217,
|
||||
/* Greek, Coptic */ 0x3B1,0x3B2,0x3B3,0x3B4,0x3B5,0x3B6,0x3B7,0x3B8,0x3B9,0x3BA,0x3BB,0x3BC,0x3BD,0x3BE,0x3BF,0x3C0,0x3C1,0x3C3,0x3C4,0x3C5,0x3C6,0x3C7,0x3C8,0x3C9,0x3CA,0x3CB,0x3CC,0x3CD,0x3CE,0x3E3,0x3E5,0x3E7,0x3E9,0x3EB,
|
||||
/* Cyrillic */ 0x430,0x431,0x432,0x433,0x434,0x435,0x436,0x437,0x438,0x439,0x43A,0x43B,0x43C,0x43D,0x43E,0x43F,0x440,0x441,0x442,0x443,0x444,0x445,0x446,0x447,0x448,0x449,0x44A,0x44B,0x44C,0x44D,0x44E,0x44F,0x452,0x453,0x454,0x455,0x456,0x457,0x458,0x459,0x45A,0x45B,0x45C,0x45E,0x45F,0x461,0x463,0x465,0x467,0x469,0x46B,0x46D,0x46F,0x471,0x473,0x475,0x477,0x479,0x47B,0x47D,0x47F,0x481,0x491,0x493,0x495,0x497,0x499,0x49B,0x49D,0x49F,0x4A1,0x4A3,0x4A5,0x4A7,0x4A9,0x4AB,0x4AD,0x4AF,0x4B1,0x4B3,0x4B5,0x4B7,0x4B9,0x4BB,0x4BD,0x4BF,0x4C2,0x4C4,0x4C8,0x4D1,0x4D3,0x4D5,0x4D7,0x4D9,0x4DB,0x4DD,0x4DF,0x4E1,0x4E3,0x4E5,0x4E7,0x4E9,0x4EB,0x4ED,0x4EF,0x4F1,0x4F3,0x4F5,0x4F9,
|
||||
/* Armenian */ 0x561,0x562,0x563,0x564,0x565,0x566,0x567,0x568,0x569,0x56A,0x56B,0x56C,0x56D,0x56E,0x56F,0x570,0x571,0x572,0x573,0x574,0x575,0x576,0x577,0x578,0x579,0x57A,0x57B,0x57C,0x57D,0x57E,0x57F,0x580,0x581,0x582,0x583,0x584,0x585,0x586,
|
||||
/* Latin Extended Additional */ 0x1E01,0x1E03,0x1E05,0x1E07,0x1E09,0x1E0B,0x1E0D,0x1E0F,0x1E11,0x1E13,0x1E15,0x1E17,0x1E19,0x1E1B,0x1E1D,0x1E1F,0x1E21,0x1E23,0x1E25,0x1E27,0x1E29,0x1E2B,0x1E2D,0x1E2F,0x1E31,0x1E33,0x1E35,0x1E37,0x1E39,0x1E3B,0x1E3D,0x1E3F,0x1E41,0x1E43,0x1E45,0x1E47,0x1E49,0x1E4B,0x1E4D,0x1E4F,0x1E51,0x1E53,0x1E55,0x1E57,0x1E59,0x1E5B,0x1E5D,0x1E5F,0x1E61,0x1E63,0x1E65,0x1E67,0x1E69,0x1E6B,0x1E6D,0x1E6F,0x1E71,0x1E73,0x1E75,0x1E77,0x1E79,0x1E7B,0x1E7D,0x1E7F,0x1E81,0x1E83,0x1E85,0x1E87,0x1E89,0x1E8B,0x1E8D,0x1E8F,0x1E91,0x1E93,0x1E95,0x1E97,0x1E99,0x1E9B,0x1E9D,0x1E9F,0x1EA1,0x1EA3,0x1EA5,0x1EA7,0x1EA9,0x1EAB,0x1EAD,0x1EAF,0x1EB1,0x1EB3,0x1EB5,0x1EB7,0x1EB9,0x1EBB,0x1EBD,0x1EBF,0x1EC1,0x1EC3,0x1EC5,0x1EC7,0x1EC9,0x1ECB,0x1ECD,0x1ECF,0x1ED1,0x1ED3,0x1ED5,0x1ED7,0x1ED9,0x1EDB,0x1EDD,0x1EDF,0x1EE1,0x1EE3,0x1EE5,0x1EE7,0x1EE9,0x1EEB,0x1EED,0x1EEF,0x1EF1,0x1EF3,0x1EF5,0x1EF7,0x1EF9,
|
||||
/* Number forms */ 0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177,0x2178,0x2179,0x217A,0x217B,0x217C,0x217D,0x217E,0x217F,
|
||||
/* Full-width */ 0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,0xFF48,0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F,0xFF50,0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0xFF57,0xFF58,0xFF59,0xFF5A
|
||||
/* Compressed upper conversion table */
|
||||
static const WCHAR cvt1[] = { /* U+0000 - U+0FFF */
|
||||
/* Basic Latin */
|
||||
0x0061,0x031A,
|
||||
/* Latin-1 Supplement */
|
||||
0x00E0,0x0317, 0x00F8,0x0307, 0x00FF,0x0001,0x0178,
|
||||
/* Latin Extended-A */
|
||||
0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106,
|
||||
/* Latin Extended-B */
|
||||
0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA,
|
||||
0x01CD,0x0110, 0x01DD,0x0001,0x018E, 0x01DE,0x0112, 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, 0x01F8,0x0128,
|
||||
0x0222,0x0112, 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, 0x0246,0x010A,
|
||||
/* IPA Extensions */
|
||||
0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7,
|
||||
/* Greek, Coptic */
|
||||
0x037B,0x0003,0x03FD,0x03FE,0x03FF, 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, 0x03B1,0x0311,
|
||||
0x03C2,0x0002,0x03A3,0x03A3, 0x03C4,0x0308, 0x03CC,0x0003,0x038C,0x038E,0x038F, 0x03D8,0x0118,
|
||||
0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA,
|
||||
/* Cyrillic */
|
||||
0x0430,0x0320, 0x0450,0x0710, 0x0460,0x0122, 0x048A,0x0136, 0x04C1,0x010E, 0x04CF,0x0001,0x04C0, 0x04D0,0x0144,
|
||||
/* Armenian */
|
||||
0x0561,0x0426,
|
||||
|
||||
0x0000
|
||||
};
|
||||
static const WCHAR upper[] = { /* Upper case characters correspond to lower[] */
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x178,
|
||||
0x100,0x102,0x104,0x106,0x108,0x10A,0x10C,0x10E,0x110,0x112,0x114,0x116,0x118,0x11A,0x11C,0x11E,0x120,0x122,0x124,0x126,0x128,0x12A,0x12C,0x12E,0x130,0x132,0x134,0x136,0x139,0x13B,0x13D,0x13F,0x141,0x143,0x145,0x147,0x14A,0x14C,0x14E,0x150,0x152,0x154,0x156,0x158,0x15A,0x15C,0x15E,0x160,0x162,0x164,0x166,0x168,0x16A,0x16C,0x16E,0x170,0x172,0x174,0x176,0x179,0x17B,0x17D,
|
||||
0x182,0x184,0x187,0x18B,0x191,0x198,0x1A0,0x1A2,0x1A7,0x1AC,0x1AF,0x1B3,0x1B5,0x1B8,0x1BC,0x1C4,0x1C7,0x1CA,0x1CD,0x1CF,0x1D1,0x1D3,0x1D5,0x1D7,0x1D9,0x1DB,0x18E,0x1DE,0x1E0,0x1E2,0x1E4,0x1E6,0x1E8,0x1EA,0x1EC,0x1EE,0x1F1,0x1F4,0x1FA,0x1FC,0x1FE,0x200,0x202,0x204,0x206,0x208,0x20A,0x20C,0x20E,0x210,0x212,0x214,0x216,
|
||||
0x391,0x392,0x393,0x394,0x395,0x396,0x397,0x398,0x399,0x39A,0x39B,0x39C,0x39D,0x39E,0x39F,0x3A0,0x3A1,0x3A3,0x3A4,0x3A5,0x3A6,0x3A7,0x3A8,0x3A9,0x3AA,0x3AB,0x38C,0x38E,0x38F,0x3E2,0x3E4,0x3E6,0x3E8,0x3EA,
|
||||
0x410,0x411,0x412,0x413,0x414,0x415,0x416,0x417,0x418,0x419,0x41A,0x41B,0x41C,0x41D,0x41E,0x41F,0x420,0x421,0x422,0x423,0x424,0x425,0x426,0x427,0x428,0x429,0x42A,0x42B,0x42C,0x42D,0x42E,0x42F,0x402,0x403,0x404,0x405,0x406,0x407,0x408,0x409,0x40A,0x40B,0x40C,0x40E,0x40F,0x460,0x462,0x464,0x466,0x468,0x46A,0x46C,0x46E,0x470,0x472,0x474,0x476,0x478,0x47A,0x47C,0x47E,0x480,0x490,0x492,0x494,0x496,0x498,0x49A,0x49C,0x49E,0x4A0,0x4A2,0x4A4,0x4A6,0x4A8,0x4AA,0x4AC,0x4AE,0x4B0,0x4B2,0x4B4,0x4B6,0x4B8,0x4BA,0x4BC,0x4BE,0x4C1,0x4C3,0x5C7,0x4D0,0x4D2,0x4D4,0x4D6,0x4D8,0x4DA,0x4DC,0x4DE,0x4E0,0x4E2,0x4E4,0x4E6,0x4E8,0x4EA,0x4EC,0x4EE,0x4F0,0x4F2,0x4F4,0x4F8,
|
||||
0x531,0x532,0x533,0x534,0x535,0x536,0x537,0x538,0x539,0x53A,0x53B,0x53C,0x53D,0x53E,0x53F,0x540,0x541,0x542,0x543,0x544,0x545,0x546,0x547,0x548,0x549,0x54A,0x54B,0x54C,0x54D,0x54E,0x54F,0x550,0x551,0x552,0x553,0x554,0x555,0x556,
|
||||
0x1E00,0x1E02,0x1E04,0x1E06,0x1E08,0x1E0A,0x1E0C,0x1E0E,0x1E10,0x1E12,0x1E14,0x1E16,0x1E18,0x1E1A,0x1E1C,0x1E1E,0x1E20,0x1E22,0x1E24,0x1E26,0x1E28,0x1E2A,0x1E2C,0x1E2E,0x1E30,0x1E32,0x1E34,0x1E36,0x1E38,0x1E3A,0x1E3C,0x1E3E,0x1E40,0x1E42,0x1E44,0x1E46,0x1E48,0x1E4A,0x1E4C,0x1E4E,0x1E50,0x1E52,0x1E54,0x1E56,0x1E58,0x1E5A,0x1E5C,0x1E5E,0x1E60,0x1E62,0x1E64,0x1E66,0x1E68,0x1E6A,0x1E6C,0x1E6E,0x1E70,0x1E72,0x1E74,0x1E76,0x1E78,0x1E7A,0x1E7C,0x1E7E,0x1E80,0x1E82,0x1E84,0x1E86,0x1E88,0x1E8A,0x1E8C,0x1E8E,0x1E90,0x1E92,0x1E94,0x1E96,0x1E98,0x1E9A,0x1E9C,0x1E9E,0x1EA0,0x1EA2,0x1EA4,0x1EA6,0x1EA8,0x1EAA,0x1EAC,0x1EAE,0x1EB0,0x1EB2,0x1EB4,0x1EB6,0x1EB8,0x1EBA,0x1EBC,0x1EBE,0x1EC0,0x1EC2,0x1EC4,0x1EC6,0x1EC8,0x1ECA,0x1ECC,0x1ECE,0x1ED0,0x1ED2,0x1ED4,0x1ED6,0x1ED8,0x1EDA,0x1EDC,0x1EDE,0x1EE0,0x1EE2,0x1EE4,0x1EE6,0x1EE8,0x1EEA,0x1EEC,0x1EEE,0x1EF0,0x1EF2,0x1EF4,0x1EF6,0x1EF8,
|
||||
0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166,0x2167,0x2168,0x2169,0x216A,0x216B,0x216C,0x216D,0x216E,0x216F,
|
||||
0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,0xFF28,0xFF29,0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F,0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,0xFF38,0xFF39,0xFF3A
|
||||
static const WCHAR cvt2[] = { /* U+1000 - U+FFFF */
|
||||
/* Phonetic Extensions */
|
||||
0x1D7D,0x0001,0x2C63,
|
||||
/* Latin Extended Additional */
|
||||
0x1E00,0x0196, 0x1EA0,0x015A,
|
||||
/* Greek Extended */
|
||||
0x1F00,0x0608, 0x1F10,0x0606, 0x1F20,0x0608, 0x1F30,0x0608, 0x1F40,0x0606,
|
||||
0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, 0x1F60,0x0608,
|
||||
0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB,
|
||||
0x1F80,0x0608, 0x1F90,0x0608, 0x1FA0,0x0608, 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
|
||||
0x1FCC,0x0001,0x1FC3, 0x1FD0,0x0602, 0x1FE0,0x0602, 0x1FE5,0x0001,0x1FEC, 0x1FF2,0x0001,0x1FFC,
|
||||
/* Letterlike Symbols */
|
||||
0x214E,0x0001,0x2132,
|
||||
/* Number forms */
|
||||
0x2170,0x0210, 0x2184,0x0001,0x2183,
|
||||
/* Enclosed Alphanumerics */
|
||||
0x24D0,0x051A, 0x2C30,0x042F,
|
||||
/* Latin Extended-C */
|
||||
0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102,
|
||||
/* Coptic */
|
||||
0x2C80,0x0164,
|
||||
/* Georgian Supplement */
|
||||
0x2D00,0x0826,
|
||||
/* Full-width */
|
||||
0xFF41,0x031A,
|
||||
|
||||
0x0000
|
||||
};
|
||||
UINT i, n, hi, li;
|
||||
const WCHAR *p;
|
||||
WCHAR bc, nc, cmd;
|
||||
|
||||
|
||||
if (chr < 0x80) { /* ASCII characters (acceleration) */
|
||||
if (chr >= 0x61 && chr <= 0x7A) chr -= 0x20;
|
||||
|
||||
} else { /* Non ASCII characters (table search) */
|
||||
n = 12; li = 0; hi = sizeof lower / sizeof lower[0];
|
||||
do {
|
||||
i = li + (hi - li) / 2;
|
||||
if (chr == lower[i]) break;
|
||||
if (chr > lower[i]) li = i; else hi = i;
|
||||
} while (--n);
|
||||
if (n) chr = upper[i];
|
||||
p = chr < 0x1000 ? cvt1 : cvt2;
|
||||
for (;;) {
|
||||
bc = *p++; /* Get block base */
|
||||
if (!bc || chr < bc) break;
|
||||
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
|
||||
if (chr < bc + nc) { /* In the block? */
|
||||
switch (cmd) {
|
||||
case 0: chr = p[chr - bc]; break; /* Table conversion */
|
||||
case 1: chr -= (chr - bc) & 1; break; /* Case pairs */
|
||||
case 2: chr -= 16; break; /* Shift -16 */
|
||||
case 3: chr -= 32; break; /* Shift -32 */
|
||||
case 4: chr -= 48; break; /* Shift -48 */
|
||||
case 5: chr -= 26; break; /* Shift -26 */
|
||||
case 6: chr += 8; break; /* Shift +8 */
|
||||
case 7: chr -= 80; break; /* Shift -80 */
|
||||
case 8: chr -= 0x1C60; break; /* Shift -0x1C60 */
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!cmd) p += nc;
|
||||
}
|
||||
|
||||
return chr;
|
||||
5
haxloader/source/fatfs/sdmmc/delay.h
Normal file
5
haxloader/source/fatfs/sdmmc/delay.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../types.h"
|
||||
|
||||
void waitcycles(u32 us);
|
||||
16
haxloader/source/fatfs/sdmmc/delay.s
Normal file
16
haxloader/source/fatfs/sdmmc/delay.s
Normal file
@@ -0,0 +1,16 @@
|
||||
.text
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
.global waitcycles
|
||||
.type waitcycles, %function
|
||||
waitcycles:
|
||||
push {r0-r2, lr}
|
||||
str r0, [sp, #4]
|
||||
waitcycles_loop:
|
||||
ldr r3, [sp, #4]
|
||||
subs r2, r3, #1
|
||||
str r2, [sp, #4]
|
||||
cmp r3, #0
|
||||
bne waitcycles_loop
|
||||
pop {r0-r2, pc}
|
||||
490
haxloader/source/fatfs/sdmmc/sdmmc.c
Normal file
490
haxloader/source/fatfs/sdmmc/sdmmc.c
Normal file
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright (c) 2014-2015, Normmatt
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms
|
||||
* of the GNU General Public License Version 2, as described below:
|
||||
*
|
||||
* This file is free software: you may copy, redistribute and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This file 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 "sdmmc.h"
|
||||
#include "delay.h"
|
||||
|
||||
//static struct mmcdevice handleNAND;
|
||||
static struct mmcdevice handleSD;
|
||||
|
||||
static inline u16 sdmmc_read16(u16 reg)
|
||||
{
|
||||
return *(vu16 *)(SDMMC_BASE + reg);
|
||||
}
|
||||
|
||||
static inline void sdmmc_write16(u16 reg, u16 val)
|
||||
{
|
||||
*(vu16 *)(SDMMC_BASE + reg) = val;
|
||||
}
|
||||
|
||||
static inline u32 sdmmc_read32(u16 reg)
|
||||
{
|
||||
return *(vu32 *)(SDMMC_BASE + reg);
|
||||
}
|
||||
|
||||
static inline void sdmmc_write32(u16 reg, u32 val)
|
||||
{
|
||||
*(vu32 *)(SDMMC_BASE + reg) = val;
|
||||
}
|
||||
|
||||
static inline void sdmmc_mask16(u16 reg, const u16 clear, const u16 set)
|
||||
{
|
||||
u16 val = sdmmc_read16(reg);
|
||||
val &= ~clear;
|
||||
val |= set;
|
||||
sdmmc_write16(reg, val);
|
||||
}
|
||||
|
||||
static inline void setckl(u32 data)
|
||||
{
|
||||
sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
|
||||
sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF);
|
||||
sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100);
|
||||
}
|
||||
|
||||
/*
|
||||
mmcdevice *getMMCDevice(int drive)
|
||||
{
|
||||
if(drive == 0) return &handleNAND;
|
||||
return &handleSD;
|
||||
}
|
||||
*/
|
||||
|
||||
static int geterror(struct mmcdevice *ctx)
|
||||
{
|
||||
return (int)((ctx->error << 29) >> 31);
|
||||
}
|
||||
|
||||
static void inittarget(struct mmcdevice *ctx)
|
||||
{
|
||||
sdmmc_mask16(REG_SDPORTSEL, 0x3, (u16)ctx->devicenumber);
|
||||
setckl(ctx->clk);
|
||||
if(ctx->SDOPT == 0) sdmmc_mask16(REG_SDOPT, 0, 0x8000);
|
||||
else sdmmc_mask16(REG_SDOPT, 0x8000, 0);
|
||||
}
|
||||
|
||||
static void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args)
|
||||
{
|
||||
u32 getSDRESP = (cmd << 15) >> 31;
|
||||
u16 flags = (cmd << 15) >> 31;
|
||||
const int readdata = cmd & 0x20000;
|
||||
const int writedata = cmd & 0x40000;
|
||||
|
||||
if(readdata || writedata)
|
||||
flags |= TMIO_STAT0_DATAEND;
|
||||
|
||||
ctx->error = 0;
|
||||
while((sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY)); //mmc working?
|
||||
sdmmc_write16(REG_SDIRMASK0, 0);
|
||||
sdmmc_write16(REG_SDIRMASK1, 0);
|
||||
sdmmc_write16(REG_SDSTATUS0, 0);
|
||||
sdmmc_write16(REG_SDSTATUS1, 0);
|
||||
sdmmc_mask16(REG_DATACTL32, 0x1800, 0);
|
||||
sdmmc_write16(REG_SDCMDARG0, args & 0xFFFF);
|
||||
sdmmc_write16(REG_SDCMDARG1, args >> 16);
|
||||
sdmmc_write16(REG_SDCMD, cmd & 0xFFFF);
|
||||
|
||||
u32 size = ctx->size;
|
||||
u8 *rDataPtr = ctx->rData;
|
||||
const u8 *tDataPtr = ctx->tData;
|
||||
|
||||
bool rUseBuf = rDataPtr != NULL;
|
||||
bool tUseBuf = tDataPtr != NULL;
|
||||
|
||||
u16 status0 = 0;
|
||||
while(true)
|
||||
{
|
||||
vu16 status1 = sdmmc_read16(REG_SDSTATUS1);
|
||||
vu16 ctl32 = sdmmc_read16(REG_DATACTL32);
|
||||
if((ctl32 & 0x100))
|
||||
{
|
||||
if(readdata)
|
||||
{
|
||||
if(rUseBuf)
|
||||
{
|
||||
sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0);
|
||||
if(size > 0x1FF)
|
||||
{
|
||||
//Gabriel Marcano: This implementation doesn't assume alignment.
|
||||
//I've removed the alignment check doen with former rUseBuf32 as a result
|
||||
for(int i = 0; i < 0x200; i += 4)
|
||||
{
|
||||
u32 data = sdmmc_read32(REG_SDFIFO32);
|
||||
*rDataPtr++ = data;
|
||||
*rDataPtr++ = data >> 8;
|
||||
*rDataPtr++ = data >> 16;
|
||||
*rDataPtr++ = data >> 24;
|
||||
}
|
||||
size -= 0x200;
|
||||
}
|
||||
}
|
||||
|
||||
sdmmc_mask16(REG_DATACTL32, 0x800, 0);
|
||||
}
|
||||
}
|
||||
if(!(ctl32 & 0x200))
|
||||
{
|
||||
if(writedata)
|
||||
{
|
||||
if(tUseBuf)
|
||||
{
|
||||
sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0);
|
||||
if(size > 0x1FF)
|
||||
{
|
||||
for(int i = 0; i < 0x200; i += 4)
|
||||
{
|
||||
u32 data = *tDataPtr++;
|
||||
data |= (u32)*tDataPtr++ << 8;
|
||||
data |= (u32)*tDataPtr++ << 16;
|
||||
data |= (u32)*tDataPtr++ << 24;
|
||||
sdmmc_write32(REG_SDFIFO32, data);
|
||||
}
|
||||
size -= 0x200;
|
||||
}
|
||||
}
|
||||
|
||||
sdmmc_mask16(REG_DATACTL32, 0x1000, 0);
|
||||
}
|
||||
}
|
||||
if(status1 & TMIO_MASK_GW)
|
||||
{
|
||||
ctx->error |= 4;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!(status1 & TMIO_STAT1_CMD_BUSY))
|
||||
{
|
||||
status0 = sdmmc_read16(REG_SDSTATUS0);
|
||||
if(sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND)
|
||||
{
|
||||
ctx->error |= 0x1;
|
||||
}
|
||||
if(status0 & TMIO_STAT0_DATAEND)
|
||||
{
|
||||
ctx->error |= 0x2;
|
||||
}
|
||||
|
||||
if((status0 & flags) == flags)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ctx->stat0 = sdmmc_read16(REG_SDSTATUS0);
|
||||
ctx->stat1 = sdmmc_read16(REG_SDSTATUS1);
|
||||
sdmmc_write16(REG_SDSTATUS0, 0);
|
||||
sdmmc_write16(REG_SDSTATUS1, 0);
|
||||
|
||||
if(getSDRESP != 0)
|
||||
{
|
||||
ctx->ret[0] = (u32)(sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16));
|
||||
ctx->ret[1] = (u32)(sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16));
|
||||
ctx->ret[2] = (u32)(sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16));
|
||||
ctx->ret[3] = (u32)(sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
int __attribute__((noinline)) sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in)
|
||||
{
|
||||
if(handleSD.isSDHC == 0) sector_no <<= 9;
|
||||
inittarget(&handleSD);
|
||||
sdmmc_write16(REG_SDSTOP, 0x100);
|
||||
sdmmc_write16(REG_SDBLKCOUNT32, numsectors);
|
||||
sdmmc_write16(REG_SDBLKLEN32, 0x200);
|
||||
sdmmc_write16(REG_SDBLKCOUNT, numsectors);
|
||||
handleSD.tData = in;
|
||||
handleSD.size = numsectors << 9;
|
||||
sdmmc_send_command(&handleSD, 0x52C19, sector_no);
|
||||
return geterror(&handleSD);
|
||||
}
|
||||
*/
|
||||
|
||||
int __attribute__((noinline)) sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out)
|
||||
{
|
||||
if(handleSD.isSDHC == 0) sector_no <<= 9;
|
||||
inittarget(&handleSD);
|
||||
sdmmc_write16(REG_SDSTOP, 0x100);
|
||||
sdmmc_write16(REG_SDBLKCOUNT32, numsectors);
|
||||
sdmmc_write16(REG_SDBLKLEN32, 0x200);
|
||||
sdmmc_write16(REG_SDBLKCOUNT, numsectors);
|
||||
handleSD.rData = out;
|
||||
handleSD.size = numsectors << 9;
|
||||
sdmmc_send_command(&handleSD, 0x33C12, sector_no);
|
||||
return geterror(&handleSD);
|
||||
}
|
||||
|
||||
/*
|
||||
int __attribute__((noinline)) sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out)
|
||||
{
|
||||
if(handleNAND.isSDHC == 0) sector_no <<= 9;
|
||||
inittarget(&handleNAND);
|
||||
sdmmc_write16(REG_SDSTOP, 0x100);
|
||||
sdmmc_write16(REG_SDBLKCOUNT32, numsectors);
|
||||
sdmmc_write16(REG_SDBLKLEN32, 0x200);
|
||||
sdmmc_write16(REG_SDBLKCOUNT, numsectors);
|
||||
handleNAND.rData = out;
|
||||
handleNAND.size = numsectors << 9;
|
||||
sdmmc_send_command(&handleNAND, 0x33C12, sector_no);
|
||||
inittarget(&handleSD);
|
||||
return geterror(&handleNAND);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
int __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in) //experimental
|
||||
{
|
||||
if(handleNAND.isSDHC == 0) sector_no <<= 9;
|
||||
inittarget(&handleNAND);
|
||||
sdmmc_write16(REG_SDSTOP, 0x100);
|
||||
sdmmc_write16(REG_SDBLKCOUNT32, numsectors);
|
||||
sdmmc_write16(REG_SDBLKLEN32, 0x200);
|
||||
sdmmc_write16(REG_SDBLKCOUNT, numsectors);
|
||||
handleNAND.tData = in;
|
||||
handleNAND.size = numsectors << 9;
|
||||
sdmmc_send_command(&handleNAND, 0x52C19, sector_no);
|
||||
inittarget(&handleSD);
|
||||
return geterror(&handleNAND);
|
||||
}
|
||||
*/
|
||||
|
||||
static u32 calcSDSize(u8 *csd, int type)
|
||||
{
|
||||
u32 result = 0;
|
||||
if(type == -1) type = csd[14] >> 6;
|
||||
switch(type)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
u32 block_len = csd[9] & 0xF;
|
||||
block_len = 1u << block_len;
|
||||
u32 mult = (u32)((csd[4] >> 7) | ((csd[5] & 3) << 1));
|
||||
mult = 1u << (mult + 2);
|
||||
result = csd[8] & 3;
|
||||
result = (result << 8) | csd[7];
|
||||
result = (result << 2) | (csd[6] >> 6);
|
||||
result = (result + 1) * mult * block_len / 512;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
result = csd[7] & 0x3F;
|
||||
result = (result << 8) | csd[6];
|
||||
result = (result << 8) | csd[5];
|
||||
result = (result + 1) * 1024;
|
||||
break;
|
||||
default:
|
||||
break; //Do nothing otherwise FIXME perhaps return some error?
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void InitSD()
|
||||
{
|
||||
*(vu16 *)0x10006100 &= 0xF7FFu; //SDDATACTL32
|
||||
*(vu16 *)0x10006100 &= 0xEFFFu; //SDDATACTL32
|
||||
*(vu16 *)0x10006100 |= 0x402u; //SDDATACTL32
|
||||
*(vu16 *)0x100060D8 = (*(vu16 *)0x100060D8 & 0xFFDD) | 2;
|
||||
*(vu16 *)0x10006100 &= 0xFFFFu; //SDDATACTL32
|
||||
*(vu16 *)0x100060D8 &= 0xFFDFu; //SDDATACTL
|
||||
*(vu16 *)0x10006104 = 512; //SDBLKLEN32
|
||||
*(vu16 *)0x10006108 = 1; //SDBLKCOUNT32
|
||||
*(vu16 *)0x100060E0 &= 0xFFFEu; //SDRESET
|
||||
*(vu16 *)0x100060E0 |= 1u; //SDRESET
|
||||
*(vu16 *)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0
|
||||
*(vu16 *)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1
|
||||
*(vu16 *)0x100060FC |= 0xDBu; //SDCTL_RESERVED7
|
||||
*(vu16 *)0x100060FE |= 0xDBu; //SDCTL_RESERVED8
|
||||
*(vu16 *)0x10006002 &= 0xFFFCu; //SDPORTSEL
|
||||
*(vu16 *)0x10006024 = 0x20;
|
||||
*(vu16 *)0x10006028 = 0x40EE;
|
||||
*(vu16 *)0x10006002 &= 0xFFFCu; ////SDPORTSEL
|
||||
*(vu16 *)0x10006026 = 512; //SDBLKLEN
|
||||
*(vu16 *)0x10006008 = 0; //SDSTOP
|
||||
}
|
||||
|
||||
/*
|
||||
static int Nand_Init()
|
||||
{
|
||||
//NAND
|
||||
handleNAND.isSDHC = 0;
|
||||
handleNAND.SDOPT = 0;
|
||||
handleNAND.res = 0;
|
||||
handleNAND.initarg = 1;
|
||||
handleNAND.clk = 0x80;
|
||||
handleNAND.devicenumber = 1;
|
||||
|
||||
inittarget(&handleNAND);
|
||||
waitcycles(0xF000);
|
||||
|
||||
sdmmc_send_command(&handleNAND, 0, 0);
|
||||
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
sdmmc_send_command(&handleNAND, 0x10701, 0x100000);
|
||||
}
|
||||
while(!(handleNAND.error & 1));
|
||||
}
|
||||
while((handleNAND.ret[0] & 0x80000000) == 0);
|
||||
|
||||
sdmmc_send_command(&handleNAND, 0x10602, 0x0);
|
||||
if((handleNAND.error & 0x4)) return -1;
|
||||
|
||||
sdmmc_send_command(&handleNAND, 0x10403, handleNAND.initarg << 0x10);
|
||||
if((handleNAND.error & 0x4)) return -1;
|
||||
|
||||
sdmmc_send_command(&handleNAND, 0x10609, handleNAND.initarg << 0x10);
|
||||
if((handleNAND.error & 0x4)) return -1;
|
||||
|
||||
handleNAND.total_size = calcSDSize((u8*)&handleNAND.ret[0], 0);
|
||||
handleNAND.clk = 1;
|
||||
setckl(1);
|
||||
|
||||
sdmmc_send_command(&handleNAND, 0x10407, handleNAND.initarg << 0x10);
|
||||
if((handleNAND.error & 0x4)) return -1;
|
||||
|
||||
handleNAND.SDOPT = 1;
|
||||
|
||||
sdmmc_send_command(&handleNAND, 0x10506, 0x3B70100);
|
||||
if((handleNAND.error & 0x4)) return -1;
|
||||
|
||||
sdmmc_send_command(&handleNAND, 0x10506, 0x3B90100);
|
||||
if((handleNAND.error & 0x4)) return -1;
|
||||
|
||||
sdmmc_send_command(&handleNAND, 0x1040D, handleNAND.initarg << 0x10);
|
||||
if((handleNAND.error & 0x4)) return -1;
|
||||
|
||||
sdmmc_send_command(&handleNAND, 0x10410, 0x200);
|
||||
if((handleNAND.error & 0x4)) return -1;
|
||||
|
||||
handleNAND.clk |= 0x200;
|
||||
|
||||
inittarget(&handleSD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
static int SD_Init()
|
||||
{
|
||||
//SD
|
||||
handleSD.isSDHC = 0;
|
||||
handleSD.SDOPT = 0;
|
||||
handleSD.res = 0;
|
||||
handleSD.initarg = 0;
|
||||
handleSD.clk = 0x80;
|
||||
handleSD.devicenumber = 0;
|
||||
|
||||
inittarget(&handleSD);
|
||||
|
||||
waitcycles(1u << 22); //Card needs a little bit of time to be detected, it seems FIXME test again to see what a good number is for the delay
|
||||
|
||||
//If not inserted
|
||||
if(!(*((vu16 *)(SDMMC_BASE + REG_SDSTATUS0)) & TMIO_STAT0_SIGSTATE)) return 5;
|
||||
|
||||
sdmmc_send_command(&handleSD, 0, 0);
|
||||
sdmmc_send_command(&handleSD, 0x10408, 0x1AA);
|
||||
u32 temp = (handleSD.error & 0x1) << 0x1E;
|
||||
|
||||
u32 temp2 = 0;
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
sdmmc_send_command(&handleSD, 0x10437, handleSD.initarg << 0x10);
|
||||
sdmmc_send_command(&handleSD, 0x10769, 0x00FF8000 | temp);
|
||||
temp2 = 1;
|
||||
}
|
||||
while(!(handleSD.error & 1));
|
||||
}
|
||||
while((handleSD.ret[0] & 0x80000000) == 0);
|
||||
|
||||
if(!((handleSD.ret[0] >> 30) & 1) || !temp)
|
||||
temp2 = 0;
|
||||
|
||||
handleSD.isSDHC = temp2;
|
||||
|
||||
sdmmc_send_command(&handleSD, 0x10602, 0);
|
||||
if((handleSD.error & 0x4)) return -1;
|
||||
|
||||
sdmmc_send_command(&handleSD, 0x10403, 0);
|
||||
if((handleSD.error & 0x4)) return -2;
|
||||
handleSD.initarg = handleSD.ret[0] >> 0x10;
|
||||
|
||||
sdmmc_send_command(&handleSD, 0x10609, handleSD.initarg << 0x10);
|
||||
if((handleSD.error & 0x4)) return -3;
|
||||
|
||||
handleSD.total_size = calcSDSize((u8*)&handleSD.ret[0], -1);
|
||||
handleSD.clk = 1;
|
||||
setckl(1);
|
||||
|
||||
sdmmc_send_command(&handleSD, 0x10507, handleSD.initarg << 0x10);
|
||||
if((handleSD.error & 0x4)) return -4;
|
||||
|
||||
sdmmc_send_command(&handleSD, 0x10437, handleSD.initarg << 0x10);
|
||||
if((handleSD.error & 0x4)) return -5;
|
||||
|
||||
handleSD.SDOPT = 1;
|
||||
sdmmc_send_command(&handleSD, 0x10446, 0x2);
|
||||
if((handleSD.error & 0x4)) return -6;
|
||||
|
||||
sdmmc_send_command(&handleSD, 0x1040D, handleSD.initarg << 0x10);
|
||||
if((handleSD.error & 0x4)) return -7;
|
||||
|
||||
sdmmc_send_command(&handleSD, 0x10410, 0x200);
|
||||
if((handleSD.error & 0x4)) return -8;
|
||||
handleSD.clk |= 0x200;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void sdmmc_get_cid(bool isNand, u32 *info)
|
||||
{
|
||||
struct mmcdevice *device = isNand ? &handleNAND : &handleSD;
|
||||
|
||||
inittarget(device);
|
||||
|
||||
// use cmd7 to put sd card in standby mode
|
||||
// CMD7
|
||||
sdmmc_send_command(device, 0x10507, 0);
|
||||
|
||||
// get sd card info
|
||||
// use cmd10 to read CID
|
||||
sdmmc_send_command(device, 0x1060A, device->initarg << 0x10);
|
||||
|
||||
for(int i = 0; i < 4; ++i)
|
||||
info[i] = device->ret[i];
|
||||
|
||||
// put sd card back to transfer mode
|
||||
// CMD7
|
||||
sdmmc_send_command(device, 0x10507, device->initarg << 0x10);
|
||||
}
|
||||
*/
|
||||
|
||||
bool sdmmc_sdcard_init()
|
||||
{
|
||||
InitSD();
|
||||
//Nand_Init();
|
||||
return SD_Init() == 0;
|
||||
}
|
||||
100
haxloader/source/fatfs/sdmmc/sdmmc.h
Normal file
100
haxloader/source/fatfs/sdmmc/sdmmc.h
Normal file
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../types.h"
|
||||
|
||||
#define SDMMC_BASE 0x10006000
|
||||
|
||||
#define REG_SDCMD 0x00
|
||||
#define REG_SDPORTSEL 0x02
|
||||
#define REG_SDCMDARG 0x04
|
||||
#define REG_SDCMDARG0 0x04
|
||||
#define REG_SDCMDARG1 0x06
|
||||
#define REG_SDSTOP 0x08
|
||||
#define REG_SDBLKCOUNT 0x0A
|
||||
|
||||
#define REG_SDRESP0 0x0C
|
||||
#define REG_SDRESP1 0x0E
|
||||
#define REG_SDRESP2 0x10
|
||||
#define REG_SDRESP3 0x12
|
||||
#define REG_SDRESP4 0x14
|
||||
#define REG_SDRESP5 0x16
|
||||
#define REG_SDRESP6 0x18
|
||||
#define REG_SDRESP7 0x1A
|
||||
|
||||
#define REG_SDSTATUS0 0x1C
|
||||
#define REG_SDSTATUS1 0x1E
|
||||
|
||||
#define REG_SDIRMASK0 0x20
|
||||
#define REG_SDIRMASK1 0x22
|
||||
#define REG_SDCLKCTL 0x24
|
||||
|
||||
#define REG_SDBLKLEN 0x26
|
||||
#define REG_SDOPT 0x28
|
||||
#define REG_SDFIFO 0x30
|
||||
|
||||
#define REG_DATACTL 0xD8
|
||||
#define REG_SDRESET 0xE0
|
||||
#define REG_SDPROTECTED 0xF6 //bit 0 determines if sd is protected or not?
|
||||
|
||||
#define REG_DATACTL32 0x100
|
||||
#define REG_SDBLKLEN32 0x104
|
||||
#define REG_SDBLKCOUNT32 0x108
|
||||
#define REG_SDFIFO32 0x10C
|
||||
|
||||
#define REG_CLK_AND_WAIT_CTL 0x138
|
||||
#define REG_RESET_SDIO 0x1E0
|
||||
|
||||
#define TMIO_STAT0_CMDRESPEND 0x0001
|
||||
#define TMIO_STAT0_DATAEND 0x0004
|
||||
#define TMIO_STAT0_CARD_REMOVE 0x0008
|
||||
#define TMIO_STAT0_CARD_INSERT 0x0010
|
||||
#define TMIO_STAT0_SIGSTATE 0x0020
|
||||
#define TMIO_STAT0_WRPROTECT 0x0080
|
||||
#define TMIO_STAT0_CARD_REMOVE_A 0x0100
|
||||
#define TMIO_STAT0_CARD_INSERT_A 0x0200
|
||||
#define TMIO_STAT0_SIGSTATE_A 0x0400
|
||||
#define TMIO_STAT1_CMD_IDX_ERR 0x0001
|
||||
#define TMIO_STAT1_CRCFAIL 0x0002
|
||||
#define TMIO_STAT1_STOPBIT_ERR 0x0004
|
||||
#define TMIO_STAT1_DATATIMEOUT 0x0008
|
||||
#define TMIO_STAT1_RXOVERFLOW 0x0010
|
||||
#define TMIO_STAT1_TXUNDERRUN 0x0020
|
||||
#define TMIO_STAT1_CMDTIMEOUT 0x0040
|
||||
#define TMIO_STAT1_RXRDY 0x0100
|
||||
#define TMIO_STAT1_TXRQ 0x0200
|
||||
#define TMIO_STAT1_ILL_FUNC 0x2000
|
||||
#define TMIO_STAT1_CMD_BUSY 0x4000
|
||||
#define TMIO_STAT1_ILL_ACCESS 0x8000
|
||||
|
||||
#define TMIO_MASK_ALL 0x837F031D
|
||||
|
||||
#define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \
|
||||
TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)
|
||||
|
||||
#define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND)
|
||||
#define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND)
|
||||
|
||||
typedef struct mmcdevice {
|
||||
u8 *rData;
|
||||
const u8 *tData;
|
||||
u32 size;
|
||||
u32 error;
|
||||
u16 stat0;
|
||||
u16 stat1;
|
||||
u32 ret[4];
|
||||
u32 initarg;
|
||||
u32 isSDHC;
|
||||
u32 clk;
|
||||
u32 SDOPT;
|
||||
u32 devicenumber;
|
||||
u32 total_size; //size in sectors of the device
|
||||
u32 res;
|
||||
} mmcdevice;
|
||||
|
||||
bool sdmmc_sdcard_init();
|
||||
int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out);
|
||||
//int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in);
|
||||
//int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out);
|
||||
//int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in);
|
||||
//void sdmmc_get_cid(bool isNand, u32 *info);
|
||||
//mmcdevice *getMMCDevice(int drive);
|
||||
139
haxloader/source/i2c.c
Normal file
139
haxloader/source/i2c.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Thanks to the everyone who 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),
|
||||
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;
|
||||
}
|
||||
44
haxloader/source/i2c.h
Normal file
44
haxloader/source/i2c.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Thanks to the everyone who 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);
|
||||
92
haxloader/source/main.c
Normal file
92
haxloader/source/main.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
#include "cache.h"
|
||||
#include "i2c.h"
|
||||
#include "types.h"
|
||||
#include "fatfs/ff.h"
|
||||
#include "../../build/bundled.h"
|
||||
|
||||
static FATFS fs;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
if(f_mount(&fs, "0:", 0) == FR_OK)
|
||||
{
|
||||
FIL pathFile,
|
||||
payload;
|
||||
bool foundPayload = false;
|
||||
|
||||
if(f_open(&pathFile, "luma/path.txt", FA_READ) == FR_OK)
|
||||
{
|
||||
u32 pathSize = f_size(&pathFile);
|
||||
|
||||
if(pathSize > 5 && pathSize < 58)
|
||||
{
|
||||
char path[57];
|
||||
unsigned int read;
|
||||
f_read(&pathFile, path, pathSize, &read);
|
||||
if(path[pathSize - 1] == 0xA) pathSize--;
|
||||
if(path[pathSize - 1] == 0xD) pathSize--;
|
||||
|
||||
if(pathSize > 5 && pathSize < 56 && path[0] == '/' && memcmp(path + pathSize - 4, ".bin", 4) == 0)
|
||||
{
|
||||
path[pathSize] = 0;
|
||||
foundPayload = f_open(&payload, path, FA_READ) == FR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
f_close(&pathFile);
|
||||
}
|
||||
|
||||
if(!foundPayload) foundPayload = f_open(&payload, "arm9loaderhax.bin", FA_READ) == FR_OK;
|
||||
|
||||
if(foundPayload)
|
||||
{
|
||||
u32 *loaderAddress = (u32 *)0x24FFFE00;
|
||||
void *payloadAddress = (void *)0x24F00000;
|
||||
u32 payloadSize = f_size(&payload);
|
||||
|
||||
memcpy(loaderAddress, loader_bin, loader_bin_size);
|
||||
loaderAddress[1] = payloadSize;
|
||||
|
||||
unsigned int read;
|
||||
f_read(&payload, payloadAddress, payloadSize, &read);
|
||||
f_close(&payload);
|
||||
|
||||
if((u32)read == payloadSize)
|
||||
{
|
||||
flushDCacheRange(loaderAddress, loader_bin_size);
|
||||
flushICacheRange(loaderAddress, loader_bin_size);
|
||||
|
||||
((void (*)())loaderAddress)();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||
flushEntireDCache();
|
||||
|
||||
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0);
|
||||
while(true);
|
||||
}
|
||||
50
haxloader/source/memory.c
Normal file
50
haxloader/source/memory.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* memcpy 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];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
32
haxloader/source/memory.h
Normal file
32
haxloader/source/memory.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* memcpy and memcmp 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);
|
||||
int memcmp(const void *buf1, const void *buf2, u32 size);
|
||||
87
haxloader/source/start.s
Normal file
87
haxloader/source/start.s
Normal file
@@ -0,0 +1,87 @@
|
||||
@ 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.
|
||||
|
||||
@ Thanks to the numerous people who took part in writing this file
|
||||
|
||||
.section .text.start
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
@ Disable interrupts
|
||||
mrs r0, cpsr
|
||||
orr r0, #0x1C0
|
||||
msr cpsr_cx, r0
|
||||
|
||||
@ Change the stack pointer
|
||||
mov sp, #0x27000000
|
||||
|
||||
@ 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
|
||||
|
||||
@ Flush caches
|
||||
bl flushEntireDCache
|
||||
bl flushEntireICache
|
||||
|
||||
@ Give read/write access to all the memory regions
|
||||
ldr r0, =0x3333333
|
||||
mcr p15, 0, r0, c5, c0, 2 @ write data access
|
||||
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
|
||||
|
||||
@ Set MPU permissions and cache settings
|
||||
ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part)
|
||||
ldr r1, =0x01FF801D @ 01ff8000 32k | itcm
|
||||
ldr r2, =0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS)
|
||||
ldr r3, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB)
|
||||
ldr r4, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS)
|
||||
ldr r5, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram
|
||||
ldr r6, =0x1800002D @ 18000000 8M | vram (+ 2MB)
|
||||
mov r7, #0
|
||||
mov r8, #0x15
|
||||
mcr p15, 0, r0, c6, c0, 0
|
||||
mcr p15, 0, r1, c6, c1, 0
|
||||
mcr p15, 0, r2, c6, c2, 0
|
||||
mcr p15, 0, r3, c6, c3, 0
|
||||
mcr p15, 0, r4, c6, c4, 0
|
||||
mcr p15, 0, r5, c6, c5, 0
|
||||
mcr p15, 0, r6, c6, c6, 0
|
||||
mcr p15, 0, r7, c6, c7, 0
|
||||
mcr p15, 0, r8, c3, c0, 0 @ Write bufferable 0, 2, 4
|
||||
mcr p15, 0, r8, c2, c0, 0 @ Data cacheable 0, 2, 4
|
||||
mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 2, 4
|
||||
|
||||
@ Enable caches / MPU / ITCM
|
||||
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
||||
orr r0, r0, #(1<<18) @ - ITCM enable
|
||||
orr r0, r0, #(1<<13) @ - alternate exception vectors enable
|
||||
orr r0, r0, #(1<<12) @ - instruction cache enable
|
||||
orr r0, r0, #(1<<2) @ - data cache enable
|
||||
orr r0, r0, #(1<<0) @ - mpu enable
|
||||
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
||||
|
||||
@ Fix mounting of SDMC
|
||||
ldr r0, =0x10000020
|
||||
mov r1, #0x340
|
||||
str r1, [r0]
|
||||
|
||||
b main
|
||||
37
haxloader/source/types.h
Normal file
37
haxloader/source/types.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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;
|
||||
192
injector/Makefile
Normal file → Executable file
192
injector/Makefile
Normal file → Executable file
@@ -1,161 +1,73 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
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
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
MAKEROM ?= makerom
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
name := $(shell basename $(CURDIR))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
|
||||
dir_source := source
|
||||
dir_patches := patches
|
||||
dir_build := build
|
||||
dir_out := ../$(dir_build)
|
||||
|
||||
CFLAGS := -flto -Wall -O2 -mword-relocations \
|
||||
-ffast-math -ffunction-sections -fdata-sections \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu99
|
||||
|
||||
ASFLAGS := $(ARCH)
|
||||
LDFLAGS = -flto -Xlinker --defsym="__start__=0x14000000" -specs=3dsx.specs $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := -lctru
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lctru
|
||||
LIBDIRS := $(CTRULIB)
|
||||
LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
INCLUDE := $(foreach dir,$(LIBDIRS),-I$(dir)/include)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
ASFLAGS := -mcpu=mpcore -mfloat-abi=hard
|
||||
CFLAGS := -Wall -Wextra $(ASFLAGS) -fno-builtin -std=c11 -O2 -flto -ffast-math $(INCLUDE) -DARM11 -D_3DS
|
||||
LDFLAGS := -specs=3dsx.specs $(ASFLAGS) -Wl,--section-start,.text=0x14000000
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
objects = $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c))
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
bundled = $(dir_build)/romfsredir.bin.o
|
||||
|
||||
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)))
|
||||
PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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 := $(addsuffix .o,$(BINFILES)) \
|
||||
$(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
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) $(OUTPUT).cxi $(TARGET).elf
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT).cxi : $(OUTPUT).elf
|
||||
$(MAKEROM) -f ncch -rsf ../loader.rsf -nocodepadding -o $@ -elf $<
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
bin2s $(CURBIN) | $(AS) -o $@
|
||||
echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h
|
||||
echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h
|
||||
echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h
|
||||
define bin2o
|
||||
bin2s $< | $(AS) -o $(@)
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
.PHONY: all
|
||||
all: $(dir_out)/$(name).bin
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@rm -rf $(dir_build)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
.PRECIOUS: $(dir_build)/%.bin
|
||||
|
||||
-include $(DEPENDS)
|
||||
$(dir_build):
|
||||
@mkdir -p "$@"
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
$(dir_out)/$(name).bin: $(dir_build)/$(name).elf
|
||||
@makerom -f ncch -rsf loader.rsf -nocodepadding -o $@ -elf $<
|
||||
|
||||
$(dir_build)/$(name).elf: $(bundled) $(objects)
|
||||
$(LINK.o) $(OUTPUT_OPTION) $^ $(LIBPATHS) $(LIBS)
|
||||
|
||||
$(dir_build)/%.bin.o: $(dir_build)/%.bin
|
||||
@$(bin2o)
|
||||
|
||||
$(dir_build)/%.bin: $(dir_patches)/%.s $(dir_build)
|
||||
@armips $<
|
||||
|
||||
$(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3
|
||||
|
||||
$(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) $<
|
||||
|
||||
99
injector/patches/romfsredir.s
Normal file
99
injector/patches/romfsredir.s
Normal file
@@ -0,0 +1,99 @@
|
||||
.arm.little
|
||||
.create "build/romfsredir.bin", 0
|
||||
|
||||
.macro addr, reg, func
|
||||
add reg, pc, #func-.-8
|
||||
.endmacro
|
||||
.macro load, reg, func
|
||||
ldr reg, [pc, #func-.-8]
|
||||
.endmacro
|
||||
|
||||
; Patch by delebile
|
||||
|
||||
.arm
|
||||
_start:
|
||||
|
||||
; Jumps here before the fsOpenFileDirectly call
|
||||
_mountArchive:
|
||||
b mountArchive
|
||||
.word 0xdead0000 ; Substituted opcode
|
||||
.word 0xdead0001 ; Branch to hooked function
|
||||
|
||||
; Jumps here before every iFileOpen call
|
||||
_fsRedir:
|
||||
b fsRedir
|
||||
.word 0xdead0002 ; Substituted opcode
|
||||
.word 0xdead0003 ; Branch to hooked function
|
||||
|
||||
; Mounts the archive and registers it as 'lf:'
|
||||
mountArchive:
|
||||
cmp r3, #3
|
||||
bne _mountArchive + 4
|
||||
stmfd sp!, {r0-r4, lr}
|
||||
sub sp, sp, #4
|
||||
load r1, archiveId
|
||||
mov r0, sp
|
||||
load r4, fsMountArchive
|
||||
blx r4
|
||||
mov r3, #0
|
||||
mov r2, #0
|
||||
ldr r1, [sp]
|
||||
addr r0, archiveName
|
||||
load r4, fsRegisterArchive
|
||||
blx r4
|
||||
add sp, sp, #4
|
||||
ldmfd sp!, {r0-r4, lr}
|
||||
b _mountArchive + 4
|
||||
|
||||
; Check the path passed to iFileOpen.
|
||||
; If it is trying to access a RomFS file, we try to
|
||||
; open it from the LayeredFS folder.
|
||||
; If the file cannot be opened, we just open
|
||||
; it from its original archive like nothing happened
|
||||
fsRedir:
|
||||
stmfd sp!, {r0-r12, lr}
|
||||
ldrb r12, [r1]
|
||||
cmp r12, #0x72 ; 'r', should include "rom:" and "rom2:"
|
||||
cmpne r12, #0x70 ; 'p', should include "patch:"
|
||||
bne endRedir
|
||||
sub sp, sp, #0x400
|
||||
pathRedir:
|
||||
stmfd sp!, {r0-r3}
|
||||
add r0, sp, #0x10
|
||||
addr r3, customPath
|
||||
pathRedir_1:
|
||||
ldrb r2, [r3], #1
|
||||
strh r2, [r0], #2
|
||||
cmp r2, #0
|
||||
bne pathRedir_1
|
||||
sub r0, r0, #2
|
||||
pathRedir_2:
|
||||
ldrh r2, [r1], #2
|
||||
cmp r2, #0x3A ; ':'
|
||||
bne pathRedir_2
|
||||
pathRedir_3:
|
||||
ldrh r2, [r1], #2
|
||||
strh r2, [r0], #2
|
||||
cmp r2, #0
|
||||
bne pathRedir_3
|
||||
ldmfd sp!, {r0-r3}
|
||||
mov r1, sp
|
||||
bl _fsRedir + 4
|
||||
add sp, sp, #0x400
|
||||
cmp r0, #0
|
||||
|
||||
endRedir:
|
||||
ldmfd sp!, {r0-r12, lr}
|
||||
moveq r0, #0
|
||||
bxeq lr
|
||||
b _fsRedir + 4
|
||||
|
||||
.pool
|
||||
.align 4
|
||||
archiveName : .dcb "lf:", 0
|
||||
fsMountArchive : .word 0xdead0005
|
||||
fsRegisterArchive : .word 0xdead0006
|
||||
archiveId : .word 0xdead0007
|
||||
customPath : .word 0xdead0004
|
||||
|
||||
.close
|
||||
19
injector/source/CFWInfo.h
Normal file
19
injector/source/CFWInfo.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <3ds/types.h>
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
char magic[4];
|
||||
|
||||
u8 versionMajor;
|
||||
u8 versionMinor;
|
||||
u8 versionBuild;
|
||||
u8 flags;
|
||||
|
||||
u32 commitHash;
|
||||
|
||||
u32 config;
|
||||
} CFWInfo;
|
||||
|
||||
u32 svcGetCFWInfo(CFWInfo *info);
|
||||
9
injector/source/CFWInfo.s
Normal file
9
injector/source/CFWInfo.s
Normal file
@@ -0,0 +1,9 @@
|
||||
.text
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
.global svcGetCFWInfo
|
||||
.type svcGetCFWInfo, %function
|
||||
svcGetCFWInfo:
|
||||
svc 0x2e
|
||||
bx lr
|
||||
@@ -82,23 +82,23 @@ Result FSLDR_SetPriority(u32 priority)
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FSLDR_OpenFileDirectly(Handle* out, FS_Archive archive, FS_Path path, u32 openFlags, u32 attributes)
|
||||
Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes)
|
||||
{
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x803,8,4); // 0x8030204
|
||||
cmdbuf[1] = 0;
|
||||
cmdbuf[2] = archive.id;
|
||||
cmdbuf[3] = archive.lowPath.type;
|
||||
cmdbuf[4] = archive.lowPath.size;
|
||||
cmdbuf[5] = path.type;
|
||||
cmdbuf[6] = path.size;
|
||||
cmdbuf[2] = archiveId;
|
||||
cmdbuf[3] = archivePath.type;
|
||||
cmdbuf[4] = archivePath.size;
|
||||
cmdbuf[5] = filePath.type;
|
||||
cmdbuf[6] = filePath.size;
|
||||
cmdbuf[7] = openFlags;
|
||||
cmdbuf[8] = attributes;
|
||||
cmdbuf[9] = IPC_Desc_StaticBuffer(archive.lowPath.size, 2);
|
||||
cmdbuf[10] = (u32) archive.lowPath.data;
|
||||
cmdbuf[11] = IPC_Desc_StaticBuffer(path.size, 0);
|
||||
cmdbuf[12] = (u32) path.data;
|
||||
cmdbuf[9] = IPC_Desc_StaticBuffer(archivePath.size, 2);
|
||||
cmdbuf[10] = (u32)archivePath.data;
|
||||
cmdbuf[11] = IPC_Desc_StaticBuffer(filePath.size, 0);
|
||||
cmdbuf[12] = (u32)filePath.data;
|
||||
|
||||
Result ret = 0;
|
||||
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
|
||||
@@ -107,3 +107,75 @@ Result FSLDR_OpenFileDirectly(Handle* out, FS_Archive archive, FS_Path path, u32
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FSLDR_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path)
|
||||
{
|
||||
if(!archive) return -2;
|
||||
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x80C,3,2); // 0x80C00C2
|
||||
cmdbuf[1] = id;
|
||||
cmdbuf[2] = path.type;
|
||||
cmdbuf[3] = path.size;
|
||||
cmdbuf[4] = IPC_Desc_StaticBuffer(path.size, 0);
|
||||
cmdbuf[5] = (u32) path.data;
|
||||
|
||||
Result ret = 0;
|
||||
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
|
||||
|
||||
if(archive) *archive = cmdbuf[2] | ((u64) cmdbuf[3] << 32);
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FSLDR_CloseArchive(FS_Archive archive)
|
||||
{
|
||||
if(!archive) return -2;
|
||||
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x80E,2,0); // 0x80E0080
|
||||
cmdbuf[1] = (u32) archive;
|
||||
cmdbuf[2] = (u32) (archive >> 32);
|
||||
|
||||
Result ret = 0;
|
||||
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path)
|
||||
{
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x80B,4,2); // 0x80B0102
|
||||
cmdbuf[1] = (u32) archive;
|
||||
cmdbuf[2] = (u32) (archive >> 32);
|
||||
cmdbuf[3] = path.type;
|
||||
cmdbuf[4] = path.size;
|
||||
cmdbuf[5] = IPC_Desc_StaticBuffer(path.size, 0);
|
||||
cmdbuf[6] = (u32) path.data;
|
||||
|
||||
Result ret = 0;
|
||||
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
|
||||
|
||||
if(out) *out = cmdbuf[3];
|
||||
|
||||
return cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FSDIRLDR_Close(Handle handle)
|
||||
{
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x802,0,0); // 0x8020000
|
||||
|
||||
Result ret = 0;
|
||||
if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
|
||||
|
||||
ret = cmdbuf[1];
|
||||
if(R_SUCCEEDED(ret)) ret = svcCloseHandle(handle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -6,4 +6,8 @@ Result fsldrInit(void);
|
||||
void fsldrExit(void);
|
||||
Result FSLDR_InitializeWithSdkVersion(Handle session, u32 version);
|
||||
Result FSLDR_SetPriority(u32 priority);
|
||||
Result FSLDR_OpenFileDirectly(Handle* out, FS_Archive archive, FS_Path path, u32 openFlags, u32 attributes);
|
||||
Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes);
|
||||
Result FSLDR_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path);
|
||||
Result FSLDR_CloseArchive(FS_Archive archive);
|
||||
Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path);
|
||||
Result FSDIRLDR_Close(Handle handle);
|
||||
@@ -2,11 +2,11 @@
|
||||
#include "ifile.h"
|
||||
#include "fsldr.h"
|
||||
|
||||
Result IFile_Open(IFile *file, FS_Archive archive, FS_Path path, u32 flags)
|
||||
Result IFile_Open(IFile *file, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 flags)
|
||||
{
|
||||
Result res;
|
||||
|
||||
res = FSLDR_OpenFileDirectly(&file->handle, archive, path, flags, 0);
|
||||
res = FSLDR_OpenFileDirectly(&file->handle, archiveId, archivePath, filePath, flags, 0);
|
||||
file->pos = 0;
|
||||
file->size = 0;
|
||||
return res;
|
||||
@@ -64,42 +64,3 @@ Result IFile_Read(IFile *file, u64 *total, void *buffer, u32 len)
|
||||
*total = cur;
|
||||
return res;
|
||||
}
|
||||
|
||||
Result IFile_Write(IFile *file, u64 *total, void *buffer, u32 len, u32 flags)
|
||||
{
|
||||
u32 written;
|
||||
u32 left;
|
||||
char *buf;
|
||||
u64 cur;
|
||||
Result res;
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
*total = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = (char *)buffer;
|
||||
cur = 0;
|
||||
left = len;
|
||||
while (1)
|
||||
{
|
||||
res = FSFILE_Write(file->handle, &written, file->pos, buf, left, flags);
|
||||
if (R_FAILED(res))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
cur += written;
|
||||
file->pos += written;
|
||||
if (written == left)
|
||||
{
|
||||
break;
|
||||
}
|
||||
buf += written;
|
||||
left -= written;
|
||||
}
|
||||
|
||||
*total = cur;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -9,8 +9,7 @@ typedef struct
|
||||
u64 size;
|
||||
} IFile;
|
||||
|
||||
Result IFile_Open(IFile *file, FS_Archive archive, FS_Path path, u32 flags);
|
||||
Result IFile_Open(IFile *file, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 flags);
|
||||
Result IFile_Close(IFile *file);
|
||||
Result IFile_GetSize(IFile *file, u64 *size);
|
||||
Result IFile_Read(IFile *file, u64 *total, void *buffer, u32 len);
|
||||
Result IFile_Write(IFile *file, u64 *total, void *buffer, u32 len, u32 flags);
|
||||
Result IFile_Read(IFile *file, u64 *total, void *buffer, u32 len);
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <3ds.h>
|
||||
#include <string.h>
|
||||
#include <sys/iosupport.h>
|
||||
#include "memory.h"
|
||||
#include "patcher.h"
|
||||
#include "exheader.h"
|
||||
#include "ifile.h"
|
||||
@@ -110,21 +109,20 @@ static Result allocate_shared_mem(prog_addrs_t *shared, prog_addrs_t *vaddr, int
|
||||
static Result load_code(u64 progid, prog_addrs_t *shared, u64 prog_handle, int is_compressed)
|
||||
{
|
||||
IFile file;
|
||||
FS_Archive archive;
|
||||
FS_Path path;
|
||||
FS_Path archivePath;
|
||||
FS_Path filePath;
|
||||
Result res;
|
||||
u64 size;
|
||||
u64 total;
|
||||
|
||||
archive.id = ARCHIVE_SAVEDATA_AND_CONTENT2;
|
||||
archive.lowPath.type = PATH_BINARY;
|
||||
archive.lowPath.data = &prog_handle;
|
||||
archive.lowPath.size = 8;
|
||||
//archive.handle = prog_handle; // not needed
|
||||
path.type = PATH_BINARY;
|
||||
path.data = CODE_PATH;
|
||||
path.size = sizeof(CODE_PATH);
|
||||
if (R_FAILED(IFile_Open(&file, archive, path, FS_OPEN_READ)))
|
||||
archivePath.type = PATH_BINARY;
|
||||
archivePath.data = &prog_handle;
|
||||
archivePath.size = 8;
|
||||
|
||||
filePath.type = PATH_BINARY;
|
||||
filePath.data = CODE_PATH;
|
||||
filePath.size = sizeof(CODE_PATH);
|
||||
if (R_FAILED(IFile_Open(&file, ARCHIVE_SAVEDATA_AND_CONTENT2, archivePath, filePath, FS_OPEN_READ)))
|
||||
{
|
||||
svcBreak(USERBREAK_ASSERT);
|
||||
}
|
||||
@@ -157,8 +155,10 @@ static Result load_code(u64 progid, prog_addrs_t *shared, u64 prog_handle, int i
|
||||
lzss_decompress((u8 *)shared->text_addr + size);
|
||||
}
|
||||
|
||||
u16 progver = g_exheader.codesetinfo.flags.remasterversion[0] | (g_exheader.codesetinfo.flags.remasterversion[1] << 8);
|
||||
|
||||
// patch
|
||||
patchCode(progid, (u8 *)shared->text_addr, shared->total_size << 12);
|
||||
patchCode(progid, progver, (u8 *)shared->text_addr, shared->total_size << 12, g_exheader.codesetinfo.text.codesize, g_exheader.codesetinfo.ro.codesize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -462,14 +462,14 @@ void __sync_init();
|
||||
void __sync_fini();
|
||||
void __system_initSyscalls();
|
||||
|
||||
void __ctru_exit(int rc)
|
||||
void __ctru_exit()
|
||||
{
|
||||
__appExit();
|
||||
__sync_fini();
|
||||
svcExitProcess();
|
||||
}
|
||||
|
||||
void initSystem(void (*retAddr)(void))
|
||||
void initSystem()
|
||||
{
|
||||
__sync_init();
|
||||
__system_initSyscalls();
|
||||
@@ -521,7 +521,7 @@ int main()
|
||||
if (R_FAILED(ret))
|
||||
{
|
||||
// check if any handle has been closed
|
||||
if (ret == 0xC920181A)
|
||||
if (ret == (int)0xC920181A)
|
||||
{
|
||||
if (index == -1)
|
||||
{
|
||||
|
||||
49
injector/source/memory.c
Normal file
49
injector/source/memory.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#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];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//Boyer-Moore Horspool algorithm, adapted from http://www-igm.univ-mlv.fr/~lecroq/string/node18.html#SECTION00180
|
||||
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize)
|
||||
{
|
||||
const u8 *patternc = (const u8 *)pattern;
|
||||
u32 table[256];
|
||||
|
||||
//Preprocessing
|
||||
for(u32 i = 0; i < 256; i++)
|
||||
table[i] = patternSize;
|
||||
for(u32 i = 0; i < patternSize - 1; i++)
|
||||
table[patternc[i]] = patternSize - i - 1;
|
||||
|
||||
//Searching
|
||||
u32 j = 0;
|
||||
while(j <= size - patternSize)
|
||||
{
|
||||
u8 c = startPos[j + patternSize - 1];
|
||||
if(patternc[patternSize - 1] == c && memcmp(pattern, startPos + j, patternSize - 1) == 0)
|
||||
return startPos + j;
|
||||
j += table[c];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
7
injector/source/memory.h
Normal file
7
injector/source/memory.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <3ds/types.h>
|
||||
|
||||
void memcpy(void *dest, const void *src, u32 size);
|
||||
int memcmp(const void *buf1, const void *buf2, u32 size);
|
||||
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,4 +2,46 @@
|
||||
|
||||
#include <3ds/types.h>
|
||||
|
||||
void patchCode(u64 progId, u8 *code, u32 size);
|
||||
#define MAKE_BRANCH(src,dst) (0xEA000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
|
||||
#define MAKE_BRANCH_LINK(src,dst) (0xEB000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
|
||||
|
||||
#define CONFIG(a) (((info.config >> (a + 20)) & 1) != 0)
|
||||
#define MULTICONFIG(a) ((info.config >> (a * 2 + 8)) & 3)
|
||||
#define BOOTCONFIG(a, b) ((info.config >> a) & b)
|
||||
#define LOADERFLAG(a) ((info.flags >> (a + 4)) & 1) != 0
|
||||
|
||||
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
|
||||
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
|
||||
#define BOOTCFG_A9LH BOOTCONFIG(6, 1)
|
||||
#define BOOTCFG_NOFORCEFLAG BOOTCONFIG(7, 1)
|
||||
|
||||
enum multiOptions
|
||||
{
|
||||
DEFAULTEMU = 0,
|
||||
BRIGHTNESS,
|
||||
SPLASH,
|
||||
PIN,
|
||||
NEWCPU
|
||||
};
|
||||
|
||||
enum singleOptions
|
||||
{
|
||||
AUTOBOOTSYS = 0,
|
||||
USESYSFIRM,
|
||||
LOADEXTFIRMSANDMODULES,
|
||||
USECUSTOMPATH,
|
||||
PATCHGAMES,
|
||||
PATCHVERSTRING,
|
||||
SHOWGBABOOT,
|
||||
PATCHACCESS,
|
||||
PATCHUNITINFO,
|
||||
ENABLEEXCEPTIONHANDLERS
|
||||
};
|
||||
|
||||
enum flags
|
||||
{
|
||||
ISN3DS = 0,
|
||||
ISSAFEMODE
|
||||
};
|
||||
|
||||
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize);
|
||||
|
||||
20
injector/source/strings.c
Normal file
20
injector/source/strings.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "strings.h"
|
||||
|
||||
size_t strnlen(const char *string, size_t maxlen)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
for(size = 0; *string && size < maxlen; string++, size++);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void progIdToStr(char *strEnd, u64 progId)
|
||||
{
|
||||
while(progId > 0)
|
||||
{
|
||||
static const char hexDigits[] = "0123456789ABCDEF";
|
||||
*strEnd-- = hexDigits[(u32)(progId & 0xF)];
|
||||
progId >>= 4;
|
||||
}
|
||||
}
|
||||
6
injector/source/strings.h
Normal file
6
injector/source/strings.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <3ds/types.h>
|
||||
|
||||
size_t strnlen(const char *string, size_t maxlen);
|
||||
void progIdToStr(char *strEnd, u64 progId);
|
||||
14
linker.ld
14
linker.ld
@@ -1,11 +1,15 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x23F00000;
|
||||
.text.start : { *(.text.start) }
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) }
|
||||
.bss : { *(.bss COMMON) }
|
||||
.rodata : { *(.rodata) }
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(4); }
|
||||
.bss : ALIGN(8) { __bss_start = .; *(.bss* COMMON); . = ALIGN(8); __bss_end = .; }
|
||||
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
||||
@@ -4,38 +4,36 @@ ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
CC := arm-none-eabi-gcc
|
||||
AS := arm-none-eabi-as
|
||||
LD := arm-none-eabi-ld
|
||||
OC := arm-none-eabi-objcopy
|
||||
include $(DEVKITARM)/base_tools
|
||||
|
||||
name := $(shell basename $(CURDIR))
|
||||
|
||||
dir_source := source
|
||||
dir_build := build
|
||||
dir_out := ../$(dir_build)
|
||||
|
||||
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math -mthumb -mthumb-interwork
|
||||
LDFLAGS := -nostartfiles
|
||||
ASFLAGS := -mcpu=arm946e-s
|
||||
CFLAGS := -Wall -Wextra -mthumb $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||
LDFLAGS := -nostdlib
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
|
||||
.PHONY: all
|
||||
all: $(name).bin
|
||||
all: $(dir_out)/$(name).bin
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@rm -rf $(dir_build)
|
||||
|
||||
$(name).bin: $(dir_build)/$(name).elf
|
||||
$(OC) -S -O binary $< $@
|
||||
$(dir_out)/$(name).bin: $(dir_build)/$(name).elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
$(dir_build)/$(name).elf: $(objects)
|
||||
$(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
||||
$(dir_build)/memory.o: CFLAGS += -O3
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
@@ -44,12 +42,3 @@ $(dir_build)/%.o: $(dir_source)/%.c
|
||||
$(dir_build)/%.o: $(dir_source)/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||
include $(call rwildcard, $(dir_build), *.d)
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x24F00000;
|
||||
.text.start : { *(.text.start) }
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) }
|
||||
.bss : { *(.bss COMMON) }
|
||||
.rodata : { *(.rodata) }
|
||||
. = 0x24FFFE00;
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
|
||||
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define HID_PAD (*(vu32 *)0x10146000 ^ 0xFFF)
|
||||
#define BUTTON_X (1 << 10)
|
||||
#define BUTTON_Y (1 << 11)
|
||||
#define BUTTON_R1 (1 << 8)
|
||||
#define BUTTON_SELECT (1 << 2)
|
||||
#define BUTTON_RIGHT (1 << 4)
|
||||
#define BUTTON_LEFT (1 << 5)
|
||||
#define BUTTON_UP (1 << 6)
|
||||
#define BUTTON_DOWN (1 << 7)
|
||||
27
loader/source/cache.h
Normal file
27
loader/source/cache.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
void flushCaches(void);
|
||||
56
loader/source/cache.s
Normal file
56
loader/source/cache.s
Normal file
@@ -0,0 +1,56 @@
|
||||
@ 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.
|
||||
|
||||
.text
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
.global flushCaches
|
||||
.type flushCaches, %function
|
||||
flushCaches:
|
||||
@ Clean and flush both the data cache and instruction caches
|
||||
|
||||
@ Adpated from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html ,
|
||||
@ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well
|
||||
@ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has)
|
||||
|
||||
@ Implemented in bootROM at addresses 0xffff0830 (DCache) and 0xffff0ab4 (ICache)
|
||||
|
||||
mov r1, #0 @ segment counter
|
||||
outer_loop:
|
||||
mov r0, #0 @ line counter
|
||||
|
||||
inner_loop:
|
||||
orr r2, r1, r0 @ generate segment and line address
|
||||
mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line
|
||||
add r0, #0x20 @ increment to next line
|
||||
cmp r0, #0x400
|
||||
bne inner_loop
|
||||
|
||||
add r1, #0x40000000
|
||||
cmp r1, #0
|
||||
bne outer_loop
|
||||
|
||||
mcr p15, 0, r1, c7, c10, 4 @ drain write buffer
|
||||
|
||||
@ Flush instruction cache
|
||||
mcr p15, 0, r1, c7, c5, 0
|
||||
|
||||
bx lr
|
||||
@@ -1,21 +0,0 @@
|
||||
FatFs Module Source Files R0.11
|
||||
|
||||
|
||||
FILES
|
||||
|
||||
00readme.txt This file.
|
||||
history.txt Revision history.
|
||||
ffconf.h Configuration file for FatFs module.
|
||||
ff.h Common include file for FatFs and application module.
|
||||
ff.c FatFs 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.
|
||||
option Optional external functions.
|
||||
|
||||
|
||||
Low level disk I/O module is not included in this archive because the FatFs
|
||||
module is only a generic file system layer and not depend on any specific
|
||||
storage device. You have to provide a low level disk I/O module that written
|
||||
to control the target storage device.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "../../types.h"
|
||||
@@ -1,9 +0,0 @@
|
||||
// Copyright 2014 Normmatt
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
void ioDelay(u32 us);
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright 2014 Normmatt
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
.arm
|
||||
.global ioDelay
|
||||
.type ioDelay STT_FUNC
|
||||
|
||||
@ioDelay ( u32 us )
|
||||
ioDelay:
|
||||
ldr r1, =0x18000000 @ VRAM
|
||||
1:
|
||||
@ Loop doing uncached reads from VRAM to make loop timing more reliable
|
||||
ldr r2, [r1]
|
||||
subs r0, #1
|
||||
bgt 1b
|
||||
bx lr
|
||||
@@ -1,404 +0,0 @@
|
||||
// Copyright 2014 Normmatt
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "sdmmc.h"
|
||||
#include "delay.h"
|
||||
|
||||
struct mmcdevice handleNAND;
|
||||
struct mmcdevice handleSD;
|
||||
|
||||
static inline u16 sdmmc_read16(u16 reg) {
|
||||
return *(vu16*)(SDMMC_BASE + reg);
|
||||
}
|
||||
|
||||
static inline void sdmmc_write16(u16 reg, u16 val) {
|
||||
*(vu16*)(SDMMC_BASE + reg) = val;
|
||||
}
|
||||
|
||||
static inline u32 sdmmc_read32(u16 reg) {
|
||||
return *(vu32*)(SDMMC_BASE + reg);
|
||||
}
|
||||
|
||||
static inline void sdmmc_write32(u16 reg, u32 val) {
|
||||
*(vu32*)(SDMMC_BASE + reg) = val;
|
||||
}
|
||||
|
||||
static inline void sdmmc_mask16(u16 reg, const u16 clear, const u16 set) {
|
||||
u16 val = sdmmc_read16(reg);
|
||||
val &= ~clear;
|
||||
val |= set;
|
||||
sdmmc_write16(reg, val);
|
||||
}
|
||||
|
||||
static inline void setckl(u32 data)
|
||||
{
|
||||
sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
|
||||
sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF);
|
||||
sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100);
|
||||
}
|
||||
|
||||
|
||||
mmcdevice *getMMCDevice(int drive)
|
||||
{
|
||||
if(drive==0) return &handleNAND;
|
||||
return &handleSD;
|
||||
}
|
||||
|
||||
static u32 __attribute__((noinline)) geterror(struct mmcdevice *ctx)
|
||||
{
|
||||
return (ctx->error << 29) >> 31;
|
||||
}
|
||||
|
||||
static void __attribute__((noinline)) inittarget(struct mmcdevice *ctx)
|
||||
{
|
||||
sdmmc_mask16(REG_SDPORTSEL,0x3,(u16)ctx->devicenumber);
|
||||
setckl(ctx->clk);
|
||||
if (ctx->SDOPT == 0) {
|
||||
sdmmc_mask16(REG_SDOPT, 0, 0x8000);
|
||||
} else {
|
||||
sdmmc_mask16(REG_SDOPT, 0x8000, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args)
|
||||
{
|
||||
bool getSDRESP = (cmd << 15) >> 31;
|
||||
u16 flags = (cmd << 15) >> 31;
|
||||
const bool readdata = cmd & 0x20000;
|
||||
const bool writedata = cmd & 0x40000;
|
||||
|
||||
if (readdata || writedata)
|
||||
flags |= TMIO_STAT0_DATAEND;
|
||||
|
||||
ctx->error = 0;
|
||||
while (sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY); //mmc working?
|
||||
sdmmc_write16(REG_SDIRMASK0,0);
|
||||
sdmmc_write16(REG_SDIRMASK1,0);
|
||||
sdmmc_write16(REG_SDSTATUS0,0);
|
||||
sdmmc_write16(REG_SDSTATUS1,0);
|
||||
sdmmc_mask16(REG_SDDATACTL32,0x1800,0);
|
||||
|
||||
sdmmc_write16(REG_SDCMDARG0,args &0xFFFF);
|
||||
sdmmc_write16(REG_SDCMDARG1,args >> 16);
|
||||
sdmmc_write16(REG_SDCMD,cmd &0xFFFF);
|
||||
|
||||
u32 size = ctx->size;
|
||||
vu8 *dataPtr = ctx->data;
|
||||
|
||||
bool useBuf = ( NULL != dataPtr );
|
||||
|
||||
u16 status0 = 0;
|
||||
while(true) {
|
||||
u16 status1 = sdmmc_read16(REG_SDSTATUS1);
|
||||
if (status1 & TMIO_STAT1_RXRDY) {
|
||||
if (readdata && useBuf) {
|
||||
sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0);
|
||||
//sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_RXRDY);
|
||||
if (size > 0x1FF) {
|
||||
for(int i = 0; i<0x200; i+=2) {
|
||||
u16 data = sdmmc_read16(REG_SDFIFO);
|
||||
*dataPtr++ = data & 0xFF;
|
||||
*dataPtr++ = data >> 8;
|
||||
}
|
||||
size -= 0x200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (status1 & TMIO_STAT1_TXRQ) {
|
||||
if (writedata && useBuf) {
|
||||
sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0);
|
||||
//sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_TXRQ);
|
||||
if (size > 0x1FF) {
|
||||
for (int i = 0; i<0x200; i+=2) {
|
||||
u16 data = *dataPtr++;
|
||||
data |= *dataPtr++ << 8;
|
||||
sdmmc_write16(REG_SDFIFO, data);
|
||||
}
|
||||
size -= 0x200;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status1 & TMIO_MASK_GW) {
|
||||
ctx->error |= 4;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(status1 & TMIO_STAT1_CMD_BUSY)) {
|
||||
status0 = sdmmc_read16(REG_SDSTATUS0);
|
||||
if (sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND)
|
||||
ctx->error |= 0x1;
|
||||
if (status0 & TMIO_STAT0_DATAEND)
|
||||
ctx->error |= 0x2;
|
||||
|
||||
if ((status0 & flags) == flags)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ctx->stat0 = sdmmc_read16(REG_SDSTATUS0);
|
||||
ctx->stat1 = sdmmc_read16(REG_SDSTATUS1);
|
||||
sdmmc_write16(REG_SDSTATUS0,0);
|
||||
sdmmc_write16(REG_SDSTATUS1,0);
|
||||
|
||||
if (getSDRESP != 0) {
|
||||
ctx->ret[0] = (u32)sdmmc_read16(REG_SDRESP0) | (u32)(sdmmc_read16(REG_SDRESP1) << 16);
|
||||
ctx->ret[1] = (u32)sdmmc_read16(REG_SDRESP2) | (u32)(sdmmc_read16(REG_SDRESP3) << 16);
|
||||
ctx->ret[2] = (u32)sdmmc_read16(REG_SDRESP4) | (u32)(sdmmc_read16(REG_SDRESP5) << 16);
|
||||
ctx->ret[3] = (u32)sdmmc_read16(REG_SDRESP6) | (u32)(sdmmc_read16(REG_SDRESP7) << 16);
|
||||
}
|
||||
}
|
||||
|
||||
u32 __attribute__((noinline)) sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, vu8 *in)
|
||||
{
|
||||
if (handleSD.isSDHC == 0)
|
||||
sector_no <<= 9;
|
||||
inittarget(&handleSD);
|
||||
sdmmc_write16(REG_SDSTOP,0x100);
|
||||
|
||||
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||
handleSD.data = in;
|
||||
handleSD.size = numsectors << 9;
|
||||
sdmmc_send_command(&handleSD,0x52C19,sector_no);
|
||||
return geterror(&handleSD);
|
||||
}
|
||||
|
||||
u32 __attribute__((noinline)) sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, vu8 *out)
|
||||
{
|
||||
if (handleSD.isSDHC == 0)
|
||||
sector_no <<= 9;
|
||||
inittarget(&handleSD);
|
||||
sdmmc_write16(REG_SDSTOP,0x100);
|
||||
|
||||
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||
handleSD.data = out;
|
||||
handleSD.size = numsectors << 9;
|
||||
sdmmc_send_command(&handleSD,0x33C12,sector_no);
|
||||
return geterror(&handleSD);
|
||||
}
|
||||
|
||||
u32 __attribute__((noinline)) sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, vu8 *out)
|
||||
{
|
||||
if (handleNAND.isSDHC == 0)
|
||||
sector_no <<= 9;
|
||||
inittarget(&handleNAND);
|
||||
sdmmc_write16(REG_SDSTOP,0x100);
|
||||
|
||||
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||
|
||||
handleNAND.data = out;
|
||||
handleNAND.size = numsectors << 9;
|
||||
sdmmc_send_command(&handleNAND,0x33C12,sector_no);
|
||||
inittarget(&handleSD);
|
||||
return geterror(&handleNAND);
|
||||
}
|
||||
|
||||
u32 __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, vu8 *in) //experimental
|
||||
{
|
||||
if (handleNAND.isSDHC == 0)
|
||||
sector_no <<= 9;
|
||||
inittarget(&handleNAND);
|
||||
sdmmc_write16(REG_SDSTOP,0x100);
|
||||
|
||||
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||
|
||||
handleNAND.data = in;
|
||||
handleNAND.size = numsectors << 9;
|
||||
sdmmc_send_command(&handleNAND,0x52C19,sector_no);
|
||||
inittarget(&handleSD);
|
||||
return geterror(&handleNAND);
|
||||
}
|
||||
|
||||
static u32 calcSDSize(u8* csd, int type)
|
||||
{
|
||||
u32 result = 0;
|
||||
if (type == -1) type = csd[14] >> 6;
|
||||
switch (type) {
|
||||
case 0:
|
||||
{
|
||||
u32 block_len = csd[9] & 0xf;
|
||||
block_len = 1u << block_len;
|
||||
u32 mult = (u32)(csd[4] >> 7) | (u32)((csd[5] & 3) << 1);
|
||||
mult = 1u << (mult + 2);
|
||||
result = csd[8] & 3;
|
||||
result = (result << 8) | csd[7];
|
||||
result = (result << 2) | (csd[6] >> 6);
|
||||
result = (result + 1) * mult * block_len / 512;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
result = csd[7] & 0x3f;
|
||||
result = (result << 8) | csd[6];
|
||||
result = (result << 8) | csd[5];
|
||||
result = (result + 1) * 1024;
|
||||
break;
|
||||
default:
|
||||
break; //Do nothing otherwise
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void InitSD()
|
||||
{
|
||||
//NAND
|
||||
handleNAND.isSDHC = 0;
|
||||
handleNAND.SDOPT = 0;
|
||||
handleNAND.res = 0;
|
||||
handleNAND.initarg = 1;
|
||||
handleNAND.clk = 0x80;
|
||||
handleNAND.devicenumber = 1;
|
||||
|
||||
//SD
|
||||
handleSD.isSDHC = 0;
|
||||
handleSD.SDOPT = 0;
|
||||
handleSD.res = 0;
|
||||
handleSD.initarg = 0;
|
||||
handleSD.clk = 0x80;
|
||||
handleSD.devicenumber = 0;
|
||||
|
||||
*(vu16*)0x10006100 &= 0xF7FFu; //SDDATACTL32
|
||||
*(vu16*)0x10006100 &= 0xEFFFu; //SDDATACTL32
|
||||
*(vu16*)0x10006100 |= 0x402u; //SDDATACTL32
|
||||
*(vu16*)0x100060D8 = (*(vu16*)0x100060D8 & 0xFFDD) | 2;
|
||||
*(vu16*)0x10006100 &= 0xFFFDu; //SDDATACTL32
|
||||
*(vu16*)0x100060D8 &= 0xFFDDu; //SDDATACTL
|
||||
*(vu16*)0x10006104 = 0; //SDBLKLEN32
|
||||
*(vu16*)0x10006108 = 1; //SDBLKCOUNT32
|
||||
*(vu16*)0x100060E0 &= 0xFFFEu; //SDRESET
|
||||
*(vu16*)0x100060E0 |= 1u; //SDRESET
|
||||
*(vu16*)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0
|
||||
*(vu16*)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1
|
||||
*(vu16*)0x100060FC |= 0xDBu; //SDCTL_RESERVED7
|
||||
*(vu16*)0x100060FE |= 0xDBu; //SDCTL_RESERVED8
|
||||
*(vu16*)0x10006002 &= 0xFFFCu; //SDPORTSEL
|
||||
*(vu16*)0x10006024 = 0x40; //Nintendo sets this to 0x20
|
||||
*(vu16*)0x10006028 = 0x40EB; //Nintendo sets this to 0x40EE
|
||||
*(vu16*)0x10006002 &= 0xFFFCu; ////SDPORTSEL
|
||||
*(vu16*)0x10006026 = 512; //SDBLKLEN
|
||||
*(vu16*)0x10006008 = 0; //SDSTOP
|
||||
|
||||
inittarget(&handleSD);
|
||||
}
|
||||
|
||||
static int Nand_Init()
|
||||
{
|
||||
inittarget(&handleNAND);
|
||||
ioDelay(0xF000);
|
||||
|
||||
sdmmc_send_command(&handleNAND,0,0);
|
||||
|
||||
do {
|
||||
do {
|
||||
sdmmc_send_command(&handleNAND,0x10701,0x100000);
|
||||
} while ( !(handleNAND.error & 1) );
|
||||
} while((handleNAND.ret[0] & 0x80000000) == 0);
|
||||
|
||||
sdmmc_send_command(&handleNAND,0x10602,0x0);
|
||||
if (handleNAND.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&handleNAND,0x10403,handleNAND.initarg << 0x10);
|
||||
if (handleNAND.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&handleNAND,0x10609,handleNAND.initarg << 0x10);
|
||||
if (handleNAND.error & 0x4) return -1;
|
||||
|
||||
handleNAND.total_size = calcSDSize((u8*)&handleNAND.ret[0],0);
|
||||
handleNAND.clk = 1;
|
||||
setckl(1);
|
||||
|
||||
sdmmc_send_command(&handleNAND,0x10407,handleNAND.initarg << 0x10);
|
||||
if (handleNAND.error & 0x4) return -1;
|
||||
|
||||
handleNAND.SDOPT = 1;
|
||||
|
||||
sdmmc_send_command(&handleNAND,0x10506,0x3B70100);
|
||||
if (handleNAND.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&handleNAND,0x10506,0x3B90100);
|
||||
if (handleNAND.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&handleNAND,0x1040D,handleNAND.initarg << 0x10);
|
||||
if (handleNAND.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&handleNAND,0x10410,0x200);
|
||||
if (handleNAND.error & 0x4) return -1;
|
||||
|
||||
handleNAND.clk |= 0x200;
|
||||
|
||||
inittarget(&handleSD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SD_Init()
|
||||
{
|
||||
inittarget(&handleSD);
|
||||
|
||||
ioDelay(1u << 18); //Card needs a little bit of time to be detected, it seems
|
||||
|
||||
//If not inserted
|
||||
if (!(*((vu16*)0x1000601c) & TMIO_STAT0_SIGSTATE)) return -1;
|
||||
|
||||
sdmmc_send_command(&handleSD,0,0);
|
||||
sdmmc_send_command(&handleSD,0x10408,0x1AA);
|
||||
//u32 temp = (handleSD.ret[0] == 0x1AA) << 0x1E;
|
||||
u32 temp = (handleSD.error & 0x1) << 0x1E;
|
||||
|
||||
//int count = 0;
|
||||
u32 temp2 = 0;
|
||||
do {
|
||||
do {
|
||||
sdmmc_send_command(&handleSD,0x10437,handleSD.initarg << 0x10);
|
||||
sdmmc_send_command(&handleSD,0x10769,0x00FF8000 | temp);
|
||||
temp2 = 1;
|
||||
} while ( !(handleSD.error & 1) );
|
||||
|
||||
} while((handleSD.ret[0] & 0x80000000) == 0);
|
||||
|
||||
if(!((handleSD.ret[0] >> 30) & 1) || !temp)
|
||||
temp2 = 0;
|
||||
|
||||
handleSD.isSDHC = temp2;
|
||||
|
||||
sdmmc_send_command(&handleSD,0x10602,0);
|
||||
if (handleSD.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&handleSD,0x10403,0);
|
||||
if (handleSD.error & 0x4) return -1;
|
||||
handleSD.initarg = handleSD.ret[0] >> 0x10;
|
||||
|
||||
sdmmc_send_command(&handleSD,0x10609,handleSD.initarg << 0x10);
|
||||
if (handleSD.error & 0x4) return -1;
|
||||
|
||||
handleSD.total_size = calcSDSize((u8*)&handleSD.ret[0],-1);
|
||||
handleSD.clk = 1;
|
||||
setckl(1);
|
||||
|
||||
sdmmc_send_command(&handleSD,0x10507,handleSD.initarg << 0x10);
|
||||
if (handleSD.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&handleSD,0x10437,handleSD.initarg << 0x10);
|
||||
if (handleSD.error & 0x4) return -1;
|
||||
|
||||
handleSD.SDOPT = 1;
|
||||
sdmmc_send_command(&handleSD,0x10446,0x2);
|
||||
if (handleSD.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&handleSD,0x1040D,handleSD.initarg << 0x10);
|
||||
if (handleSD.error & 0x4) return -1;
|
||||
|
||||
sdmmc_send_command(&handleSD,0x10410,0x200);
|
||||
if (handleSD.error & 0x4) return -1;
|
||||
handleSD.clk |= 0x200;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sdmmc_sdcard_init()
|
||||
{
|
||||
InitSD();
|
||||
int result = Nand_Init();
|
||||
return result | SD_Init();
|
||||
}
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
// Copyright 2014 Normmatt
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define SDMMC_BASE 0x10006000u
|
||||
|
||||
#define REG_SDCMD 0x00
|
||||
#define REG_SDPORTSEL 0x02
|
||||
#define REG_SDCMDARG 0x04
|
||||
#define REG_SDCMDARG0 0x04
|
||||
#define REG_SDCMDARG1 0x06
|
||||
#define REG_SDSTOP 0x08
|
||||
#define REG_SDBLKCOUNT 0x0a
|
||||
|
||||
#define REG_SDRESP0 0x0c
|
||||
#define REG_SDRESP1 0x0e
|
||||
#define REG_SDRESP2 0x10
|
||||
#define REG_SDRESP3 0x12
|
||||
#define REG_SDRESP4 0x14
|
||||
#define REG_SDRESP5 0x16
|
||||
#define REG_SDRESP6 0x18
|
||||
#define REG_SDRESP7 0x1a
|
||||
|
||||
#define REG_SDSTATUS0 0x1c
|
||||
#define REG_SDSTATUS1 0x1e
|
||||
|
||||
#define REG_SDIRMASK0 0x20
|
||||
#define REG_SDIRMASK1 0x22
|
||||
#define REG_SDCLKCTL 0x24
|
||||
|
||||
#define REG_SDBLKLEN 0x26
|
||||
#define REG_SDOPT 0x28
|
||||
#define REG_SDFIFO 0x30
|
||||
|
||||
#define REG_SDDATACTL 0xd8
|
||||
#define REG_SDRESET 0xe0
|
||||
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
|
||||
|
||||
#define REG_SDDATACTL32 0x100
|
||||
#define REG_SDBLKLEN32 0x104
|
||||
#define REG_SDBLKCOUNT32 0x108
|
||||
#define REG_SDFIFO32 0x10C
|
||||
|
||||
#define REG_CLK_AND_WAIT_CTL 0x138
|
||||
#define REG_RESET_SDIO 0x1e0
|
||||
|
||||
#define TMIO_STAT0_CMDRESPEND 0x0001
|
||||
#define TMIO_STAT0_DATAEND 0x0004
|
||||
#define TMIO_STAT0_CARD_REMOVE 0x0008
|
||||
#define TMIO_STAT0_CARD_INSERT 0x0010
|
||||
#define TMIO_STAT0_SIGSTATE 0x0020
|
||||
#define TMIO_STAT0_WRPROTECT 0x0080
|
||||
#define TMIO_STAT0_CARD_REMOVE_A 0x0100
|
||||
#define TMIO_STAT0_CARD_INSERT_A 0x0200
|
||||
#define TMIO_STAT0_SIGSTATE_A 0x0400
|
||||
#define TMIO_STAT1_CMD_IDX_ERR 0x0001
|
||||
#define TMIO_STAT1_CRCFAIL 0x0002
|
||||
#define TMIO_STAT1_STOPBIT_ERR 0x0004
|
||||
#define TMIO_STAT1_DATATIMEOUT 0x0008
|
||||
#define TMIO_STAT1_RXOVERFLOW 0x0010
|
||||
#define TMIO_STAT1_TXUNDERRUN 0x0020
|
||||
#define TMIO_STAT1_CMDTIMEOUT 0x0040
|
||||
#define TMIO_STAT1_RXRDY 0x0100
|
||||
#define TMIO_STAT1_TXRQ 0x0200
|
||||
#define TMIO_STAT1_ILL_FUNC 0x2000
|
||||
#define TMIO_STAT1_CMD_BUSY 0x4000
|
||||
#define TMIO_STAT1_ILL_ACCESS 0x8000
|
||||
|
||||
//Comes from TWLSDK mongoose.tef DWARF info
|
||||
#define SDMC_NORMAL 0x00000000
|
||||
#define SDMC_ERR_COMMAND 0x00000001
|
||||
#define SDMC_ERR_CRC 0x00000002
|
||||
#define SDMC_ERR_END 0x00000004
|
||||
#define SDMC_ERR_TIMEOUT 0x00000008
|
||||
#define SDMC_ERR_FIFO_OVF 0x00000010
|
||||
#define SDMC_ERR_FIFO_UDF 0x00000020
|
||||
#define SDMC_ERR_WP 0x00000040
|
||||
#define SDMC_ERR_ABORT 0x00000080
|
||||
#define SDMC_ERR_FPGA_TIMEOUT 0x00000100
|
||||
#define SDMC_ERR_PARAM 0x00000200
|
||||
#define SDMC_ERR_R1_STATUS 0x00000800
|
||||
#define SDMC_ERR_NUM_WR_SECTORS 0x00001000
|
||||
#define SDMC_ERR_RESET 0x00002000
|
||||
#define SDMC_ERR_ILA 0x00004000
|
||||
#define SDMC_ERR_INFO_DETECT 0x00008000
|
||||
|
||||
#define SDMC_STAT_ERR_UNKNOWN 0x00080000
|
||||
#define SDMC_STAT_ERR_CC 0x00100000
|
||||
#define SDMC_STAT_ERR_ECC_FAILED 0x00200000
|
||||
#define SDMC_STAT_ERR_CRC 0x00800000
|
||||
#define SDMC_STAT_ERR_OTHER 0xf9c70008
|
||||
|
||||
#define TMIO_MASK_ALL 0x837f031d
|
||||
|
||||
#define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \
|
||||
TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)
|
||||
|
||||
#define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND)
|
||||
#define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND)
|
||||
|
||||
typedef struct mmcdevice {
|
||||
vu8* data;
|
||||
u32 size;
|
||||
u32 error;
|
||||
u16 stat0;
|
||||
u16 stat1;
|
||||
u32 ret[4];
|
||||
u32 initarg;
|
||||
u32 isSDHC;
|
||||
u32 clk;
|
||||
u32 SDOPT;
|
||||
u32 devicenumber;
|
||||
u32 total_size; //size in sectors of the device
|
||||
u32 res;
|
||||
} mmcdevice;
|
||||
|
||||
int sdmmc_sdcard_init();
|
||||
u32 sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, vu8 *out);
|
||||
u32 sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, vu8 *in);
|
||||
mmcdevice *getMMCDevice(int drive);
|
||||
|
||||
u32 sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, vu8 *out);
|
||||
u32 sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, vu8 *in);
|
||||
@@ -1,42 +1,38 @@
|
||||
#include "types.h"
|
||||
#include "buttons.h"
|
||||
#include "fatfs/ff.h"
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define PAYLOAD_ADDRESS 0x23F00000
|
||||
#include "memory.h"
|
||||
#include "cache.h"
|
||||
|
||||
static u32 loadPayload(const char *path)
|
||||
{
|
||||
FIL payload;
|
||||
unsigned int br;
|
||||
|
||||
if(f_open(&payload, path, FA_READ) == FR_OK)
|
||||
{
|
||||
f_read(&payload, (void *)PAYLOAD_ADDRESS, f_size(&payload), &br);
|
||||
f_close(&payload);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
extern u32 payloadSize; //Defined in start.s
|
||||
|
||||
void main(void)
|
||||
{
|
||||
FATFS fs;
|
||||
void *payloadAddress = (void *)0x23F00000;
|
||||
|
||||
f_mount(&fs, "0:", 1);
|
||||
memcpy(payloadAddress, (void *)0x24F00000, payloadSize);
|
||||
|
||||
//Get pressed buttons
|
||||
u32 pressed = HID_PAD;
|
||||
//Ensure that all memory transfers have completed and that the caches have been flushed
|
||||
flushCaches();
|
||||
|
||||
if(((pressed & BUTTON_RIGHT) && loadPayload("/aurei/payloads/right.bin")) ||
|
||||
((pressed & BUTTON_LEFT) && loadPayload("/aurei/payloads/left.bin")) ||
|
||||
((pressed & BUTTON_UP) && loadPayload("/aurei/payloads/up.bin")) ||
|
||||
((pressed & BUTTON_DOWN) && loadPayload("/aurei/payloads/down.bin")) ||
|
||||
((pressed & BUTTON_X) && loadPayload("/aurei/payloads/x.bin")) ||
|
||||
((pressed & BUTTON_Y) && loadPayload("/aurei/payloads/y.bin")) ||
|
||||
((pressed & BUTTON_SELECT) && loadPayload("/aurei/payloads/select.bin")) ||
|
||||
((pressed & BUTTON_R1) && loadPayload("/aurei/payloads/r.bin")) ||
|
||||
loadPayload("/aurei/payloads/default.bin"))
|
||||
((void (*)())PAYLOAD_ADDRESS)();
|
||||
((void (*)())payloadAddress)();
|
||||
}
|
||||
36
loader/source/memory.c
Normal file
36
loader/source/memory.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* memcpy adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
void memcpy(void *dest, const void *src, u32 size)
|
||||
{
|
||||
u8 *destc = (u8 *)dest;
|
||||
const u8 *srcc = (const u8 *)src;
|
||||
|
||||
for(u32 i = 0; i < size; i++)
|
||||
destc[i] = srcc[i];
|
||||
}
|
||||
31
loader/source/memory.h
Normal file
31
loader/source/memory.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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);
|
||||
@@ -1,15 +1,29 @@
|
||||
@ 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.
|
||||
|
||||
.section .text.start
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
@ Fix payloads like Decrypt9
|
||||
mov r0, #0x5
|
||||
mcr p15, 0, r0, c3, c0, 0 @ data bufferable
|
||||
|
||||
@ Flush caches
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 @ flush I-cache
|
||||
mcr p15, 0, r0, c7, c6, 0 @ flush D-cache
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
|
||||
|
||||
b main
|
||||
|
||||
.global payloadSize
|
||||
payloadSize:
|
||||
.word 0
|
||||
|
||||
@@ -1,13 +1,28 @@
|
||||
/*
|
||||
* types.h
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//Common data types
|
||||
typedef uint8_t u8;
|
||||
|
||||
@@ -1,46 +1,48 @@
|
||||
; Code by Normmatt
|
||||
|
||||
.arm.little
|
||||
|
||||
.create "emunand.bin", 0
|
||||
.create "build/emunand.bin", 0
|
||||
.arm
|
||||
nand_sd:
|
||||
; Original code that still needs to be executed.
|
||||
; Original code that still needs to be executed
|
||||
mov r4, r0
|
||||
mov r5, r1
|
||||
mov r7, r2
|
||||
mov r6, r3
|
||||
; End.
|
||||
; End
|
||||
|
||||
; If we're already trying to access the SD, return.
|
||||
; If we're already trying to access the SD, return
|
||||
ldr r2, [r0, #4]
|
||||
ldr r1, [sdmmc]
|
||||
cmp r2, r1
|
||||
beq nand_sd_ret
|
||||
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)
|
||||
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, [nand_offset]
|
||||
add r2, r3 ; Add the offset to the NAND in the SD.
|
||||
add r2, r3 ; Add the offset to the NAND in the SD
|
||||
|
||||
ldreq r3, [ncsd_header_offset]
|
||||
addeq r2, r3 ; If we're reading the ncsd header, add the offset of that sector.
|
||||
addeq r2, r3 ; If we're reading the ncsd header, add the offset of that sector
|
||||
|
||||
str r2, [r0, #8] ; Store sector to read
|
||||
str r2, [r0, #8] ; Store sector to read
|
||||
|
||||
nand_sd_ret:
|
||||
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.
|
||||
; due to the offset of this function being stored there
|
||||
mov r0, lr
|
||||
add r0, #4
|
||||
bx r0
|
||||
|
||||
.pool
|
||||
sdmmc: .ascii "SDMC"
|
||||
nand_offset: .ascii "NAND" ; for rednand this should be 1
|
||||
ncsd_header_offset: .ascii "NCSD" ; depends on nand manufacturer + emunand type (GW/RED)
|
||||
.close
|
||||
nand_offset: .ascii "NAND" ; For rednand this should be 1
|
||||
ncsd_header_offset: .ascii "NCSD" ; Depends on nand manufacturer + emunand type (GW/RED)
|
||||
.close
|
||||
105
patches/k11modules.s
Normal file
105
patches/k11modules.s
Normal file
@@ -0,0 +1,105 @@
|
||||
;
|
||||
; 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.
|
||||
;
|
||||
|
||||
; Code originally from Subv
|
||||
|
||||
.arm.little
|
||||
|
||||
.create "build/k11modules.bin", 0
|
||||
.arm
|
||||
; This code searches the sm module for a specific byte pattern and patches some of the instructions
|
||||
; in the code to disable service access checks when calling srv:GetServiceHandle
|
||||
|
||||
; It also searches the fs module for archive access check code
|
||||
|
||||
; Save the registers we'll be using
|
||||
; Register contents:
|
||||
; r4: Pointer to a pointer to the exheader of the current NCCH
|
||||
; r6: Constant 0
|
||||
; SP + 4: Pointer to the memory location where the NCCH text was loaded
|
||||
|
||||
; Execute the instruction we overwrote in our detour
|
||||
ldr r0, [r4]
|
||||
|
||||
; Save the value of the register we use
|
||||
push {r0-r4}
|
||||
|
||||
ldr r1, [sp, #24] ; Load the .text address
|
||||
ldr r2, [r0, #0x200] ; Load the low title id of the current NCCH
|
||||
ldr r0, [r0, #0x18] ; Load the size of the .text
|
||||
add r0, r1, r0 ; Max bounds of the memory region
|
||||
|
||||
ldr r3, =0x1002 ; Low title id of the sm module
|
||||
cmp r2, r3 ; Compare the low title id to the id of the sm module
|
||||
bne fs_patch ; Skip if they're not the same
|
||||
|
||||
ldr r2, =0xE1A01006 ; mov r1, r6
|
||||
|
||||
loop:
|
||||
cmp r0, r1
|
||||
blo die ; Check if we didn't go past the bounds of the memory region
|
||||
ldr r3, [r1]
|
||||
cmp r3, r2
|
||||
ldreqh r3, [r1, #4]
|
||||
cmpeq r3, #5
|
||||
addne r1, #4
|
||||
bne loop
|
||||
|
||||
; r1 now contains the start address of the pattern we found
|
||||
ldr r0, =0xE3A00001 ; mov r0, #1
|
||||
str r0, [r1, #8] ; Patch the bl
|
||||
b out
|
||||
|
||||
fs_patch: ; patch adapted from BootNTR
|
||||
ldr r3, =0x1102 ; Low title id of the fs module
|
||||
cmp r2, r3 ; Compare the low title id to the id of the sm module
|
||||
bne out ; Skip if they're not the same
|
||||
|
||||
ldr r2, =0x7401 ; strb r1, [r0, #16]
|
||||
ldr r3, =0x2000 ; movs r0, #0
|
||||
|
||||
loop_fs:
|
||||
cmp r0, r1
|
||||
blo die
|
||||
ldrh r4, [r1]
|
||||
cmp r4, r2
|
||||
ldreqh r4, [r1, #2]
|
||||
cmpeq r4, r3
|
||||
addeq r1, #8
|
||||
addne r1, #2
|
||||
bne loop_fs
|
||||
|
||||
; r1 now contains the start address of the pattern we found
|
||||
ldr r0, =0x2001 ; mov r0, #1
|
||||
ldr r2, =0x4770 ; bx lr
|
||||
strh r0, [r1]
|
||||
strh r2, [r1, #2]
|
||||
|
||||
out:
|
||||
pop {r0-r4} ; Restore the registers we used
|
||||
bx lr ; Jump back to whoever called us
|
||||
|
||||
die:
|
||||
b die
|
||||
|
||||
.pool
|
||||
.close
|
||||
165
patches/reboot.s
165
patches/reboot.s
@@ -1,14 +1,21 @@
|
||||
; Code originally from delebile and mid-kid
|
||||
|
||||
.arm.little
|
||||
|
||||
payload_addr equ 0x23F00000 ; Brahma payload address.
|
||||
payload_maxsize equ 0x20000 ; Maximum size for the payload (200 KB will do).
|
||||
payload_addr equ 0x23F00000 ; Brahma payload address
|
||||
payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeBrah supports)
|
||||
|
||||
.create "reboot.bin", 0
|
||||
.create "build/reboot.bin", 0
|
||||
.arm
|
||||
; Interesting registers and locations to keep in mind, set before this code is ran:
|
||||
; - sp + 0x3A8 - 0x70: FIRM path in exefs.
|
||||
; - r7 (which is sp + 0x3A8 - 0x198): Reserved space for file handle
|
||||
; - *(sp + 0x3A8 - 0x198) + 0x28: fread function.
|
||||
; Interesting registers and locations to keep in mind, set just before this code is ran:
|
||||
; - r1: FIRM path in exefs.
|
||||
; - r7 (or r8): pointer to file object
|
||||
; - *r7: vtable
|
||||
; - *(vtable + 0x28): fread function
|
||||
; - *(r7 + 8): file handle
|
||||
|
||||
sub r7, r0, #8
|
||||
mov r8, r1
|
||||
|
||||
pxi_wait_recv:
|
||||
ldr r2, =0x44846
|
||||
@@ -21,43 +28,41 @@ payload_maxsize equ 0x20000 ; Maximum size for the payload (200 KB will do).
|
||||
cmp r0, r2
|
||||
bne pxi_wait_recv
|
||||
|
||||
mov r4, #0
|
||||
adr r1, bin_fname
|
||||
b open_payload
|
||||
|
||||
fallback:
|
||||
mov r4, #1
|
||||
adr r1, dat_fname
|
||||
mov r4, #2
|
||||
|
||||
open_payload:
|
||||
; Open file
|
||||
add r0, r7, #8
|
||||
adr r1, fname
|
||||
mov r2, #1
|
||||
ldr r6, [fopen]
|
||||
orr r6, 1
|
||||
blx r6
|
||||
cmp r0, #0
|
||||
bne fallback ; If the .bin is not found, try the .dat.
|
||||
beq read_payload
|
||||
subs r4, r4, #1
|
||||
beq panic
|
||||
adr r0, fname
|
||||
adr r1, nand_mount
|
||||
mov r2, #8
|
||||
bl memcpy16
|
||||
b open_payload
|
||||
|
||||
read_payload:
|
||||
; Read file
|
||||
mov r0, r7
|
||||
mov r0, r7
|
||||
adr r1, bytes_read
|
||||
ldr r2, =payload_addr
|
||||
cmp r4, #0
|
||||
movne r3, #0x12000 ; Skip the first 0x12000 bytes.
|
||||
moveq r3, payload_maxsize
|
||||
ldr r6, [sp, #0x3A8-0x198]
|
||||
ldr r6, [r6, #0x28]
|
||||
blx r6
|
||||
cmp r4, #0
|
||||
movne r4, #0
|
||||
bne read_payload ; Go read the real payload.
|
||||
ldr r3, =payload_maxsize
|
||||
ldr r6, [r7]
|
||||
ldr r6, [r6, #0x28]
|
||||
blx r6
|
||||
|
||||
add r0, sp, #0x3A8 - 0x70
|
||||
ldr r0, [r0, #0x27]
|
||||
ldr r1, =payload_addr + 4
|
||||
str r0, [r1] ; Copy the last digits of the wanted firm to the 5th byte of the payload.
|
||||
; Copy the low TID (in UTF-16) of the wanted firm to the 5th byte of the payload
|
||||
ldr r0, =payload_addr + 4
|
||||
add r1, r8, #0x1A
|
||||
mov r2, #0x10
|
||||
bl memcpy16
|
||||
|
||||
; Set kernel state
|
||||
mov r0, #0
|
||||
@@ -69,76 +74,65 @@ payload_maxsize equ 0x20000 ; Maximum size for the payload (200 KB will do).
|
||||
goto_reboot:
|
||||
; Jump to reboot code
|
||||
ldr r0, =(kernelcode_start - goto_reboot - 12)
|
||||
add r0, pc
|
||||
add r0, pc ; pc is two instructions ahead of the instruction being executed (12 = 2*4 + 4)
|
||||
swi 0x7B
|
||||
|
||||
die:
|
||||
b die
|
||||
|
||||
memcpy16:
|
||||
add r2, r0, r2
|
||||
copy_loop:
|
||||
ldrh r3, [r1], #2
|
||||
strh r3, [r0], #2
|
||||
cmp r0, r2
|
||||
blo copy_loop
|
||||
bx lr
|
||||
|
||||
panic:
|
||||
mov r1, r0 ; unused register
|
||||
mov r0, #0
|
||||
swi 0x3C ; svcBreak(USERBREAK_PANIC)
|
||||
b die
|
||||
|
||||
bytes_read: .word 0
|
||||
fopen: .ascii "OPEN"
|
||||
.pool
|
||||
bin_fname: .dcw "sdmc:/arm9loaderhax.bin"
|
||||
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
dat_fname: .dcw "sdmc:/AuReiNand.dat"
|
||||
.word 0
|
||||
fname: .dcw "sdmc:/arm9loaderhax.bin"
|
||||
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
.pool
|
||||
nand_mount: .dcw "nand"
|
||||
|
||||
.align 4
|
||||
kernelcode_start:
|
||||
; Set MPU settings
|
||||
mrc p15, 0, r0, c2, c0, 0 ; dcacheable
|
||||
mrc p15, 0, r12, c2, c0, 1 ; icacheable
|
||||
mrc p15, 0, r1, c3, c0, 0 ; write bufferable
|
||||
mrc p15, 0, r2, c5, c0, 2 ; daccess
|
||||
mrc p15, 0, r3, c5, c0, 3 ; iaccess
|
||||
ldr r4, =0x18000035 ; 0x18000000 128M
|
||||
bic r2, r2, #0xF0000 ; unprotect region 4
|
||||
bic r3, r3, #0xF0000 ; unprotect region 4
|
||||
orr r0, r0, #0x10 ; dcacheable region 4
|
||||
orr r2, r2, #0x30000 ; region 4 r/w
|
||||
orr r3, r3, #0x30000 ; region 4 r/w
|
||||
orr r12, r12, #0x10 ; icacheable region 4
|
||||
orr r1, r1, #0x10 ; write bufferable region 4
|
||||
mcr p15, 0, r0, c2, c0, 0
|
||||
mcr p15, 0, r12, c2, c0, 1
|
||||
mcr p15, 0, r1, c3, c0, 0 ; write bufferable
|
||||
mcr p15, 0, r2, c5, c0, 2 ; daccess
|
||||
mcr p15, 0, r3, c5, c0, 3 ; iaccess
|
||||
mcr p15, 0, r4, c6, c4, 0 ; region 4 (hmmm)
|
||||
|
||||
mrc p15, 0, r0, c2, c0, 0 ; dcacheable
|
||||
mrc p15, 0, r1, c2, c0, 1 ; icacheable
|
||||
mrc p15, 0, r2, c3, c0, 0 ; write bufferable
|
||||
orr r0, r0, #0x20 ; dcacheable region 5
|
||||
orr r1, r1, #0x20 ; icacheable region 5
|
||||
orr r2, r2, #0x20 ; write bufferable region 5
|
||||
mcr p15, 0, r0, c2, c0, 0 ; dcacheable
|
||||
mcr p15, 0, r1, c2, c0, 1 ; icacheable
|
||||
mcr p15, 0, r2, c3, c0, 0 ; write bufferable
|
||||
ldr sp, =0x080FF000
|
||||
|
||||
; Flush cache
|
||||
mov r2, #0
|
||||
mov r1, r2
|
||||
flush_cache:
|
||||
mov r0, #0
|
||||
mov r3, r2, lsl #30
|
||||
flush_cache_inner_loop:
|
||||
orr r12, r3, r0, lsl#5
|
||||
mcr p15, 0, r1, c7, c10, 4 ; drain write buffer
|
||||
mcr p15, 0, r12, c7, c14, 2 ; clean and flush dcache entry (index and segment)
|
||||
add r0, #1
|
||||
cmp r0, #0x20
|
||||
bcc flush_cache_inner_loop
|
||||
add r2, #1
|
||||
cmp r2, #4
|
||||
bcc flush_cache
|
||||
|
||||
; Enable 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
|
||||
mcr p15, 0, r1, c7, c5, 0 ; flush dcache
|
||||
mcr p15, 0, r1, c7, c6, 0 ; flush icache
|
||||
mcr p15, 0, r1, c7, c10, 4 ; drain write buffer
|
||||
|
||||
; Clean and flush data cache
|
||||
mov r1, #0 ; segment counter
|
||||
outer_loop:
|
||||
mov r0, #0 ; line counter
|
||||
|
||||
inner_loop:
|
||||
orr r2, r1, r0 ; generate segment and line address
|
||||
mcr p15, 0, r2, c7, c14, 2 ; clean and flush the line
|
||||
add r0, #0x20 ; increment to next line
|
||||
cmp r0, #0x400
|
||||
bne inner_loop
|
||||
|
||||
add r1, #0x40000000
|
||||
cmp r1, #0
|
||||
bne outer_loop
|
||||
|
||||
; Drain write buffer
|
||||
mcr p15, 0, r1, c7, c10, 4
|
||||
|
||||
; Flush instruction cache
|
||||
mcr p15, 0, r1, c7, c5, 0
|
||||
|
||||
; Jump to payload
|
||||
ldr r0, =payload_addr
|
||||
@@ -146,3 +140,4 @@ dat_fname: .dcw "sdmc:/AuReiNand.dat"
|
||||
|
||||
.pool
|
||||
.close
|
||||
|
||||
|
||||
48
patches/svcGetCFWInfo.s
Normal file
48
patches/svcGetCFWInfo.s
Normal file
@@ -0,0 +1,48 @@
|
||||
;
|
||||
; 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.
|
||||
;
|
||||
|
||||
.arm.little
|
||||
|
||||
.create "build/svcGetCFWInfo.bin", 0
|
||||
.arm
|
||||
|
||||
adr r1, infoStart
|
||||
add r2, r0, #(infoEnd - infoStart)
|
||||
|
||||
loop:
|
||||
ldrb r3, [r1], #1
|
||||
strbt r3, [r0], #1
|
||||
cmp r0, r2
|
||||
blo loop
|
||||
|
||||
mov r0, #0
|
||||
|
||||
bx lr
|
||||
|
||||
.pool
|
||||
infoStart:
|
||||
.ascii "LUMA" ; magic
|
||||
.word 0 ; version
|
||||
.word 0 ; truncated commit hash
|
||||
.word 0 ; config
|
||||
infoEnd:
|
||||
.close
|
||||
@@ -1,98 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef uint8_t u8;
|
||||
|
||||
static u8 *memsearch(u8 *startPos, const void *pattern, int size, int patternSize)
|
||||
{
|
||||
const u8 *patternc = (const u8 *)pattern;
|
||||
|
||||
//Preprocessing
|
||||
int table[256];
|
||||
|
||||
int i;
|
||||
for(i = 0; i < 256; ++i)
|
||||
table[i] = patternSize + 1;
|
||||
for(i = 0; i < patternSize; ++i)
|
||||
table[patternc[i]] = patternSize - i;
|
||||
|
||||
//Searching
|
||||
int j = 0;
|
||||
|
||||
while(j <= size - patternSize)
|
||||
{
|
||||
if(memcmp(patternc, startPos + j, patternSize) == 0)
|
||||
return startPos + j;
|
||||
j += table[startPos[j + patternSize]];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int fsize(FILE *fp)
|
||||
{
|
||||
fseek(fp, 0, SEEK_END);
|
||||
int size = ftell(fp);
|
||||
rewind(fp);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void error(FILE *payload, const char *message)
|
||||
{
|
||||
fclose(payload);
|
||||
printf("%s, are you sure you're using an AuReiNand payload?\n", message);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if(argc == 1)
|
||||
{
|
||||
printf("Usage: %s <AuReiNand payload path>\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
FILE *payload;
|
||||
size_t size;
|
||||
|
||||
payload = fopen(argv[1], "rb+");
|
||||
size = fsize(payload);
|
||||
if(size > 0x20000)
|
||||
error(payload, "The input file is too large");
|
||||
|
||||
u8 *buffer = (u8 *)malloc(size);
|
||||
fread(buffer, 1, size, payload);
|
||||
|
||||
u8 pattern[] = {'s', 0, 'd', 0, 'm', 0, 'c', 0, ':', 0, '/', 0};
|
||||
|
||||
u8 *found = memsearch(buffer, pattern, size, sizeof(pattern));
|
||||
|
||||
if(found == NULL)
|
||||
{
|
||||
free(buffer);
|
||||
error(payload, "Pattern not found");
|
||||
}
|
||||
|
||||
u8 input[37] = {0};
|
||||
u8 payloadname[2 * sizeof(input)] = {0};
|
||||
|
||||
printf("Enter the payload's path (37 characters max): ");
|
||||
scanf("%37s", input);
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(input); i++)
|
||||
payloadname[2 * i] = input[i];
|
||||
|
||||
memcpy(found + 12, payloadname, sizeof(payloadname));
|
||||
|
||||
rewind(payload);
|
||||
fwrite(buffer, 1, size, payload);
|
||||
|
||||
free(buffer);
|
||||
fclose(payload);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x24F03000;
|
||||
.text.start : { *(.text.start) }
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) }
|
||||
.bss : { *(.bss COMMON) }
|
||||
.rodata : { *(.rodata) }
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
#include "types.h"
|
||||
|
||||
void main(void)
|
||||
{
|
||||
const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26};
|
||||
u32 brightnessLevel = *(vu32 *)0x24F03008;
|
||||
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
|
||||
|
||||
*(vu32 *)0x10141200 = 0x1007F;
|
||||
*(vu32 *)0x10202014 = 0x00000001;
|
||||
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
|
||||
*(vu32 *)0x10202240 = brightness[brightnessLevel];
|
||||
*(vu32 *)0x10202A40 = brightness[brightnessLevel];
|
||||
*(vu32 *)0x10202244 = 0x1023E;
|
||||
*(vu32 *)0x10202A44 = 0x1023E;
|
||||
|
||||
// Top screen
|
||||
*(vu32 *)0x10400400 = 0x000001c2;
|
||||
*(vu32 *)0x10400404 = 0x000000d1;
|
||||
*(vu32 *)0x10400408 = 0x000001c1;
|
||||
*(vu32 *)0x1040040c = 0x000001c1;
|
||||
*(vu32 *)0x10400410 = 0x00000000;
|
||||
*(vu32 *)0x10400414 = 0x000000cf;
|
||||
*(vu32 *)0x10400418 = 0x000000d1;
|
||||
*(vu32 *)0x1040041c = 0x01c501c1;
|
||||
*(vu32 *)0x10400420 = 0x00010000;
|
||||
*(vu32 *)0x10400424 = 0x0000019d;
|
||||
*(vu32 *)0x10400428 = 0x00000002;
|
||||
*(vu32 *)0x1040042c = 0x00000192;
|
||||
*(vu32 *)0x10400430 = 0x00000192;
|
||||
*(vu32 *)0x10400434 = 0x00000192;
|
||||
*(vu32 *)0x10400438 = 0x00000001;
|
||||
*(vu32 *)0x1040043c = 0x00000002;
|
||||
*(vu32 *)0x10400440 = 0x01960192;
|
||||
*(vu32 *)0x10400444 = 0x00000000;
|
||||
*(vu32 *)0x10400448 = 0x00000000;
|
||||
*(vu32 *)0x1040045C = 0x00f00190;
|
||||
*(vu32 *)0x10400460 = 0x01c100d1;
|
||||
*(vu32 *)0x10400464 = 0x01920002;
|
||||
*(vu32 *)0x10400468 = 0x18300000;
|
||||
*(vu32 *)0x10400470 = 0x80341;
|
||||
*(vu32 *)0x10400474 = 0x00010501;
|
||||
*(vu32 *)0x10400478 = 0;
|
||||
*(vu32 *)0x10400490 = 0x000002D0;
|
||||
*(vu32 *)0x1040049C = 0x00000000;
|
||||
|
||||
// Disco register
|
||||
for(u32 i = 0; i < 256; i++)
|
||||
*(vu32 *)0x10400484 = 0x10101 * i;
|
||||
|
||||
// Bottom screen
|
||||
*(vu32 *)0x10400500 = 0x000001c2;
|
||||
*(vu32 *)0x10400504 = 0x000000d1;
|
||||
*(vu32 *)0x10400508 = 0x000001c1;
|
||||
*(vu32 *)0x1040050c = 0x000001c1;
|
||||
*(vu32 *)0x10400510 = 0x000000cd;
|
||||
*(vu32 *)0x10400514 = 0x000000cf;
|
||||
*(vu32 *)0x10400518 = 0x000000d1;
|
||||
*(vu32 *)0x1040051c = 0x01c501c1;
|
||||
*(vu32 *)0x10400520 = 0x00010000;
|
||||
*(vu32 *)0x10400524 = 0x0000019d;
|
||||
*(vu32 *)0x10400528 = 0x00000052;
|
||||
*(vu32 *)0x1040052c = 0x00000192;
|
||||
*(vu32 *)0x10400530 = 0x00000192;
|
||||
*(vu32 *)0x10400534 = 0x0000004f;
|
||||
*(vu32 *)0x10400538 = 0x00000050;
|
||||
*(vu32 *)0x1040053c = 0x00000052;
|
||||
*(vu32 *)0x10400540 = 0x01980194;
|
||||
*(vu32 *)0x10400544 = 0x00000000;
|
||||
*(vu32 *)0x10400548 = 0x00000011;
|
||||
*(vu32 *)0x1040055C = 0x00f00140;
|
||||
*(vu32 *)0x10400560 = 0x01c100d1;
|
||||
*(vu32 *)0x10400564 = 0x01920052;
|
||||
*(vu32 *)0x10400568 = 0x18300000 + 0x46500;
|
||||
*(vu32 *)0x10400570 = 0x80301;
|
||||
*(vu32 *)0x10400574 = 0x00010501;
|
||||
*(vu32 *)0x10400578 = 0;
|
||||
*(vu32 *)0x10400590 = 0x000002D0;
|
||||
*(vu32 *)0x1040059C = 0x00000000;
|
||||
|
||||
// Disco register
|
||||
for(u32 i = 0; i < 256; i++)
|
||||
*(vu32 *)0x10400584 = 0x10101 * i;
|
||||
|
||||
*(vu32 *)0x10400468 = 0x18300000;
|
||||
*(vu32 *)0x1040046c = 0x18300000;
|
||||
*(vu32 *)0x10400494 = 0x18300000;
|
||||
*(vu32 *)0x10400498 = 0x18300000;
|
||||
*(vu32 *)0x10400568 = 0x18346500;
|
||||
*(vu32 *)0x1040056c = 0x18346500;
|
||||
|
||||
//Set CakeBrah framebuffers
|
||||
*((vu32 *)0x23FFFE00) = 0x18300000;
|
||||
*((vu32 *)0x23FFFE04) = 0x18300000;
|
||||
*((vu32 *)0x23FFFE08) = 0x18346500;
|
||||
|
||||
//Clear ARM11 entry offset
|
||||
*arm11 = 0;
|
||||
|
||||
//Wait for the entry to be set
|
||||
while(!*arm11);
|
||||
|
||||
//Jump to it
|
||||
((void (*)())*arm11)();
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
.section .text.start
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
@ Disable interrupts
|
||||
CPSID aif
|
||||
|
||||
b main
|
||||
|
||||
.word 0
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* types.h
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
*/
|
||||
|
||||
#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;
|
||||
161
source/3dsheaders.h
Normal file
161
source/3dsheaders.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Adapted from 3DBrew and https://github.com/mid-kid/CakesForeveryWan/blob/master/source/headers.h
|
||||
*/
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u32 address;
|
||||
u32 phyRegionSize;
|
||||
u32 size;
|
||||
} CodeSetInfo;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u32 saveDataSize[2];
|
||||
u32 jumpID[2];
|
||||
u8 reserved[0x30];
|
||||
} SystemInfo;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
char appTitle[8];
|
||||
u8 reserved1[5];
|
||||
u8 flag;
|
||||
u8 remasterVersion[2];
|
||||
CodeSetInfo textCodeSet;
|
||||
u32 stackSize;
|
||||
CodeSetInfo roCodeSet;
|
||||
u8 reserved2[4];
|
||||
CodeSetInfo dataCodeSet;
|
||||
u32 bssSize;
|
||||
char depends[0x180];
|
||||
SystemInfo systemInfo;
|
||||
} SystemControlInfo;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
SystemControlInfo systemControlInfo;
|
||||
u8 aci[0x200];
|
||||
u8 accessDescSig[0x100];
|
||||
u8 ncchPubKey[0x100];
|
||||
u8 aciLim[0x200];
|
||||
} ExHeader;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u8 sig[0x100]; //RSA-2048 signature of the NCCH header, using SHA-256
|
||||
char magic[4]; //NCCH
|
||||
u32 contentSize; //Media unit
|
||||
u8 partitionId[8];
|
||||
u8 makerCode[2];
|
||||
u16 version;
|
||||
u8 reserved1[4];
|
||||
u8 programID[8];
|
||||
u8 reserved2[0x10];
|
||||
u8 logoHash[0x20]; //Logo Region SHA-256 hash
|
||||
char productCode[0x10];
|
||||
u8 exHeaderHash[0x20]; //Extended header SHA-256 hash
|
||||
u32 exHeaderSize; //Extended header size
|
||||
u32 reserved3;
|
||||
u8 flags[8];
|
||||
u32 plainOffset; //Media unit
|
||||
u32 plainSize; //Media unit
|
||||
u32 logoOffset; //Media unit
|
||||
u32 logoSize; //Media unit
|
||||
u32 exeFsOffset; //Media unit
|
||||
u32 exeFsSize; //Media unit
|
||||
u32 exeFsHashSize; //Media unit
|
||||
u32 reserved4;
|
||||
u32 romFsOffset; //Media unit
|
||||
u32 romFsSize; //Media unit
|
||||
u32 romFsHashSize; //Media unit
|
||||
u32 reserved5;
|
||||
u8 exeFsHash[0x20]; //ExeFS superblock SHA-256 hash
|
||||
u8 romFsHash[0x20]; //RomFS superblock SHA-256 hash
|
||||
} Ncch;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
Ncch ncch;
|
||||
ExHeader exHeader;
|
||||
} Cxi;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
char sigIssuer[0x40];
|
||||
u8 eccPubKey[0x3C];
|
||||
u8 version;
|
||||
u8 caCrlVersion;
|
||||
u8 signerCrlVersion;
|
||||
u8 titleKey[0x10];
|
||||
u8 reserved1;
|
||||
u8 ticketId[8];
|
||||
u8 consoleId[4];
|
||||
u8 titleId[8];
|
||||
u8 reserved2[2];
|
||||
u16 ticketTitleVersion;
|
||||
u8 reserved3[8];
|
||||
u8 licenseType;
|
||||
u8 ticketCommonKeyYIndex; //Ticket common keyY index, usually 0x1 for retail system titles.
|
||||
u8 reserved4[0x2A];
|
||||
u8 unk[4]; //eShop Account ID?
|
||||
u8 reserved5;
|
||||
u8 audit;
|
||||
u8 reserved6[0x42];
|
||||
u8 limits[0x40];
|
||||
u8 contentIndex[0xAC];
|
||||
} Ticket;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u32 offset;
|
||||
u8 *address;
|
||||
u32 size;
|
||||
u32 procType;
|
||||
u8 hash[0x20];
|
||||
} FirmSection;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u32 magic;
|
||||
u32 reserved1;
|
||||
u8 *arm11Entry;
|
||||
u8 *arm9Entry;
|
||||
u8 reserved2[0x30];
|
||||
FirmSection section[4];
|
||||
} Firm;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u8 keyX[0x10];
|
||||
u8 keyY[0x10];
|
||||
u8 ctr[0x10];
|
||||
char size[8];
|
||||
u8 reserved[8];
|
||||
u8 ctlBlock[0x10];
|
||||
char magic[4];
|
||||
u8 reserved2[0xC];
|
||||
u8 slot0x16keyX[0x10];
|
||||
} Arm9Bin;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user