1 /*---------------------------------------------------------------------------*
2 Project: WiiConnect24
3 File: Download.c
4
5 Copyright 2007 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Log: Download.c,v $
14 Revision 1.6 2008/08/27 02:51:42 adachi_hiroaki
15 Revised comments.
16
17 Revision 1.5 2008/07/30 02:09:41 adachi_hiroaki
18 Added support for NANDCheck.
19
20 Revision 1.4 2008/03/10 00:30:46 adachi_hiroaki
21 Removed notes.
22
23 Revision 1.3 2008/03/10 00:15:42 adachi_hiroaki
24 Added a note about the overhead of VF archives.
25
26 Revision 1.2 2007/11/30 08:49:07 adachi_hiroaki
27 Changed the priority that is set.
28
29 Revision 1.1 2007/06/07 06:06:39 adachi_hiroaki
30 Added a demo of the download feature.
31
32
33 *---------------------------------------------------------------------------*/
34
35 /*---------------------------------------------------------------------------*
36
37 *---------------------------------------------------------------------------*/
38
39 #include <string.h>
40 #include <revolution/os.h>
41 #include <revolution/mem.h>
42 #include <revolution/nand.h>
43 #include <revolution/net.h>
44 #include <revolution/vf.h>
45 #include <revolution/nwc24.h>
46 #include <revolution/nwc24/NWC24Dl.h>
47
48 /*---------------------------------------------------------------------------*
49 Macros
50 *---------------------------------------------------------------------------*/
51
52 #define VERIFY_NWC24ERR(err, expected) ASSERTMSG( err == expected, "unexpected error code: %d", err )
53
54 #define URL "http://nintendo/file.bin"
55
56 #define DRIVE "C"
57 #define SIZE_VF (500*1024)
58
59 /* Force simulation of the initial run (it is best to initialize the task list with nwc24init.elf) */
60 #define SIMULATE_FIRSTRUN
61
62 /* Do not use a signature */
63 #define NOSIGN
64
65 /* Use the public key prepared by the application */
66 //#define USE_MYPUBLICKEY
67
68 BOOL DownloadTaskMain( void );
69
70 /*---------------------------------------------------------------------------*
71 Static Data
72 *---------------------------------------------------------------------------*/
73
74 /* The application's public key is specified here. It is easiest to use makeo */
75 static u8 publicKey[] =
76 {
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
103 };
104
105 /*---------------------------------------------------------------------------*
106 Forward references to local functions
107 *---------------------------------------------------------------------------*/
108 static void SetProperty( NWC24DlTask* task );
109 static NWC24Err UpdateTask( NWC24DlTask* task );
110 static BOOL CheckVf( NWC24DlTask* task, NWC24Err* nwc24Err, VFErr* vfErr );
111 static u32 GetFsBlock(s32 sizeByte);
112
main()113 int main()
114 {
115 OSReport("*******************************************************\n");
116 OSReport(" WiiConnect24 download sample\n");
117 OSReport("*******************************************************\n");
118 VFInit();
119 if (DownloadTaskMain())
120 {
121 OSReport("==== Waiting... ====\n");
122 OSSleepSeconds(60*5);
123
124 (void) DownloadTaskMain();
125 }
126 else
127 {
128 OSReport("NG\n");
129 }
130 OSHalt("Finished.\n");
131 return 0;
132 }
133
DownloadTaskMain(void)134 BOOL DownloadTaskMain( void )
135 {
136 static u32 libWorkMem[NWC24_WORK_MEM_SIZE/sizeof(u32)] ATTRIBUTE_ALIGN(32);
137
138 NWC24Err err = NWC24_OK;
139 NWC24Err err2 = NWC24_OK;
140 VFErr vfErr = VF_ERR_SUCCESS;
141 NWC24DlTask dlTask;
142
143 /*
144 Ease the restrictions on the parameters for the sake of debugging
145 (Incorporating this into products is prohibited)
146 */
147 NWC24EnableDlLaxParameterChecking(TRUE);
148
149 /*
150 Reduce the scheduler interval to make the downloads happen earlier
151 (Incorporating this into products is prohibited)
152 */
153 (void) NWC24SetScheduleSpan(10, 1);
154
155 err = NWC24OpenLib(&libWorkMem);
156 if (err < NWC24_OK)
157 {
158 return FALSE;
159 }
160
161 /* Update the task */
162 err = UpdateTask(&dlTask);
163
164 if (err < NWC24_OK)
165 {
166 goto close;
167 }
168
169 /* Display the task's content to the console */
170 (void) NWC24DumpDlTask(&dlTask);
171
172 /* Check that the content was downloaded */
173 if (CheckVf(&dlTask, &err, &vfErr))
174 {
175 OSReport("a new content was found.\n");
176 }
177
178
179 close:
180 err2 = NWC24CloseLib();
181 return err == NWC24_OK;
182 }
183
UpdateTask(NWC24DlTask * task)184 static NWC24Err UpdateTask( NWC24DlTask* task )
185 {
186 NWC24Err err;
187 u16 myId = 0;
188
189 /*
190 Get the tasks that have already been registered. Register again if it failed
191
192 Note: This function cannot be used when a single application registers two or more tasks
193
194 The application must save each task ID and get the tasks using NWC24GetDlTask()
195
196 */
197 #ifndef SIMULATE_FIRSTRUN
198 err = NWC24GetDlTaskMine( task );
199 #else
200 err = NWC24_ERR_NOT_FOUND;
201 #endif
202 if (err == NWC24_ERR_NOT_FOUND)
203 {
204 /*
205 The task was deleted, either because it had not been registered or had expired, and must be recreated
206
207 */
208
209 /* Create a new binary data receiving-type task */
210 err = NWC24InitDlTask(task, NWC24_DLTYPE_OCTETSTREAM);
211 if (err < NWC24_OK)
212 {
213 return err;
214 }
215 /*
216 If the task was newly created, configure the required items
217 */
218 SetProperty( task );
219 }
220 else if (err < NWC24_OK)
221 {
222 return err;
223 }
224
225 /*
226 Specify the number of remaining downloads
227 Each time a download is done, the number is decreased by one; when it reaches zero, the task is removed
228 For this reason, it is necessary to restore the value each time the application is run in order to prevent the task from being removed
229 */
230 err = NWC24SetDlCount( task, 50 );
231 if (err < NWC24_OK)
232 {
233 return err;
234 }
235
236 /*
237 Register the task data in the task list
238 */
239 err = NWC24AddDlTask(task);
240 if (err < NWC24_OK)
241 {
242 return err;
243 }
244 return NWC24_OK;
245 }
246
247
SetProperty(NWC24DlTask * task)248 static void SetProperty( NWC24DlTask* task )
249 {
250 NWC24Err err;
251 u32 flags = 0;
252 /* Specify the URL */
253 err = NWC24SetDlUrl( task, URL );
254 VERIFY_NWC24ERR( err, NWC24_OK );
255
256 /*
257 Specify the priority. Tasks will be run with priority given to those with lower values
258 The values should be set following the guidelines
259 */
260 err = NWC24SetDlPriority( task, 192 );
261 VERIFY_NWC24ERR( err, NWC24_OK );
262
263 /*
264 Specify the execution interval of the download task
265 Note that task execution will not necessarily be performed in this interval
266 */
267 err = NWC24SetDlInterval( task, 1 );
268 VERIFY_NWC24ERR( err, NWC24_OK );
269
270 /*
271 Specify the filename when storing in VF
272 */
273 err = NWC24SetDlFilename(task, "file.dat");
274 VERIFY_NWC24ERR( err, NWC24_OK );
275
276 #ifdef USE_MYPUBLICKEY
277 flags |= NWC24_DL_FLAG_USE_MYPUBLICKEY;
278 #endif
279
280 /*
281 Specify to download unsigned content without any further processing
282 If parameter checking has been disabled for tasks, this cannot be used for http:// URLs
283 */
284 #ifdef NOSIGN
285 flags |= NWC24_DL_FLAG_RAW_CONTENT;
286 #endif
287
288 err = NWC24SetDlFlags(task, flags);
289 VERIFY_NWC24ERR( err, NWC24_OK );
290
291 }
292
GetFsBlock(s32 sizeByte)293 static u32 GetFsBlock(s32 sizeByte)
294 {
295 ASSERT(sizeByte > 0);
296 if ((sizeByte % NAND_FSBLOCK_SIZE) == 0)
297 {
298 return (u32)(sizeByte / NAND_FSBLOCK_SIZE);
299 }
300 else
301 {
302 return (u32)(sizeByte / NAND_FSBLOCK_SIZE + 1);
303 }
304 }
305
CheckVf(NWC24DlTask * task,NWC24Err * nwc24Err,VFErr * vfErr)306 static BOOL CheckVf( NWC24DlTask* task, NWC24Err* nwc24Err, VFErr* vfErr )
307 {
308 VFFile* vfFile = NULL;
309 BOOL create = TRUE;
310 BOOL result = FALSE;
311 char bufVfName[NAND_MAX_PATH];
312 char bufVfContentName[VF_PATH_BUF_SIZE];
313
314 /* Load the content that was obtained using the VF library */
315
316 /* Get the VFF filename */
317 *nwc24Err = NWC24GetDlVfName(task, bufVfName, sizeof(bufVfName));
318 VERIFY_NWC24ERR( *nwc24Err, NWC24_OK );
319
320 /* Get the filename of the content that was saved within VFF */
321 *nwc24Err = NWC24GetDlFilename(task, bufVfContentName, sizeof(bufVfContentName));
322 VERIFY_NWC24ERR( *nwc24Err, NWC24_OK );
323
324 OSReport("VF archive = %s\n", bufVfName);
325
326 /* Mount */
327 *vfErr = VFMountDriveNANDFlash( DRIVE, bufVfName );
328 if (*vfErr == VF_ERR_SUCCESS)
329 {
330 vfFile = VFOpenFile(bufVfContentName, "r", 0);
331 if ( vfFile )
332 {
333 /* Load the content that was downloaded here */
334 {
335 s32 length = 0;
336 length = VFGetFileSizeByFd( vfFile );
337 OSReport("filename = %s, size = %d\n", bufVfContentName, length);
338
339 /*
340 To determine if received content is new, it is necessary to embed the sequence number, creation date, and other information in said content and then compare this information with what was previously received
341
342
343 */
344 }
345 (void)VFCloseFile( vfFile );
346
347 /* If subsequent files are not required, delete them */
348 *vfErr = VFDeleteFile(bufVfContentName);
349 result = TRUE;
350 create = FALSE;
351 }
352 else
353 {
354 result = FALSE;
355 /* Find out the reason that the file failed to open */
356 *vfErr = VFGetLastError();
357 if (*vfErr == VF_ERR_ENOENT)
358 {
359 /* The file simply does not exist. Recreating VFF is not necessary */
360 create = FALSE;
361 }
362 else
363 {
364 /* There is a chance that the VFF file is corrupted. Recreate it just in case */
365 create = TRUE;
366 }
367 }
368 (void)VFUnmountDrive( DRIVE );
369 }
370 else
371 {
372 result = FALSE;
373 create = TRUE;
374 }
375
376 /*
377 If the VFF file needs to be recreated, do so together with files under the home directory
378
379 */
380 if (create)
381 {
382 s32 checkResult = 0;
383 u32 answer = 0;
384
385 /* Prepare by deleting all files below the home directory */
386 (void)NANDDelete(bufVfName);
387 (void)NWC24ClearDlKeys();
388
389 /*
390 Before creating the files, do a check with NANDCheck()
391 If you will use NWC24SetDlKeys(), the key file must also be checked
392 (The key file uses 1 FS block and consumes 1 inode)
393 */
394 checkResult = NANDCheck(GetFsBlock(SIZE_VF) + 1, 2, &answer);
395 if (checkResult != NAND_RESULT_OK
396 || answer != 0)
397 {
398 /* Follow the NANDCheck processing sequence */
399 return FALSE;
400 }
401
402 /*
403 Prepare a 500 KB VF archive as the destination for storing the download file
404 The FAT region is included in the 500 KB, so the actual downloadable size is approximately 490 KB
405 */
406 *nwc24Err = NWC24CreateDlVf(task, SIZE_VF);
407 if (*nwc24Err < NWC24_OK)
408 {
409 /* If creation failed, handle it in the same way as you would if save data creation failed */
410 return FALSE;
411 }
412
413 *nwc24Err = NWC24SetDlKeys(publicKey, NULL);
414 if (*nwc24Err < NWC24_OK)
415 {
416 /* If configuration failed, handle it in the same way as you would if save data creation failed */
417 return FALSE;
418 }
419 }
420 return result;
421 }
422
423 #if 0
424 static void CheckErrors( NWC24DlTask* task )
425 {
426 NWC24Err err;
427 int globalErr = 0, count = 0;
428
429 /* Get the error that occurred when the task was running */
430 err = NWC24GetDlError( task, &globalErr, &count );
431 VERIFY_NWC24ERR( err, NWC24_OK );
432
433 if (count > 0 && globalErr != 0)
434 {
435 /* Handle errors */
436 OSReport("error %d\n", globalErr);
437
438 /* Clear error information stored in the task */
439 (void) NWC24ClearDlError( task );
440 }
441 }
442 #endif
443
444 /*---------------------------------------------------------------------------*/
445
446 /*---------------------------------------------------------------------------*/
447