Skip to content

Commit

Permalink
Support USBs with no parition table
Browse files Browse the repository at this point in the history
  • Loading branch information
McCaulay committed Mar 11, 2023
1 parent 2258a5c commit ebc374f
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 45 deletions.
2 changes: 2 additions & 0 deletions sdk/include/ps/sce/usb/usb/usb.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class Usb
bool updateDescriptors();
bool readSector(uint32_t blockAddress, uint8_t* buffer);
bool readSectors(uint32_t blockAddress, uint8_t* buffer, uint32_t count = 1);
bool isSectorExFAT(uint8_t* sector);
bool findFilesystem();
private:
static uint64_t devices;
private:
Expand Down
2 changes: 2 additions & 0 deletions sdk/src/ps/sce/usb/filesystems/exfat/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ bool exFAT::Filesystem::readNextCluster(exFAT::File file, uint8_t* buffer)

uint32_t sectorIndex = this->getSectorIndexForCluster(this->readClusterIndex);
bool valid = this->readCluster(sectorIndex, buffer);
if (!valid)
PS::Debug.printf("Failed to read cluster at sector index: %i\n", sectorIndex);

if (file.isContinuous())
this->readClusterIndex++;
Expand Down
3 changes: 3 additions & 0 deletions sdk/src/ps/sce/usb/mass-store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ int32_t PS::MassStore::readBlock(uint32_t blockAddress, uint16_t blocks, uint16_

int32_t err = this->command(&command, buffer);
if (err != SCE_OK)
{
PS::Debug.printf("PS::MassStore::readBlock: command error 0x%x\n", err);
return err;
}

SCSI::CommandStatus status;
return this->getReturnedStatus(&status);
Expand Down
109 changes: 64 additions & 45 deletions sdk/src/ps/sce/usb/usb/usb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,51 +257,8 @@ bool Usb::mount()
if (this->sectorSize != SECTOR_SIZE)
return false;

// Read master boot record table
MasterBootRecordTable mbr;
if (!this->readSector(0, (uint8_t*)&mbr))
{
PS::Debug.printf("Failed to read master boot record\n");
return false;
}

// Validate master boot record
if (!mbr.isValid())
{
PS::Debug.printf("Master boot record is invalid\n");
return false;
}

// Loop each partition
bool filesystemFound = false;
for (uint32_t i = 0; i < mbr.getMaxParitionCount(); i++)
{
MasterBootRecord partition = mbr.getParition(i);
if (partition.isEmpty())
continue;

// Determine partition filesystem type
uint8_t bootSector[SECTOR_SIZE];
if (!this->readSector(partition.logicalBlockAddress, bootSector))
continue;

// https://en.wikipedia.org/wiki/BIOS_parameter_block

// exFAT
if (PS2::memcmp(bootSector + 0x03, (void*)"EXFAT ", 8) == 0)
{
this->partition = partition;
this->filesystem = exFAT::Filesystem(&this->massStore, this->partition.logicalBlockAddress, *(exFAT::BootSector*)bootSector);
filesystemFound = true;
break;
}

// Unhandled filesystem
continue;
}

// Failed to find filesystem
if (!filesystemFound)
// Find filesystem
if (!this->findFilesystem())
{
PS::Debug.printf("Failed to find exFAT filesystem\n");
return false;
Expand Down Expand Up @@ -430,5 +387,67 @@ bool Usb::readSectors(uint32_t blockAddress, uint8_t* buffer, uint32_t count)
PS::Debug.printf("Mass Store read block failed with error 0x%x\n", error);
return error == SCE_OK;
}

bool Usb::isSectorExFAT(uint8_t* sector)
{
// https://en.wikipedia.org/wiki/BIOS_parameter_block

// exFAT
return PS2::memcmp(sector + 0x03, (void*)"EXFAT ", 8) == 0;
}

bool Usb::findFilesystem()
{
// Read boot sector
uint8_t bootSector[SECTOR_SIZE];
if (!this->readSector(0, bootSector))
{
PS::Debug.printf("Failed to read boot sector\n");
return false;
}

// exFAT is in boot sector with no partition table
if (this->isSectorExFAT(bootSector))
{
this->filesystem = exFAT::Filesystem(&this->massStore, 0, *(exFAT::BootSector*)bootSector);
return true;
}

// Read boot sector as master boot record table
MasterBootRecordTable mbr = *(MasterBootRecordTable*)bootSector;

// Validate master boot record
if (!mbr.isValid())
{
PS::Debug.printf("Master boot record is invalid\n");
return false;
}

// Loop each partition
for (uint32_t i = 0; i < mbr.getMaxParitionCount(); i++)
{
MasterBootRecord partition = mbr.getParition(i);
if (partition.isEmpty())
continue;

// Determine partition filesystem type
if (!this->readSector(partition.logicalBlockAddress, bootSector))
continue;

// exFAT check
if (this->isSectorExFAT(bootSector))
{
this->partition = partition;
this->filesystem = exFAT::Filesystem(&this->massStore, this->partition.logicalBlockAddress, *(exFAT::BootSector*)bootSector);
return true;
}

// Unhandled filesystem
continue;
}

// Failed to find exFAT filesystem
return false;
}
#endif
#endif

0 comments on commit ebc374f

Please sign in to comment.