mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-24 00:31:52 +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();
|
||||
}
|
||||
|
||||
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
|
||||
bool GetOverrideArgStr(std::vector<std::string>& args)
|
||||
{
|
||||
|
@ -4,6 +4,9 @@
|
||||
#include "Cafe/TitleList/TitleId.h"
|
||||
#include "config/CemuConfig.h"
|
||||
|
||||
enum class CosCapabilityBits : uint64;
|
||||
enum class CosCapabilityGroup : uint32;
|
||||
|
||||
namespace CafeSystem
|
||||
{
|
||||
class SystemImplementation
|
||||
@ -41,6 +44,7 @@ namespace CafeSystem
|
||||
std::string GetForegroundTitleName();
|
||||
std::string GetForegroundTitleArgStr();
|
||||
uint32 GetForegroundTitleOlvAccesskey();
|
||||
CosCapabilityBits GetForegroundTitleCosCapabilities(CosCapabilityGroup group);
|
||||
|
||||
void ShutdownTitle();
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "coreinit_IPC.h"
|
||||
#include "Cafe/Filesystem/fsc.h"
|
||||
#include "coreinit_IPCBuf.h"
|
||||
#include "Cafe/CafeSystem.h"
|
||||
#include "Cafe/TitleList/TitleInfo.h"
|
||||
|
||||
#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.
|
||||
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;
|
||||
strcpy(mountSourceInfo->path, "/sd");
|
||||
return FS_RESULT::SUCCESS;
|
||||
|
@ -1,13 +1,11 @@
|
||||
#include "TitleInfo.h"
|
||||
|
||||
#include "Cafe/Filesystem/fscDeviceHostFS.h"
|
||||
#include "Cafe/Filesystem/FST/FST.h"
|
||||
|
||||
#include "pugixml.hpp"
|
||||
#include "Common/FileStream.h"
|
||||
|
||||
#include <zarchive/zarchivereader.h>
|
||||
#include "config/ActiveSettings.h"
|
||||
#include "util/helpers/helpers.h"
|
||||
|
||||
// detect format by reading file header/footer
|
||||
CafeTitleFileType DetermineCafeSystemFileType(fs::path filePath)
|
||||
@ -709,10 +707,41 @@ std::string TitleInfo::GetInstallPath() const
|
||||
{
|
||||
TitleId titleId = GetAppTitleId();
|
||||
TitleIdParser tip(titleId);
|
||||
std::string tmp;
|
||||
std::string tmp;
|
||||
if (tip.IsSystemTitle())
|
||||
tmp = fmt::format("sys/title/{:08x}/{:08x}", GetTitleIdHigh(titleId), GetTitleIdLow(titleId));
|
||||
else
|
||||
tmp = fmt::format("usr/title/{:08x}/{:08x}", GetTitleIdHigh(titleId), GetTitleIdLow(titleId));
|
||||
tmp = fmt::format("sys/title/{:08x}/{:08x}", GetTitleIdHigh(titleId), GetTitleIdLow(titleId));
|
||||
else
|
||||
tmp = fmt::format("usr/title/{:08x}/{:08x}", GetTitleIdHigh(titleId), GetTitleIdLow(titleId));
|
||||
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;
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
||||
std::string argstr;
|
||||
|
||||
static ParsedCosXml* Parse(uint8* xmlData, size_t xmlLen)
|
||||
struct Permission
|
||||
{
|
||||
pugi::xml_document app_doc;
|
||||
if (!app_doc.load_buffer_inplace(xmlData, xmlLen))
|
||||
return nullptr;
|
||||
CosCapabilityGroup group{CosCapabilityGroup::None};
|
||||
CosCapabilityBits mask{CosCapabilityBits::All};
|
||||
};
|
||||
Permission permissions[19]{};
|
||||
|
||||
const auto root = app_doc.child("app");
|
||||
if (!root)
|
||||
return nullptr;
|
||||
static ParsedCosXml* Parse(uint8* xmlData, size_t xmlLen);
|
||||
|
||||
ParsedCosXml* parsedCos = new ParsedCosXml();
|
||||
|
||||
for (const auto& child : root.children())
|
||||
CosCapabilityBits GetCapabilityBits(CosCapabilityGroup group) const
|
||||
{
|
||||
for (const auto& perm : permissions)
|
||||
{
|
||||
std::string_view name = child.name();
|
||||
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
|
||||
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
|
||||
|
||||
TitleIdParser::TITLE_TYPE GetTitleType();
|
||||
@ -160,6 +226,11 @@ public:
|
||||
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 GetInstallPath() const; // installation subpath, relative to storage base. E.g. "usr/title/.../..." or "sys/title/.../..."
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user