usbloadergx/source/usbloader/partition_usbloader.c
dimok321 2adc6cc995 *Completely rewrote the asynchron GuiImageData class (problems from switch Carousel<->Grid layour should be fixed now)
*Fixed bug mounting a wbfs partition which was formatted from an ext partition
*Rewrote the parental control feature. Removed loading pin or settings from the Wii Settings. Parental control is now completely managed in the loader from the settings selected and the password set.
*Saving password in config file is now encrypted
*Added loop to wait for usb when reloading the cIOS before game start


The parental control feature is filtering games like following when usb loader is locked:
level 0 (everyone 0+)		> shows only games with lvl 0
level 1 (childs 7+)		> shows games with lvl 0, 1
level 2 (teens 12+)		> shows games with lvl 0, 1, 2
level 3 (mature 16+)		> shows games with lvl 0, 1, 2, 3
level 4 (adults only 18+)	> shows all games (lvl 0, 1, 2, 3, 4)

level 4 is default when creating new configs
2010-12-19 18:20:33 +00:00

429 lines
10 KiB
C

// Modified by oggzee
#include <stdio.h>
#include <string.h>
#include <ogcsys.h>
#include <unistd.h>
#include "partition_usbloader.h"
#include "sdhc.h"
#include "usbstorage2.h"
#include "utils.h"
#include "wbfs.h"
#include "libs/libwbfs/libwbfs.h"
/* 'partition table' structure */
typedef struct
{
/* Zero bytes */
u8 padding[446];
/* Partition table entries */
partitionEntry entries[MAX_PARTITIONS];
}ATTRIBUTE_PACKED partitionTable;
s32 Partition_GetEntries(u32 device, partitionEntry *outbuf, u32 *outval)
{
static partitionTable table ATTRIBUTE_ALIGN( 32 );
u32 cnt, sector_size;
s32 ret;
/* Read from specified device */
switch (device)
{
case WBFS_DEVICE_USB:
{
/* Get sector size */
ret = USBStorage2_GetCapacity(&sector_size);
if (ret == 0) return -1;
/* Read partition table */
ret = USBStorage2_ReadSectors(0, 1, &table);
if (ret < 0) return ret;
break;
}
case WBFS_DEVICE_SDHC:
{
/* SDHC sector size */
sector_size = SDHC_SECTOR_SIZE;
/* Read partition table */
ret = SDHC_ReadSectors(0, 1, &table);
if (!ret) return -1;
break;
}
default:
return -1;
}
/* Swap endianess */
for (cnt = 0; cnt < 4; cnt++)
{
partitionEntry *entry = &table.entries[cnt];
entry->sector = swap32(entry->sector);
entry->size = swap32(entry->size);
}
/* Set partition entries */
memcpy(outbuf, table.entries, sizeof(table.entries));
/* Set sector size */
*outval = sector_size;
return 0;
}
bool Device_ReadSectors(u32 device, u32 sector, u32 count, void *buffer)
{
s32 ret;
/* Read from specified device */
switch (device)
{
case WBFS_DEVICE_USB:
ret = USBStorage2_ReadSectors(sector, count, buffer);
if (ret < 0) return false;
return true;
case WBFS_DEVICE_SDHC:
return SDHC_ReadSectors(sector, count, buffer);
}
return false;
}
bool Device_WriteSectors(u32 device, u32 sector, u32 count, void *buffer)
{
s32 ret;
/* Read from specified device */
switch (device)
{
case WBFS_DEVICE_USB:
ret = USBStorage2_WriteSectors(sector, count, buffer);
if (ret < 0) return false;
return true;
case WBFS_DEVICE_SDHC:
return SDHC_WriteSectors(sector, count, buffer);
}
return false;
}
s32 Partition_GetEntriesEx(u32 device, partitionEntry *outbuf, u32 *psect_size, u8 *num)
{
static u8 Buffer[sizeof(partitionTable)] ATTRIBUTE_ALIGN( 32 );
partitionTable *table = (partitionTable *) Buffer;
partitionEntry *entry;
u32 i, sector_size;
s32 ret;
int maxpart = *num;
// Get sector size
switch (device)
{
case WBFS_DEVICE_USB:
ret = USBStorage2_GetCapacity(&sector_size);
if (ret == 0) return -1;
break;
case WBFS_DEVICE_SDHC:
sector_size = SDHC_SECTOR_SIZE;
break;
default:
return -1;
}
/* Set sector size */
*psect_size = sector_size;
u32 ext = 0;
u32 next = 0;
// Read partition table
ret = Device_ReadSectors(device, 0, 1, table);
if (!ret) return -1;
// Check if it's a RAW WBFS disc, without partition table
if (get_fs_type((u8 *) table) == FS_TYPE_WBFS)
{
memset(outbuf, 0, sizeof(table->entries));
wbfs_head_t * head = (wbfs_head_t *) Buffer;
outbuf->size = wbfs_ntohl( head->n_hd_sec );
*num = 1;
return 0;
}
/* Swap endianess */
for (i = 0; i < 4; i++)
{
entry = &table->entries[i];
entry->sector = swap32(entry->sector);
entry->size = swap32(entry->size);
if (!ext && part_is_extended(entry->type))
{
ext = entry->sector;
}
}
/* Set partition entries */
memcpy(outbuf, table->entries, sizeof(table->entries));
// num primary
*num = 4;
if (!ext) return 0;
next = ext;
// scan extended partition for logical
for (i = 0; i < maxpart - 4; i++)
{
ret = Device_ReadSectors(device, next, 1, table);
if (!ret) break;
if (i == 0)
{
// handle the invalid scenario where wbfs is on an EXTENDED
// partition instead of on the Logical inside Extended.
if (get_fs_type((u8 *) table) == FS_TYPE_WBFS) break;
}
entry = &table->entries[0];
entry->sector = swap32(entry->sector);
entry->size = swap32(entry->size);
if (entry->type && entry->size && entry->sector)
{
// rebase to abolute address
entry->sector += next;
// add logical
memcpy(&outbuf[*num], entry, sizeof(*entry));
(*num)++;
// get next
entry++;
if (entry->type && entry->size && entry->sector)
{
next = ext + swap32(entry->sector);
}
else
{
break;
}
}
}
return 0;
}
bool part_is_extended(int type)
{
if (type == 0x05) return true;
if (type == 0x0f) return true;
return false;
}
bool part_is_data(int type)
{
if (type && !part_is_extended(type)) return true;
return false;
}
bool part_valid_data(partitionEntry *entry)
{
if (entry->size && entry->type && entry->sector)
{
return part_is_data(entry->type);
}
return false;
}
char* part_type_data(int type)
{
switch (type)
{
case 0x01:
return "FAT12";
case 0x04:
return "FAT16";
case 0x06:
return "FAT16"; //+
case 0x07:
return "NTFS";
case 0x0b:
return "FAT32";
case 0x0c:
return "FAT32";
case 0x0e:
return "FAT16";
case 0x82:
return "LxSWP";
case 0x83:
return "LINUX";
case 0x8e:
return "LxLVM";
case 0xa8:
return "OSX";
case 0xab:
return "OSXBT";
case 0xaf:
return "OSXHF";
case 0xe8:
return "LUKS";
}
return NULL;
}
char *part_type_name(int type)
{
static char unk[8];
if (type == 0) return "UNUSED";
if (part_is_extended(type)) return "EXTEND";
char *p = part_type_data(type);
if (p) return p;
sprintf(unk, "UNK-%02x", type);
return unk;
}
int get_fs_type(u8 *buff)
{
// WBFS
wbfs_head_t *head = (wbfs_head_t *) buff;
if (head->magic == wbfs_htonl( WBFS_MAGIC )) return FS_TYPE_WBFS;
// 55AA
if(*((u16 *) (buff + 0x1FE)) == 0x55AA)
{
// FAT
if (memcmp(buff + 0x36, "FAT", 3) == 0) return FS_TYPE_FAT16;
if (memcmp(buff + 0x52, "FAT", 3) == 0) return FS_TYPE_FAT32;
// NTFS
if (memcmp(buff + 0x03, "NTFS", 4) == 0) return FS_TYPE_NTFS;
}
return FS_TYPE_UNK;
}
int get_part_fs(int fs_type)
{
switch (fs_type)
{
case FS_TYPE_FAT32:
return PART_FS_FAT;
case FS_TYPE_NTFS:
return PART_FS_NTFS;
case FS_TYPE_WBFS:
return PART_FS_WBFS;
case FS_TYPE_EXT:
return PART_FS_EXT;
default:
return -1;
}
}
bool is_type_fat(int type)
{
return (type == FS_TYPE_FAT16 || type == FS_TYPE_FAT32);
}
char *get_fs_name(int i)
{
switch (i)
{
case FS_TYPE_FAT16:
return "FAT16";
case FS_TYPE_FAT32:
return "FAT32";
case FS_TYPE_NTFS:
return "NTFS";
case FS_TYPE_EXT:
return "EXT";
case FS_TYPE_WBFS:
return "WBFS";
}
return "";
}
s32 Partition_GetList(u32 device, PartList *plist)
{
partitionEntry *entry = NULL;
PartInfo *pinfo = NULL;
int i, ret;
memset(plist, 0, sizeof(PartList));
// Get partition entries
plist->num = MAX_PARTITIONS_EX;
ret = Partition_GetEntriesEx(device, plist->pentry, &plist->sector_size, &plist->num);
if (ret < 0)
{
return -1;
}
// check for RAW WBFS disc
if (plist->num == 1)
{
pinfo = &plist->pinfo[0];
entry = &plist->pentry[0];
plist->wbfs_n = 1;
pinfo->wbfs_i = pinfo->index = 1;
return 0;
}
char buf[plist->sector_size];
// scan partitions for filesystem type
for (i = 0; i < plist->num; i++)
{
pinfo = &plist->pinfo[i];
entry = &plist->pentry[i];
if (!entry->size) continue;
if (!entry->type) continue;
if (!entry->sector) continue;
// even though wrong, it's possible WBFS is on an extended part.
//if (!part_is_data(entry->type)) continue;
if (!Device_ReadSectors(device, entry->sector, 1, buf)) continue;
pinfo->fs_type = get_fs_type((u8 *) buf);
if(entry->type == 0x83 && pinfo->fs_type == FS_TYPE_UNK) pinfo->fs_type = FS_TYPE_EXT;
if (pinfo->fs_type == FS_TYPE_WBFS)
{
// multiple wbfs on sdhc not supported
if (device == WBFS_DEVICE_SDHC && (plist->wbfs_n > 1 || i > 4)) continue;
plist->wbfs_n++;
pinfo->wbfs_i = pinfo->index = plist->wbfs_n;
}
else if (is_type_fat(pinfo->fs_type))
{
plist->fat_n++;
pinfo->fat_i = pinfo->index = plist->fat_n;
}
else if (pinfo->fs_type == FS_TYPE_NTFS)
{
plist->ntfs_n++;
pinfo->ntfs_i = pinfo->index = plist->ntfs_n;
}
else if (pinfo->fs_type == FS_TYPE_EXT)
{
plist->ext_n++;
pinfo->ext_i = pinfo->index = plist->ext_n;
}
pinfo->part_fs = get_part_fs(pinfo->fs_type);
}
return 0;
}
int Partition_FixEXT(u32 device, u8 part)
{
static partitionTable table ATTRIBUTE_ALIGN( 32 );
int ret;
if (part > 3) return -1;
// Read partition table
ret = Device_ReadSectors(device, 0, 1, &table);
if (!ret) return -1;
if (part_is_extended(table.entries[part].type))
{
table.entries[part].type = 0x0b; // FAT32
ret = Device_WriteSectors(device, 0, 1, &table);
if (!ret) return -1;
return 0;
}
return -1;
}