*Added support for physical sector sizes other than 512 bytes per sector for wbfs partitions only! Others filesystems are currently still hardcoded in their libs. Tested with a 3TB drive with a sector size 4096 one wbfs partition (thanks dexter).

*Added initial source for support for virtual sector size other than 512 bytes per sector on wbfs partitions. This still doesn't work (not tested) and will still cause many code dumps because of some unfinished things. So don't use it yet.

*New ehcmodule for Hermes IOS versions. This gives a big boost in compatibility to usb drives using Hermes cIOSes. Now many drives should work with it. Hermes cIOSes have now probably the best compatibility to usb devices. (big thanks to rodries here) (more to come ;))
This commit is contained in:
dimok321 2011-01-28 21:19:43 +00:00
parent 1c3b3ac966
commit 2764ac6b76
13 changed files with 1075 additions and 1644 deletions

View File

@ -2,8 +2,8 @@
<app version="1">
<name> USB Loader GX</name>
<coder>USB Loader GX Team</coder>
<version>2.0 r1057</version>
<release_date>201101252019</release_date>
<version>2.0 r1058</version>
<release_date>201101261855</release_date>
<no_ios_reload/>
<short_description>Loads games from USB-devices</short_description>
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.

View File

@ -202,19 +202,26 @@ bool PartitionHandle::IsExisting(u64 lba)
int PartitionHandle::FindPartitions()
{
MASTER_BOOT_RECORD mbr;
MASTER_BOOT_RECORD *mbr = (MASTER_BOOT_RECORD *) malloc(MAX_BYTES_PER_SECTOR);
if(!mbr) return -1;
// Read the first sector on the device
if (!interface->readSectors(0, 1, &mbr))
if (!interface->readSectors(0, 1, mbr))
{
free(mbr);
return -1;
}
// If this is the devices master boot record
if (mbr.signature != MBR_SIGNATURE)
if (mbr->signature != MBR_SIGNATURE)
{
free(mbr);
return -1;
}
for (int i = 0; i < 4; i++)
{
PARTITION_RECORD * partition = (PARTITION_RECORD *) &mbr.partitions[i];
PARTITION_RECORD * partition = (PARTITION_RECORD *) &mbr->partitions[i];
if(partition->type == PARTITION_TYPE_GPT)
{
@ -237,34 +244,45 @@ int PartitionHandle::FindPartitions()
}
}
free(mbr);
return 0;
}
void PartitionHandle::CheckEBR(u8 PartNum, sec_t ebr_lba)
{
EXTENDED_BOOT_RECORD ebr;
EXTENDED_BOOT_RECORD *ebr = (EXTENDED_BOOT_RECORD *) malloc(MAX_BYTES_PER_SECTOR);
if(!ebr) return;
sec_t next_erb_lba = 0;
do
{
// Read and validate the extended boot record
if (!interface->readSectors(ebr_lba + next_erb_lba, 1, &ebr))
return;
if (ebr.signature != EBR_SIGNATURE)
return;
if(le32(ebr.partition.block_count) > 0 && !IsExisting(ebr_lba + next_erb_lba + le32(ebr.partition.lba_start)))
if (!interface->readSectors(ebr_lba + next_erb_lba, 1, ebr))
{
AddPartition(PartFromType(ebr.partition.type), ebr_lba + next_erb_lba + le32(ebr.partition.lba_start),
le32(ebr.partition.block_count), (ebr.partition.status == PARTITION_BOOTABLE),
ebr.partition.type, PartNum);
free(ebr);
return;
}
if (ebr->signature != EBR_SIGNATURE)
{
free(ebr);
return;
}
if(le32(ebr->partition.block_count) > 0 && !IsExisting(ebr_lba + next_erb_lba + le32(ebr->partition.lba_start)))
{
AddPartition(PartFromType(ebr->partition.type), ebr_lba + next_erb_lba + le32(ebr->partition.lba_start),
le32(ebr->partition.block_count), (ebr->partition.status == PARTITION_BOOTABLE),
ebr->partition.type, PartNum);
}
// Get the start sector of the current partition
// and the next extended boot record in the chain
next_erb_lba = le32(ebr.next_ebr.lba_start);
next_erb_lba = le32(ebr->next_ebr.lba_start);
}
while(next_erb_lba > 0);
free(ebr);
}
static const u8 TYPE_UNUSED[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
@ -273,32 +291,39 @@ static const u8 TYPE_LINUX_MS_BASIC_DATA[16] = { 0xA2,0xA0,0xD0,0xEB,0xE5,0xB9,0
int PartitionHandle::CheckGPT(u8 PartNum)
{
GPT_HEADER gpt_header;
GPT_HEADER *gpt_header = (GPT_HEADER *) malloc(MAX_BYTES_PER_SECTOR);
if(!gpt_header) return -1;
// Read and validate the extended boot record
if (!interface->readSectors(1, 1, &gpt_header))
if (!interface->readSectors(1, 1, gpt_header))
{
free(gpt_header);
return -1;
}
if(strncmp(gpt_header.magic, "EFI PART", 8) != 0)
if(strncmp(gpt_header->magic, "EFI PART", 8) != 0)
{
free(gpt_header);
return -1;
}
gpt_header.part_table_lba = le64(gpt_header.part_table_lba);
gpt_header.part_entries = le32(gpt_header.part_entries);
gpt_header.part_entry_size = le32(gpt_header.part_entry_size);
gpt_header.part_entry_checksum = le32(gpt_header.part_entry_checksum);
gpt_header->part_table_lba = le64(gpt_header->part_table_lba);
gpt_header->part_entries = le32(gpt_header->part_entries);
gpt_header->part_entry_size = le32(gpt_header->part_entry_size);
gpt_header->part_entry_checksum = le32(gpt_header->part_entry_checksum);
u8 * sector_buf = new u8[BYTES_PER_SECTOR];
u8 * sector_buf = new u8[MAX_BYTES_PER_SECTOR];
u64 next_lba = gpt_header.part_table_lba;
u64 next_lba = gpt_header->part_table_lba;
for(u32 i = 0; i < gpt_header.part_entries; ++i)
for(u32 i = 0; i < gpt_header->part_entries; ++i)
{
if (!interface->readSectors(next_lba, 1, sector_buf))
break;
for(u32 n = 0; n < BYTES_PER_SECTOR/gpt_header.part_entry_size; ++n, ++i)
for(u32 n = 0; n < BYTES_PER_SECTOR/gpt_header->part_entry_size; ++n, ++i)
{
GUID_PART_ENTRY * part_entry = (GUID_PART_ENTRY *) (sector_buf+gpt_header.part_entry_size*n);
GUID_PART_ENTRY * part_entry = (GUID_PART_ENTRY *) (sector_buf+gpt_header->part_entry_size*n);
if(memcmp(part_entry->part_type_guid, TYPE_UNUSED, 16) == 0)
continue;
@ -315,16 +340,20 @@ int PartitionHandle::CheckGPT(u8 PartNum)
}
delete [] sector_buf;
free(gpt_header);
return 0;
}
void PartitionHandle::AddPartition(const char * name, u64 lba_start, u64 sec_count, bool bootable, u8 part_type, u8 part_num)
{
char buffer[BYTES_PER_SECTOR];
char *buffer = (char *) malloc(MAX_BYTES_PER_SECTOR);
if (!interface->readSectors(lba_start, 1, buffer))
{
free(buffer);
return;
}
wbfs_head_t *head = (wbfs_head_t *) buffer;
@ -362,4 +391,5 @@ void PartitionHandle::AddPartition(const char * name, u64 lba_start, u64 sec_cou
PartitionList.push_back(PartitionEntrie);
free(buffer);
}

View File

@ -46,7 +46,8 @@
#define GUID_HIDDEN_PARTITION 0x2000000000000000LL /* Hidden partition */
#define GUID_NO_AUTOMOUNT_PARTITION 0x4000000000000000LL /* Do not automount (e.g., do not assign drive letter) */
#define BYTES_PER_SECTOR 512 /* Default in libogc */
#define BYTES_PER_SECTOR 512 /* Default in libogc */
#define MAX_BYTES_PER_SECTOR 4096 /* Max bytes per sector */
typedef struct _PARTITION_RECORD {
u8 status; /* Partition status; see above */

View File

@ -103,6 +103,14 @@ bool StartUpProcess::USBSpinUp()
messageTxt->SetTextf("Waiting for HDD: %i sec left\n", retries/20);
Draw();
}
if(retries/20 == 18 && IOS_GetVersion() < 200)
{
DeviceHandler::DestroyInstance();
IosLoader::LoadAppCios();
DeviceHandler::Instance()->MountSD();
handle = DeviceHandler::GetUSBInterface();
}
}
while(!started && --retries > 0);

View File

@ -31,7 +31,7 @@ int mload_init()
{
int n;
if(hid<0) hid = iosCreateHeap(0x8000);
if(hid<0) hid = iosCreateHeap(0x10000);
if(hid<0)
{

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
extern "C" {
#endif
extern unsigned char ehcmodule_5[3352];
extern unsigned char ehcmodule_5[25883];
#define ehcmodule_5_size sizeof(ehcmodule_5)

View File

@ -32,6 +32,7 @@ u32 AppEntrypoint = 0;
struct discHdr *dvdheader = NULL;
extern int wbfs_part_fs;
extern u32 hdd_sector_size;
extern int mountMethod;
int GameBooter::BootGCMode()
@ -134,7 +135,8 @@ int GameBooter::SetupDisc(u8 * gameID)
int ret = -1;
if(IosLoader::IsWaninkokoIOS() && IOS_GetRevision() < 18)
if(((IosLoader::IsWaninkokoIOS() && IOS_GetRevision() < 18) ||
hdd_sector_size != 512) && wbfs_part_fs == PART_FS_WBFS)
{
gprintf("Disc_SetUSB...");
ret = Disc_SetUSB(gameID);

View File

@ -65,7 +65,7 @@ static char fs3[] ATTRIBUTE_ALIGN(32) = "/dev/usb/ehc";
static u8 * mem2_ptr = NULL;
static s32 hid = -1, fd = -1;
static u32 sector_size = 0;
u32 hdd_sector_size = 512;
s32 USBStorage2_Init(void)
{
@ -93,7 +93,7 @@ s32 USBStorage2_Init(void)
if (ret < 0) goto err;
/* Get device capacity */
if (USBStorage2_GetCapacity(&sector_size) == 0)
if (USBStorage2_GetCapacity(&hdd_sector_size) == 0)
{
ret = IPC_ENOENT;
goto err;
@ -120,6 +120,8 @@ void USBStorage2_Deinit(void)
IOS_Close(fd);
fd = -1;
}
hdd_sector_size = 512;
}
@ -143,9 +145,9 @@ s32 USBStorage2_GetCapacity(u32 *_sector_size)
{
s32 ret;
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i", &sector_size);
ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i", &hdd_sector_size);
if (ret && _sector_size) *_sector_size = sector_size;
if (ret && _sector_size) *_sector_size = hdd_sector_size;
return ret;
}
@ -162,14 +164,14 @@ s32 USBStorage2_ReadSectors(u32 sector, u32 numSectors, void *buffer)
if (fd < 0) return fd;
if (!mem2_ptr)
mem2_ptr = (u8 *) MEM2_alloc(sector_size * MAX_BUFFER_SECTORS);
mem2_ptr = (u8 *) MEM2_alloc(hdd_sector_size * MAX_BUFFER_SECTORS);
s32 read_secs, read_size;
while(numSectors > 0)
{
read_secs = numSectors > MAX_BUFFER_SECTORS ? MAX_BUFFER_SECTORS : numSectors;
read_size = read_secs*sector_size;
read_size = read_secs*hdd_sector_size;
// Do not read more than MAX_BUFFER_SECTORS sectors at once and create a mem overflow!
if (!isMEM2Buffer(buffer))
@ -206,14 +208,14 @@ s32 USBStorage2_WriteSectors(u32 sector, u32 numSectors, const void *buffer)
/* Device not opened */
if (!mem2_ptr)
mem2_ptr = (u8 *) MEM2_alloc(sector_size * MAX_BUFFER_SECTORS);
mem2_ptr = (u8 *) MEM2_alloc(hdd_sector_size * MAX_BUFFER_SECTORS);
s32 write_size, write_secs;
while(numSectors > 0)
{
write_secs = numSectors > MAX_BUFFER_SECTORS ? MAX_BUFFER_SECTORS : numSectors;
write_size = write_secs*sector_size;
write_size = write_secs*hdd_sector_size;
/* MEM1 buffer */
if (!isMEM2Buffer(buffer))

View File

@ -14,8 +14,6 @@ rw_sector_callback_t readCallback = NULL;
rw_sector_callback_t writeCallback = NULL;
const DISC_INTERFACE * currentHandle = NULL;
static const u32 sector_size = 512;
s32 __ReadDVD(void *fp, u32 lba, u32 len, void *iobuf)
{
void *buffer = NULL;
@ -66,20 +64,23 @@ s32 __ReadDVD(void *fp, u32 lba, u32 len, void *iobuf)
s32 __ReadUSB(void *fp, u32 lba, u32 count, void *iobuf)
{
WBFS_PartInfo * info = (WBFS_PartInfo *) fp;
u32 cnt = 0;
s32 ret;
u32 partition_offset = info->partition_lba + (lba-info->partition_lba)*(info->wbfs_sector_size/info->hdd_sector_size);
count *= info->wbfs_sector_size/info->hdd_sector_size;
/* Do reads */
while (cnt < count)
{
void *ptr = ((u8 *) iobuf) + (cnt * sector_size);
u8 *ptr = ((u8 *) iobuf) + (cnt * info->wbfs_sector_size);
u32 sectors = (count - cnt);
/* Read sectors is too big */
if (sectors > MAX_NB_SECTORS) sectors = MAX_NB_SECTORS;
/* USB read */
ret = currentHandle->readSectors(lba + cnt, sectors, ptr);
ret = currentHandle->readSectors(partition_offset + cnt, sectors, ptr);
if (!ret) return -1;
/* Increment counter */
@ -91,20 +92,23 @@ s32 __ReadUSB(void *fp, u32 lba, u32 count, void *iobuf)
s32 __WriteUSB(void *fp, u32 lba, u32 count, void *iobuf)
{
WBFS_PartInfo * info = (WBFS_PartInfo *) fp;
u32 cnt = 0;
s32 ret;
u32 partition_offset = info->partition_lba + (lba-info->partition_lba)*(info->wbfs_sector_size/info->hdd_sector_size);
count *= info->wbfs_sector_size/info->hdd_sector_size;
/* Do writes */
while (cnt < count)
{
void *ptr = ((u8 *) iobuf) + (cnt * sector_size);
u8 *ptr = ((u8 *) iobuf) + (cnt * info->wbfs_sector_size);
u32 sectors = (count - cnt);
/* Write sectors is too big */
if (sectors > MAX_NB_SECTORS) sectors = MAX_NB_SECTORS;
/* USB write */
ret = currentHandle->writeSectors(lba + cnt, sectors, ptr);
ret = currentHandle->writeSectors(partition_offset + cnt, sectors, ptr);
if (!ret) return -1;
/* Increment counter */
@ -116,20 +120,23 @@ s32 __WriteUSB(void *fp, u32 lba, u32 count, void *iobuf)
s32 __ReadSDHC(void *fp, u32 lba, u32 count, void *iobuf)
{
WBFS_PartInfo * info = (WBFS_PartInfo *) fp;
u32 cnt = 0;
s32 ret;
u32 partition_offset = info->partition_lba + (lba-info->partition_lba)*(info->wbfs_sector_size/info->hdd_sector_size);
count *= info->wbfs_sector_size/info->hdd_sector_size;
/* Do reads */
while (cnt < count)
{
void *ptr = ((u8 *) iobuf) + (cnt * sector_size);
void *ptr = ((u8 *) iobuf) + (cnt * info->wbfs_sector_size);
u32 sectors = (count - cnt);
/* Read sectors is too big */
if (sectors > MAX_NB_SECTORS) sectors = MAX_NB_SECTORS;
/* SDHC read */
ret = SDHC_ReadSectors(lba + cnt, sectors, ptr);
ret = SDHC_ReadSectors(partition_offset + cnt, sectors, ptr);
if (!ret) return -1;
/* Increment counter */
@ -141,20 +148,23 @@ s32 __ReadSDHC(void *fp, u32 lba, u32 count, void *iobuf)
s32 __WriteSDHC(void *fp, u32 lba, u32 count, void *iobuf)
{
WBFS_PartInfo * info = (WBFS_PartInfo *) fp;
u32 cnt = 0;
s32 ret;
u32 partition_offset = info->partition_lba + (lba-info->partition_lba)*(info->wbfs_sector_size/info->hdd_sector_size);
count *= info->wbfs_sector_size/info->hdd_sector_size;
/* Do writes */
while (cnt < count)
{
void *ptr = ((u8 *) iobuf) + (cnt * sector_size);
void *ptr = ((u8 *) iobuf) + (cnt * info->wbfs_sector_size);
u32 sectors = (count - cnt);
/* Write sectors is too big */
if (sectors > MAX_NB_SECTORS) sectors = MAX_NB_SECTORS;
/* SDHC write */
ret = SDHC_WriteSectors(lba + cnt, sectors, ptr);
ret = SDHC_WriteSectors(partition_offset + cnt, sectors, ptr);
if (!ret) return -1;
/* Increment counter */

View File

@ -6,8 +6,17 @@ extern "C"
{
#endif
#include <gccore.h>
#include "libs/libwbfs/libwbfs.h"
typedef struct _WBFS_PartInfo
{
u32 wbfs_sector_size;
u32 hdd_sector_size;
u32 partition_lba;
u32 partition_num_sec;
} WBFS_PartInfo;
extern rw_sector_callback_t readCallback;
extern rw_sector_callback_t writeCallback;
extern const DISC_INTERFACE * currentHandle;

View File

@ -5,24 +5,37 @@
#include "wbfs_rw.h"
extern int wbfs_part_fs;
extern u32 hdd_sector_size;
s32 Wbfs_Wbfs::Open()
{
wbfs_t *part = NULL;
u8 buffer[512];
memset(buffer, 0, sizeof(buffer));
PartInfo.wbfs_sector_size = hdd_sector_size;
PartInfo.hdd_sector_size = hdd_sector_size;
PartInfo.partition_lba = lba;
PartInfo.partition_num_sec = size;
wbfs_head_t *head = (wbfs_head_t *) buffer;
u8 * buffer = (u8 *) malloc(hdd_sector_size);
memset(buffer, 0, hdd_sector_size);
if(readCallback(NULL, lba, 1, buffer) < 0)
if(readCallback(&PartInfo, lba, 1, buffer) < 0)
{
free(buffer);
return -1;
}
wbfs_head_t head;
memcpy(&head, buffer, sizeof(wbfs_head_t));
free(buffer);
if (head.magic != wbfs_htonl(WBFS_MAGIC))
return -1;
if (head->magic != wbfs_htonl(WBFS_MAGIC))
return -1;
PartInfo.wbfs_sector_size = 1 << head.hd_sec_sz_s;
/* Open partition */
part = wbfs_open_partition(readCallback, writeCallback, NULL, 512, head->n_hd_sec, lba, 0);
part = wbfs_open_partition(readCallback, writeCallback, &PartInfo, 1 << head.hd_sec_sz_s, head.n_hd_sec, lba, 0);
if (!part) return -1;
/* Close current hard disk */
@ -65,10 +78,16 @@ void Wbfs_Wbfs::CloseDisc(wbfs_disc_t *disc)
s32 Wbfs_Wbfs::Format()
{
WBFS_PartInfo HDD_Inf;
HDD_Inf.wbfs_sector_size = hdd_sector_size;
HDD_Inf.hdd_sector_size = hdd_sector_size;
HDD_Inf.partition_lba = lba;
HDD_Inf.partition_num_sec = size;
wbfs_t *partition = NULL;
/* Reset partition */
partition = wbfs_open_partition(readCallback, writeCallback, NULL, 512, size, lba, 1);
partition = wbfs_open_partition(readCallback, writeCallback, &PartInfo, hdd_sector_size, size, lba, 1);
if (!partition) return -1;
/* Free memory */

View File

@ -3,6 +3,7 @@
#include "wbfs_base.h"
#include "libs/libwbfs/libwbfs.h"
#include "wbfs_rw.h"
class Wbfs_Wbfs: public Wbfs
{
@ -31,6 +32,8 @@ class Wbfs_Wbfs: public Wbfs
u64 EstimateGameSize();
int GetFragList(u8 *id);
private:
_WBFS_PartInfo PartInfo;
};
#endif //_WBFS_WBFS_H