mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-16 14:42:52 +00:00
IOS: Allow instances that are not tied to emulation
This enables constructing an IOS instance that is not tied to emulation and that can be simply used for internal purposes (ES, FS). NAND root initialisation was moved to IOS since we cannot rely on HW doing that for us anymore, and technically the NAND is entirely managed by IOS anyway.
This commit is contained in:
parent
f4e115b322
commit
12801fd722
@ -24,7 +24,6 @@
|
|||||||
#include "Core/IOS/IOS.h"
|
#include "Core/IOS/IOS.h"
|
||||||
#include "Core/Movie.h"
|
#include "Core/Movie.h"
|
||||||
#include "Core/State.h"
|
#include "Core/State.h"
|
||||||
#include "Core/WiiRoot.h"
|
|
||||||
|
|
||||||
namespace HW
|
namespace HW
|
||||||
{
|
{
|
||||||
@ -50,7 +49,6 @@ void Init()
|
|||||||
|
|
||||||
if (SConfig::GetInstance().bWii)
|
if (SConfig::GetInstance().bWii)
|
||||||
{
|
{
|
||||||
Core::InitializeWiiRoot(Core::WantsDeterminism());
|
|
||||||
IOS::Init();
|
IOS::Init();
|
||||||
IOS::HLE::Init(); // Depends on Memory
|
IOS::HLE::Init(); // Depends on Memory
|
||||||
}
|
}
|
||||||
@ -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 should always be shut down regardless of bWii because it can be running in GC mode (MIOS).
|
||||||
IOS::HLE::Shutdown(); // Depends on Memory
|
IOS::HLE::Shutdown(); // Depends on Memory
|
||||||
IOS::Shutdown();
|
IOS::Shutdown();
|
||||||
if (SConfig::GetInstance().bWii)
|
|
||||||
Core::ShutdownWiiRoot();
|
|
||||||
|
|
||||||
SystemTimers::Shutdown();
|
SystemTimers::Shutdown();
|
||||||
CPU::Shutdown();
|
CPU::Shutdown();
|
||||||
|
@ -51,13 +51,14 @@
|
|||||||
#include "Core/IOS/WFS/WFSI.h"
|
#include "Core/IOS/WFS/WFSI.h"
|
||||||
#include "Core/IOS/WFS/WFSSRV.h"
|
#include "Core/IOS/WFS/WFSSRV.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
#include "Core/WiiRoot.h"
|
||||||
#include "DiscIO/NANDContentLoader.h"
|
#include "DiscIO/NANDContentLoader.h"
|
||||||
|
|
||||||
namespace IOS
|
namespace IOS
|
||||||
{
|
{
|
||||||
namespace HLE
|
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_REQUEST_FLAG = 0x100000000ULL;
|
||||||
constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
|
constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
|
||||||
@ -172,29 +173,17 @@ constexpr u64 IOS80_TITLE_ID = 0x0000000100000050;
|
|||||||
constexpr u64 BC_TITLE_ID = 0x0000000100000100;
|
constexpr u64 BC_TITLE_ID = 0x0000000100000100;
|
||||||
constexpr u64 MIOS_TITLE_ID = 0x0000000100000101;
|
constexpr u64 MIOS_TITLE_ID = 0x0000000100000101;
|
||||||
|
|
||||||
Kernel::Kernel(u64 title_id) : m_title_id(title_id)
|
Kernel::Kernel()
|
||||||
{
|
{
|
||||||
INFO_LOG(IOS, "Starting IOS %016" PRIx64, title_id);
|
// 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.
|
||||||
if (!SetupMemory(title_id, MemorySetupType::IOSReload))
|
_assert_(GetIOS() == nullptr);
|
||||||
WARN_LOG(IOS, "No information about this IOS -- cannot set up memory values");
|
Core::InitializeWiiRoot(false);
|
||||||
|
AddCoreDevices();
|
||||||
if (title_id == MIOS_TITLE_ID)
|
|
||||||
{
|
|
||||||
MIOS::Load();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IOS re-inits IPC and sends a dummy ack during its boot process.
|
|
||||||
EnqueueIPCAcknowledgement(0);
|
|
||||||
|
|
||||||
AddStaticDevices();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::~Kernel()
|
Kernel::~Kernel()
|
||||||
{
|
{
|
||||||
CoreTiming::RemoveAllEvents(s_event_enqueue);
|
|
||||||
|
|
||||||
// Close all devices that were opened
|
// Close all devices that were opened
|
||||||
for (auto& device : m_fdmap)
|
for (auto& device : m_fdmap)
|
||||||
{
|
{
|
||||||
@ -207,6 +196,36 @@ Kernel::~Kernel()
|
|||||||
std::lock_guard<std::mutex> lock(m_device_map_mutex);
|
std::lock_guard<std::mutex> lock(m_device_map_mutex);
|
||||||
m_device_map.clear();
|
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();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IOS re-inits IPC and sends a dummy ack during its boot process.
|
||||||
|
EnqueueIPCAcknowledgement(0);
|
||||||
|
|
||||||
|
AddCoreDevices();
|
||||||
|
AddStaticDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulationKernel::~EmulationKernel()
|
||||||
|
{
|
||||||
|
CoreTiming::RemoveAllEvents(s_event_enqueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The title ID is a u64 where the first 32 bits are used for the title type.
|
// The title ID is a u64 where the first 32 bits are used for the title type.
|
||||||
@ -217,6 +236,16 @@ u32 Kernel::GetVersion() const
|
|||||||
return static_cast<u32>(m_title_id);
|
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.
|
// 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).
|
// These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC).
|
||||||
void Kernel::SetUidForPPC(u32 uid)
|
void Kernel::SetUidForPPC(u32 uid)
|
||||||
@ -289,7 +318,7 @@ bool Kernel::BootIOS(const u64 ios_title_id)
|
|||||||
|
|
||||||
// Shut down the active IOS first before switching to the new one.
|
// Shut down the active IOS first before switching to the new one.
|
||||||
s_ios.reset();
|
s_ios.reset();
|
||||||
s_ios = std::make_unique<Kernel>(ios_title_id);
|
s_ios = std::make_unique<EmulationKernel>(ios_title_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,10 +328,16 @@ void Kernel::AddDevice(std::unique_ptr<Device::Device> device)
|
|||||||
m_device_map[device->GetDeviceName()] = std::move(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()
|
void Kernel::AddStaticDevices()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_device_map_mutex);
|
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)
|
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
|
||||||
AddDevice(std::make_unique<Device::BluetoothEmu>(*this, "/dev/usb/oh1/57e/305"));
|
AddDevice(std::make_unique<Device::BluetoothEmu>(*this, "/dev/usb/oh1/57e/305"));
|
||||||
@ -311,8 +346,6 @@ void Kernel::AddStaticDevices()
|
|||||||
|
|
||||||
AddDevice(std::make_unique<Device::STMImmediate>(*this, "/dev/stm/immediate"));
|
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::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::DI>(*this, "/dev/di"));
|
||||||
AddDevice(std::make_unique<Device::NetKDRequest>(*this, "/dev/net/kd/request"));
|
AddDevice(std::make_unique<Device::NetKDRequest>(*this, "/dev/net/kd/request"));
|
||||||
AddDevice(std::make_unique<Device::NetKDTime>(*this, "/dev/net/kd/time"));
|
AddDevice(std::make_unique<Device::NetKDTime>(*this, "/dev/net/kd/time"));
|
||||||
@ -351,6 +384,11 @@ std::shared_ptr<Device::Device> Kernel::GetDeviceByName(const std::string& devic
|
|||||||
return iterator != m_device_map.end() ? iterator->second : nullptr;
|
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.
|
// Returns the FD for the newly opened device (on success) or an error code.
|
||||||
s32 Kernel::OpenDevice(OpenRequest& request)
|
s32 Kernel::OpenDevice(OpenRequest& request)
|
||||||
{
|
{
|
||||||
@ -639,7 +677,7 @@ void Init()
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Start with IOS80 to simulate part of the Wii boot process.
|
// 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
|
// 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.
|
// (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
|
// This means that the constants in the 0x3100 region are always set up by the time
|
||||||
@ -653,7 +691,7 @@ void Shutdown()
|
|||||||
s_ios.reset();
|
s_ios.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel* GetIOS()
|
EmulationKernel* GetIOS()
|
||||||
{
|
{
|
||||||
return s_ios.get();
|
return s_ios.get();
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ namespace HLE
|
|||||||
namespace Device
|
namespace Device
|
||||||
{
|
{
|
||||||
class Device;
|
class Device;
|
||||||
|
class ES;
|
||||||
|
class FS;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Request;
|
struct Request;
|
||||||
@ -84,8 +86,8 @@ enum ProcessId : u32
|
|||||||
class Kernel
|
class Kernel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Kernel(u64 ios_title_id);
|
Kernel();
|
||||||
~Kernel();
|
virtual ~Kernel();
|
||||||
|
|
||||||
void DoState(PointerWrap& p);
|
void DoState(PointerWrap& p);
|
||||||
void HandleIPCEvent(u64 userdata);
|
void HandleIPCEvent(u64 userdata);
|
||||||
@ -93,7 +95,11 @@ public:
|
|||||||
void UpdateDevices();
|
void UpdateDevices();
|
||||||
void UpdateWantDeterminism(bool new_want_determinism);
|
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 SDIO_EventNotify();
|
||||||
|
|
||||||
void EnqueueIPCRequest(u32 address);
|
void EnqueueIPCRequest(u32 address);
|
||||||
@ -111,13 +117,15 @@ public:
|
|||||||
|
|
||||||
IOSC& GetIOSC();
|
IOSC& GetIOSC();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void ExecuteIPCCommand(u32 address);
|
void ExecuteIPCCommand(u32 address);
|
||||||
IPCCommandResult HandleIPCCommand(const Request& request);
|
IPCCommandResult HandleIPCCommand(const Request& request);
|
||||||
void EnqueueIPCAcknowledgement(u32 address, int cycles_in_future = 0);
|
void EnqueueIPCAcknowledgement(u32 address, int cycles_in_future = 0);
|
||||||
|
|
||||||
void AddDevice(std::unique_ptr<Device::Device> device);
|
void AddDevice(std::unique_ptr<Device::Device> device);
|
||||||
|
void AddCoreDevices();
|
||||||
void AddStaticDevices();
|
void AddStaticDevices();
|
||||||
|
std::shared_ptr<Device::Device> GetDeviceByName(const std::string& device_name);
|
||||||
s32 GetFreeDeviceID();
|
s32 GetFreeDeviceID();
|
||||||
s32 OpenDevice(OpenRequest& request);
|
s32 OpenDevice(OpenRequest& request);
|
||||||
|
|
||||||
@ -140,10 +148,22 @@ private:
|
|||||||
IOSC m_iosc;
|
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.
|
// Used for controlling and accessing an IOS instance that is tied to emulation.
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
Kernel* GetIOS();
|
EmulationKernel* GetIOS();
|
||||||
|
|
||||||
} // namespace HLE
|
} // namespace HLE
|
||||||
} // namespace IOS
|
} // namespace IOS
|
||||||
|
@ -45,7 +45,7 @@ OH0Device::OH0Device(Kernel& ios, const std::string& name) : Device(ios, name, D
|
|||||||
|
|
||||||
void OH0Device::DoState(PointerWrap& p)
|
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_name);
|
||||||
p.Do(m_vid);
|
p.Do(m_vid);
|
||||||
p.Do(m_pid);
|
p.Do(m_pid);
|
||||||
@ -61,7 +61,7 @@ ReturnCode OH0Device::Open(const OpenRequest& request)
|
|||||||
if (m_vid == 0 && m_pid == 0)
|
if (m_vid == 0 && m_pid == 0)
|
||||||
return IPC_ENOENT;
|
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;
|
ReturnCode return_code;
|
||||||
std::tie(return_code, m_device_id) = m_oh0->DeviceOpen(m_vid, m_pid);
|
std::tie(return_code, m_device_id) = m_oh0->DeviceOpen(m_vid, m_pid);
|
||||||
|
@ -109,7 +109,7 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
|||||||
Memory::CopyFromEmu(tmd_bytes.data(), tmd_addr, tmd_size);
|
Memory::CopyFromEmu(tmd_bytes.data(), tmd_addr, tmd_size);
|
||||||
m_tmd.SetBytes(std::move(tmd_bytes));
|
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())
|
if (!ticket.IsValid())
|
||||||
{
|
{
|
||||||
return_error_code = -11028;
|
return_error_code = -11028;
|
||||||
@ -134,7 +134,7 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
|
|||||||
|
|
||||||
// Initializes the IV from the index of the content in the TMD contents.
|
// Initializes the IV from the index of the content in the TMD contents.
|
||||||
u32 content_id = Memory::Read_U32(request.buffer_in + 8);
|
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))
|
if (!m_tmd.FindContentById(content_id, &content_info))
|
||||||
{
|
{
|
||||||
WARN_LOG(IOS, "%s: Content id %08x not found", ioctl_name, content_id);
|
WARN_LOG(IOS, "%s: Content id %08x not found", ioctl_name, content_id);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user