1 /*---------------------------------------------------------------------------*
2 Project: Sample demo program for NAND library
3 File: check.c
4 Programmer: HIRATSU Daisuke
5
6 Copyright (C) 2006 Nintendo. All rights reserved.
7
8 These coded instructions, statements, and computer programs contain
9 proprietary information of Nintendo of America Inc. and/or Nintendo
10 Company Ltd., and are protected by Federal copyright law. They may
11 not be disclosed to third parties or copied or duplicated in any form,
12 in whole or in part, without the prior written consent of Nintendo.
13
14 $Log: check.c,v $
15 Revision 1.4 2006/12/20 02:53:17 hiratsu
16 Refactoring. Added comments.
17
18 Revision 1.3 2006/12/14 09:00:52 hiratsu
19 Almost completely revised.
20
21 Revision 1.2 2006/09/06 09:42:48 hiratsu
22 Fixed wrong message.
23
24 Revision 1.1 2006/09/05 12:49:28 hiratsu
25 Sample demo program for NANDCheck().
26
27 *---------------------------------------------------------------------------*/
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <revolution.h>
32
33 #include "util.h"
34
35 #define PERM (NAND_PERM_OWNER_READ | NAND_PERM_OWNER_WRITE) /* Owner can read/write */
36 #define ATTR 0x00 /* No attributes. */
37 #define BUF_SIZE (128*1024) /* 128KB */
38
39 /* Please note 1 FS block is 16 KB. */
40 #define FILE_A_SIZE ( 1*1024) /* 1KB occupies 1 FS block. */
41 #define FILE_B_SIZE ( 130*1024) /* 130KB occupies 9 FS blocks. 130KB = 16KB * 8 + 2KB) */
42 #define FILE_C_SIZE (2*1024*1024) /* 2MB occupies 128 FS blocks. 2MB = 16KB * 128 */
43
44 /* Below files are placed under ~/profile[n] */
45 #define FILE_A_NAME "a.dat"
46 #define FILE_B_NAME "b.dat"
47 #define FILE_C_NAME "c.dat"
48
49 static BOOL init(void);
50 static BOOL generateFile(const char *path, u32 size); /* Creates dummy file. */
51 static BOOL createDir(const char *path);
52 static BOOL generateSaveFile(const char *path);
53 static BOOL verifySaveFile(const char *path); /* Does save data already exist? */
54 static BOOL nandCheck(u32 fsBlock, u32 inode); /* Wrapper function for NANDCheck(). */
55 static BOOL moveToHome(const char *src); /* /tmp/profile[n] -> ~/profile[n] */
56
57 static char s_homePath[NAND_MAX_PATH] = "";
58
59
main(void)60 int main(void)
61 {
62 u16 prev_button = 0x0000;
63
64 init();
65
66 OSReport("This is NANDCheck() demo program.\n");
67 OSReport("Press A to create save data.\n");
68 OSReport("Press START to halt this demo.\n");
69
70 while(1)
71 {
72 PADStatus pad[PAD_MAX_CONTROLLERS];
73 PADRead(pad);
74
75 if((pad[PAD_CHAN0].button & PAD_BUTTON_A) && !(prev_button & PAD_BUTTON_A))
76 {
77 /* Try to create save files and directory. */
78 if(nandCheck(1+9+128, 1+3))
79 {
80 char saveFilePath[NAND_MAX_PATH];
81 char tmpFilePath[NAND_MAX_PATH];
82 int i = 0;
83 for(;; ++i)
84 {
85 sprintf(saveFilePath, "profile%d", i);
86 if(!verifySaveFile(saveFilePath))
87 {
88 break;
89 }
90 }
91
92 OSReport("NANDCheck() passed. Creating files/directories...\n");
93 sprintf(tmpFilePath, "/tmp/%s", saveFilePath);
94 if(!generateSaveFile(tmpFilePath))
95 {
96 OSReport("generateSaveFile() failed.\n");
97 }
98 else{
99 if(!moveToHome(tmpFilePath))
100 {
101 OSReport("moveToHome() failed.\n");
102 }
103 else{
104 OSReport("Done. Save files are created under ~/%s .\n", saveFilePath);
105 }
106 }
107 }
108 }
109
110 if(pad[PAD_CHAN0].button & PAD_BUTTON_START)
111 {
112 OSHalt("START buttun was pressed. Halt.");
113 }
114
115 prev_button = pad[PAD_CHAN0].button;
116 VIWaitForRetrace();
117 }
118
119 return 0; // Never reach here.
120 }
121
122
init(void)123 static BOOL init(void)
124 {
125 s32 ret = NAND_RESULT_FATAL_ERROR;
126
127 VIInit();
128 PADInit();
129
130 ret = NANDGetHomeDir(s_homePath);
131 if(ret!=NAND_RESULT_OK)
132 {
133 OSReport("NANDGetHomeDir() failed. (Result code: %d)\n", ret);
134 return FALSE;
135 }
136
137 return TRUE;
138 }
139
140
generateSaveFile(const char * path)141 static BOOL generateSaveFile(const char *path)
142 {
143 const char *FILENAME[] = {FILE_A_NAME, FILE_B_NAME, FILE_C_NAME};
144 const u32 FILESIZE[] = {FILE_A_SIZE, FILE_B_SIZE, FILE_C_SIZE};
145 char filePath[NAND_MAX_PATH] = "";
146 int i = 0;
147 if(!createDir(path))
148 {
149 OSReport("createDir() failed.\n");
150 return FALSE;
151 }
152
153 for(i = 0; i<3; ++i)
154 {
155 sprintf(filePath, "%s/%s", path, FILENAME[i]);
156 if(!generateFile(filePath, FILESIZE[i]))
157 {
158 OSReport("generateFile() failed.\n");
159 return FALSE;
160 }
161 }
162
163 return TRUE;
164 }
165
166
generateFile(const char * path,u32 size)167 static BOOL generateFile(const char *path, u32 size)
168 {
169 static u8 s_buffer[BUF_SIZE] ATTRIBUTE_ALIGN(32);
170 NANDFileInfo info;
171 u32 i = 0;
172 s32 ret = NAND_RESULT_FATAL_ERROR;
173
174 ret = NANDCreate(path, PERM, ATTR);
175 if(ret != NAND_RESULT_OK)
176 {
177 printErrMsg(ret);
178 OSReport("NANDCreate() failed. Result code: %d\n", ret);
179 return FALSE;
180 }
181
182 ret = NANDOpen(path, &info, NAND_ACCESS_WRITE);
183 if(ret != NAND_RESULT_OK)
184 {
185 printErrMsg(ret);
186 OSReport("NANDOpen() failed. Result code: %d\n", ret);
187 return FALSE;
188 }
189
190 for(i = 0; i<size; i = i+BUF_SIZE)
191 {
192 u32 sz = 0;
193 if(i+BUF_SIZE > size)
194 {
195 sz = size - i;
196 }
197 else
198 {
199 sz = BUF_SIZE;
200 }
201
202 ret = NANDWrite(&info, s_buffer, sz);
203 if(ret != sz)
204 {
205 printErrMsg(ret);
206 OSReport("NANDWrite() failed. Result code: %d\n", ret);
207 NANDClose(&info);
208 return FALSE;
209 }
210 }
211
212 ret = NANDClose(&info);
213 if(ret != NAND_RESULT_OK)
214 {
215 printErrMsg(ret);
216 OSReport("NANDClose() failed. Result code: %d\n", ret);
217 return FALSE;
218 }
219
220 return TRUE;
221 }
222
223
createDir(const char * path)224 static BOOL createDir(const char *path)
225 {
226 s32 ret = NAND_RESULT_FATAL_ERROR;
227
228 ret = NANDCreateDir(path, PERM, ATTR);
229 if(ret != NAND_RESULT_OK)
230 {
231 printErrMsg(ret);
232 OSReport("NANDCreateDir() failed. Result code: %d\n", ret);
233 return FALSE;
234 }
235
236 return TRUE;
237 }
238
239
nandCheck(const u32 fsBlock,const u32 inode)240 static BOOL nandCheck(const u32 fsBlock, const u32 inode)
241 {
242 u32 answer = 0xffffffff;
243 s32 ret = NANDCheck(fsBlock, inode, &answer);
244 if(ret==NAND_RESULT_OK)
245 {
246 if(answer==0)
247 {
248 return TRUE;
249 }
250 else
251 {
252 if(answer & NAND_CHECK_HOME_INSSPACE)
253 {
254 OSReport("Your request will exceed limit of home directory (16MB).\n");
255 }
256 if(answer & NAND_CHECK_HOME_INSINODE)
257 {
258 OSReport("Your request will exceed limit of home directory (32 i-nodes).\n");
259 }
260 if(answer & NAND_CHECK_SYS_INSSPACE)
261 {
262 OSReport("Your request will invade space of system area.\n");
263 }
264 if(answer & NAND_CHECK_SYS_INSINODE)
265 {
266 OSReport("Your request will invade i-nodes of system area.\n");
267 }
268 return FALSE;
269 }
270 }
271 else
272 {
273 OSReport("NANDCheck() failed. Result code: %d\n", ret);
274 return FALSE;
275 }
276 }
277
278
moveToHome(const char * src)279 static BOOL moveToHome(const char *src)
280 {
281 s32 ret = NAND_RESULT_FATAL_ERROR;
282
283 ret = NANDMove(src, s_homePath);
284 if(ret != NAND_RESULT_OK){
285 printErrMsg(ret);
286 OSReport("NANDMove() failed. Result code: %d\n", ret);
287 return FALSE;
288 }
289
290 return TRUE;
291 }
292
293
294 // This function just checks specified directory exists or not.
295 // Of course, more decent checking mechanism is required in your
296 // application program.
verifySaveFile(const char * path)297 static BOOL verifySaveFile(const char *path)
298 {
299 s32 ret = NAND_RESULT_FATAL_ERROR;
300 u8 type = 0x00;
301
302 ret = NANDGetType(path, &type);
303 if(ret == NAND_RESULT_OK && type == NAND_TYPE_DIR)
304 {
305 return TRUE;
306 }
307 else
308 {
309 return FALSE;
310 }
311 }
312