├── .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);
--------------------------------------------------------------------------------