mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-22 17:19:18 +01:00
coreinit: Handle SD mounting permission in FSGetMountSource
One Piece requires this to not get stuck in an infinite loop on boot. This also sets up initial infrastructure for handling cos.xml permissions
This commit is contained in:
parent
fde7230191
commit
74e8d205b0
@ -914,6 +914,27 @@ namespace CafeSystem
|
|||||||
return sGameInfo_ForegroundTitle.GetBase().GetArgStr();
|
return sGameInfo_ForegroundTitle.GetBase().GetArgStr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CosCapabilityBits GetForegroundTitleCosCapabilities(CosCapabilityGroup group)
|
||||||
|
{
|
||||||
|
if (sLaunchModeIsStandalone)
|
||||||
|
return CosCapabilityBits::All;
|
||||||
|
auto& update = sGameInfo_ForegroundTitle.GetUpdate();
|
||||||
|
if (update.IsValid())
|
||||||
|
{
|
||||||
|
ParsedCosXml* cosXml = update.GetCosInfo();
|
||||||
|
if (cosXml)
|
||||||
|
return cosXml->GetCapabilityBits(group);
|
||||||
|
}
|
||||||
|
auto& base = sGameInfo_ForegroundTitle.GetBase();
|
||||||
|
if(base.IsValid())
|
||||||
|
{
|
||||||
|
ParsedCosXml* cosXml = base.GetCosInfo();
|
||||||
|
if (cosXml)
|
||||||
|
return cosXml->GetCapabilityBits(group);
|
||||||
|
}
|
||||||
|
return CosCapabilityBits::All;
|
||||||
|
}
|
||||||
|
|
||||||
// when switching titles custom parameters can be passed, returns true if override args are used
|
// when switching titles custom parameters can be passed, returns true if override args are used
|
||||||
bool GetOverrideArgStr(std::vector<std::string>& args)
|
bool GetOverrideArgStr(std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
#include "Cafe/TitleList/TitleId.h"
|
#include "Cafe/TitleList/TitleId.h"
|
||||||
#include "config/CemuConfig.h"
|
#include "config/CemuConfig.h"
|
||||||
|
|
||||||
|
enum class CosCapabilityBits : uint64;
|
||||||
|
enum class CosCapabilityGroup : uint32;
|
||||||
|
|
||||||
namespace CafeSystem
|
namespace CafeSystem
|
||||||
{
|
{
|
||||||
class SystemImplementation
|
class SystemImplementation
|
||||||
@ -41,6 +44,7 @@ namespace CafeSystem
|
|||||||
std::string GetForegroundTitleName();
|
std::string GetForegroundTitleName();
|
||||||
std::string GetForegroundTitleArgStr();
|
std::string GetForegroundTitleArgStr();
|
||||||
uint32 GetForegroundTitleOlvAccesskey();
|
uint32 GetForegroundTitleOlvAccesskey();
|
||||||
|
CosCapabilityBits GetForegroundTitleCosCapabilities(CosCapabilityGroup group);
|
||||||
|
|
||||||
void ShutdownTitle();
|
void ShutdownTitle();
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include "coreinit_IPC.h"
|
#include "coreinit_IPC.h"
|
||||||
#include "Cafe/Filesystem/fsc.h"
|
#include "Cafe/Filesystem/fsc.h"
|
||||||
#include "coreinit_IPCBuf.h"
|
#include "coreinit_IPCBuf.h"
|
||||||
|
#include "Cafe/CafeSystem.h"
|
||||||
|
#include "Cafe/TitleList/TitleInfo.h"
|
||||||
|
|
||||||
#define FS_CB_PLACEHOLDER_FINISHCMD (MPTR)(0xF122330E)
|
#define FS_CB_PLACEHOLDER_FINISHCMD (MPTR)(0xF122330E)
|
||||||
|
|
||||||
@ -94,6 +96,14 @@ namespace coreinit
|
|||||||
// so we can just hard code it. Other mount types are not (yet) supported.
|
// so we can just hard code it. Other mount types are not (yet) supported.
|
||||||
if (mountSourceType == MOUNT_TYPE::SD)
|
if (mountSourceType == MOUNT_TYPE::SD)
|
||||||
{
|
{
|
||||||
|
// check for SD card permissions (from cos.xml)
|
||||||
|
// One Piece relies on failing here, otherwise it will call FSGetMountSource in an infinite loop
|
||||||
|
CosCapabilityBitsFS perms = static_cast<CosCapabilityBitsFS>(CafeSystem::GetForegroundTitleCosCapabilities(CosCapabilityGroup::FS));
|
||||||
|
if(!HAS_FLAG(perms, CosCapabilityBitsFS::SDCARD_MOUNT))
|
||||||
|
{
|
||||||
|
cemuLog_logOnce(LogType::Force, "Title is trying to access SD card mount info without having SD card permissions. This may not be a bug");
|
||||||
|
return FS_RESULT::END_ITERATION;
|
||||||
|
}
|
||||||
mountSourceInfo->sourceType = 0;
|
mountSourceInfo->sourceType = 0;
|
||||||
strcpy(mountSourceInfo->path, "/sd");
|
strcpy(mountSourceInfo->path, "/sd");
|
||||||
return FS_RESULT::SUCCESS;
|
return FS_RESULT::SUCCESS;
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
#include "TitleInfo.h"
|
#include "TitleInfo.h"
|
||||||
|
|
||||||
#include "Cafe/Filesystem/fscDeviceHostFS.h"
|
#include "Cafe/Filesystem/fscDeviceHostFS.h"
|
||||||
#include "Cafe/Filesystem/FST/FST.h"
|
#include "Cafe/Filesystem/FST/FST.h"
|
||||||
|
|
||||||
#include "pugixml.hpp"
|
#include "pugixml.hpp"
|
||||||
#include "Common/FileStream.h"
|
#include "Common/FileStream.h"
|
||||||
|
|
||||||
#include <zarchive/zarchivereader.h>
|
#include <zarchive/zarchivereader.h>
|
||||||
#include "config/ActiveSettings.h"
|
#include "config/ActiveSettings.h"
|
||||||
|
#include "util/helpers/helpers.h"
|
||||||
|
|
||||||
// detect format by reading file header/footer
|
// detect format by reading file header/footer
|
||||||
CafeTitleFileType DetermineCafeSystemFileType(fs::path filePath)
|
CafeTitleFileType DetermineCafeSystemFileType(fs::path filePath)
|
||||||
@ -716,3 +714,34 @@ std::string TitleInfo::GetInstallPath() const
|
|||||||
tmp = fmt::format("usr/title/{:08x}/{:08x}", GetTitleIdHigh(titleId), GetTitleIdLow(titleId));
|
tmp = fmt::format("usr/title/{:08x}/{:08x}", GetTitleIdHigh(titleId), GetTitleIdLow(titleId));
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParsedCosXml* ParsedCosXml::Parse(uint8* xmlData, size_t xmlLen)
|
||||||
|
{
|
||||||
|
pugi::xml_document app_doc;
|
||||||
|
if (!app_doc.load_buffer_inplace(xmlData, xmlLen))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const auto root = app_doc.child("app");
|
||||||
|
if (!root)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
ParsedCosXml* parsedCos = new ParsedCosXml();
|
||||||
|
|
||||||
|
auto node = root.child("argstr");
|
||||||
|
if (node)
|
||||||
|
parsedCos->argstr = node.text().as_string();
|
||||||
|
|
||||||
|
// parse permissions
|
||||||
|
auto permissionsNode = root.child("permissions");
|
||||||
|
for(uint32 permissionIndex = 0; permissionIndex < 19; ++permissionIndex)
|
||||||
|
{
|
||||||
|
std::string permissionName = fmt::format("p{}", permissionIndex);
|
||||||
|
auto permissionNode = permissionsNode.child(permissionName.c_str());
|
||||||
|
if (!permissionNode)
|
||||||
|
break;
|
||||||
|
parsedCos->permissions[permissionIndex].group = static_cast<CosCapabilityGroup>(ConvertString<uint32>(permissionNode.child("group").text().as_string(), 10));
|
||||||
|
parsedCos->permissions[permissionIndex].mask = static_cast<CosCapabilityBits>(ConvertString<uint64>(permissionNode.child("mask").text().as_string(), 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedCos;
|
||||||
|
}
|
@ -26,29 +26,95 @@ struct ParsedAppXml
|
|||||||
uint32 sdk_version;
|
uint32 sdk_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class CosCapabilityGroup : uint32
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
BSP = 1,
|
||||||
|
DK = 3,
|
||||||
|
USB = 9,
|
||||||
|
UHS = 12,
|
||||||
|
FS = 11,
|
||||||
|
MCP = 13,
|
||||||
|
NIM = 14,
|
||||||
|
ACT = 15,
|
||||||
|
FPD = 16,
|
||||||
|
BOSS = 17,
|
||||||
|
ACP = 18,
|
||||||
|
PDM = 19,
|
||||||
|
AC = 20,
|
||||||
|
NDM = 21,
|
||||||
|
NSEC = 22
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class CosCapabilityBits : uint64
|
||||||
|
{
|
||||||
|
All = 0xFFFFFFFFFFFFFFFFull
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class CosCapabilityBitsFS : uint64
|
||||||
|
{
|
||||||
|
ODD_READ = (1llu << 0),
|
||||||
|
ODD_WRITE = (1llu << 1),
|
||||||
|
ODD_RAW_OPEN = (1llu << 2),
|
||||||
|
ODD_MOUNT = (1llu << 3),
|
||||||
|
SLCCMPT_READ = (1llu << 4),
|
||||||
|
SLCCMPT_WRITE = (1llu << 5),
|
||||||
|
SLCCMPT_RAW_OPEN = (1llu << 6),
|
||||||
|
SLCCMPT_MOUNT = (1llu << 7),
|
||||||
|
SLC_READ = (1llu << 8),
|
||||||
|
SLC_WRITE = (1llu << 9),
|
||||||
|
SLC_RAW_OPEN = (1llu << 10),
|
||||||
|
SLC_MOUNT = (1llu << 11),
|
||||||
|
MLC_READ = (1llu << 12),
|
||||||
|
MLC_WRITE = (1llu << 13),
|
||||||
|
MLC_RAW_OPEN = (1llu << 14),
|
||||||
|
MLC_MOUNT = (1llu << 15),
|
||||||
|
SDCARD_READ = (1llu << 16),
|
||||||
|
SDCARD_WRITE = (1llu << 17),
|
||||||
|
SDCARD_RAW_OPEN = (1llu << 18),
|
||||||
|
SDCARD_MOUNT = (1llu << 19),
|
||||||
|
HFIO_READ = (1llu << 20),
|
||||||
|
HFIO_WRITE = (1llu << 21),
|
||||||
|
HFIO_RAW_OPEN = (1llu << 22),
|
||||||
|
HFIO_MOUNT = (1llu << 23),
|
||||||
|
RAMDISK_READ = (1llu << 24),
|
||||||
|
RAMDISK_WRITE = (1llu << 25),
|
||||||
|
RAMDISK_RAW_OPEN = (1llu << 26),
|
||||||
|
RAMDISK_MOUNT = (1llu << 27),
|
||||||
|
USB_READ = (1llu << 28),
|
||||||
|
USB_WRITE = (1llu << 29),
|
||||||
|
USB_RAW_OPEN = (1llu << 30),
|
||||||
|
USB_MOUNT = (1llu << 31),
|
||||||
|
OTHER_READ = (1llu << 32),
|
||||||
|
OTHER_WRITE = (1llu << 33),
|
||||||
|
OTHER_RAW_OPEN = (1llu << 34),
|
||||||
|
OTHER_MOUNT = (1llu << 35)
|
||||||
|
};
|
||||||
|
ENABLE_BITMASK_OPERATORS(CosCapabilityBitsFS);
|
||||||
|
|
||||||
struct ParsedCosXml
|
struct ParsedCosXml
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
std::string argstr;
|
std::string argstr;
|
||||||
|
|
||||||
static ParsedCosXml* Parse(uint8* xmlData, size_t xmlLen)
|
struct Permission
|
||||||
{
|
{
|
||||||
pugi::xml_document app_doc;
|
CosCapabilityGroup group{CosCapabilityGroup::None};
|
||||||
if (!app_doc.load_buffer_inplace(xmlData, xmlLen))
|
CosCapabilityBits mask{CosCapabilityBits::All};
|
||||||
return nullptr;
|
};
|
||||||
|
Permission permissions[19]{};
|
||||||
|
|
||||||
const auto root = app_doc.child("app");
|
static ParsedCosXml* Parse(uint8* xmlData, size_t xmlLen);
|
||||||
if (!root)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
ParsedCosXml* parsedCos = new ParsedCosXml();
|
CosCapabilityBits GetCapabilityBits(CosCapabilityGroup group) const
|
||||||
|
|
||||||
for (const auto& child : root.children())
|
|
||||||
{
|
{
|
||||||
std::string_view name = child.name();
|
for (const auto& perm : permissions)
|
||||||
if (name == "argstr")
|
{
|
||||||
parsedCos->argstr = child.text().as_string();
|
if (perm.group == group)
|
||||||
|
return perm.mask;
|
||||||
}
|
}
|
||||||
return parsedCos;
|
return CosCapabilityBits::All;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -151,7 +217,7 @@ public:
|
|||||||
// cos.xml
|
// cos.xml
|
||||||
std::string GetArgStr() const;
|
std::string GetArgStr() const;
|
||||||
|
|
||||||
// meta.xml also contains a version which seems to match the one from app.xml
|
// meta.xml also contains a version field which seems to match the one from app.xml
|
||||||
// the titleId in meta.xml seems to be the title id of the base game for updates specifically. For AOC content it's the AOC's titleId
|
// the titleId in meta.xml seems to be the title id of the base game for updates specifically. For AOC content it's the AOC's titleId
|
||||||
|
|
||||||
TitleIdParser::TITLE_TYPE GetTitleType();
|
TitleIdParser::TITLE_TYPE GetTitleType();
|
||||||
@ -160,6 +226,11 @@ public:
|
|||||||
return m_parsedMetaXml;
|
return m_parsedMetaXml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParsedCosXml* GetCosInfo()
|
||||||
|
{
|
||||||
|
return m_parsedCosXml;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetPrintPath() const; // formatted path including type and WUA subpath. Intended for logging and user-facing information
|
std::string GetPrintPath() const; // formatted path including type and WUA subpath. Intended for logging and user-facing information
|
||||||
std::string GetInstallPath() const; // installation subpath, relative to storage base. E.g. "usr/title/.../..." or "sys/title/.../..."
|
std::string GetInstallPath() const; // installation subpath, relative to storage base. E.g. "usr/title/.../..." or "sys/title/.../..."
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user