/*---------------------------------------------------------------------------* Project: Sample demo program for NAND library File: safe.c Programmer: HIRATSU Daisuke Copyright (C) 2006 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Log: safe.c,v $ Revision 1.4 2007/05/07 12:50:37 hiratsu Modified copy buffer size. Revision 1.3 2007/04/23 09:32:13 hiratsu Replaced NANDSafe series API with NANDSimpleSafe series API. Revision 1.2 2006/08/12 12:00:54 hiratsu Refactoring. Revision 1.1 2006/07/24 07:24:03 hiratsu This demo tells differences between normal Open/Close and SafeOpen/SafeClose. *---------------------------------------------------------------------------*/ #include #include #include #include "util.h" #define PERM (NAND_PERM_OWNER_READ | NAND_PERM_OWNER_WRITE) // Owner can read/write #define ATTR 0x00 // No attributes. #define COPYBUF_SIZE NAND_FSBLOCK_SIZE #define FILE_SIZE (1*1024*1024) #define SAFE_FILENAME "safe.dat" #define UNSAFE_FILENAME "unsafe.dat" static void checkFileData(const char *filename); static void initFile(const char *filename); static void checkFileData(const char *filename) { static u8 s_buf[FILE_SIZE] ATTRIBUTE_ALIGN(32); int i = 0; NANDFileInfo info; s32 rc = NANDOpen(filename, &info, NAND_ACCESS_READ); if(rc!=NAND_RESULT_OK) { printErrMsg(rc); } rc = NANDRead(&info, s_buf, FILE_SIZE); if(rc!=FILE_SIZE) { printErrMsg(rc); } rc = NANDClose(&info); if(rc!=NAND_RESULT_OK) { printErrMsg(rc); } OSReport("Checking anterior half and last half of %s ... ", filename); if(memcmp(s_buf, s_buf+FILE_SIZE/2, FILE_SIZE/2)==0) { OSReport("Equivalent.\n"); } else { OSReport("Different!\n"); } } static void initFile(const char *filename) { s32 rc = NANDCreate(filename, PERM, ATTR); if(rc==NAND_RESULT_OK) { OSReport("Created %s.\n", filename); } if(rc==NAND_RESULT_OK || rc==NAND_RESULT_EXISTS) { static u8 s_buf[FILE_SIZE] ATTRIBUTE_ALIGN(32); NANDFileInfo info; rc = NANDOpen(filename, &info, NAND_ACCESS_WRITE); if(rc!=NAND_RESULT_OK) { printErrMsg(rc); } memset(s_buf, 'A', FILE_SIZE); rc = NANDWrite(&info, s_buf, FILE_SIZE); if(rc!=FILE_SIZE) { printErrMsg(rc); } rc = NANDClose(&info); if(rc!=NAND_RESULT_OK) { printErrMsg(rc); } OSReport("Now %s is filled with 'A'.\n", filename); } else { printErrMsg(rc); OSHalt("Unexpected error."); } } int main(void) { PADStatus pad[PAD_MAX_CONTROLLERS]; NANDFileInfo safeInfo, unsafeInfo; static u8 aryB[FILE_SIZE/2] ATTRIBUTE_ALIGN(32); static u8 copyBuf[COPYBUF_SIZE] ATTRIBUTE_ALIGN(32); s32 rc = NAND_RESULT_FATAL_ERROR; u8 type = 0x00; NANDInit(); PADInit(); VIInit(); memset(aryB, 'B', FILE_SIZE/2); rc = NANDGetType(SAFE_FILENAME, &type); if(rc==NAND_RESULT_OK && type==NAND_TYPE_FILE) { checkFileData(SAFE_FILENAME); } rc = NANDGetType(SAFE_FILENAME, &type); if(rc==NAND_RESULT_OK && type==NAND_TYPE_FILE) { checkFileData(UNSAFE_FILENAME); } initFile(SAFE_FILENAME); initFile(UNSAFE_FILENAME); rc = NANDSimpleSafeOpen(SAFE_FILENAME, &safeInfo, NAND_ACCESS_RW, copyBuf, COPYBUF_SIZE); if(rc != NAND_RESULT_OK) { printErrMsg(rc); OSHalt("Unexpected error."); } rc = NANDOpen(UNSAFE_FILENAME, &unsafeInfo, NAND_ACCESS_RW); if(rc != NAND_RESULT_OK) { printErrMsg(rc); OSHalt("Unexpected error."); } // First write rc = NANDWrite(&safeInfo, aryB, FILE_SIZE/2); if(rc != FILE_SIZE/2) { printErrMsg(rc); OSHalt("Unexpected error."); } // First write rc = NANDWrite(&unsafeInfo, aryB, FILE_SIZE/2); if(rc != FILE_SIZE/2) { printErrMsg(rc); OSHalt("Unexpected error."); } OSReport("Wrote 'B' to both anterior half area.\n"); // This operation causes FAT commit. rc = NANDCreate("/tmp/file.tmp", PERM, ATTR); if(rc!=NAND_RESULT_OK) { printErrMsg(rc); OSHalt("create tmp file failed."); } OSReport("Press A button to continue writing data.\n"); OSReport("Press START button to quit writing data.\n"); OSReport("After that, please execute this demo program again.\n"); while(1) { PADRead(pad); if(pad[0].button & PAD_BUTTON_A) { break; } if(pad[0].button & PAD_BUTTON_START) { OSHalt("Program is terminated before closing files."); } VIWaitForRetrace(); } // Second write rc = NANDWrite(&safeInfo, aryB, FILE_SIZE/2); if(rc != FILE_SIZE/2) { printErrMsg(rc); OSHalt("Unexpected error."); } // Second write rc = NANDWrite(&unsafeInfo, aryB, FILE_SIZE/2); if(rc != FILE_SIZE/2) { printErrMsg(rc); OSHalt("Unexpected error."); } OSReport("Wrote 'B' to both last half area.\n"); rc = NANDSimpleSafeClose(&safeInfo); if(rc != NAND_RESULT_OK) { printErrMsg(rc); OSHalt("Unexpected error."); } rc = NANDClose(&unsafeInfo); if(rc != NAND_RESULT_OK) { printErrMsg(rc); OSHalt("Unexpected error."); } OSHalt("Program completed normally."); return 0; }