فهرست منبع

Merge pull request #6472 from Morph1984/spl

service: spl: Implement general SPL service
bunnei 5 سال پیش
والد
کامیت
255f8d22d7

+ 3 - 0
src/core/CMakeLists.txt

@@ -139,6 +139,7 @@ add_library(core STATIC
     frontend/input.h
     hardware_interrupt_manager.cpp
     hardware_interrupt_manager.h
+    hle/api_version.h
     hle/ipc.h
     hle/ipc_helpers.h
     hle/kernel/board/nintendo/nx/k_system_control.cpp
@@ -550,6 +551,8 @@ add_library(core STATIC
     hle/service/spl/module.h
     hle/service/spl/spl.cpp
     hle/service/spl/spl.h
+    hle/service/spl/spl_results.h
+    hle/service/spl/spl_types.h
     hle/service/ssl/ssl.cpp
     hle/service/ssl/ssl.h
     hle/service/time/clock_types.h

+ 15 - 33
src/core/file_sys/system_archive/system_version.cpp

@@ -4,47 +4,29 @@
 
 #include "core/file_sys/system_archive/system_version.h"
 #include "core/file_sys/vfs_vector.h"
+#include "core/hle/api_version.h"
 
 namespace FileSys::SystemArchive {
 
-namespace SystemVersionData {
-
-// This section should reflect the best system version to describe yuzu's HLE api.
-// TODO(DarkLordZach): Update when HLE gets better.
-
-constexpr u8 VERSION_MAJOR = 11;
-constexpr u8 VERSION_MINOR = 0;
-constexpr u8 VERSION_MICRO = 1;
-
-constexpr u8 REVISION_MAJOR = 1;
-constexpr u8 REVISION_MINOR = 0;
-
-constexpr char PLATFORM_STRING[] = "NX";
-constexpr char VERSION_HASH[] = "69103fcb2004dace877094c2f8c29e6113be5dbf";
-constexpr char DISPLAY_VERSION[] = "11.0.1";
-constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.1-1.0";
-
-} // namespace SystemVersionData
-
 std::string GetLongDisplayVersion() {
-    return SystemVersionData::DISPLAY_TITLE;
+    return HLE::ApiVersion::DISPLAY_TITLE;
 }
 
 VirtualDir SystemVersion() {
     VirtualFile file = std::make_shared<VectorVfsFile>(std::vector<u8>(0x100), "file");
-    file->WriteObject(SystemVersionData::VERSION_MAJOR, 0);
-    file->WriteObject(SystemVersionData::VERSION_MINOR, 1);
-    file->WriteObject(SystemVersionData::VERSION_MICRO, 2);
-    file->WriteObject(SystemVersionData::REVISION_MAJOR, 4);
-    file->WriteObject(SystemVersionData::REVISION_MINOR, 5);
-    file->WriteArray(SystemVersionData::PLATFORM_STRING,
-                     std::min<u64>(sizeof(SystemVersionData::PLATFORM_STRING), 0x20ULL), 0x8);
-    file->WriteArray(SystemVersionData::VERSION_HASH,
-                     std::min<u64>(sizeof(SystemVersionData::VERSION_HASH), 0x40ULL), 0x28);
-    file->WriteArray(SystemVersionData::DISPLAY_VERSION,
-                     std::min<u64>(sizeof(SystemVersionData::DISPLAY_VERSION), 0x18ULL), 0x68);
-    file->WriteArray(SystemVersionData::DISPLAY_TITLE,
-                     std::min<u64>(sizeof(SystemVersionData::DISPLAY_TITLE), 0x80ULL), 0x80);
+    file->WriteObject(HLE::ApiVersion::HOS_VERSION_MAJOR, 0);
+    file->WriteObject(HLE::ApiVersion::HOS_VERSION_MINOR, 1);
+    file->WriteObject(HLE::ApiVersion::HOS_VERSION_MICRO, 2);
+    file->WriteObject(HLE::ApiVersion::SDK_REVISION_MAJOR, 4);
+    file->WriteObject(HLE::ApiVersion::SDK_REVISION_MINOR, 5);
+    file->WriteArray(HLE::ApiVersion::PLATFORM_STRING,
+                     std::min<u64>(sizeof(HLE::ApiVersion::PLATFORM_STRING), 0x20ULL), 0x8);
+    file->WriteArray(HLE::ApiVersion::VERSION_HASH,
+                     std::min<u64>(sizeof(HLE::ApiVersion::VERSION_HASH), 0x40ULL), 0x28);
+    file->WriteArray(HLE::ApiVersion::DISPLAY_VERSION,
+                     std::min<u64>(sizeof(HLE::ApiVersion::DISPLAY_VERSION), 0x18ULL), 0x68);
+    file->WriteArray(HLE::ApiVersion::DISPLAY_TITLE,
+                     std::min<u64>(sizeof(HLE::ApiVersion::DISPLAY_TITLE), 0x80ULL), 0x80);
     return std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{file},
                                                 std::vector<VirtualDir>{}, "data");
 }

+ 38 - 0
src/core/hle/api_version.h

@@ -0,0 +1,38 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/common_types.h"
+
+// This file contains yuzu's HLE API version constants.
+
+namespace HLE::ApiVersion {
+
+// Horizon OS version constants.
+
+constexpr u8 HOS_VERSION_MAJOR = 11;
+constexpr u8 HOS_VERSION_MINOR = 0;
+constexpr u8 HOS_VERSION_MICRO = 1;
+
+// NintendoSDK version constants.
+
+constexpr u8 SDK_REVISION_MAJOR = 1;
+constexpr u8 SDK_REVISION_MINOR = 0;
+
+constexpr char PLATFORM_STRING[] = "NX";
+constexpr char VERSION_HASH[] = "69103fcb2004dace877094c2f8c29e6113be5dbf";
+constexpr char DISPLAY_VERSION[] = "11.0.1";
+constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.1-1.0";
+
+// Atmosphere version constants.
+
+constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 0;
+constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 19;
+constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 4;
+
+constexpr u32 GetTargetFirmware() {
+    return u32{HOS_VERSION_MAJOR} << 24 | u32{HOS_VERSION_MINOR} << 16 |
+           u32{HOS_VERSION_MICRO} << 8 | 0U;
+}
+
+} // namespace HLE::ApiVersion

+ 1 - 1
src/core/hle/service/spl/csrng.cpp

@@ -9,7 +9,7 @@ namespace Service::SPL {
 CSRNG::CSRNG(Core::System& system_, std::shared_ptr<Module> module_)
     : Interface(system_, std::move(module_), "csrng") {
     static const FunctionInfo functions[] = {
-        {0, &CSRNG::GetRandomBytes, "GetRandomBytes"},
+        {0, &CSRNG::GenerateRandomBytes, "GenerateRandomBytes"},
     };
     RegisterHandlers(functions);
 }

+ 123 - 1
src/core/hle/service/spl/module.cpp

@@ -10,6 +10,7 @@
 #include <vector>
 #include "common/logging/log.h"
 #include "common/settings.h"
+#include "core/hle/api_version.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/spl/csrng.h"
 #include "core/hle/service/spl/module.h"
@@ -24,7 +25,46 @@ Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> modu
 
 Module::Interface::~Interface() = default;
 
-void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) {
+void Module::Interface::GetConfig(Kernel::HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto config_item = rp.PopEnum<ConfigItem>();
+
+    // This should call svcCallSecureMonitor with the appropriate args.
+    // Since we do not have it implemented yet, we will use this for now.
+    const auto smc_result = GetConfigImpl(config_item);
+    const auto result_code = smc_result.Code();
+
+    if (smc_result.Failed()) {
+        LOG_ERROR(Service_SPL, "called, config_item={}, result_code={}", config_item,
+                  result_code.raw);
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(result_code);
+    }
+
+    LOG_DEBUG(Service_SPL, "called, config_item={}, result_code={}, smc_result={}", config_item,
+              result_code.raw, *smc_result);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(result_code);
+    rb.Push(*smc_result);
+}
+
+void Module::Interface::ModularExponentiate(Kernel::HLERequestContext& ctx) {
+    UNIMPLEMENTED_MSG("ModularExponentiate is not implemented!");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSecureMonitorNotImplemented);
+}
+
+void Module::Interface::SetConfig(Kernel::HLERequestContext& ctx) {
+    UNIMPLEMENTED_MSG("SetConfig is not implemented!");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSecureMonitorNotImplemented);
+}
+
+void Module::Interface::GenerateRandomBytes(Kernel::HLERequestContext& ctx) {
     LOG_DEBUG(Service_SPL, "called");
 
     const std::size_t size = ctx.GetWriteBufferSize();
@@ -39,6 +79,88 @@ void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) {
     rb.Push(ResultSuccess);
 }
 
+void Module::Interface::IsDevelopment(Kernel::HLERequestContext& ctx) {
+    UNIMPLEMENTED_MSG("IsDevelopment is not implemented!");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSecureMonitorNotImplemented);
+}
+
+void Module::Interface::SetBootReason(Kernel::HLERequestContext& ctx) {
+    UNIMPLEMENTED_MSG("SetBootReason is not implemented!");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSecureMonitorNotImplemented);
+}
+
+void Module::Interface::GetBootReason(Kernel::HLERequestContext& ctx) {
+    UNIMPLEMENTED_MSG("GetBootReason is not implemented!");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSecureMonitorNotImplemented);
+}
+
+ResultVal<u64> Module::Interface::GetConfigImpl(ConfigItem config_item) const {
+    switch (config_item) {
+    case ConfigItem::DisableProgramVerification:
+    case ConfigItem::DramId:
+    case ConfigItem::SecurityEngineInterruptNumber:
+    case ConfigItem::FuseVersion:
+    case ConfigItem::HardwareType:
+    case ConfigItem::HardwareState:
+    case ConfigItem::IsRecoveryBoot:
+    case ConfigItem::DeviceId:
+    case ConfigItem::BootReason:
+    case ConfigItem::MemoryMode:
+    case ConfigItem::IsDevelopmentFunctionEnabled:
+    case ConfigItem::KernelConfiguration:
+    case ConfigItem::IsChargerHiZModeEnabled:
+    case ConfigItem::QuestState:
+    case ConfigItem::RegulatorType:
+    case ConfigItem::DeviceUniqueKeyGeneration:
+    case ConfigItem::Package2Hash:
+        return ResultSecureMonitorNotImplemented;
+    case ConfigItem::ExosphereApiVersion:
+        // Get information about the current exosphere version.
+        return MakeResult((u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MAJOR} << 56) |
+                          (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MINOR} << 48) |
+                          (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MICRO} << 40) |
+                          (static_cast<u64>(HLE::ApiVersion::GetTargetFirmware())));
+    case ConfigItem::ExosphereNeedsReboot:
+        // We are executing, so we aren't in the process of rebooting.
+        return MakeResult(u64{0});
+    case ConfigItem::ExosphereNeedsShutdown:
+        // We are executing, so we aren't in the process of shutting down.
+        return MakeResult(u64{0});
+    case ConfigItem::ExosphereGitCommitHash:
+        // Get information about the current exosphere git commit hash.
+        return MakeResult(u64{0});
+    case ConfigItem::ExosphereHasRcmBugPatch:
+        // Get information about whether this unit has the RCM bug patched.
+        return MakeResult(u64{0});
+    case ConfigItem::ExosphereBlankProdInfo:
+        // Get whether this unit should simulate a "blanked" PRODINFO.
+        return MakeResult(u64{0});
+    case ConfigItem::ExosphereAllowCalWrites:
+        // Get whether this unit should allow writing to the calibration partition.
+        return MakeResult(u64{0});
+    case ConfigItem::ExosphereEmummcType:
+        // Get what kind of emummc this unit has active.
+        return MakeResult(u64{0});
+    case ConfigItem::ExospherePayloadAddress:
+        // Gets the physical address of the reboot payload buffer, if one exists.
+        return ResultSecureMonitorNotInitialized;
+    case ConfigItem::ExosphereLogConfiguration:
+        // Get the log configuration.
+        return MakeResult(u64{0});
+    case ConfigItem::ExosphereForceEnableUsb30:
+        // Get whether usb 3.0 should be force-enabled.
+        return MakeResult(u64{0});
+    default:
+        return ResultSecureMonitorInvalidArgument;
+    }
+}
+
 void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
     auto module = std::make_shared<Module>();
     std::make_shared<CSRNG>(system, module)->InstallAsService(service_manager);

