spl: Implement IGeneralInterface GetConfig (#2705)

* spl: Implement IGeneralInterface GetConfig

This PR implement the GetConfig call of the spl service. This is currently needed for some homebrews which currently needs Ignore Missing Service to boot. Now it's fixed.
Implementation was done using Atmosphère code and REing too.

* Addresses gdkchan feedback
This commit is contained in:
Ac_K 2021-10-12 22:15:55 +02:00 committed by GitHub
parent 380b95bc59
commit 0510fde25a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 227 additions and 2 deletions

View file

@ -1,4 +1,9 @@
namespace Ryujinx.HLE.HOS.Services.Sm
using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem.Content;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Services.Spl.Types;
namespace Ryujinx.HLE.HOS.Services.Spl
{
[Service("spl:")]
[Service("spl:es")]
@ -9,5 +14,114 @@
class IGeneralInterface : IpcService
{
public IGeneralInterface(ServiceCtx context) { }
[CommandHipc(0)]
// GetConfig(u32 config_item) -> u64 config_value
public ResultCode GetConfig(ServiceCtx context)
{
ConfigItem configItem = (ConfigItem)context.RequestData.ReadUInt32();
// NOTE: Nintendo explicitly blacklists package2 hash here, amusingly.
// This is not blacklisted in safemode, but we're never in safe mode...
if (configItem == ConfigItem.Package2Hash)
{
return ResultCode.InvalidArguments;
}
// TODO: This should call svcCallSecureMonitor using arg 0xC3000002.
// Since it's currently not implemented we can use a private method for now.
SmcResult result = SmcGetConfig(context, out ulong configValue, configItem);
// Nintendo has some special handling here for hardware type/is_retail.
if (result == SmcResult.InvalidArgument)
{
switch (configItem)
{
case ConfigItem.HardwareType:
configValue = (ulong)HardwareType.Icosa;
result = SmcResult.Success;
break;
case ConfigItem.HardwareState:
configValue = (ulong)HardwareState.Development;
result = SmcResult.Success;
break;
default:
break;
}
}
context.ResponseData.Write(configValue);
return (ResultCode)((int)result << 9) | ResultCode.ModuleId;
}
private SmcResult SmcGetConfig(ServiceCtx context, out ulong configValue, ConfigItem configItem)
{
configValue = default;
SystemVersion version = context.Device.System.ContentManager.GetCurrentFirmwareVersion();
MemorySize memorySize = context.Device.Configuration.MemoryConfiguration.ToKernelMemorySize();
switch (configItem)
{
case ConfigItem.DisableProgramVerification:
configValue = 0;
break;
case ConfigItem.DramId:
if (memorySize == MemorySize.MemorySize8GB)
{
configValue = (ulong)DramId.IowaSamsung8GB;
}
else if (memorySize == MemorySize.MemorySize6GB)
{
configValue = (ulong)DramId.IcosaSamsung6GB;
}
else
{
configValue = (ulong)DramId.IcosaSamsung4GB;
}
break;
case ConfigItem.SecurityEngineInterruptNumber:
return SmcResult.NotImplemented;
case ConfigItem.FuseVersion:
return SmcResult.NotImplemented;
case ConfigItem.HardwareType:
configValue = (ulong)HardwareType.Icosa;
break;
case ConfigItem.HardwareState:
configValue = (ulong)HardwareState.Production;
break;
case ConfigItem.IsRecoveryBoot:
configValue = 0;
break;
case ConfigItem.DeviceId:
return SmcResult.NotImplemented;
case ConfigItem.BootReason:
// This was removed in firmware 4.0.0.
return SmcResult.InvalidArgument;
case ConfigItem.MemoryMode:
configValue = (ulong)context.Device.Configuration.MemoryConfiguration;
break;
case ConfigItem.IsDevelopmentFunctionEnabled:
configValue = 0;
break;
case ConfigItem.KernelConfiguration:
return SmcResult.NotImplemented;
case ConfigItem.IsChargerHiZModeEnabled:
return SmcResult.NotImplemented;
case ConfigItem.QuestState:
return SmcResult.NotImplemented;
case ConfigItem.RegulatorType:
return SmcResult.NotImplemented;
case ConfigItem.DeviceUniqueKeyGeneration:
return SmcResult.NotImplemented;
case ConfigItem.Package2Hash:
return SmcResult.NotImplemented;
default:
return SmcResult.InvalidArgument;
}
return SmcResult.Success;
}
}
}

View file

@ -0,0 +1,12 @@
namespace Ryujinx.HLE.HOS.Services.Spl
{
enum ResultCode
{
ModuleId = 26,
ErrorCodeShift = 9,
Success = 0,
InvalidArguments = (101 << ErrorCodeShift) | ModuleId
}
}

View file

@ -0,0 +1,24 @@
namespace Ryujinx.HLE.HOS.Services.Spl.Types
{
enum ConfigItem
{
// Standard config items.
DisableProgramVerification = 1,
DramId = 2,
SecurityEngineInterruptNumber = 3,
FuseVersion = 4,
HardwareType = 5,
HardwareState = 6,
IsRecoveryBoot = 7,
DeviceId = 8,
BootReason = 9,
MemoryMode = 10,
IsDevelopmentFunctionEnabled = 11,
KernelConfiguration = 12,
IsChargerHiZModeEnabled = 13,
QuestState = 14,
RegulatorType = 15,
DeviceUniqueKeyGeneration = 16,
Package2Hash = 17
}
}

View file

@ -0,0 +1,35 @@
namespace Ryujinx.HLE.HOS.Services.Spl.Types
{
enum DramId
{
IcosaSamsung4GB,
IcosaHynix4GB,
IcosaMicron4GB,
IowaHynix1y4GB,
IcosaSamsung6GB,
HoagHynix1y4GB,
AulaHynix1y4GB,
IowaX1X2Samsung4GB,
IowaSansung4GB,
IowaSamsung8GB,
IowaHynix4GB,
IowaMicron4GB,
HoagSamsung4GB,
HoagSamsung8GB,
HoagHynix4GB,
HoagMicron4GB,
IowaSamsung4GBY,
IowaSamsung1y4GBX,
IowaSamsung1y8GBX,
HoagSamsung1y4GBX,
IowaSamsung1y4GBY,
IowaSamsung1y8GBY,
AulaSamsung1y4GB,
HoagSamsung1y8GBX,
AulaSamsung1y4GBX,
IowaMicron1y4GB,
HoagMicron1y4GB,
AulaMicron1y4GB,
AulaSamsung1y8GBX
}
}

View file

@ -0,0 +1,8 @@
namespace Ryujinx.HLE.HOS.Services.Spl.Types
{
enum HardwareState
{
Development,
Production
}
}

View file

@ -0,0 +1,12 @@
namespace Ryujinx.HLE.HOS.Services.Spl.Types
{
enum HardwareType
{
Icosa,
Copper,
Hoag,
Iowa,
Calcio,
Aula
}
}

View file

@ -0,0 +1,20 @@
namespace Ryujinx.HLE.HOS.Services.Spl.Types
{
enum SmcResult
{
Success = 0,
NotImplemented = 1,
InvalidArgument = 2,
Busy = 3,
NoAsyncOperation = 4,
InvalidAsyncOperation = 5,
NotPermitted = 6,
NotInitialized = 7,
PsciSuccess = 0,
PsciNotSupported = -1,
PsciInvalidParameters = -2,
PsciDenied = -3,
PsciAlreadyOn = -4
}
}