├── .gitignore ├── LICENSE.txt ├── Makefile ├── README.md ├── hashGenerator.c ├── payload_stage1 ├── Makefile ├── linker.ld └── source │ ├── cache.h │ ├── cache.s │ ├── delay.h │ ├── delay.s │ ├── main.c │ ├── sdmmc.c │ ├── sdmmc.h │ ├── start.s │ └── types.h └── payload_stage2 ├── Makefile ├── arm11 ├── Makefile ├── linker.ld └── source │ ├── main.c │ ├── start.s │ └── types.h ├── linker.ld └── source ├── cache.h ├── cache.s ├── crypto.c ├── crypto.h ├── fatfs ├── 00history.txt ├── 00readme.txt ├── diskio.c ├── diskio.h ├── ff.c ├── ff.h ├── ffconf.h ├── integer.h ├── option │ └── ccsbcs.c └── sdmmc │ ├── delay.h │ ├── delay.s │ ├── sdmmc.c │ └── sdmmc.h ├── fs.c ├── fs.h ├── i2c.c ├── i2c.h ├── main.c ├── memory.c ├── memory.h ├── start.s └── types.h /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | hashGenerator 3 | hashGenerator.exe 4 | payload_stage1/build 5 | payload_stage2/build 6 | payload_stage2/arm11/build 7 | *.elf 8 | *.bin 9 | *.o 10 | *.d -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | dir_out := out 2 | 3 | all: $(dir_out) hashGenerator stage1 stage2 4 | 5 | $(dir_out): 6 | @mkdir -p $(dir_out) 7 | 8 | .PHONY: hashGenerator 9 | hashGenerator: 10 | @cc hashGenerator.c -o hashGenerator 11 | 12 | .PHONY: stage1 13 | stage1: $(dir_out) hashGenerator 14 | @$(MAKE) -C payload_stage1 15 | @./hashGenerator $(dir_out)/payload_stage1.bin 16 | 17 | .PHONY: stage2 18 | stage2: $(dir_out) hashGenerator 19 | @$(MAKE) -C payload_stage2 20 | @./hashGenerator $(dir_out)/payload_stage2.bin 21 | 22 | clean: 23 | @$(MAKE) -C payload_stage1 clean 24 | @$(MAKE) -C payload_stage2 clean 25 | @rm -rf $(dir_out) hashGenerator hashGenerator.exe 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # arm9loaderhax for 3DS 2 | 3 | ## What this is 4 | 5 | This is a fork of delebile's A9LH implementation, this exploit is documented [here](http://3dbrew.org/wiki/3DS_System_Flaws) and also presented [in this conference](https://media.ccc.de/v/32c3-7240-console_hacking), and provides ARM9 code execution directly at boot, exploiting a vulnerability present in the 9.6+ version of the New3DS arm9loader. 6 | The exploit was found by **plutoo** and **yellows8**. 7 | 8 | ## Usage 9 | 10 | It loads an **arm9loaderhax.bin** (does not init the screens) or **arm9loaderhax_si.bin** (inits the screens) ARM9 payload from the root of the SD card or CTRNAND at address 0x23F00000. 11 | This means that it offers a BRAHMA-like setup, and as such has compatibility with every payload BRAHMA can run. 12 | You can also run code on the ARM11 by writing its memory address to 0x1FFFFFF8. 13 | 14 | ## Installation 15 | 16 | This fork is specifically meant to work with [Safe A9LH installer](https://github.com/AuroraWright/SafeA9LHInstaller). 17 | 18 | ## Setup 19 | 20 | Compilation needs devkitARM r45. 21 | 22 | ## Credits 23 | 24 | Copyright 2016, Jason Dellaluce/Aurora Wright 25 | 26 | * Normmatt for sdmmc.c and .h, and also for .ld files and the log from 3dmoo9 that provided some of the information needed to get screen init 27 | * Christophe Devine for the SHA code 28 | * Archshift for i2c.c and .h 29 | * Megazig for crypto.c and .h 30 | * Patois for original BRAHMA code 31 | * Smealum, Derrek, Plutoo for publishing the exploit 32 | * Yellows8 and Plutoo as the for discovering it 33 | * bilis/b1l1s and dark_samus for the screen init code, and for fixing shutdown when no SD is inserted 34 | * TuxSH for the screen clearing code and caches code (from Luma3DS) 35 | * [3dbrew community](http://3dbrew.org/) 36 | 37 | ## Licensing 38 | 39 | This code is licensed under GPLv2 or any later version, refer to the included LICENSE.txt file. -------------------------------------------------------------------------------- /hashGenerator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | typedef uint8_t u8; 7 | typedef uint32_t u32; 8 | 9 | /**************************************************************** 10 | * SHA-256 lib 11 | * by Brad Conte (https://github.com/B-Con/crypto-algorithms) 12 | ****************************************************************/ 13 | 14 | typedef struct { 15 | u8 data[64]; 16 | u32 datalen; 17 | unsigned long long bitlen; 18 | u32 state[8]; 19 | } SHA256_CTX; 20 | 21 | #define SHA256_BLOCK_SIZE 32 //SHA256 outputs a 32 byte digest 22 | 23 | #define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b)))) 24 | #define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b)))) 25 | 26 | #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) 27 | #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 28 | #define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) 29 | #define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) 30 | #define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) 31 | #define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) 32 | 33 | static const u32 k[64] = { 34 | 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, 35 | 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, 36 | 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, 37 | 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, 38 | 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, 39 | 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, 40 | 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, 41 | 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 42 | }; 43 | 44 | static void sha256_transform(SHA256_CTX *ctx, const u8 data[]) 45 | { 46 | u32 a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; 47 | 48 | for(i = 0, j = 0; i < 16; ++i, j += 4) 49 | m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); 50 | for(; i < 64; ++i) 51 | m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; 52 | 53 | a = ctx->state[0]; 54 | b = ctx->state[1]; 55 | c = ctx->state[2]; 56 | d = ctx->state[3]; 57 | e = ctx->state[4]; 58 | f = ctx->state[5]; 59 | g = ctx->state[6]; 60 | h = ctx->state[7]; 61 | 62 | for(i = 0; i < 64; ++i) 63 | { 64 | t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; 65 | t2 = EP0(a) + MAJ(a,b,c); 66 | h = g; 67 | g = f; 68 | f = e; 69 | e = d + t1; 70 | d = c; 71 | c = b; 72 | b = a; 73 | a = t1 + t2; 74 | } 75 | 76 | ctx->state[0] += a; 77 | ctx->state[1] += b; 78 | ctx->state[2] += c; 79 | ctx->state[3] += d; 80 | ctx->state[4] += e; 81 | ctx->state[5] += f; 82 | ctx->state[6] += g; 83 | ctx->state[7] += h; 84 | } 85 | 86 | static void sha256_init(SHA256_CTX *ctx) 87 | { 88 | ctx->datalen = 0; 89 | ctx->bitlen = 0; 90 | ctx->state[0] = 0x6a09e667; 91 | ctx->state[1] = 0xbb67ae85; 92 | ctx->state[2] = 0x3c6ef372; 93 | ctx->state[3] = 0xa54ff53a; 94 | ctx->state[4] = 0x510e527f; 95 | ctx->state[5] = 0x9b05688c; 96 | ctx->state[6] = 0x1f83d9ab; 97 | ctx->state[7] = 0x5be0cd19; 98 | } 99 | 100 | static void sha256_update(SHA256_CTX *ctx, const u8 data[], size_t len) 101 | { 102 | u32 i; 103 | 104 | for(i = 0; i < len; ++i) 105 | { 106 | ctx->data[ctx->datalen] = data[i]; 107 | ctx->datalen++; 108 | if(ctx->datalen == 64) 109 | { 110 | sha256_transform(ctx, ctx->data); 111 | ctx->bitlen += 512; 112 | ctx->datalen = 0; 113 | } 114 | } 115 | } 116 | 117 | static void sha256_final(SHA256_CTX *ctx, u8 hash[]) 118 | { 119 | u32 i; 120 | 121 | i = ctx->datalen; 122 | 123 | //Pad whatever data is left in the buffer. 124 | if(ctx->datalen < 56) 125 | { 126 | ctx->data[i++] = 0x80; 127 | while(i < 56) 128 | ctx->data[i++] = 0x00; 129 | } 130 | else 131 | { 132 | ctx->data[i++] = 0x80; 133 | while(i < 64) 134 | ctx->data[i++] = 0x00; 135 | sha256_transform(ctx, ctx->data); 136 | memset(ctx->data, 0, 56); 137 | } 138 | 139 | //Append to the padding the total message's length in bits and transform. 140 | ctx->bitlen += ctx->datalen * 8; 141 | ctx->data[63] = ctx->bitlen; 142 | ctx->data[62] = ctx->bitlen >> 8; 143 | ctx->data[61] = ctx->bitlen >> 16; 144 | ctx->data[60] = ctx->bitlen >> 24; 145 | ctx->data[59] = ctx->bitlen >> 32; 146 | ctx->data[58] = ctx->bitlen >> 40; 147 | ctx->data[57] = ctx->bitlen >> 48; 148 | ctx->data[56] = ctx->bitlen >> 56; 149 | sha256_transform(ctx, ctx->data); 150 | 151 | //Since this implementation uses little endian byte ordering and SHA uses big endian, 152 | //reverse all the bytes when copying the final state to the output hash. 153 | for(i = 0; i < 4; ++i) 154 | { 155 | hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; 156 | hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; 157 | hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; 158 | hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; 159 | hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; 160 | hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; 161 | hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; 162 | hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; 163 | } 164 | } 165 | 166 | /*****************************************************************/ 167 | 168 | static long int fsize(FILE *fp) 169 | { 170 | fseek(fp, 0, SEEK_END); 171 | long int size = ftell(fp); 172 | rewind(fp); 173 | 174 | return size; 175 | } 176 | 177 | int main(int argc, char **argv) 178 | { 179 | if(argc == 1) 180 | { 181 | printf("Usage: %s \n", argv[0]); 182 | exit(0); 183 | } 184 | 185 | FILE *payloadFile, 186 | *hashFile; 187 | size_t payloadSize; 188 | u8 hash[SHA256_BLOCK_SIZE]; 189 | 190 | payloadFile = fopen(argv[1], "rb"); 191 | if(payloadFile == NULL) 192 | { 193 | printf("The input payload doesn't exist\n"); 194 | exit(0); 195 | } 196 | 197 | payloadSize = fsize(payloadFile); 198 | if(payloadSize > 0x89A00) 199 | { 200 | fclose(payloadFile); 201 | printf("The input payload is too large\n"); 202 | exit(0); 203 | } 204 | 205 | u8 *payloadBuffer = (u8 *)malloc(payloadSize); 206 | fread(payloadBuffer, 1, payloadSize, payloadFile); 207 | 208 | SHA256_CTX ctx; 209 | sha256_init(&ctx); 210 | sha256_update(&ctx, payloadBuffer, payloadSize); 211 | sha256_final(&ctx, hash); 212 | 213 | free(payloadBuffer); 214 | fclose(payloadFile); 215 | 216 | char *nameBuffer = (char *)calloc(1, strlen(argv[1]) + 5); 217 | strcat(nameBuffer, argv[1]); 218 | strcat(nameBuffer, ".sha"); 219 | 220 | hashFile = fopen(nameBuffer, "wb"); 221 | fwrite(hash, 1, sizeof(hash), hashFile); 222 | fclose(hashFile); 223 | free(nameBuffer); 224 | 225 | printf("Generated hash file for %s\n", argv[1]); 226 | 227 | exit(0); 228 | } -------------------------------------------------------------------------------- /payload_stage1/Makefile: -------------------------------------------------------------------------------- 1 | rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) 2 | 3 | ifeq ($(strip $(DEVKITARM)),) 4 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 5 | endif 6 | 7 | include $(DEVKITARM)/base_tools 8 | 9 | name := $(shell basename $(CURDIR)) 10 | 11 | dir_source := source 12 | dir_build := build 13 | dir_out := ../out 14 | 15 | ASFLAGS := -mcpu=arm946e-s 16 | CFLAGS := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math 17 | LDFLAGS := -nostdlib 18 | 19 | objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ 20 | $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ 21 | $(call rwildcard, $(dir_source), *.s *.c))) 22 | 23 | .PHONY: all 24 | all: $(dir_out)/$(name).bin 25 | 26 | .PHONY: clean 27 | clean: 28 | @rm -rf $(dir_build) 29 | 30 | $(dir_out)/$(name).bin: $(dir_build)/$(name).elf 31 | $(OBJCOPY) -S -O binary $< $@ 32 | 33 | $(dir_build)/$(name).elf: $(objects) 34 | $(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^ 35 | 36 | $(dir_build)/%.o: $(dir_source)/%.c 37 | @mkdir -p "$(@D)" 38 | $(COMPILE.c) $(OUTPUT_OPTION) $< 39 | 40 | $(dir_build)/%.o: $(dir_source)/%.s 41 | @mkdir -p "$(@D)" 42 | $(COMPILE.s) $(OUTPUT_OPTION) $< 43 | -------------------------------------------------------------------------------- /payload_stage1/linker.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | 4 | ENTRY(_start) 5 | SECTIONS 6 | { 7 | . = 0x0808FB90; 8 | 9 | .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } 10 | .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } 11 | .data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); } 12 | 13 | . = ALIGN(4); 14 | } 15 | -------------------------------------------------------------------------------- /payload_stage1/source/cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Luma3DS 3 | * Copyright (C) 2016 Aurora Wright, TuxSH 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified 19 | * reasonable legal notices or author attributions in that material or in the Appropriate Legal 20 | * Notices displayed by works containing it. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "types.h" 26 | 27 | void flushCaches(void); -------------------------------------------------------------------------------- /payload_stage1/source/cache.s: -------------------------------------------------------------------------------- 1 | @ This file is part of Luma3DS 2 | @ Copyright (C) 2016 Aurora Wright, TuxSH 3 | @ 4 | @ This program is free software: you can redistribute it and/or modify 5 | @ it under the terms of the GNU General Public License as published by 6 | @ the Free Software Foundation, either version 3 of the License, or 7 | @ (at your option) any later version. 8 | @ 9 | @ This program is distributed in the hope that it will be useful, 10 | @ but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | @ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | @ GNU General Public License for more details. 13 | @ 14 | @ You should have received a copy of the GNU General Public License 15 | @ along with this program. If not, see . 16 | @ 17 | @ Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified 18 | @ reasonable legal notices or author attributions in that material or in the Appropriate Legal 19 | @ Notices displayed by works containing it. 20 | 21 | .text 22 | .arm 23 | .align 4 24 | 25 | .global flushCaches 26 | .type flushCaches, %function 27 | flushCaches: 28 | @ Clean and flush data cache 29 | @ Adpated from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html , 30 | @ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well 31 | @ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has) 32 | @ Implemented in bootROM at address 0xffff0830 33 | 34 | mov r1, #0 @ segment counter 35 | outer_loop: 36 | mov r0, #0 @ line counter 37 | 38 | inner_loop: 39 | orr r2, r1, r0 @ generate segment and line address 40 | mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line 41 | add r0, #0x20 @ increment to next line 42 | cmp r0, #0x400 43 | bne inner_loop 44 | 45 | add r1, #0x40000000 46 | cmp r1, #0 47 | bne outer_loop 48 | 49 | mcr p15, 0, r1, c7, c10, 4 @ drain write buffer 50 | 51 | @ Flush instruction cache 52 | mcr p15, 0, r1, c7, c5, 0 53 | 54 | bx lr 55 | -------------------------------------------------------------------------------- /payload_stage1/source/delay.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | void waitcycles(u32 us); 6 | -------------------------------------------------------------------------------- /payload_stage1/source/delay.s: -------------------------------------------------------------------------------- 1 | .text 2 | .arm 3 | .align 4 4 | 5 | .global waitcycles 6 | .type waitcycles, %function 7 | waitcycles: 8 | push {r0-r2, lr} 9 | str r0, [sp, #4] 10 | waitcycles_loop: 11 | ldr r3, [sp, #4] 12 | subs r2, r3, #1 13 | str r2, [sp, #4] 14 | cmp r3, #0 15 | bne waitcycles_loop 16 | pop {r0-r2, pc} 17 | -------------------------------------------------------------------------------- /payload_stage1/source/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | */ 4 | 5 | #include "types.h" 6 | #include "sdmmc.h" 7 | #include "cache.h" 8 | 9 | void main(void) 10 | { 11 | //Initialize sdcard and nand 12 | sdmmc_sdcard_init(); 13 | 14 | sdmmc_nand_readsectors(0x5C000, 22, (u8 *)0x08006000); 15 | 16 | flushCaches(); 17 | 18 | //Jump to secondary payload 19 | ((void (*)())0x08006000)(); 20 | } -------------------------------------------------------------------------------- /payload_stage1/source/sdmmc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2014-2015, Normmatt 7 | * 8 | * Alternatively, the contents of this file may be used under the terms 9 | * of the GNU General Public License Version 2, as described below: 10 | * 11 | * This file is free software: you may copy, redistribute and/or modify 12 | * it under the terms of the GNU General Public License as published by the 13 | * Free Software Foundation, either version 2 of the License, or (at your 14 | * option) any later version. 15 | * 16 | * This file is distributed in the hope that it will be useful, but 17 | * WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 19 | * Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see http://www.gnu.org/licenses/. 23 | */ 24 | 25 | #include "sdmmc.h" 26 | #include "delay.h" 27 | 28 | static struct mmcdevice handleNAND; 29 | //static struct mmcdevice handleSD; 30 | 31 | static inline u16 sdmmc_read16(u16 reg) 32 | { 33 | return *(vu16 *)(SDMMC_BASE + reg); 34 | } 35 | 36 | static inline void sdmmc_write16(u16 reg, u16 val) 37 | { 38 | *(vu16 *)(SDMMC_BASE + reg) = val; 39 | } 40 | 41 | static inline u32 sdmmc_read32(u16 reg) 42 | { 43 | return *(vu32 *)(SDMMC_BASE + reg); 44 | } 45 | 46 | static inline void sdmmc_write32(u16 reg, u32 val) 47 | { 48 | *(vu32 *)(SDMMC_BASE + reg) = val; 49 | } 50 | 51 | static inline void sdmmc_mask16(u16 reg, const u16 clear, const u16 set) 52 | { 53 | u16 val = sdmmc_read16(reg); 54 | val &= ~clear; 55 | val |= set; 56 | sdmmc_write16(reg, val); 57 | } 58 | 59 | static inline void setckl(u32 data) 60 | { 61 | sdmmc_mask16(REG_SDCLKCTL, 0x100, 0); 62 | sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF); 63 | sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100); 64 | } 65 | 66 | /* 67 | mmcdevice *getMMCDevice(int drive) 68 | { 69 | if(drive == 0) return &handleNAND; 70 | return &handleSD; 71 | } 72 | */ 73 | 74 | static int geterror(struct mmcdevice *ctx) 75 | { 76 | return (int)((ctx->error << 29) >> 31); 77 | } 78 | 79 | static void inittarget(struct mmcdevice *ctx) 80 | { 81 | sdmmc_mask16(REG_SDPORTSEL, 0x3, (u16)ctx->devicenumber); 82 | setckl(ctx->clk); 83 | if(ctx->SDOPT == 0) sdmmc_mask16(REG_SDOPT, 0, 0x8000); 84 | else sdmmc_mask16(REG_SDOPT, 0x8000, 0); 85 | } 86 | 87 | static void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args) 88 | { 89 | u32 getSDRESP = (cmd << 15) >> 31; 90 | u16 flags = (cmd << 15) >> 31; 91 | const int readdata = cmd & 0x20000; 92 | const int writedata = cmd & 0x40000; 93 | 94 | if(readdata || writedata) 95 | flags |= TMIO_STAT0_DATAEND; 96 | 97 | ctx->error = 0; 98 | while((sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY)); //mmc working? 99 | sdmmc_write16(REG_SDIRMASK0, 0); 100 | sdmmc_write16(REG_SDIRMASK1, 0); 101 | sdmmc_write16(REG_SDSTATUS0, 0); 102 | sdmmc_write16(REG_SDSTATUS1, 0); 103 | sdmmc_mask16(REG_DATACTL32, 0x1800, 0); 104 | sdmmc_write16(REG_SDCMDARG0, args & 0xFFFF); 105 | sdmmc_write16(REG_SDCMDARG1, args >> 16); 106 | sdmmc_write16(REG_SDCMD, cmd & 0xFFFF); 107 | 108 | u32 size = ctx->size; 109 | u8 *rDataPtr = ctx->rData; 110 | const u8 *tDataPtr = ctx->tData; 111 | 112 | bool rUseBuf = rDataPtr != NULL; 113 | bool tUseBuf = tDataPtr != NULL; 114 | 115 | u16 status0 = 0; 116 | while(true) 117 | { 118 | vu16 status1 = sdmmc_read16(REG_SDSTATUS1); 119 | vu16 ctl32 = sdmmc_read16(REG_DATACTL32); 120 | if((ctl32 & 0x100)) 121 | { 122 | if(readdata) 123 | { 124 | if(rUseBuf) 125 | { 126 | sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0); 127 | if(size > 0x1FF) 128 | { 129 | //Gabriel Marcano: This implementation doesn't assume alignment. 130 | //I've removed the alignment check doen with former rUseBuf32 as a result 131 | for(int i = 0; i < 0x200; i += 4) 132 | { 133 | u32 data = sdmmc_read32(REG_SDFIFO32); 134 | *rDataPtr++ = data; 135 | *rDataPtr++ = data >> 8; 136 | *rDataPtr++ = data >> 16; 137 | *rDataPtr++ = data >> 24; 138 | } 139 | size -= 0x200; 140 | } 141 | } 142 | 143 | sdmmc_mask16(REG_DATACTL32, 0x800, 0); 144 | } 145 | } 146 | if(!(ctl32 & 0x200)) 147 | { 148 | if(writedata) 149 | { 150 | if(tUseBuf) 151 | { 152 | sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0); 153 | if(size > 0x1FF) 154 | { 155 | for(int i = 0; i < 0x200; i += 4) 156 | { 157 | u32 data = *tDataPtr++; 158 | data |= (u32)*tDataPtr++ << 8; 159 | data |= (u32)*tDataPtr++ << 16; 160 | data |= (u32)*tDataPtr++ << 24; 161 | sdmmc_write32(REG_SDFIFO32, data); 162 | } 163 | size -= 0x200; 164 | } 165 | } 166 | 167 | sdmmc_mask16(REG_DATACTL32, 0x1000, 0); 168 | } 169 | } 170 | if(status1 & TMIO_MASK_GW) 171 | { 172 | ctx->error |= 4; 173 | break; 174 | } 175 | 176 | if(!(status1 & TMIO_STAT1_CMD_BUSY)) 177 | { 178 | status0 = sdmmc_read16(REG_SDSTATUS0); 179 | if(sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND) 180 | { 181 | ctx->error |= 0x1; 182 | } 183 | if(status0 & TMIO_STAT0_DATAEND) 184 | { 185 | ctx->error |= 0x2; 186 | } 187 | 188 | if((status0 & flags) == flags) 189 | break; 190 | } 191 | } 192 | ctx->stat0 = sdmmc_read16(REG_SDSTATUS0); 193 | ctx->stat1 = sdmmc_read16(REG_SDSTATUS1); 194 | sdmmc_write16(REG_SDSTATUS0, 0); 195 | sdmmc_write16(REG_SDSTATUS1, 0); 196 | 197 | if(getSDRESP != 0) 198 | { 199 | ctx->ret[0] = (u32)(sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16)); 200 | ctx->ret[1] = (u32)(sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16)); 201 | ctx->ret[2] = (u32)(sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16)); 202 | ctx->ret[3] = (u32)(sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16)); 203 | } 204 | } 205 | 206 | /* 207 | int __attribute__((noinline)) sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in) 208 | { 209 | if(handleSD.isSDHC == 0) sector_no <<= 9; 210 | inittarget(&handleSD); 211 | sdmmc_write16(REG_SDSTOP, 0x100); 212 | sdmmc_write16(REG_SDBLKCOUNT32, numsectors); 213 | sdmmc_write16(REG_SDBLKLEN32, 0x200); 214 | sdmmc_write16(REG_SDBLKCOUNT, numsectors); 215 | handleSD.tData = in; 216 | handleSD.size = numsectors << 9; 217 | sdmmc_send_command(&handleSD, 0x52C19, sector_no); 218 | return geterror(&handleSD); 219 | } 220 | */ 221 | 222 | /* 223 | int __attribute__((noinline)) sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out) 224 | { 225 | if(handleSD.isSDHC == 0) sector_no <<= 9; 226 | inittarget(&handleSD); 227 | sdmmc_write16(REG_SDSTOP, 0x100); 228 | sdmmc_write16(REG_SDBLKCOUNT32, numsectors); 229 | sdmmc_write16(REG_SDBLKLEN32, 0x200); 230 | sdmmc_write16(REG_SDBLKCOUNT, numsectors); 231 | handleSD.rData = out; 232 | handleSD.size = numsectors << 9; 233 | sdmmc_send_command(&handleSD, 0x33C12, sector_no); 234 | return geterror(&handleSD); 235 | } 236 | */ 237 | 238 | int __attribute__((noinline)) sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out) 239 | { 240 | if(handleNAND.isSDHC == 0) sector_no <<= 9; 241 | inittarget(&handleNAND); 242 | sdmmc_write16(REG_SDSTOP, 0x100); 243 | sdmmc_write16(REG_SDBLKCOUNT32, numsectors); 244 | sdmmc_write16(REG_SDBLKLEN32, 0x200); 245 | sdmmc_write16(REG_SDBLKCOUNT, numsectors); 246 | handleNAND.rData = out; 247 | handleNAND.size = numsectors << 9; 248 | sdmmc_send_command(&handleNAND, 0x33C12, sector_no); 249 | //inittarget(&handleSD); 250 | return geterror(&handleNAND); 251 | } 252 | 253 | /* 254 | int __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in) //experimental 255 | { 256 | if(handleNAND.isSDHC == 0) sector_no <<= 9; 257 | inittarget(&handleNAND); 258 | sdmmc_write16(REG_SDSTOP, 0x100); 259 | sdmmc_write16(REG_SDBLKCOUNT32, numsectors); 260 | sdmmc_write16(REG_SDBLKLEN32, 0x200); 261 | sdmmc_write16(REG_SDBLKCOUNT, numsectors); 262 | handleNAND.tData = in; 263 | handleNAND.size = numsectors << 9; 264 | sdmmc_send_command(&handleNAND, 0x52C19, sector_no); 265 | inittarget(&handleSD); 266 | return geterror(&handleNAND); 267 | } 268 | */ 269 | 270 | static u32 calcSDSize(u8 *csd, int type) 271 | { 272 | u32 result = 0; 273 | if(type == -1) type = csd[14] >> 6; 274 | switch(type) 275 | { 276 | case 0: 277 | { 278 | u32 block_len = csd[9] & 0xF; 279 | block_len = 1u << block_len; 280 | u32 mult = (u32)((csd[4] >> 7) | ((csd[5] & 3) << 1)); 281 | mult = 1u << (mult + 2); 282 | result = csd[8] & 3; 283 | result = (result << 8) | csd[7]; 284 | result = (result << 2) | (csd[6] >> 6); 285 | result = (result + 1) * mult * block_len / 512; 286 | break; 287 | } 288 | case 1: 289 | result = csd[7] & 0x3F; 290 | result = (result << 8) | csd[6]; 291 | result = (result << 8) | csd[5]; 292 | result = (result + 1) * 1024; 293 | break; 294 | default: 295 | break; //Do nothing otherwise FIXME perhaps return some error? 296 | } 297 | return result; 298 | } 299 | 300 | static void InitSD() 301 | { 302 | *(vu16 *)0x10006100 &= 0xF7FFu; //SDDATACTL32 303 | *(vu16 *)0x10006100 &= 0xEFFFu; //SDDATACTL32 304 | *(vu16 *)0x10006100 |= 0x402u; //SDDATACTL32 305 | *(vu16 *)0x100060D8 = (*(vu16 *)0x100060D8 & 0xFFDD) | 2; 306 | *(vu16 *)0x10006100 &= 0xFFFFu; //SDDATACTL32 307 | *(vu16 *)0x100060D8 &= 0xFFDFu; //SDDATACTL 308 | *(vu16 *)0x10006104 = 512; //SDBLKLEN32 309 | *(vu16 *)0x10006108 = 1; //SDBLKCOUNT32 310 | *(vu16 *)0x100060E0 &= 0xFFFEu; //SDRESET 311 | *(vu16 *)0x100060E0 |= 1u; //SDRESET 312 | *(vu16 *)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0 313 | *(vu16 *)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1 314 | *(vu16 *)0x100060FC |= 0xDBu; //SDCTL_RESERVED7 315 | *(vu16 *)0x100060FE |= 0xDBu; //SDCTL_RESERVED8 316 | *(vu16 *)0x10006002 &= 0xFFFCu; //SDPORTSEL 317 | *(vu16 *)0x10006024 = 0x20; 318 | *(vu16 *)0x10006028 = 0x40EE; 319 | *(vu16 *)0x10006002 &= 0xFFFCu; ////SDPORTSEL 320 | *(vu16 *)0x10006026 = 512; //SDBLKLEN 321 | *(vu16 *)0x10006008 = 0; //SDSTOP 322 | } 323 | 324 | static int Nand_Init() 325 | { 326 | //NAND 327 | handleNAND.isSDHC = 0; 328 | handleNAND.SDOPT = 0; 329 | handleNAND.res = 0; 330 | handleNAND.initarg = 1; 331 | handleNAND.clk = 0x80; 332 | handleNAND.devicenumber = 1; 333 | 334 | inittarget(&handleNAND); 335 | waitcycles(0xF000); 336 | 337 | sdmmc_send_command(&handleNAND, 0, 0); 338 | 339 | do 340 | { 341 | do 342 | { 343 | sdmmc_send_command(&handleNAND, 0x10701, 0x100000); 344 | } 345 | while(!(handleNAND.error & 1)); 346 | } 347 | while((handleNAND.ret[0] & 0x80000000) == 0); 348 | 349 | sdmmc_send_command(&handleNAND, 0x10602, 0x0); 350 | if((handleNAND.error & 0x4)) return -1; 351 | 352 | sdmmc_send_command(&handleNAND, 0x10403, handleNAND.initarg << 0x10); 353 | if((handleNAND.error & 0x4)) return -1; 354 | 355 | sdmmc_send_command(&handleNAND, 0x10609, handleNAND.initarg << 0x10); 356 | if((handleNAND.error & 0x4)) return -1; 357 | 358 | handleNAND.total_size = calcSDSize((u8*)&handleNAND.ret[0], 0); 359 | handleNAND.clk = 1; 360 | setckl(1); 361 | 362 | sdmmc_send_command(&handleNAND, 0x10407, handleNAND.initarg << 0x10); 363 | if((handleNAND.error & 0x4)) return -1; 364 | 365 | handleNAND.SDOPT = 1; 366 | 367 | sdmmc_send_command(&handleNAND, 0x10506, 0x3B70100); 368 | if((handleNAND.error & 0x4)) return -1; 369 | 370 | sdmmc_send_command(&handleNAND, 0x10506, 0x3B90100); 371 | if((handleNAND.error & 0x4)) return -1; 372 | 373 | sdmmc_send_command(&handleNAND, 0x1040D, handleNAND.initarg << 0x10); 374 | if((handleNAND.error & 0x4)) return -1; 375 | 376 | sdmmc_send_command(&handleNAND, 0x10410, 0x200); 377 | if((handleNAND.error & 0x4)) return -1; 378 | 379 | handleNAND.clk |= 0x200; 380 | 381 | //inittarget(&handleSD); 382 | 383 | return 0; 384 | } 385 | 386 | /* 387 | static int SD_Init() 388 | { 389 | //SD 390 | handleSD.isSDHC = 0; 391 | handleSD.SDOPT = 0; 392 | handleSD.res = 0; 393 | handleSD.initarg = 0; 394 | handleSD.clk = 0x80; 395 | handleSD.devicenumber = 0; 396 | 397 | inittarget(&handleSD); 398 | 399 | 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 400 | 401 | //If not inserted 402 | if(!(*((vu16 *)(SDMMC_BASE + REG_SDSTATUS0)) & TMIO_STAT0_SIGSTATE)) return 5; 403 | 404 | sdmmc_send_command(&handleSD, 0, 0); 405 | sdmmc_send_command(&handleSD, 0x10408, 0x1AA); 406 | u32 temp = (handleSD.error & 0x1) << 0x1E; 407 | 408 | u32 temp2 = 0; 409 | do 410 | { 411 | do 412 | { 413 | sdmmc_send_command(&handleSD, 0x10437, handleSD.initarg << 0x10); 414 | sdmmc_send_command(&handleSD, 0x10769, 0x00FF8000 | temp); 415 | temp2 = 1; 416 | } 417 | while(!(handleSD.error & 1)); 418 | } 419 | while((handleSD.ret[0] & 0x80000000) == 0); 420 | 421 | if(!((handleSD.ret[0] >> 30) & 1) || !temp) 422 | temp2 = 0; 423 | 424 | handleSD.isSDHC = temp2; 425 | 426 | sdmmc_send_command(&handleSD, 0x10602, 0); 427 | if((handleSD.error & 0x4)) return -1; 428 | 429 | sdmmc_send_command(&handleSD, 0x10403, 0); 430 | if((handleSD.error & 0x4)) return -2; 431 | handleSD.initarg = handleSD.ret[0] >> 0x10; 432 | 433 | sdmmc_send_command(&handleSD, 0x10609, handleSD.initarg << 0x10); 434 | if((handleSD.error & 0x4)) return -3; 435 | 436 | handleSD.total_size = calcSDSize((u8*)&handleSD.ret[0], -1); 437 | handleSD.clk = 1; 438 | setckl(1); 439 | 440 | sdmmc_send_command(&handleSD, 0x10507, handleSD.initarg << 0x10); 441 | if((handleSD.error & 0x4)) return -4; 442 | 443 | sdmmc_send_command(&handleSD, 0x10437, handleSD.initarg << 0x10); 444 | if((handleSD.error & 0x4)) return -5; 445 | 446 | handleSD.SDOPT = 1; 447 | sdmmc_send_command(&handleSD, 0x10446, 0x2); 448 | if((handleSD.error & 0x4)) return -6; 449 | 450 | sdmmc_send_command(&handleSD, 0x1040D, handleSD.initarg << 0x10); 451 | if((handleSD.error & 0x4)) return -7; 452 | 453 | sdmmc_send_command(&handleSD, 0x10410, 0x200); 454 | if((handleSD.error & 0x4)) return -8; 455 | handleSD.clk |= 0x200; 456 | 457 | return 0; 458 | } 459 | */ 460 | 461 | /* 462 | void sdmmc_get_cid(bool isNand, u32 *info) 463 | { 464 | struct mmcdevice *device = isNand ? &handleNAND : &handleSD; 465 | 466 | inittarget(device); 467 | 468 | // use cmd7 to put sd card in standby mode 469 | // CMD7 470 | sdmmc_send_command(device, 0x10507, 0); 471 | 472 | // get sd card info 473 | // use cmd10 to read CID 474 | sdmmc_send_command(device, 0x1060A, device->initarg << 0x10); 475 | 476 | for(int i = 0; i < 4; ++i) 477 | info[i] = device->ret[i]; 478 | 479 | // put sd card back to transfer mode 480 | // CMD7 481 | sdmmc_send_command(device, 0x10507, device->initarg << 0x10); 482 | } 483 | */ 484 | 485 | void sdmmc_sdcard_init() 486 | { 487 | InitSD(); 488 | Nand_Init(); 489 | //SD_Init(); 490 | } -------------------------------------------------------------------------------- /payload_stage1/source/sdmmc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #define SDMMC_BASE 0x10006000 6 | 7 | #define REG_SDCMD 0x00 8 | #define REG_SDPORTSEL 0x02 9 | #define REG_SDCMDARG 0x04 10 | #define REG_SDCMDARG0 0x04 11 | #define REG_SDCMDARG1 0x06 12 | #define REG_SDSTOP 0x08 13 | #define REG_SDBLKCOUNT 0x0A 14 | 15 | #define REG_SDRESP0 0x0C 16 | #define REG_SDRESP1 0x0E 17 | #define REG_SDRESP2 0x10 18 | #define REG_SDRESP3 0x12 19 | #define REG_SDRESP4 0x14 20 | #define REG_SDRESP5 0x16 21 | #define REG_SDRESP6 0x18 22 | #define REG_SDRESP7 0x1A 23 | 24 | #define REG_SDSTATUS0 0x1C 25 | #define REG_SDSTATUS1 0x1E 26 | 27 | #define REG_SDIRMASK0 0x20 28 | #define REG_SDIRMASK1 0x22 29 | #define REG_SDCLKCTL 0x24 30 | 31 | #define REG_SDBLKLEN 0x26 32 | #define REG_SDOPT 0x28 33 | #define REG_SDFIFO 0x30 34 | 35 | #define REG_DATACTL 0xD8 36 | #define REG_SDRESET 0xE0 37 | #define REG_SDPROTECTED 0xF6 //bit 0 determines if sd is protected or not? 38 | 39 | #define REG_DATACTL32 0x100 40 | #define REG_SDBLKLEN32 0x104 41 | #define REG_SDBLKCOUNT32 0x108 42 | #define REG_SDFIFO32 0x10C 43 | 44 | #define REG_CLK_AND_WAIT_CTL 0x138 45 | #define REG_RESET_SDIO 0x1E0 46 | 47 | #define TMIO_STAT0_CMDRESPEND 0x0001 48 | #define TMIO_STAT0_DATAEND 0x0004 49 | #define TMIO_STAT0_CARD_REMOVE 0x0008 50 | #define TMIO_STAT0_CARD_INSERT 0x0010 51 | #define TMIO_STAT0_SIGSTATE 0x0020 52 | #define TMIO_STAT0_WRPROTECT 0x0080 53 | #define TMIO_STAT0_CARD_REMOVE_A 0x0100 54 | #define TMIO_STAT0_CARD_INSERT_A 0x0200 55 | #define TMIO_STAT0_SIGSTATE_A 0x0400 56 | #define TMIO_STAT1_CMD_IDX_ERR 0x0001 57 | #define TMIO_STAT1_CRCFAIL 0x0002 58 | #define TMIO_STAT1_STOPBIT_ERR 0x0004 59 | #define TMIO_STAT1_DATATIMEOUT 0x0008 60 | #define TMIO_STAT1_RXOVERFLOW 0x0010 61 | #define TMIO_STAT1_TXUNDERRUN 0x0020 62 | #define TMIO_STAT1_CMDTIMEOUT 0x0040 63 | #define TMIO_STAT1_RXRDY 0x0100 64 | #define TMIO_STAT1_TXRQ 0x0200 65 | #define TMIO_STAT1_ILL_FUNC 0x2000 66 | #define TMIO_STAT1_CMD_BUSY 0x4000 67 | #define TMIO_STAT1_ILL_ACCESS 0x8000 68 | 69 | #define TMIO_MASK_ALL 0x837F031D 70 | 71 | #define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \ 72 | TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR) 73 | 74 | #define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND) 75 | #define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND) 76 | 77 | typedef struct mmcdevice { 78 | u8 *rData; 79 | const u8 *tData; 80 | u32 size; 81 | u32 error; 82 | u16 stat0; 83 | u16 stat1; 84 | u32 ret[4]; 85 | u32 initarg; 86 | u32 isSDHC; 87 | u32 clk; 88 | u32 SDOPT; 89 | u32 devicenumber; 90 | u32 total_size; //size in sectors of the device 91 | u32 res; 92 | } mmcdevice; 93 | 94 | void sdmmc_sdcard_init(); 95 | //int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out); 96 | //int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in); 97 | int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out); 98 | //int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in); 99 | //void sdmmc_get_cid(bool isNand, u32 *info); 100 | //mmcdevice *getMMCDevice(int drive); -------------------------------------------------------------------------------- /payload_stage1/source/start.s: -------------------------------------------------------------------------------- 1 | .section .text.start 2 | .align 4 3 | .global _start 4 | _start: 5 | @ Disable interrupts 6 | mrs r0, cpsr 7 | orr r0, r0, #0x80 8 | msr cpsr_c, r0 9 | 10 | @ Change the stack pointer 11 | mov sp, #0x27000000 12 | 13 | @ Disable caches / MPU 14 | mrc p15, 0, r0, c1, c0, 0 @ read control register 15 | bic r0, #(1<<12) @ - instruction cache disable 16 | bic r0, #(1<<2) @ - data cache disable 17 | bic r0, #(1<<0) @ - mpu disable 18 | mcr p15, 0, r0, c1, c0, 0 @ write control register 19 | 20 | @ Flush caches 21 | bl flushCaches 22 | 23 | @ Give read/write access to all the memory regions 24 | ldr r0, =0x3333333 25 | mcr p15, 0, r0, c5, c0, 2 @ write data access 26 | mcr p15, 0, r0, c5, c0, 3 @ write instruction access 27 | 28 | @ Set MPU permissions and cache settings 29 | ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part) 30 | ldr r1, =0x01FF801D @ 01ff8000 32k | itcm 31 | ldr r2, =0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS) 32 | ldr r3, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB) 33 | ldr r4, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS) 34 | ldr r5, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram 35 | ldr r6, =0x1800002D @ 18000000 8M | vram (+ 2MB) 36 | mov r7, #0 37 | mov r8, #0x15 38 | mcr p15, 0, r0, c6, c0, 0 39 | mcr p15, 0, r1, c6, c1, 0 40 | mcr p15, 0, r2, c6, c2, 0 41 | mcr p15, 0, r3, c6, c3, 0 42 | mcr p15, 0, r4, c6, c4, 0 43 | mcr p15, 0, r5, c6, c5, 0 44 | mcr p15, 0, r6, c6, c6, 0 45 | mcr p15, 0, r7, c6, c7, 0 46 | mcr p15, 0, r8, c3, c0, 0 @ Write bufferable 0, 2, 4 47 | mcr p15, 0, r8, c2, c0, 0 @ Data cacheable 0, 2, 4 48 | mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 2, 4 49 | 50 | @ Enable caches / MPU 51 | mrc p15, 0, r0, c1, c0, 0 @ read control register 52 | orr r0, r0, #(1<<12) @ - instruction cache enable 53 | orr r0, r0, #(1<<2) @ - data cache enable 54 | orr r0, r0, #(1<<0) @ - mpu enable 55 | mcr p15, 0, r0, c1, c0, 0 @ write control register 56 | 57 | @ Fix mounting of SDMC 58 | ldr r0, =0x10000020 59 | mov r1, #0x340 60 | str r1, [r0] 61 | 62 | b main 63 | -------------------------------------------------------------------------------- /payload_stage1/source/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * types.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | //Common data types 12 | typedef uint8_t u8; 13 | typedef uint16_t u16; 14 | typedef uint32_t u32; 15 | typedef uint64_t u64; 16 | typedef volatile u8 vu8; 17 | typedef volatile u16 vu16; 18 | typedef volatile u32 vu32; 19 | typedef volatile u64 vu64; -------------------------------------------------------------------------------- /payload_stage2/Makefile: -------------------------------------------------------------------------------- 1 | rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) 2 | 3 | ifeq ($(strip $(DEVKITARM)),) 4 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 5 | endif 6 | 7 | include $(DEVKITARM)/base_tools 8 | 9 | name := $(shell basename $(CURDIR)) 10 | 11 | dir_source := source 12 | dir_arm11 := arm11 13 | dir_build := build 14 | dir_out := ../out 15 | 16 | ASFLAGS := -mcpu=arm946e-s 17 | CFLAGS := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math 18 | LDFLAGS := -nostartfiles 19 | 20 | objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ 21 | $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ 22 | $(call rwildcard, $(dir_source), *.s *.c))) 23 | 24 | bundled = $(dir_build)/arm11.bin.o 25 | 26 | define bin2o 27 | bin2s $< | $(AS) -o $(@) 28 | endef 29 | 30 | .PHONY: all 31 | all: $(dir_out)/$(name).bin 32 | 33 | .PHONY: clean 34 | clean: 35 | @$(MAKE) -C $(dir_arm11) clean 36 | @rm -rf $(dir_build) 37 | 38 | $(dir_out)/$(name).bin: $(dir_build)/$(name).elf 39 | $(OBJCOPY) -S -O binary $< $@ 40 | 41 | $(dir_build)/bundled.h: $(bundled) 42 | @$(foreach f, $(bundled),\ 43 | echo "extern const u8" `(echo $(basename $(notdir $(f))) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> $@;\ 44 | echo "extern const u32" `(echo $(basename $(notdir $(f)))| sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> $@;\ 45 | ) 46 | 47 | $(dir_build)/$(name).elf: $(bundled) $(objects) 48 | $(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^ 49 | 50 | $(dir_build)/%.bin.o: $(dir_build)/%.bin 51 | @$(bin2o) 52 | 53 | $(dir_build)/arm11.bin: $(dir_arm11) 54 | @mkdir -p "$(@D)" 55 | @$(MAKE) -C $< 56 | 57 | $(dir_build)/memory.o: CFLAGS += -O3 58 | 59 | $(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/bundled.h 60 | @mkdir -p "$(@D)" 61 | $(COMPILE.c) $(OUTPUT_OPTION) $< 62 | 63 | $(dir_build)/%.o: $(dir_source)/%.s 64 | @mkdir -p "$(@D)" 65 | $(COMPILE.s) $(OUTPUT_OPTION) $< 66 | -------------------------------------------------------------------------------- /payload_stage2/arm11/Makefile: -------------------------------------------------------------------------------- 1 | rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) 2 | 3 | ifeq ($(strip $(DEVKITARM)),) 4 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 5 | endif 6 | 7 | include $(DEVKITARM)/base_tools 8 | 9 | name := $(shell basename $(CURDIR)) 10 | 11 | dir_source := source 12 | dir_build := build 13 | dir_out := ../$(dir_build) 14 | 15 | ASFLAGS := -mcpu=mpcore -mfloat-abi=hard 16 | CFLAGS := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math 17 | LDFLAGS := -nostdlib 18 | 19 | objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ 20 | $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ 21 | $(call rwildcard, $(dir_source), *.s *.c))) 22 | 23 | .PHONY: all 24 | all: $(dir_out)/$(name).bin 25 | 26 | .PHONY: clean 27 | clean: 28 | @rm -rf $(dir_build) 29 | 30 | $(dir_out)/$(name).bin: $(dir_build)/$(name).elf 31 | $(OBJCOPY) -S -O binary $< $@ 32 | 33 | $(dir_build)/$(name).elf: $(objects) 34 | $(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^ 35 | 36 | $(dir_build)/%.o: $(dir_source)/%.c 37 | @mkdir -p "$(@D)" 38 | $(COMPILE.c) $(OUTPUT_OPTION) $< 39 | 40 | $(dir_build)/%.o: $(dir_source)/%.s 41 | @mkdir -p "$(@D)" 42 | $(COMPILE.s) $(OUTPUT_OPTION) $< 43 | -------------------------------------------------------------------------------- /payload_stage2/arm11/linker.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | 4 | ENTRY(_start) 5 | SECTIONS 6 | { 7 | . = 0x1FFF4C80; 8 | 9 | .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } 10 | .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } 11 | .data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); } 12 | 13 | . = ALIGN(4); 14 | } 15 | -------------------------------------------------------------------------------- /payload_stage2/arm11/source/main.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | 3 | #define BRIGHTNESS 0x39 4 | 5 | extern u32 screenInit; 6 | 7 | void main(void) 8 | { 9 | vu32 *arm11Entry = (vu32 *)0x1FFFFFF8; 10 | 11 | if(screenInit != 0) 12 | { 13 | *(vu32 *)0x10141200 = 0x1007F; 14 | *(vu32 *)0x10202014 = 0x00000001; 15 | *(vu32 *)0x1020200C &= 0xFFFEFFFE; 16 | 17 | *(vu32 *)0x10202240 = BRIGHTNESS; 18 | *(vu32 *)0x10202A40 = BRIGHTNESS; 19 | *(vu32 *)0x10202244 = 0x1023E; 20 | *(vu32 *)0x10202A44 = 0x1023E; 21 | 22 | //Top screen 23 | *(vu32 *)0x10400400 = 0x000001c2; 24 | *(vu32 *)0x10400404 = 0x000000d1; 25 | *(vu32 *)0x10400408 = 0x000001c1; 26 | *(vu32 *)0x1040040c = 0x000001c1; 27 | *(vu32 *)0x10400410 = 0x00000000; 28 | *(vu32 *)0x10400414 = 0x000000cf; 29 | *(vu32 *)0x10400418 = 0x000000d1; 30 | *(vu32 *)0x1040041c = 0x01c501c1; 31 | *(vu32 *)0x10400420 = 0x00010000; 32 | *(vu32 *)0x10400424 = 0x0000019d; 33 | *(vu32 *)0x10400428 = 0x00000002; 34 | *(vu32 *)0x1040042c = 0x00000192; 35 | *(vu32 *)0x10400430 = 0x00000192; 36 | *(vu32 *)0x10400434 = 0x00000192; 37 | *(vu32 *)0x10400438 = 0x00000001; 38 | *(vu32 *)0x1040043c = 0x00000002; 39 | *(vu32 *)0x10400440 = 0x01960192; 40 | *(vu32 *)0x10400444 = 0x00000000; 41 | *(vu32 *)0x10400448 = 0x00000000; 42 | *(vu32 *)0x1040045C = 0x00f00190; 43 | *(vu32 *)0x10400460 = 0x01c100d1; 44 | *(vu32 *)0x10400464 = 0x01920002; 45 | *(vu32 *)0x10400468 = 0x18300000; 46 | *(vu32 *)0x10400470 = 0x80341; 47 | *(vu32 *)0x10400474 = 0x00010501; 48 | *(vu32 *)0x10400478 = 0; 49 | *(vu32 *)0x10400490 = 0x000002D0; 50 | *(vu32 *)0x1040049C = 0x00000000; 51 | 52 | //Disco register 53 | for(u32 i = 0; i < 256; i++) 54 | *(vu32 *)0x10400484 = 0x10101 * i; 55 | 56 | //Bottom screen 57 | *(vu32 *)0x10400500 = 0x000001c2; 58 | *(vu32 *)0x10400504 = 0x000000d1; 59 | *(vu32 *)0x10400508 = 0x000001c1; 60 | *(vu32 *)0x1040050c = 0x000001c1; 61 | *(vu32 *)0x10400510 = 0x000000cd; 62 | *(vu32 *)0x10400514 = 0x000000cf; 63 | *(vu32 *)0x10400518 = 0x000000d1; 64 | *(vu32 *)0x1040051c = 0x01c501c1; 65 | *(vu32 *)0x10400520 = 0x00010000; 66 | *(vu32 *)0x10400524 = 0x0000019d; 67 | *(vu32 *)0x10400528 = 0x00000052; 68 | *(vu32 *)0x1040052c = 0x00000192; 69 | *(vu32 *)0x10400530 = 0x00000192; 70 | *(vu32 *)0x10400534 = 0x0000004f; 71 | *(vu32 *)0x10400538 = 0x00000050; 72 | *(vu32 *)0x1040053c = 0x00000052; 73 | *(vu32 *)0x10400540 = 0x01980194; 74 | *(vu32 *)0x10400544 = 0x00000000; 75 | *(vu32 *)0x10400548 = 0x00000011; 76 | *(vu32 *)0x1040055C = 0x00f00140; 77 | *(vu32 *)0x10400560 = 0x01c100d1; 78 | *(vu32 *)0x10400564 = 0x01920052; 79 | *(vu32 *)0x10400568 = 0x18300000 + 0x46500; 80 | *(vu32 *)0x10400570 = 0x80301; 81 | *(vu32 *)0x10400574 = 0x00010501; 82 | *(vu32 *)0x10400578 = 0; 83 | *(vu32 *)0x10400590 = 0x000002D0; 84 | *(vu32 *)0x1040059C = 0x00000000; 85 | 86 | //Disco register 87 | for(u32 i = 0; i < 256; i++) 88 | *(vu32 *)0x10400584 = 0x10101 * i; 89 | 90 | //Set CakeBrah framebuffers 91 | fb->top_left = (u8 *)0x18300000; 92 | fb->top_right = (u8 *)0x18300000; 93 | fb->bottom = (u8 *)0x18346500; 94 | 95 | *(vu32 *)0x10400468 = (u32)fb->top_left; 96 | *(vu32 *)0x1040046c = (u32)fb->top_left; 97 | *(vu32 *)0x10400494 = (u32)fb->top_right; 98 | *(vu32 *)0x10400498 = (u32)fb->top_right; 99 | *(vu32 *)0x10400568 = (u32)fb->bottom; 100 | *(vu32 *)0x1040056c = (u32)fb->bottom; 101 | 102 | vu32 *REGs_PSC0 = (vu32 *)0x10400010, 103 | *REGs_PSC1 = (vu32 *)0x10400020; 104 | 105 | REGs_PSC0[0] = (u32)fb->top_left >> 3; //Start address 106 | REGs_PSC0[1] = (u32)(fb->top_left + SCREEN_TOP_FBSIZE) >> 3; //End address 107 | REGs_PSC0[2] = 0; //Fill value 108 | REGs_PSC0[3] = (2 << 8) | 1; //32-bit pattern; start 109 | 110 | REGs_PSC1[0] = (u32)fb->bottom >> 3; //Start address 111 | REGs_PSC1[1] = (u32)(fb->bottom + SCREEN_BOTTOM_FBSIZE) >> 3; //End address 112 | REGs_PSC1[2] = 0; //Fill value 113 | REGs_PSC1[3] = (2 << 8) | 1; //32-bit pattern; start 114 | 115 | while(!((REGs_PSC0[3] & 2) && (REGs_PSC1[3] & 2))); 116 | } 117 | 118 | //Clear ARM11 entrypoint 119 | *arm11Entry = 0; 120 | 121 | //Wait for the entrypoint to be set 122 | while(!*arm11Entry); 123 | 124 | //Jump to it 125 | ((void (*)())*arm11Entry)(); 126 | } -------------------------------------------------------------------------------- /payload_stage2/arm11/source/start.s: -------------------------------------------------------------------------------- 1 | .section .text.start 2 | .align 4 3 | .global _start 4 | _start: 5 | @ Disable interrupts 6 | CPSID aif 7 | 8 | b main 9 | 10 | .global screenInit 11 | screenInit: 12 | .word 0 13 | -------------------------------------------------------------------------------- /payload_stage2/arm11/source/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | //Common data types 6 | typedef uint8_t u8; 7 | typedef uint16_t u16; 8 | typedef uint32_t u32; 9 | typedef uint64_t u64; 10 | typedef volatile u8 vu8; 11 | typedef volatile u16 vu16; 12 | typedef volatile u32 vu32; 13 | typedef volatile u64 vu64; 14 | 15 | #define SCREEN_TOP_WIDTH 400 16 | #define SCREEN_BOTTOM_WIDTH 320 17 | #define SCREEN_HEIGHT 240 18 | #define SCREEN_TOP_FBSIZE (3 * SCREEN_TOP_WIDTH * SCREEN_HEIGHT) 19 | #define SCREEN_BOTTOM_FBSIZE (3 * SCREEN_BOTTOM_WIDTH * SCREEN_HEIGHT) 20 | 21 | static volatile struct fb { 22 | u8 *top_left; 23 | u8 *top_right; 24 | u8 *bottom; 25 | } *const fb = (volatile struct fb *)0x23FFFE00; -------------------------------------------------------------------------------- /payload_stage2/linker.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | 4 | ENTRY(_start) 5 | SECTIONS 6 | { 7 | . = 0x08006000; 8 | 9 | .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } 10 | .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } 11 | .data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); } 12 | 13 | . = ALIGN(4); 14 | } 15 | -------------------------------------------------------------------------------- /payload_stage2/source/cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Luma3DS 3 | * Copyright (C) 2016 Aurora Wright, TuxSH 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified 19 | * reasonable legal notices or author attributions in that material or in the Appropriate Legal 20 | * Notices displayed by works containing it. 21 | */ 22 | 23 | #pragma once 24 | 25 | #include "types.h" 26 | 27 | void flushEntireDCache(void); //actually: "clean and flush" 28 | void flushEntireICache(void); -------------------------------------------------------------------------------- /payload_stage2/source/cache.s: -------------------------------------------------------------------------------- 1 | @ This file is part of Luma3DS 2 | @ Copyright (C) 2016 Aurora Wright, TuxSH 3 | @ 4 | @ This program is free software: you can redistribute it and/or modify 5 | @ it under the terms of the GNU General Public License as published by 6 | @ the Free Software Foundation, either version 3 of the License, or 7 | @ (at your option) any later version. 8 | @ 9 | @ This program is distributed in the hope that it will be useful, 10 | @ but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | @ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | @ GNU General Public License for more details. 13 | @ 14 | @ You should have received a copy of the GNU General Public License 15 | @ along with this program. If not, see . 16 | @ 17 | @ Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified 18 | @ reasonable legal notices or author attributions in that material or in the Appropriate Legal 19 | @ Notices displayed by works containing it. 20 | 21 | .text 22 | .arm 23 | .align 4 24 | 25 | .global flushEntireDCache 26 | .type flushEntireDCache, %function 27 | flushEntireDCache: 28 | @ Adapted from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html, 29 | @ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well 30 | @ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has) 31 | 32 | @ Implemented in bootROM at address 0xffff0830 33 | mov r1, #0 @ segment counter 34 | outer_loop: 35 | mov r0, #0 @ line counter 36 | 37 | inner_loop: 38 | orr r2, r1, r0 @ generate segment and line address 39 | mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line 40 | add r0, #0x20 @ increment to next line 41 | cmp r0, #0x400 42 | bne inner_loop 43 | 44 | add r1, #0x40000000 45 | cmp r1, #0 46 | bne outer_loop 47 | 48 | mcr p15, 0, r1, c7, c10, 4 @ drain write buffer 49 | bx lr 50 | 51 | .global flushEntireICache 52 | .type flushEntireICache, %function 53 | flushEntireICache: 54 | @ Implemented in bootROM at address 0xffff0ab4 55 | mov r0, #0 56 | mcr p15, 0, r0, c7, c5, 0 57 | bx lr 58 | -------------------------------------------------------------------------------- /payload_stage2/source/crypto.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Luma3DS 3 | * Copyright (C) 2016 Aurora Wright, TuxSH 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified 19 | * reasonable legal notices or author attributions in that material or in the Appropriate Legal 20 | * Notices displayed by works containing it. 21 | */ 22 | 23 | /* 24 | * Crypto libs from http://github.com/b1l1s/ctr 25 | * kernel9Loader code originally adapted from https://github.com/Reisyukaku/ReiNand/blob/228c378255ba693133dec6f3368e14d386f2cde7/source/crypto.c#L233 26 | */ 27 | 28 | #include "crypto.h" 29 | #include "memory.h" 30 | #include "fatfs/sdmmc/sdmmc.h" 31 | 32 | /**************************************************************** 33 | * Crypto libs 34 | ****************************************************************/ 35 | 36 | /* original version by megazig */ 37 | 38 | #ifndef __thumb__ 39 | #define BSWAP32(x) {\ 40 | __asm__\ 41 | (\ 42 | "eor r1, %1, %1, ror #16\n\t"\ 43 | "bic r1, r1, #0xFF0000\n\t"\ 44 | "mov %0, %1, ror #8\n\t"\ 45 | "eor %0, %0, r1, lsr #8\n\t"\ 46 | :"=r"(x)\ 47 | :"0"(x)\ 48 | :"r1"\ 49 | );\ 50 | }; 51 | 52 | #define ADD_u128_u32(u128_0, u128_1, u128_2, u128_3, u32_0) {\ 53 | __asm__\ 54 | (\ 55 | "adds %0, %4\n\t"\ 56 | "addcss %1, %1, #1\n\t"\ 57 | "addcss %2, %2, #1\n\t"\ 58 | "addcs %3, %3, #1\n\t"\ 59 | : "+r"(u128_0), "+r"(u128_1), "+r"(u128_2), "+r"(u128_3)\ 60 | : "r"(u32_0)\ 61 | : "cc"\ 62 | );\ 63 | } 64 | #else 65 | #define BSWAP32(x) {x = __builtin_bswap32(x);} 66 | 67 | #define ADD_u128_u32(u128_0, u128_1, u128_2, u128_3, u32_0) {\ 68 | __asm__\ 69 | (\ 70 | "mov r4, #0\n\t"\ 71 | "add %0, %0, %4\n\t"\ 72 | "adc %1, %1, r4\n\t"\ 73 | "adc %2, %2, r4\n\t"\ 74 | "adc %3, %3, r4\n\t"\ 75 | : "+r"(u128_0), "+r"(u128_1), "+r"(u128_2), "+r"(u128_3)\ 76 | : "r"(u32_0)\ 77 | : "cc", "r4"\ 78 | );\ 79 | } 80 | #endif /*__thumb__*/ 81 | 82 | static void aes_setkey(u8 keyslot, const void *key, u32 keyType, u32 mode) 83 | { 84 | if(keyslot <= 0x03) return; //Ignore TWL keys for now 85 | u32 *key32 = (u32 *)key; 86 | *REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode; 87 | *REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | AES_KEYCNT_WRITE; 88 | 89 | REG_AESKEYFIFO[keyType] = key32[0]; 90 | REG_AESKEYFIFO[keyType] = key32[1]; 91 | REG_AESKEYFIFO[keyType] = key32[2]; 92 | REG_AESKEYFIFO[keyType] = key32[3]; 93 | } 94 | 95 | static void aes_use_keyslot(u8 keyslot) 96 | { 97 | if(keyslot > 0x3F) 98 | return; 99 | 100 | *REG_AESKEYSEL = keyslot; 101 | *REG_AESCNT = *REG_AESCNT | 0x04000000; /* mystery bit */ 102 | } 103 | 104 | static void aes_setiv(const void *iv, u32 mode) 105 | { 106 | const u32 *iv32 = (const u32 *)iv; 107 | *REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode; 108 | 109 | //Word order for IV can't be changed in REG_AESCNT and always default to reversed 110 | if(mode & AES_INPUT_NORMAL) 111 | { 112 | REG_AESCTR[0] = iv32[3]; 113 | REG_AESCTR[1] = iv32[2]; 114 | REG_AESCTR[2] = iv32[1]; 115 | REG_AESCTR[3] = iv32[0]; 116 | } 117 | else 118 | { 119 | REG_AESCTR[0] = iv32[0]; 120 | REG_AESCTR[1] = iv32[1]; 121 | REG_AESCTR[2] = iv32[2]; 122 | REG_AESCTR[3] = iv32[3]; 123 | } 124 | } 125 | 126 | static void __attribute__((optimize("O1"))) aes_advctr(void *ctr, u32 val, u32 mode) 127 | { 128 | u32 *ctr32 = (u32 *)ctr; 129 | 130 | int i; 131 | if(mode & AES_INPUT_BE) 132 | { 133 | for(i = 0; i < 4; ++i) //Endian swap 134 | BSWAP32(ctr32[i]); 135 | } 136 | 137 | if(mode & AES_INPUT_NORMAL) 138 | { 139 | ADD_u128_u32(ctr32[3], ctr32[2], ctr32[1], ctr32[0], val); 140 | } 141 | else 142 | { 143 | ADD_u128_u32(ctr32[0], ctr32[1], ctr32[2], ctr32[3], val); 144 | } 145 | 146 | if(mode & AES_INPUT_BE) 147 | { 148 | for(i = 0; i < 4; ++i) //Endian swap 149 | BSWAP32(ctr32[i]); 150 | } 151 | } 152 | 153 | static void aes_change_ctrmode(void *ctr, u32 fromMode, u32 toMode) 154 | { 155 | u32 *ctr32 = (u32 *)ctr; 156 | int i; 157 | if((fromMode ^ toMode) & AES_CNT_INPUT_ENDIAN) 158 | { 159 | for(i = 0; i < 4; ++i) 160 | BSWAP32(ctr32[i]); 161 | } 162 | 163 | if((fromMode ^ toMode) & AES_CNT_INPUT_ORDER) 164 | { 165 | u32 temp = ctr32[0]; 166 | ctr32[0] = ctr32[3]; 167 | ctr32[3] = temp; 168 | 169 | temp = ctr32[1]; 170 | ctr32[1] = ctr32[2]; 171 | ctr32[2] = temp; 172 | } 173 | } 174 | 175 | static void aes_batch(void *dst, const void *src, u32 blockCount) 176 | { 177 | *REG_AESBLKCNT = blockCount << 16; 178 | *REG_AESCNT |= AES_CNT_START; 179 | 180 | const u32 *src32 = (const u32 *)src; 181 | u32 *dst32 = (u32 *)dst; 182 | 183 | u32 wbc = blockCount; 184 | u32 rbc = blockCount; 185 | 186 | while(rbc) 187 | { 188 | if(wbc && ((*REG_AESCNT & 0x1F) <= 0xC)) //There's space for at least 4 ints 189 | { 190 | *REG_AESWRFIFO = *src32++; 191 | *REG_AESWRFIFO = *src32++; 192 | *REG_AESWRFIFO = *src32++; 193 | *REG_AESWRFIFO = *src32++; 194 | wbc--; 195 | } 196 | 197 | if(rbc && ((*REG_AESCNT & (0x1F << 0x5)) >= (0x4 << 0x5))) //At least 4 ints available for read 198 | { 199 | *dst32++ = *REG_AESRDFIFO; 200 | *dst32++ = *REG_AESRDFIFO; 201 | *dst32++ = *REG_AESRDFIFO; 202 | *dst32++ = *REG_AESRDFIFO; 203 | rbc--; 204 | } 205 | } 206 | } 207 | 208 | static void aes(void *dst, const void *src, u32 blockCount, void *iv, u32 mode, u32 ivMode) 209 | { 210 | *REG_AESCNT = mode | 211 | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | 212 | AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN | 213 | AES_CNT_FLUSH_READ | AES_CNT_FLUSH_WRITE; 214 | 215 | u32 blocks; 216 | while(blockCount != 0) 217 | { 218 | if((mode & AES_ALL_MODES) != AES_ECB_ENCRYPT_MODE 219 | && (mode & AES_ALL_MODES) != AES_ECB_DECRYPT_MODE) 220 | aes_setiv(iv, ivMode); 221 | 222 | blocks = (blockCount >= 0xFFFF) ? 0xFFFF : blockCount; 223 | 224 | //Save the last block for the next decryption CBC batch's iv 225 | if((mode & AES_ALL_MODES) == AES_CBC_DECRYPT_MODE) 226 | { 227 | memcpy(iv, src + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE); 228 | aes_change_ctrmode(iv, AES_INPUT_BE | AES_INPUT_NORMAL, ivMode); 229 | } 230 | 231 | //Process the current batch 232 | aes_batch(dst, src, blocks); 233 | 234 | //Save the last block for the next encryption CBC batch's iv 235 | if((mode & AES_ALL_MODES) == AES_CBC_ENCRYPT_MODE) 236 | { 237 | memcpy(iv, dst + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE); 238 | aes_change_ctrmode(iv, AES_INPUT_BE | AES_INPUT_NORMAL, ivMode); 239 | } 240 | 241 | //Advance counter for CTR mode 242 | else if((mode & AES_ALL_MODES) == AES_CTR_MODE) 243 | aes_advctr(iv, blocks, ivMode); 244 | 245 | src += blocks * AES_BLOCK_SIZE; 246 | dst += blocks * AES_BLOCK_SIZE; 247 | blockCount -= blocks; 248 | } 249 | } 250 | 251 | static void sha_wait_idle() 252 | { 253 | while(*REG_SHA_CNT & 1); 254 | } 255 | 256 | static void sha(void *res, const void *src, u32 size, u32 mode) 257 | { 258 | sha_wait_idle(); 259 | *REG_SHA_CNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND; 260 | 261 | const u32 *src32 = (const u32 *)src; 262 | int i; 263 | while(size >= 0x40) 264 | { 265 | sha_wait_idle(); 266 | for(i = 0; i < 4; ++i) 267 | { 268 | *REG_SHA_INFIFO = *src32++; 269 | *REG_SHA_INFIFO = *src32++; 270 | *REG_SHA_INFIFO = *src32++; 271 | *REG_SHA_INFIFO = *src32++; 272 | } 273 | 274 | size -= 0x40; 275 | } 276 | 277 | sha_wait_idle(); 278 | memcpy((void *)REG_SHA_INFIFO, src32, size); 279 | 280 | *REG_SHA_CNT = (*REG_SHA_CNT & ~SHA_NORMAL_ROUND) | SHA_FINAL_ROUND; 281 | 282 | while(*REG_SHA_CNT & SHA_FINAL_ROUND); 283 | sha_wait_idle(); 284 | 285 | u32 hashSize = SHA_256_HASH_SIZE; 286 | if(mode == SHA_224_MODE) 287 | hashSize = SHA_224_HASH_SIZE; 288 | else if(mode == SHA_1_MODE) 289 | hashSize = SHA_1_HASH_SIZE; 290 | 291 | memcpy(res, (void *)REG_SHA_HASH, hashSize); 292 | } 293 | 294 | /*****************************************************************/ 295 | 296 | __attribute__((aligned(4))) static u8 nandCtr[AES_BLOCK_SIZE], 297 | shaHashBackup[SHA_256_HASH_SIZE]; 298 | static u8 nandSlot; 299 | static u32 fatStart; 300 | 301 | void ctrNandInit(void) 302 | { 303 | memcpy(shaHashBackup, (void *)REG_SHA_HASH, sizeof(shaHashBackup)); 304 | 305 | __attribute__((aligned(4))) u8 cid[AES_BLOCK_SIZE], 306 | shaSum[SHA_256_HASH_SIZE]; 307 | 308 | sdmmc_get_cid(1, (u32 *)cid); 309 | sha(shaSum, cid, sizeof(cid), SHA_256_MODE); 310 | memcpy(nandCtr, shaSum, sizeof(nandCtr)); 311 | 312 | if(ISN3DS) 313 | { 314 | __attribute__((aligned(4))) u8 keyY0x5[AES_BLOCK_SIZE] = {0x4D, 0x80, 0x4F, 0x4E, 0x99, 0x90, 0x19, 0x46, 0x13, 0xA2, 0x04, 0xAC, 0x58, 0x44, 0x60, 0xBE}; 315 | aes_setkey(0x05, keyY0x5, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); 316 | 317 | nandSlot = 0x05; 318 | fatStart = 0x5CAD7; 319 | } 320 | else 321 | { 322 | nandSlot = 0x04; 323 | fatStart = 0x5CAE5; 324 | } 325 | } 326 | 327 | int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf) 328 | { 329 | __attribute__((aligned(4))) u8 tmpCtr[sizeof(nandCtr)]; 330 | memcpy(tmpCtr, nandCtr, sizeof(nandCtr)); 331 | aes_advctr(tmpCtr, ((sector + fatStart) * 0x200) / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL); 332 | 333 | //Read 334 | int result = sdmmc_nand_readsectors(sector + fatStart, sectorCount, outbuf); 335 | 336 | //Decrypt 337 | aes_use_keyslot(nandSlot); 338 | aes(outbuf, outbuf, sectorCount * 0x200 / AES_BLOCK_SIZE, tmpCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); 339 | 340 | return result; 341 | } 342 | 343 | void restoreShaHashBackup(void) 344 | { 345 | memcpy((void *)REG_SHA_HASH, shaHashBackup, sizeof(shaHashBackup)); 346 | } -------------------------------------------------------------------------------- /payload_stage2/source/crypto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Luma3DS 3 | * Copyright (C) 2016 Aurora Wright, TuxSH 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified 19 | * reasonable legal notices or author attributions in that material or in the Appropriate Legal 20 | * Notices displayed by works containing it. 21 | */ 22 | 23 | /* 24 | * Crypto libs from http://github.com/b1l1s/ctr 25 | * kernel9Loader code originally adapted from https://github.com/Reisyukaku/ReiNand/blob/228c378255ba693133dec6f3368e14d386f2cde7/source/crypto.c#L233 26 | */ 27 | 28 | #pragma once 29 | 30 | #include "types.h" 31 | 32 | /**************************AES****************************/ 33 | #define REG_AESCNT ((vu32 *)0x10009000) 34 | #define REG_AESBLKCNT ((vu32 *)0x10009004) 35 | #define REG_AESWRFIFO ((vu32 *)0x10009008) 36 | #define REG_AESRDFIFO ((vu32 *)0x1000900C) 37 | #define REG_AESKEYSEL ((vu8 *)0x10009010) 38 | #define REG_AESKEYCNT ((vu8 *)0x10009011) 39 | #define REG_AESCTR ((vu32 *)0x10009020) 40 | 41 | #define REG_AESKEYFIFO ((vu32 *)0x10009100) 42 | #define REG_AESKEYXFIFO ((vu32 *)0x10009104) 43 | #define REG_AESKEYYFIFO ((vu32 *)0x10009108) 44 | 45 | #define AES_CCM_DECRYPT_MODE (0u << 27) 46 | #define AES_CCM_ENCRYPT_MODE (1u << 27) 47 | #define AES_CTR_MODE (2u << 27) 48 | #define AES_CTR_MODE (2u << 27) 49 | #define AES_CBC_DECRYPT_MODE (4u << 27) 50 | #define AES_CBC_ENCRYPT_MODE (5u << 27) 51 | #define AES_ECB_DECRYPT_MODE (6u << 27) 52 | #define AES_ECB_ENCRYPT_MODE (7u << 27) 53 | #define AES_ALL_MODES (7u << 27) 54 | 55 | #define AES_CNT_START 0x80000000 56 | #define AES_CNT_INPUT_ORDER 0x02000000 57 | #define AES_CNT_OUTPUT_ORDER 0x01000000 58 | #define AES_CNT_INPUT_ENDIAN 0x00800000 59 | #define AES_CNT_OUTPUT_ENDIAN 0x00400000 60 | #define AES_CNT_FLUSH_READ 0x00000800 61 | #define AES_CNT_FLUSH_WRITE 0x00000400 62 | 63 | #define AES_INPUT_BE (AES_CNT_INPUT_ENDIAN) 64 | #define AES_INPUT_LE 0 65 | #define AES_INPUT_NORMAL (AES_CNT_INPUT_ORDER) 66 | #define AES_INPUT_REVERSED 0 67 | 68 | #define AES_BLOCK_SIZE 0x10 69 | 70 | #define AES_KEYCNT_WRITE (1 << 0x7) 71 | #define AES_KEYNORMAL 0 72 | #define AES_KEYX 1 73 | #define AES_KEYY 2 74 | 75 | /**************************SHA****************************/ 76 | #define REG_SHA_CNT ((vu32 *)0x1000A000) 77 | #define REG_SHA_BLKCNT ((vu32 *)0x1000A004) 78 | #define REG_SHA_HASH ((vu32 *)0x1000A040) 79 | #define REG_SHA_INFIFO ((vu32 *)0x1000A080) 80 | 81 | #define SHA_CNT_STATE 0x00000003 82 | #define SHA_CNT_UNK2 0x00000004 83 | #define SHA_CNT_OUTPUT_ENDIAN 0x00000008 84 | #define SHA_CNT_MODE 0x00000030 85 | #define SHA_CNT_ENABLE 0x00010000 86 | #define SHA_CNT_ACTIVE 0x00020000 87 | 88 | #define SHA_HASH_READY 0x00000000 89 | #define SHA_NORMAL_ROUND 0x00000001 90 | #define SHA_FINAL_ROUND 0x00000002 91 | 92 | #define SHA_OUTPUT_BE SHA_CNT_OUTPUT_ENDIAN 93 | #define SHA_OUTPUT_LE 0 94 | 95 | #define SHA_256_MODE 0 96 | #define SHA_224_MODE 0x00000010 97 | #define SHA_1_MODE 0x00000020 98 | 99 | #define SHA_256_HASH_SIZE (256 / 8) 100 | #define SHA_224_HASH_SIZE (224 / 8) 101 | #define SHA_1_HASH_SIZE (160 / 8) 102 | 103 | #define PDN_MPCORE_CFG (*(vu32 *)0x10140FFC) 104 | 105 | #define ISN3DS (PDN_MPCORE_CFG == 7) 106 | 107 | void ctrNandInit(void); 108 | int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); 109 | void restoreShaHashBackup(void); -------------------------------------------------------------------------------- /payload_stage2/source/fatfs/00history.txt: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | Revision history of FatFs module 3 | ---------------------------------------------------------------------------- 4 | 5 | R0.00 (February 26, 2006) 6 | 7 | Prototype. 8 | 9 | 10 | 11 | R0.01 (April 29, 2006) 12 | 13 | The first release. 14 | 15 | 16 | 17 | R0.02 (June 01, 2006) 18 | 19 | Added FAT12 support. 20 | Removed unbuffered mode. 21 | Fixed a problem on small (<32M) partition. 22 | 23 | 24 | 25 | R0.02a (June 10, 2006) 26 | 27 | Added a configuration option (_FS_MINIMUM). 28 | 29 | 30 | 31 | R0.03 (September 22, 2006) 32 | 33 | Added f_rename(). 34 | Changed option _FS_MINIMUM to _FS_MINIMIZE. 35 | 36 | 37 | 38 | R0.03a (December 11, 2006) 39 | 40 | Improved cluster scan algorithm to write files fast. 41 | Fixed f_mkdir() creates incorrect directory on FAT32. 42 | 43 | 44 | 45 | R0.04 (February 04, 2007) 46 | 47 | Added f_mkfs(). 48 | Supported multiple drive system. 49 | Changed some interfaces for multiple drive system. 50 | Changed f_mountdrv() to f_mount(). 51 | 52 | 53 | 54 | R0.04a (April 01, 2007) 55 | 56 | Supported multiple partitions on a physical drive. 57 | Added a capability of extending file size to f_lseek(). 58 | Added minimization level 3. 59 | Fixed an endian sensitive code in f_mkfs(). 60 | 61 | 62 | 63 | R0.04b (May 05, 2007) 64 | 65 | Added a configuration option _USE_NTFLAG. 66 | Added FSINFO support. 67 | Fixed DBCS name can result FR_INVALID_NAME. 68 | Fixed short seek (<= csize) collapses the file object. 69 | 70 | 71 | 72 | R0.05 (August 25, 2007) 73 | 74 | Changed arguments of f_read(), f_write() and f_mkfs(). 75 | Fixed f_mkfs() on FAT32 creates incorrect FSINFO. 76 | Fixed f_mkdir() on FAT32 creates incorrect directory. 77 | 78 | 79 | 80 | R0.05a (February 03, 2008) 81 | 82 | Added f_truncate() and f_utime(). 83 | Fixed off by one error at FAT sub-type determination. 84 | Fixed btr in f_read() can be mistruncated. 85 | Fixed cached sector is not flushed when create and close without write. 86 | 87 | 88 | 89 | R0.06 (April 01, 2008) 90 | 91 | Added fputc(), fputs(), fprintf() and fgets(). 92 | Improved performance of f_lseek() on moving to the same or following cluster. 93 | 94 | 95 | 96 | R0.07 (April 01, 2009) 97 | 98 | Merged Tiny-FatFs as a configuration option. (_FS_TINY) 99 | Added long file name feature. (_USE_LFN) 100 | Added multiple code page feature. (_CODE_PAGE) 101 | Added re-entrancy for multitask operation. (_FS_REENTRANT) 102 | Added auto cluster size selection to f_mkfs(). 103 | Added rewind option to f_readdir(). 104 | Changed result code of critical errors. 105 | Renamed string functions to avoid name collision. 106 | 107 | 108 | 109 | R0.07a (April 14, 2009) 110 | 111 | Septemberarated out OS dependent code on reentrant cfg. 112 | Added multiple sector size feature. 113 | 114 | 115 | 116 | R0.07c (June 21, 2009) 117 | 118 | Fixed f_unlink() can return FR_OK on error. 119 | Fixed wrong cache control in f_lseek(). 120 | Added relative path feature. 121 | Added f_chdir() and f_chdrive(). 122 | Added proper case conversion to extended character. 123 | 124 | 125 | 126 | R0.07e (November 03, 2009) 127 | 128 | Septemberarated out configuration options from ff.h to ffconf.h. 129 | Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH. 130 | Fixed name matching error on the 13 character boundary. 131 | Added a configuration option, _LFN_UNICODE. 132 | Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. 133 | 134 | 135 | 136 | R0.08 (May 15, 2010) 137 | 138 | Added a memory configuration option. (_USE_LFN = 3) 139 | Added file lock feature. (_FS_SHARE) 140 | Added fast seek feature. (_USE_FASTSEEK) 141 | Changed some types on the API, XCHAR->TCHAR. 142 | Changed .fname in the FILINFO structure on Unicode cfg. 143 | String functions support UTF-8 encoding files on Unicode cfg. 144 | 145 | 146 | 147 | R0.08a (August 16, 2010) 148 | 149 | Added f_getcwd(). (_FS_RPATH = 2) 150 | Added sector erase feature. (_USE_ERASE) 151 | Moved file lock semaphore table from fs object to the bss. 152 | Fixed f_mkfs() creates wrong FAT32 volume. 153 | 154 | 155 | 156 | R0.08b (January 15, 2011) 157 | 158 | Fast seek feature is also applied to f_read() and f_write(). 159 | f_lseek() reports required table size on creating CLMP. 160 | Extended format syntax of f_printf(). 161 | Ignores duplicated directory separators in given path name. 162 | 163 | 164 | 165 | R0.09 (September 06, 2011) 166 | 167 | f_mkfs() supports multiple partition to complete the multiple partition feature. 168 | Added f_fdisk(). 169 | 170 | 171 | 172 | R0.09a (August 27, 2012) 173 | 174 | Changed f_open() and f_opendir() reject null object pointer to avoid crash. 175 | Changed option name _FS_SHARE to _FS_LOCK. 176 | Fixed assertion failure due to OS/2 EA on FAT12/16 volume. 177 | 178 | 179 | 180 | R0.09b (January 24, 2013) 181 | 182 | Added f_setlabel() and f_getlabel(). 183 | 184 | 185 | 186 | R0.10 (October 02, 2013) 187 | 188 | Added selection of character encoding on the file. (_STRF_ENCODE) 189 | Added f_closedir(). 190 | Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO) 191 | Added forced mount feature with changes of f_mount(). 192 | Improved behavior of volume auto detection. 193 | Improved write throughput of f_puts() and f_printf(). 194 | Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write(). 195 | Fixed f_write() can be truncated when the file size is close to 4GB. 196 | Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect value on error. 197 | 198 | 199 | 200 | R0.10a (January 15, 2014) 201 | 202 | Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID) 203 | Added a configuration option of minimum sector size. (_MIN_SS) 204 | 2nd argument of f_rename() can have a drive number and it will be ignored. 205 | Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10) 206 | Fixed f_close() invalidates the file object without volume lock. 207 | Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10) 208 | Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07) 209 | 210 | 211 | 212 | R0.10b (May 19, 2014) 213 | 214 | Fixed a hard error in the disk I/O layer can collapse the directory entry. 215 | Fixed LFN entry is not deleted when delete/rename an object with lossy converted SFN. (appeared at R0.07) 216 | 217 | 218 | 219 | R0.10c (November 09, 2014) 220 | 221 | Added a configuration option for the platforms without RTC. (_FS_NORTC) 222 | Changed option name _USE_ERASE to _USE_TRIM. 223 | Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b) 224 | Fixed a potential problem of FAT access that can appear on disk error. 225 | Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08) 226 | 227 | 228 | 229 | R0.11 (February 09, 2015) 230 | 231 | Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND) 232 | Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c) 233 | Fixed _FS_NORTC option does not work properly. (appeared at R0.10c) 234 | 235 | 236 | 237 | R0.11a (September 05, 2015) 238 | 239 | Fixed wrong media change can lead a deadlock at thread-safe configuration. 240 | Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE) 241 | Removed some code pages actually not exist on the standard systems. (_CODE_PAGE) 242 | Fixed errors in the case conversion teble of code page 437 and 850 (ff.c). 243 | Fixed errors in the case conversion teble of Unicode (cc*.c). 244 | 245 | 246 | 247 | R0.12 (April 12, 2016) 248 | 249 | Added support for exFAT file system. (_FS_EXFAT) 250 | Added f_expand(). (_USE_EXPAND) 251 | Changed some members in FINFO structure and behavior of f_readdir(). 252 | Added an option _USE_CHMOD. 253 | Removed an option _WORD_ACCESS. 254 | Fixed errors in the case conversion table of Unicode (cc*.c). 255 | 256 | 257 | 258 | R0.12a (July 10, 2016) 259 | 260 | Added support for creating exFAT volume with some changes of f_mkfs(). 261 | Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed. 262 | f_forward() is available regardless of _FS_TINY. 263 | Fixed f_mkfs() creates wrong volume. (appeared at R0.12) 264 | Fixed wrong memory read in create_name(). (appeared at R0.12) 265 | Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD. 266 | 267 | 268 | 269 | R0.12b (September 04, 2016) 270 | 271 | Made f_rename() be able to rename objects with the same name but case. 272 | Fixed an error in the case conversion teble of code page 866. (ff.c) 273 | Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12) 274 | Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12) 275 | Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12) 276 | Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12) 277 | Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12) 278 | Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12) 279 | 280 | 281 | 282 | R0.12c (March 04, 2017) 283 | 284 | Improved write throughput at the fragmented file on the exFAT volume. 285 | Made memory usage for exFAT be able to be reduced as decreasing _MAX_LFN. 286 | Fixed successive f_getfree() can return wrong count on the FAT12/16 volume. (appeared at R0.12) 287 | Fixed configuration option _VOLUMES cannot be set 10. (appeared at R0.10c) 288 | 289 | -------------------------------------------------------------------------------- /payload_stage2/source/fatfs/00readme.txt: -------------------------------------------------------------------------------- 1 | FatFs Module Source Files R0.12c 2 | 3 | 4 | FILES 5 | 6 | 00readme.txt This file. 7 | 00history.txt Revision history. 8 | ff.c FatFs module. 9 | ffconf.h Configuration file of FatFs module. 10 | ff.h Common include file for FatFs and application module. 11 | diskio.h Common include file for FatFs and disk I/O module. 12 | diskio.c An example of glue function to attach existing disk I/O module to FatFs. 13 | integer.h Integer type definitions for FatFs. 14 | option Optional external modules. 15 | 16 | 17 | Low level disk I/O module is not included in this archive because the FatFs 18 | module is only a generic file system layer and it does not depend on any specific 19 | storage device. You have to provide a low level disk I/O module written to 20 | control the storage device that attached to the target system. 21 | 22 | -------------------------------------------------------------------------------- /payload_stage2/source/fatfs/diskio.c: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2014 */ 3 | /*-----------------------------------------------------------------------*/ 4 | /* If a working storage control module is available, it should be */ 5 | /* attached to the FatFs via a glue function rather than modifying it. */ 6 | /* This is an example of glue functions to attach various exsisting */ 7 | /* storage control modules to the FatFs module with a defined API. */ 8 | /*-----------------------------------------------------------------------*/ 9 | 10 | #include "diskio.h" /* FatFs lower layer API */ 11 | #include "sdmmc/sdmmc.h" 12 | #include "../crypto.h" 13 | 14 | /* Definitions of physical drive number for each media */ 15 | #define SDCARD 0 16 | #define CTRNAND 1 17 | 18 | /*-----------------------------------------------------------------------*/ 19 | /* Get Drive Status */ 20 | /*-----------------------------------------------------------------------*/ 21 | 22 | DSTATUS disk_status ( 23 | __attribute__((unused)) 24 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 25 | ) 26 | { 27 | return RES_OK; 28 | } 29 | 30 | 31 | 32 | /*-----------------------------------------------------------------------*/ 33 | /* Inidialize a Drive */ 34 | /*-----------------------------------------------------------------------*/ 35 | 36 | DSTATUS disk_initialize ( 37 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 38 | ) 39 | { 40 | DSTATUS ret; 41 | static u32 sdmmcInitResult = 4; 42 | 43 | if(sdmmcInitResult == 4) sdmmcInitResult = sdmmc_sdcard_init(); 44 | 45 | if(pdrv == CTRNAND) 46 | { 47 | if(!(sdmmcInitResult & 1)) 48 | { 49 | ctrNandInit(); 50 | ret = 0; 51 | } 52 | else ret = STA_NOINIT; 53 | } 54 | else ret = (!(sdmmcInitResult & 2)) ? 0 : STA_NOINIT; 55 | 56 | return ret; 57 | } 58 | 59 | 60 | 61 | /*-----------------------------------------------------------------------*/ 62 | /* Read Sector(s) */ 63 | /*-----------------------------------------------------------------------*/ 64 | 65 | /*-----------------------------------------------------------------------*/ 66 | /* Read Sector(s) */ 67 | /*-----------------------------------------------------------------------*/ 68 | 69 | DRESULT disk_read ( 70 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 71 | BYTE *buff, /* Data buffer to store read data */ 72 | DWORD sector, /* Sector address in LBA */ 73 | UINT count /* Number of sectors to read */ 74 | ) 75 | { 76 | return ((pdrv == SDCARD && !sdmmc_sdcard_readsectors(sector, count, buff)) || 77 | (pdrv == CTRNAND && !ctrNandRead(sector, count, buff))) ? RES_OK : RES_PARERR; 78 | } 79 | 80 | 81 | 82 | /*-----------------------------------------------------------------------*/ 83 | /* Write Sector(s) */ 84 | /*-----------------------------------------------------------------------*/ 85 | 86 | #if _USE_WRITE 87 | DRESULT disk_write ( 88 | __attribute__((unused)) 89 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 90 | __attribute__((unused)) 91 | const BYTE *buff, /* Data to be written */ 92 | __attribute__((unused)) 93 | DWORD sector, /* Sector address in LBA */ 94 | __attribute__((unused)) 95 | UINT count /* Number of sectors to write */ 96 | ) 97 | { 98 | return RES_OK; 99 | } 100 | #endif 101 | 102 | 103 | 104 | /*-----------------------------------------------------------------------*/ 105 | /* Miscellaneous Functions */ 106 | /*-----------------------------------------------------------------------*/ 107 | 108 | #if _USE_IOCTL 109 | DRESULT disk_ioctl ( 110 | __attribute__((unused)) 111 | BYTE pdrv, /* Physical drive nmuber (0..) */ 112 | __attribute__((unused)) 113 | BYTE cmd, /* Control code */ 114 | __attribute__((unused)) 115 | void *buff /* Buffer to send/receive control data */ 116 | ) 117 | { 118 | return RES_PARERR; 119 | } 120 | #endif 121 | -------------------------------------------------------------------------------- /payload_stage2/source/fatfs/diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------/ 2 | / Low level disk interface modlue include file (C)ChaN, 2014 / 3 | /-----------------------------------------------------------------------*/ 4 | 5 | #ifndef _DISKIO_DEFINED 6 | #define _DISKIO_DEFINED 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #define _USE_WRITE 1 /* 1: Enable disk_write function */ 13 | #define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */ 14 | 15 | #include "integer.h" 16 | 17 | 18 | /* Status of Disk Functions */ 19 | typedef BYTE DSTATUS; 20 | 21 | /* Results of Disk Functions */ 22 | typedef enum { 23 | RES_OK = 0, /* 0: Successful */ 24 | RES_ERROR, /* 1: R/W Error */ 25 | RES_WRPRT, /* 2: Write Protected */ 26 | RES_NOTRDY, /* 3: Not Ready */ 27 | RES_PARERR /* 4: Invalid Parameter */ 28 | } DRESULT; 29 | 30 | 31 | /*---------------------------------------*/ 32 | /* Prototypes for disk control functions */ 33 | 34 | 35 | DSTATUS disk_initialize (BYTE pdrv); 36 | DSTATUS disk_status (BYTE pdrv); 37 | DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); 38 | DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); 39 | DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); 40 | 41 | 42 | /* Disk Status Bits (DSTATUS) */ 43 | 44 | #define STA_NOINIT 0x01 /* Drive not initialized */ 45 | #define STA_NODISK 0x02 /* No medium in the drive */ 46 | #define STA_PROTECT 0x04 /* Write protected */ 47 | 48 | 49 | /* Command code for disk_ioctrl fucntion */ 50 | 51 | /* Generic command (Used by FatFs) */ 52 | #define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */ 53 | #define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */ 54 | #define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */ 55 | #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */ 56 | #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ 57 | 58 | /* Generic command (Not used by FatFs) */ 59 | #define CTRL_POWER 5 /* Get/Set power status */ 60 | #define CTRL_LOCK 6 /* Lock/Unlock media removal */ 61 | #define CTRL_EJECT 7 /* Eject media */ 62 | #define CTRL_FORMAT 8 /* Create physical format on the media */ 63 | 64 | /* MMC/SDC specific ioctl command */ 65 | #define MMC_GET_TYPE 10 /* Get card type */ 66 | #define MMC_GET_CSD 11 /* Get CSD */ 67 | #define MMC_GET_CID 12 /* Get CID */ 68 | #define MMC_GET_OCR 13 /* Get OCR */ 69 | #define MMC_GET_SDSTAT 14 /* Get SD status */ 70 | 71 | /* ATA/CF specific ioctl command */ 72 | #define ATA_GET_REV 20 /* Get F/W revision */ 73 | #define ATA_GET_MODEL 21 /* Get model name */ 74 | #define ATA_GET_SN 22 /* Get serial number */ 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /payload_stage2/source/fatfs/ff.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------/ 2 | / FatFs - Generic FAT file system module R0.12c / 3 | /-----------------------------------------------------------------------------/ 4 | / 5 | / Copyright (C) 2017, ChaN, all right reserved. 6 | / 7 | / FatFs module is an open source software. Redistribution and use of FatFs in 8 | / source and binary forms, with or without modification, are permitted provided 9 | / that the following condition is met: 10 | 11 | / 1. Redistributions of source code must retain the above copyright notice, 12 | / this condition and the following disclaimer. 13 | / 14 | / This software is provided by the copyright holder and contributors "AS IS" 15 | / and any warranties related to this software are DISCLAIMED. 16 | / The copyright owner or contributors be NOT LIABLE for any damages caused 17 | / by use of this software. 18 | /----------------------------------------------------------------------------*/ 19 | 20 | 21 | #ifndef _FATFS 22 | #define _FATFS 68300 /* Revision ID */ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #include "integer.h" /* Basic integer types */ 29 | #include "ffconf.h" /* FatFs configuration options */ 30 | 31 | #if _FATFS != _FFCONF 32 | #error Wrong configuration file (ffconf.h). 33 | #endif 34 | 35 | 36 | 37 | /* Definitions of volume management */ 38 | 39 | #if _MULTI_PARTITION /* Multiple partition configuration */ 40 | typedef struct { 41 | BYTE pd; /* Physical drive number */ 42 | BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ 43 | } PARTITION; 44 | extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ 45 | #endif 46 | 47 | 48 | 49 | /* Type of path name strings on FatFs API */ 50 | 51 | #if _LFN_UNICODE /* Unicode (UTF-16) string */ 52 | #if _USE_LFN == 0 53 | #error _LFN_UNICODE must be 0 at non-LFN cfg. 54 | #endif 55 | #ifndef _INC_TCHAR 56 | typedef WCHAR TCHAR; 57 | #define _T(x) L ## x 58 | #define _TEXT(x) L ## x 59 | #endif 60 | #else /* ANSI/OEM string */ 61 | #ifndef _INC_TCHAR 62 | typedef char TCHAR; 63 | #define _T(x) x 64 | #define _TEXT(x) x 65 | #endif 66 | #endif 67 | 68 | 69 | 70 | /* Type of file size variables */ 71 | 72 | #if _FS_EXFAT 73 | #if _USE_LFN == 0 74 | #error LFN must be enabled when enable exFAT 75 | #endif 76 | typedef QWORD FSIZE_t; 77 | #else 78 | typedef DWORD FSIZE_t; 79 | #endif 80 | 81 | 82 | 83 | /* File system object structure (FATFS) */ 84 | 85 | typedef struct { 86 | BYTE fs_type; /* File system type (0:N/A) */ 87 | BYTE drv; /* Physical drive number */ 88 | BYTE n_fats; /* Number of FATs (1 or 2) */ 89 | BYTE wflag; /* win[] flag (b0:dirty) */ 90 | BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ 91 | WORD id; /* File system mount ID */ 92 | WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ 93 | WORD csize; /* Cluster size [sectors] */ 94 | #if _MAX_SS != _MIN_SS 95 | WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ 96 | #endif 97 | #if _USE_LFN != 0 98 | WCHAR* lfnbuf; /* LFN working buffer */ 99 | #endif 100 | #if _FS_EXFAT 101 | BYTE* dirbuf; /* Directory entry block scratchpad buffer */ 102 | #endif 103 | #if _FS_REENTRANT 104 | _SYNC_t sobj; /* Identifier of sync object */ 105 | #endif 106 | #if !_FS_READONLY 107 | DWORD last_clst; /* Last allocated cluster */ 108 | DWORD free_clst; /* Number of free clusters */ 109 | #endif 110 | #if _FS_RPATH != 0 111 | DWORD cdir; /* Current directory start cluster (0:root) */ 112 | #if _FS_EXFAT 113 | DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ 114 | DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ 115 | DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ 116 | #endif 117 | #endif 118 | DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ 119 | DWORD fsize; /* Size of an FAT [sectors] */ 120 | DWORD volbase; /* Volume base sector */ 121 | DWORD fatbase; /* FAT base sector */ 122 | DWORD dirbase; /* Root directory base sector/cluster */ 123 | DWORD database; /* Data base sector */ 124 | DWORD winsect; /* Current sector appearing in the win[] */ 125 | BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ 126 | } FATFS; 127 | 128 | 129 | 130 | /* Object ID and allocation information (_FDID) */ 131 | 132 | typedef struct { 133 | FATFS* fs; /* Pointer to the owner file system object */ 134 | WORD id; /* Owner file system mount ID */ 135 | BYTE attr; /* Object attribute */ 136 | 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) */ 137 | DWORD sclust; /* Object start cluster (0:no cluster or root directory) */ 138 | FSIZE_t objsize; /* Object size (valid when sclust != 0) */ 139 | #if _FS_EXFAT 140 | DWORD n_cont; /* Size of first fragment, clusters - 1 (valid when stat == 3) */ 141 | DWORD n_frag; /* Size of last fragment needs to be written (valid when not zero) */ 142 | DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ 143 | DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ 144 | DWORD c_ofs; /* Offset in the containing directory (valid when sclust != 0 and non-directory object) */ 145 | #endif 146 | #if _FS_LOCK != 0 147 | UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ 148 | #endif 149 | } _FDID; 150 | 151 | 152 | 153 | /* File object structure (FIL) */ 154 | 155 | typedef struct { 156 | _FDID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ 157 | BYTE flag; /* File status flags */ 158 | BYTE err; /* Abort flag (error code) */ 159 | FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ 160 | DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ 161 | DWORD sect; /* Sector number appearing in buf[] (0:invalid) */ 162 | #if !_FS_READONLY 163 | DWORD dir_sect; /* Sector number containing the directory entry */ 164 | BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */ 165 | #endif 166 | #if _USE_FASTSEEK 167 | DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ 168 | #endif 169 | #if !_FS_TINY 170 | BYTE buf[_MAX_SS]; /* File private data read/write window */ 171 | #endif 172 | } FIL; 173 | 174 | 175 | 176 | /* Directory object structure (DIR) */ 177 | 178 | typedef struct { 179 | _FDID obj; /* Object identifier */ 180 | DWORD dptr; /* Current read/write offset */ 181 | DWORD clust; /* Current cluster */ 182 | DWORD sect; /* Current sector (0:Read operation has terminated) */ 183 | BYTE* dir; /* Pointer to the directory item in the win[] */ 184 | BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ 185 | #if _USE_LFN != 0 186 | DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ 187 | #endif 188 | #if _USE_FIND 189 | const TCHAR* pat; /* Pointer to the name matching pattern */ 190 | #endif 191 | } DIR; 192 | 193 | 194 | 195 | /* File information structure (FILINFO) */ 196 | 197 | typedef struct { 198 | FSIZE_t fsize; /* File size */ 199 | WORD fdate; /* Modified date */ 200 | WORD ftime; /* Modified time */ 201 | BYTE fattrib; /* File attribute */ 202 | #if _USE_LFN != 0 203 | TCHAR altname[13]; /* Altenative file name */ 204 | TCHAR fname[_MAX_LFN + 1]; /* Primary file name */ 205 | #else 206 | TCHAR fname[13]; /* File name */ 207 | #endif 208 | } FILINFO; 209 | 210 | 211 | 212 | /* File function return code (FRESULT) */ 213 | 214 | typedef enum { 215 | FR_OK = 0, /* (0) Succeeded */ 216 | FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ 217 | FR_INT_ERR, /* (2) Assertion failed */ 218 | FR_NOT_READY, /* (3) The physical drive cannot work */ 219 | FR_NO_FILE, /* (4) Could not find the file */ 220 | FR_NO_PATH, /* (5) Could not find the path */ 221 | FR_INVALID_NAME, /* (6) The path name format is invalid */ 222 | FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ 223 | FR_EXIST, /* (8) Access denied due to prohibited access */ 224 | FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ 225 | FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ 226 | FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ 227 | FR_NOT_ENABLED, /* (12) The volume has no work area */ 228 | FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ 229 | FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ 230 | FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ 231 | FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ 232 | FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ 233 | FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_LOCK */ 234 | FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ 235 | } FRESULT; 236 | 237 | 238 | 239 | /*--------------------------------------------------------------*/ 240 | /* FatFs module application interface */ 241 | 242 | FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ 243 | FRESULT f_close (FIL* fp); /* Close an open file object */ 244 | FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ 245 | FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ 246 | FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ 247 | FRESULT f_truncate (FIL* fp); /* Truncate the file */ 248 | FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ 249 | FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ 250 | FRESULT f_closedir (DIR* dp); /* Close an open directory */ 251 | FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ 252 | FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ 253 | FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ 254 | FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ 255 | FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ 256 | FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ 257 | FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ 258 | FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ 259 | FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */ 260 | FRESULT f_chdir (const TCHAR* path); /* Change current directory */ 261 | FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ 262 | FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ 263 | FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ 264 | FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ 265 | FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ 266 | FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ 267 | FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */ 268 | FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ 269 | FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ 270 | FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */ 271 | int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ 272 | int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ 273 | int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ 274 | TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ 275 | 276 | #define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) 277 | #define f_error(fp) ((fp)->err) 278 | #define f_tell(fp) ((fp)->fptr) 279 | #define f_size(fp) ((fp)->obj.objsize) 280 | #define f_rewind(fp) f_lseek((fp), 0) 281 | #define f_rewinddir(dp) f_readdir((dp), 0) 282 | #define f_rmdir(path) f_unlink(path) 283 | 284 | #ifndef EOF 285 | #define EOF (-1) 286 | #endif 287 | 288 | 289 | 290 | 291 | /*--------------------------------------------------------------*/ 292 | /* Additional user defined functions */ 293 | 294 | /* RTC function */ 295 | #if !_FS_READONLY && !_FS_NORTC 296 | DWORD get_fattime (void); 297 | #endif 298 | 299 | /* Unicode support functions */ 300 | #if _USE_LFN != 0 /* Unicode - OEM code conversion */ 301 | WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */ 302 | WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */ 303 | #if _USE_LFN == 3 /* Memory functions */ 304 | void* ff_memalloc (UINT msize); /* Allocate memory block */ 305 | void ff_memfree (void* mblock); /* Free memory block */ 306 | #endif 307 | #endif 308 | 309 | /* Sync functions */ 310 | #if _FS_REENTRANT 311 | int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */ 312 | int ff_req_grant (_SYNC_t sobj); /* Lock sync object */ 313 | void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */ 314 | int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */ 315 | #endif 316 | 317 | 318 | 319 | 320 | /*--------------------------------------------------------------*/ 321 | /* Flags and offset address */ 322 | 323 | 324 | /* File access mode and open method flags (3rd argument of f_open) */ 325 | #define FA_READ 0x01 326 | #define FA_WRITE 0x02 327 | #define FA_OPEN_EXISTING 0x00 328 | #define FA_CREATE_NEW 0x04 329 | #define FA_CREATE_ALWAYS 0x08 330 | #define FA_OPEN_ALWAYS 0x10 331 | #define FA_OPEN_APPEND 0x30 332 | 333 | /* Fast seek controls (2nd argument of f_lseek) */ 334 | #define CREATE_LINKMAP ((FSIZE_t)0 - 1) 335 | 336 | /* Format options (2nd argument of f_mkfs) */ 337 | #define FM_FAT 0x01 338 | #define FM_FAT32 0x02 339 | #define FM_EXFAT 0x04 340 | #define FM_ANY 0x07 341 | #define FM_SFD 0x08 342 | 343 | /* Filesystem type (FATFS.fs_type) */ 344 | #define FS_FAT12 1 345 | #define FS_FAT16 2 346 | #define FS_FAT32 3 347 | #define FS_EXFAT 4 348 | 349 | /* File attribute bits for directory entry (FILINFO.fattrib) */ 350 | #define AM_RDO 0x01 /* Read only */ 351 | #define AM_HID 0x02 /* Hidden */ 352 | #define AM_SYS 0x04 /* System */ 353 | #define AM_DIR 0x10 /* Directory */ 354 | #define AM_ARC 0x20 /* Archive */ 355 | 356 | 357 | #ifdef __cplusplus 358 | } 359 | #endif 360 | 361 | #endif /* _FATFS */ 362 | -------------------------------------------------------------------------------- /payload_stage2/source/fatfs/ffconf.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------/ 2 | / FatFs - FAT file system module configuration file 3 | /---------------------------------------------------------------------------*/ 4 | 5 | #define _FFCONF 68300 /* Revision ID */ 6 | 7 | /*---------------------------------------------------------------------------/ 8 | / Function Configurations 9 | /---------------------------------------------------------------------------*/ 10 | 11 | #define _FS_READONLY 1 12 | /* This option switches read-only configuration. (0:Read/Write or 1:Read-only) 13 | / Read-only configuration removes writing API functions, f_write(), f_sync(), 14 | / f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() 15 | / and optional writing functions as well. */ 16 | 17 | 18 | #define _FS_MINIMIZE 3 19 | /* This option defines minimization level to remove some basic API functions. 20 | / 21 | / 0: All basic functions are enabled. 22 | / 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() 23 | / are removed. 24 | / 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. 25 | / 3: f_lseek() function is removed in addition to 2. */ 26 | 27 | 28 | #define _USE_STRFUNC 0 29 | /* This option switches string functions, f_gets(), f_putc(), f_puts() and 30 | / f_printf(). 31 | / 32 | / 0: Disable string functions. 33 | / 1: Enable without LF-CRLF conversion. 34 | / 2: Enable with LF-CRLF conversion. */ 35 | 36 | 37 | #define _USE_FIND 0 38 | /* This option switches filtered directory read functions, f_findfirst() and 39 | / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ 40 | 41 | 42 | #define _USE_MKFS 0 43 | /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ 44 | 45 | 46 | #define _USE_FASTSEEK 0 47 | /* This option switches fast seek function. (0:Disable or 1:Enable) */ 48 | 49 | 50 | #define _USE_EXPAND 0 51 | /* This option switches f_expand function. (0:Disable or 1:Enable) */ 52 | 53 | 54 | #define _USE_CHMOD 0 55 | /* This option switches attribute manipulation functions, f_chmod() and f_utime(). 56 | / (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */ 57 | 58 | 59 | #define _USE_LABEL 0 60 | /* This option switches volume label functions, f_getlabel() and f_setlabel(). 61 | / (0:Disable or 1:Enable) */ 62 | 63 | 64 | #define _USE_FORWARD 0 65 | /* This option switches f_forward() function. (0:Disable or 1:Enable) */ 66 | 67 | 68 | /*---------------------------------------------------------------------------/ 69 | / Locale and Namespace Configurations 70 | /---------------------------------------------------------------------------*/ 71 | 72 | #define _CODE_PAGE 437 73 | /* This option specifies the OEM code page to be used on the target system. 74 | / Incorrect setting of the code page can cause a file open failure. 75 | / 76 | / 1 - ASCII (No support of extended character. Non-LFN cfg. only) 77 | / 437 - U.S. 78 | / 720 - Arabic 79 | / 737 - Greek 80 | / 771 - KBL 81 | / 775 - Baltic 82 | / 850 - Latin 1 83 | / 852 - Latin 2 84 | / 855 - Cyrillic 85 | / 857 - Turkish 86 | / 860 - Portuguese 87 | / 861 - Icelandic 88 | / 862 - Hebrew 89 | / 863 - Canadian French 90 | / 864 - Arabic 91 | / 865 - Nordic 92 | / 866 - Russian 93 | / 869 - Greek 2 94 | / 932 - Japanese (DBCS) 95 | / 936 - Simplified Chinese (DBCS) 96 | / 949 - Korean (DBCS) 97 | / 950 - Traditional Chinese (DBCS) 98 | */ 99 | 100 | 101 | #define _USE_LFN 2 102 | #define _MAX_LFN 255 103 | /* The _USE_LFN switches the support of long file name (LFN). 104 | / 105 | / 0: Disable support of LFN. _MAX_LFN has no effect. 106 | / 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. 107 | / 2: Enable LFN with dynamic working buffer on the STACK. 108 | / 3: Enable LFN with dynamic working buffer on the HEAP. 109 | / 110 | / To enable the LFN, Unicode handling functions (option/unicode.c) must be added 111 | / to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and 112 | / additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255. 113 | / It should be set 255 to support full featured LFN operations. 114 | / When use stack for the working buffer, take care on stack overflow. When use heap 115 | / memory for the working buffer, memory management functions, ff_memalloc() and 116 | / ff_memfree(), must be added to the project. */ 117 | 118 | 119 | #define _LFN_UNICODE 0 120 | /* This option switches character encoding on the API. (0:ANSI/OEM or 1:UTF-16) 121 | / To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1. 122 | / This option also affects behavior of string I/O functions. */ 123 | 124 | 125 | #define _STRF_ENCODE 3 126 | /* When _LFN_UNICODE == 1, this option selects the character encoding ON THE FILE to 127 | / be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf(). 128 | / 129 | / 0: ANSI/OEM 130 | / 1: UTF-16LE 131 | / 2: UTF-16BE 132 | / 3: UTF-8 133 | / 134 | / This option has no effect when _LFN_UNICODE == 0. */ 135 | 136 | 137 | #define _FS_RPATH 1 138 | /* This option configures support of relative path. 139 | / 140 | / 0: Disable relative path and remove related functions. 141 | / 1: Enable relative path. f_chdir() and f_chdrive() are available. 142 | / 2: f_getcwd() function is available in addition to 1. 143 | */ 144 | 145 | 146 | /*---------------------------------------------------------------------------/ 147 | / Drive/Volume Configurations 148 | /---------------------------------------------------------------------------*/ 149 | 150 | #define _VOLUMES 2 151 | /* Number of volumes (logical drives) to be used. (1-10) */ 152 | 153 | 154 | #define _STR_VOLUME_ID 0 155 | #define _VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" 156 | /* _STR_VOLUME_ID switches string support of volume ID. 157 | / When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive 158 | / number in the path name. _VOLUME_STRS defines the drive ID strings for each 159 | / logical drives. Number of items must be equal to _VOLUMES. Valid characters for 160 | / the drive ID strings are: A-Z and 0-9. */ 161 | 162 | 163 | #define _MULTI_PARTITION 0 164 | /* This option switches support of multi-partition on a physical drive. 165 | / By default (0), each logical drive number is bound to the same physical drive 166 | / number and only an FAT volume found on the physical drive will be mounted. 167 | / When multi-partition is enabled (1), each logical drive number can be bound to 168 | / arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() 169 | / funciton will be available. */ 170 | 171 | 172 | #define _MIN_SS 512 173 | #define _MAX_SS 512 174 | /* These options configure the range of sector size to be supported. (512, 1024, 175 | / 2048 or 4096) Always set both 512 for most systems, generic memory card and 176 | / harddisk. But a larger value may be required for on-board flash memory and some 177 | / type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured 178 | / to variable sector size and GET_SECTOR_SIZE command needs to be implemented to 179 | / the disk_ioctl() function. */ 180 | 181 | 182 | #define _USE_TRIM 0 183 | /* This option switches support of ATA-TRIM. (0:Disable or 1:Enable) 184 | / To enable Trim function, also CTRL_TRIM command should be implemented to the 185 | / disk_ioctl() function. */ 186 | 187 | 188 | #define _FS_NOFSINFO 0 189 | /* If you need to know correct free space on the FAT32 volume, set bit 0 of this 190 | / option, and f_getfree() function at first time after volume mount will force 191 | / a full FAT scan. Bit 1 controls the use of last allocated cluster number. 192 | / 193 | / bit0=0: Use free cluster count in the FSINFO if available. 194 | / bit0=1: Do not trust free cluster count in the FSINFO. 195 | / bit1=0: Use last allocated cluster number in the FSINFO if available. 196 | / bit1=1: Do not trust last allocated cluster number in the FSINFO. 197 | */ 198 | 199 | 200 | 201 | /*---------------------------------------------------------------------------/ 202 | / System Configurations 203 | /---------------------------------------------------------------------------*/ 204 | 205 | #define _FS_TINY 0 206 | /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) 207 | / At the tiny configuration, size of file object (FIL) is shrinked _MAX_SS bytes. 208 | / Instead of private sector buffer eliminated from the file object, common sector 209 | / buffer in the file system object (FATFS) is used for the file data transfer. */ 210 | 211 | 212 | #define _FS_EXFAT 0 213 | /* This option switches support of exFAT file system. (0:Disable or 1:Enable) 214 | / When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1) 215 | / Note that enabling exFAT discards ANSI C (C89) compatibility. */ 216 | 217 | 218 | #define _FS_NORTC 1 219 | #define _NORTC_MON 1 220 | #define _NORTC_MDAY 1 221 | #define _NORTC_YEAR 2017 222 | /* The option _FS_NORTC switches timestamp functiton. If the system does not have 223 | / any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable 224 | / the timestamp function. All objects modified by FatFs will have a fixed timestamp 225 | / defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time. 226 | / To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be 227 | / added to the project to get current time form real-time clock. _NORTC_MON, 228 | / _NORTC_MDAY and _NORTC_YEAR have no effect. 229 | / These options have no effect at read-only configuration (_FS_READONLY = 1). */ 230 | 231 | 232 | #define _FS_LOCK 0 233 | /* The option _FS_LOCK switches file lock function to control duplicated file open 234 | / and illegal operation to open objects. This option must be 0 when _FS_READONLY 235 | / is 1. 236 | / 237 | / 0: Disable file lock function. To avoid volume corruption, application program 238 | / should avoid illegal open, remove and rename to the open objects. 239 | / >0: Enable file lock function. The value defines how many files/sub-directories 240 | / can be opened simultaneously under file lock control. Note that the file 241 | / lock control is independent of re-entrancy. */ 242 | 243 | 244 | #define _FS_REENTRANT 0 245 | #define _FS_TIMEOUT 1000 246 | #define _SYNC_t HANDLE 247 | /* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs 248 | / module itself. Note that regardless of this option, file access to different 249 | / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() 250 | / and f_fdisk() function, are always not re-entrant. Only file/directory access 251 | / to the same volume is under control of this function. 252 | / 253 | / 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect. 254 | / 1: Enable re-entrancy. Also user provided synchronization handlers, 255 | / ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() 256 | / function, must be added to the project. Samples are available in 257 | / option/syscall.c. 258 | / 259 | / The _FS_TIMEOUT defines timeout period in unit of time tick. 260 | / The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, 261 | / SemaphoreHandle_t and etc. A header file for O/S definitions needs to be 262 | / included somewhere in the scope of ff.h. */ 263 | 264 | /* #include // O/S definitions */ 265 | 266 | 267 | 268 | /*--- End of configuration options ---*/ 269 | -------------------------------------------------------------------------------- /payload_stage2/source/fatfs/integer.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------*/ 2 | /* Integer type definitions for FatFs module */ 3 | /*-------------------------------------------*/ 4 | 5 | #ifndef _FF_INTEGER 6 | #define _FF_INTEGER 7 | 8 | #ifdef _WIN32 /* FatFs development platform */ 9 | 10 | #include 11 | #include 12 | typedef unsigned __int64 QWORD; 13 | 14 | 15 | #else /* Embedded platform */ 16 | 17 | /* These types MUST be 16-bit or 32-bit */ 18 | typedef int INT; 19 | typedef unsigned int UINT; 20 | 21 | /* This type MUST be 8-bit */ 22 | typedef unsigned char BYTE; 23 | 24 | /* These types MUST be 16-bit */ 25 | typedef short SHORT; 26 | typedef unsigned short WORD; 27 | typedef unsigned short WCHAR; 28 | 29 | /* These types MUST be 32-bit */ 30 | typedef long LONG; 31 | typedef unsigned long DWORD; 32 | 33 | /* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */ 34 | typedef unsigned long long QWORD; 35 | 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /payload_stage2/source/fatfs/option/ccsbcs.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------*/ 2 | /* Unicode - Local code bidirectional converter (C)ChaN, 2015 */ 3 | /* (SBCS code pages) */ 4 | /*------------------------------------------------------------------------*/ 5 | /* 437 U.S. 6 | / 720 Arabic 7 | / 737 Greek 8 | / 771 KBL 9 | / 775 Baltic 10 | / 850 Latin 1 11 | / 852 Latin 2 12 | / 855 Cyrillic 13 | / 857 Turkish 14 | / 860 Portuguese 15 | / 861 Icelandic 16 | / 862 Hebrew 17 | / 863 Canadian French 18 | / 864 Arabic 19 | / 865 Nordic 20 | / 866 Russian 21 | / 869 Greek 2 22 | */ 23 | 24 | #include "../ff.h" 25 | 26 | 27 | #if _CODE_PAGE == 437 28 | #define _TBLDEF 1 29 | static 30 | const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */ 31 | 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 32 | 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, 33 | 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 34 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 35 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 36 | 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 37 | 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 38 | 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 39 | }; 40 | 41 | #elif _CODE_PAGE == 720 42 | #define _TBLDEF 1 43 | static 44 | const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */ 45 | 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, 46 | 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, 47 | 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, 48 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 49 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 50 | 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 51 | 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 52 | 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 53 | }; 54 | 55 | #elif _CODE_PAGE == 737 56 | #define _TBLDEF 1 57 | static 58 | const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */ 59 | 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 60 | 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 61 | 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 62 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 63 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 64 | 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 65 | 0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, 66 | 0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 67 | }; 68 | 69 | #elif _CODE_PAGE == 771 70 | #define _TBLDEF 1 71 | static 72 | const WCHAR Tbl[] = { /* CP771(0x80-0xFF) to Unicode conversion table */ 73 | 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 74 | 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 75 | 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 76 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, 77 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 78 | 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D, 79 | 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, 80 | 0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0 81 | }; 82 | 83 | #elif _CODE_PAGE == 775 84 | #define _TBLDEF 1 85 | static 86 | const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */ 87 | 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, 88 | 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, 89 | 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, 90 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510, 91 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D, 92 | 0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 93 | 0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019, 94 | 0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 95 | }; 96 | 97 | #elif _CODE_PAGE == 850 98 | #define _TBLDEF 1 99 | static 100 | const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */ 101 | 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 102 | 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, 103 | 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 104 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, 105 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 106 | 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, 107 | 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, 108 | 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 109 | }; 110 | 111 | #elif _CODE_PAGE == 852 112 | #define _TBLDEF 1 113 | static 114 | const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */ 115 | 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, 116 | 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, 117 | 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, 118 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510, 119 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 120 | 0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, 121 | 0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4, 122 | 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0 123 | }; 124 | 125 | #elif _CODE_PAGE == 855 126 | #define _TBLDEF 1 127 | static 128 | const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */ 129 | 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, 130 | 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, 131 | 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, 132 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510, 133 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 134 | 0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, 135 | 0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116, 136 | 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0 137 | }; 138 | 139 | #elif _CODE_PAGE == 857 140 | #define _TBLDEF 1 141 | static 142 | const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */ 143 | 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, 144 | 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, 145 | 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 146 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, 147 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 148 | 0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, 149 | 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4, 150 | 0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 151 | }; 152 | 153 | #elif _CODE_PAGE == 860 154 | #define _TBLDEF 1 155 | static 156 | const WCHAR Tbl[] = { /* CP860(0x80-0xFF) to Unicode conversion table */ 157 | 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2, 158 | 0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3, 159 | 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 160 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, 161 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 162 | 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 163 | 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 164 | 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 165 | }; 166 | 167 | #elif _CODE_PAGE == 861 168 | #define _TBLDEF 1 169 | static 170 | const WCHAR Tbl[] = { /* CP861(0x80-0xFF) to Unicode conversion table */ 171 | 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5, 172 | 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, 173 | 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 174 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 175 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 176 | 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 177 | 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 178 | 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 179 | }; 180 | 181 | #elif _CODE_PAGE == 862 182 | #define _TBLDEF 1 183 | static 184 | const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */ 185 | 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 186 | 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, 187 | 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 188 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 189 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 190 | 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 191 | 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 192 | 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 193 | }; 194 | 195 | #elif _CODE_PAGE == 863 196 | #define _TBLDEF 1 197 | static 198 | const WCHAR Tbl[] = { /* CP863(0x80-0xFF) to Unicode conversion table */ 199 | 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0, 200 | 0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192, 201 | 0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB, 202 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 203 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 204 | 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 205 | 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219, 206 | 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 207 | }; 208 | 209 | #elif _CODE_PAGE == 864 210 | #define _TBLDEF 1 211 | static 212 | const WCHAR Tbl[] = { /* CP864(0x80-0xFF) to Unicode conversion table */ 213 | 0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518, 214 | 0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000, 215 | 0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5, 216 | 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F, 217 | 0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9, 218 | 0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9, 219 | 0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1, 220 | 0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000 221 | }; 222 | 223 | #elif _CODE_PAGE == 865 224 | #define _TBLDEF 1 225 | static 226 | const WCHAR Tbl[] = { /* CP865(0x80-0xFF) to Unicode conversion table */ 227 | 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 228 | 0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, 229 | 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4, 230 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, 231 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 232 | 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 233 | 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 234 | 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 235 | }; 236 | 237 | #elif _CODE_PAGE == 866 238 | #define _TBLDEF 1 239 | static 240 | const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */ 241 | 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 242 | 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 243 | 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 244 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 245 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 246 | 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 247 | 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, 248 | 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0 249 | }; 250 | 251 | #elif _CODE_PAGE == 869 252 | #define _TBLDEF 1 253 | static 254 | const WCHAR Tbl[] = { /* CP869(0x80-0xFF) to Unicode conversion table */ 255 | 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389, 256 | 0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF, 257 | 0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB, 258 | 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510, 259 | 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3, 260 | 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580, 261 | 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384, 262 | 0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0 263 | }; 264 | 265 | #endif 266 | 267 | 268 | #if !_TBLDEF || !_USE_LFN 269 | #error This file is not needed at current configuration. Remove from the project. 270 | #endif 271 | 272 | 273 | 274 | 275 | WCHAR ff_convert ( /* Converted character, Returns zero on error */ 276 | WCHAR chr, /* Character code to be converted */ 277 | UINT dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */ 278 | ) 279 | { 280 | WCHAR c; 281 | 282 | 283 | if (chr < 0x80) { /* ASCII */ 284 | c = chr; 285 | 286 | } else { 287 | if (dir) { /* OEM code to Unicode */ 288 | c = (chr >= 0x100) ? 0 : Tbl[chr - 0x80]; 289 | 290 | } else { /* Unicode to OEM code */ 291 | for (c = 0; c < 0x80; c++) { 292 | if (chr == Tbl[c]) break; 293 | } 294 | c = (c + 0x80) & 0xFF; 295 | } 296 | } 297 | 298 | return c; 299 | } 300 | 301 | 302 | 303 | WCHAR ff_wtoupper ( /* Returns upper converted character */ 304 | WCHAR chr /* Unicode character to be upper converted (BMP only) */ 305 | ) 306 | { 307 | /* Compressed upper conversion table */ 308 | static const WCHAR cvt1[] = { /* U+0000 - U+0FFF */ 309 | /* Basic Latin */ 310 | 0x0061,0x031A, 311 | /* Latin-1 Supplement */ 312 | 0x00E0,0x0317, 0x00F8,0x0307, 0x00FF,0x0001,0x0178, 313 | /* Latin Extended-A */ 314 | 0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106, 315 | /* Latin Extended-B */ 316 | 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, 317 | 0x01CD,0x0110, 0x01DD,0x0001,0x018E, 0x01DE,0x0112, 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, 0x01F8,0x0128, 318 | 0x0222,0x0112, 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, 0x0246,0x010A, 319 | /* IPA Extensions */ 320 | 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, 321 | /* Greek, Coptic */ 322 | 0x037B,0x0003,0x03FD,0x03FE,0x03FF, 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, 0x03B1,0x0311, 323 | 0x03C2,0x0002,0x03A3,0x03A3, 0x03C4,0x0308, 0x03CC,0x0003,0x038C,0x038E,0x038F, 0x03D8,0x0118, 324 | 0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA, 325 | /* Cyrillic */ 326 | 0x0430,0x0320, 0x0450,0x0710, 0x0460,0x0122, 0x048A,0x0136, 0x04C1,0x010E, 0x04CF,0x0001,0x04C0, 0x04D0,0x0144, 327 | /* Armenian */ 328 | 0x0561,0x0426, 329 | 330 | 0x0000 331 | }; 332 | static const WCHAR cvt2[] = { /* U+1000 - U+FFFF */ 333 | /* Phonetic Extensions */ 334 | 0x1D7D,0x0001,0x2C63, 335 | /* Latin Extended Additional */ 336 | 0x1E00,0x0196, 0x1EA0,0x015A, 337 | /* Greek Extended */ 338 | 0x1F00,0x0608, 0x1F10,0x0606, 0x1F20,0x0608, 0x1F30,0x0608, 0x1F40,0x0606, 339 | 0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, 0x1F60,0x0608, 340 | 0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB, 341 | 0x1F80,0x0608, 0x1F90,0x0608, 0x1FA0,0x0608, 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC, 342 | 0x1FCC,0x0001,0x1FC3, 0x1FD0,0x0602, 0x1FE0,0x0602, 0x1FE5,0x0001,0x1FEC, 0x1FF2,0x0001,0x1FFC, 343 | /* Letterlike Symbols */ 344 | 0x214E,0x0001,0x2132, 345 | /* Number forms */ 346 | 0x2170,0x0210, 0x2184,0x0001,0x2183, 347 | /* Enclosed Alphanumerics */ 348 | 0x24D0,0x051A, 0x2C30,0x042F, 349 | /* Latin Extended-C */ 350 | 0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102, 351 | /* Coptic */ 352 | 0x2C80,0x0164, 353 | /* Georgian Supplement */ 354 | 0x2D00,0x0826, 355 | /* Full-width */ 356 | 0xFF41,0x031A, 357 | 358 | 0x0000 359 | }; 360 | const WCHAR *p; 361 | WCHAR bc, nc, cmd; 362 | 363 | 364 | p = chr < 0x1000 ? cvt1 : cvt2; 365 | for (;;) { 366 | bc = *p++; /* Get block base */ 367 | if (!bc || chr < bc) break; 368 | nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */ 369 | if (chr < bc + nc) { /* In the block? */ 370 | switch (cmd) { 371 | case 0: chr = p[chr - bc]; break; /* Table conversion */ 372 | case 1: chr -= (chr - bc) & 1; break; /* Case pairs */ 373 | case 2: chr -= 16; break; /* Shift -16 */ 374 | case 3: chr -= 32; break; /* Shift -32 */ 375 | case 4: chr -= 48; break; /* Shift -48 */ 376 | case 5: chr -= 26; break; /* Shift -26 */ 377 | case 6: chr += 8; break; /* Shift +8 */ 378 | case 7: chr -= 80; break; /* Shift -80 */ 379 | case 8: chr -= 0x1C60; break; /* Shift -0x1C60 */ 380 | } 381 | break; 382 | } 383 | if (!cmd) p += nc; 384 | } 385 | 386 | return chr; 387 | } 388 | 389 | -------------------------------------------------------------------------------- /payload_stage2/source/fatfs/sdmmc/delay.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../types.h" 4 | 5 | void waitcycles(u32 us); 6 | -------------------------------------------------------------------------------- /payload_stage2/source/fatfs/sdmmc/delay.s: -------------------------------------------------------------------------------- 1 | .text 2 | .arm 3 | .align 4 4 | 5 | .global waitcycles 6 | .type waitcycles, %function 7 | waitcycles: 8 | push {r0-r2, lr} 9 | str r0, [sp, #4] 10 | waitcycles_loop: 11 | ldr r3, [sp, #4] 12 | subs r2, r3, #1 13 | str r2, [sp, #4] 14 | cmp r3, #0 15 | bne waitcycles_loop 16 | pop {r0-r2, pc} 17 | -------------------------------------------------------------------------------- /payload_stage2/source/fatfs/sdmmc/sdmmc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 | * You can obtain one at http://mozilla.org/MPL/2.0/. 5 | * 6 | * Copyright (c) 2014-2015, Normmatt 7 | * 8 | * Alternatively, the contents of this file may be used under the terms 9 | * of the GNU General Public License Version 2, as described below: 10 | * 11 | * This file is free software: you may copy, redistribute and/or modify 12 | * it under the terms of the GNU General Public License as published by the 13 | * Free Software Foundation, either version 2 of the License, or (at your 14 | * option) any later version. 15 | * 16 | * This file is distributed in the hope that it will be useful, but 17 | * WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 19 | * Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see http://www.gnu.org/licenses/. 23 | */ 24 | 25 | #include "sdmmc.h" 26 | #include "delay.h" 27 | 28 | static struct mmcdevice handleNAND; 29 | static struct mmcdevice handleSD; 30 | 31 | static inline u16 sdmmc_read16(u16 reg) 32 | { 33 | return *(vu16 *)(SDMMC_BASE + reg); 34 | } 35 | 36 | static inline void sdmmc_write16(u16 reg, u16 val) 37 | { 38 | *(vu16 *)(SDMMC_BASE + reg) = val; 39 | } 40 | 41 | static inline u32 sdmmc_read32(u16 reg) 42 | { 43 | return *(vu32 *)(SDMMC_BASE + reg); 44 | } 45 | 46 | static inline void sdmmc_write32(u16 reg, u32 val) 47 | { 48 | *(vu32 *)(SDMMC_BASE + reg) = val; 49 | } 50 | 51 | static inline void sdmmc_mask16(u16 reg, const u16 clear, const u16 set) 52 | { 53 | u16 val = sdmmc_read16(reg); 54 | val &= ~clear; 55 | val |= set; 56 | sdmmc_write16(reg, val); 57 | } 58 | 59 | static inline void setckl(u32 data) 60 | { 61 | sdmmc_mask16(REG_SDCLKCTL, 0x100, 0); 62 | sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF); 63 | sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100); 64 | } 65 | 66 | /* 67 | mmcdevice *getMMCDevice(int drive) 68 | { 69 | if(drive == 0) return &handleNAND; 70 | return &handleSD; 71 | } 72 | */ 73 | 74 | static int geterror(struct mmcdevice *ctx) 75 | { 76 | return (int)((ctx->error << 29) >> 31); 77 | } 78 | 79 | static void inittarget(struct mmcdevice *ctx) 80 | { 81 | sdmmc_mask16(REG_SDPORTSEL, 0x3, (u16)ctx->devicenumber); 82 | setckl(ctx->clk); 83 | if(ctx->SDOPT == 0) sdmmc_mask16(REG_SDOPT, 0, 0x8000); 84 | else sdmmc_mask16(REG_SDOPT, 0x8000, 0); 85 | } 86 | 87 | static void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args) 88 | { 89 | u32 getSDRESP = (cmd << 15) >> 31; 90 | u16 flags = (cmd << 15) >> 31; 91 | const int readdata = cmd & 0x20000; 92 | const int writedata = cmd & 0x40000; 93 | 94 | if(readdata || writedata) 95 | flags |= TMIO_STAT0_DATAEND; 96 | 97 | ctx->error = 0; 98 | while((sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY)); //mmc working? 99 | sdmmc_write16(REG_SDIRMASK0, 0); 100 | sdmmc_write16(REG_SDIRMASK1, 0); 101 | sdmmc_write16(REG_SDSTATUS0, 0); 102 | sdmmc_write16(REG_SDSTATUS1, 0); 103 | sdmmc_mask16(REG_DATACTL32, 0x1800, 0); 104 | sdmmc_write16(REG_SDCMDARG0, args & 0xFFFF); 105 | sdmmc_write16(REG_SDCMDARG1, args >> 16); 106 | sdmmc_write16(REG_SDCMD, cmd & 0xFFFF); 107 | 108 | u32 size = ctx->size; 109 | u8 *rDataPtr = ctx->rData; 110 | const u8 *tDataPtr = ctx->tData; 111 | 112 | bool rUseBuf = rDataPtr != NULL; 113 | bool tUseBuf = tDataPtr != NULL; 114 | 115 | u16 status0 = 0; 116 | while(true) 117 | { 118 | vu16 status1 = sdmmc_read16(REG_SDSTATUS1); 119 | vu16 ctl32 = sdmmc_read16(REG_DATACTL32); 120 | if((ctl32 & 0x100)) 121 | { 122 | if(readdata) 123 | { 124 | if(rUseBuf) 125 | { 126 | sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0); 127 | if(size > 0x1FF) 128 | { 129 | //Gabriel Marcano: This implementation doesn't assume alignment. 130 | //I've removed the alignment check doen with former rUseBuf32 as a result 131 | for(int i = 0; i < 0x200; i += 4) 132 | { 133 | u32 data = sdmmc_read32(REG_SDFIFO32); 134 | *rDataPtr++ = data; 135 | *rDataPtr++ = data >> 8; 136 | *rDataPtr++ = data >> 16; 137 | *rDataPtr++ = data >> 24; 138 | } 139 | size -= 0x200; 140 | } 141 | } 142 | 143 | sdmmc_mask16(REG_DATACTL32, 0x800, 0); 144 | } 145 | } 146 | if(!(ctl32 & 0x200)) 147 | { 148 | if(writedata) 149 | { 150 | if(tUseBuf) 151 | { 152 | sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0); 153 | if(size > 0x1FF) 154 | { 155 | for(int i = 0; i < 0x200; i += 4) 156 | { 157 | u32 data = *tDataPtr++; 158 | data |= (u32)*tDataPtr++ << 8; 159 | data |= (u32)*tDataPtr++ << 16; 160 | data |= (u32)*tDataPtr++ << 24; 161 | sdmmc_write32(REG_SDFIFO32, data); 162 | } 163 | size -= 0x200; 164 | } 165 | } 166 | 167 | sdmmc_mask16(REG_DATACTL32, 0x1000, 0); 168 | } 169 | } 170 | if(status1 & TMIO_MASK_GW) 171 | { 172 | ctx->error |= 4; 173 | break; 174 | } 175 | 176 | if(!(status1 & TMIO_STAT1_CMD_BUSY)) 177 | { 178 | status0 = sdmmc_read16(REG_SDSTATUS0); 179 | if(sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND) 180 | { 181 | ctx->error |= 0x1; 182 | } 183 | if(status0 & TMIO_STAT0_DATAEND) 184 | { 185 | ctx->error |= 0x2; 186 | } 187 | 188 | if((status0 & flags) == flags) 189 | break; 190 | } 191 | } 192 | ctx->stat0 = sdmmc_read16(REG_SDSTATUS0); 193 | ctx->stat1 = sdmmc_read16(REG_SDSTATUS1); 194 | sdmmc_write16(REG_SDSTATUS0, 0); 195 | sdmmc_write16(REG_SDSTATUS1, 0); 196 | 197 | if(getSDRESP != 0) 198 | { 199 | ctx->ret[0] = (u32)(sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16)); 200 | ctx->ret[1] = (u32)(sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16)); 201 | ctx->ret[2] = (u32)(sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16)); 202 | ctx->ret[3] = (u32)(sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16)); 203 | } 204 | } 205 | 206 | /* 207 | int __attribute__((noinline)) sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in) 208 | { 209 | if(handleSD.isSDHC == 0) sector_no <<= 9; 210 | inittarget(&handleSD); 211 | sdmmc_write16(REG_SDSTOP, 0x100); 212 | sdmmc_write16(REG_SDBLKCOUNT32, numsectors); 213 | sdmmc_write16(REG_SDBLKLEN32, 0x200); 214 | sdmmc_write16(REG_SDBLKCOUNT, numsectors); 215 | handleSD.tData = in; 216 | handleSD.size = numsectors << 9; 217 | sdmmc_send_command(&handleSD, 0x52C19, sector_no); 218 | return geterror(&handleSD); 219 | } 220 | */ 221 | 222 | int __attribute__((noinline)) sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out) 223 | { 224 | if(handleSD.isSDHC == 0) sector_no <<= 9; 225 | inittarget(&handleSD); 226 | sdmmc_write16(REG_SDSTOP, 0x100); 227 | sdmmc_write16(REG_SDBLKCOUNT32, numsectors); 228 | sdmmc_write16(REG_SDBLKLEN32, 0x200); 229 | sdmmc_write16(REG_SDBLKCOUNT, numsectors); 230 | handleSD.rData = out; 231 | handleSD.size = numsectors << 9; 232 | sdmmc_send_command(&handleSD, 0x33C12, sector_no); 233 | return geterror(&handleSD); 234 | } 235 | 236 | int __attribute__((noinline)) sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out) 237 | { 238 | if(handleNAND.isSDHC == 0) sector_no <<= 9; 239 | inittarget(&handleNAND); 240 | sdmmc_write16(REG_SDSTOP, 0x100); 241 | sdmmc_write16(REG_SDBLKCOUNT32, numsectors); 242 | sdmmc_write16(REG_SDBLKLEN32, 0x200); 243 | sdmmc_write16(REG_SDBLKCOUNT, numsectors); 244 | handleNAND.rData = out; 245 | handleNAND.size = numsectors << 9; 246 | sdmmc_send_command(&handleNAND, 0x33C12, sector_no); 247 | inittarget(&handleSD); 248 | return geterror(&handleNAND); 249 | } 250 | 251 | /* 252 | int __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in) //experimental 253 | { 254 | if(handleNAND.isSDHC == 0) sector_no <<= 9; 255 | inittarget(&handleNAND); 256 | sdmmc_write16(REG_SDSTOP, 0x100); 257 | sdmmc_write16(REG_SDBLKCOUNT32, numsectors); 258 | sdmmc_write16(REG_SDBLKLEN32, 0x200); 259 | sdmmc_write16(REG_SDBLKCOUNT, numsectors); 260 | handleNAND.tData = in; 261 | handleNAND.size = numsectors << 9; 262 | sdmmc_send_command(&handleNAND, 0x52C19, sector_no); 263 | inittarget(&handleSD); 264 | return geterror(&handleNAND); 265 | } 266 | */ 267 | 268 | static u32 calcSDSize(u8 *csd, int type) 269 | { 270 | u32 result = 0; 271 | if(type == -1) type = csd[14] >> 6; 272 | switch(type) 273 | { 274 | case 0: 275 | { 276 | u32 block_len = csd[9] & 0xF; 277 | block_len = 1u << block_len; 278 | u32 mult = (u32)((csd[4] >> 7) | ((csd[5] & 3) << 1)); 279 | mult = 1u << (mult + 2); 280 | result = csd[8] & 3; 281 | result = (result << 8) | csd[7]; 282 | result = (result << 2) | (csd[6] >> 6); 283 | result = (result + 1) * mult * block_len / 512; 284 | break; 285 | } 286 | case 1: 287 | result = csd[7] & 0x3F; 288 | result = (result << 8) | csd[6]; 289 | result = (result << 8) | csd[5]; 290 | result = (result + 1) * 1024; 291 | break; 292 | default: 293 | break; //Do nothing otherwise FIXME perhaps return some error? 294 | } 295 | return result; 296 | } 297 | 298 | static void InitSD() 299 | { 300 | *(vu16 *)0x10006100 &= 0xF7FFu; //SDDATACTL32 301 | *(vu16 *)0x10006100 &= 0xEFFFu; //SDDATACTL32 302 | *(vu16 *)0x10006100 |= 0x402u; //SDDATACTL32 303 | *(vu16 *)0x100060D8 = (*(vu16 *)0x100060D8 & 0xFFDD) | 2; 304 | *(vu16 *)0x10006100 &= 0xFFFFu; //SDDATACTL32 305 | *(vu16 *)0x100060D8 &= 0xFFDFu; //SDDATACTL 306 | *(vu16 *)0x10006104 = 512; //SDBLKLEN32 307 | *(vu16 *)0x10006108 = 1; //SDBLKCOUNT32 308 | *(vu16 *)0x100060E0 &= 0xFFFEu; //SDRESET 309 | *(vu16 *)0x100060E0 |= 1u; //SDRESET 310 | *(vu16 *)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0 311 | *(vu16 *)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1 312 | *(vu16 *)0x100060FC |= 0xDBu; //SDCTL_RESERVED7 313 | *(vu16 *)0x100060FE |= 0xDBu; //SDCTL_RESERVED8 314 | *(vu16 *)0x10006002 &= 0xFFFCu; //SDPORTSEL 315 | *(vu16 *)0x10006024 = 0x20; 316 | *(vu16 *)0x10006028 = 0x40EE; 317 | *(vu16 *)0x10006002 &= 0xFFFCu; ////SDPORTSEL 318 | *(vu16 *)0x10006026 = 512; //SDBLKLEN 319 | *(vu16 *)0x10006008 = 0; //SDSTOP 320 | } 321 | 322 | static int Nand_Init() 323 | { 324 | //NAND 325 | handleNAND.isSDHC = 0; 326 | handleNAND.SDOPT = 0; 327 | handleNAND.res = 0; 328 | handleNAND.initarg = 1; 329 | handleNAND.clk = 0x80; 330 | handleNAND.devicenumber = 1; 331 | 332 | inittarget(&handleNAND); 333 | waitcycles(0xF000); 334 | 335 | sdmmc_send_command(&handleNAND, 0, 0); 336 | 337 | do 338 | { 339 | do 340 | { 341 | sdmmc_send_command(&handleNAND, 0x10701, 0x100000); 342 | } 343 | while(!(handleNAND.error & 1)); 344 | } 345 | while((handleNAND.ret[0] & 0x80000000) == 0); 346 | 347 | sdmmc_send_command(&handleNAND, 0x10602, 0x0); 348 | if((handleNAND.error & 0x4)) return -1; 349 | 350 | sdmmc_send_command(&handleNAND, 0x10403, handleNAND.initarg << 0x10); 351 | if((handleNAND.error & 0x4)) return -1; 352 | 353 | sdmmc_send_command(&handleNAND, 0x10609, handleNAND.initarg << 0x10); 354 | if((handleNAND.error & 0x4)) return -1; 355 | 356 | handleNAND.total_size = calcSDSize((u8*)&handleNAND.ret[0], 0); 357 | handleNAND.clk = 1; 358 | setckl(1); 359 | 360 | sdmmc_send_command(&handleNAND, 0x10407, handleNAND.initarg << 0x10); 361 | if((handleNAND.error & 0x4)) return -1; 362 | 363 | handleNAND.SDOPT = 1; 364 | 365 | sdmmc_send_command(&handleNAND, 0x10506, 0x3B70100); 366 | if((handleNAND.error & 0x4)) return -1; 367 | 368 | sdmmc_send_command(&handleNAND, 0x10506, 0x3B90100); 369 | if((handleNAND.error & 0x4)) return -1; 370 | 371 | sdmmc_send_command(&handleNAND, 0x1040D, handleNAND.initarg << 0x10); 372 | if((handleNAND.error & 0x4)) return -1; 373 | 374 | sdmmc_send_command(&handleNAND, 0x10410, 0x200); 375 | if((handleNAND.error & 0x4)) return -1; 376 | 377 | handleNAND.clk |= 0x200; 378 | 379 | inittarget(&handleSD); 380 | 381 | return 0; 382 | } 383 | 384 | static int SD_Init() 385 | { 386 | //SD 387 | handleSD.isSDHC = 0; 388 | handleSD.SDOPT = 0; 389 | handleSD.res = 0; 390 | handleSD.initarg = 0; 391 | handleSD.clk = 0x80; 392 | handleSD.devicenumber = 0; 393 | 394 | inittarget(&handleSD); 395 | 396 | 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 397 | 398 | //If not inserted 399 | if(!(*((vu16 *)(SDMMC_BASE + REG_SDSTATUS0)) & TMIO_STAT0_SIGSTATE)) return 5; 400 | 401 | sdmmc_send_command(&handleSD, 0, 0); 402 | sdmmc_send_command(&handleSD, 0x10408, 0x1AA); 403 | u32 temp = (handleSD.error & 0x1) << 0x1E; 404 | 405 | u32 temp2 = 0; 406 | do 407 | { 408 | do 409 | { 410 | sdmmc_send_command(&handleSD, 0x10437, handleSD.initarg << 0x10); 411 | sdmmc_send_command(&handleSD, 0x10769, 0x00FF8000 | temp); 412 | temp2 = 1; 413 | } 414 | while(!(handleSD.error & 1)); 415 | } 416 | while((handleSD.ret[0] & 0x80000000) == 0); 417 | 418 | if(!((handleSD.ret[0] >> 30) & 1) || !temp) 419 | temp2 = 0; 420 | 421 | handleSD.isSDHC = temp2; 422 | 423 | sdmmc_send_command(&handleSD, 0x10602, 0); 424 | if((handleSD.error & 0x4)) return -1; 425 | 426 | sdmmc_send_command(&handleSD, 0x10403, 0); 427 | if((handleSD.error & 0x4)) return -2; 428 | handleSD.initarg = handleSD.ret[0] >> 0x10; 429 | 430 | sdmmc_send_command(&handleSD, 0x10609, handleSD.initarg << 0x10); 431 | if((handleSD.error & 0x4)) return -3; 432 | 433 | handleSD.total_size = calcSDSize((u8*)&handleSD.ret[0], -1); 434 | handleSD.clk = 1; 435 | setckl(1); 436 | 437 | sdmmc_send_command(&handleSD, 0x10507, handleSD.initarg << 0x10); 438 | if((handleSD.error & 0x4)) return -4; 439 | 440 | sdmmc_send_command(&handleSD, 0x10437, handleSD.initarg << 0x10); 441 | if((handleSD.error & 0x4)) return -5; 442 | 443 | handleSD.SDOPT = 1; 444 | sdmmc_send_command(&handleSD, 0x10446, 0x2); 445 | if((handleSD.error & 0x4)) return -6; 446 | 447 | sdmmc_send_command(&handleSD, 0x1040D, handleSD.initarg << 0x10); 448 | if((handleSD.error & 0x4)) return -7; 449 | 450 | sdmmc_send_command(&handleSD, 0x10410, 0x200); 451 | if((handleSD.error & 0x4)) return -8; 452 | handleSD.clk |= 0x200; 453 | 454 | return 0; 455 | } 456 | 457 | void sdmmc_get_cid(bool isNand, u32 *info) 458 | { 459 | struct mmcdevice *device = isNand ? &handleNAND : &handleSD; 460 | 461 | inittarget(device); 462 | 463 | // use cmd7 to put sd card in standby mode 464 | // CMD7 465 | sdmmc_send_command(device, 0x10507, 0); 466 | 467 | // get sd card info 468 | // use cmd10 to read CID 469 | sdmmc_send_command(device, 0x1060A, device->initarg << 0x10); 470 | 471 | for(int i = 0; i < 4; ++i) 472 | info[i] = device->ret[i]; 473 | 474 | // put sd card back to transfer mode 475 | // CMD7 476 | sdmmc_send_command(device, 0x10507, device->initarg << 0x10); 477 | } 478 | 479 | u32 sdmmc_sdcard_init() 480 | { 481 | u32 ret = 0; 482 | InitSD(); 483 | if(Nand_Init() != 0) ret &= 1; 484 | if(SD_Init() != 0) ret &= 2; 485 | return ret; 486 | } -------------------------------------------------------------------------------- /payload_stage2/source/fatfs/sdmmc/sdmmc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../types.h" 4 | 5 | #define SDMMC_BASE 0x10006000 6 | 7 | #define REG_SDCMD 0x00 8 | #define REG_SDPORTSEL 0x02 9 | #define REG_SDCMDARG 0x04 10 | #define REG_SDCMDARG0 0x04 11 | #define REG_SDCMDARG1 0x06 12 | #define REG_SDSTOP 0x08 13 | #define REG_SDBLKCOUNT 0x0A 14 | 15 | #define REG_SDRESP0 0x0C 16 | #define REG_SDRESP1 0x0E 17 | #define REG_SDRESP2 0x10 18 | #define REG_SDRESP3 0x12 19 | #define REG_SDRESP4 0x14 20 | #define REG_SDRESP5 0x16 21 | #define REG_SDRESP6 0x18 22 | #define REG_SDRESP7 0x1A 23 | 24 | #define REG_SDSTATUS0 0x1C 25 | #define REG_SDSTATUS1 0x1E 26 | 27 | #define REG_SDIRMASK0 0x20 28 | #define REG_SDIRMASK1 0x22 29 | #define REG_SDCLKCTL 0x24 30 | 31 | #define REG_SDBLKLEN 0x26 32 | #define REG_SDOPT 0x28 33 | #define REG_SDFIFO 0x30 34 | 35 | #define REG_DATACTL 0xD8 36 | #define REG_SDRESET 0xE0 37 | #define REG_SDPROTECTED 0xF6 //bit 0 determines if sd is protected or not? 38 | 39 | #define REG_DATACTL32 0x100 40 | #define REG_SDBLKLEN32 0x104 41 | #define REG_SDBLKCOUNT32 0x108 42 | #define REG_SDFIFO32 0x10C 43 | 44 | #define REG_CLK_AND_WAIT_CTL 0x138 45 | #define REG_RESET_SDIO 0x1E0 46 | 47 | #define TMIO_STAT0_CMDRESPEND 0x0001 48 | #define TMIO_STAT0_DATAEND 0x0004 49 | #define TMIO_STAT0_CARD_REMOVE 0x0008 50 | #define TMIO_STAT0_CARD_INSERT 0x0010 51 | #define TMIO_STAT0_SIGSTATE 0x0020 52 | #define TMIO_STAT0_WRPROTECT 0x0080 53 | #define TMIO_STAT0_CARD_REMOVE_A 0x0100 54 | #define TMIO_STAT0_CARD_INSERT_A 0x0200 55 | #define TMIO_STAT0_SIGSTATE_A 0x0400 56 | #define TMIO_STAT1_CMD_IDX_ERR 0x0001 57 | #define TMIO_STAT1_CRCFAIL 0x0002 58 | #define TMIO_STAT1_STOPBIT_ERR 0x0004 59 | #define TMIO_STAT1_DATATIMEOUT 0x0008 60 | #define TMIO_STAT1_RXOVERFLOW 0x0010 61 | #define TMIO_STAT1_TXUNDERRUN 0x0020 62 | #define TMIO_STAT1_CMDTIMEOUT 0x0040 63 | #define TMIO_STAT1_RXRDY 0x0100 64 | #define TMIO_STAT1_TXRQ 0x0200 65 | #define TMIO_STAT1_ILL_FUNC 0x2000 66 | #define TMIO_STAT1_CMD_BUSY 0x4000 67 | #define TMIO_STAT1_ILL_ACCESS 0x8000 68 | 69 | #define TMIO_MASK_ALL 0x837F031D 70 | 71 | #define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \ 72 | TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR) 73 | 74 | #define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND) 75 | #define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND) 76 | 77 | typedef struct mmcdevice { 78 | u8 *rData; 79 | const u8 *tData; 80 | u32 size; 81 | u32 error; 82 | u16 stat0; 83 | u16 stat1; 84 | u32 ret[4]; 85 | u32 initarg; 86 | u32 isSDHC; 87 | u32 clk; 88 | u32 SDOPT; 89 | u32 devicenumber; 90 | u32 total_size; //size in sectors of the device 91 | u32 res; 92 | } mmcdevice; 93 | 94 | u32 sdmmc_sdcard_init(); 95 | int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out); 96 | //int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in); 97 | int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out); 98 | //int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in); 99 | void sdmmc_get_cid(bool isNand, u32 *info); 100 | //mmcdevice *getMMCDevice(int drive); -------------------------------------------------------------------------------- /payload_stage2/source/fs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * fs.c 3 | */ 4 | 5 | #include "fs.h" 6 | #include "fatfs/ff.h" 7 | 8 | static FATFS fs; 9 | 10 | bool mountSd(void) 11 | { 12 | return f_mount(&fs, "0:", 1) == FR_OK; 13 | } 14 | 15 | void unmountSd(void) 16 | { 17 | f_mount(NULL, "0:", 1); 18 | } 19 | 20 | bool mountCtrNand(void) 21 | { 22 | return f_mount(&fs, "1:", 1) == FR_OK && f_chdrive("1:") == FR_OK; 23 | } 24 | 25 | u32 fileRead(void *dest, const char *path, u32 maxSize) 26 | { 27 | FIL file; 28 | u32 ret = 0; 29 | 30 | if(f_open(&file, path, FA_READ) != FR_OK) return ret; 31 | 32 | u32 size = f_size(&file); 33 | if(size <= maxSize) 34 | f_read(&file, dest, size, (unsigned int *)&ret); 35 | f_close(&file); 36 | 37 | return ret; 38 | } -------------------------------------------------------------------------------- /payload_stage2/source/fs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fs.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include "types.h" 8 | 9 | bool mountSd(void); 10 | void unmountSd(void); 11 | bool mountCtrNand(void); 12 | u32 fileRead(void *dest, const char *path, u32 maxSize); -------------------------------------------------------------------------------- /payload_stage2/source/i2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Luma3DS 3 | * Copyright (C) 2016 Aurora Wright, TuxSH 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified 19 | * reasonable legal notices or author attributions in that material or in the Appropriate Legal 20 | * Notices displayed by works containing it. 21 | */ 22 | 23 | /* 24 | * Thanks to the everyone who contributed in the development of this file 25 | */ 26 | 27 | #include "i2c.h" 28 | 29 | //----------------------------------------------------------------------------- 30 | 31 | static const struct { u8 bus_id, reg_addr; } dev_data[] = { 32 | {0, 0x4A}, {0, 0x7A}, {0, 0x78}, 33 | {1, 0x4A}, {1, 0x78}, {1, 0x2C}, 34 | {1, 0x2E}, {1, 0x40}, {1, 0x44}, 35 | {2, 0xD6}, {2, 0xD0}, {2, 0xD2}, 36 | {2, 0xA4}, {2, 0x9A}, {2, 0xA0}, 37 | }; 38 | 39 | static inline u8 i2cGetDeviceBusId(u8 device_id) 40 | { 41 | return dev_data[device_id].bus_id; 42 | } 43 | 44 | static inline u8 i2cGetDeviceRegAddr(u8 device_id) 45 | { 46 | return dev_data[device_id].reg_addr; 47 | } 48 | 49 | //----------------------------------------------------------------------------- 50 | 51 | static vu8 *reg_data_addrs[] = { 52 | (vu8 *)(I2C1_REG_OFF + I2C_REG_DATA), 53 | (vu8 *)(I2C2_REG_OFF + I2C_REG_DATA), 54 | (vu8 *)(I2C3_REG_OFF + I2C_REG_DATA), 55 | }; 56 | 57 | static inline vu8 *i2cGetDataReg(u8 bus_id) 58 | { 59 | return reg_data_addrs[bus_id]; 60 | } 61 | 62 | //----------------------------------------------------------------------------- 63 | 64 | static vu8 *reg_cnt_addrs[] = { 65 | (vu8 *)(I2C1_REG_OFF + I2C_REG_CNT), 66 | (vu8 *)(I2C2_REG_OFF + I2C_REG_CNT), 67 | (vu8 *)(I2C3_REG_OFF + I2C_REG_CNT), 68 | }; 69 | 70 | static inline vu8 *i2cGetCntReg(u8 bus_id) 71 | { 72 | return reg_cnt_addrs[bus_id]; 73 | } 74 | 75 | //----------------------------------------------------------------------------- 76 | 77 | static inline void i2cWaitBusy(u8 bus_id) 78 | { 79 | while (*i2cGetCntReg(bus_id) & 0x80); 80 | } 81 | 82 | static inline bool i2cGetResult(u8 bus_id) 83 | { 84 | i2cWaitBusy(bus_id); 85 | 86 | return (*i2cGetCntReg(bus_id) >> 4) & 1; 87 | } 88 | 89 | static void i2cStop(u8 bus_id, u8 arg0) 90 | { 91 | *i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0; 92 | i2cWaitBusy(bus_id); 93 | *i2cGetCntReg(bus_id) = 0xC5; 94 | } 95 | 96 | //----------------------------------------------------------------------------- 97 | 98 | static bool i2cSelectDevice(u8 bus_id, u8 dev_reg) 99 | { 100 | i2cWaitBusy(bus_id); 101 | *i2cGetDataReg(bus_id) = dev_reg; 102 | *i2cGetCntReg(bus_id) = 0xC2; 103 | 104 | return i2cGetResult(bus_id); 105 | } 106 | 107 | static bool i2cSelectRegister(u8 bus_id, u8 reg) 108 | { 109 | i2cWaitBusy(bus_id); 110 | *i2cGetDataReg(bus_id) = reg; 111 | *i2cGetCntReg(bus_id) = 0xC0; 112 | 113 | return i2cGetResult(bus_id); 114 | } 115 | 116 | //----------------------------------------------------------------------------- 117 | 118 | bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data) 119 | { 120 | u8 bus_id = i2cGetDeviceBusId(dev_id), 121 | dev_addr = i2cGetDeviceRegAddr(dev_id); 122 | 123 | for(u32 i = 0; i < 8; i++) 124 | { 125 | if(i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) 126 | { 127 | i2cWaitBusy(bus_id); 128 | *i2cGetDataReg(bus_id) = data; 129 | *i2cGetCntReg(bus_id) = 0xC1; 130 | i2cStop(bus_id, 0); 131 | 132 | if(i2cGetResult(bus_id)) return true; 133 | } 134 | *i2cGetCntReg(bus_id) = 0xC5; 135 | i2cWaitBusy(bus_id); 136 | } 137 | 138 | return false; 139 | } -------------------------------------------------------------------------------- /payload_stage2/source/i2c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Luma3DS 3 | * Copyright (C) 2016 Aurora Wright, TuxSH 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified 19 | * reasonable legal notices or author attributions in that material or in the Appropriate Legal 20 | * Notices displayed by works containing it. 21 | */ 22 | 23 | /* 24 | * Thanks to the everyone who contributed in the development of this file 25 | */ 26 | 27 | #pragma once 28 | 29 | #include "types.h" 30 | 31 | #define I2C1_REG_OFF 0x10161000 32 | #define I2C2_REG_OFF 0x10144000 33 | #define I2C3_REG_OFF 0x10148000 34 | 35 | #define I2C_REG_DATA 0 36 | #define I2C_REG_CNT 1 37 | #define I2C_REG_CNTEX 2 38 | #define I2C_REG_SCL 4 39 | 40 | #define I2C_DEV_MCU 3 41 | #define I2C_DEV_GYRO 10 42 | #define I2C_DEV_IR 13 43 | 44 | bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data); -------------------------------------------------------------------------------- /payload_stage2/source/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | */ 4 | 5 | #include "types.h" 6 | #include "memory.h" 7 | #include "crypto.h" 8 | #include "i2c.h" 9 | #include "cache.h" 10 | #include "fs.h" 11 | #include "../build/bundled.h" 12 | 13 | #define A11_PAYLOAD_LOC 0x1FFF4C80 //Keep in mind this needs to be changed in the ld script for arm11 too 14 | #define A11_ENTRYPOINT 0x1FFFFFF8 15 | #define PAYLOAD_ADDRESS 0x23F00000 16 | #define MAX_PAYLOAD_SIZE 0xFFE00 //Beyond this the fb struct is overwritten 17 | 18 | static void ownArm11(bool isScreenInit) 19 | { 20 | memcpy((void *)A11_PAYLOAD_LOC, arm11_bin, arm11_bin_size); 21 | 22 | //Let the ARM11 code know if it needs to screen init 23 | ((vu32 *)A11_PAYLOAD_LOC)[2] = isScreenInit ? 1 : 0; 24 | 25 | *(vu32 *)A11_ENTRYPOINT = 1; 26 | *(vu32 *)0x1FFAED80 = 0xE51FF004; 27 | *(vu32 *)0x1FFAED84 = A11_PAYLOAD_LOC; 28 | *(vu8 *)0x1FFFFFF0 = 2; 29 | while(*(vu32 *)A11_ENTRYPOINT != 0); 30 | } 31 | 32 | static void loadPayload(bool isNand) 33 | { 34 | bool payloadFound; 35 | 36 | //No-screeninit payload 37 | if(fileRead((void *)PAYLOAD_ADDRESS, "arm9loaderhax.bin", MAX_PAYLOAD_SIZE) != 0) 38 | { 39 | payloadFound = true; 40 | ownArm11(false); 41 | } 42 | 43 | //Screeninit payload 44 | else if(fileRead((void *)PAYLOAD_ADDRESS, "arm9loaderhax_si.bin", MAX_PAYLOAD_SIZE) != 0) 45 | { 46 | payloadFound = true; 47 | ownArm11(true); 48 | i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A); //Turn on backlight 49 | } 50 | else payloadFound = false; 51 | 52 | //Jump to payload 53 | if(payloadFound) 54 | { 55 | if(isNand) restoreShaHashBackup(); 56 | flushEntireDCache(); 57 | flushEntireICache(); 58 | ((void (*)())PAYLOAD_ADDRESS)(); 59 | } 60 | } 61 | 62 | void main(void) 63 | { 64 | if(mountSd()) 65 | { 66 | loadPayload(false); 67 | unmountSd(); 68 | } 69 | 70 | if(mountCtrNand()) loadPayload(true); 71 | 72 | //Shutdown 73 | flushEntireDCache(); 74 | i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0); 75 | while(true); 76 | } -------------------------------------------------------------------------------- /payload_stage2/source/memory.c: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | 3 | void memcpy(void *dest, const void *src, u32 size) 4 | { 5 | u8 *destc = (u8 *)dest; 6 | const u8 *srcc = (const u8 *)src; 7 | 8 | for(u32 i = 0; i < size; i++) 9 | destc[i] = srcc[i]; 10 | } -------------------------------------------------------------------------------- /payload_stage2/source/memory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * memcpy adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c 3 | */ 4 | 5 | #pragma once 6 | 7 | #include "types.h" 8 | 9 | void memcpy(void *dest, const void *src, u32 size); -------------------------------------------------------------------------------- /payload_stage2/source/start.s: -------------------------------------------------------------------------------- 1 | .section .text.start 2 | .align 4 3 | .global _start 4 | _start: 5 | 6 | b main 7 | -------------------------------------------------------------------------------- /payload_stage2/source/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * types.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | //Common data types 12 | typedef uint8_t u8; 13 | typedef uint16_t u16; 14 | typedef uint32_t u32; 15 | typedef uint64_t u64; 16 | typedef volatile u8 vu8; 17 | typedef volatile u16 vu16; 18 | typedef volatile u32 vu32; 19 | typedef volatile u64 vu64; --------------------------------------------------------------------------------