Skip to content

Commit

Permalink
Fix SDIO HLE writing garbage to memory.
Browse files Browse the repository at this point in the history
When servicing a write-register request, it wrote the contents to the
register offset plus 0x8d070000, which corresponds to the actual
hardware registers, presumably in case the application wanted to read
them directly rather than with a read-register request.  WriteToHardware
doesn't handle cached writes to registers, so it decided the address was
RAM, applied RAM_MASK, and happily wrote the register contents to
0x81070000, causing random corruption.  Since the PPC does not normally
have access to those registers, there is no reason to be doing this in
the first place.  Use a member to store these values instead.

(Also add a proper DoState.)
  • Loading branch information
comex committed Sep 10, 2013
1 parent a3ef35a commit 4add0f5
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 12 deletions.
46 changes: 39 additions & 7 deletions Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp
Expand Up @@ -22,6 +22,19 @@ CWII_IPC_HLE_Device_sdio_slot0::CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, co
, m_Card(NULL)
{}

void CWII_IPC_HLE_Device_sdio_slot0::DoState(PointerWrap& p)
{
DoStateShared(p);
if (p.GetMode() == PointerWrap::MODE_READ)
{
OpenInternal();
}
p.Do(m_Status);
p.Do(m_BlockLength);
p.Do(m_BusWidth);
p.Do(m_Registers);
}

void CWII_IPC_HLE_Device_sdio_slot0::EventNotify()
{
if ((SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_INSERT) ||
Expand All @@ -34,10 +47,8 @@ void CWII_IPC_HLE_Device_sdio_slot0::EventNotify()
}
}

bool CWII_IPC_HLE_Device_sdio_slot0::Open(u32 _CommandAddress, u32 _Mode)
void CWII_IPC_HLE_Device_sdio_slot0::OpenInternal()
{
INFO_LOG(WII_IPC_SD, "Open");

const std::string filename = File::GetUserPath(D_WIIUSER_IDX) + "sd.raw";
m_Card.Open(filename, "r+b");
if (!m_Card)
Expand All @@ -53,8 +64,16 @@ bool CWII_IPC_HLE_Device_sdio_slot0::Open(u32 _CommandAddress, u32 _Mode)
ERROR_LOG(WII_IPC_SD, "Could not open SD Card image or create a new one, are you running from a read-only directory?");
}
}
}

bool CWII_IPC_HLE_Device_sdio_slot0::Open(u32 _CommandAddress, u32 _Mode)
{
INFO_LOG(WII_IPC_SD, "Open");

OpenInternal();

Memory::Write_U32(GetDeviceID(), _CommandAddress + 0x4);
memset(m_Registers, 0, sizeof(m_Registers));
m_Active = true;
return true;
}
Expand Down Expand Up @@ -96,30 +115,43 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)

DEBUG_LOG(WII_IPC_SD, "IOCTL_WRITEHCR 0x%08x - 0x%08x", reg, val);

if (reg >= 0x200)
{
DEBUG_LOG(WII_IPC_SD, "IOCTL_WRITEHCR out of range");
break;
}

if ((reg == HCR_CLOCKCONTROL) && (val & 1))
{
// Clock is set to oscillate, enable bit 1 to say it's stable
Memory::Write_U32(val | 2, SDIO_BASE + reg);
m_Registers[reg] = val | 2;
}
else if ((reg == HCR_SOFTWARERESET) && val)
{
// When a reset is specified, the register gets cleared
Memory::Write_U32(0, SDIO_BASE + reg);
m_Registers[reg] = 0;
}
else
{
// Default to just storing the new value
Memory::Write_U32(val, SDIO_BASE + reg);
m_Registers[reg] = val;
}
}
break;

case IOCTL_READHCR:
{
u32 reg = Memory::Read_U32(BufferIn);
u32 val = Memory::Read_U32(SDIO_BASE + reg);

if (reg >= 0x200)
{
DEBUG_LOG(WII_IPC_SD, "IOCTL_READHCR out of range");
break;
}

u32 val = m_Registers[reg];
DEBUG_LOG(WII_IPC_SD, "IOCTL_READHCR 0x%08x - 0x%08x", reg, val);

// Just reading the register
Memory::Write_U32(val, BufferOut);
}
Expand Down
10 changes: 5 additions & 5 deletions Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.h
Expand Up @@ -15,6 +15,8 @@ class CWII_IPC_HLE_Device_sdio_slot0 : public IWII_IPC_HLE_Device

CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, const std::string& _rDeviceName);

virtual void DoState(PointerWrap& p);

bool Open(u32 _CommandAddress, u32 _Mode);
bool Close(u32 _CommandAddress, bool _bForce);
bool IOCtl(u32 _CommandAddress);
Expand All @@ -24,11 +26,6 @@ class CWII_IPC_HLE_Device_sdio_slot0 : public IWII_IPC_HLE_Device

private:

enum
{
SDIO_BASE = 0x8d070000,
};

// SD Host Controller Registers
enum
{
Expand Down Expand Up @@ -119,11 +116,14 @@ class CWII_IPC_HLE_Device_sdio_slot0 : public IWII_IPC_HLE_Device
u32 m_BlockLength;
u32 m_BusWidth;

u32 m_Registers[0x200/4];

File::IOFile m_Card;

u32 ExecuteCommand(u32 BufferIn, u32 BufferInSize,
u32 BufferIn2, u32 BufferInSize2,
u32 _BufferOut, u32 BufferOutSize);
void OpenInternal();
};

#endif

0 comments on commit 4add0f5

Please sign in to comment.