Skip to content

Commit

Permalink
Merge pull request #5391 from leoetlino/delete-title-content
Browse files Browse the repository at this point in the history
IOS/ES: Implement DeleteTitleContent properly
  • Loading branch information
leoetlino committed May 12, 2017
2 parents dae46fa + bacf523 commit ea89e85
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 80 deletions.
4 changes: 0 additions & 4 deletions Source/Core/Core/HW/HW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "Core/State.h"
#include "Core/WiiRoot.h"

namespace HW
{
Expand All @@ -50,7 +49,6 @@ void Init()

if (SConfig::GetInstance().bWii)
{
Core::InitializeWiiRoot(Core::WantsDeterminism());
IOS::Init();
IOS::HLE::Init(); // Depends on Memory
}
Expand All @@ -61,8 +59,6 @@ void Shutdown()
// IOS should always be shut down regardless of bWii because it can be running in GC mode (MIOS).
IOS::HLE::Shutdown(); // Depends on Memory
IOS::Shutdown();
if (SConfig::GetInstance().bWii)
Core::ShutdownWiiRoot();

SystemTimers::Shutdown();
CPU::Shutdown();
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/Core/IOS/ES/ES.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class ES final : public Device
ReturnCode Close(u32 fd) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;

ReturnCode DeleteTitleContent(u64 title_id) const;

private:
enum
{
Expand Down
29 changes: 19 additions & 10 deletions Source/Core/Core/IOS/ES/TitleManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,20 +376,29 @@ IPCCommandResult ES::DeleteTicket(const IOCtlVRequest& request)
return GetDefaultReply(IPC_SUCCESS);
}

IPCCommandResult ES::DeleteTitleContent(const IOCtlVRequest& request)
ReturnCode ES::DeleteTitleContent(u64 title_id) const
{
if (!request.HasNumberOfValidVectors(1, 0))
return GetDefaultReply(ES_EINVAL);
if (!CanDeleteTitle(title_id))
return ES_EINVAL;

u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
INFO_LOG(IOS_ES, "IOCTL_ES_DELETETITLECONTENT: title: %08x/%08x", (u32)(TitleID >> 32),
(u32)TitleID);
const std::string content_dir = Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT);
if (!File::IsDirectory(content_dir))
return FS_ENOENT;

// Presumably return -1017 when title not installed TODO verify
if (!DiscIO::CNANDContentManager::Access().RemoveTitle(TitleID, Common::FROM_SESSION_ROOT))
return GetDefaultReply(ES_EINVAL);
for (const auto& file : File::ScanDirectoryTree(content_dir, false).children)
{
if (file.virtualName.size() == 12 && file.virtualName.compare(8, 4, ".app") == 0)
File::Delete(file.physicalName);
}

return GetDefaultReply(IPC_SUCCESS);
return IPC_SUCCESS;
}

IPCCommandResult ES::DeleteTitleContent(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u64))
return GetDefaultReply(ES_EINVAL);
return GetDefaultReply(DeleteTitleContent(Memory::Read_U64(request.in_vectors[0].address)));
}

IPCCommandResult ES::ExportTitleInit(Context& context, const IOCtlVRequest& request)
Expand Down
82 changes: 60 additions & 22 deletions Source/Core/Core/IOS/IOS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,14 @@
#include "Core/IOS/WFS/WFSI.h"
#include "Core/IOS/WFS/WFSSRV.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/WiiRoot.h"
#include "DiscIO/NANDContentLoader.h"

