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