diff --git a/src/common/common_sizes.h b/src/common/common_sizes.h
index 26425a57dc..a6500bddda 100644
--- a/src/common/common_sizes.h
+++ b/src/common/common_sizes.h
@@ -12,11 +12,21 @@ enum : u64 {
     Size_4_MB = 4ULL * Size_1_MB,
     Size_14_MB = 14ULL * Size_1_MB,
     Size_32_MB = 32ULL * Size_1_MB,
+    Size_33_MB = 33ULL * Size_1_MB,
     Size_128_MB = 128ULL * Size_1_MB,
+    Size_448_MB = 448ULL * Size_1_MB,
+    Size_507_MB = 507ULL * Size_1_MB,
+    Size_562_MB = 562ULL * Size_1_MB,
+    Size_1554_MB = 1554ULL * Size_1_MB,
+    Size_2048_MB = 2048ULL * Size_1_MB,
+    Size_2193_MB = 2193ULL * Size_1_MB,
+    Size_3285_MB = 3285ULL * Size_1_MB,
+    Size_4916_MB = 4916ULL * Size_1_MB,
     Size_1_GB = 0x40000000ULL,
     Size_2_GB = 2ULL * Size_1_GB,
     Size_4_GB = 4ULL * Size_1_GB,
     Size_6_GB = 6ULL * Size_1_GB,
+    Size_8_GB = 8ULL * Size_1_GB,
     Size_64_GB = 64ULL * Size_1_GB,
     Size_512_GB = 512ULL * Size_1_GB,
     Invalid = std::numeric_limits<u64>::max(),
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
index 0f41c41106..a48d0c11ed 100644
--- a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
+++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
@@ -4,14 +4,132 @@
 
 #include <random>
 
-#include "core/hle/kernel/k_system_control.h"
+#include "common/common_sizes.h"
+#include "core/hle/kernel/board/nintendo/nx/k_system_control.h"
+#include "core/hle/kernel/board/nintendo/nx/secure_monitor.h"
+#include "core/hle/kernel/k_trace.h"
 
 namespace Kernel::Board::Nintendo::Nx {
 
+namespace impl {
+
+constexpr inline const std::size_t RequiredNonSecureSystemMemorySizeVi = 0x2238 * 4 * 1024;
+constexpr inline const std::size_t RequiredNonSecureSystemMemorySizeNvservices = 0x710 * 4 * 1024;
+constexpr inline const std::size_t RequiredNonSecureSystemMemorySizeMisc = 0x80 * 4 * 1024;
+
+} // namespace impl
+
+constexpr inline const std::size_t RequiredNonSecureSystemMemorySize =
+    impl::RequiredNonSecureSystemMemorySizeVi + impl::RequiredNonSecureSystemMemorySizeNvservices +
+    impl::RequiredNonSecureSystemMemorySizeMisc;
+
+namespace {
+
+u32 GetMemoryModeForInit() {
+    return 0x01;
+}
+
+u32 GetMemorySizeForInit() {
+    return 0;
+}
+
+Smc::MemoryArrangement GetMemoryArrangeForInit() {
+    switch (GetMemoryModeForInit() & 0x3F) {
+    case 0x01:
+    default:
+        return Smc::MemoryArrangement_4GB;
+    case 0x02:
+        return Smc::MemoryArrangement_4GBForAppletDev;
+    case 0x03:
+        return Smc::MemoryArrangement_4GBForSystemDev;
+    case 0x11:
+        return Smc::MemoryArrangement_6GB;
+    case 0x12:
+        return Smc::MemoryArrangement_6GBForAppletDev;
+    case 0x21:
+        return Smc::MemoryArrangement_8GB;
+    }
+}
+} // namespace
+
+// Initialization.
+size_t KSystemControl::Init::GetIntendedMemorySize() {
+    switch (GetMemorySizeForInit()) {
+    case Smc::MemorySize_4GB:
+    default: // All invalid modes should go to 4GB.
+        return Size_4_GB;
+    case Smc::MemorySize_6GB:
+        return Size_6_GB;
+    case Smc::MemorySize_8GB:
+        return Size_8_GB;
+    }
+}
+
+PAddr KSystemControl::Init::GetKernelPhysicalBaseAddress(u64 base_address) {
+    return base_address;
+}
+
 bool KSystemControl::Init::ShouldIncreaseThreadResourceLimit() {
     return true;
 }
 
+std::size_t KSystemControl::Init::GetApplicationPoolSize() {
+    // Get the base pool size.
+    const size_t base_pool_size = []() -> size_t {
+        switch (GetMemoryArrangeForInit()) {
+        case Smc::MemoryArrangement_4GB:
+        default:
+            return Size_3285_MB;
+        case Smc::MemoryArrangement_4GBForAppletDev:
+            return Size_2048_MB;
+        case Smc::MemoryArrangement_4GBForSystemDev:
+            return Size_3285_MB;
+        case Smc::MemoryArrangement_6GB:
+            return Size_4916_MB;
+        case Smc::MemoryArrangement_6GBForAppletDev:
+            return Size_3285_MB;
+        case Smc::MemoryArrangement_8GB:
+            return Size_4916_MB;
+        }
+    }();
+
+    // Return (possibly) adjusted size.
+    return base_pool_size;
+}
+
+size_t KSystemControl::Init::GetAppletPoolSize() {
+    // Get the base pool size.
+    const size_t base_pool_size = []() -> size_t {
+        switch (GetMemoryArrangeForInit()) {
+        case Smc::MemoryArrangement_4GB:
+        default:
+            return Size_507_MB;
+        case Smc::MemoryArrangement_4GBForAppletDev:
+            return Size_1554_MB;
+        case Smc::MemoryArrangement_4GBForSystemDev:
+            return Size_448_MB;
+        case Smc::MemoryArrangement_6GB:
+            return Size_562_MB;
+        case Smc::MemoryArrangement_6GBForAppletDev:
+            return Size_2193_MB;
+        case Smc::MemoryArrangement_8GB:
+            return Size_2193_MB;
+        }
+    }();
+
+    // Return (possibly) adjusted size.
+    constexpr size_t ExtraSystemMemoryForAtmosphere = Size_33_MB;
+    return base_pool_size - ExtraSystemMemoryForAtmosphere - KTraceBufferSize;
+}
+
+size_t KSystemControl::Init::GetMinimumNonSecureSystemPoolSize() {
+    // Verify that our minimum is at least as large as Nintendo's.
+    constexpr size_t MinimumSize = RequiredNonSecureSystemMemorySize;
+    static_assert(MinimumSize >= 0x29C8000);
+
+    return MinimumSize;
+}
+
 namespace {
 template <typename F>
 u64 GenerateUniformRange(u64 min, u64 max, F f) {
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.h b/src/core/hle/kernel/board/nintendo/nx/k_system_control.h
index 3fde619717..52f230cede 100644
--- a/src/core/hle/kernel/board/nintendo/nx/k_system_control.h
+++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.h
@@ -12,7 +12,13 @@ class KSystemControl {
 public:
     class Init {
     public:
+        // Initialization.
+        static std::size_t GetIntendedMemorySize();
+        static PAddr GetKernelPhysicalBaseAddress(u64 base_address);
         static bool ShouldIncreaseThreadResourceLimit();
+        static std::size_t GetApplicationPoolSize();
+        static std::size_t GetAppletPoolSize();
+        static std::size_t GetMinimumNonSecureSystemPoolSize();
     };
 
     static u64 GenerateRandomRange(u64 min, u64 max);