namespace IOS
{
namespace HLE
{
static std::unique_ptr<Kernel> s_ios;
static std::unique_ptr<EmulationKernel> s_ios;

constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL;
constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
Expand Down Expand Up @@ -172,13 +173,43 @@ constexpr u64 IOS80_TITLE_ID = 0x0000000100000050;
constexpr u64 BC_TITLE_ID = 0x0000000100000100;
constexpr u64 MIOS_TITLE_ID = 0x0000000100000101;

Kernel::Kernel(u64 title_id) : m_title_id(title_id)
Kernel::Kernel()
{
// Until the Wii root and NAND path stuff is entirely managed by IOS and made non-static,
// using more than one IOS instance at a time is not supported.
_assert_(GetIOS() == nullptr);
Core::InitializeWiiRoot(false);
AddCoreDevices();
}

Kernel::~Kernel()
{
// Close all devices that were opened
for (auto& device : m_fdmap)
{
if (!device)
continue;
device->Close(0);
}

{
std::lock_guard<std::mutex> lock(m_device_map_mutex);
m_device_map.clear();
}

Core::ShutdownWiiRoot();
}

EmulationKernel::EmulationKernel(u64 title_id)
{
m_title_id = title_id;
INFO_LOG(IOS, "Starting IOS %016" PRIx64, title_id);

if (!SetupMemory(title_id, MemorySetupType::IOSReload))
WARN_LOG(IOS, "No information about this IOS -- cannot set up memory values");

Core::InitializeWiiRoot(Core::WantsDeterminism());

if (title_id == MIOS_TITLE_ID)
{
MIOS::Load();
Expand All @@ -188,25 +219,13 @@ Kernel::Kernel(u64 title_id) : m_title_id(title_id)
// IOS re-inits IPC and sends a dummy ack during its boot process.
EnqueueIPCAcknowledgement(0);

AddCoreDevices();
AddStaticDevices();
}

Kernel::~Kernel()
EmulationKernel::~EmulationKernel()
{
CoreTiming::RemoveAllEvents(s_event_enqueue);

// Close all devices that were opened
for (auto& device : m_fdmap)
{
if (!device)
continue;
device->Close(0);
}

{
std::lock_guard<std::mutex> lock(m_device_map_mutex);
m_device_map.clear();
}
}

// The title ID is a u64 where the first 32 bits are used for the title type.
Expand All @@ -217,6 +236,16 @@ u32 Kernel::GetVersion() const
return static_cast<u32>(m_title_id);
}

std::shared_ptr<Device::FS> Kernel::GetFS()
{
return std::static_pointer_cast<Device::FS>(m_device_map.at("/dev/fs"));
}

std::shared_ptr<Device::ES> Kernel::GetES()
{
return std::static_pointer_cast<Device::ES>(m_device_map.at("/dev/es"));
}

// Since we don't have actual processes, we keep track of only the PPC's UID/GID.
// These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC).
void Kernel::SetUidForPPC(u32 uid)
Expand Down Expand Up @@ -289,7 +318,7 @@ bool Kernel::BootIOS(const u64 ios_title_id)

// Shut down the active IOS first before switching to the new one.
s_ios.reset();
s_ios = std::make_unique<Kernel>(ios_title_id);
s_ios = std::make_unique<EmulationKernel>(ios_title_id);
return true;
}

Expand All @@ -299,10 +328,16 @@ void Kernel::AddDevice(std::unique_ptr<Device::Device> device)
m_device_map[device->GetDeviceName()] = std::move(device);
}

void Kernel::AddCoreDevices()
{
std::lock_guard<std::mutex> lock(m_device_map_mutex);
AddDevice(std::make_unique<Device::FS>(*this, "/dev/fs"));
AddDevice(std::make_unique<Device::ES>(*this, "/dev/es"));
}

void Kernel::AddStaticDevices()
{
std::lock_guard<std::mutex> lock(m_device_map_mutex);
_assert_msg_(IOS, m_device_map.empty(), "Reinit called while already initialized");

if (!SConfig::GetInstance().m_bt_passthrough_enabled)
AddDevice(std::make_unique<Device::BluetoothEmu>(*this, "/dev/usb/oh1/57e/305"));
Expand All @@ -311,8 +346,6 @@ void Kernel::AddStaticDevices()

AddDevice(std::make_unique<Device::STMImmediate>(*this, "/dev/stm/immediate"));
AddDevice(std::make_unique<Device::STMEventHook>(*this, "/dev/stm/eventhook"));
AddDevice(std::make_unique<Device::FS>(*this, "/dev/fs"));
AddDevice(std::make_unique<Device::ES>(*this, "/dev/es"));
AddDevice(std::make_unique<Device::DI>(*this, "/dev/di"));
AddDevice(std::make_unique<Device::NetKDRequest>(*this, "/dev/net/kd/request"));
AddDevice(std::make_unique<Device::NetKDTime>(*this, "/dev/net/kd/time"));
Expand Down Expand Up @@ -351,6 +384,11 @@ std::shared_ptr<Device::Device> Kernel::GetDeviceByName(const std::string& devic
return iterator != m_device_map.end() ? iterator->second : nullptr;
}

std::shared_ptr<Device::Device> EmulationKernel::GetDeviceByName(const std::string& device_name)
{
return Kernel::GetDeviceByName(device_name);
}

// Returns the FD for the newly opened device (on success) or an error code.
s32 Kernel::OpenDevice(OpenRequest& request)
{
Expand Down Expand Up @@ -639,7 +677,7 @@ void Init()
});

// Start with IOS80 to simulate part of the Wii boot process.
s_ios = std::make_unique<Kernel>(IOS80_TITLE_ID);
s_ios = std::make_unique<EmulationKernel>(IOS80_TITLE_ID);
// On a Wii, boot2 launches the system menu IOS, which then launches the system menu
// (which bootstraps the PPC). Bootstrapping the PPC results in memory values being set up.
// This means that the constants in the 0x3100 region are always set up by the time
Expand All @@ -653,7 +691,7 @@ void Shutdown()
s_ios.reset();
}

Kernel* GetIOS()
EmulationKernel* GetIOS()
{
return s_ios.get();
}
Expand Down
30 changes: 25 additions & 5 deletions Source/Core/Core/IOS/IOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ namespace HLE
namespace Device
{
class Device;
class ES;
class FS;
}

