gcmm/source/raw.c

486 lines
12 KiB
C

#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <malloc.h>
#include <sys/dir.h>
#include <dirent.h>
#include <ogcsys.h>
#include "sdsupp.h"
#include "card.h"
#include "mcard.h"
#include "gci.h"
#include "freetype.h"
#include "raw.h"
#define mem_free(x) {free(x);x=NULL;}
u8 *CardBuffer = 0;
s8 read_data = 0;
s8 write_data = 0;
s8 erase_data = 0;
Header cardheader;
extern syssram* __SYS_LockSram();
extern syssramex* __SYS_LockSramEx();
extern u32 __SYS_UnlockSram(u32 write);
extern u32 __SYS_UnlockSramEx(u32 write);
syssramex *sramex;
u8 imageserial[12];
void freecardbuf(){
if(CardBuffer)
{
if(CardBuffer != NULL)
{
mem_free(CardBuffer);
CardBuffer = NULL;
}
}
}
//code from tueidj's Devolution
void getserial(u8 *serial)
{
int i;
uint64_t rand;
// rand() taken from K&R, lol
rand = cardheader.formatTime; // seed
for (i=0; i < 12; i++)
{
rand = (rand * 1103515245 + 12345) >> 16;
cardheader.serial[i] -= rand;
rand = ((uint32_t)rand * 1103515245 + 12345) >> 16;
rand &= 0x7FFF;
serial[i] = cardheader.serial[i];
}
}
void ClearFlashID(s32 chn){
int i;
sramex = __SYS_LockSramEx();
for (i=0; i<12; i++){
sramex->flash_id[chn][i] = 0x00;
}
__SYS_UnlockSramEx(1);
}
void _read_callback(s32 chn,s32 result)
{
read_data =1;
}
void _write_callback(s32 chn,s32 result)
{
write_data =1;
}
void _erase_callback(s32 chn,s32 result)
{
erase_data =1;
}
u64 Card_SerialNo(s32 slot)
{
int err;
u32 SectorSize = 0;
CARD_Init(NULL,NULL);
EXI_ProbeReset();
err = MountCard(slot);
if (err < 0)
{
WaitCardError("SerialNo", err);
return -1; /*** Unable to mount the card ***/
}
usleep(10*1000);
err = CARD_GetSectorSize(slot,&SectorSize);
if(err < 0 )
{
WaitCardError("SerialNo Sectsize", err);
return -1;
}
CardBuffer = (u8*)memalign(32,SectorSize);
if(CardBuffer == NULL)
{
WaitPrompt("SerialNo: Failed to malloc memory.");
return -1;
}
s32 current_block = 0;
int read = 0;
while( 1 )
{
read_data = 0;
if( (err != 0) || current_block >= 1)
break;
err = __card_read(slot,0,SectorSize,CardBuffer+SectorSize*current_block,_read_callback);
if(err == 0)
{
while(read_data == 0)
usleep(1*1000); //sleep untill the read is done
read = read + SectorSize;
current_block++;
}
else
{
mem_free(CardBuffer);
WaitCardError("BakRaw __read", err);
return -1;
}
}
//get the true serial
u64 serial1[4];
int i;
for (i=0;i<4;i++){
memcpy(&serial1[i], CardBuffer+(8*i), sizeof(u64));
}
u64 serialA = serial1[0]^serial1[1]^serial1[2]^serial1[3];
mem_free(CardBuffer);
return serialA;
}
//output is 29 char long
void time2name(char *name)
{
int month, day, year, hour, min, sec;
month = day = year = hour = min = sec = 0;
char monthstr[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec"
};
// Taken from void SecondsToDate(int seconds, int *pYear, int *pMonth, int *pDay)
// Calculates year month and day since jan 1, 1970 from (t) seconds
// Reference: Fliegel, H. F. and van Flandern, T. C. (1968).
// Communications of the ACM, Vol. 11, No. 10 (October, 1968).
// Original code in Fortran
int I, J, K, L, N;
u32 t = time(NULL);
L = t / 86400 + 2509157;
N = 4 * L / 146097;
L = L - (146097 * N + 3) / 4;
I = 4000 * (L + 1) / 1461001;
L = L - 1461 * I / 4 + 31;
J = 80 * L / 2447;
K = L - 2447 * J / 80;
L = J / 11;
J = J + 2 - 12 * L;
I = 100 * (N - 49) + I + L;
year = I;
month = J;
day = K;
sec = t % 60;
t /= 60;
min = t % 60;
t /= 60;
hour = t % 24;
sprintf(name, "%04d_%02d%s_%02d_%02d-%02d-%02d", year, month, monthstr[month-1], day, hour, min, sec);
}
s8 BackupRawImage(s32 slot, s32 *bytes_writen )
{
int err;
char filename[1024];
char msg[1024];
FILE* dumpFd = 0;
u32 SectorSize = 0;
s32 BlockCount = 0;
CARD_Init(NULL,NULL);
EXI_ProbeReset();
err = MountCard(slot);
if (err < 0)
{
WaitCardError("BakRaw", err);
return -1; /*** Unable to mount the card ***/
}
usleep(10*1000);
err = CARD_GetSectorSize(slot,&SectorSize);
if(err < 0 )
{
WaitCardError("BakRaw Sectsize", err);
return -1;
}
err = CARD_GetBlockCount(slot,(u32*)&BlockCount);
if(err < 0 )
{
WaitCardError("BakRaw Blockcount", err);
return -1;
}
CardBuffer = (u8*)memalign(32,SectorSize*BlockCount);
if(CardBuffer == NULL)
{
//printf("failed to malloc memory. fail\n");
WaitPrompt("BackRaw: Failed to malloc memory.");
return -1;
}
s32 current_block = 0;
int read = 0;
s32 writen = 0;
char name[64];
int filenumber = 1;
sprintf (filename, "fat:/%s", MCSAVES);
mkdir(filename, S_IREAD | S_IWRITE);
time2name(name);
sprintf (filename, "fat:/%s/%04db_%s.raw", MCSAVES, BlockCount-5, name);
//not really needed because the filename has seconds in it and the same filename will "never" happen
while (file_exists(filename)){
sprintf (filename, "fat:/%s/%04db_%s_%02d.raw", MCSAVES, BlockCount-5, name, filenumber);
filenumber++;
}
dumpFd = fopen(filename,"wb");
if (dumpFd == NULL)
{
mem_free(CardBuffer);
//printf("can not create file on SD\n");
WaitPrompt("BackRaw: cannot create file on SD.");
return -1;
}
//printf("dumping...\n");
while( 1 )
{
read_data = 0;
//printf("\rReading : %u bytes of %u (block %d)...",read,BlockCount*SectorSize,current_block);
sprintf(msg, "Reading... : Block %d of %d (%u bytes of %u)",current_block,BlockCount,read,BlockCount*SectorSize);
writeStatusBar(msg, "");
if( (err != 0) || current_block >= BlockCount)
break;
err = __card_read(slot,SectorSize*current_block,SectorSize,CardBuffer+SectorSize*current_block,_read_callback);
if(err == 0)
{
while(read_data == 0)
usleep(1*1000); //sleep untill the read is done
read = read + SectorSize;
current_block++;
}
else
{
mem_free(CardBuffer);
//printf("\nerror reading data : %d...\n",err);
fclose(dumpFd);
WaitCardError("BakRaw __read", err);
return -1;
}
}
//printf("\n");
u8* ptr = (u8*)CardBuffer;
for(writen = 0;writen < read;writen=writen+16384)
{
fwrite((u8*)ptr+writen,16384,1,dumpFd);
//printf("\rWriting : %u bytes of %u",writen+16384,read);
sprintf(msg, "Writing : %u bytes of %u",writen+16384,read);
writeStatusBar(msg, "");
}
fclose(dumpFd);
if(bytes_writen != NULL)
*bytes_writen = writen;
mem_free(CardBuffer);
return 1;
}
s8 RestoreRawImage( s32 slot, char *sdfilename, s32 *bytes_writen )
{
FILE *dumpFd = 0;
char filename[1024];
char msg[256];
int err;
u32 SectorSize = 0;
s32 BlockCount = 0;
s32 current_block = 0;
s32 writen = 0;
err = MountCard(slot);
if (err < 0)
{
WaitCardError("RestRaw", err);
return -1; /*** Unable to mount the card ***/
}
usleep(10*1000);
err = CARD_GetSectorSize(slot,&SectorSize);
if(err < 0 )
{
WaitCardError("RestRaw Sectsize", err);
return -1;
}
err = CARD_GetBlockCount(slot,(u32*)&BlockCount);
if(err < 0 )
{
WaitCardError("RestRaw Blockcount", err);
return -1;
}
CardBuffer = (u8*)memalign(32,SectorSize*BlockCount);
if(CardBuffer == NULL)
{
//printf("failed to malloc memory. fail\n");
WaitPrompt("RestRaw: Failed to malloc memory.");
return -1;
}
/*** Make fullpath filename ***/
sprintf (filename, "fat:/%s/%s", MCSAVES, sdfilename);
/*** Open the SD Card file ***/
dumpFd = fopen ( filename , "rb" );
if (dumpFd <= 0)
{
mem_free(CardBuffer);
sprintf(msg, "Couldn't open %s", filename);
WaitPrompt (msg);
return -1;
}
//first read the content of the SD dump into the buffer.
u32 lSize;
fseek (dumpFd , 0 , SEEK_END);
lSize = ftell (dumpFd);
rewind (dumpFd);
if(lSize != BlockCount*SectorSize)
{
//check for mci raw image
if((lSize-64) != BlockCount*SectorSize){
//incorrect dump size D:<
fclose(dumpFd);
mem_free(CardBuffer);
WaitPrompt ("Card and image sizes differ");
return -1;
}
}
//printf("are you -SURE- you want to recover? a faulty backup or even a program\nfailure will corrupt the memory card!\n");
int erase = 1;
//0 = B wass pressed -> ask again
if (!slot){
erase = WaitPromptChoice("Are you -SURE- you want to restore to memory card in slot A?", "Restore", "Cancel");
}else{
erase = WaitPromptChoice("Are you -SURE- you want to restore to memory card in slot B?", "Restore", "Cancel");
}
if (!erase)
{
if (!slot){
erase = WaitPromptChoiceAZ("All contents of memory card in slot A will be overwritten, continue?", "Restore", "Cancel");
}else{
erase = WaitPromptChoiceAZ("All contents of memory card in slot B will be erased, continue?", "Restore", "Cancel");
}
if (!erase)
{
ShowAction ("Reading data...");
if ((lSize-64) == BlockCount*SectorSize) fseek(dumpFd, 64, SEEK_SET);
fread(CardBuffer,BlockCount*0x2000,1,dumpFd);
fclose(dumpFd);
// Test code to see if raw image is correctly read
/*FILE *test = 0;
test = fopen ( "fat:/test.bin" , "wb" );
fwrite (CardBuffer , 1 , BlockCount*0x2000 , test );
fclose (test);
*/
//printf("writing data to memory card...\n");
ShowAction ("Writing data to memory card...");
s32 upblock = 0;
s32 write_len = SectorSize;
//s32 write_len = 0x80;//pagesize of memory card
while( 1 )
{
//printf("\rWriting... : %d of %d (block %d)",writen,BlockCount*SectorSize,current_block);
sprintf(msg, "Writing... : Block %d of %d (%d of %d)",current_block,BlockCount,writen,BlockCount*SectorSize);
ShowAction (msg);
//gprintf("\rWriting... : %d of %d (block %d of %d)",writen,BlockCount*SectorSize,current_block,BlockCount);
write_data = 0;
erase_data = 0;
if( (err != 0) || current_block >= BlockCount || writen == BlockCount*SectorSize)
break;
DCStoreRange(CardBuffer+writen,write_len);
if(writen == 0 || !(writen%SectorSize)){
//s32 __card_sectorerase(s32 chn,u32 sector,cardcallback callback);
err = __card_sectorerase(slot,writen, _erase_callback);
if(err == 0)
{
while(erase_data == 0)
usleep(1*1000); //sleep untill the erase is done which sadly takes alot longer then read
__card_sync(slot);
}else
{
fclose(dumpFd);
mem_free(CardBuffer);
//printf("\nerror writing data(%d) Memory card could be corrupt now!!!\n",err);
sprintf(msg, "error erasing sector(%d) Memory card could be corrupt now!!!",err);
WaitPrompt (msg);
return -1;
}
}
//s32 __card_write(s32 chn,u32 address,u32 block_len,void *buffer,cardcallback callback)
err = __card_write(slot,writen,write_len,CardBuffer+writen,_write_callback);
if(err == 0)
{
while(write_data == 0)
usleep(1*1000); //sleep untill the write is done which sadly takes alot longer then read
__card_sync(slot);
writen = writen + write_len;
upblock=upblock+write_len;
if(upblock == SectorSize)
{
current_block++;
upblock = 0;
}
}
else
{
fclose(dumpFd);
mem_free(CardBuffer);
//printf("\nerror writing data(%d) Memory card could be corrupt now!!!\n",err);
sprintf(msg, "error writing data(%d) Memory card could be corrupt now!!!",err);
WaitPrompt (msg);
return -1;
}
}
//printf("\n");
//gprintf("\n");
if(bytes_writen != NULL)
*bytes_writen = writen;
mem_free(CardBuffer);
return 1;
}
}
mem_free(CardBuffer);
return -1;
}