makes the forwarder fit for loading the "USB Loader GX" from USB-Device

Strategy to find the boot.dol from "USB Loader GX":

1. looking for "/config/GXGlobal.cfg" first on "SD:/" and then on "USB:/"
2.1. when cfg is found and update_path is set, then searches for "boot.dol"/"boot.elf" in "update_path"
2.2. when cfg isn't found or update_path isn't set, then looking for "boot.dol"/"boot.elf" in "apps/usbloader_gx/" first on "SD:/" and then on "USB:/" 
3. if the Loader is found, then LOAD and RUN it. Otherwise exits the for-warder

Primarily searched on SD-Card. This makes easier to test new versions.
This commit is contained in:
ardi@ist-einmalig.de 2009-06-09 18:26:47 +00:00
parent 11e17e07ab
commit e9423c807e
5 changed files with 300 additions and 75 deletions

View File

@ -8,6 +8,8 @@
#include "cfg.h" #include "cfg.h"
char update_path[150]="";
static char *cfg_name, *cfg_val; static char *cfg_name, *cfg_val;
char* strcopy(char *dest, char *src, int size) char* strcopy(char *dest, char *src, int size)

View File

@ -6,7 +6,7 @@ extern "C"
{ {
#endif #endif
char update_path[150]; extern char update_path[150];
void cfg_set(char *name, char *val); void cfg_set(char *name, char *val);
bool cfg_parsefile(char * fname, void (*set_func)(char*, char*)); bool cfg_parsefile(char * fname, void (*set_func)(char*, char*));

184
source/fatmounter.c Normal file
View File

@ -0,0 +1,184 @@
#include <fat.h>
#include <string.h>
#include <sys/dir.h>
#include <sys/iosupport.h>
#include <ogc/lwp_watchdog.h>
#include <ogc/mutex.h>
#include <ogc/system.h>
#include <ogc/usbstorage.h>
#include <sdcard/wiisd_io.h>
//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:/");
}

19
source/fatmounter.h Normal file
View File

@ -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

View File

@ -31,6 +31,7 @@
#include <malloc.h> #include <malloc.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <ogc/machine/processor.h> #include <ogc/machine/processor.h>
#include "pngu/pngu.h" #include "pngu/pngu.h"
@ -39,6 +40,7 @@
#include "dolloader.h" #include "dolloader.h"
#include "elfloader.h" #include "elfloader.h"
#include "cfg.h" #include "cfg.h"
#include "fatmounter.h"
PNGUPROP imgProp; 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; u32 cookie;
FILE *exeFile = NULL; FILE *exeFile = NULL;
void *exeBuffer = (void *)EXECUTABLE_MEM_ADDR; void *exeBuffer = (void *)EXECUTABLE_MEM_ADDR;
int exeSize = 0; int exeSize = 0;
u32 exeEntryPointAddress = 0; u32 exeEntryPointAddress = 0;
entrypoint exeEntryPoint; 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 */
SDCard_Init();
USBDevice_Init();
char cfgpath[256];
sprintf(cfgpath, "SD:/config/GXGlobal.cfg");
/* int videomod */ if(!cfg_parsefile(cfgpath, &cfg_set)) //no cfg-File on SD: try USB:
InitVideo(); {
sprintf(cfgpath, "USB:/config/GXGlobal.cfg");
/* get imagedata */ cfg_parsefile(cfgpath, &cfg_set);
u8 * imgdata = GetImageData(); }
if(update_path[0] == '\0') // non cfg-File loaded or update_path not set
/* fadein of image */ {
for(int i = 0; i < 255; i = i+10) { /* Open dol File and check exist */
if(i>255) i = 255; strcpy(cfgpath, "SD:/apps/usbloader_gx/boot.dol");
Background_Show(0, 0, 0, imgdata, 0, 1, 1, i); exeFile = fopen (cfgpath ,"rb");
Menu_Render(); if (exeFile==NULL)
} {
/* check devices */ strcpy(cfgpath, "SD:/apps/usbloader_gx/boot.elf");
__io_wiisd.startup(); exeFile = fopen (cfgpath ,"rb");
fatMount("SD", &__io_wiisd, 0, 32, 128); }
if (exeFile==NULL)
char cfgpath[40]; {
sprintf(cfgpath, "SD:/config/GXGlobal.cfg"); strcpy(cfgpath, "USB:/apps/usbloader_gx/boot.dol");
exeFile = fopen (cfgpath ,"rb");
if(!cfg_parsefile(cfgpath, &cfg_set)) { }
/* Open dol File and check exist */ if (exeFile==NULL)
exeFile = fopen ("SD:/apps/usbloader_gx/boot.dol" ,"rb"); {
if (exeFile==NULL) { strcpy(cfgpath, "USB:/apps/usbloader_gx/boot.elf");
fclose(exeFile); exeFile = fopen (cfgpath ,"rb");
exeFile = fopen ("SD:/apps/usbloader_gx/boot.elf" ,"rb"); }
if (exeFile==NULL) { if (exeFile==NULL)
fclose(exeFile); SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); }
} else
} {
} else { sprintf(cfgpath, "%sboot.dol", update_path);
sprintf(cfgpath, "%sboot.dol", update_path); /* Open dol File and check exist */
/* Open dol File and check exist */ exeFile = fopen (cfgpath, "rb");
exeFile = fopen (cfgpath, "rb"); if (exeFile==NULL)
if (exeFile==NULL) { {
fclose(exeFile); sprintf(cfgpath, "%sboot.elf", update_path);
sprintf(cfgpath, "%sboot.elf", update_path); exeFile = fopen (cfgpath,"rb");
exeFile = fopen (cfgpath,"rb"); }
if (exeFile==NULL) { if (exeFile==NULL)
fclose(exeFile); SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
}
}
} }
fseek (exeFile, 0, SEEK_END); fseek (exeFile, 0, SEEK_END);
exeSize = ftell(exeFile); exeSize = ftell(exeFile);
fseek (exeFile, 0, SEEK_SET); fseek (exeFile, 0, SEEK_SET);
if(fread (exeBuffer, 1, exeSize, exeFile) != (unsigned int) exeSize) {
printf("Can't open DOL File...\n");
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);;
}
if(fread (exeBuffer, 1, exeSize, exeFile) != (unsigned int) exeSize)
{
printf("Can't open DOL File...\n");
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
}
fclose (exeFile); fclose (exeFile);
/* load entry point */ /* load entry point */
struct __argv args[10]; 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); int ret = valid_elf_image(exeBuffer);
if (ret == 1) { if (ret == 1)
exeEntryPointAddress = load_elf_image(exeBuffer); exeEntryPointAddress = load_elf_image(exeBuffer);
} else { else
exeEntryPointAddress = load_dol_image(exeBuffer, args); 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();
} }
SDCard_deInit();
/* fadeout of image */ USBDevice_deInit();
for(int i = 255; i > 1; i = i-7) { StopGX();
if(i < 0) i = 0;
Background_Show(0, 0, 0, imgdata, 0, 1, 1, i);
Menu_Render();
}
fatUnmount("SD");
__io_wiisd.shutdown();
StopGX();
if (exeEntryPointAddress == 0) { if (exeEntryPointAddress == 0) {
printf("EntryPointAddress failed...\n"); printf("EntryPointAddress failed...\n");
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);; SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);;
} }
exeEntryPoint = (entrypoint) exeEntryPointAddress; exeEntryPoint = (entrypoint) exeEntryPointAddress;
/* cleaning up and load dol */
/* cleaning up and load dol */
SYS_ResetSystem(SYS_SHUTDOWN, 0, 0); SYS_ResetSystem(SYS_SHUTDOWN, 0, 0);
_CPU_ISR_Disable (cookie); _CPU_ISR_Disable (cookie);
__exception_closeall (); __exception_closeall ();
exeEntryPoint (); exeEntryPoint ();
_CPU_ISR_Restore (cookie); _CPU_ISR_Restore (cookie);
return 0; return 0;
} }