├── .gitignore ├── .gitmodules ├── LICENSE.txt ├── Makefile ├── README.md ├── linker.ld ├── patches ├── emunand.s └── reboot.s └── source ├── buttons.h ├── crypto.c ├── crypto.h ├── draw.c ├── draw.h ├── emunand.c ├── emunand.h ├── fatfs ├── 00readme.txt ├── diskio.c ├── diskio.h ├── ff.c ├── ff.h ├── ffconf.h ├── history.txt ├── integer.h └── sdmmc │ ├── common.h │ ├── delay.h │ ├── delay.s │ ├── sdmmc.c │ └── sdmmc.h ├── firm.c ├── firm.h ├── font.h ├── fs.c ├── fs.h ├── i2c.c ├── i2c.h ├── main.c ├── memory.c ├── memory.h ├── patches.c ├── patches.h ├── screeninit.c ├── screeninit.h ├── start.s ├── types.h ├── utils.c └── utils.h /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | build 3 | loader/build 4 | injector/build 5 | *.bin 6 | *.3dsx 7 | *.smdh 8 | *.o 9 | *.d 10 | *.elf 11 | *.bat -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "CakeBrah"] 2 | path = CakeBrah 3 | url = https://github.com/mid-kid/CakeBrah 4 | [submodule "CakeHax"] 5 | path = CakeHax 6 | url = https://github.com/mid-kid/CakeHax 7 | [submodule "injector"] 8 | path = injector 9 | url = https://github.com/yifanlu/3ds_injector.git 10 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) 2 | 3 | CC := arm-none-eabi-gcc 4 | AS := arm-none-eabi-as 5 | LD := arm-none-eabi-ld 6 | OC := arm-none-eabi-objcopy 7 | 8 | name := Cosmo3DS 9 | version := $(shell git describe --abbrev=0 --tags) 10 | 11 | dir_source := source 12 | dir_patches := patches 13 | dir_injector := injector 14 | dir_mset := CakeHax 15 | dir_ninjhax := CakeBrah 16 | dir_build := build 17 | dir_out := out 18 | 19 | ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te 20 | CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -ffast-math 21 | CFLAGS += -DCONFIG_TITLE="\"$(name) $(version) configuration\"" 22 | FLAGS := name=$(name).dat dir_out=$(abspath $(dir_out)) APP_DESCRIPTION="Noob-friendly 3DS CFW." APP_AUTHOR="Reisyukaku/Aurora Wright" --no-print-directory 23 | 24 | objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ 25 | $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ 26 | $(call rwildcard, $(dir_source), *.s *.c))) 27 | 28 | 29 | .PHONY: all 30 | all: launcher a9lh ninjhax 31 | 32 | .PHONY: launcher 33 | launcher: $(dir_out)/$(name).dat 34 | 35 | .PHONY: a9lh 36 | a9lh: $(dir_out)/arm9loaderhax.bin 37 | 38 | .PHONY: ninjhax 39 | ninjhax: $(dir_out)/3ds/$(name) 40 | 41 | .PHONY: release 42 | release: $(dir_out)/$(name).zip 43 | 44 | .PHONY: clean 45 | clean: 46 | @$(MAKE) $(FLAGS) -C $(dir_mset) clean 47 | @$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean 48 | @rm -rf $(dir_out) $(dir_build) 49 | @$(MAKE) -C $(dir_injector) clean 50 | 51 | $(dir_out): 52 | @mkdir -p "$(dir_out)" 53 | 54 | $(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out) 55 | @$(MAKE) $(FLAGS) -C $(dir_mset) launcher 56 | @dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144 57 | 58 | $(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out) 59 | @cp -av $(dir_build)/main.bin $@ 60 | 61 | $(dir_out)/3ds/$(name): $(dir_out) 62 | @mkdir -p "$(dir_out)/3ds/$(name)" 63 | @$(MAKE) $(FLAGS) -C $(dir_ninjhax) 64 | @mv $(dir_out)/$(name).3dsx $@ 65 | @mv $(dir_out)/$(name).smdh $@ 66 | 67 | $(dir_out)/$(name).zip: launcher a9lh ninjhax 68 | @cd $(dir_out) && zip -9 -r $(name) * 69 | 70 | $(dir_build)/patches.h: $(dir_patches)/emunand.s $(dir_patches)/reboot.s $(dir_injector)/Makefile 71 | @mkdir -p "$(dir_build)" 72 | @armips $< 73 | @armips $(word 2,$^) 74 | @$(MAKE) -C $(dir_injector) 75 | @mv emunand.bin reboot.bin $(dir_injector)/injector.cxi $(dir_build) 76 | @bin2c -o $@ -n emunand $(dir_build)/emunand.bin -n reboot $(dir_build)/reboot.bin -n injector $(dir_build)/injector.cxi 77 | 78 | $(dir_build)/main.bin: $(dir_build)/main.elf 79 | $(OC) -S -O binary $< $@ 80 | 81 | $(dir_build)/main.elf: $(objects_cfw) 82 | # FatFs requires libgcc for __aeabi_uidiv 83 | $(CC) -nostartfiles $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^ 84 | 85 | $(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/patches.h 86 | @mkdir -p "$(@D)" 87 | $(COMPILE.c) $(OUTPUT_OPTION) $< 88 | 89 | $(dir_build)/%.o: $(dir_source)/%.s 90 | @mkdir -p "$(@D)" 91 | $(COMPILE.s) $(OUTPUT_OPTION) $< 92 | 93 | $(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.c 94 | @mkdir -p "$(@D)" 95 | $(COMPILE.c) -mthumb -mthumb-interwork -Wno-unused-function $(OUTPUT_OPTION) $< 96 | 97 | $(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.s 98 | @mkdir -p "$(@D)" 99 | $(COMPILE.s) -mthumb -mthumb-interwork $(OUTPUT_OPTION) $< 100 | include $(call rwildcard, $(dir_build), *.d) 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cosmo3DS 2 | 3 | This is a stripped down version of [AuReiNand](https://github.com/AuroraWright/AuReiNand) 4 | that does nothing but load FIRM and emuNAND. 5 | 6 | It is intended to be used with [3ds_injector](https://github.com/yifanlu/3ds_injector) 7 | to launch a modified `loader` in FIRM. 8 | 9 | ## Why not just AuReiNand? 10 | 11 | This adds no features to AuReiNand and in fact removes many features. This is 12 | because I believe in simplicity and I believe in keeping features of code 13 | integrity in the system intact. The name change is a result of this change in 14 | philosophy. I understand that not everyone agrees with this so they are always 15 | free to use AuReiNand instead. 16 | 17 | ## Build 18 | 19 | Follow the directions for building AuReiNand. 20 | 21 | ## Credits 22 | 23 | All credits go to Rei and AuroraWright for AuReiNand. 24 | -------------------------------------------------------------------------------- /linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | SECTIONS 3 | { 4 | . = 0x23F00000; 5 | .text.start : { *(.text.start) } 6 | .text : { *(.text) } 7 | .data : { *(.data) } 8 | .bss : { *(.bss COMMON) } 9 | .rodata : { *(.rodata) } 10 | . = ALIGN(4); 11 | } 12 | -------------------------------------------------------------------------------- /patches/emunand.s: -------------------------------------------------------------------------------- 1 | .arm.little 2 | 3 | .create "emunand.bin", 0 4 | .arm 5 | nand_sd: 6 | ; Original code that still needs to be executed. 7 | mov r4, r0 8 | mov r5, r1 9 | mov r7, r2 10 | mov r6, r3 11 | ; End. 12 | 13 | ; If we're already trying to access the SD, return. 14 | ldr r2, [r0, #4] 15 | ldr r1, [sdmmc] 16 | cmp r2, r1 17 | beq nand_sd_ret 18 | 19 | str r1, [r0, #4] ; Set object to be SD 20 | ldr r2, [r0, #8] ; Get sector to read 21 | cmp r2, #0 ; For GW compatibility, see if we're trying to read the ncsd header (sector 0) 22 | 23 | ldr r3, [nand_offset] 24 | add r2, r3 ; Add the offset to the NAND in the SD. 25 | 26 | ldreq r3, [ncsd_header_offset] 27 | addeq r2, r3 ; If we're reading the ncsd header, add the offset of that sector. 28 | 29 | str r2, [r0, #8] ; Store sector to read 30 | 31 | nand_sd_ret: 32 | ; Restore registers. 33 | mov r1, r5 34 | mov r2, r7 35 | mov r3, r6 36 | 37 | ; Return 4 bytes behind where we got called, 38 | ; due to the offset of this function being stored there. 39 | mov r0, lr 40 | add r0, #4 41 | bx r0 42 | .pool 43 | sdmmc: .ascii "SDMC" 44 | nand_offset: .ascii "NAND" ; for rednand this should be 1 45 | ncsd_header_offset: .ascii "NCSD" ; depends on nand manufacturer + emunand type (GW/RED) 46 | .close 47 | -------------------------------------------------------------------------------- /patches/reboot.s: -------------------------------------------------------------------------------- 1 | .arm.little 2 | 3 | payload_addr equ 0x23F00000 ; Brahma payload address. 4 | payload_maxsize equ 0x20000 ; Maximum size for the payload (200 KB will do). 5 | 6 | .create "reboot.bin", 0 7 | .arm 8 | ; Interesting registers and locations to keep in mind, set before this code is ran: 9 | ; - sp + 0x3A8 - 0x70: FIRM path in exefs. 10 | ; - r7 (which is sp + 0x3A8 - 0x198): Reserved space for file handle 11 | ; - *(sp + 0x3A8 - 0x198) + 0x28: fread function. 12 | 13 | pxi_wait_recv: 14 | ldr r2, =0x44846 15 | ldr r0, =0x10008000 16 | readPxiLoop1: 17 | ldrh r1, [r0, #4] 18 | lsls r1, #0x17 19 | bmi readPxiLoop1 20 | ldr r0, [r0, #0xC] 21 | cmp r0, r2 22 | bne pxi_wait_recv 23 | 24 | mov r4, #0 25 | adr r1, bin_fname 26 | b open_payload 27 | 28 | fallback: 29 | mov r4, #1 30 | adr r1, dat_fname 31 | 32 | open_payload: 33 | ; Open file 34 | add r0, r7, #8 35 | mov r2, #1 36 | ldr r6, [fopen] 37 | orr r6, 1 38 | blx r6 39 | cmp r0, #0 40 | bne fallback ; If the .bin is not found, try the .dat. 41 | 42 | read_payload: 43 | ; Read file 44 | mov r0, r7 45 | adr r1, bytes_read 46 | ldr r2, =payload_addr 47 | cmp r4, #0 48 | movne r3, #0x12000 ; Skip the first 0x12000 bytes. 49 | moveq r3, payload_maxsize 50 | ldr r6, [sp, #0x3A8-0x198] 51 | ldr r6, [r6, #0x28] 52 | blx r6 53 | cmp r4, #0 54 | movne r4, #0 55 | bne read_payload ; Go read the real payload. 56 | 57 | ; Copy the last digits of the wanted firm to the 5th byte of the payload 58 | add r2, sp, #0x3A8 - 0x70 59 | ldr r0, [r2, #0x27] 60 | ldr r1, =payload_addr + 4 61 | str r0, [r1] 62 | ldr r0, [r2, #0x2B] 63 | str r0, [r1, #4] 64 | 65 | ; Set kernel state 66 | mov r0, #0 67 | mov r1, #0 68 | mov r2, #0 69 | mov r3, #0 70 | swi 0x7C 71 | 72 | goto_reboot: 73 | ; Jump to reboot code 74 | ldr r0, =(kernelcode_start - goto_reboot - 12) 75 | add r0, pc 76 | swi 0x7B 77 | 78 | die: 79 | b die 80 | 81 | bytes_read: .word 0 82 | fopen: .ascii "OPEN" 83 | .pool 84 | bin_fname: .dcw "sdmc:/arm9loaderhax.bin" 85 | .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 86 | dat_fname: .dcw "sdmc:/Cosmo3DS.dat" 87 | .word 0 88 | 89 | .align 4 90 | kernelcode_start: 91 | ; Set MPU settings 92 | mrc p15, 0, r0, c2, c0, 0 ; dcacheable 93 | mrc p15, 0, r12, c2, c0, 1 ; icacheable 94 | mrc p15, 0, r1, c3, c0, 0 ; write bufferable 95 | mrc p15, 0, r2, c5, c0, 2 ; daccess 96 | mrc p15, 0, r3, c5, c0, 3 ; iaccess 97 | ldr r4, =0x18000035 ; 0x18000000 128M 98 | bic r2, r2, #0xF0000 ; unprotect region 4 99 | bic r3, r3, #0xF0000 ; unprotect region 4 100 | orr r0, r0, #0x10 ; dcacheable region 4 101 | orr r2, r2, #0x30000 ; region 4 r/w 102 | orr r3, r3, #0x30000 ; region 4 r/w 103 | orr r12, r12, #0x10 ; icacheable region 4 104 | orr r1, r1, #0x10 ; write bufferable region 4 105 | mcr p15, 0, r0, c2, c0, 0 106 | mcr p15, 0, r12, c2, c0, 1 107 | mcr p15, 0, r1, c3, c0, 0 ; write bufferable 108 | mcr p15, 0, r2, c5, c0, 2 ; daccess 109 | mcr p15, 0, r3, c5, c0, 3 ; iaccess 110 | mcr p15, 0, r4, c6, c4, 0 ; region 4 (hmmm) 111 | 112 | mrc p15, 0, r0, c2, c0, 0 ; dcacheable 113 | mrc p15, 0, r1, c2, c0, 1 ; icacheable 114 | mrc p15, 0, r2, c3, c0, 0 ; write bufferable 115 | orr r0, r0, #0x20 ; dcacheable region 5 116 | orr r1, r1, #0x20 ; icacheable region 5 117 | orr r2, r2, #0x20 ; write bufferable region 5 118 | mcr p15, 0, r0, c2, c0, 0 ; dcacheable 119 | mcr p15, 0, r1, c2, c0, 1 ; icacheable 120 | mcr p15, 0, r2, c3, c0, 0 ; write bufferable 121 | 122 | ; Flush cache 123 | mov r2, #0 124 | mov r1, r2 125 | flush_cache: 126 | mov r0, #0 127 | mov r3, r2, lsl #30 128 | flush_cache_inner_loop: 129 | orr r12, r3, r0, lsl#5 130 | mcr p15, 0, r1, c7, c10, 4 ; drain write buffer 131 | mcr p15, 0, r12, c7, c14, 2 ; clean and flush dcache entry (index and segment) 132 | add r0, #1 133 | cmp r0, #0x20 134 | bcc flush_cache_inner_loop 135 | add r2, #1 136 | cmp r2, #4 137 | bcc flush_cache 138 | 139 | ; Enable MPU 140 | ldr r0, =0x42078 ; alt vector select, enable itcm 141 | mcr p15, 0, r0, c1, c0, 0 142 | mcr p15, 0, r1, c7, c5, 0 ; flush dcache 143 | mcr p15, 0, r1, c7, c6, 0 ; flush icache 144 | mcr p15, 0, r1, c7, c10, 4 ; drain write buffer 145 | 146 | ; Jump to payload 147 | ldr r0, =payload_addr 148 | bx r0 149 | 150 | .pool 151 | .close -------------------------------------------------------------------------------- /source/buttons.h: -------------------------------------------------------------------------------- 1 | /* 2 | * buttons.h 3 | * by Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "types.h" 10 | 11 | #define HID_PAD (*(vu16 *)0x10146000 ^ 0xFFF) 12 | #define BUTTON_R1 (1 << 8) 13 | #define BUTTON_L1 (1 << 9) 14 | #define BUTTON_A 1 15 | #define BUTTON_B (1 << 1) 16 | #define BUTTON_SELECT (1 << 2) 17 | #define BUTTON_START (1 << 3) 18 | #define BUTTON_RIGHT (1 << 4) 19 | #define BUTTON_LEFT (1 << 5) 20 | #define BUTTON_UP (1 << 6) 21 | #define BUTTON_DOWN (1 << 7) 22 | #define BUTTON_L1R1 ((1 << 8) | (1 << 9)) 23 | #define SAFE_MODE (BUTTON_L1R1 | BUTTON_A | BUTTON_UP) 24 | #define OPTION_BUTTONS (BUTTON_L1R1 | BUTTON_A | BUTTON_SELECT) 25 | #define PAYLOAD_BUTTONS ((BUTTON_L1 | BUTTON_A | BUTTON_B) ^ 0xFFF) 26 | #define MENU_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_A | BUTTON_START) -------------------------------------------------------------------------------- /source/crypto.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crypto.c 3 | * by Reisyukaku / Aurora Wright 4 | * Crypto libs from http://github.com/b1l1s/ctr 5 | * 6 | * Copyright (c) 2016 All Rights Reserved 7 | */ 8 | 9 | #include "crypto.h" 10 | #include "firm.h" 11 | #include "memory.h" 12 | #include "fatfs/sdmmc/sdmmc.h" 13 | 14 | /**************************************************************** 15 | * Crypto Libs 16 | ****************************************************************/ 17 | 18 | /* original version by megazig */ 19 | 20 | #ifndef __thumb__ 21 | #define BSWAP32(x) {\ 22 | __asm__\ 23 | (\ 24 | "eor r1, %1, %1, ror #16\n\t"\ 25 | "bic r1, r1, #0xFF0000\n\t"\ 26 | "mov %0, %1, ror #8\n\t"\ 27 | "eor %0, %0, r1, lsr #8\n\t"\ 28 | :"=r"(x)\ 29 | :"0"(x)\ 30 | :"r1"\ 31 | );\ 32 | }; 33 | 34 | #define ADD_u128_u32(u128_0, u128_1, u128_2, u128_3, u32_0) {\ 35 | __asm__\ 36 | (\ 37 | "adds %0, %4\n\t"\ 38 | "addcss %1, %1, #1\n\t"\ 39 | "addcss %2, %2, #1\n\t"\ 40 | "addcs %3, %3, #1\n\t"\ 41 | : "+r"(u128_0), "+r"(u128_1), "+r"(u128_2), "+r"(u128_3)\ 42 | : "r"(u32_0)\ 43 | : "cc"\ 44 | );\ 45 | } 46 | #else 47 | #define BSWAP32(x) {x = __builtin_bswap32(x);} 48 | 49 | #define ADD_u128_u32(u128_0, u128_1, u128_2, u128_3, u32_0) {\ 50 | __asm__\ 51 | (\ 52 | "mov r4, #0\n\t"\ 53 | "add %0, %0, %4\n\t"\ 54 | "adc %1, %1, r4\n\t"\ 55 | "adc %2, %2, r4\n\t"\ 56 | "adc %3, %3, r4\n\t"\ 57 | : "+r"(u128_0), "+r"(u128_1), "+r"(u128_2), "+r"(u128_3)\ 58 | : "r"(u32_0)\ 59 | : "cc", "r4"\ 60 | );\ 61 | } 62 | #endif /*__thumb__*/ 63 | 64 | static void aes_setkey(u8 keyslot, const void *key, u32 keyType, u32 mode) 65 | { 66 | if(keyslot <= 0x03) return; // Ignore TWL keys for now 67 | u32 *key32 = (u32 *)key; 68 | *REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode; 69 | *REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | AES_KEYCNT_WRITE; 70 | 71 | REG_AESKEYFIFO[keyType] = key32[0]; 72 | REG_AESKEYFIFO[keyType] = key32[1]; 73 | REG_AESKEYFIFO[keyType] = key32[2]; 74 | REG_AESKEYFIFO[keyType] = key32[3]; 75 | } 76 | 77 | static void aes_use_keyslot(u8 keyslot) 78 | { 79 | if(keyslot > 0x3F) 80 | return; 81 | 82 | *REG_AESKEYSEL = keyslot; 83 | *REG_AESCNT = *REG_AESCNT | 0x04000000; /* mystery bit */ 84 | } 85 | 86 | static void aes_setiv(const void *iv, u32 mode) 87 | { 88 | const u32 *iv32 = (const u32 *)iv; 89 | *REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode; 90 | 91 | // Word order for IV can't be changed in REG_AESCNT and always default to reversed 92 | if(mode & AES_INPUT_NORMAL) 93 | { 94 | REG_AESCTR[0] = iv32[3]; 95 | REG_AESCTR[1] = iv32[2]; 96 | REG_AESCTR[2] = iv32[1]; 97 | REG_AESCTR[3] = iv32[0]; 98 | } 99 | else 100 | { 101 | REG_AESCTR[0] = iv32[0]; 102 | REG_AESCTR[1] = iv32[1]; 103 | REG_AESCTR[2] = iv32[2]; 104 | REG_AESCTR[3] = iv32[3]; 105 | } 106 | } 107 | 108 | static void aes_advctr(void *ctr, u32 val, u32 mode) 109 | { 110 | u32 *ctr32 = (u32 *)ctr; 111 | 112 | int i; 113 | if(mode & AES_INPUT_BE) 114 | { 115 | for(i = 0; i < 4; ++i) // Endian swap 116 | BSWAP32(ctr32[i]); 117 | } 118 | 119 | if(mode & AES_INPUT_NORMAL) 120 | { 121 | ADD_u128_u32(ctr32[3], ctr32[2], ctr32[1], ctr32[0], val); 122 | } 123 | else 124 | { 125 | ADD_u128_u32(ctr32[0], ctr32[1], ctr32[2], ctr32[3], val); 126 | } 127 | 128 | if(mode & AES_INPUT_BE) 129 | { 130 | for(i = 0; i < 4; ++i) // Endian swap 131 | BSWAP32(ctr32[i]); 132 | } 133 | } 134 | 135 | static void aes_change_ctrmode(void *ctr, u32 fromMode, u32 toMode) 136 | { 137 | u32 *ctr32 = (u32 *)ctr; 138 | int i; 139 | if((fromMode ^ toMode) & AES_CNT_INPUT_ENDIAN) 140 | { 141 | for(i = 0; i < 4; ++i) 142 | BSWAP32(ctr32[i]); 143 | } 144 | 145 | if((fromMode ^ toMode) & AES_CNT_INPUT_ORDER) 146 | { 147 | u32 temp = ctr32[0]; 148 | ctr32[0] = ctr32[3]; 149 | ctr32[3] = temp; 150 | 151 | temp = ctr32[1]; 152 | ctr32[1] = ctr32[2]; 153 | ctr32[2] = temp; 154 | } 155 | } 156 | 157 | static void aes_batch(void *dst, const void *src, u32 blockCount) 158 | { 159 | *REG_AESBLKCNT = blockCount << 16; 160 | *REG_AESCNT |= AES_CNT_START; 161 | 162 | const u32 *src32 = (const u32 *)src; 163 | u32 *dst32 = (u32 *)dst; 164 | 165 | u32 wbc = blockCount; 166 | u32 rbc = blockCount; 167 | 168 | while(rbc) 169 | { 170 | if(wbc && ((*REG_AESCNT & 0x1F) <= 0xC)) // There's space for at least 4 ints 171 | { 172 | *REG_AESWRFIFO = *src32++; 173 | *REG_AESWRFIFO = *src32++; 174 | *REG_AESWRFIFO = *src32++; 175 | *REG_AESWRFIFO = *src32++; 176 | wbc--; 177 | } 178 | 179 | if(rbc && ((*REG_AESCNT & (0x1F << 0x5)) >= (0x4 << 0x5))) // At least 4 ints available for read 180 | { 181 | *dst32++ = *REG_AESRDFIFO; 182 | *dst32++ = *REG_AESRDFIFO; 183 | *dst32++ = *REG_AESRDFIFO; 184 | *dst32++ = *REG_AESRDFIFO; 185 | rbc--; 186 | } 187 | } 188 | } 189 | 190 | static void aes(void *dst, const void *src, u32 blockCount, void *iv, u32 mode, u32 ivMode) 191 | { 192 | *REG_AESCNT = mode | 193 | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | 194 | AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN | 195 | AES_CNT_FLUSH_READ | AES_CNT_FLUSH_WRITE; 196 | 197 | u32 blocks; 198 | while(blockCount != 0) 199 | { 200 | if((mode & AES_ALL_MODES) != AES_ECB_ENCRYPT_MODE 201 | && (mode & AES_ALL_MODES) != AES_ECB_DECRYPT_MODE) 202 | aes_setiv(iv, ivMode); 203 | 204 | blocks = (blockCount >= 0xFFFF) ? 0xFFFF : blockCount; 205 | 206 | // Save the last block for the next decryption CBC batch's iv 207 | if((mode & AES_ALL_MODES) == AES_CBC_DECRYPT_MODE) 208 | { 209 | memcpy(iv, src + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE); 210 | aes_change_ctrmode(iv, AES_INPUT_BE | AES_INPUT_NORMAL, ivMode); 211 | } 212 | 213 | // Process the current batch 214 | aes_batch(dst, src, blocks); 215 | 216 | // Save the last block for the next encryption CBC batch's iv 217 | if((mode & AES_ALL_MODES) == AES_CBC_ENCRYPT_MODE) 218 | { 219 | memcpy(iv, dst + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE); 220 | aes_change_ctrmode(iv, AES_INPUT_BE | AES_INPUT_NORMAL, ivMode); 221 | } 222 | 223 | // Advance counter for CTR mode 224 | else if((mode & AES_ALL_MODES) == AES_CTR_MODE) 225 | aes_advctr(iv, blocks, ivMode); 226 | 227 | src += blocks * AES_BLOCK_SIZE; 228 | dst += blocks * AES_BLOCK_SIZE; 229 | blockCount -= blocks; 230 | } 231 | } 232 | 233 | static void sha_init(u32 mode) 234 | { 235 | while(*REG_SHACNT & 1); 236 | *REG_SHACNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND; 237 | } 238 | 239 | static void sha_update(const void* src, u32 size) 240 | { 241 | const u32* src32 = (const u32*)src; 242 | 243 | while(size >= 0x40) { 244 | while(*REG_SHACNT & 1); 245 | for(u32 i = 0; i < 4; i++) { 246 | *REG_SHAINFIFO = *src32++; 247 | *REG_SHAINFIFO = *src32++; 248 | *REG_SHAINFIFO = *src32++; 249 | *REG_SHAINFIFO = *src32++; 250 | } 251 | size -= 0x40; 252 | } 253 | while(*REG_SHACNT & 1); 254 | memcpy((void*)REG_SHAINFIFO, src32, size); 255 | } 256 | 257 | static void sha_get(void* res) { 258 | *REG_SHACNT = (*REG_SHACNT & ~SHA_NORMAL_ROUND) | SHA_FINAL_ROUND; 259 | while(*REG_SHACNT & SHA_FINAL_ROUND); 260 | while(*REG_SHACNT & 1); 261 | memcpy(res, (void*)REG_SHAHASH, (256 / 8)); 262 | } 263 | 264 | static void sha_quick(void* res, const void* src, u32 size, u32 mode) { 265 | sha_init(mode); 266 | sha_update(src, size); 267 | sha_get(res); 268 | } 269 | 270 | /**************************************************************** 271 | * Nand/FIRM Crypto stuff 272 | ****************************************************************/ 273 | 274 | //Nand key#2 (0x12C10) 275 | static const u8 key2[0x10] = { 276 | 0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0 277 | }; 278 | 279 | //Get Nand CTR key 280 | static void getNandCTR(u8 *buf){ 281 | // calculate CTRNAND/TWL ctr from NAND CID 282 | // Taken from Decrypt9 283 | u8 NandCid[16]; 284 | u8 shasum[32]; 285 | 286 | sdmmc_get_cid(1, (uint32_t *)NandCid); 287 | sha_quick(shasum, NandCid, 16, SHA256_MODE); 288 | memcpy(buf, shasum, 16); 289 | } 290 | 291 | //Read firm0 from NAND and write to buffer 292 | void nandFirm0(u32 usesd, u32 sdoff, u8 *outbuf){ 293 | u8 CTR[0x10]; 294 | u32 last; 295 | firmHeader *hdr = (firmHeader *)outbuf; 296 | getNandCTR(CTR); 297 | 298 | if (usesd) 299 | sdmmc_sdcard_readsectors(sdoff + (0x0B130000 / 0x200), 1, outbuf); 300 | else 301 | sdmmc_nand_readsectors(0x0B130000 / 0x200, 1, outbuf); 302 | 303 | aes_use_keyslot(0x06); 304 | aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL); 305 | aes(outbuf, outbuf, 0x200 / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); 306 | if (hdr->magic != 0x4D524946) // FIRM 307 | return; 308 | 309 | last = 0x200; 310 | for (int i = 0; i < 4; i++) { 311 | if (!hdr->section[i].size) 312 | continue; 313 | 314 | if (usesd) 315 | sdmmc_sdcard_readsectors(sdoff + (0x0B130000 + hdr->section[i].offset) / 0x200, hdr->section[i].size / 0x200, hdr->section[i].address); 316 | else 317 | sdmmc_nand_readsectors((0x0B130000 + hdr->section[i].offset) / 0x200, hdr->section[i].size / 0x200, hdr->section[i].address); 318 | 319 | aes_advctr(CTR, hdr->section[i].offset - last, AES_INPUT_BE | AES_INPUT_NORMAL); 320 | aes(hdr->section[i].address, hdr->section[i].address, hdr->section[i].size / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); 321 | last = hdr->section[i].offset + hdr->section[i].size; 322 | } 323 | } 324 | 325 | //ARM9Loader replacement 326 | void arm9Loader(u8 *arm9Section, u32 mode) 327 | { 328 | //Firm keys 329 | u8 keyY[0x10], 330 | arm9BinCTR[0x10], 331 | arm9BinSlot = mode ? 0x16 : 0x15; 332 | 333 | //Setup keys needed for arm9bin decryption 334 | memcpy(keyY, arm9Section + 0x10, 0x10); 335 | memcpy(arm9BinCTR, arm9Section + 0x20, 0x10); 336 | 337 | //Calculate the size of the ARM9 binary 338 | u32 arm9BinSize = 0; 339 | //http://stackoverflow.com/questions/12791077/atoi-implementation-in-c 340 | for(u8 *tmp = arm9Section + 0x30; *tmp; tmp++) 341 | arm9BinSize = (arm9BinSize << 3) + (arm9BinSize << 1) + *tmp - '0'; 342 | 343 | if(mode) 344 | { 345 | const u8 key1[0x10] = {0x07, 0x29, 0x44, 0x38, 0xF8, 0xC9, 0x75, 0x93, 0xAA, 0x0E, 0x4A, 0xB4, 0xAE, 0x84, 0xC1, 0xD8}, 346 | key2[0x10] = {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0}; 347 | u8 keyX[0x10]; 348 | 349 | aes_setkey(0x11, mode == 1 ? key1 : key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); 350 | aes_use_keyslot(0x11); 351 | aes(keyX, arm9Section + 0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0); 352 | aes_setkey(arm9BinSlot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); 353 | } 354 | 355 | aes_setkey(arm9BinSlot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); 356 | aes_setiv(arm9BinCTR, AES_INPUT_BE | AES_INPUT_NORMAL); 357 | aes_use_keyslot(arm9BinSlot); 358 | 359 | //Decrypt arm9bin 360 | aes(arm9Section + 0x800, arm9Section + 0x800, arm9BinSize / AES_BLOCK_SIZE, arm9BinCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); 361 | 362 | //Set >=9.6 KeyXs 363 | if(mode == 2) 364 | { 365 | u8 keyData[0x10] = {0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98}, 366 | decKey[0x10]; 367 | 368 | //Set keys 0x19..0x1F keyXs 369 | aes_use_keyslot(0x11); 370 | for(u8 slot = 0x19; slot < 0x20; slot++) 371 | { 372 | aes(decKey, keyData, 1, NULL, AES_ECB_DECRYPT_MODE, 0); 373 | aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); 374 | keyData[0xF] += 1; 375 | } 376 | } 377 | } -------------------------------------------------------------------------------- /source/crypto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crypto.h 3 | * by Reisyukaku / Aurora Wright 4 | * Crypto libs from http://github.com/b1l1s/ctr 5 | * 6 | * Copyright (c) 2016 All Rights Reserved 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "types.h" 12 | 13 | /**************************AES****************************/ 14 | #define REG_AESCNT ((vu32 *)0x10009000) 15 | #define REG_AESBLKCNT ((vu32 *)0x10009004) 16 | #define REG_AESWRFIFO ((vu32 *)0x10009008) 17 | #define REG_AESRDFIFO ((vu32 *)0x1000900C) 18 | #define REG_AESKEYSEL ((vu8 *)0x10009010) 19 | #define REG_AESKEYCNT ((vu8 *)0x10009011) 20 | #define REG_AESCTR ((vu32 *)0x10009020) 21 | 22 | #define REG_AESKEYFIFO ((vu32 *)0x10009100) 23 | #define REG_AESKEYXFIFO ((vu32 *)0x10009104) 24 | #define REG_AESKEYYFIFO ((vu32 *)0x10009108) 25 | 26 | #define AES_CCM_DECRYPT_MODE (0u << 27) 27 | #define AES_CCM_ENCRYPT_MODE (1u << 27) 28 | #define AES_CTR_MODE (2u << 27) 29 | #define AES_CTR_MODE (2u << 27) 30 | #define AES_CBC_DECRYPT_MODE (4u << 27) 31 | #define AES_CBC_ENCRYPT_MODE (5u << 27) 32 | #define AES_ECB_DECRYPT_MODE (6u << 27) 33 | #define AES_ECB_ENCRYPT_MODE (7u << 27) 34 | #define AES_ALL_MODES (7u << 27) 35 | 36 | #define AES_CNT_START 0x80000000 37 | #define AES_CNT_INPUT_ORDER 0x02000000 38 | #define AES_CNT_OUTPUT_ORDER 0x01000000 39 | #define AES_CNT_INPUT_ENDIAN 0x00800000 40 | #define AES_CNT_OUTPUT_ENDIAN 0x00400000 41 | #define AES_CNT_FLUSH_READ 0x00000800 42 | #define AES_CNT_FLUSH_WRITE 0x00000400 43 | 44 | #define AES_INPUT_BE (AES_CNT_INPUT_ENDIAN) 45 | #define AES_INPUT_LE 0 46 | #define AES_INPUT_NORMAL (AES_CNT_INPUT_ORDER) 47 | #define AES_INPUT_REVERSED 0 48 | 49 | #define AES_BLOCK_SIZE 0x10 50 | 51 | #define AES_KEYCNT_WRITE (1 << 0x7) 52 | #define AES_KEYNORMAL 0 53 | #define AES_KEYX 1 54 | #define AES_KEYY 2 55 | 56 | #define REG_SHACNT ((volatile uint32_t*)0x1000A000) 57 | #define REG_SHABLKCNT ((volatile uint32_t*)0x1000A004) 58 | #define REG_SHAHASH ((volatile uint32_t*)0x1000A040) 59 | #define REG_SHAINFIFO ((volatile uint32_t*)0x1000A080) 60 | 61 | #define SHA_CNT_STATE 0x00000003 62 | #define SHA_CNT_OUTPUT_ENDIAN 0x00000008 63 | #define SHA_CNT_MODE 0x00000030 64 | #define SHA_CNT_ENABLE 0x00010000 65 | #define SHA_CNT_ACTIVE 0x00020000 66 | 67 | #define SHA_HASH_READY 0x00000000 68 | #define SHA_NORMAL_ROUND 0x00000001 69 | #define SHA_FINAL_ROUND 0x00000002 70 | 71 | #define SHA256_MODE 0 72 | #define SHA224_MODE 0x00000010 73 | #define SHA1_MODE 0x00000020 74 | 75 | //NAND/FIRM stuff 76 | void nandFirm0(u32 usesd, u32 sdoff, u8 *outbuf); 77 | void arm9Loader(u8 *arm9Section, u32 mode); -------------------------------------------------------------------------------- /source/draw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * draw.c 3 | * by Reisyukaku / Aurora Wright 4 | * Code to print to the screen by mid-kid @CakesFW 5 | * 6 | * Copyright (c) 2016 All Rights Reserved 7 | */ 8 | 9 | #include "draw.h" 10 | #include "fs.h" 11 | #include "memory.h" 12 | #include "font.h" 13 | 14 | #define SCREEN_TOP_WIDTH 400 15 | #define SCREEN_TOP_HEIGHT 240 16 | 17 | static const struct fb { 18 | u8 *top_left; 19 | u8 *top_right; 20 | u8 *bottom; 21 | } *const fb = (struct fb *)0x23FFFE00; 22 | 23 | static inline int strlen(const char *string){ 24 | char *stringEnd = (char *)string; 25 | while(*stringEnd) stringEnd++; 26 | return stringEnd - string; 27 | } 28 | 29 | void clearScreens(void){ 30 | memset32(fb->top_left, 0, 0x46500); 31 | memset32(fb->top_right, 0, 0x46500); 32 | memset32(fb->bottom, 0, 0x38400); 33 | } 34 | 35 | void drawCharacter(char character, int posX, int posY, u32 color){ 36 | u8 *const select = fb->top_left; 37 | 38 | for(int y = 0; y < 8; y++){ 39 | char charPos = font[character * 8 + y]; 40 | 41 | for(int x = 7; x >= 0; x--){ 42 | int screenPos = (posX * SCREEN_TOP_HEIGHT * 3 + (SCREEN_TOP_HEIGHT - y - posY - 1) * 3) + (7 - x) * 3 * SCREEN_TOP_HEIGHT; 43 | 44 | if ((charPos >> x) & 1) { 45 | select[screenPos] = color >> 16; 46 | select[screenPos + 1] = color >> 8; 47 | select[screenPos + 2] = color; 48 | } 49 | } 50 | } 51 | } 52 | 53 | int drawString(const char *string, int posX, int posY, u32 color){ 54 | int length = strlen(string); 55 | 56 | for(int i = 0, line_i = 0; i < length; i++, line_i++){ 57 | if(string[i] == '\n'){ 58 | posY += SPACING_Y; 59 | line_i = 0; 60 | i++; 61 | } else if(line_i >= (SCREEN_TOP_WIDTH - posX) / SPACING_X){ 62 | // Make sure we never get out of the screen. 63 | posY += SPACING_Y; 64 | line_i = 2; // Little offset so we know the same string continues. 65 | if(string[i] == ' ') i++; // Spaces at the start look weird 66 | } 67 | 68 | drawCharacter(string[i], posX + line_i * SPACING_X, posY, color); 69 | } 70 | 71 | return posY; 72 | } -------------------------------------------------------------------------------- /source/draw.h: -------------------------------------------------------------------------------- 1 | /* 2 | * draw.h 3 | * by Reisyukaku / Aurora Wright 4 | * Code to print to the screen by mid-kid @CakesFW 5 | * 6 | * Copyright (c) 2016 All Rights Reserved 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "types.h" 12 | 13 | #define SPACING_Y 10 14 | #define SPACING_X 8 15 | 16 | void clearScreens(void); 17 | void drawCharacter(char character, int posX, int posY, u32 color); 18 | int drawString(const char *string, int posX, int posY, u32 color); -------------------------------------------------------------------------------- /source/emunand.c: -------------------------------------------------------------------------------- 1 | /* 2 | * emunand.c 3 | * by Reisyukaku / Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | */ 6 | 7 | #include "emunand.h" 8 | #include "memory.h" 9 | #include "fatfs/sdmmc/sdmmc.h" 10 | 11 | void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND){ 12 | u8 *const temp = (u8 *)0x24300000; 13 | 14 | const u32 nandSize = getMMCDevice(0)->total_size; 15 | u32 nandOffset = *emuNAND == 1 ? 0 : 16 | (nandSize > 0x200000 ? 0x400000 : 0x200000); 17 | 18 | //Check for RedNAND 19 | if(sdmmc_sdcard_readsectors(nandOffset + 1, 1, temp) == 0){ 20 | if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){ 21 | *off = nandOffset + 1; 22 | *head = nandOffset + 1; 23 | } 24 | //Check for Gateway emuNAND 25 | else if(sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) == 0){ 26 | if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){ 27 | *off = nandOffset; 28 | *head = nandOffset + nandSize; 29 | } 30 | //Fallback to the first emuNAND if there's no second one 31 | else if(*emuNAND == 2){ 32 | *emuNAND = 1; 33 | getEmunandSect(off, head, emuNAND); 34 | } 35 | else *emuNAND = 0; 36 | } 37 | } 38 | } 39 | 40 | u32 getSDMMC(u8 *pos, u32 size){ 41 | //Look for struct code 42 | const u8 pattern[] = {0x21, 0x20, 0x18, 0x20}; 43 | const u8 *off = memsearch(pos, pattern, size, 4) - 1; 44 | 45 | return *(u32 *)(off + 0x0A) + *(u32 *)(off + 0x0E); 46 | } 47 | 48 | void getEmuRW(u8 *pos, u32 size, u32 *readOff, u32 *writeOff){ 49 | //Look for read/write code 50 | const u8 pattern[] = {0x1E, 0x00, 0xC8, 0x05}; 51 | 52 | *readOff = (u32)memsearch(pos, pattern, size, 4) - 6; 53 | *writeOff = (u32)memsearch((u8 *)(*readOff + 0xA), pattern, 0x100, 4) - 6; 54 | } 55 | 56 | u32 *getMPU(u8 *pos, u32 size){ 57 | //Look for MPU pattern 58 | const u8 pattern[] = {0x03, 0x00, 0x24, 0x00}; 59 | 60 | return (u32 *)memsearch(pos, pattern, size, 4); 61 | } 62 | 63 | void *getEmuCode(u8 *proc9Offset){ 64 | const u8 pattern[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}; 65 | 66 | //Looking for the last free space before Process9 67 | return memsearch(proc9Offset - 0x3000, pattern, 0x3000, 6) + 0x455; 68 | } -------------------------------------------------------------------------------- /source/emunand.h: -------------------------------------------------------------------------------- 1 | /* 2 | * emunand.h 3 | * by Reisyukaku / Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "types.h" 10 | 11 | #define NCSD_MAGIC (0x4453434E) 12 | 13 | void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND); 14 | u32 getSDMMC(u8 *pos, u32 size); 15 | void getEmuRW(u8 *pos, u32 size, u32 *readOff, u32 *writeOff); 16 | u32 *getMPU(u8 *pos, u32 size); 17 | void *getEmuCode(u8 *proc9Offset); -------------------------------------------------------------------------------- /source/fatfs/00readme.txt: -------------------------------------------------------------------------------- 1 | FatFs Module Source Files R0.11 2 | 3 | 4 | FILES 5 | 6 | 00readme.txt This file. 7 | history.txt Revision history. 8 | ffconf.h Configuration file for FatFs module. 9 | ff.h Common include file for FatFs and application module. 10 | ff.c FatFs 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 functions. 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 not depend on any specific 19 | storage device. You have to provide a low level disk I/O module that written 20 | to control the target storage device. 21 | 22 | -------------------------------------------------------------------------------- /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 | 13 | 14 | /*-----------------------------------------------------------------------*/ 15 | /* Get Drive Status */ 16 | /*-----------------------------------------------------------------------*/ 17 | 18 | DSTATUS disk_status ( 19 | __attribute__((unused)) 20 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 21 | ) 22 | { 23 | return RES_OK; 24 | } 25 | 26 | 27 | 28 | /*-----------------------------------------------------------------------*/ 29 | /* Inidialize a Drive */ 30 | /*-----------------------------------------------------------------------*/ 31 | 32 | DSTATUS disk_initialize ( 33 | __attribute__((unused)) 34 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 35 | ) 36 | { 37 | sdmmc_sdcard_init(); 38 | return RES_OK; 39 | } 40 | 41 | 42 | 43 | /*-----------------------------------------------------------------------*/ 44 | /* Read Sector(s) */ 45 | /*-----------------------------------------------------------------------*/ 46 | 47 | DRESULT disk_read ( 48 | __attribute__((unused)) 49 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 50 | BYTE *buff, /* Data buffer to store read data */ 51 | DWORD sector, /* Sector address in LBA */ 52 | UINT count /* Number of sectors to read */ 53 | ) 54 | { 55 | if (sdmmc_sdcard_readsectors(sector, count, buff)) { 56 | return RES_PARERR; 57 | } 58 | 59 | return RES_OK; 60 | } 61 | 62 | 63 | 64 | /*-----------------------------------------------------------------------*/ 65 | /* Write Sector(s) */ 66 | /*-----------------------------------------------------------------------*/ 67 | 68 | #if _USE_WRITE 69 | DRESULT disk_write ( 70 | __attribute__((unused)) 71 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 72 | const BYTE *buff, /* Data to be written */ 73 | DWORD sector, /* Sector address in LBA */ 74 | UINT count /* Number of sectors to write */ 75 | ) 76 | { 77 | if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) { 78 | return RES_PARERR; 79 | } 80 | 81 | return RES_OK; 82 | } 83 | #endif 84 | 85 | 86 | 87 | /*-----------------------------------------------------------------------*/ 88 | /* Miscellaneous Functions */ 89 | /*-----------------------------------------------------------------------*/ 90 | 91 | #if _USE_IOCTL 92 | DRESULT disk_ioctl ( 93 | __attribute__((unused)) 94 | BYTE pdrv, /* Physical drive nmuber (0..) */ 95 | __attribute__((unused)) 96 | BYTE cmd, /* Control code */ 97 | __attribute__((unused)) 98 | void *buff /* Buffer to send/receive control data */ 99 | ) 100 | { 101 | return RES_PARERR; 102 | } 103 | #endif 104 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /source/fatfs/ff.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------/ 2 | / FatFs - FAT file system module include R0.11 (C)ChaN, 2015 3 | /----------------------------------------------------------------------------/ 4 | / FatFs module is a free software that opened under license policy of 5 | / following conditions. 6 | / 7 | / Copyright (C) 2015, ChaN, all right reserved. 8 | / 9 | / 1. Redistributions of source code must retain the above copyright notice, 10 | / this condition and the following disclaimer. 11 | / 12 | / This software is provided by the copyright holder and contributors "AS IS" 13 | / and any warranties related to this software are DISCLAIMED. 14 | / The copyright owner or contributors be NOT LIABLE for any damages caused 15 | / by use of this software. 16 | /---------------------------------------------------------------------------*/ 17 | 18 | 19 | #ifndef _FATFS 20 | #define _FATFS 32020 /* Revision ID */ 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | #include "integer.h" /* Basic integer types */ 27 | #include "ffconf.h" /* FatFs configuration options */ 28 | #if _FATFS != _FFCONF 29 | #error Wrong configuration file (ffconf.h). 30 | #endif 31 | 32 | 33 | 34 | /* Definitions of volume management */ 35 | 36 | #if _MULTI_PARTITION /* Multiple partition configuration */ 37 | typedef struct { 38 | BYTE pd; /* Physical drive number */ 39 | BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ 40 | } PARTITION; 41 | extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ 42 | #define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ 43 | #define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ 44 | 45 | #else /* Single partition configuration */ 46 | #define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ 47 | #define LD2PT(vol) 0 /* Find first valid partition or in SFD */ 48 | 49 | #endif 50 | 51 | 52 | 53 | /* Type of path name strings on FatFs API */ 54 | 55 | #if _LFN_UNICODE /* Unicode string */ 56 | #if !_USE_LFN 57 | #error _LFN_UNICODE must be 0 at non-LFN cfg. 58 | #endif 59 | #ifndef _INC_TCHAR 60 | typedef WCHAR TCHAR; 61 | #define _T(x) L ## x 62 | #define _TEXT(x) L ## x 63 | #endif 64 | 65 | #else /* ANSI/OEM string */ 66 | #ifndef _INC_TCHAR 67 | typedef char TCHAR; 68 | #define _T(x) x 69 | #define _TEXT(x) x 70 | #endif 71 | 72 | #endif 73 | 74 | 75 | 76 | /* File system object structure (FATFS) */ 77 | 78 | typedef struct { 79 | BYTE fs_type; /* FAT sub-type (0:Not mounted) */ 80 | BYTE drv; /* Physical drive number */ 81 | BYTE csize; /* Sectors per cluster (1,2,4...128) */ 82 | BYTE n_fats; /* Number of FAT copies (1 or 2) */ 83 | BYTE wflag; /* win[] flag (b0:dirty) */ 84 | BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ 85 | WORD id; /* File system mount ID */ 86 | WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ 87 | #if _MAX_SS != _MIN_SS 88 | WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */ 89 | #endif 90 | #if _FS_REENTRANT 91 | _SYNC_t sobj; /* Identifier of sync object */ 92 | #endif 93 | #if !_FS_READONLY 94 | DWORD last_clust; /* Last allocated cluster */ 95 | DWORD free_clust; /* Number of free clusters */ 96 | #endif 97 | #if _FS_RPATH 98 | DWORD cdir; /* Current directory start cluster (0:root) */ 99 | #endif 100 | DWORD n_fatent; /* Number of FAT entries, = number of clusters + 2 */ 101 | DWORD fsize; /* Sectors per FAT */ 102 | DWORD volbase; /* Volume start sector */ 103 | DWORD fatbase; /* FAT start sector */ 104 | DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ 105 | DWORD database; /* Data start sector */ 106 | DWORD winsect; /* Current sector appearing in the win[] */ 107 | BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ 108 | } FATFS; 109 | 110 | 111 | 112 | /* File object structure (FIL) */ 113 | 114 | typedef struct { 115 | FATFS* fs; /* Pointer to the related file system object (**do not change order**) */ 116 | WORD id; /* Owner file system mount ID (**do not change order**) */ 117 | BYTE flag; /* Status flags */ 118 | BYTE err; /* Abort flag (error code) */ 119 | DWORD fptr; /* File read/write pointer (Zeroed on file open) */ 120 | DWORD fsize; /* File size */ 121 | DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */ 122 | DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */ 123 | DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */ 124 | #if !_FS_READONLY 125 | DWORD dir_sect; /* Sector number containing the directory entry */ 126 | BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */ 127 | #endif 128 | #if _USE_FASTSEEK 129 | DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */ 130 | #endif 131 | #if _FS_LOCK 132 | UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ 133 | #endif 134 | #if !_FS_TINY 135 | BYTE buf[_MAX_SS]; /* File private data read/write window */ 136 | #endif 137 | } FIL; 138 | 139 | 140 | 141 | /* Directory object structure (DIR) */ 142 | 143 | typedef struct { 144 | FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */ 145 | WORD id; /* Owner file system mount ID (**do not change order**) */ 146 | WORD index; /* Current read/write index number */ 147 | DWORD sclust; /* Table start cluster (0:Root dir) */ 148 | DWORD clust; /* Current cluster */ 149 | DWORD sect; /* Current sector */ 150 | BYTE* dir; /* Pointer to the current SFN entry in the win[] */ 151 | BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ 152 | #if _FS_LOCK 153 | UINT lockid; /* File lock ID (index of file semaphore table Files[]) */ 154 | #endif 155 | #if _USE_LFN 156 | WCHAR* lfn; /* Pointer to the LFN working buffer */ 157 | WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ 158 | #endif 159 | #if _USE_FIND 160 | const TCHAR* pat; /* Pointer to the name matching pattern */ 161 | #endif 162 | } DIR; 163 | 164 | 165 | 166 | /* File information structure (FILINFO) */ 167 | 168 | typedef struct { 169 | DWORD fsize; /* File size */ 170 | WORD fdate; /* Last modified date */ 171 | WORD ftime; /* Last modified time */ 172 | BYTE fattrib; /* Attribute */ 173 | TCHAR fname[13]; /* Short file name (8.3 format) */ 174 | #if _USE_LFN 175 | TCHAR* lfname; /* Pointer to the LFN buffer */ 176 | UINT lfsize; /* Size of LFN buffer in TCHAR */ 177 | #endif 178 | } FILINFO; 179 | 180 | 181 | 182 | /* File function return code (FRESULT) */ 183 | 184 | typedef enum { 185 | FR_OK = 0, /* (0) Succeeded */ 186 | FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ 187 | FR_INT_ERR, /* (2) Assertion failed */ 188 | FR_NOT_READY, /* (3) The physical drive cannot work */ 189 | FR_NO_FILE, /* (4) Could not find the file */ 190 | FR_NO_PATH, /* (5) Could not find the path */ 191 | FR_INVALID_NAME, /* (6) The path name format is invalid */ 192 | FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ 193 | FR_EXIST, /* (8) Access denied due to prohibited access */ 194 | FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ 195 | FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ 196 | FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ 197 | FR_NOT_ENABLED, /* (12) The volume has no work area */ 198 | FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ 199 | FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ 200 | FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ 201 | FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ 202 | FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ 203 | FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ 204 | FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ 205 | } FRESULT; 206 | 207 | 208 | 209 | /*--------------------------------------------------------------*/ 210 | /* FatFs module application interface */ 211 | 212 | FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ 213 | FRESULT f_close (FIL* fp); /* Close an open file object */ 214 | FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */ 215 | FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */ 216 | FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ 217 | FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */ 218 | FRESULT f_truncate (FIL* fp); /* Truncate file */ 219 | FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */ 220 | FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ 221 | FRESULT f_closedir (DIR* dp); /* Close an open directory */ 222 | FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ 223 | FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ 224 | FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ 225 | FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ 226 | FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ 227 | FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ 228 | FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ 229 | FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of the file/dir */ 230 | FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */ 231 | FRESULT f_chdir (const TCHAR* path); /* Change current directory */ 232 | FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ 233 | FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ 234 | FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ 235 | FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ 236 | FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ 237 | FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ 238 | FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */ 239 | FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */ 240 | int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ 241 | int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ 242 | int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ 243 | TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ 244 | 245 | #define f_eof(fp) ((int)((fp)->fptr == (fp)->fsize)) 246 | #define f_error(fp) ((fp)->err) 247 | #define f_tell(fp) ((fp)->fptr) 248 | #define f_size(fp) ((fp)->fsize) 249 | #define f_rewind(fp) f_lseek((fp), 0) 250 | #define f_rewinddir(dp) f_readdir((dp), 0) 251 | 252 | #ifndef EOF 253 | #define EOF (-1) 254 | #endif 255 | 256 | 257 | 258 | 259 | /*--------------------------------------------------------------*/ 260 | /* Additional user defined functions */ 261 | 262 | /* RTC function */ 263 | #if !_FS_READONLY && !_FS_NORTC 264 | DWORD get_fattime (void); 265 | #endif 266 | 267 | /* Unicode support functions */ 268 | #if _USE_LFN /* Unicode - OEM code conversion */ 269 | WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */ 270 | WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */ 271 | #if _USE_LFN == 3 /* Memory functions */ 272 | void* ff_memalloc (UINT msize); /* Allocate memory block */ 273 | void ff_memfree (void* mblock); /* Free memory block */ 274 | #endif 275 | #endif 276 | 277 | /* Sync functions */ 278 | #if _FS_REENTRANT 279 | int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */ 280 | int ff_req_grant (_SYNC_t sobj); /* Lock sync object */ 281 | void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */ 282 | int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */ 283 | #endif 284 | 285 | 286 | 287 | 288 | /*--------------------------------------------------------------*/ 289 | /* Flags and offset address */ 290 | 291 | 292 | /* File access control and file status flags (FIL.flag) */ 293 | 294 | #define FA_READ 0x01 295 | #define FA_OPEN_EXISTING 0x00 296 | 297 | #if !_FS_READONLY 298 | #define FA_WRITE 0x02 299 | #define FA_CREATE_NEW 0x04 300 | #define FA_CREATE_ALWAYS 0x08 301 | #define FA_OPEN_ALWAYS 0x10 302 | #define FA__WRITTEN 0x20 303 | #define FA__DIRTY 0x40 304 | #endif 305 | 306 | 307 | /* FAT sub type (FATFS.fs_type) */ 308 | 309 | #define FS_FAT12 1 310 | #define FS_FAT16 2 311 | #define FS_FAT32 3 312 | 313 | 314 | /* File attribute bits for directory entry */ 315 | 316 | #define AM_RDO 0x01 /* Read only */ 317 | #define AM_HID 0x02 /* Hidden */ 318 | #define AM_SYS 0x04 /* System */ 319 | #define AM_VOL 0x08 /* Volume label */ 320 | #define AM_LFN 0x0F /* LFN entry */ 321 | #define AM_DIR 0x10 /* Directory */ 322 | #define AM_ARC 0x20 /* Archive */ 323 | #define AM_MASK 0x3F /* Mask of defined bits */ 324 | 325 | 326 | /* Fast seek feature */ 327 | #define CREATE_LINKMAP 0xFFFFFFFF 328 | 329 | 330 | 331 | /*--------------------------------*/ 332 | /* Multi-byte word access macros */ 333 | 334 | #if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ 335 | #define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) 336 | #define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) 337 | #define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) 338 | #define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) 339 | #else /* Use byte-by-byte access to the FAT structure */ 340 | #define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) 341 | #define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) 342 | #define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8) 343 | #define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24) 344 | #endif 345 | 346 | #ifdef __cplusplus 347 | } 348 | #endif 349 | 350 | #endif /* _FATFS */ 351 | -------------------------------------------------------------------------------- /source/fatfs/ffconf.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------/ 2 | / FatFs - FAT file system module configuration file R0.11 (C)ChaN, 2015 3 | /---------------------------------------------------------------------------*/ 4 | 5 | #define _FFCONF 32020 /* Revision ID */ 6 | 7 | /*---------------------------------------------------------------------------/ 8 | / Functions and Buffer Configurations 9 | /---------------------------------------------------------------------------*/ 10 | 11 | #define _FS_TINY 0 12 | /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) 13 | / At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS 14 | / bytes. Instead of private sector buffer eliminated from the file object, 15 | / common sector buffer in the file system object (FATFS) is used for the file 16 | / data transfer. */ 17 | 18 | 19 | #define _FS_READONLY 0 20 | /* This option switches read-only configuration. (0:Read/Write or 1:Read-only) 21 | / Read-only configuration removes writing API functions, f_write(), f_sync(), 22 | / f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() 23 | / and optional writing functions as well. */ 24 | 25 | 26 | #define _FS_MINIMIZE 0 27 | /* This option defines minimization level to remove some basic API functions. 28 | / 29 | / 0: All basic functions are enabled. 30 | / 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(), 31 | / f_truncate() and f_rename() function are removed. 32 | / 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. 33 | / 3: f_lseek() function is removed in addition to 2. */ 34 | 35 | 36 | #define _USE_STRFUNC 0 37 | /* This option switches string functions, f_gets(), f_putc(), f_puts() and 38 | / f_printf(). 39 | / 40 | / 0: Disable string functions. 41 | / 1: Enable without LF-CRLF conversion. 42 | / 2: Enable with LF-CRLF conversion. */ 43 | 44 | 45 | #define _USE_FIND 0 46 | /* This option switches filtered directory read feature and related functions, 47 | / f_findfirst() and f_findnext(). (0:Disable or 1:Enable) */ 48 | 49 | 50 | #define _USE_MKFS 0 51 | /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ 52 | 53 | 54 | #define _USE_FASTSEEK 0 55 | /* This option switches fast seek feature. (0:Disable or 1:Enable) */ 56 | 57 | 58 | #define _USE_LABEL 0 59 | /* This option switches volume label functions, f_getlabel() and f_setlabel(). 60 | / (0:Disable or 1:Enable) */ 61 | 62 | 63 | #define _USE_FORWARD 0 64 | /* This option switches f_forward() function. (0:Disable or 1:Enable) 65 | / To enable it, also _FS_TINY need to be set to 1. */ 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 extended character. Non-LFN cfg. only) 77 | / 437 - U.S. 78 | / 720 - Arabic 79 | / 737 - Greek 80 | / 775 - Baltic 81 | / 850 - Multilingual Latin 1 82 | / 852 - Latin 2 83 | / 855 - Cyrillic 84 | / 857 - Turkish 85 | / 858 - Multilingual Latin 1 + Euro 86 | / 862 - Hebrew 87 | / 866 - Russian 88 | / 874 - Thai 89 | / 932 - Japanese Shift_JIS (DBCS) 90 | / 936 - Simplified Chinese GBK (DBCS) 91 | / 949 - Korean (DBCS) 92 | / 950 - Traditional Chinese Big5 (DBCS) 93 | */ 94 | 95 | 96 | #define _USE_LFN 2 97 | #define _MAX_LFN 255 98 | /* The _USE_LFN option switches the LFN feature. 99 | / 100 | / 0: Disable LFN feature. _MAX_LFN has no effect. 101 | / 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. 102 | / 2: Enable LFN with dynamic working buffer on the STACK. 103 | / 3: Enable LFN with dynamic working buffer on the HEAP. 104 | / 105 | / When enable the LFN feature, Unicode handling functions (option/unicode.c) must 106 | / be added to the project. The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. 107 | / When use stack for the working buffer, take care on stack overflow. When use heap 108 | / memory for the working buffer, memory management functions, ff_memalloc() and 109 | / ff_memfree(), must be added to the project. */ 110 | 111 | 112 | #define _LFN_UNICODE 0 113 | /* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode) 114 | / To use Unicode string for the path name, enable LFN feature and set _LFN_UNICODE 115 | / to 1. This option also affects behavior of string I/O functions. */ 116 | 117 | 118 | #define _STRF_ENCODE 0 119 | /* When _LFN_UNICODE is 1, this option selects the character encoding on the file to 120 | / be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf(). 121 | / 122 | / 0: ANSI/OEM 123 | / 1: UTF-16LE 124 | / 2: UTF-16BE 125 | / 3: UTF-8 126 | / 127 | / When _LFN_UNICODE is 0, this option has no effect. */ 128 | 129 | 130 | #define _FS_RPATH 0 131 | /* This option configures relative path feature. 132 | / 133 | / 0: Disable relative path feature and remove related functions. 134 | / 1: Enable relative path feature. f_chdir() and f_chdrive() are available. 135 | / 2: f_getcwd() function is available in addition to 1. 136 | / 137 | / Note that directory items read via f_readdir() are affected by this option. */ 138 | 139 | 140 | /*---------------------------------------------------------------------------/ 141 | / Drive/Volume Configurations 142 | /---------------------------------------------------------------------------*/ 143 | 144 | #define _VOLUMES 1 145 | /* Number of volumes (logical drives) to be used. */ 146 | 147 | 148 | #define _STR_VOLUME_ID 0 149 | #define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3" 150 | /* _STR_VOLUME_ID option switches string volume ID feature. 151 | / When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive 152 | / number in the path name. _VOLUME_STRS defines the drive ID strings for each 153 | / logical drives. Number of items must be equal to _VOLUMES. Valid characters for 154 | / the drive ID strings are: A-Z and 0-9. */ 155 | 156 | 157 | #define _MULTI_PARTITION 0 158 | /* This option switches multi-partition feature. By default (0), each logical drive 159 | / number is bound to the same physical drive number and only an FAT volume found on 160 | / the physical drive will be mounted. When multi-partition feature is enabled (1), 161 | / each logical drive number is bound to arbitrary physical drive and partition 162 | / listed in the VolToPart[]. Also f_fdisk() funciton will be available. */ 163 | 164 | 165 | #define _MIN_SS 512 166 | #define _MAX_SS 512 167 | /* These options configure the range of sector size to be supported. (512, 1024, 168 | / 2048 or 4096) Always set both 512 for most systems, all type of memory cards and 169 | / harddisk. But a larger value may be required for on-board flash memory and some 170 | / type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured 171 | / to variable sector size and GET_SECTOR_SIZE command must be implemented to the 172 | / disk_ioctl() function. */ 173 | 174 | 175 | #define _USE_TRIM 0 176 | /* This option switches ATA-TRIM feature. (0:Disable or 1:Enable) 177 | / To enable Trim feature, also CTRL_TRIM command should be implemented to the 178 | / disk_ioctl() function. */ 179 | 180 | 181 | #define _FS_NOFSINFO 0 182 | /* If you need to know correct free space on the FAT32 volume, set bit 0 of this 183 | / option, and f_getfree() function at first time after volume mount will force 184 | / a full FAT scan. Bit 1 controls the use of last allocated cluster number. 185 | / 186 | / bit0=0: Use free cluster count in the FSINFO if available. 187 | / bit0=1: Do not trust free cluster count in the FSINFO. 188 | / bit1=0: Use last allocated cluster number in the FSINFO if available. 189 | / bit1=1: Do not trust last allocated cluster number in the FSINFO. 190 | */ 191 | 192 | 193 | 194 | /*---------------------------------------------------------------------------/ 195 | / System Configurations 196 | /---------------------------------------------------------------------------*/ 197 | 198 | #define _FS_NORTC 1 199 | #define _NORTC_MON 2 200 | #define _NORTC_MDAY 1 201 | #define _NORTC_YEAR 2015 202 | /* The _FS_NORTC option switches timestamp feature. If the system does not have 203 | / an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable 204 | / the timestamp feature. All objects modified by FatFs will have a fixed timestamp 205 | / defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR. 206 | / When timestamp feature is enabled (_FS_NORTC == 0), get_fattime() function need 207 | / to be added to the project to read current time form RTC. _NORTC_MON, 208 | / _NORTC_MDAY and _NORTC_YEAR have no effect. 209 | / These options have no effect at read-only configuration (_FS_READONLY == 1). */ 210 | 211 | 212 | #define _FS_LOCK 0 213 | /* The _FS_LOCK option switches file lock feature to control duplicated file open 214 | / and illegal operation to open objects. This option must be 0 when _FS_READONLY 215 | / is 1. 216 | / 217 | / 0: Disable file lock feature. To avoid volume corruption, application program 218 | / should avoid illegal open, remove and rename to the open objects. 219 | / >0: Enable file lock feature. The value defines how many files/sub-directories 220 | / can be opened simultaneously under file lock control. Note that the file 221 | / lock feature is independent of re-entrancy. */ 222 | 223 | 224 | #define _FS_REENTRANT 0 225 | #define _FS_TIMEOUT 1000 226 | #define _SYNC_t HANDLE 227 | /* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs 228 | / module itself. Note that regardless of this option, file access to different 229 | / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() 230 | / and f_fdisk() function, are always not re-entrant. Only file/directory access 231 | / to the same volume is under control of this feature. 232 | / 233 | / 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect. 234 | / 1: Enable re-entrancy. Also user provided synchronization handlers, 235 | / ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() 236 | / function, must be added to the project. Samples are available in 237 | / option/syscall.c. 238 | / 239 | / The _FS_TIMEOUT defines timeout period in unit of time tick. 240 | / The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, 241 | / SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be 242 | / included somewhere in the scope of ff.c. */ 243 | 244 | 245 | #define _WORD_ACCESS 0 246 | /* The _WORD_ACCESS option is an only platform dependent option. It defines 247 | / which access method is used to the word data on the FAT volume. 248 | / 249 | / 0: Byte-by-byte access. Always compatible with all platforms. 250 | / 1: Word access. Do not choose this unless under both the following conditions. 251 | / 252 | / * Address misaligned memory access is always allowed to ALL instructions. 253 | / * Byte order on the memory is little-endian. 254 | / 255 | / If it is the case, _WORD_ACCESS can also be set to 1 to reduce code size. 256 | / Following table shows allowable settings of some processor types. 257 | / 258 | / ARM7TDMI 0 *2 ColdFire 0 *1 V850E 0 *2 259 | / Cortex-M3 0 *3 Z80 0/1 V850ES 0/1 260 | / Cortex-M0 0 *2 x86 0/1 TLCS-870 0/1 261 | / AVR 0/1 RX600(LE) 0/1 TLCS-900 0/1 262 | / AVR32 0 *1 RL78 0 *2 R32C 0 *2 263 | / PIC18 0/1 SH-2 0 *1 M16C 0/1 264 | / PIC24 0 *2 H8S 0 *1 MSP430 0 *2 265 | / PIC32 0 *1 H8/300H 0 *1 8051 0/1 266 | / 267 | / *1:Big-endian. 268 | / *2:Unaligned memory access is not supported. 269 | / *3:Some compilers generate LDM/STM for mem_cpy function. 270 | */ 271 | 272 | -------------------------------------------------------------------------------- /source/fatfs/history.txt: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | Revision history of FatFs module 3 | ---------------------------------------------------------------------------- 4 | 5 | R0.00 (February 26, 2006) 6 | Prototype. 7 | 8 | 9 | R0.01 (April 29, 2006) 10 | First stable version. 11 | 12 | 13 | R0.02 (June 01, 2006) 14 | Added FAT12 support. 15 | Removed unbuffered mode. 16 | Fixed a problem on small (<32M) partition. 17 | 18 | 19 | R0.02a (June 10, 2006) 20 | Added a configuration option (_FS_MINIMUM). 21 | 22 | 23 | R0.03 (September 22, 2006) 24 | Added f_rename(). 25 | Changed option _FS_MINIMUM to _FS_MINIMIZE. 26 | 27 | 28 | R0.03a (December 11, 2006) 29 | Improved cluster scan algorithm to write files fast. 30 | Fixed f_mkdir() creates incorrect directory on FAT32. 31 | 32 | 33 | R0.04 (February 04, 2007) 34 | Added f_mkfs(). 35 | Supported multiple drive system. 36 | Changed some interfaces for multiple drive system. 37 | Changed f_mountdrv() to f_mount(). 38 | 39 | 40 | R0.04a (April 01, 2007) 41 | Supported multiple partitions on a physical drive. 42 | Added a capability of extending file size to f_lseek(). 43 | Added minimization level 3. 44 | Fixed an endian sensitive code in f_mkfs(). 45 | 46 | 47 | R0.04b (May 05, 2007) 48 | Added a configuration option _USE_NTFLAG. 49 | Added FSINFO support. 50 | Fixed DBCS name can result FR_INVALID_NAME. 51 | Fixed short seek (<= csize) collapses the file object. 52 | 53 | 54 | R0.05 (August 25, 2007) 55 | Changed arguments of f_read(), f_write() and f_mkfs(). 56 | Fixed f_mkfs() on FAT32 creates incorrect FSINFO. 57 | Fixed f_mkdir() on FAT32 creates incorrect directory. 58 | 59 | 60 | R0.05a (February 03, 2008) 61 | Added f_truncate() and f_utime(). 62 | Fixed off by one error at FAT sub-type determination. 63 | Fixed btr in f_read() can be mistruncated. 64 | Fixed cached sector is not flushed when create and close without write. 65 | 66 | 67 | R0.06 (April 01, 2008) 68 | Added fputc(), fputs(), fprintf() and fgets(). 69 | Improved performance of f_lseek() on moving to the same or following cluster. 70 | 71 | 72 | R0.07 (April 01, 2009) 73 | Merged Tiny-FatFs as a configuration option. (_FS_TINY) 74 | Added long file name feature. (_USE_LFN) 75 | Added multiple code page feature. (_CODE_PAGE) 76 | Added re-entrancy for multitask operation. (_FS_REENTRANT) 77 | Added auto cluster size selection to f_mkfs(). 78 | Added rewind option to f_readdir(). 79 | Changed result code of critical errors. 80 | Renamed string functions to avoid name collision. 81 | 82 | 83 | R0.07a (April 14, 2009) 84 | Septemberarated out OS dependent code on reentrant cfg. 85 | Added multiple sector size feature. 86 | 87 | 88 | R0.07c (June 21, 2009) 89 | Fixed f_unlink() can return FR_OK on error. 90 | Fixed wrong cache control in f_lseek(). 91 | Added relative path feature. 92 | Added f_chdir() and f_chdrive(). 93 | Added proper case conversion to extended character. 94 | 95 | 96 | R0.07e (November 03, 2009) 97 | Septemberarated out configuration options from ff.h to ffconf.h. 98 | Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH. 99 | Fixed name matching error on the 13 character boundary. 100 | Added a configuration option, _LFN_UNICODE. 101 | Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. 102 | 103 | 104 | R0.08 (May 15, 2010) 105 | Added a memory configuration option. (_USE_LFN = 3) 106 | Added file lock feature. (_FS_SHARE) 107 | Added fast seek feature. (_USE_FASTSEEK) 108 | Changed some types on the API, XCHAR->TCHAR. 109 | Changed .fname in the FILINFO structure on Unicode cfg. 110 | String functions support UTF-8 encoding files on Unicode cfg. 111 | 112 | 113 | R0.08a (August 16, 2010) 114 | Added f_getcwd(). (_FS_RPATH = 2) 115 | Added sector erase feature. (_USE_ERASE) 116 | Moved file lock semaphore table from fs object to the bss. 117 | Fixed f_mkfs() creates wrong FAT32 volume. 118 | 119 | 120 | R0.08b (January 15, 2011) 121 | Fast seek feature is also applied to f_read() and f_write(). 122 | f_lseek() reports required table size on creating CLMP. 123 | Extended format syntax of f_printf(). 124 | Ignores duplicated directory separators in given path name. 125 | 126 | 127 | R0.09 (September 06, 2011) 128 | f_mkfs() supports multiple partition to complete the multiple partition feature. 129 | Added f_fdisk(). 130 | 131 | 132 | R0.09a (August 27, 2012) 133 | Changed f_open() and f_opendir() reject null object pointer to avoid crash. 134 | Changed option name _FS_SHARE to _FS_LOCK. 135 | Fixed assertion failure due to OS/2 EA on FAT12/16 volume. 136 | 137 | 138 | R0.09b (January 24, 2013) 139 | Added f_setlabel() and f_getlabel(). 140 | 141 | 142 | R0.10 (October 02, 2013) 143 | Added selection of character encoding on the file. (_STRF_ENCODE) 144 | Added f_closedir(). 145 | Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO) 146 | Added forced mount feature with changes of f_mount(). 147 | Improved behavior of volume auto detection. 148 | Improved write throughput of f_puts() and f_printf(). 149 | Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write(). 150 | Fixed f_write() can be truncated when the file size is close to 4GB. 151 | Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect error code. 152 | 153 | 154 | R0.10a (January 15, 2014) 155 | Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID) 156 | Added a configuration option of minimum sector size. (_MIN_SS) 157 | 2nd argument of f_rename() can have a drive number and it will be ignored. 158 | Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10) 159 | Fixed f_close() invalidates the file object without volume lock. 160 | Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10) 161 | Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07) 162 | 163 | 164 | R0.10b (May 19, 2014) 165 | Fixed a hard error in the disk I/O layer can collapse the directory entry. 166 | Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN. (appeared at R0.07) 167 | 168 | 169 | R0.10c (November 09, 2014) 170 | Added a configuration option for the platforms without RTC. (_FS_NORTC) 171 | Changed option name _USE_ERASE to _USE_TRIM. 172 | Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b) 173 | Fixed a potential problem of FAT access that can appear on disk error. 174 | Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08) 175 | 176 | 177 | R0.11 (February 09, 2015) 178 | Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND) 179 | Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c) 180 | Fixed _FS_NORTC option does not work properly. (appeared at R0.10c) 181 | -------------------------------------------------------------------------------- /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 | 13 | #else /* Embedded platform */ 14 | 15 | /* This type MUST be 8 bit */ 16 | typedef unsigned char BYTE; 17 | 18 | /* These types MUST be 16 bit */ 19 | typedef short SHORT; 20 | typedef unsigned short WORD; 21 | typedef unsigned short WCHAR; 22 | 23 | /* These types MUST be 16 bit or 32 bit */ 24 | typedef int INT; 25 | typedef unsigned int UINT; 26 | 27 | /* These types MUST be 32 bit */ 28 | typedef long LONG; 29 | typedef unsigned long DWORD; 30 | 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /source/fatfs/sdmmc/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../../types.h" -------------------------------------------------------------------------------- /source/fatfs/sdmmc/delay.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Normmatt 2 | // Licensed under GPLv2 or any later version 3 | // Refer to the license.txt file included. 4 | 5 | #pragma once 6 | 7 | #include "common.h" 8 | 9 | void ioDelay(u32 us); 10 | -------------------------------------------------------------------------------- /source/fatfs/sdmmc/delay.s: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Normmatt 2 | // Licensed under GPLv2 or any later version 3 | // Refer to the license.txt file included. 4 | 5 | .arm 6 | .global ioDelay 7 | .type ioDelay STT_FUNC 8 | 9 | @ioDelay ( u32 us ) 10 | ioDelay: 11 | ldr r1, =0x18000000 @ VRAM 12 | 1: 13 | @ Loop doing uncached reads from VRAM to make loop timing more reliable 14 | ldr r2, [r1] 15 | subs r0, #1 16 | bgt 1b 17 | bx lr 18 | -------------------------------------------------------------------------------- /source/fatfs/sdmmc/sdmmc.c: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Normmatt 2 | // Licensed under GPLv2 or any later version 3 | // Refer to the license.txt file included. 4 | 5 | #include "sdmmc.h" 6 | #include "delay.h" 7 | 8 | struct mmcdevice handleNAND; 9 | struct mmcdevice handleSD; 10 | 11 | static inline u16 sdmmc_read16(u16 reg) { 12 | return *(vu16*)(SDMMC_BASE + reg); 13 | } 14 | 15 | static inline void sdmmc_write16(u16 reg, u16 val) { 16 | *(vu16*)(SDMMC_BASE + reg) = val; 17 | } 18 | 19 | static inline u32 sdmmc_read32(u16 reg) { 20 | return *(vu32*)(SDMMC_BASE + reg); 21 | } 22 | 23 | static inline void sdmmc_write32(u16 reg, u32 val) { 24 | *(vu32*)(SDMMC_BASE + reg) = val; 25 | } 26 | 27 | static inline void sdmmc_mask16(u16 reg, const u16 clear, const u16 set) { 28 | u16 val = sdmmc_read16(reg); 29 | val &= ~clear; 30 | val |= set; 31 | sdmmc_write16(reg, val); 32 | } 33 | 34 | static inline void setckl(u32 data) 35 | { 36 | sdmmc_mask16(REG_SDCLKCTL, 0x100, 0); 37 | sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF); 38 | sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100); 39 | } 40 | 41 | 42 | mmcdevice *getMMCDevice(int drive) 43 | { 44 | if(drive==0) return &handleNAND; 45 | return &handleSD; 46 | } 47 | 48 | static u32 __attribute__((noinline)) geterror(struct mmcdevice *ctx) 49 | { 50 | return (ctx->error << 29) >> 31; 51 | } 52 | 53 | static void __attribute__((noinline)) inittarget(struct mmcdevice *ctx) 54 | { 55 | sdmmc_mask16(REG_SDPORTSEL,0x3,(u16)ctx->devicenumber); 56 | setckl(ctx->clk); 57 | if (ctx->SDOPT == 0) { 58 | sdmmc_mask16(REG_SDOPT, 0, 0x8000); 59 | } else { 60 | sdmmc_mask16(REG_SDOPT, 0x8000, 0); 61 | } 62 | 63 | } 64 | 65 | static void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args) 66 | { 67 | bool getSDRESP = (cmd << 15) >> 31; 68 | u16 flags = (cmd << 15) >> 31; 69 | const bool readdata = cmd & 0x20000; 70 | const bool writedata = cmd & 0x40000; 71 | 72 | if (readdata || writedata) 73 | flags |= TMIO_STAT0_DATAEND; 74 | 75 | ctx->error = 0; 76 | while (sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY); //mmc working? 77 | sdmmc_write16(REG_SDIRMASK0,0); 78 | sdmmc_write16(REG_SDIRMASK1,0); 79 | sdmmc_write16(REG_SDSTATUS0,0); 80 | sdmmc_write16(REG_SDSTATUS1,0); 81 | sdmmc_mask16(REG_SDDATACTL32,0x1800,0); 82 | 83 | sdmmc_write16(REG_SDCMDARG0,args &0xFFFF); 84 | sdmmc_write16(REG_SDCMDARG1,args >> 16); 85 | sdmmc_write16(REG_SDCMD,cmd &0xFFFF); 86 | 87 | u32 size = ctx->size; 88 | vu8 *dataPtr = ctx->data; 89 | 90 | bool useBuf = ( NULL != dataPtr ); 91 | 92 | u16 status0 = 0; 93 | while(true) { 94 | u16 status1 = sdmmc_read16(REG_SDSTATUS1); 95 | if (status1 & TMIO_STAT1_RXRDY) { 96 | if (readdata && useBuf) { 97 | sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0); 98 | //sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_RXRDY); 99 | if (size > 0x1FF) { 100 | for(int i = 0; i<0x200; i+=2) { 101 | u16 data = sdmmc_read16(REG_SDFIFO); 102 | *dataPtr++ = data & 0xFF; 103 | *dataPtr++ = data >> 8; 104 | } 105 | size -= 0x200; 106 | } 107 | } 108 | } 109 | 110 | if (status1 & TMIO_STAT1_TXRQ) { 111 | if (writedata && useBuf) { 112 | sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0); 113 | //sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_TXRQ); 114 | if (size > 0x1FF) { 115 | for (int i = 0; i<0x200; i+=2) { 116 | u16 data = *dataPtr++; 117 | data |= *dataPtr++ << 8; 118 | sdmmc_write16(REG_SDFIFO, data); 119 | } 120 | size -= 0x200; 121 | } 122 | } 123 | } 124 | if (status1 & TMIO_MASK_GW) { 125 | ctx->error |= 4; 126 | break; 127 | } 128 | 129 | if (!(status1 & TMIO_STAT1_CMD_BUSY)) { 130 | status0 = sdmmc_read16(REG_SDSTATUS0); 131 | if (sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND) 132 | ctx->error |= 0x1; 133 | if (status0 & TMIO_STAT0_DATAEND) 134 | ctx->error |= 0x2; 135 | 136 | if ((status0 & flags) == flags) 137 | break; 138 | } 139 | } 140 | ctx->stat0 = sdmmc_read16(REG_SDSTATUS0); 141 | ctx->stat1 = sdmmc_read16(REG_SDSTATUS1); 142 | sdmmc_write16(REG_SDSTATUS0,0); 143 | sdmmc_write16(REG_SDSTATUS1,0); 144 | 145 | if (getSDRESP != 0) { 146 | ctx->ret[0] = (u32)sdmmc_read16(REG_SDRESP0) | (u32)(sdmmc_read16(REG_SDRESP1) << 16); 147 | ctx->ret[1] = (u32)sdmmc_read16(REG_SDRESP2) | (u32)(sdmmc_read16(REG_SDRESP3) << 16); 148 | ctx->ret[2] = (u32)sdmmc_read16(REG_SDRESP4) | (u32)(sdmmc_read16(REG_SDRESP5) << 16); 149 | ctx->ret[3] = (u32)sdmmc_read16(REG_SDRESP6) | (u32)(sdmmc_read16(REG_SDRESP7) << 16); 150 | } 151 | } 152 | 153 | u32 __attribute__((noinline)) sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, vu8 *in) 154 | { 155 | if (handleSD.isSDHC == 0) 156 | sector_no <<= 9; 157 | inittarget(&handleSD); 158 | sdmmc_write16(REG_SDSTOP,0x100); 159 | 160 | sdmmc_write16(REG_SDBLKCOUNT,numsectors); 161 | handleSD.data = in; 162 | handleSD.size = numsectors << 9; 163 | sdmmc_send_command(&handleSD,0x52C19,sector_no); 164 | return geterror(&handleSD); 165 | } 166 | 167 | u32 __attribute__((noinline)) sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, vu8 *out) 168 | { 169 | if (handleSD.isSDHC == 0) 170 | sector_no <<= 9; 171 | inittarget(&handleSD); 172 | sdmmc_write16(REG_SDSTOP,0x100); 173 | 174 | sdmmc_write16(REG_SDBLKCOUNT,numsectors); 175 | handleSD.data = out; 176 | handleSD.size = numsectors << 9; 177 | sdmmc_send_command(&handleSD,0x33C12,sector_no); 178 | return geterror(&handleSD); 179 | } 180 | 181 | u32 __attribute__((noinline)) sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, vu8 *out) 182 | { 183 | if (handleNAND.isSDHC == 0) 184 | sector_no <<= 9; 185 | inittarget(&handleNAND); 186 | sdmmc_write16(REG_SDSTOP,0x100); 187 | 188 | sdmmc_write16(REG_SDBLKCOUNT,numsectors); 189 | 190 | handleNAND.data = out; 191 | handleNAND.size = numsectors << 9; 192 | sdmmc_send_command(&handleNAND,0x33C12,sector_no); 193 | inittarget(&handleSD); 194 | return geterror(&handleNAND); 195 | } 196 | 197 | u32 __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, vu8 *in) //experimental 198 | { 199 | if (handleNAND.isSDHC == 0) 200 | sector_no <<= 9; 201 | inittarget(&handleNAND); 202 | sdmmc_write16(REG_SDSTOP,0x100); 203 | 204 | sdmmc_write16(REG_SDBLKCOUNT,numsectors); 205 | 206 | handleNAND.data = in; 207 | handleNAND.size = numsectors << 9; 208 | sdmmc_send_command(&handleNAND,0x52C19,sector_no); 209 | inittarget(&handleSD); 210 | return geterror(&handleNAND); 211 | } 212 | 213 | static u32 calcSDSize(u8* csd, int type) 214 | { 215 | u32 result = 0; 216 | if (type == -1) type = csd[14] >> 6; 217 | switch (type) { 218 | case 0: 219 | { 220 | u32 block_len = csd[9] & 0xf; 221 | block_len = 1u << block_len; 222 | u32 mult = (u32)(csd[4] >> 7) | (u32)((csd[5] & 3) << 1); 223 | mult = 1u << (mult + 2); 224 | result = csd[8] & 3; 225 | result = (result << 8) | csd[7]; 226 | result = (result << 2) | (csd[6] >> 6); 227 | result = (result + 1) * mult * block_len / 512; 228 | } 229 | break; 230 | case 1: 231 | result = csd[7] & 0x3f; 232 | result = (result << 8) | csd[6]; 233 | result = (result << 8) | csd[5]; 234 | result = (result + 1) * 1024; 235 | break; 236 | default: 237 | break; //Do nothing otherwise 238 | } 239 | return result; 240 | } 241 | 242 | static void InitSD() 243 | { 244 | //NAND 245 | handleNAND.isSDHC = 0; 246 | handleNAND.SDOPT = 0; 247 | handleNAND.res = 0; 248 | handleNAND.initarg = 1; 249 | handleNAND.clk = 0x80; 250 | handleNAND.devicenumber = 1; 251 | 252 | //SD 253 | handleSD.isSDHC = 0; 254 | handleSD.SDOPT = 0; 255 | handleSD.res = 0; 256 | handleSD.initarg = 0; 257 | handleSD.clk = 0x80; 258 | handleSD.devicenumber = 0; 259 | 260 | *(vu16*)0x10006100 &= 0xF7FFu; //SDDATACTL32 261 | *(vu16*)0x10006100 &= 0xEFFFu; //SDDATACTL32 262 | *(vu16*)0x10006100 |= 0x402u; //SDDATACTL32 263 | *(vu16*)0x100060D8 = (*(vu16*)0x100060D8 & 0xFFDD) | 2; 264 | *(vu16*)0x10006100 &= 0xFFFDu; //SDDATACTL32 265 | *(vu16*)0x100060D8 &= 0xFFDDu; //SDDATACTL 266 | *(vu16*)0x10006104 = 0; //SDBLKLEN32 267 | *(vu16*)0x10006108 = 1; //SDBLKCOUNT32 268 | *(vu16*)0x100060E0 &= 0xFFFEu; //SDRESET 269 | *(vu16*)0x100060E0 |= 1u; //SDRESET 270 | *(vu16*)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0 271 | *(vu16*)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1 272 | *(vu16*)0x100060FC |= 0xDBu; //SDCTL_RESERVED7 273 | *(vu16*)0x100060FE |= 0xDBu; //SDCTL_RESERVED8 274 | *(vu16*)0x10006002 &= 0xFFFCu; //SDPORTSEL 275 | *(vu16*)0x10006024 = 0x40; //Nintendo sets this to 0x20 276 | *(vu16*)0x10006028 = 0x40EB; //Nintendo sets this to 0x40EE 277 | *(vu16*)0x10006002 &= 0xFFFCu; ////SDPORTSEL 278 | *(vu16*)0x10006026 = 512; //SDBLKLEN 279 | *(vu16*)0x10006008 = 0; //SDSTOP 280 | 281 | inittarget(&handleSD); 282 | } 283 | 284 | static int Nand_Init() 285 | { 286 | inittarget(&handleNAND); 287 | ioDelay(0xF000); 288 | 289 | sdmmc_send_command(&handleNAND,0,0); 290 | 291 | do { 292 | do { 293 | sdmmc_send_command(&handleNAND,0x10701,0x100000); 294 | } while ( !(handleNAND.error & 1) ); 295 | } while((handleNAND.ret[0] & 0x80000000) == 0); 296 | 297 | sdmmc_send_command(&handleNAND,0x10602,0x0); 298 | if (handleNAND.error & 0x4) return -1; 299 | 300 | sdmmc_send_command(&handleNAND,0x10403,handleNAND.initarg << 0x10); 301 | if (handleNAND.error & 0x4) return -1; 302 | 303 | sdmmc_send_command(&handleNAND,0x10609,handleNAND.initarg << 0x10); 304 | if (handleNAND.error & 0x4) return -1; 305 | 306 | handleNAND.total_size = calcSDSize((u8*)&handleNAND.ret[0],0); 307 | handleNAND.clk = 1; 308 | setckl(1); 309 | 310 | sdmmc_send_command(&handleNAND,0x10407,handleNAND.initarg << 0x10); 311 | if (handleNAND.error & 0x4) return -1; 312 | 313 | handleNAND.SDOPT = 1; 314 | 315 | sdmmc_send_command(&handleNAND,0x10506,0x3B70100); 316 | if (handleNAND.error & 0x4) return -1; 317 | 318 | sdmmc_send_command(&handleNAND,0x10506,0x3B90100); 319 | if (handleNAND.error & 0x4) return -1; 320 | 321 | sdmmc_send_command(&handleNAND,0x1040D,handleNAND.initarg << 0x10); 322 | if (handleNAND.error & 0x4) return -1; 323 | 324 | sdmmc_send_command(&handleNAND,0x10410,0x200); 325 | if (handleNAND.error & 0x4) return -1; 326 | 327 | handleNAND.clk |= 0x200; 328 | 329 | inittarget(&handleSD); 330 | 331 | return 0; 332 | } 333 | 334 | static int SD_Init() 335 | { 336 | inittarget(&handleSD); 337 | 338 | ioDelay(1u << 18); //Card needs a little bit of time to be detected, it seems 339 | 340 | //If not inserted 341 | if (!(*((vu16*)0x1000601c) & TMIO_STAT0_SIGSTATE)) return -1; 342 | 343 | sdmmc_send_command(&handleSD,0,0); 344 | sdmmc_send_command(&handleSD,0x10408,0x1AA); 345 | //u32 temp = (handleSD.ret[0] == 0x1AA) << 0x1E; 346 | u32 temp = (handleSD.error & 0x1) << 0x1E; 347 | 348 | //int count = 0; 349 | u32 temp2 = 0; 350 | do { 351 | do { 352 | sdmmc_send_command(&handleSD,0x10437,handleSD.initarg << 0x10); 353 | sdmmc_send_command(&handleSD,0x10769,0x00FF8000 | temp); 354 | temp2 = 1; 355 | } while ( !(handleSD.error & 1) ); 356 | 357 | } while((handleSD.ret[0] & 0x80000000) == 0); 358 | 359 | if(!((handleSD.ret[0] >> 30) & 1) || !temp) 360 | temp2 = 0; 361 | 362 | handleSD.isSDHC = temp2; 363 | 364 | sdmmc_send_command(&handleSD,0x10602,0); 365 | if (handleSD.error & 0x4) return -1; 366 | 367 | sdmmc_send_command(&handleSD,0x10403,0); 368 | if (handleSD.error & 0x4) return -1; 369 | handleSD.initarg = handleSD.ret[0] >> 0x10; 370 | 371 | sdmmc_send_command(&handleSD,0x10609,handleSD.initarg << 0x10); 372 | if (handleSD.error & 0x4) return -1; 373 | 374 | handleSD.total_size = calcSDSize((u8*)&handleSD.ret[0],-1); 375 | handleSD.clk = 1; 376 | setckl(1); 377 | 378 | sdmmc_send_command(&handleSD,0x10507,handleSD.initarg << 0x10); 379 | if (handleSD.error & 0x4) return -1; 380 | 381 | sdmmc_send_command(&handleSD,0x10437,handleSD.initarg << 0x10); 382 | if (handleSD.error & 0x4) return -1; 383 | 384 | handleSD.SDOPT = 1; 385 | sdmmc_send_command(&handleSD,0x10446,0x2); 386 | if (handleSD.error & 0x4) return -1; 387 | 388 | sdmmc_send_command(&handleSD,0x1040D,handleSD.initarg << 0x10); 389 | if (handleSD.error & 0x4) return -1; 390 | 391 | sdmmc_send_command(&handleSD,0x10410,0x200); 392 | if (handleSD.error & 0x4) return -1; 393 | handleSD.clk |= 0x200; 394 | 395 | return 0; 396 | } 397 | 398 | int sdmmc_sdcard_init() 399 | { 400 | InitSD(); 401 | int result = Nand_Init(); 402 | return result | SD_Init(); 403 | } 404 | 405 | int sdmmc_get_cid(int isNand, uint32_t *info) 406 | { 407 | struct mmcdevice *device; 408 | if(isNand) 409 | device = &handleNAND; 410 | else 411 | device = &handleSD; 412 | 413 | inittarget(device); 414 | // use cmd7 to put sd card in standby mode 415 | // CMD7 416 | { 417 | sdmmc_send_command(device,0x10507,0); 418 | //if((device->error & 0x4)) return -1; 419 | } 420 | 421 | // get sd card info 422 | // use cmd10 to read CID 423 | { 424 | sdmmc_send_command(device,0x1060A,device->initarg << 0x10); 425 | //if((device->error & 0x4)) return -2; 426 | 427 | for( int i = 0; i < 4; ++i ) { 428 | info[i] = device->ret[i]; 429 | } 430 | } 431 | 432 | // put sd card back to transfer mode 433 | // CMD7 434 | { 435 | sdmmc_send_command(device,0x10507,device->initarg << 0x10); 436 | //if((device->error & 0x4)) return -3; 437 | } 438 | 439 | if(isNand) 440 | { 441 | inittarget(&handleSD); 442 | } 443 | 444 | return 0; 445 | } 446 | -------------------------------------------------------------------------------- /source/fatfs/sdmmc/sdmmc.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Normmatt 2 | // Licensed under GPLv2 or any later version 3 | // Refer to the license.txt file included. 4 | 5 | #pragma once 6 | 7 | #include "common.h" 8 | 9 | #define SDMMC_BASE 0x10006000u 10 | 11 | #define REG_SDCMD 0x00 12 | #define REG_SDPORTSEL 0x02 13 | #define REG_SDCMDARG 0x04 14 | #define REG_SDCMDARG0 0x04 15 | #define REG_SDCMDARG1 0x06 16 | #define REG_SDSTOP 0x08 17 | #define REG_SDBLKCOUNT 0x0a 18 | 19 | #define REG_SDRESP0 0x0c 20 | #define REG_SDRESP1 0x0e 21 | #define REG_SDRESP2 0x10 22 | #define REG_SDRESP3 0x12 23 | #define REG_SDRESP4 0x14 24 | #define REG_SDRESP5 0x16 25 | #define REG_SDRESP6 0x18 26 | #define REG_SDRESP7 0x1a 27 | 28 | #define REG_SDSTATUS0 0x1c 29 | #define REG_SDSTATUS1 0x1e 30 | 31 | #define REG_SDIRMASK0 0x20 32 | #define REG_SDIRMASK1 0x22 33 | #define REG_SDCLKCTL 0x24 34 | 35 | #define REG_SDBLKLEN 0x26 36 | #define REG_SDOPT 0x28 37 | #define REG_SDFIFO 0x30 38 | 39 | #define REG_SDDATACTL 0xd8 40 | #define REG_SDRESET 0xe0 41 | #define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not? 42 | 43 | #define REG_SDDATACTL32 0x100 44 | #define REG_SDBLKLEN32 0x104 45 | #define REG_SDBLKCOUNT32 0x108 46 | #define REG_SDFIFO32 0x10C 47 | 48 | #define REG_CLK_AND_WAIT_CTL 0x138 49 | #define REG_RESET_SDIO 0x1e0 50 | 51 | #define TMIO_STAT0_CMDRESPEND 0x0001 52 | #define TMIO_STAT0_DATAEND 0x0004 53 | #define TMIO_STAT0_CARD_REMOVE 0x0008 54 | #define TMIO_STAT0_CARD_INSERT 0x0010 55 | #define TMIO_STAT0_SIGSTATE 0x0020 56 | #define TMIO_STAT0_WRPROTECT 0x0080 57 | #define TMIO_STAT0_CARD_REMOVE_A 0x0100 58 | #define TMIO_STAT0_CARD_INSERT_A 0x0200 59 | #define TMIO_STAT0_SIGSTATE_A 0x0400 60 | #define TMIO_STAT1_CMD_IDX_ERR 0x0001 61 | #define TMIO_STAT1_CRCFAIL 0x0002 62 | #define TMIO_STAT1_STOPBIT_ERR 0x0004 63 | #define TMIO_STAT1_DATATIMEOUT 0x0008 64 | #define TMIO_STAT1_RXOVERFLOW 0x0010 65 | #define TMIO_STAT1_TXUNDERRUN 0x0020 66 | #define TMIO_STAT1_CMDTIMEOUT 0x0040 67 | #define TMIO_STAT1_RXRDY 0x0100 68 | #define TMIO_STAT1_TXRQ 0x0200 69 | #define TMIO_STAT1_ILL_FUNC 0x2000 70 | #define TMIO_STAT1_CMD_BUSY 0x4000 71 | #define TMIO_STAT1_ILL_ACCESS 0x8000 72 | 73 | //Comes from TWLSDK mongoose.tef DWARF info 74 | #define SDMC_NORMAL 0x00000000 75 | #define SDMC_ERR_COMMAND 0x00000001 76 | #define SDMC_ERR_CRC 0x00000002 77 | #define SDMC_ERR_END 0x00000004 78 | #define SDMC_ERR_TIMEOUT 0x00000008 79 | #define SDMC_ERR_FIFO_OVF 0x00000010 80 | #define SDMC_ERR_FIFO_UDF 0x00000020 81 | #define SDMC_ERR_WP 0x00000040 82 | #define SDMC_ERR_ABORT 0x00000080 83 | #define SDMC_ERR_FPGA_TIMEOUT 0x00000100 84 | #define SDMC_ERR_PARAM 0x00000200 85 | #define SDMC_ERR_R1_STATUS 0x00000800 86 | #define SDMC_ERR_NUM_WR_SECTORS 0x00001000 87 | #define SDMC_ERR_RESET 0x00002000 88 | #define SDMC_ERR_ILA 0x00004000 89 | #define SDMC_ERR_INFO_DETECT 0x00008000 90 | 91 | #define SDMC_STAT_ERR_UNKNOWN 0x00080000 92 | #define SDMC_STAT_ERR_CC 0x00100000 93 | #define SDMC_STAT_ERR_ECC_FAILED 0x00200000 94 | #define SDMC_STAT_ERR_CRC 0x00800000 95 | #define SDMC_STAT_ERR_OTHER 0xf9c70008 96 | 97 | #define TMIO_MASK_ALL 0x837f031d 98 | 99 | #define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \ 100 | TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR) 101 | 102 | #define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND) 103 | #define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND) 104 | 105 | typedef struct mmcdevice { 106 | vu8* data; 107 | u32 size; 108 | u32 error; 109 | u16 stat0; 110 | u16 stat1; 111 | u32 ret[4]; 112 | u32 initarg; 113 | u32 isSDHC; 114 | u32 clk; 115 | u32 SDOPT; 116 | u32 devicenumber; 117 | u32 total_size; //size in sectors of the device 118 | u32 res; 119 | } mmcdevice; 120 | 121 | int sdmmc_sdcard_init(); 122 | u32 sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, vu8 *out); 123 | u32 sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, vu8 *in); 124 | mmcdevice *getMMCDevice(int drive); 125 | 126 | u32 sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, vu8 *out); 127 | u32 sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, vu8 *in); 128 | int sdmmc_get_cid(int isNand, uint32_t *info); -------------------------------------------------------------------------------- /source/firm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * firm.c 3 | * by Reisyukaku / Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | */ 6 | 7 | #include "firm.h" 8 | #include "patches.h" 9 | #include "memory.h" 10 | #include "fs.h" 11 | #include "emunand.h" 12 | #include "crypto.h" 13 | #include "draw.h" 14 | #include "screeninit.h" 15 | #include "utils.h" 16 | #include "buttons.h" 17 | #include "../build/patches.h" 18 | 19 | static firmHeader *const firm = (firmHeader *)0x24000000; 20 | static const firmSectionHeader *section; 21 | static u8 *arm9Section; 22 | 23 | static u32 firmSize, 24 | console, 25 | emuNAND, 26 | a9lhSetup, 27 | emuOffset, 28 | emuHeader; 29 | 30 | void setupCFW(void){ 31 | 32 | //Determine if booting with A9LH 33 | u32 a9lhBoot = (PDN_SPI_CNT == 0x0) ? 1 : 0; 34 | //Retrieve the last booted FIRM 35 | u8 previousFirm = CFG_BOOTENV; 36 | //Detect the console being used 37 | console = (PDN_MPCORE_CFG == 1) ? 0 : 1; 38 | //Get pressed buttons 39 | u16 pressed = HID_PAD; 40 | 41 | //Determine if A9LH is installed 42 | 43 | if(a9lhBoot){ 44 | if(pressed == SAFE_MODE) 45 | error("Using Safe Mode would brick you, or remove A9LH!"); 46 | 47 | a9lhSetup = 1; 48 | } else{ 49 | a9lhSetup = 0; 50 | } 51 | 52 | //Detect EmuNAND if not booting sysNAND or returning from AGB_FIRM 53 | emuNAND = 0; 54 | if (pressed != BUTTON_L1 && previousFirm != 7){ 55 | emuNAND = 1; 56 | getEmunandSect(&emuOffset, &emuHeader, &emuNAND); 57 | } 58 | } 59 | 60 | //Load FIRM into FCRAM 61 | void loadFirm(void){ 62 | u32 mode; 63 | 64 | // Load firm from emuNAND 65 | if (emuNAND){ 66 | //Read FIRM from NAND and write to FCRAM 67 | nandFirm0(1, emuOffset, (u8 *)firm); 68 | //Check for correct decryption 69 | if(firm->magic != 0x4D524946) 70 | error("Couldn't decrypt emuNAND FIRM0"); 71 | } 72 | //If not using an A9LH setup, load 9.0 FIRM from NAND 73 | else if(!a9lhSetup){ 74 | //Read FIRM from NAND and write to FCRAM 75 | nandFirm0(0, 0, (u8 *)firm); 76 | //Check for correct decryption 77 | if(firm->magic != 0x4D524946) 78 | error("Couldn't decrypt NAND FIRM0 (O3DS not on 9.x?)"); 79 | } 80 | //Load FIRM from SD 81 | else{ 82 | const char *path = "/firmware.bin"; 83 | firmSize = fileSize(path); 84 | if(!firmSize) error("firmware.bin doesn't exist"); 85 | fileFirm0(path, (u8 *)firm); 86 | } 87 | 88 | section = firm->section; 89 | 90 | //Check that the loaded FIRM matches the console 91 | if((((u32)section[2].address >> 8) & 0xFF) != (console ? 0x60 : 0x68)) 92 | error("FIRM doesn't match this\nconsole, or it's encrypted"); 93 | 94 | arm9Section = (u8 *)section[2].address; 95 | 96 | if(console) 97 | { 98 | switch(arm9Section[0x53]) 99 | { 100 | case 0xFF: 101 | mode = 0; 102 | break; 103 | case '1': 104 | mode = 1; 105 | break; 106 | default: 107 | mode = 2; 108 | break; 109 | } 110 | arm9Loader(arm9Section, mode); 111 | } 112 | } 113 | 114 | //NAND redirection 115 | static inline void loadEmu(u8 *proc9Offset){ 116 | 117 | //Copy emuNAND code 118 | void *emuCodeOffset = getEmuCode(proc9Offset); 119 | memcpy(emuCodeOffset, emunand, emunand_size); 120 | 121 | //Add the data of the found emuNAND 122 | u32 *pos_offset = (u32 *)memsearch(emuCodeOffset, "NAND", emunand_size, 4); 123 | u32 *pos_header = (u32 *)memsearch(emuCodeOffset, "NCSD", emunand_size, 4); 124 | *pos_offset = emuOffset; 125 | *pos_header = emuHeader; 126 | 127 | //Find and add the SDMMC struct 128 | u32 *pos_sdmmc = (u32 *)memsearch(emuCodeOffset, "SDMC", emunand_size, 4); 129 | *pos_sdmmc = getSDMMC(arm9Section, section[2].size); 130 | 131 | //Calculate offset for the hooks 132 | u32 branchOffset = (u32)emuCodeOffset; 133 | 134 | //Add emunand hooks 135 | u32 emuRead, 136 | emuWrite; 137 | 138 | getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite); 139 | *(u16 *)emuRead = nandRedir[0]; 140 | *((u16 *)emuRead + 1) = nandRedir[1]; 141 | *((u32 *)emuRead + 1) = branchOffset; 142 | *(u16 *)emuWrite = nandRedir[0]; 143 | *((u16 *)emuWrite + 1) = nandRedir[1]; 144 | *((u32 *)emuWrite + 1) = branchOffset; 145 | 146 | //Set MPU for emu code region 147 | u32 *mpuOffset = getMPU(arm9Section, section[2].size); 148 | *mpuOffset = mpuPatch[0]; 149 | *(mpuOffset + 6) = mpuPatch[1]; 150 | *(mpuOffset + 9) = mpuPatch[2]; 151 | } 152 | 153 | static inline void injectLoader(void) 154 | { 155 | u8 *arm11Section0 = section[0].address; 156 | u32 loaderSize; 157 | u32 loaderOffset = getLoader(arm11Section0, &loaderSize); 158 | 159 | if (loaderSize < (u32)injector_size) 160 | { 161 | error("Injector too large for this FIRM! Please rebuild."); 162 | return; 163 | } 164 | 165 | //memcpy(section[0].address, arm11Section0, loaderOffset); 166 | memcpy(arm11Section0 + loaderOffset, injector, injector_size); 167 | //Patch content size and ExeFS size to match the repaced loader's ones 168 | *((u32 *)(arm11Section0 + loaderOffset) + 0x41) = loaderSize / 0x200; 169 | *((u32 *)(arm11Section0 + loaderOffset) + 0x69) = loaderSize / 0x200 - 5; 170 | } 171 | 172 | //Patches 173 | void patchFirm(void){ 174 | 175 | if(emuNAND){ 176 | //Find the Process9 NCCH location 177 | u8 *proc9Offset = getProc9(arm9Section, section[2].size); 178 | 179 | //Apply emuNAND patches 180 | loadEmu(proc9Offset); 181 | 182 | /* 183 | //Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax 184 | //Calculate offset for the firmlaunch code 185 | void *rebootOffset = getReboot(arm9Section, section[2].size); 186 | //Calculate offset for the fOpen function 187 | u32 fOpenOffset = getfOpen(proc9Offset, rebootOffset); 188 | 189 | //Copy firmlaunch code 190 | memcpy(rebootOffset, reboot, reboot_size); 191 | 192 | //Put the fOpen offset in the right location 193 | u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4); 194 | *pos_fopen = fOpenOffset; 195 | */ 196 | } 197 | 198 | if(a9lhSetup && !emuNAND){ 199 | //Patch FIRM partitions writes on sysNAND to protect A9LH 200 | u16 *writeOffset = getFirmWrite(arm9Section, section[2].size); 201 | *writeOffset = writeBlock[0]; 202 | *(writeOffset + 1) = writeBlock[1]; 203 | } 204 | 205 | //Replace the FIRM loader with the injector while copying section0 206 | injectLoader(); 207 | 208 | //Patch ARM9 entrypoint on N3DS to skip arm9loader 209 | if(console) 210 | firm->arm9Entry = (u8 *)0x801B01C; 211 | } 212 | 213 | void launchFirm(void){ 214 | //Fixes N3DS 3D 215 | deinitScreens(); 216 | 217 | //Set ARM11 kernel entrypoint 218 | *(vu32 *)0x1FFFFFF8 = (u32)firm->arm11Entry; 219 | 220 | //Final jump to arm9 kernel 221 | ((void (*)())firm->arm9Entry)(); 222 | } -------------------------------------------------------------------------------- /source/firm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * firm.h 3 | * by Reisyukaku / Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "types.h" 10 | 11 | #define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC) 12 | #define PDN_SPI_CNT (*(vu8 *)0x101401C0) 13 | 14 | //FIRM Header layout 15 | typedef struct firmSectionHeader { 16 | u32 offset; 17 | u8 *address; 18 | u32 size; 19 | u32 procType; 20 | u8 hash[0x20]; 21 | } firmSectionHeader; 22 | 23 | typedef struct firmHeader { 24 | u32 magic; 25 | u32 reserved1; 26 | u8 *arm11Entry; 27 | u8 *arm9Entry; 28 | u8 reserved2[0x30]; 29 | firmSectionHeader section[4]; 30 | } firmHeader; 31 | 32 | void setupCFW(void); 33 | void loadFirm(void); 34 | void patchFirm(void); 35 | void launchFirm(void); -------------------------------------------------------------------------------- /source/font.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file was autogenerated by raw2c. 3 | Visit http://www.devkitpro.org 4 | */ 5 | 6 | //--------------------------------------------------------------------------------- 7 | #ifndef _font_h_ 8 | #define _font_h_ 9 | //--------------------------------------------------------------------------------- 10 | static const unsigned char font[] = { 11 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, 12 | 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 13 | 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x3c, 0x3c, 0x18, 0xff, 0xe7, 0x18, 0x3c, 0x00, 14 | 0x10, 0x38, 0x7c, 0xfe, 0xee, 0x10, 0x38, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 15 | 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 16 | 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, 17 | 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x08, 0x0c, 0x0a, 0x0a, 0x08, 0x78, 0xf0, 0x00, 18 | 0x18, 0x14, 0x1a, 0x16, 0x72, 0xe2, 0x0e, 0x1c, 0x10, 0x54, 0x38, 0xee, 0x38, 0x54, 0x10, 0x00, 19 | 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, 20 | 0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, 21 | 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x00, 0x1c, 0x22, 0x38, 0x44, 0x44, 0x38, 0x88, 0x70, 22 | 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, 0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x7e, 23 | 0x18, 0x3c, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x5a, 0x3c, 0x18, 0x00, 24 | 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 25 | 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x24, 0x42, 0xff, 0x42, 0x24, 0x00, 0x00, 26 | 0x00, 0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00, 28 | 0x6c, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 29 | 0x10, 0x7c, 0xd0, 0x7c, 0x16, 0xfc, 0x10, 0x00, 0x00, 0x66, 0xac, 0xd8, 0x36, 0x6a, 0xcc, 0x00, 30 | 0x38, 0x4c, 0x38, 0x78, 0xce, 0xcc, 0x7a, 0x00, 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 31 | 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, 32 | 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 33 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 34 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00, 35 | 0x7c, 0xce, 0xde, 0xf6, 0xe6, 0xe6, 0x7c, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x7e, 0x00, 36 | 0x7c, 0xc6, 0x06, 0x1c, 0x70, 0xc6, 0xfe, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 37 | 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, 0xfe, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00, 38 | 0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00, 0xfe, 0xc6, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, 39 | 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00, 40 | 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20, 41 | 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 42 | 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, 43 | 0x7c, 0x82, 0x9e, 0xa6, 0x9e, 0x80, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 44 | 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 45 | 0xfc, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 46 | 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0xce, 0xc6, 0x7e, 0x00, 47 | 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 48 | 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 49 | 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x82, 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, 50 | 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 51 | 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x06, 52 | 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0xc6, 0xc0, 0x7c, 0x06, 0xc6, 0x7c, 0x00, 53 | 0x7e, 0x5a, 0x5a, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 54 | 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x82, 0x00, 55 | 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00, 56 | 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, 57 | 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 58 | 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 59 | 0x30, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 60 | 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc6, 0x7c, 0x00, 61 | 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 62 | 0x1c, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x78, 63 | 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 64 | 0x00, 0x0c, 0x00, 0x1c, 0x0c, 0x0c, 0xcc, 0x78, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, 65 | 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0xcc, 0xfe, 0xd6, 0xd6, 0xd6, 0x00, 66 | 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 67 | 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, 68 | 0x00, 0x00, 0xde, 0x76, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0x7c, 0x00, 69 | 0x10, 0x30, 0xfc, 0x30, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 70 | 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 71 | 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 72 | 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, 0x0e, 0x18, 0x18, 0x30, 0x18, 0x18, 0x0e, 0x00, 73 | 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0xe0, 0x30, 0x30, 0x18, 0x30, 0x30, 0xe0, 0x00, 74 | 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 75 | 0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x70, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 76 | 0x0e, 0x10, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0x7c, 0x82, 0x38, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 77 | 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 78 | 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0xc0, 0x7c, 0x18, 0x70, 79 | 0x7c, 0x82, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 80 | 0xe0, 0x10, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 81 | 0x7c, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xe0, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 82 | 0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x38, 0x38, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 83 | 0x0e, 0x10, 0xfe, 0x60, 0x78, 0x60, 0xfe, 0x00, 0x00, 0x00, 0x7c, 0x12, 0x7e, 0xd0, 0x7e, 0x00, 84 | 0x7e, 0xc8, 0xc8, 0xfe, 0xc8, 0xc8, 0xce, 0x00, 0x7c, 0x82, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 85 | 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xe0, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 86 | 0x7c, 0x82, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 87 | 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 88 | 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x18, 0x7c, 0xd6, 0xd0, 0xd6, 0x7c, 0x18, 0x00, 89 | 0x38, 0x6c, 0x60, 0xf0, 0x60, 0xf2, 0xdc, 0x00, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x00, 90 | 0xf8, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0x06, 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, 91 | 0x0e, 0x10, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0x0e, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 92 | 0x0e, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x0e, 0x10, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 93 | 0x66, 0x98, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x98, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0x00, 94 | 0x38, 0x0c, 0x3c, 0x34, 0x00, 0x7e, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 95 | 0x30, 0x00, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00, 96 | 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, 0xc0, 0xc8, 0xd0, 0xfe, 0x46, 0x8c, 0x1e, 0x00, 97 | 0xc0, 0xc8, 0xd0, 0xec, 0x5c, 0xbe, 0x0c, 0x00, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x18, 0x00, 98 | 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 99 | 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 100 | 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 101 | 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 102 | 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 103 | 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 104 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 105 | 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 106 | 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 107 | 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 108 | 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 109 | 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 110 | 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 111 | 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 112 | 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 113 | 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 114 | 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 115 | 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 116 | 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 117 | 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 118 | 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 119 | 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 120 | 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 121 | 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 122 | 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 123 | 0x00, 0x00, 0x74, 0xcc, 0xc8, 0xdc, 0x76, 0x00, 0x78, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xdc, 0x40, 124 | 0xfe, 0x62, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x02, 0x7e, 0xec, 0x6c, 0x6c, 0x48, 0x00, 125 | 0xfe, 0x62, 0x30, 0x18, 0x30, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x7e, 0xd0, 0xc8, 0xc8, 0x70, 0x00, 126 | 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xf8, 0x80, 0x00, 0x00, 0x7e, 0xd8, 0x18, 0x18, 0x10, 0x00, 127 | 0x38, 0x10, 0x7c, 0xd6, 0xd6, 0x7c, 0x10, 0x38, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 128 | 0x7c, 0xc6, 0xc6, 0xc6, 0x6c, 0x28, 0xee, 0x00, 0x3c, 0x22, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00, 129 | 0x00, 0x00, 0x66, 0x99, 0x99, 0x66, 0x00, 0x00, 0x00, 0x06, 0x7c, 0x9e, 0xf2, 0x7c, 0xc0, 0x00, 130 | 0x00, 0x00, 0x7c, 0xc0, 0xf8, 0xc0, 0x7c, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 131 | 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00, 132 | 0x30, 0x18, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x00, 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x00, 133 | 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 134 | 0x00, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 135 | 0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 136 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x00, 137 | 0xd8, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x30, 0xc0, 0xf0, 0x00, 0x00, 0x00, 0x00, 138 | 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 139 | 140 | }; 141 | const int font_size = sizeof(font); 142 | //--------------------------------------------------------------------------------- 143 | #endif //_font_h_ 144 | //--------------------------------------------------------------------------------- 145 | -------------------------------------------------------------------------------- /source/fs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * fs.c 3 | * by Reisyukaku / Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | */ 6 | 7 | #include "fs.h" 8 | #include "fatfs/ff.h" 9 | #include "firm.h" 10 | 11 | static FATFS fs; 12 | 13 | u32 mountSD(void){ 14 | if(f_mount(&fs, "0:", 1) != FR_OK) return 0; 15 | return 1; 16 | } 17 | 18 | u32 fileRead(void *dest, const char *path, u32 size){ 19 | FRESULT fr; 20 | FIL fp; 21 | unsigned int br = 0; 22 | 23 | fr = f_open(&fp, path, FA_READ); 24 | if(fr == FR_OK){ 25 | if(!size) size = f_size(&fp); 26 | fr = f_read(&fp, dest, size, &br); 27 | } 28 | 29 | f_close(&fp); 30 | return fr ? 0 : 1; 31 | } 32 | 33 | u32 fileWrite(const void *buffer, const char *path, u32 size){ 34 | FRESULT fr; 35 | FIL fp; 36 | unsigned int br = 0; 37 | 38 | fr = f_open(&fp, path, FA_WRITE | FA_OPEN_ALWAYS); 39 | if(fr == FR_OK) fr = f_write(&fp, buffer, size, &br); 40 | 41 | f_close(&fp); 42 | return fr ? 0 : 1; 43 | } 44 | 45 | u32 fileSize(const char *path){ 46 | FIL fp; 47 | u32 size = 0; 48 | 49 | if(f_open(&fp, path, FA_READ) == FR_OK) 50 | size = f_size(&fp); 51 | 52 | f_close(&fp); 53 | return size; 54 | } 55 | 56 | u32 fileExists(const char *path){ 57 | FIL fp; 58 | u32 exists = 0; 59 | 60 | if(f_open(&fp, path, FA_READ) == FR_OK) exists = 1; 61 | 62 | f_close(&fp); 63 | return exists; 64 | } 65 | 66 | void fileDelete(const char *path){ 67 | f_unlink(path); 68 | } 69 | 70 | void fileFirm0(const char *path, u8 *outbuf) { 71 | FRESULT fr; 72 | FIL fp; 73 | unsigned int br = 0; 74 | firmHeader *hdr = (firmHeader *)outbuf; 75 | 76 | if (f_open(&fp, path, FA_READ) != FR_OK){ 77 | return; 78 | } 79 | fr = f_read(&fp, outbuf, 0x200, &br); 80 | if (fr != FR_OK || hdr->magic != 0x4D524946) { // FIRM 81 | goto err; 82 | } 83 | 84 | for (int i = 0; i < 4; i++) { 85 | if (hdr->section[i].size) { 86 | if (f_lseek(&fp, hdr->section[i].offset) != FR_OK) { 87 | goto err; 88 | } 89 | if (f_read(&fp, hdr->section[i].address, hdr->section[i].size, &br) != FR_OK) { 90 | goto err; 91 | } 92 | } 93 | } 94 | 95 | err: 96 | f_close(&fp); 97 | } -------------------------------------------------------------------------------- /source/fs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fs.h 3 | * by Reisyukaku / Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "types.h" 10 | 11 | u32 mountSD(void); 12 | u32 fileRead(void *dest, const char *path, u32 size); 13 | u32 fileWrite(const void *buffer, const char *path, u32 size); 14 | u32 fileSize(const char *path); 15 | u32 fileExists(const char *path); 16 | void fileDelete(const char *path); 17 | void fileFirm0(const char *path, u8 *outbuf); -------------------------------------------------------------------------------- /source/i2c.c: -------------------------------------------------------------------------------- 1 | #include "i2c.h" 2 | 3 | //----------------------------------------------------------------------------- 4 | 5 | static const struct { u8 bus_id, reg_addr; } dev_data[] = { 6 | {0, 0x4A}, {0, 0x7A}, {0, 0x78}, 7 | {1, 0x4A}, {1, 0x78}, {1, 0x2C}, 8 | {1, 0x2E}, {1, 0x40}, {1, 0x44}, 9 | {2, 0xD6}, {2, 0xD0}, {2, 0xD2}, 10 | {2, 0xA4}, {2, 0x9A}, {2, 0xA0}, 11 | }; 12 | 13 | static inline u8 i2cGetDeviceBusId(u8 device_id) { 14 | return dev_data[device_id].bus_id; 15 | } 16 | 17 | static inline u8 i2cGetDeviceRegAddr(u8 device_id) { 18 | return dev_data[device_id].reg_addr; 19 | } 20 | 21 | //----------------------------------------------------------------------------- 22 | 23 | static vu8* reg_data_addrs[] = { 24 | (vu8*)(I2C1_REG_OFF + I2C_REG_DATA), 25 | (vu8*)(I2C2_REG_OFF + I2C_REG_DATA), 26 | (vu8*)(I2C3_REG_OFF + I2C_REG_DATA), 27 | }; 28 | 29 | static inline vu8* i2cGetDataReg(u8 bus_id) { 30 | return reg_data_addrs[bus_id]; 31 | } 32 | 33 | //----------------------------------------------------------------------------- 34 | 35 | static vu8* reg_cnt_addrs[] = { 36 | (vu8*)(I2C1_REG_OFF + I2C_REG_CNT), 37 | (vu8*)(I2C2_REG_OFF + I2C_REG_CNT), 38 | (vu8*)(I2C3_REG_OFF + I2C_REG_CNT), 39 | }; 40 | 41 | static inline vu8* i2cGetCntReg(u8 bus_id) { 42 | return reg_cnt_addrs[bus_id]; 43 | } 44 | 45 | //----------------------------------------------------------------------------- 46 | 47 | static inline void i2cWaitBusy(u8 bus_id) { 48 | while (*i2cGetCntReg(bus_id) & 0x80); 49 | } 50 | 51 | static inline u32 i2cGetResult(u8 bus_id) { 52 | i2cWaitBusy(bus_id); 53 | return (*i2cGetCntReg(bus_id) >> 4) & 1; 54 | } 55 | 56 | static void i2cStop(u8 bus_id, u8 arg0) { 57 | *i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0; 58 | i2cWaitBusy(bus_id); 59 | *i2cGetCntReg(bus_id) = 0xC5; 60 | } 61 | 62 | //----------------------------------------------------------------------------- 63 | 64 | static u32 i2cSelectDevice(u8 bus_id, u8 dev_reg) { 65 | i2cWaitBusy(bus_id); 66 | *i2cGetDataReg(bus_id) = dev_reg; 67 | *i2cGetCntReg(bus_id) = 0xC2; 68 | return i2cGetResult(bus_id); 69 | } 70 | 71 | static u32 i2cSelectRegister(u8 bus_id, u8 reg) { 72 | i2cWaitBusy(bus_id); 73 | *i2cGetDataReg(bus_id) = reg; 74 | *i2cGetCntReg(bus_id) = 0xC0; 75 | return i2cGetResult(bus_id); 76 | } 77 | 78 | //----------------------------------------------------------------------------- 79 | 80 | u32 i2cWriteRegister(u8 dev_id, u8 reg, u8 data) { 81 | u8 bus_id = i2cGetDeviceBusId(dev_id); 82 | u8 dev_addr = i2cGetDeviceRegAddr(dev_id); 83 | 84 | for (int i = 0; i < 8; i++) { 85 | if (i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) { 86 | i2cWaitBusy(bus_id); 87 | *i2cGetDataReg(bus_id) = data; 88 | *i2cGetCntReg(bus_id) = 0xC1; 89 | i2cStop(bus_id, 0); 90 | if (i2cGetResult(bus_id)) 91 | return 1; 92 | } 93 | *i2cGetCntReg(bus_id) = 0xC5; 94 | i2cWaitBusy(bus_id); 95 | } 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /source/i2c.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #define I2C1_REG_OFF 0x10161000 6 | #define I2C2_REG_OFF 0x10144000 7 | #define I2C3_REG_OFF 0x10148000 8 | 9 | #define I2C_REG_DATA 0 10 | #define I2C_REG_CNT 1 11 | #define I2C_REG_CNTEX 2 12 | #define I2C_REG_SCL 4 13 | 14 | #define I2C_DEV_MCU 3 15 | #define I2C_DEV_GYRO 10 16 | #define I2C_DEV_IR 13 17 | 18 | u32 i2cWriteRegister(u8 dev_id, u8 reg, u8 data); -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | * by Reisyukaku / Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | * 6 | * Minimalist CFW for (N)3DS 7 | */ 8 | 9 | #include "fs.h" 10 | #include "firm.h" 11 | 12 | void main(void){ 13 | mountSD(); 14 | setupCFW(); 15 | loadFirm(); 16 | patchFirm(); 17 | launchFirm(); 18 | } -------------------------------------------------------------------------------- /source/memory.c: -------------------------------------------------------------------------------- 1 | /* 2 | * memory.c 3 | * by Reisyukaku / Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | * 6 | * Quick Search algorithm adapted from http://igm.univ-mlv.fr/~lecroq/string/node19.html#SECTION00190 7 | */ 8 | 9 | #include "memory.h" 10 | 11 | void memcpy(void *dest, const void *src, u32 size){ 12 | u8 *destc = (u8 *)dest; 13 | const u8 *srcc = (const u8 *)src; 14 | for(u32 i = 0; i < size; i++) 15 | destc[i] = srcc[i]; 16 | } 17 | 18 | void memmove(void *dest, const void *src, u32 size){ 19 | if (dest < src) 20 | return memcpy(dest, src, size); 21 | else{ 22 | u8 *destc = (u8 *)dest; 23 | const u8 *srcc = (const u8 *)src; 24 | for(u32 i = 1; i <= size; ++i) 25 | destc[size-i] = srcc[size-i]; 26 | } 27 | } 28 | 29 | void memset(void *dest, int filler, u32 size){ 30 | u8 *destc = (u8 *)dest; 31 | for(u32 i = 0; i < size; i++) 32 | destc[i] = (u8)filler; 33 | } 34 | 35 | void memset32(void *dest, u32 filler, u32 size){ 36 | u32 *dest32 = (u32 *)dest; 37 | for (u32 i = 0; i < size / 4; i++) 38 | dest32[i] = filler; 39 | } 40 | 41 | int memcmp(const void *buf1, const void *buf2, u32 size){ 42 | const u8 *buf1c = (const u8 *)buf1; 43 | const u8 *buf2c = (const u8 *)buf2; 44 | for(u32 i = 0; i < size; i++){ 45 | int cmp = buf1c[i] - buf2c[i]; 46 | if(cmp) return cmp; 47 | } 48 | return 0; 49 | } 50 | 51 | u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize){ 52 | const u8 *patternc = (const u8 *)pattern; 53 | 54 | //Preprocessing 55 | u32 table[256]; 56 | 57 | for(u32 i = 0; i < 256; ++i) 58 | table[i] = patternSize + 1; 59 | for(u32 i = 0; i < patternSize; ++i) 60 | table[patternc[i]] = patternSize - i; 61 | 62 | //Searching 63 | u32 j = 0; 64 | 65 | while(j <= size - patternSize){ 66 | if(memcmp(patternc, startPos + j, patternSize) == 0) 67 | return startPos + j; 68 | j += table[startPos[j + patternSize]]; 69 | } 70 | 71 | return NULL; 72 | } -------------------------------------------------------------------------------- /source/memory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * memory.h 3 | * by Reisyukaku / Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | * 6 | * Quick Search algorithm adapted from http://igm.univ-mlv.fr/~lecroq/string/node19.html#SECTION00190 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "types.h" 12 | 13 | void memcpy(void *dest, const void *src, u32 size); 14 | void memmove(void *dest, const void *src, u32 size); 15 | void memset(void *dest, int filler, u32 size); 16 | void memset32(void *dest, u32 filler, u32 size); 17 | int memcmp(const void *buf1, const void *buf2, u32 size); 18 | u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize); -------------------------------------------------------------------------------- /source/patches.c: -------------------------------------------------------------------------------- 1 | /* 2 | * patches.c 3 | * by Reisyukaku / Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | */ 6 | 7 | #include "patches.h" 8 | #include "memory.h" 9 | 10 | /************************************************** 11 | * Patches 12 | **************************************************/ 13 | 14 | const u32 mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603}; 15 | 16 | const u16 nandRedir[2] = {0x4C00, 0x47A0}; 17 | 18 | const u16 writeBlock[2] = {0x2000, 0x46C0}; 19 | 20 | /************************************************** 21 | * Functions 22 | **************************************************/ 23 | 24 | u8 *getProc9(u8 *pos, u32 size){ 25 | return memsearch(pos, "ess9", size, 4); 26 | } 27 | 28 | void *getReboot(u8 *pos, u32 size){ 29 | //Look for FIRM reboot code 30 | const u8 pattern[] = {0xDE, 0x1F, 0x8D, 0xE2}; 31 | 32 | return memsearch(pos, pattern, size, 4) - 0x10; 33 | } 34 | 35 | u32 getfOpen(u8 *proc9Offset, void *rebootOffset){ 36 | //Offset Process9 code gets loaded to in memory (defined in ExHeader) 37 | u32 p9MemAddr = *(u32 *)(proc9Offset + 0xC); 38 | //Process9 code offset (start of NCCH + ExeFS offset + ExeFS header size) 39 | u32 p9CodeOff = (u32)(proc9Offset - 0x204) + (*(u32 *)(proc9Offset - 0x64) * 0x200) + 0x200; 40 | 41 | //Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1 42 | return (u32)rebootOffset + 9 - (-((*(u32 *)rebootOffset & 0x00FFFFFF) << 2) & 0xFFFFF) - p9CodeOff + p9MemAddr; 43 | } 44 | 45 | u16 *getFirmWrite(u8 *pos, u32 size){ 46 | //Look for FIRM writing code 47 | u8 *const off = memsearch(pos, "exe:", size, 4); 48 | const u8 pattern[] = {0x00, 0x28, 0x01, 0xDA}; 49 | 50 | return (u16 *)memsearch(off - 0x100, pattern, 0x100, 4); 51 | } 52 | 53 | u32 getLoader(u8 *pos, u32 *loaderSize){ 54 | u8 *off = pos; 55 | u32 size; 56 | 57 | while(1) 58 | { 59 | size = *(u32 *)(off + 0x104) * 0x200; 60 | if(*(u32 *)(off + 0x200) == 0x64616F6C) break; 61 | off += size; 62 | } 63 | 64 | *loaderSize = size; 65 | 66 | return (u32)(off - pos); 67 | } -------------------------------------------------------------------------------- /source/patches.h: -------------------------------------------------------------------------------- 1 | /* 2 | * patches.h 3 | * by Reisyukaku / Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "types.h" 10 | 11 | /************************************************** 12 | * Patches 13 | **************************************************/ 14 | const u32 mpuPatch[3]; 15 | const u16 nandRedir[2]; 16 | const u16 sigPatch[2]; 17 | const u16 writeBlock[2]; 18 | 19 | /************************************************** 20 | * Functions 21 | **************************************************/ 22 | u8 *getProc9(u8 *pos, u32 size); 23 | void getSigChecks(u8 *pos, u32 size, u32 *off, u32 *off2); 24 | void *getReboot(u8 *pos, u32 size); 25 | u32 getfOpen(u8 *proc9Offset, void *rebootOffset); 26 | u16 *getFirmWrite(u8 *pos, u32 size); 27 | u32 getLoader(u8 *pos, u32 *loaderSize); -------------------------------------------------------------------------------- /source/screeninit.c: -------------------------------------------------------------------------------- 1 | /* 2 | * screeninit.c 3 | * by Aurora Wright 4 | * Screen init code by dark_samus, bil1s, Normmatt, delebile and others. 5 | * Screen deinit code by tiniVi. 6 | * 7 | * Copyright (c) 2016 All Rights Reserved 8 | */ 9 | 10 | #include "screeninit.h" 11 | #include "draw.h" 12 | #include "i2c.h" 13 | 14 | static vu32 *const arm11 = (u32 *)0x1FFFFFF8; 15 | 16 | void deinitScreens(void){ 17 | void __attribute__((naked)) ARM11(void){ 18 | //Disable interrupts 19 | __asm(".word 0xF10C01C0"); 20 | 21 | //Clear ARM11 entry offset 22 | *arm11 = 0; 23 | 24 | //Shutdown LCDs 25 | *(vu32 *)0x10202A44 = 0; 26 | *(vu32 *)0x10202244 = 0; 27 | *(vu32 *)0x10202014 = 0; 28 | 29 | //Wait for the entry to be set 30 | while(!*arm11); 31 | //Jump to it 32 | ((void (*)())*arm11)(); 33 | } 34 | 35 | if(PDN_GPU_CNT != 1){ 36 | *arm11 = (u32)ARM11; 37 | while(*arm11); 38 | } 39 | } 40 | 41 | void initScreens(void){ 42 | void __attribute__((naked)) ARM11(void){ 43 | //Disable interrupts 44 | __asm(".word 0xF10C01C0"); 45 | 46 | *(vu32 *)0x10141200 = 0x1007F; 47 | *(vu32 *)0x10202014 = 0x00000001; 48 | *(vu32 *)0x1020200C &= 0xFFFEFFFE; 49 | *(vu32 *)0x10202240 = 0x45; 50 | *(vu32 *)0x10202A40 = 0x45; 51 | *(vu32 *)0x10202244 = 0x1023E; 52 | *(vu32 *)0x10202A44 = 0x1023E; 53 | 54 | // Top screen 55 | *(vu32 *)0x10400400 = 0x000001c2; 56 | *(vu32 *)0x10400404 = 0x000000d1; 57 | *(vu32 *)0x10400408 = 0x000001c1; 58 | *(vu32 *)0x1040040c = 0x000001c1; 59 | *(vu32 *)0x10400410 = 0x00000000; 60 | *(vu32 *)0x10400414 = 0x000000cf; 61 | *(vu32 *)0x10400418 = 0x000000d1; 62 | *(vu32 *)0x1040041c = 0x01c501c1; 63 | *(vu32 *)0x10400420 = 0x00010000; 64 | *(vu32 *)0x10400424 = 0x0000019d; 65 | *(vu32 *)0x10400428 = 0x00000002; 66 | *(vu32 *)0x1040042c = 0x00000192; 67 | *(vu32 *)0x10400430 = 0x00000192; 68 | *(vu32 *)0x10400434 = 0x00000192; 69 | *(vu32 *)0x10400438 = 0x00000001; 70 | *(vu32 *)0x1040043c = 0x00000002; 71 | *(vu32 *)0x10400440 = 0x01960192; 72 | *(vu32 *)0x10400444 = 0x00000000; 73 | *(vu32 *)0x10400448 = 0x00000000; 74 | *(vu32 *)0x1040045C = 0x00f00190; 75 | *(vu32 *)0x10400460 = 0x01c100d1; 76 | *(vu32 *)0x10400464 = 0x01920002; 77 | *(vu32 *)0x10400468 = 0x18300000; 78 | *(vu32 *)0x10400470 = 0x80341; 79 | *(vu32 *)0x10400474 = 0x00010501; 80 | *(vu32 *)0x10400478 = 0; 81 | *(vu32 *)0x10400490 = 0x000002D0; 82 | *(vu32 *)0x1040049C = 0x00000000; 83 | 84 | // Disco register 85 | for(u32 i = 0; i < 256; i++) 86 | *(vu32 *)0x10400484 = 0x10101 * i; 87 | 88 | // Bottom screen 89 | *(vu32 *)0x10400500 = 0x000001c2; 90 | *(vu32 *)0x10400504 = 0x000000d1; 91 | *(vu32 *)0x10400508 = 0x000001c1; 92 | *(vu32 *)0x1040050c = 0x000001c1; 93 | *(vu32 *)0x10400510 = 0x000000cd; 94 | *(vu32 *)0x10400514 = 0x000000cf; 95 | *(vu32 *)0x10400518 = 0x000000d1; 96 | *(vu32 *)0x1040051c = 0x01c501c1; 97 | *(vu32 *)0x10400520 = 0x00010000; 98 | *(vu32 *)0x10400524 = 0x0000019d; 99 | *(vu32 *)0x10400528 = 0x00000052; 100 | *(vu32 *)0x1040052c = 0x00000192; 101 | *(vu32 *)0x10400530 = 0x00000192; 102 | *(vu32 *)0x10400534 = 0x0000004f; 103 | *(vu32 *)0x10400538 = 0x00000050; 104 | *(vu32 *)0x1040053c = 0x00000052; 105 | *(vu32 *)0x10400540 = 0x01980194; 106 | *(vu32 *)0x10400544 = 0x00000000; 107 | *(vu32 *)0x10400548 = 0x00000011; 108 | *(vu32 *)0x1040055C = 0x00f00140; 109 | *(vu32 *)0x10400560 = 0x01c100d1; 110 | *(vu32 *)0x10400564 = 0x01920052; 111 | *(vu32 *)0x10400568 = 0x18300000 + 0x46500; 112 | *(vu32 *)0x10400570 = 0x80301; 113 | *(vu32 *)0x10400574 = 0x00010501; 114 | *(vu32 *)0x10400578 = 0; 115 | *(vu32 *)0x10400590 = 0x000002D0; 116 | *(vu32 *)0x1040059C = 0x00000000; 117 | 118 | // Disco register 119 | for(u32 i = 0; i < 256; i++) 120 | *(vu32 *)0x10400584 = 0x10101 * i; 121 | 122 | // Enable backlight 123 | i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A); 124 | 125 | *(vu32 *)0x10400468 = 0x18300000; 126 | *(vu32 *)0x1040046c = 0x18300000; 127 | *(vu32 *)0x10400494 = 0x18300000; 128 | *(vu32 *)0x10400498 = 0x18300000; 129 | *(vu32 *)0x10400568 = 0x18346500; 130 | *(vu32 *)0x1040056c = 0x18346500; 131 | 132 | //Set CakeBrah framebuffers 133 | *((vu32 *)0x23FFFE00) = 0x18300000; 134 | *((vu32 *)0x23FFFE04) = 0x18300000; 135 | *((vu32 *)0x23FFFE08) = 0x18346500; 136 | 137 | //Clear ARM11 entry offset 138 | *arm11 = 0; 139 | 140 | //Wait for the entry to be set 141 | while(!*arm11); 142 | //Jump to it 143 | ((void (*)())*arm11)(); 144 | } 145 | 146 | if(PDN_GPU_CNT == 1){ 147 | *arm11 = (u32)ARM11; 148 | while(*arm11); 149 | } 150 | 151 | clearScreens(); 152 | } -------------------------------------------------------------------------------- /source/screeninit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * screeninit.h 3 | * by Aurora Wright 4 | * Screen init code by dark_samus, bil1s, Normmatt, delebile and others. 5 | * Screen deinit code by tiniVi. 6 | * 7 | * Copyright (c) 2016 All Rights Reserved 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "types.h" 13 | 14 | #define PDN_GPU_CNT (*(vu8 *)0x10141200) 15 | 16 | void deinitScreens(void); 17 | void initScreens(void); -------------------------------------------------------------------------------- /source/start.s: -------------------------------------------------------------------------------- 1 | .section .text.start 2 | .align 4 3 | .global _start 4 | _start: 5 | @ Change the stack pointer 6 | mov sp, #0x27000000 7 | 8 | @ Give read/write access to all the memory regions 9 | ldr r0, =0x33333333 10 | mcr p15, 0, r0, c5, c0, 2 @ write data access 11 | mcr p15, 0, r0, c5, c0, 3 @ write instruction access 12 | 13 | @ Set MPU permissions and cache settings 14 | ldr r0, =0xFFFF001D @ ffff0000 32k 15 | ldr r1, =0x01FF801D @ 01ff8000 32k 16 | ldr r2, =0x08000027 @ 08000000 1M 17 | ldr r3, =0x10000021 @ 10000000 128k 18 | ldr r4, =0x10100025 @ 10100000 512k 19 | ldr r5, =0x20000035 @ 20000000 128M 20 | ldr r6, =0x1FF00027 @ 1FF00000 1M 21 | ldr r7, =0x1800002D @ 18000000 8M 22 | mcr p15, 0, r0, c6, c0, 0 23 | mcr p15, 0, r1, c6, c1, 0 24 | mcr p15, 0, r2, c6, c2, 0 25 | mcr p15, 0, r3, c6, c3, 0 26 | mcr p15, 0, r4, c6, c4, 0 27 | mcr p15, 0, r5, c6, c5, 0 28 | mcr p15, 0, r6, c6, c6, 0 29 | mcr p15, 0, r7, c6, c7, 0 30 | mov r0, #0x25 31 | mcr p15, 0, r0, c2, c0, 0 @ data cacheable 32 | mcr p15, 0, r0, c2, c0, 1 @ instruction cacheable 33 | mcr p15, 0, r0, c3, c0, 0 @ data bufferable 34 | 35 | @ Enable caches 36 | mrc p15, 0, r0, c1, c0, 0 @ read control register 37 | orr r0, r0, #(1<<12) @ - instruction cache enable 38 | orr r0, r0, #(1<<2) @ - data cache enable 39 | orr r0, r0, #(1<<0) @ - mpu enable 40 | mcr p15, 0, r0, c1, c0, 0 @ write control register 41 | 42 | @ Flush caches 43 | mov r0, #0 44 | mcr p15, 0, r0, c7, c5, 0 @ flush I-cache 45 | mcr p15, 0, r0, c7, c6, 0 @ flush D-cache 46 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 47 | 48 | @ Fix mounting of SDMC 49 | ldr r0, =0x10000020 50 | mov r1, #0x340 51 | str r1, [r0] 52 | 53 | bl main 54 | 55 | .die: 56 | b .die 57 | -------------------------------------------------------------------------------- /source/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * types.h 3 | * by Reisyukaku 4 | * Copyright (c) 2015 All Rights Reserved 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | //Common data types 13 | typedef uint8_t u8; 14 | typedef uint16_t u16; 15 | typedef uint32_t u32; 16 | typedef uint64_t u64; 17 | typedef volatile u8 vu8; 18 | typedef volatile u16 vu16; 19 | typedef volatile u32 vu32; 20 | typedef volatile u64 vu64; -------------------------------------------------------------------------------- /source/utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * utils.c 3 | * by Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | */ 6 | 7 | #include "utils.h" 8 | #include "screeninit.h" 9 | #include "draw.h" 10 | #include "fs.h" 11 | #include "i2c.h" 12 | #include "buttons.h" 13 | 14 | #define COLOR_TITLE 0xFF9900 15 | #define COLOR_WHITE 0xFFFFFF 16 | #define COLOR_RED 0x0000FF 17 | #define COLOR_BLACK 0x000000 18 | 19 | struct option { 20 | int posY; 21 | u32 enabled; 22 | }; 23 | 24 | static u16 waitInput(void){ 25 | u32 pressedKey = 0; 26 | u16 key; 27 | 28 | //Wait for no keys to be pressed 29 | while(HID_PAD); 30 | 31 | do { 32 | //Wait for a key to be pressed 33 | while(!HID_PAD); 34 | key = HID_PAD; 35 | 36 | //Make sure it's pressed 37 | for(u32 i = 0x13000; i; i--){ 38 | if(key != HID_PAD) break; 39 | if(i == 1) pressedKey = 1; 40 | } 41 | } while(!pressedKey); 42 | 43 | return key; 44 | } 45 | 46 | void error(const char *message){ 47 | initScreens(); 48 | 49 | drawString("An error has occurred:", 10, 10, COLOR_RED); 50 | int posY = drawString(message, 10, 30, COLOR_WHITE); 51 | drawString("Press any button to shutdown", 10, posY + 2 * SPACING_Y, COLOR_WHITE); 52 | 53 | waitInput(); 54 | 55 | //Shutdown 56 | i2cWriteRegister(I2C_DEV_MCU, 0x20, 1); 57 | while(1); 58 | } -------------------------------------------------------------------------------- /source/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * utils.h 3 | * by Aurora Wright 4 | * Copyright (c) 2016 All Rights Reserved 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "types.h" 10 | 11 | #define CFG_BOOTENV (*(vu8 *)0x10010000) 12 | 13 | void error(const char *message); --------------------------------------------------------------------------------