diff --git a/source/cfg.c b/source/cfg.c index 1d81b23e..83a26541 100644 --- a/source/cfg.c +++ b/source/cfg.c @@ -8,6 +8,8 @@ #include "cfg.h" +char update_path[150]=""; + static char *cfg_name, *cfg_val; char* strcopy(char *dest, char *src, int size) diff --git a/source/cfg.h b/source/cfg.h index 45b84e03..261a25a5 100644 --- a/source/cfg.h +++ b/source/cfg.h @@ -6,7 +6,7 @@ extern "C" { #endif -char update_path[150]; +extern char update_path[150]; void cfg_set(char *name, char *val); bool cfg_parsefile(char * fname, void (*set_func)(char*, char*)); diff --git a/source/fatmounter.c b/source/fatmounter.c new file mode 100644 index 00000000..4e9b8e09 --- /dev/null +++ b/source/fatmounter.c @@ -0,0 +1,184 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//these are the only stable and speed is good +#define CACHE 32 +#define SECTORS 128 + +enum BPB { + BPB_jmpBoot = 0x00, + BPB_OEMName = 0x03, + // BIOS Parameter Block + BPB_bytesPerSector = 0x0B, + BPB_sectorsPerCluster = 0x0D, + BPB_reservedSectors = 0x0E, + BPB_numFATs = 0x10, + BPB_rootEntries = 0x11, + BPB_numSectorsSmall = 0x13, + BPB_mediaDesc = 0x15, + BPB_sectorsPerFAT = 0x16, + BPB_sectorsPerTrk = 0x18, + BPB_numHeads = 0x1A, + BPB_numHiddenSectors = 0x1C, + BPB_numSectors = 0x20, + // Ext BIOS Parameter Block for FAT16 + BPB_FAT16_driveNumber = 0x24, + BPB_FAT16_reserved1 = 0x25, + BPB_FAT16_extBootSig = 0x26, + BPB_FAT16_volumeID = 0x27, + BPB_FAT16_volumeLabel = 0x2B, + BPB_FAT16_fileSysType = 0x36, + // Bootcode + BPB_FAT16_bootCode = 0x3E, + // FAT32 extended block + BPB_FAT32_sectorsPerFAT32 = 0x24, + BPB_FAT32_extFlags = 0x28, + BPB_FAT32_fsVer = 0x2A, + BPB_FAT32_rootClus = 0x2C, + BPB_FAT32_fsInfo = 0x30, + BPB_FAT32_bkBootSec = 0x32, + // Ext BIOS Parameter Block for FAT32 + BPB_FAT32_driveNumber = 0x40, + BPB_FAT32_reserved1 = 0x41, + BPB_FAT32_extBootSig = 0x42, + BPB_FAT32_volumeID = 0x43, + BPB_FAT32_volumeLabel = 0x47, + BPB_FAT32_fileSysType = 0x52, + // Bootcode + BPB_FAT32_bootCode = 0x5A, + BPB_bootSig_55 = 0x1FE, + BPB_bootSig_AA = 0x1FF +}; + +static const char FAT_SIG[3] = {'F', 'A', 'T'}; + +#define BYTES_PER_READ 512 + +static bool _FAT_partition_isFAT(const DISC_INTERFACE* disc, sec_t startSector) +{ + uint8_t sectorBuffer[BYTES_PER_READ] = {0}; + if (!disc->readSectors(startSector, 1, sectorBuffer)) { + return false; + } + // Make sure it is a valid BPB + if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) { + return false; + } + + // Now verify that this is indeed a FAT partition + if (memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) && + memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + { + return false; + } + + // check again for the last two cases to make sure that we really have a FAT filesystem here + // and won't corrupt any data + if(memcmp(sectorBuffer + BPB_FAT16_fileSysType, "FAT", 3) != 0 && memcmp(sectorBuffer + BPB_FAT32_fileSysType, "FAT32", 5) != 0) + { + return false; + } + return true; +} +static inline uint32_t u8array_to_u32 (const uint8_t* item, int offset) { + return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24)); +} + +sec_t GetFATPartition(const DISC_INTERFACE* disc) +{ + int i; + uint8_t sectorBuffer[BYTES_PER_READ] = {0}; + sec_t startSector = 0; + + if(!disc->startup()) + return 0; + + // Read first sector of disc + if (!disc->readSectors(0, 1, sectorBuffer)) + startSector = 0; + + // Make sure it is a valid MBR or boot sector + if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) + startSector = 0; + + if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + { + // Check if there is a FAT string, which indicates this is a boot sector + startSector = 0; + } + else if (!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + { + // Check for FAT32 + startSector = 0; + } + else + { + // This is an MBR + // Find first valid partition from MBR + // First check for an active partition + for (i=0x1BE; (i < 0x1FE) && (sectorBuffer[i] != 0x80); i+= 0x10); + // If it find an active partition, check for FAT-Partition + if ( i != 0x1FE && !_FAT_partition_isFAT(disc, u8array_to_u32(sectorBuffer, 0x8 + i)) ) + i = 0x1FE; + + // If it didn't find an active partition, search for any valid partition + if (i == 0x1FE) + { + for (i=0x1BE; i < 0x1FE; i+= 0x10) + { + if ( sectorBuffer[i+0x04] != 0x00 && _FAT_partition_isFAT(disc, u8array_to_u32(sectorBuffer, 0x8 + i)) ) + break; + } + } + if (i != 0x1FE) + startSector = u8array_to_u32(sectorBuffer, 0x8 + i);; + } + disc->shutdown(); + return startSector; +} + +int USBDevice_Init() +{ + //closing all open Files write back the cache and then shutdown em! + fatUnmount("USB:/"); + //right now mounts first FAT-partition + if (fatMount("USB", &__io_usbstorage, GetFATPartition(&__io_usbstorage), CACHE, SECTORS)) { + //try first mount with libogc + return 1; + } + return -1; +} + +void USBDevice_deInit() +{ + //closing all open Files write back the cache and then shutdown em! + fatUnmount("USB:/"); +} + +int isSdInserted() +{ + return __io_wiisd.isInserted(); +} + +int SDCard_Init() +{ + //closing all open Files write back the cache and then shutdown em! + fatUnmount("SD:/"); + //right now mounts first FAT-partition + if (fatMount("SD", &__io_wiisd, GetFATPartition(&__io_wiisd), CACHE, SECTORS)) + return 1; + return -1; +} + +void SDCard_deInit() +{ + //closing all open Files write back the cache and then shutdown em! + fatUnmount("SD:/"); +} diff --git a/source/fatmounter.h b/source/fatmounter.h new file mode 100644 index 00000000..e2357020 --- /dev/null +++ b/source/fatmounter.h @@ -0,0 +1,19 @@ +#ifndef _FATMOUNTER_H_ +#define _FATMOUNTER_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +int USBDevice_Init(); +void USBDevice_deInit(); +int isSdInserted(); +int SDCard_Init(); +void SDCard_deInit(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/main.cpp b/source/main.cpp index 3ef263d4..c9c7148d 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "pngu/pngu.h" @@ -39,6 +40,7 @@ #include "dolloader.h" #include "elfloader.h" #include "cfg.h" +#include "fatmounter.h" PNGUPROP imgProp; @@ -78,105 +80,123 @@ void Background_Show(int x, int y, int z, u8 * data, int angle, int scaleX, int } -int main(int argc, char **argv) { - +int main(int argc, char **argv) +{ u32 cookie; FILE *exeFile = NULL; void *exeBuffer = (void *)EXECUTABLE_MEM_ADDR; int exeSize = 0; u32 exeEntryPointAddress = 0; entrypoint exeEntryPoint; - - - /* int videomod */ - InitVideo(); - - /* get imagedata */ - u8 * imgdata = GetImageData(); - - /* fadein of image */ - for(int i = 0; i < 255; i = i+10) { - if(i>255) i = 255; - Background_Show(0, 0, 0, imgdata, 0, 1, 1, i); - Menu_Render(); - } - /* check devices */ - __io_wiisd.startup(); - fatMount("SD", &__io_wiisd, 0, 32, 128); - - char cfgpath[40]; - sprintf(cfgpath, "SD:/config/GXGlobal.cfg"); - - if(!cfg_parsefile(cfgpath, &cfg_set)) { - /* Open dol File and check exist */ - exeFile = fopen ("SD:/apps/usbloader_gx/boot.dol" ,"rb"); - if (exeFile==NULL) { - fclose(exeFile); - exeFile = fopen ("SD:/apps/usbloader_gx/boot.elf" ,"rb"); - if (exeFile==NULL) { - fclose(exeFile); - SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); - } - } - } else { - sprintf(cfgpath, "%sboot.dol", update_path); - /* Open dol File and check exist */ - exeFile = fopen (cfgpath, "rb"); - if (exeFile==NULL) { - fclose(exeFile); - sprintf(cfgpath, "%sboot.elf", update_path); - exeFile = fopen (cfgpath,"rb"); - if (exeFile==NULL) { - fclose(exeFile); - SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); - } - } + /* int videomod */ + InitVideo(); + /* get imagedata */ + u8 * imgdata = GetImageData(); + /* fadein of image */ + for(int i = 0; i < 255; i = i+10) + { + if(i>255) i = 255; + Background_Show(0, 0, 0, imgdata, 0, 1, 1, i); + Menu_Render(); + } + /* check devices */ + SDCard_Init(); + USBDevice_Init(); + char cfgpath[256]; + + sprintf(cfgpath, "SD:/config/GXGlobal.cfg"); + if(!cfg_parsefile(cfgpath, &cfg_set)) //no cfg-File on SD: try USB: + { + sprintf(cfgpath, "USB:/config/GXGlobal.cfg"); + cfg_parsefile(cfgpath, &cfg_set); + } + if(update_path[0] == '\0') // non cfg-File loaded or update_path not set + { + /* Open dol File and check exist */ + strcpy(cfgpath, "SD:/apps/usbloader_gx/boot.dol"); + exeFile = fopen (cfgpath ,"rb"); + if (exeFile==NULL) + { + strcpy(cfgpath, "SD:/apps/usbloader_gx/boot.elf"); + exeFile = fopen (cfgpath ,"rb"); + } + if (exeFile==NULL) + { + strcpy(cfgpath, "USB:/apps/usbloader_gx/boot.dol"); + exeFile = fopen (cfgpath ,"rb"); + } + if (exeFile==NULL) + { + strcpy(cfgpath, "USB:/apps/usbloader_gx/boot.elf"); + exeFile = fopen (cfgpath ,"rb"); + } + if (exeFile==NULL) + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + } + else + { + sprintf(cfgpath, "%sboot.dol", update_path); + /* Open dol File and check exist */ + exeFile = fopen (cfgpath, "rb"); + if (exeFile==NULL) + { + sprintf(cfgpath, "%sboot.elf", update_path); + exeFile = fopen (cfgpath,"rb"); + } + if (exeFile==NULL) + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); } fseek (exeFile, 0, SEEK_END); exeSize = ftell(exeFile); fseek (exeFile, 0, SEEK_SET); - if(fread (exeBuffer, 1, exeSize, exeFile) != (unsigned int) exeSize) { + + if(fread (exeBuffer, 1, exeSize, exeFile) != (unsigned int) exeSize) + { printf("Can't open DOL File...\n"); - SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);; + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); } - fclose (exeFile); - - /* load entry point */ - struct __argv args[10]; + + /* load entry point */ + struct __argv args; + bzero(&args, sizeof(args)); + args.argvMagic = ARGV_MAGIC; + args.length = strlen(cfgpath) + 2; + args.commandLine = (char*)malloc(args.length); + if (!args.commandLine) SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + strcpy(args.commandLine, cfgpath); + args.commandLine[args.length - 1] = '\x00'; + args.argc = 1; + args.argv = &args.commandLine; + args.endARGV = args.argv + 1; int ret = valid_elf_image(exeBuffer); - if (ret == 1) { - exeEntryPointAddress = load_elf_image(exeBuffer); - } else { - exeEntryPointAddress = load_dol_image(exeBuffer, args); + if (ret == 1) + exeEntryPointAddress = load_elf_image(exeBuffer); + else + exeEntryPointAddress = load_dol_image(exeBuffer, &args); + + /* fadeout of image */ + for(int i = 255; i > 1; i = i-7) + { + if(i < 0) i = 0; + Background_Show(0, 0, 0, imgdata, 0, 1, 1, i); + Menu_Render(); } - - /* fadeout of image */ - for(int i = 255; i > 1; i = i-7) { - if(i < 0) i = 0; - Background_Show(0, 0, 0, imgdata, 0, 1, 1, i); - Menu_Render(); - } - - fatUnmount("SD"); - __io_wiisd.shutdown(); - StopGX(); - + SDCard_deInit(); + USBDevice_deInit(); + StopGX(); if (exeEntryPointAddress == 0) { - printf("EntryPointAddress failed...\n"); + printf("EntryPointAddress failed...\n"); SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);; } - exeEntryPoint = (entrypoint) exeEntryPointAddress; - - /* cleaning up and load dol */ + /* cleaning up and load dol */ SYS_ResetSystem(SYS_SHUTDOWN, 0, 0); _CPU_ISR_Disable (cookie); __exception_closeall (); exeEntryPoint (); _CPU_ISR_Restore (cookie); return 0; - }