diff --git a/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs b/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs
index b4aebc7ea7..15625fc2e3 100644
--- a/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs
+++ b/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs
@@ -1,13 +1,127 @@
-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")]
     [Service("spl:fs")]
     [Service("spl:manu")]
     [Service("spl:mig")]
-    [Service("spl:ssl")] 
+    [Service("spl:ssl")]
     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;
+        }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Spl/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Spl/ResultCode.cs
new file mode 100644
index 0000000000..4f61998a69
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Spl/ResultCode.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.HLE.HOS.Services.Spl
+{
+    enum ResultCode
+    {
+        ModuleId       = 26,
+        ErrorCodeShift = 9,
+
+        Success = 0,
+
+        InvalidArguments = (101 << ErrorCodeShift) | ModuleId
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Spl/Types/ConfigItem.cs b/Ryujinx.HLE/HOS/Services/Spl/Types/ConfigItem.cs
new file mode 100644
index 0000000000..f08bbeaa31
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Spl/Types/ConfigItem.cs
@@ -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
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Spl/Types/DramId.cs b/Ryujinx.HLE/HOS/Services/Spl/Types/DramId.cs
new file mode 100644
index 0000000000..4e1d1f0e11
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Spl/Types/DramId.cs
@@ -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
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Spl/Types/HardwareState.cs b/Ryujinx.HLE/HOS/Services/Spl/Types/HardwareState.cs
new file mode 100644
index 0000000000..414d0f1182
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Spl/Types/HardwareState.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Spl.Types
+{
+    enum HardwareState
+    {
+        Development,
+        Production
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Spl/Types/HardwareType.cs b/Ryujinx.HLE/HOS/Services/Spl/Types/HardwareType.cs
new file mode 100644
index 0000000000..491eb943a8
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Spl/Types/HardwareType.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.HLE.HOS.Services.Spl.Types
+{
+    enum HardwareType
+    {
+        Icosa,
+        Copper,
+        Hoag,
+        Iowa,
+        Calcio,
+        Aula
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Spl/Types/SmcResult.cs b/Ryujinx.HLE/HOS/Services/Spl/Types/SmcResult.cs
new file mode 100644
index 0000000000..d5f424a631
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Spl/Types/SmcResult.cs
@@ -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
+    }
+}
\ No newline at end of file