Guest User

Untitled

a guest
Jun 24th, 2018
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 32.15 KB | None | 0 0
  1. From 8cc8dac612a432cdb973c69ab9d2af71341ab9fe Mon Sep 17 00:00:00 2001
  2. From: Alex Marshall <SquidMan72@gmail.com>
  3. Date: Mon, 25 May 2009 15:14:12 -0700
  4. Subject: [PATCH 3/3] Added AES encryption, NAND FS (implemented as a new device), and several new access methods to the raw NAND.
  5.  
  6. ---
  7. Makefile | 2 +-
  8. crypto.c | 27 ++++-
  9. crypto.h | 1 +
  10. ipc.c | 4 +
  11. ipc.h | 143 +++++++++++++++----------
  12. nand.c | 161 ++++++++++++++++++++++++++++
  13. nand.h | 14 ++-
  14. nandfs.c | 331 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  15. nandfs.h | 38 +++++++
  16. nandstructs.h | 133 +++++++++++++++++++++++
  17. string.c | 43 ++++++++
  18. string.h | 1 +
  19. 12 files changed, 830 insertions(+), 68 deletions(-)
  20. create mode 100644 nandfs.c
  21. create mode 100644 nandfs.h
  22. create mode 100644 nandstructs.h
  23.  
  24. diff --git a/Makefile b/Makefile
  25. index d35474e..0cd7719 100644
  26. --- a/Makefile
  27. +++ b/Makefile
  28. @@ -13,7 +13,7 @@ TARGET_BIN = armboot.bin
  29. OBJS = start.o main.o ipc.o vsprintf.o string.o gecko.o memory.o memory_asm.o \
  30. utils_asm.o utils.o ff.o diskio.o sdhc.o powerpc_elf.o powerpc.o panic.o \
  31. irq.o irq_asm.o exception.o exception_asm.o seeprom.o crypto.o nand.o \
  32. - boot2.o ldhack.o sdmmc.o
  33. + boot2.o ldhack.o sdmmc.o nandfs.o
  34.  
  35. include common.mk
  36.  
  37. diff --git a/crypto.c b/crypto.c
  38. index ffb517a..ac7cc10 100644
  39. --- a/crypto.c
  40. +++ b/crypto.c
  41. @@ -21,6 +21,7 @@ Copyright (C) 2008, 2009 Sven Peter <svenpeter@gmail.com>
  42.  
  43. #define AES_CMD_RESET 0
  44. #define AES_CMD_DECRYPT 0x9800
  45. +#define AES_CMD_ENCRYPT 0x9000
  46.  
  47. otp_t otp;
  48. seeprom_t seeprom;
  49. @@ -115,31 +116,41 @@ void aes_set_key(u8 *key)
  50. }
  51. }
  52.  
  53. -void aes_decrypt(u8 *src, u8 *dst, u32 blocks, u8 keep_iv)
  54. +void aes_engine(u8 *src, u8 *dst, u32 blocks, u8 keep_iv, u16 cmd)
  55. {
  56. int this_blocks = 0;
  57. while(blocks > 0) {
  58. this_blocks = blocks;
  59. if (this_blocks > 0x80)
  60. this_blocks = 0x80;
  61. -
  62. +
  63. write32(AES_SRC, dma_addr(src));
  64. write32(AES_DEST, dma_addr(dst));
  65. -
  66. +
  67. dc_flushrange(src, blocks * 16);
  68. dc_invalidaterange(dst, blocks * 16);
  69. -
  70. +
  71. ahb_flush_to(AHB_AES);
  72. - aes_command(AES_CMD_DECRYPT, keep_iv, this_blocks);
  73. + aes_command(cmd, keep_iv, this_blocks);
  74. ahb_flush_from(AHB_AES);
  75. ahb_flush_to(AHB_STARLET);
  76. -
  77. +
  78. blocks -= this_blocks;
  79. src += this_blocks<<4;
  80. dst += this_blocks<<4;
  81. keep_iv = 1;
  82. }
  83. +
  84. +}
  85.  
  86. +void aes_decrypt(u8 *src, u8 *dst, u32 blocks, u8 keep_iv)
  87. +{
  88. + aes_engine(src, dst, blocks, keep_iv, AES_CMD_DECRYPT);
  89. +}
  90. +
  91. +void aes_encrypt(u8 *src, u8 *dst, u32 blocks, u8 keep_iv)
  92. +{
  93. + aes_engine(src, dst, blocks, keep_iv, AES_CMD_ENCRYPT);
  94. }
  95.  
  96. void aes_ipc(volatile ipc_request *req)
  97. @@ -158,6 +169,10 @@ void aes_ipc(volatile ipc_request *req)
  98. aes_decrypt((u8 *)req->args[0], (u8 *)req->args[1],
  99. req->args[2], req->args[3]);
  100. break;
  101. + case IPC_AES_ENCRYPT:
  102. + aes_encrypt((u8 *)req->args[0], (u8 *)req->args[1],
  103. + req->args[2], req->args[3]);
  104. + break;
  105. default:
  106. gecko_printf("IPC: unknown SLOW AES request %04x\n",
  107. req->req);
  108. diff --git a/crypto.h b/crypto.h
  109. index 66f0ede..34de424 100644
  110. --- a/crypto.h
  111. +++ b/crypto.h
  112. @@ -75,6 +75,7 @@ void aes_set_iv(u8 *iv);
  113. void aes_empty_iv();
  114. void aes_set_key(u8 *key);
  115. void aes_decrypt(u8 *src, u8 *dst, u32 blocks, u8 keep_iv);
  116. +void aes_encrypt(u8 *src, u8 *dst, u32 blocks, u8 keep_iv);
  117. void aes_ipc(volatile ipc_request *req);
  118.  
  119. #endif
  120. diff --git a/ipc.c b/ipc.c
  121. index 9daad2d..5b6e583 100644
  122. --- a/ipc.c
  123. +++ b/ipc.c
  124. @@ -22,6 +22,7 @@ Copyright (C) 2009 John Kelley <wiidev@kelley.ca>
  125. #include "gecko.h"
  126. #include "ipc.h"
  127. #include "nand.h"
  128. +#include "nandfs.h"
  129. #include "sdhcvar.h"
  130. #include "sdmmc.h"
  131. #include "crypto.h"
  132. @@ -156,6 +157,9 @@ static u32 process_slow(volatile ipc_request *req)
  133. case IPC_DEV_NAND:
  134. nand_ipc(req);
  135. break;
  136. + case IPC_DEV_NANDFS:
  137. + nandfs_ipc(req);
  138. + break;
  139. case IPC_DEV_SDHC:
  140. sdhc_ipc(req);
  141. break;
  142. diff --git a/ipc.h b/ipc.h
  143. index 1071f08..984e452 100644
  144. --- a/ipc.h
  145. +++ b/ipc.h
  146. @@ -31,72 +31,97 @@ Copyright (C) 2009 John Kelley <wiidev@kelley.ca>
  147. Even still, you are encouraged to add in sanity checks and version
  148. checking to prevent strange bugs or even data loss. --bushing */
  149.  
  150. -#define IPC_FAST 0x01
  151. -#define IPC_SLOW 0x00
  152. -
  153. -#define IPC_DEV_SYS 0x00
  154. -#define IPC_DEV_NAND 0x01
  155. -#define IPC_DEV_SDHC 0x02
  156. -#define IPC_DEV_KEYS 0x03
  157. -#define IPC_DEV_AES 0x04
  158. -#define IPC_DEV_BOOT2 0x05
  159. -#define IPC_DEV_PPC 0x06
  160. -#define IPC_DEV_SDMMC 0x07
  161. -
  162. -//#define IPC_DEV_USER0 0x80
  163. -//#define IPC_DEV_USER1 0x81
  164. -
  165. -#define IPC_SYS_PING 0x0000
  166. -#define IPC_SYS_JUMP 0x0001
  167. -#define IPC_SYS_GETVERS 0x0002
  168. -#define IPC_SYS_GETGITS 0x0003
  169. -#define IPC_SYS_WRITE32 0x0100
  170. -#define IPC_SYS_WRITE16 0x0101
  171. -#define IPC_SYS_WRITE8 0x0102
  172. -#define IPC_SYS_READ32 0x0103
  173. -#define IPC_SYS_READ16 0x0104
  174. -#define IPC_SYS_READ8 0x0105
  175. -#define IPC_SYS_SET32 0x0106
  176. -#define IPC_SYS_SET16 0x0107
  177. -#define IPC_SYS_SET8 0x0108
  178. -#define IPC_SYS_CLEAR32 0x0109
  179. -#define IPC_SYS_CLEAR16 0x010a
  180. -#define IPC_SYS_CLEAR8 0x010b
  181. -#define IPC_SYS_MASK32 0x010c
  182. -#define IPC_SYS_MASK16 0x010d
  183. -#define IPC_SYS_MASK8 0x010e
  184. -
  185. -#define IPC_NAND_RESET 0x0000
  186. -#define IPC_NAND_GETID 0x0001
  187. -#define IPC_NAND_READ 0x0002
  188. -#define IPC_NAND_WRITE 0x0003
  189. -#define IPC_NAND_ERASE 0x0004
  190. -#define IPC_NAND_STATUS 0x0005
  191. -//#define IPC_NAND_USER0 0x8000
  192. -//#define IPC_NAND_USER1 0x8001
  193. +#define IPC_FAST 0x01
  194. +#define IPC_SLOW 0x00
  195. +
  196. +#define IPC_DEV_SYS 0x00
  197. +#define IPC_DEV_NAND 0x01
  198. +#define IPC_DEV_SDHC 0x02
  199. +#define IPC_DEV_KEYS 0x03
  200. +#define IPC_DEV_AES 0x04
  201. +#define IPC_DEV_BOOT2 0x05
  202. +#define IPC_DEV_PPC 0x06
  203. +#define IPC_DEV_SDMMC 0x07
  204. +#define IPC_DEV_NANDFS 0x80
  205. +
  206. +//#define IPC_DEV_USER0 0x80
  207. +//#define IPC_DEV_USER1 0x81
  208. +
  209. +#define IPC_SYS_PING 0x0000
  210. +#define IPC_SYS_JUMP 0x0001
  211. +#define IPC_SYS_GETVERS 0x0002
  212. +#define IPC_SYS_GETGITS 0x0003
  213. +#define IPC_SYS_WRITE32 0x0100
  214. +#define IPC_SYS_WRITE16 0x0101
  215. +#define IPC_SYS_WRITE8 0x0102
  216. +#define IPC_SYS_READ32 0x0103
  217. +#define IPC_SYS_READ16 0x0104
  218. +#define IPC_SYS_READ8 0x0105
  219. +#define IPC_SYS_SET32 0x0106
  220. +#define IPC_SYS_SET16 0x0107
  221. +#define IPC_SYS_SET8 0x0108
  222. +#define IPC_SYS_CLEAR32 0x0109
  223. +#define IPC_SYS_CLEAR16 0x010a
  224. +#define IPC_SYS_CLEAR8 0x010b
  225. +#define IPC_SYS_MASK32 0x010c
  226. +#define IPC_SYS_MASK16 0x010d
  227. +#define IPC_SYS_MASK8 0x010e
  228. +
  229. +#define IPC_NAND_RESET 0x0000
  230. +#define IPC_NAND_GETID 0x0001
  231. +#define IPC_NAND_READ 0x0002
  232. +#define IPC_NAND_WRITE 0x0003
  233. +#define IPC_NAND_ERASE 0x0004
  234. +#define IPC_NAND_STATUS 0x0005
  235. +// Read and decrypt a cluster
  236. +#define IPC_NAND_READ_DECRYPT_C 0x8000
  237. +// Read and decrypt a block
  238. +#define IPC_NAND_READ_DECRYPT_B 0x8001
  239. +// Read a cluster
  240. +#define IPC_NAND_READ_CLUSTER 0x8002
  241. +// Read a block
  242. +#define IPC_NAND_READ_BLOCK 0x8003
  243. +// Encrypt and write a cluster
  244. +#define IPC_NAND_WRITE_CRYPT_C 0x8004
  245. +// Encrypt and write a block
  246. +#define IPC_NAND_WRITE_CRYPT_B 0x8005
  247. +// Write a cluster
  248. +#define IPC_NAND_WRITE_CLUSTER 0x8006
  249. +// Write a block
  250. +#define IPC_NAND_WRITE_BLOCK 0x8007
  251. +
  252. +//#define IPC_NAND_USER0 0x8000
  253. +//#define IPC_NAND_USER1 0x8001
  254. // etc.
  255.  
  256. -#define IPC_SDHC_DISCOVER 0x0000
  257. -#define IPC_SDHC_EXIT 0x0001
  258. +#define IPC_NANDFS_MOUNT 0x8000
  259. +#define IPC_NANDFS_OPEN 0x8001
  260. +#define IPC_NANDFS_CLOSE 0x8002
  261. +#define IPC_NANDFS_READ 0x8003
  262. +#define IPC_NANDFS_WRITE 0x8004
  263.  
  264. -#define IPC_SDMMC_ACK 0x0000
  265. -#define IPC_SDMMC_READ 0x0001
  266. -#define IPC_SDMMC_WRITE 0x0002
  267. -#define IPC_SDMMC_STATE 0x0003
  268. -#define IPC_SDMMC_SIZE 0x0004
  269. +#define IPC_SDHC_DISCOVER 0x0000
  270. +#define IPC_SDHC_EXIT 0x0001
  271.  
  272. -#define IPC_KEYS_GETOTP 0x0000
  273. -#define IPC_KEYS_GETEEP 0x0001
  274. +#define IPC_SDMMC_ACK 0x0000
  275. +#define IPC_SDMMC_READ 0x0001
  276. +#define IPC_SDMMC_WRITE 0x0002
  277. +#define IPC_SDMMC_STATE 0x0003
  278. +#define IPC_SDMMC_SIZE 0x0004
  279.  
  280. -#define IPC_AES_RESET 0x0000
  281. -#define IPC_AES_SETIV 0x0001
  282. -#define IPC_AES_SETKEY 0x0002
  283. -#define IPC_AES_DECRYPT 0x0003
  284. +#define IPC_KEYS_GETOTP 0x0000
  285. +#define IPC_KEYS_GETEEP 0x0001
  286.  
  287. -#define IPC_BOOT2_RUN 0x0000
  288. -#define IPC_BOOT2_TMD 0x0001
  289. +#define IPC_AES_RESET 0x0000
  290. +#define IPC_AES_SETIV 0x0001
  291. +#define IPC_AES_SETKEY 0x0002
  292. +#define IPC_AES_DECRYPT 0x0003
  293. +#define IPC_AES_ENCRYPT 0x8000
  294.  
  295. -#define IPC_PPC_BOOT 0x0000
  296. +#define IPC_BOOT2_RUN 0x0000
  297. +#define IPC_BOOT2_TMD 0x0001
  298. +
  299. +#define IPC_PPC_BOOT 0x0000
  300.  
  301. #define IPC_CODE (f,d,r) (((f)<<24)|((d)<<16)|(r))
  302.  
  303. diff --git a/nand.c b/nand.c
  304. index a5f2e8e..5600b81 100644
  305. --- a/nand.c
  306. +++ b/nand.c
  307. @@ -96,9 +96,39 @@ void nand_irq(void)
  308. dc_flushrange((void*)current_request.args[2], PAGE_SPARE_SIZE);
  309. }
  310. break;
  311. + case IPC_NAND_READ_DECRYPT_C:
  312. + case IPC_NAND_READ_CLUSTER:
  313. + err = nand_correct(last_page_read, ipc_data, ipc_ecc);
  314. +
  315. + if (current_request.args[1] != 0xFFFFFFFF) {
  316. + memcpy32((void*)current_request.args[1], ipc_data, CLUSTER_SIZE);
  317. + dc_flushrange((void*)current_request.args[1], CLUSTER_SIZE);
  318. + }
  319. + if (current_request.args[2] != 0xFFFFFFFF) {
  320. + memcpy32((void*)current_request.args[2], ipc_ecc, PAGE_SPARE_SIZE * PAGES_PER_CLUSTER);
  321. + dc_flushrange((void*)current_request.args[2], PAGE_SPARE_SIZE * PAGES_PER_CLUSTER);
  322. + }
  323. + break;
  324. + case IPC_NAND_READ_DECRYPT_B:
  325. + case IPC_NAND_READ_BLOCK:
  326. + err = nand_correct(last_page_read, ipc_data, ipc_ecc);
  327. +
  328. + if (current_request.args[1] != 0xFFFFFFFF) {
  329. + memcpy32((void*)current_request.args[1], ipc_data, BLOCK_SIZE);
  330. + dc_flushrange((void*)current_request.args[1], BLOCK_SIZE);
  331. + }
  332. + if (current_request.args[2] != 0xFFFFFFFF) {
  333. + memcpy32((void*)current_request.args[2], ipc_ecc, PAGE_SPARE_SIZE * PAGES_PER_BLOCK);
  334. + dc_flushrange((void*)current_request.args[2], PAGE_SPARE_SIZE * PAGES_PER_BLOCK);
  335. + }
  336. + break;
  337. case IPC_NAND_ERASE:
  338. // no action needed upon erase completion
  339. break;
  340. + case IPC_NAND_WRITE_CLUSTER:
  341. + case IPC_NAND_WRITE_BLOCK:
  342. + case IPC_NAND_WRITE_CRYPT_B:
  343. + case IPC_NAND_WRITE_CRYPT_C:
  344. case IPC_NAND_WRITE:
  345. // no action needed upon write completion
  346. break;
  347. @@ -195,6 +225,16 @@ void nand_read_page(u32 pageno, void *data, void *ecc) {
  348. nand_send_command(NAND_READ_POST, 0, NAND_FLAGS_IRQ | NAND_FLAGS_WAIT | NAND_FLAGS_RD | NAND_FLAGS_ECC, 0x840);
  349. }
  350.  
  351. +void nand_read_cluster(u32 clusterno, void *data, void *ecc)
  352. +{
  353. + int i;
  354. + for (i = 0; i < PAGES_PER_CLUSTER; i++) {
  355. + nand_read_page((clusterno * PAGES_PER_CLUSTER) + i, ((u8*)data) + (i * PAGE_SIZE), \
  356. + ((u8*)ecc) + (i * ECC_BUFFER_SIZE));
  357. + }
  358. +
  359. +}
  360. +
  361. void nand_wait(void) {
  362. // power-saving IRQ wait
  363. while(!irq_flag) {
  364. @@ -205,6 +245,29 @@ void nand_wait(void) {
  365. }
  366. }
  367.  
  368. +void nand_decrypt_cluster(unsigned int cluster, void *data, void *ecc)
  369. +{
  370. + u8 crypted_buffer[CLUSTER_SIZE];
  371. + u8 iv[16];
  372. +
  373. + nand_read_cluster(cluster, crypted_buffer, ecc);
  374. +
  375. + memset(iv, 0, sizeof iv);
  376. + crypto_read_otp();
  377. + aes_set_key(otp.nand_key);
  378. + aes_set_iv(iv);
  379. + aes_decrypt(crypted_buffer, data, CLUSTER_SIZE / 16, 0);
  380. +}
  381. +
  382. +void nand_decrypt_block(unsigned int block, void *data, void *ecc)
  383. +{
  384. + int i;
  385. + for (i = 0; i < CLUSTERS_PER_BLOCK; i++) {
  386. + nand_decrypt_cluster((block * CLUSTERS_PER_BLOCK) + i, ((u8*)data) + (i * CLUSTER_SIZE), \
  387. + ((u8*)ecc) + (i * ECC_BUFFER_SIZE * CLUSTERS_PER_BLOCK));
  388. + }
  389. +}
  390. +
  391. #ifdef NAND_SUPPORT_WRITE
  392. void nand_write_page(u32 pageno, void *data, void *ecc) {
  393. irq_flag = 0;
  394. @@ -224,6 +287,51 @@ void nand_write_page(u32 pageno, void *data, void *ecc) {
  395. __nand_wait();
  396. nand_send_command(NAND_WRITE_POST, 0, NAND_FLAGS_IRQ | NAND_FLAGS_WAIT, 0);
  397. }
  398. +
  399. +void nand_write_cluster(unsigned int cluster, void *data, void *ecc)
  400. +{
  401. + int i;
  402. + for (i = 0; i < PAGES_PER_CLUSTER; i++) {
  403. + nand_write_page((cluster * PAGES_PER_CLUSTER) + i, \
  404. + ((u8*)data) + (i * PAGE_SIZE), ((u8*)ecc) + (i * PAGE_SPARE_SIZE));
  405. + }
  406. +}
  407. +
  408. +void nand_write_block(unsigned int block, void *data, void *ecc)
  409. +{
  410. + int i;
  411. + for (i = 0; i < CLUSTERS_PER_BLOCK; i++) {
  412. + nand_write_cluster((block * CLUSTERS_PER_BLOCK) + i, \
  413. + ((u8*)data) + (i * CLUSTER_SIZE), \
  414. + ((u8*)ecc) + (i * PAGE_SPARE_SIZE * CLUSTERS_PER_BLOCK));
  415. + }
  416. +}
  417. +
  418. +void nand_write_encrypted_cluster(unsigned int cluster, void *data, void *ecc)
  419. +{
  420. + u8 crypted_buffer[CLUSTER_SIZE];
  421. + u8 iv[16];
  422. +
  423. +
  424. + memset(iv, 0, sizeof iv);
  425. + crypto_read_otp();
  426. + aes_set_key(otp.nand_key);
  427. + aes_set_iv(iv);
  428. + aes_encrypt(data, crypted_buffer, CLUSTER_SIZE / 16, 0);
  429. +
  430. + nand_write_cluster(cluster, crypted_buffer, ecc);
  431. +}
  432. +
  433. +void nand_write_encrypted_block(unsigned int block, void *data, void *ecc)
  434. +{
  435. + int i;
  436. +
  437. + for (i = 0; i < CLUSTERS_PER_BLOCK; i++) {
  438. + nand_write_encrypted_cluster((block * CLUSTERS_PER_BLOCK) + i, \
  439. + ((u8*)data) + (i * CLUSTER_SIZE), \
  440. + ((u8*)ecc) + (i * PAGE_SPARE_SIZE * CLUSTERS_PER_BLOCK));
  441. + }
  442. +}
  443. #endif
  444.  
  445. #ifdef NAND_SUPPORT_ERASE
  446. @@ -321,6 +429,7 @@ void nand_ipc(volatile ipc_request *req)
  447. current_request = *req;
  448. nand_read_page(req->args[0], ipc_data, ipc_ecc);
  449. break;
  450. +
  451. #ifdef NAND_SUPPORT_WRITE
  452. case IPC_NAND_WRITE:
  453. current_request = *req;
  454. @@ -330,6 +439,38 @@ void nand_ipc(volatile ipc_request *req)
  455. memcpy(ipc_ecc, (void*)req->args[2], PAGE_SPARE_SIZE);
  456. nand_write_page(req->args[0], ipc_data, ipc_ecc);
  457. break;
  458. + case IPC_NAND_WRITE_CLUSTER:
  459. + current_request = *req;
  460. + dc_invalidaterange((void*)req->args[1], CLUSTER_SIZE);
  461. + dc_invalidaterange((void*)req->args[2], PAGE_SPARE_SIZE * PAGES_PER_CLUSTER);
  462. + memcpy(ipc_data, (void*)req->args[1], CLUSTER_SIZE);
  463. + memcpy(ipc_ecc, (void*)req->args[2], PAGE_SPARE_SIZE * PAGES_PER_CLUSTER);
  464. + nand_write_cluster(req->args[0], ipc_data, ipc_ecc);
  465. + break;
  466. + case IPC_NAND_WRITE_BLOCK:
  467. + current_request = *req;
  468. + dc_invalidaterange((void*)req->args[1], BLOCK_SIZE);
  469. + dc_invalidaterange((void*)req->args[2], PAGE_SPARE_SIZE * PAGES_PER_BLOCK);
  470. + memcpy(ipc_data, (void*)req->args[1], BLOCK_SIZE);
  471. + memcpy(ipc_ecc, (void*)req->args[2], PAGE_SPARE_SIZE * PAGES_PER_BLOCK);
  472. + nand_write_block(req->args[0], ipc_data, ipc_ecc);
  473. + break;
  474. + case IPC_NAND_WRITE_CRYPT_C:
  475. + current_request = *req;
  476. + dc_invalidaterange((void*)req->args[1], CLUSTER_SIZE);
  477. + dc_invalidaterange((void*)req->args[2], PAGE_SPARE_SIZE * PAGES_PER_CLUSTER);
  478. + memcpy(ipc_data, (void*)req->args[1], CLUSTER_SIZE);
  479. + memcpy(ipc_ecc, (void*)req->args[2], PAGE_SPARE_SIZE * PAGES_PER_CLUSTER);
  480. + nand_write_encrypted_cluster(req->args[0], ipc_data, ipc_ecc);
  481. + break;
  482. + case IPC_NAND_WRITE_CRYPT_B:
  483. + current_request = *req;
  484. + dc_invalidaterange((void*)req->args[1], BLOCK_SIZE);
  485. + dc_invalidaterange((void*)req->args[2], PAGE_SPARE_SIZE * PAGES_PER_BLOCK);
  486. + memcpy(ipc_data, (void*)req->args[1], BLOCK_SIZE);
  487. + memcpy(ipc_ecc, (void*)req->args[2], PAGE_SPARE_SIZE * PAGES_PER_BLOCK);
  488. + nand_write_encrypted_block(req->args[0], ipc_data, ipc_ecc);
  489. + break;
  490. #endif
  491. #ifdef NAND_SUPPORT_ERASE
  492. case IPC_NAND_ERASE:
  493. @@ -337,6 +478,26 @@ void nand_ipc(volatile ipc_request *req)
  494. nand_erase_block(req->args[0]);
  495. break;
  496. #endif
  497. + case IPC_NAND_READ_DECRYPT_C:
  498. + current_request = *req;
  499. + nand_decrypt_cluster(req->args[0], ipc_data, ipc_ecc);
  500. + break;
  501. +
  502. + case IPC_NAND_READ_DECRYPT_B:
  503. + current_request = *req;
  504. + nand_decrypt_block(req->args[0], ipc_data, ipc_ecc);
  505. + break;
  506. +
  507. + case IPC_NAND_READ_CLUSTER:
  508. + current_request = *req;
  509. + nand_decrypt_cluster(req->args[0], ipc_data, ipc_ecc);
  510. + break;
  511. +
  512. + case IPC_NAND_READ_BLOCK:
  513. + current_request = *req;
  514. + nand_decrypt_block(req->args[0], ipc_data, ipc_ecc);
  515. + break;
  516. +
  517. default:
  518. gecko_printf("IPC: unknown SLOW NAND request %04x\n",
  519. req->req);
  520. diff --git a/nand.h b/nand.h
  521. index 205e73a..1b72525 100644
  522. --- a/nand.h
  523. +++ b/nand.h
  524. @@ -15,11 +15,15 @@ Copyright (C) 2008, 2009 Sven Peter <svenpeter@gmail.com>
  525. #include "types.h"
  526. #include "ipc.h"
  527.  
  528. +#define PAGES_PER_CLUSTER (8)
  529. +#define CLUSTERS_PER_BLOCK (8)
  530. +#define PAGES_PER_BLOCK (PAGES_PER_CLUSTER * CLUSTERS_PER_BLOCK)
  531. #define PAGE_SIZE 2048
  532. +#define CLUSTER_SIZE (PAGE_SIZE * PAGES_PER_CLUSTER)
  533. +#define BLOCK_SIZE (CLUSTER_SIZE * CLUSTERS_PER_BLOCK)
  534. #define PAGE_SPARE_SIZE 64
  535. #define ECC_BUFFER_SIZE (PAGE_SPARE_SIZE+16)
  536. #define ECC_BUFFER_ALLOC (PAGE_SPARE_SIZE+32)
  537. -#define BLOCK_SIZE 64
  538. #define NAND_MAX_PAGE 0x40000
  539.  
  540. void nand_irq(void);
  541. @@ -33,7 +37,13 @@ void nand_write_page(u32 pageno, void *data, void *ecc);
  542. void nand_erase_block(u32 pageno);
  543. void nand_wait(void);
  544.  
  545. -void nand_read_cluster(u32 clusterno, void *data);
  546. +void nand_read_cluster(u32 clusterno, void *data, void *ecc);
  547. +void nand_decrypt_cluster(unsigned int cluster, void *data, void *ecc);
  548. +void nand_decrypt_block(unsigned int block, void *data, void *ecc);
  549. +void nand_write_cluster(unsigned int cluster, void *data, void *ecc);
  550. +void nand_write_block(unsigned int block, void *data, void *ecc);
  551. +void nand_write_encrypted_cluster(unsigned int cluster, void *data, void *ecc);
  552. +void nand_write_encrypted_block(unsigned int block, void *data, void *ecc);
  553.  
  554. #define NAND_ECC_OK 0
  555. #define NAND_ECC_CORRECTED 1
  556. diff --git a/nandfs.c b/nandfs.c
  557. new file mode 100644
  558. index 0000000..7594a52
  559. --- /dev/null
  560. +++ b/nandfs.c
  561. @@ -0,0 +1,331 @@
  562. +#include "crypto.h"
  563. +#include "utils.h"
  564. +#include "memory.h"
  565. +#include "gecko.h"
  566. +#include "string.h"
  567. +#include "types.h"
  568. +#include "nand.h"
  569. +#include "nandfs.h"
  570. +#include "nandstructs.h"
  571. +#include "crypto.h"
  572. +#include "ipc.h"
  573. +
  574. +#define SFFS_COUNT (16)
  575. +
  576. +#define SFFS_FIRST_BLOCK (4064)
  577. +#define SFFS_FIRST_CLUSTER (SFFS_FIRST_BLOCK * CLUSTERS_PER_BLOCK)
  578. +#define SFFS_FIRST_PAGE (SFFS_FIRST_CLUSTER * PAGES_PER_CLUSTER)
  579. +
  580. +//#define NANDFS_DEBUG 1
  581. +#ifdef NANDFS_DEBUG
  582. +# define dbgprintf(f, arg...) do { gecko_printf("nandfs: " f, ##arg); } while(0)
  583. +#else
  584. +# define dbgprintf(f, arg...)
  585. +#endif
  586. +
  587. +#define NANDFS_ERROR_NOMOUNT -1
  588. +#define NANDFS_ERROR_NOENT -2
  589. +#define NANDFS_ERROR_NOIMPLEMENT -3
  590. +#define NANDFS_ERROR_TOOBIG -4
  591. +
  592. +struct nandfs *_nandfs;
  593. +struct nandfs _nandfs_x;
  594. +u8* _nand_key;
  595. +
  596. +static ipc_request current_request;
  597. +
  598. +static u8 ipc_input1 [4096] MEM2_BSS ALIGNED(32);
  599. +static u8 ipc_output1[4096] MEM2_BSS ALIGNED(32);
  600. +
  601. +static u8 devnullbuf[ECC_BUFFER_SIZE * PAGES_PER_CLUSTER] MEM2_BSS ALIGNED(32);
  602. +
  603. +static s16 nandfs_find_super()
  604. +{
  605. + u32 newest = 0;
  606. + s16 superclstr = 0, cluster;
  607. + struct sffs_header *sffs_head;
  608. + static u8 buffer[BYTES_PER_CLUSTER] MEM2_BSS ALIGNED(32);
  609. +
  610. + for (cluster = SFFS_START_CLUSTER; cluster < SFFS_END_CLUSTER; cluster++){
  611. + nand_read_cluster(cluster, buffer, devnullbuf);
  612. +
  613. + sffs_head = (struct sffs_header *)buffer;
  614. + if(memcmp(&sffs_head->fourcc, SFFS_FOURCC, sizeof
  615. + SFFS_FOURCC) == 0) {
  616. + u32 version = sffs_head->generation;
  617. + if (superclstr == 0 || version > newest) {
  618. + superclstr = cluster;
  619. + newest = version;
  620. + }
  621. + }
  622. + }
  623. + return superclstr;
  624. +}
  625. +
  626. +int nandfs_read(void *buffer, size_t size, struct nandfile *fp)
  627. +{
  628. + static u8 tmpbuf[BYTES_PER_CLUSTER] MEM2_BSS ALIGNED(32);
  629. + u16 cluster = fp->entry.first_cluster;
  630. + u32 this_size, size_left = size;
  631. + u32 amount_read = 0;
  632. +
  633. + if(!fp->enabled) {
  634. + gecko_printf("file not opened!\n");
  635. + return NANDFS_ERROR_NOENT;
  636. + }
  637. +
  638. + if((size_t)fp->entry.size < size) {
  639. + gecko_printf("attempted to read too much from file.\n");
  640. + return NANDFS_ERROR_TOOBIG;
  641. + }
  642. +
  643. + while (size_left) {
  644. + this_size = size_left > BYTES_PER_CLUSTER ? BYTES_PER_CLUSTER : size_left;
  645. +
  646. + nand_decrypt_cluster(cluster, tmpbuf, devnullbuf);
  647. +
  648. + memcpy((u8*)(buffer+amount_read), tmpbuf, this_size);
  649. +
  650. + size_left -= this_size;
  651. + amount_read += this_size;
  652. + cluster = fp->fs->sffs->cluster_map[cluster];
  653. + }
  654. + return amount_read;
  655. +}
  656. +
  657. +int nandfs_write(void *buffer, size_t size, struct nandfile *fp)
  658. +{
  659. + static u8 tmpbuf[BYTES_PER_CLUSTER] MEM2_BSS ALIGNED(32);
  660. + u16 cluster = fp->entry.first_cluster;
  661. + u32 this_size, size_left=size;
  662. + u32 amount_wrote = 0;
  663. +
  664. + gecko_printf("this function is not currently at a state where it should be used. Sorry.\n");
  665. + return NANDFS_ERROR_NOIMPLEMENT;
  666. +
  667. + if(!fp->enabled) {
  668. + gecko_printf("file not opened!\n");
  669. + return NANDFS_ERROR_NOENT;
  670. + }
  671. +
  672. + if((size_t)fp->entry.size < size) {
  673. + gecko_printf("attempted to write too much to file.\nWriting more to a file than already exists currently is not supported.\n");
  674. + return NANDFS_ERROR_TOOBIG;
  675. + }
  676. +
  677. + while (size_left) {
  678. + this_size = size_left > BYTES_PER_CLUSTER ? BYTES_PER_CLUSTER : size_left;
  679. +
  680. + memcpy(tmpbuf, (u8*)buffer, this_size);
  681. + if (this_size != BYTES_PER_CLUSTER)
  682. + memset(tmpbuf+this_size, 0, BYTES_PER_CLUSTER-this_size);
  683. + // We need to get the ECC generation stuff in here.
  684. +// nand_write_encrypted_cluster(cluster, tmpbuf);
  685. +
  686. + size_left -= this_size;
  687. + amount_wrote += this_size;
  688. + cluster = fp->fs->sffs->cluster_map[cluster];
  689. + }
  690. + return amount_wrote;
  691. +}
  692. +
  693. +static int nandfs_get_fs_entry(struct nandfs *nandfs, size_t dir_levels, char *directories, struct fs_entry *entry)
  694. +{
  695. + if (!nandfs->enabled) {
  696. + gecko_printf("fs not mounted!\n");
  697. + return -1;
  698. + }
  699. +
  700. + struct fs_entry _current_dir, *current_dir = &_current_dir;
  701. + memcpy(current_dir, &nandfs->sffs->entries[0],
  702. + sizeof(struct fs_entry));
  703. +
  704. + while(dir_levels > 0) {
  705. + gecko_printf("looking for \"%s\"\n", directories);
  706. + for(;;) {
  707. + current_dir->first_child = current_dir->first_child;
  708. + current_dir->sibling = current_dir->sibling;
  709. + current_dir->size = current_dir->size;
  710. + current_dir->user_id = current_dir->user_id;
  711. + current_dir->group_id = current_dir->group_id;
  712. + current_dir->unknown = current_dir->unknown;
  713. +
  714. + gecko_printf("checking (sibling = %08x): %s\n", current_dir->sibling, current_dir->name);
  715. + if(dir_levels > 1 &&
  716. + strncmp((const char*)current_dir->name, directories,
  717. + MAX_FS_NAME_LEN) == 0 &&
  718. + current_dir->type == TYPE_DIRECTORY &&
  719. + current_dir->first_child != (s16)0xffff) {
  720. + gecko_printf("found dir; first_child = %08x\n",
  721. + current_dir->first_child);
  722. + memcpy(current_dir, &nandfs->sffs->entries[current_dir->first_child],
  723. + sizeof(struct fs_entry));
  724. + directories += MAX_FS_NAME_LEN;
  725. + dir_levels--;
  726. + break;
  727. + }
  728. + else if(dir_levels == 1 &&
  729. + strncmp((const char*)current_dir->name,
  730. + directories,
  731. + MAX_FS_NAME_LEN) == 0 &&
  732. + current_dir->type == TYPE_FILE) {
  733. + gecko_printf("FOUND\n");
  734. + memcpy(entry, current_dir, sizeof(struct fs_entry));
  735. + return 0;
  736. + }else if(current_dir->sibling != 0xffff) {
  737. + gecko_printf("going to next sibling %08x\n",
  738. + current_dir->sibling);
  739. + memcpy(current_dir, &nandfs->sffs->entries[current_dir->sibling],
  740. + sizeof(struct fs_entry));
  741. + }else{
  742. + gecko_printf("no more siblings :/\n");
  743. + return NANDFS_ERROR_NOENT;
  744. + }
  745. + }
  746. + }
  747. +
  748. + return NANDFS_ERROR_NOENT;
  749. +}
  750. +
  751. +s8 nandfs_open(const char *path, struct nandfile *fp)
  752. +{
  753. + int dir_depth = 0;
  754. + int ret;
  755. + char *pch;
  756. + static char path_new[256] MEM2_BSS ALIGNED(32);
  757. +
  758. + if (!_nandfs->enabled) {
  759. + gecko_printf("fs not mounted!\n");
  760. + return NANDFS_ERROR_NOMOUNT;
  761. + }
  762. +
  763. + fp->fs = _nandfs;
  764. + static char directories[16 * MAX_FS_NAME_LEN] MEM2_BSS ALIGNED(32);
  765. +
  766. + strlcpy(path_new, path, 256);
  767. + pch = strtok(path_new, "/");
  768. +
  769. + // HAXX
  770. + directories[0] = '/';
  771. + directories[1] = 0;
  772. + dir_depth++;
  773. + while (pch != NULL) {
  774. + strlcpy(&directories[dir_depth * MAX_FS_NAME_LEN], pch, MAX_FS_NAME_LEN);
  775. + dir_depth++;
  776. + pch = strtok(NULL, "/");
  777. + }
  778. +
  779. + ret = nandfs_get_fs_entry(_nandfs, dir_depth, directories, &fp->entry);
  780. + if(ret < 0) {
  781. + return ret;
  782. + }else
  783. + fp->enabled = 1;
  784. +
  785. +/*
  786. + for each cluster i in cluster chain:
  787. + fs_hmac_data(cluster_buf,user_id,name,entry_index,entry->unknown,i++,calc_hmac);
  788. +*/
  789. +
  790. + return 0;
  791. +}
  792. +
  793. +int nandfs_close(struct nandfile *fp)
  794. +{
  795. + if (!fp->enabled) {
  796. + gecko_printf("file not open!\n");
  797. + return NANDFS_ERROR_NOENT;
  798. + }
  799. + return 0;
  800. +}
  801. +
  802. +s8 nandfs_mount()
  803. +{
  804. + int i;
  805. + static u8 buffer[BYTES_PER_CLUSTER] MEM2_BSS ALIGNED(32);
  806. + static u8 sffs_buffer[16 * BYTES_PER_CLUSTER] MEM2_BSS ALIGNED(32);
  807. + _nandfs = &_nandfs_x;
  808. +
  809. + _nandfs->super = nandfs_find_super();
  810. +
  811. + for (i = 0; i < 16; i++) {
  812. + nand_read_cluster(_nandfs->super+i, buffer, devnullbuf);
  813. + memcpy(sffs_buffer + (BYTES_PER_CLUSTER * i), buffer, BYTES_PER_CLUSTER);
  814. + }
  815. + crypto_read_otp();
  816. + _nand_key = otp.nand_key;
  817. + _nandfs->sffs = (struct sffs *)sffs_buffer;
  818. + _nandfs->enabled = 1;
  819. +
  820. + return 0;
  821. +}
  822. +
  823. +void nandfs_initialize(void)
  824. +{
  825. + current_request.code = 0;
  826. +}
  827. +
  828. +void nandfs_ipc(volatile ipc_request *req)
  829. +{
  830. + if (current_request.code != 0) {
  831. + gecko_printf("NANDFS: previous IPC request is not done yet.");
  832. + ipc_post(req->code, req->tag, 1, -1);
  833. + return;
  834. + }
  835. + s8 retval;
  836. + switch (req->req) {
  837. + case IPC_NANDFS_MOUNT:
  838. + current_request = *req;
  839. + nandfs_mount();
  840. + break;
  841. +
  842. + // args[0] (in) == filename
  843. + // args[1] (out) == file pointer
  844. + case IPC_NANDFS_OPEN:
  845. + current_request = *req;
  846. + retval = nandfs_open((char *)req->args[0], (struct nandfile *)ipc_output1);
  847. + if(retval < 0)
  848. + gecko_printf("NANDFS: open error %d.\n", retval);
  849. + else {
  850. + memcpy((void *)req->args[1], ipc_output1, sizeof(struct nandfile));
  851. + dc_flushrange((void *)req->args[1], sizeof(struct nandfile));
  852. + }
  853. + break;
  854. +
  855. + // args[0] (in) == file pointer
  856. + case IPC_NANDFS_CLOSE:
  857. + current_request = *req;
  858. + retval = nandfs_close((struct nandfile *)(req->args[0]));
  859. + if(retval < 0)
  860. + gecko_printf("NANDFS: close error %d.\n", retval);
  861. + break;
  862. +
  863. + // args[0] (in) == filepointer
  864. + // args[1] (in) == size
  865. + // args[2] (out) == buffer
  866. + case IPC_NANDFS_READ:
  867. + current_request = *req;
  868. + retval = nandfs_read(ipc_output1, req->args[1], (struct nandfile *)req->args[0]);
  869. + if(retval < 0)
  870. + gecko_printf("NANDFS: read error %d.\n", retval);
  871. + else {
  872. + memcpy((void *)req->args[2], ipc_output1, req->args[1]);
  873. + dc_flushrange((void *)req->args[2], req->args[1]);
  874. + }
  875. + break;
  876. +
  877. + // args[0] (in) == filepointer
  878. + // args[1] (in) == size
  879. + // args[2] (in) == buffer
  880. + case IPC_NANDFS_WRITE:
  881. + current_request = *req;
  882. + dc_invalidaterange((void*)req->args[2], req->args[1]);
  883. + memcpy(ipc_input1, (void*)req->args[2], req->args[1]);
  884. + nandfs_write(ipc_input1, req->args[1], (struct nandfile *)(req->args[0]));
  885. + break;
  886. +
  887. + default:
  888. + gecko_printf("IPC: unknown SLOW NANDFS request %04x\n",
  889. + req->req);
  890. + }
  891. +}
  892. +
  893. diff --git a/nandfs.h b/nandfs.h
  894. new file mode 100644
  895. index 0000000..9c38504
  896. --- /dev/null
  897. +++ b/nandfs.h
  898. @@ -0,0 +1,38 @@
  899. +#ifndef _NANDFS_H_
  900. +#define _NANDFS_H_
  901. +
  902. +// Functions to access the NAND filesystem
  903. +
  904. +#include "ipc.h"
  905. +#include "types.h"
  906. +#include "nandstructs.h"
  907. +#include "nand.h"
  908. +
  909. +#define SFFS_START_CLUSTER 0x7F00
  910. +#define SFFS_END_CLUSTER 0x7FFF
  911. +
  912. +struct nandfile
  913. +{
  914. + struct nandfs *fs;
  915. + struct fs_entry entry;
  916. + s8 enabled;
  917. +};
  918. +
  919. +struct nandfs
  920. +{
  921. + struct sffs *sffs;
  922. + s16 super;
  923. + s8 enabled;
  924. +};
  925. +
  926. +s8 nandfs_mount();
  927. +s8 nandfs_open(const char *path, struct nandfile *fp);
  928. +int nandfs_read(void *buffer, size_t size, struct nandfile *fp);
  929. +int nandfs_write(void *buffer, size_t size, struct nandfile *fp);
  930. +// int nandfs_seek(struct nandfile *fp, u64 offset, u32 whence);
  931. +int nandfs_close(struct nandfile *fp);
  932. +void nandfs_initialize(void);
  933. +void nandfs_ipc(volatile ipc_request *req);
  934. +
  935. +#endif // _NANDFS_H_
  936. +
  937. diff --git a/nandstructs.h b/nandstructs.h
  938. new file mode 100644
  939. index 0000000..a07a3ef
  940. --- /dev/null
  941. +++ b/nandstructs.h
  942. @@ -0,0 +1,133 @@
  943. +#ifndef _NANDSTRUCTS_H_
  944. +#define _NANDSTRUCTS_H_
  945. +
  946. +
  947. +#include "types.h"
  948. +
  949. +#define SFFS_FOURCC ("SFFS")
  950. +
  951. +#define MAX_CLUSTERS (32768)
  952. +#define MAX_FS_ENTRIES (0x17ff)
  953. +
  954. +#define MAX_FS_NAME_LEN (12)
  955. +
  956. +#define FS_NO_SIBLING (-1)
  957. +
  958. +
  959. +#define BYTES_PER_PAGE (2048)
  960. +#define BYTES_PER_CLUSTER (BYTES_PER_PAGE * PAGES_PER_CLUSTER)
  961. +#define BYTES_PER_BLOCK (BYTES_PER_CLUSTER * CLUSTERS_PER_BLOCK)
  962. +
  963. +#define PAGES_PER_CLUSTER (8)
  964. +#define CLUSTERS_PER_BLOCK (8)
  965. +
  966. +#define PAGES_PER_BLOCK (PAGES_PER_CLUSTER * CLUSTERS_PER_BLOCK)
  967. +#define SPARE_DATA_SIZE (64)
  968. +#define ECC_DATA_SIZE (16)
  969. +#define HMAC_DATA_SIZE (48)
  970. +
  971. +#define BLOCK_COUNT (4096)
  972. +#define CLUSTER_COUNT (BLOCK_COUNT * CLUSTERS_PER_BLOCK)
  973. +#define PAGE_COUNT (CLUSTER_COUNT * PAGES_PER_CLUSTER)
  974. +
  975. +#define NAND_DATA_SIZE (PAGE_COUNT * BYTES_PER_PAGE)
  976. +#define NAND_SIZE (PAGE_COUNT * (BYTES_PER_PAGE + SPARE_DATA_SIZE))
  977. +
  978. +#define SFFS_COUNT (16)
  979. +
  980. +#define SFFS_FIRST_BLOCK (4064)
  981. +#define SFFS_FIRST_CLUSTER (SFFS_FIRST_BLOCK * CLUSTERS_PER_BLOCK)
  982. +#define SFFS_FIRST_PAGE (SFFS_FIRST_CLUSTER * PAGES_PER_CLUSTER)
  983. +#define SFFS_OFFSET (SFFS_FIRST_PAGE * BYTES_PER_PAGE)
  984. +
  985. +
  986. +//Goes from -1 to -5 or -6, so it needs more investigation
  987. +#define CLUSTER_FREE (-2)
  988. +#define CLUSTER_RESERVED (-4)
  989. +#define CLUSTER_CHAIN_LAST (-5)
  990. +
  991. +
  992. +#define TYPE_FREE (0)
  993. +#define TYPE_FILE (1)
  994. +#define TYPE_DIRECTORY (2)
  995. +
  996. +#ifdef _MSC_VER
  997. +#pragma pack(push, 1)
  998. +#endif //_MSC_VER
  999. +
  1000. +/*
  1001. +"attributes" apears to be unused
  1002. +The sole purpose of "unknown" is possibly padding up to 32/20h size
  1003. +
  1004. +"first_child" is used in directiory entries
  1005. +"first_cluster" is used in file entries
  1006. +*/
  1007. +
  1008. +struct fs_entry {
  1009. + s8 name[MAX_FS_NAME_LEN]; //00
  1010. + union {
  1011. + u8 permissions; //0C
  1012. + struct {
  1013. + u8 type : 2; //0C
  1014. + u8 other_perm : 2; //0C
  1015. + u8 group_perm : 2; //0C
  1016. + u8 user_perm : 2; //0C
  1017. + };
  1018. + };
  1019. + u8 attributes; //0D
  1020. + union {
  1021. + s16 first_child; //0E
  1022. + s16 first_cluster; //0E
  1023. + };
  1024. + s16 sibling; //10
  1025. + u32 size; //12
  1026. + u32 user_id; //16
  1027. + u16 group_id; //1A
  1028. + u32 unknown; //1C
  1029. +#ifdef _MSC_VER
  1030. +};
  1031. +#elif __GNUC__ //_MSC_VER
  1032. +} __attribute__((packed));
  1033. +#endif //__GNUC__
  1034. +
  1035. +
  1036. +/*
  1037. +The highest generation out of the 16 stored SFFS blocks is the newest.
  1038. +Upon each filesystem modification, the generation number is incremented
  1039. +and the SFFS block is copied to the next slot (round-robin), for purposes
  1040. +of data integrity and wear-levelling. The generation number is then
  1041. +stored in the Hollywood SEEPROM, but this may or may not actually get used.
  1042. +*/
  1043. +
  1044. +struct sffs_header {
  1045. + u32 fourcc;
  1046. + u32 generation;
  1047. + u32 whatever;
  1048. +#ifdef _MSC_VER
  1049. +};
  1050. +#elif __GNUC__ //_MSC_VER
  1051. +} __attribute__((packed));
  1052. +#endif //__GNUC__
  1053. +
  1054. +struct sffs {
  1055. + struct sffs_header header;
  1056. +
  1057. + // this either is s16 or MAX_CLUSTERS/2
  1058. + s16 cluster_map[MAX_CLUSTERS];
  1059. + union {
  1060. + struct fs_entry entries[MAX_FS_ENTRIES];
  1061. + u8 entries_size[0x2FFF4];
  1062. + };
  1063. +#ifdef _MSC_VER
  1064. +};
  1065. +#elif __GNUC__ //_MSC_VER
  1066. +} __attribute__((packed));
  1067. +#endif //__GNUC__
  1068. +
  1069. +
  1070. +#ifdef _MSC_VER
  1071. +#pragma pack(pop)
  1072. +#endif //_MSC_VER
  1073. +
  1074. +#endif //_NANDSTRUCTS_H_
  1075. +
  1076. diff --git a/string.c b/string.c
  1077. index 5b867b0..eed8de9 100644
  1078. --- a/string.c
  1079. +++ b/string.c
  1080. @@ -155,3 +155,46 @@ size_t strcspn(const char *s1, const char *s2)
  1081. return len;
  1082. }
  1083.  
  1084. +// Thanks ReactOS!
  1085. +char* strtok(char *s, const char *delim)
  1086. +{
  1087. + const char *spanp;
  1088. + int c, sc;
  1089. + int brk = 0;
  1090. + char *tok;
  1091. + static char *last;
  1092. +
  1093. + if (s == NULL && (s = last) == NULL)
  1094. + return (NULL);
  1095. +
  1096. + while(!brk) {
  1097. + brk = 1;
  1098. + c = *s++;
  1099. + for (spanp = delim; (sc = *spanp++) != 0;) {
  1100. + if (c == sc)
  1101. + brk = 0;
  1102. + }
  1103. + }
  1104. +
  1105. + if (c == 0) {
  1106. + last = NULL;
  1107. + return (NULL);
  1108. + }
  1109. + tok = s - 1;
  1110. +
  1111. + for (;;) {
  1112. + c = *s++;
  1113. + spanp = delim;
  1114. + do {
  1115. + if ((sc = *spanp++) == c) {
  1116. + if (c == 0)
  1117. + s = NULL;
  1118. + else
  1119. + s[-1] = 0;
  1120. + last = s;
  1121. + return (tok);
  1122. + }
  1123. + } while (sc != 0);
  1124. + }
  1125. + /* NOTREACHED */
  1126. +}
  1127. diff --git a/string.h b/string.h
  1128. index da87683..106034e 100644
  1129. --- a/string.h
  1130. +++ b/string.h
  1131. @@ -24,6 +24,7 @@ size_t strlcat(char *, const char *, size_t);
  1132. char *strchr(const char *, int);
  1133. size_t strspn(const char *, const char *);
  1134. size_t strcspn(const char *, const char *);
  1135. +char* strtok(char *, const char *);
  1136.  
  1137. #endif
  1138.  
  1139. --
  1140. 1.6.1
Add Comment
Please, Sign In to add comment