struct Request;
Expand Down Expand Up @@ -84,16 +86,20 @@ enum ProcessId : u32
class Kernel
{
public:
explicit Kernel(u64 ios_title_id);
~Kernel();
Kernel();
virtual ~Kernel();

void DoState(PointerWrap& p);
void HandleIPCEvent(u64 userdata);
void UpdateIPC();
void UpdateDevices();
void UpdateWantDeterminism(bool new_want_determinism);

std::shared_ptr<Device::Device> GetDeviceByName(const std::string& device_name);
// These are *always* part of the IOS kernel and always available.
// They are also the only available resource managers even before loading any module.
std::shared_ptr<Device::FS> GetFS();
std::shared_ptr<Device::ES> GetES();

void SDIO_EventNotify();

void EnqueueIPCRequest(u32 address);
Expand All @@ -111,13 +117,15 @@ class Kernel

IOSC& GetIOSC();

private:
protected:
void ExecuteIPCCommand(u32 address);
IPCCommandResult HandleIPCCommand(const Request& request);
void EnqueueIPCAcknowledgement(u32 address, int cycles_in_future = 0);

void AddDevice(std::unique_ptr<Device::Device> device);
void AddCoreDevices();
void AddStaticDevices();
std::shared_ptr<Device::Device> GetDeviceByName(const std::string& device_name);
s32 GetFreeDeviceID();
s32 OpenDevice(OpenRequest& request);

Expand All @@ -140,10 +148,22 @@ class Kernel
IOSC m_iosc;
};

// HLE for an IOS tied to emulation: base kernel which may have additional modules loaded.
class EmulationKernel : public Kernel
{
public:
explicit EmulationKernel(u64 ios_title_id);
~EmulationKernel();

// Get a resource manager by name.
// This only works for devices which are part of the device map.
std::shared_ptr<Device::Device> GetDeviceByName(const std::string& device_name);
};

// Used for controlling and accessing an IOS instance that is tied to emulation.
void Init();
void Shutdown();
Kernel* GetIOS();
EmulationKernel* GetIOS();

} // namespace HLE
} // namespace IOS
4 changes: 2 additions & 2 deletions Source/Core/Core/IOS/USB/OH0/OH0Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ OH0Device::OH0Device(Kernel& ios, const std::string& name) : Device(ios, name, D

void OH0Device::DoState(PointerWrap& p)
{
m_oh0 = std::static_pointer_cast<OH0>(m_ios.GetDeviceByName("/dev/usb/oh0"));
m_oh0 = std::static_pointer_cast<OH0>(GetIOS()->GetDeviceByName("/dev/usb/oh0"));
p.Do(m_name);
p.Do(m_vid);
p.Do(m_pid);
Expand All @@ -61,7 +61,7 @@ ReturnCode OH0Device::Open(const OpenRequest& request)
if (m_vid == 0 && m_pid == 0)
return IPC_ENOENT;

m_oh0 = std::static_pointer_cast<OH0>(m_ios.GetDeviceByName("/dev/usb/oh0"));
m_oh0 = std::static_pointer_cast<OH0>(GetIOS()->GetDeviceByName("/dev/usb/oh0"));

ReturnCode return_code;
std::tie(return_code, m_device_id) = m_oh0->DeviceOpen(m_vid, m_pid);
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/Core/IOS/WFS/WFSI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
Memory::CopyFromEmu(tmd_bytes.data(), tmd_addr, tmd_size);
m_tmd.SetBytes(std::move(tmd_bytes));

ES::TicketReader ticket = DiscIO::FindSignedTicket(m_tmd.GetTitleId());
IOS::ES::TicketReader ticket = DiscIO::FindSignedTicket(m_tmd.GetTitleId());
if (!ticket.IsValid())
{
return_error_code = -11028;
Expand All @@ -134,7 +134,7 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)

// Initializes the IV from the index of the content in the TMD contents.
u32 content_id = Memory::Read_U32(request.buffer_in + 8);
ES::Content content_info;
IOS::ES::Content content_info;
if (!m_tmd.FindContentById(content_id, &content_info))
{
WARN_LOG(IOS, "%s: Content id %08x not found", ioctl_name, content_id);
Expand Down
29 changes: 0 additions & 29 deletions Source/Core/DiscIO/NANDContentLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,40 +241,11 @@ const CNANDContentLoader& CNANDContentManager::GetNANDLoader(u64 title_id,
return GetNANDLoader(path);
}

bool CNANDContentManager::RemoveTitle(u64 title_id, Common::FromWhichRoot from)
{
auto& loader = GetNANDLoader(title_id, from);
if (!loader.IsValid())
return false;
loader.RemoveTitle();
return GetNANDLoader(title_id, from).IsValid();
}

void CNANDContentManager::ClearCache()
{
m_map.clear();
}

void CNANDContentLoader::RemoveTitle() const
{
const u64 title_id = m_tmd.GetTitleId();
INFO_LOG(DISCIO, "RemoveTitle %016" PRIx64, title_id);
if (IsValid())
{
// remove TMD?
for (const auto& content : m_Content)
{
if (!content.m_metadata.IsShared())
{
std::string path = StringFromFormat("%s/%08x.app", m_Path.c_str(), content.m_metadata.id);
INFO_LOG(DISCIO, "Delete %s", path.c_str());
File::Delete(path);
}
}
CNANDContentManager::Access().ClearCache(); // deletes 'this'
}
}

u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
{
if (filename.find(".wad") == std::string::npos)
Expand Down

0 comments on commit ea89e85

Please sign in to comment.