+ 12 - 1
src/core/hle/service/spl/module.h

@@ -6,6 +6,8 @@
 
 #include <random>
 #include "core/hle/service/service.h"
+#include "core/hle/service/spl/spl_results.h"
+#include "core/hle/service/spl/spl_types.h"
 
 namespace Core {
 class System;
@@ -21,12 +23,21 @@ public:
                            const char* name);
         ~Interface() override;
 
-        void GetRandomBytes(Kernel::HLERequestContext& ctx);
+        // General
+        void GetConfig(Kernel::HLERequestContext& ctx);
+        void ModularExponentiate(Kernel::HLERequestContext& ctx);
+        void SetConfig(Kernel::HLERequestContext& ctx);
+        void GenerateRandomBytes(Kernel::HLERequestContext& ctx);
+        void IsDevelopment(Kernel::HLERequestContext& ctx);
+        void SetBootReason(Kernel::HLERequestContext& ctx);
+        void GetBootReason(Kernel::HLERequestContext& ctx);
 
     protected:
         std::shared_ptr<Module> module;
 
     private:
+        ResultVal<u64> GetConfigImpl(ConfigItem config_item) const;
+
         std::mt19937 rng;
     };
 };

+ 42 - 42
src/core/hle/service/spl/spl.cpp

@@ -10,13 +10,13 @@ SPL::SPL(Core::System& system_, std::shared_ptr<Module> module_)
     : Interface(system_, std::move(module_), "spl:") {
     // clang-format off
     static const FunctionInfo functions[] = {
-        {0, nullptr, "GetConfig"},
-        {1, nullptr, "ModularExponentiate"},
-        {5, nullptr, "SetConfig"},
-        {7, &SPL::GetRandomBytes, "GetRandomBytes"},
-        {11, nullptr, "IsDevelopment"},
-        {24, nullptr, "SetBootReason"},
-        {25, nullptr, "GetBootReason"},
+        {0, &SPL::GetConfig, "GetConfig"},
+        {1, &SPL::ModularExponentiate, "ModularExponentiate"},
+        {5, &SPL::SetConfig, "SetConfig"},
+        {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
+        {11, &SPL::IsDevelopment, "IsDevelopment"},
+        {24, &SPL::SetBootReason, "SetBootReason"},
+        {25, &SPL::GetBootReason, "GetBootReason"},
     };
     // clang-format on
 
@@ -27,22 +27,22 @@ SPL_MIG::SPL_MIG(Core::System& system_, std::shared_ptr<Module> module_)
     : Interface(system_, std::move(module_), "spl:mig") {
     // clang-format off
     static const FunctionInfo functions[] = {
-        {0, nullptr, "GetConfig"},
-        {1, nullptr, "ModularExponentiate"},
+        {0, &SPL::GetConfig, "GetConfig"},
+        {1, &SPL::ModularExponentiate, "ModularExponentiate"},
         {2, nullptr, "GenerateAesKek"},
         {3, nullptr, "LoadAesKey"},
         {4, nullptr, "GenerateAesKey"},
-        {5, nullptr, "SetConfig"},
-        {7, &SPL::GetRandomBytes, "GenerateRandomBytes"},
-        {11, nullptr, "IsDevelopment"},
+        {5, &SPL::SetConfig, "SetConfig"},
+        {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
+        {11, &SPL::IsDevelopment, "IsDevelopment"},
         {14, nullptr, "DecryptAesKey"},
         {15, nullptr, "CryptAesCtr"},
         {16, nullptr, "ComputeCmac"},
         {21, nullptr, "AllocateAesKeyslot"},
         {22, nullptr, "DeallocateAesKeySlot"},
         {23, nullptr, "GetAesKeyslotAvailableEvent"},
-        {24, nullptr, "SetBootReason"},
-        {25, nullptr, "GetBootReason"},
+        {24, &SPL::SetBootReason, "SetBootReason"},
+        {25, &SPL::GetBootReason, "GetBootReason"},
     };
     // clang-format on
 
@@ -53,16 +53,16 @@ SPL_FS::SPL_FS(Core::System& system_, std::shared_ptr<Module> module_)
     : Interface(system_, std::move(module_), "spl:fs") {
     // clang-format off
     static const FunctionInfo functions[] = {
-        {0, nullptr, "GetConfig"},
-        {1, nullptr, "ModularExponentiate"},
+        {0, &SPL::GetConfig, "GetConfig"},
+        {1, &SPL::ModularExponentiate, "ModularExponentiate"},
         {2, nullptr, "GenerateAesKek"},
         {3, nullptr, "LoadAesKey"},
         {4, nullptr, "GenerateAesKey"},
-        {5, nullptr, "SetConfig"},
-        {7, &SPL::GetRandomBytes, "GenerateRandomBytes"},
+        {5, &SPL::SetConfig, "SetConfig"},
+        {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
         {9, nullptr, "ImportLotusKey"},
         {10, nullptr, "DecryptLotusMessage"},
-        {11, nullptr, "IsDevelopment"},
+        {11, &SPL::IsDevelopment, "IsDevelopment"},
         {12, nullptr, "GenerateSpecificAesKey"},
         {14, nullptr, "DecryptAesKey"},
         {15, nullptr, "CryptAesCtr"},
@@ -71,8 +71,8 @@ SPL_FS::SPL_FS(Core::System& system_, std::shared_ptr<Module> module_)
         {21, nullptr, "AllocateAesKeyslot"},
         {22, nullptr, "DeallocateAesKeySlot"},
         {23, nullptr, "GetAesKeyslotAvailableEvent"},
-        {24, nullptr, "SetBootReason"},
-        {25, nullptr, "GetBootReason"},
+        {24, &SPL::SetBootReason, "SetBootReason"},
+        {25, &SPL::GetBootReason, "GetBootReason"},
         {31, nullptr, "GetPackage2Hash"},
     };
     // clang-format on
@@ -84,14 +84,14 @@ SPL_SSL::SPL_SSL(Core::System& system_, std::shared_ptr<Module> module_)
     : Interface(system_, std::move(module_), "spl:ssl") {
     // clang-format off
     static const FunctionInfo functions[] = {
-        {0, nullptr, "GetConfig"},
-        {1, nullptr, "ModularExponentiate"},
+        {0, &SPL::GetConfig, "GetConfig"},
+        {1, &SPL::ModularExponentiate, "ModularExponentiate"},
         {2, nullptr, "GenerateAesKek"},
         {3, nullptr, "LoadAesKey"},
         {4, nullptr, "GenerateAesKey"},
-        {5, nullptr, "SetConfig"},
-        {7, &SPL::GetRandomBytes, "GetRandomBytes"},
-        {11, nullptr, "IsDevelopment"},
+        {5, &SPL::SetConfig, "SetConfig"},
+        {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
+        {11, &SPL::IsDevelopment, "IsDevelopment"},
         {13, nullptr, "DecryptDeviceUniqueData"},
         {14, nullptr, "DecryptAesKey"},
         {15, nullptr, "CryptAesCtr"},
@@ -99,8 +99,8 @@ SPL_SSL::SPL_SSL(Core::System& system_, std::shared_ptr<Module> module_)
         {21, nullptr, "AllocateAesKeyslot"},
         {22, nullptr, "DeallocateAesKeySlot"},
         {23, nullptr, "GetAesKeyslotAvailableEvent"},
-        {24, nullptr, "SetBootReason"},
-        {25, nullptr, "GetBootReason"},
+        {24, &SPL::SetBootReason, "SetBootReason"},
+        {25, &SPL::GetBootReason, "GetBootReason"},
         {26, nullptr, "DecryptAndStoreSslClientCertKey"},
         {27, nullptr, "ModularExponentiateWithSslClientCertKey"},
     };
@@ -113,14 +113,14 @@ SPL_ES::SPL_ES(Core::System& system_, std::shared_ptr<Module> module_)
     : Interface(system_, std::move(module_), "spl:es") {
     // clang-format off
     static const FunctionInfo functions[] = {
-        {0, nullptr, "GetConfig"},
-        {1, nullptr, "ModularExponentiate"},
+        {0, &SPL::GetConfig, "GetConfig"},
+        {1, &SPL::ModularExponentiate, "ModularExponentiate"},
         {2, nullptr, "GenerateAesKek"},
         {3, nullptr, "LoadAesKey"},
         {4, nullptr, "GenerateAesKey"},
-        {5, nullptr, "SetConfig"},
-        {7, &SPL::GetRandomBytes, "GenerateRandomBytes"},
-        {11, nullptr, "IsDevelopment"},
+        {5, &SPL::SetConfig, "SetConfig"},
+        {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
+        {11, &SPL::IsDevelopment, "IsDevelopment"},
         {13, nullptr, "DecryptDeviceUniqueData"},
         {14, nullptr, "DecryptAesKey"},
         {15, nullptr, "CryptAesCtr"},
@@ -131,8 +131,8 @@ SPL_ES::SPL_ES(Core::System& system_, std::shared_ptr<Module> module_)
         {21, nullptr, "AllocateAesKeyslot"},
         {22, nullptr, "DeallocateAesKeySlot"},
         {23, nullptr, "GetAesKeyslotAvailableEvent"},
-        {24, nullptr, "SetBootReason"},
-        {25, nullptr, "GetBootReason"},
+        {24, &SPL::SetBootReason, "SetBootReason"},
+        {25, &SPL::GetBootReason, "GetBootReason"},
         {28, nullptr, "DecryptAndStoreDrmDeviceCertKey"},
         {29, nullptr, "ModularExponentiateWithDrmDeviceCertKey"},
         {31, nullptr, "PrepareEsArchiveKey"},
@@ -147,14 +147,14 @@ SPL_MANU::SPL_MANU(Core::System& system_, std::shared_ptr<Module> module_)
     : Interface(system_, std::move(module_), "spl:manu") {
     // clang-format off
     static const FunctionInfo functions[] = {
-        {0, nullptr, "GetConfig"},
-        {1, nullptr, "ModularExponentiate"},
+        {0, &SPL::GetConfig, "GetConfig"},
+        {1, &SPL::ModularExponentiate, "ModularExponentiate"},
         {2, nullptr, "GenerateAesKek"},
         {3, nullptr, "LoadAesKey"},
         {4, nullptr, "GenerateAesKey"},
-        {5, nullptr, "SetConfig"},
-        {7, &SPL::GetRandomBytes, "GetRandomBytes"},
-        {11, nullptr, "IsDevelopment"},
+        {5, &SPL::SetConfig, "SetConfig"},
+        {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
+        {11, &SPL::IsDevelopment, "IsDevelopment"},
         {13, nullptr, "DecryptDeviceUniqueData"},
         {14, nullptr, "DecryptAesKey"},
         {15, nullptr, "CryptAesCtr"},
@@ -162,8 +162,8 @@ SPL_MANU::SPL_MANU(Core::System& system_, std::shared_ptr<Module> module_)
         {21, nullptr, "AllocateAesKeyslot"},
         {22, nullptr, "DeallocateAesKeySlot"},
         {23, nullptr, "GetAesKeyslotAvailableEvent"},
-        {24, nullptr, "SetBootReason"},
-        {25, nullptr, "GetBootReason"},
+        {24, &SPL::SetBootReason, "SetBootReason"},
+        {25, &SPL::GetBootReason, "GetBootReason"},
         {30, nullptr, "ReencryptDeviceUniqueData"},
     };
     // clang-format on

+ 29 - 0
src/core/hle/service/spl/spl_results.h

@@ -0,0 +1,29 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/result.h"
+
+namespace Service::SPL {
+
+// Description 0 - 99
+constexpr ResultCode ResultSecureMonitorError{ErrorModule::SPL, 0};
+constexpr ResultCode ResultSecureMonitorNotImplemented{ErrorModule::SPL, 1};
+constexpr ResultCode ResultSecureMonitorInvalidArgument{ErrorModule::SPL, 2};
+constexpr ResultCode ResultSecureMonitorBusy{ErrorModule::SPL, 3};
+constexpr ResultCode ResultSecureMonitorNoAsyncOperation{ErrorModule::SPL, 4};
+constexpr ResultCode ResultSecureMonitorInvalidAsyncOperation{ErrorModule::SPL, 5};
+constexpr ResultCode ResultSecureMonitorNotPermitted{ErrorModule::SPL, 6};
+constexpr ResultCode ResultSecureMonitorNotInitialized{ErrorModule::SPL, 7};
+
+constexpr ResultCode ResultInvalidSize{ErrorModule::SPL, 100};
+constexpr ResultCode ResultUnknownSecureMonitorError{ErrorModule::SPL, 101};
+constexpr ResultCode ResultDecryptionFailed{ErrorModule::SPL, 102};
+
+constexpr ResultCode ResultOutOfKeySlots{ErrorModule::SPL, 104};
+constexpr ResultCode ResultInvalidKeySlot{ErrorModule::SPL, 105};
+constexpr ResultCode ResultBootReasonAlreadySet{ErrorModule::SPL, 106};
+constexpr ResultCode ResultBootReasonNotSet{ErrorModule::SPL, 107};
+constexpr ResultCode ResultInvalidArgument{ErrorModule::SPL, 108};
+
+} // namespace Service::SPL

+ 230 - 0
src/core/hle/service/spl/spl_types.h

@@ -0,0 +1,230 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <span>
+
+#include "common/bit_field.h"
+#include "common/common_types.h"
+
+namespace Service::SPL {
+
+constexpr size_t AES_128_KEY_SIZE = 0x10;
+
+namespace Smc {
+
+enum class FunctionId : u32 {
+    SetConfig = 0xC3000401,
+    GetConfig = 0xC3000002,
+    GetResult = 0xC3000003,
+    GetResultData = 0xC3000404,
+    ModularExponentiate = 0xC3000E05,
+    GenerateRandomBytes = 0xC3000006,
+    GenerateAesKek = 0xC3000007,
+    LoadAesKey = 0xC3000008,
+    ComputeAes = 0xC3000009,
+    GenerateSpecificAesKey = 0xC300000A,
+    ComputeCmac = 0xC300040B,
+    ReencryptDeviceUniqueData = 0xC300D60C,
+    DecryptDeviceUniqueData = 0xC300100D,
+
+    ModularExponentiateWithStorageKey = 0xC300060F,
+    PrepareEsDeviceUniqueKey = 0xC3000610,
+    LoadPreparedAesKey = 0xC3000011,
+    PrepareCommonEsTitleKey = 0xC3000012,
+
+    // Deprecated functions.
+    LoadEsDeviceKey = 0xC300100C,
+    DecryptAndStoreGcKey = 0xC300100E,
+
+    // Atmosphere functions.
+    AtmosphereIramCopy = 0xF0000201,
+    AtmosphereReadWriteRegister = 0xF0000002,
+
+    AtmosphereGetEmummcConfig = 0xF0000404,
+};
+
+enum class CipherMode {
+    CbcEncrypt = 0,
+    CbcDecrypt = 1,
+    Ctr = 2,
+};
+
+enum class DeviceUniqueDataMode {
+    DecryptDeviceUniqueData = 0,
+    DecryptAndStoreGcKey = 1,
+    DecryptAndStoreEsDeviceKey = 2,
+    DecryptAndStoreSslKey = 3,
+    DecryptAndStoreDrmDeviceCertKey = 4,
+};
+
+enum class ModularExponentiateWithStorageKeyMode {
+    Gc = 0,
+    Ssl = 1,
+    DrmDeviceCert = 2,
+};
+
+enum class EsCommonKeyType {
+    TitleKey = 0,
+    ArchiveKey = 1,
+};
+
+struct AsyncOperationKey {
+    u64 value;
+};
+
+} // namespace Smc
+
+enum class HardwareType {
+    Icosa = 0,
+    Copper = 1,
+    Hoag = 2,
+    Iowa = 3,
+    Calcio = 4,
+    Aula = 5,
+};
+
+enum class SocType {
+    Erista = 0,
+    Mariko = 1,
+};
+
+enum class HardwareState {
+    Development = 0,
+    Production = 1,
+};
+
+enum class MemoryArrangement {
+    Standard = 0,
+    StandardForAppletDev = 1,
+    StandardForSystemDev = 2,
+    Expanded = 3,
+    ExpandedForAppletDev = 4,
+
+    // Note: Dynamic is not official.
+    // Atmosphere uses it to maintain compatibility with firmwares prior to 6.0.0,
+    // which removed the explicit retrieval of memory arrangement from PM.
+    Dynamic = 5,
+    Count,
+};
+
+enum class BootReason {
+    Unknown = 0,
+    AcOk = 1,
+    OnKey = 2,
+    RtcAlarm1 = 3,
+    RtcAlarm2 = 4,
+};
+
+struct BootReasonValue {
+    union {
+        u32 value{};
+
+        BitField<0, 8, u32> power_intr;
+        BitField<8, 8, u32> rtc_intr;
+        BitField<16, 8, u32> nv_erc;
+        BitField<24, 8, u32> boot_reason;
+    };
+};
+static_assert(sizeof(BootReasonValue) == sizeof(u32), "BootReasonValue definition!");
+
+struct AesKey {
+    std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
+
+    std::span<u8> AsBytes() {
+        return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
+    }
+
+    std::span<const u8> AsBytes() const {
+        return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
+    }
+};
+static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "AesKey definition!");
+
+struct IvCtr {
+    std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
+
+    std::span<u8> AsBytes() {
+        return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
+    }
+
+    std::span<const u8> AsBytes() const {
+        return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
+    }
+};
+static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "IvCtr definition!");
+
+struct Cmac {
+    std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
+
+    std::span<u8> AsBytes() {
+        return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
+    }
+
+    std::span<const u8> AsBytes() const {
+        return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
+    }
+};
+static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "Cmac definition!");
+
+struct AccessKey {
+    std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
+
+    std::span<u8> AsBytes() {
+        return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
+    }
+
+    std::span<const u8> AsBytes() const {
+        return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
+    }
+};
+static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "AccessKey definition!");
+
+struct KeySource {
+    std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
+
+    std::span<u8> AsBytes() {
+        return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
+    }
+
+    std::span<const u8> AsBytes() const {
+        return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
+    }
+};
+static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "KeySource definition!");
+
+enum class ConfigItem : u32 {
+    // 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,
+
+    // Extension config items for exosphere.
+    ExosphereApiVersion = 65000,
+    ExosphereNeedsReboot = 65001,
+    ExosphereNeedsShutdown = 65002,
+    ExosphereGitCommitHash = 65003,
+    ExosphereHasRcmBugPatch = 65004,
+    ExosphereBlankProdInfo = 65005,
+    ExosphereAllowCalWrites = 65006,
+    ExosphereEmummcType = 65007,
+    ExospherePayloadAddress = 65008,
+    ExosphereLogConfiguration = 65009,
+    ExosphereForceEnableUsb30 = 65010,
+};
+
+} // namespace Service::SPL