diff --git a/libstratosphere/include/stratosphere/ams/ams_environment.hpp b/libstratosphere/include/stratosphere/ams/ams_environment.hpp index 4fdd8f16..d610bce3 100644 --- a/libstratosphere/include/stratosphere/ams/ams_environment.hpp +++ b/libstratosphere/include/stratosphere/ams/ams_environment.hpp @@ -22,4 +22,8 @@ namespace ams { /* Will be called by libstratosphere on crash. */ void CrashHandler(ThreadExceptionDump *ctx); + /* API for boot sysmodule. */ + void InitializeForBoot(); + void SetInitialRebootPayload(const void *src, size_t src_size); + } diff --git a/libstratosphere/include/stratosphere/ams/ams_exosphere_api.hpp b/libstratosphere/include/stratosphere/ams/ams_exosphere_api.hpp index eb80efef..bc0efd13 100644 --- a/libstratosphere/include/stratosphere/ams/ams_exosphere_api.hpp +++ b/libstratosphere/include/stratosphere/ams/ams_exosphere_api.hpp @@ -27,6 +27,11 @@ namespace ams::exosphere { bool IsRcmBugPatched(); + bool ShouldBlankProdInfo(); + bool ShouldAllowWritesToProdInfo(); + + u64 GetDeviceId(); + void CopyToIram(uintptr_t iram_dst, const void *dram_src, size_t size); void CopyFromIram(void *dram_dst, uintptr_t iram_src, size_t size); diff --git a/libstratosphere/include/stratosphere/settings.hpp b/libstratosphere/include/stratosphere/settings.hpp index a509fe93..d78e42be 100644 --- a/libstratosphere/include/stratosphere/settings.hpp +++ b/libstratosphere/include/stratosphere/settings.hpp @@ -16,11 +16,13 @@ #pragma once -#include "settings/settings_types.hpp" -#include "settings/settings_fwdbg_types.hpp" -#include "settings/settings_fwdbg_api.hpp" -#include "settings/system/settings_error_report.hpp" -#include "settings/system/settings_firmware_version.hpp" -#include "settings/system/settings_product_model.hpp" -#include "settings/system/settings_region.hpp" -#include "settings/system/settings_serial_number.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/libstratosphere/include/stratosphere/settings/factory/settings_device_certificate.hpp b/libstratosphere/include/stratosphere/settings/factory/settings_device_certificate.hpp new file mode 100644 index 00000000..b9be0525 --- /dev/null +++ b/libstratosphere/include/stratosphere/settings/factory/settings_device_certificate.hpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::settings::factory { + + struct EccP256DeviceCertificate { + u8 data[0x180]; + }; + static_assert(sizeof(EccP256DeviceCertificate) == 0x180); + static_assert(std::is_pod::value); + + struct EccB233DeviceCertificate { + u8 data[0x180]; + }; + static_assert(sizeof(EccB233DeviceCertificate) == 0x180); + static_assert(std::is_pod::value); + + struct Rsa2048DeviceCertificate { + u8 data[0x240]; + }; + static_assert(sizeof(Rsa2048DeviceCertificate) == 0x240); + static_assert(std::is_pod::value); + +} diff --git a/libstratosphere/include/stratosphere/settings/factory/settings_serial_number.hpp b/libstratosphere/include/stratosphere/settings/factory/settings_serial_number.hpp new file mode 100644 index 00000000..068d7d65 --- /dev/null +++ b/libstratosphere/include/stratosphere/settings/factory/settings_serial_number.hpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::settings::factory { + + struct SerialNumber { + char str[0x18]; + }; + static_assert(sizeof(SerialNumber) == 0x18); + static_assert(std::is_pod::value); + +} diff --git a/libstratosphere/include/stratosphere/spl/spl_api.hpp b/libstratosphere/include/stratosphere/spl/spl_api.hpp index b2ce4a56..3b9639f8 100644 --- a/libstratosphere/include/stratosphere/spl/spl_api.hpp +++ b/libstratosphere/include/stratosphere/spl/spl_api.hpp @@ -27,4 +27,7 @@ namespace ams::spl { bool IsMariko(); bool IsRecoveryBoot(); + Result GenerateAesKek(AccessKey *access_key, const void *key_source, size_t key_source_size, u32 generation, u32 option); + Result GenerateAesKey(void *dst, size_t dst_size, const AccessKey &access_key, const void *key_source, size_t key_source_size); + } diff --git a/libstratosphere/include/stratosphere/spl/spl_types.hpp b/libstratosphere/include/stratosphere/spl/spl_types.hpp index e73e6671..43dbb54e 100644 --- a/libstratosphere/include/stratosphere/spl/spl_types.hpp +++ b/libstratosphere/include/stratosphere/spl/spl_types.hpp @@ -183,6 +183,36 @@ namespace ams::spl { static_assert(alignof(AccessKey) == alignof(u8), "KeySource definition!"); #pragma pack(pop) + enum class ConfigItem : u32 { + /* Standard config items. */ + DisableProgramVerification = 1, + DramId = 2, + SecurityEngineIrqNumber = 3, + Version = 4, + HardwareType = 5, + IsRetail = 6, + IsRecoveryBoot = 7, + DeviceId = 8, + BootReason = 9, + MemoryMode = 10, + IsDebugMode = 11, + KernelConfiguration = 12, + IsChargerHiZModeEnabled = 13, + IsQuest = 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, + }; + } /* Extensions to libnx spl config item enum. */ @@ -191,3 +221,5 @@ constexpr inline SplConfigItem SplConfigItem_ExosphereNeedsReboot = static_ca constexpr inline SplConfigItem SplConfigItem_ExosphereNeedsShutdown = static_cast(65002); constexpr inline SplConfigItem SplConfigItem_ExosphereGitCommitHash = static_cast(65003); constexpr inline SplConfigItem SplConfigItem_ExosphereHasRcmBugPatch = static_cast(65004); +constexpr inline SplConfigItem SplConfigItem_ExosphereBlankProdInfo = static_cast(65005); +constexpr inline SplConfigItem SplConfigItem_ExosphereAllowCalWrites = static_cast(65006); diff --git a/libstratosphere/source/ams/ams_bpc.c b/libstratosphere/source/ams/ams_bpc.c index d04a69b7..8a3ddee4 100644 --- a/libstratosphere/source/ams/ams_bpc.c +++ b/libstratosphere/source/ams/ams_bpc.c @@ -24,6 +24,11 @@ NX_GENERATE_SERVICE_GUARD(amsBpc); Result _amsBpcInitialize(void) { Handle h; Result rc = svcConnectToNamedPort(&h, "bpc:ams"); /* TODO: ams:bpc */ + while (R_VALUE(rc) == KERNELRESULT(NotFound)) { + svcSleepThread(50000000ul); + rc = svcConnectToNamedPort(&h, "bpc:ams"); + } + if (R_SUCCEEDED(rc)) serviceCreate(&g_amsBpcSrv, h); return rc; } @@ -44,3 +49,11 @@ Result amsBpcRebootToFatalError(void *ctx) { .buffers = { { ctx, 0x450 } }, ); } + + +Result amsBpcSetInitialPayload(const void *src, size_t src_size) { + return serviceDispatch(&g_amsBpcSrv, 65001, + .buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias }, + .buffers = { { src, src_size } }, + ); +} diff --git a/libstratosphere/source/ams/ams_bpc.h b/libstratosphere/source/ams/ams_bpc.h index 05983fa6..d8a3a9ed 100644 --- a/libstratosphere/source/ams/ams_bpc.h +++ b/libstratosphere/source/ams/ams_bpc.h @@ -28,6 +28,7 @@ void amsBpcExit(void); Service *amsBpcGetServiceSession(void); Result amsBpcRebootToFatalError(void *ctx); +Result amsBpcSetInitialPayload(const void *src, size_t src_size); #ifdef __cplusplus } diff --git a/libstratosphere/source/ams/ams_environment.cpp b/libstratosphere/source/ams/ams_environment.cpp index 0af5dc5b..f4bc0419 100644 --- a/libstratosphere/source/ams/ams_environment.cpp +++ b/libstratosphere/source/ams/ams_environment.cpp @@ -36,6 +36,14 @@ namespace ams { extern ncm::ProgramId CurrentProgramId; + void InitializeForBoot() { + R_ABORT_UNLESS(amsBpcInitialize()); + } + + void SetInitialRebootPayload(const void *src, size_t src_size) { + R_ABORT_UNLESS(amsBpcSetInitialPayload(src, src_size)); + } + void WEAK_SYMBOL ExceptionHandler(FatalErrorContext *ctx) { R_ABORT_UNLESS(amsBpcInitialize()); R_ABORT_UNLESS(amsBpcRebootToFatalError(ctx)); diff --git a/libstratosphere/source/ams/ams_exosphere_api.cpp b/libstratosphere/source/ams/ams_exosphere_api.cpp index 91516644..63243d66 100644 --- a/libstratosphere/source/ams/ams_exosphere_api.cpp +++ b/libstratosphere/source/ams/ams_exosphere_api.cpp @@ -51,19 +51,32 @@ namespace ams::exosphere { namespace { - inline Result GetRcmBugPatched(bool *out) { - u64 tmp = 0; - R_TRY(spl::smc::ConvertResult(spl::smc::GetConfig(&tmp, 1, SplConfigItem_ExosphereHasRcmBugPatch))); - *out = (tmp != 0); - return ResultSuccess(); + inline u64 GetU64ConfigItem(spl::ConfigItem cfg) { + u64 tmp; + R_ABORT_UNLESS(spl::smc::ConvertResult(spl::smc::GetConfig(std::addressof(tmp), 1, static_cast<::SplConfigItem>(cfg)))); + return tmp; + } + + inline bool GetBooleanConfigItem(spl::ConfigItem cfg) { + return GetU64ConfigItem(cfg) != 0; } } bool IsRcmBugPatched() { - bool rcm_bug_patched; - R_ABORT_UNLESS(GetRcmBugPatched(&rcm_bug_patched)); - return rcm_bug_patched; + return GetBooleanConfigItem(spl::ConfigItem::ExosphereHasRcmBugPatch); + } + + bool ShouldBlankProdInfo() { + return GetBooleanConfigItem(spl::ConfigItem::ExosphereBlankProdInfo); + } + + bool ShouldAllowWritesToProdInfo() { + return GetBooleanConfigItem(spl::ConfigItem::ExosphereAllowCalWrites); + } + + u64 GetDeviceId() { + return GetU64ConfigItem(spl::ConfigItem::DeviceId); } } diff --git a/libstratosphere/source/spl/spl_api.cpp b/libstratosphere/source/spl/spl_api.cpp index 032ac52a..7ffa4c33 100644 --- a/libstratosphere/source/spl/spl_api.cpp +++ b/libstratosphere/source/spl/spl_api.cpp @@ -78,4 +78,15 @@ namespace ams::spl { } } + Result GenerateAesKek(AccessKey *access_key, const void *key_source, size_t key_source_size, u32 generation, u32 option) { + AMS_ASSERT(key_source_size == sizeof(KeySource)); + return splCryptoGenerateAesKek(key_source, generation, option, static_cast(access_key)); + } + + Result GenerateAesKey(void *dst, size_t dst_size, const AccessKey &access_key, const void *key_source, size_t key_source_size) { + AMS_ASSERT(dst_size == crypto::AesEncryptor128::KeySize); + AMS_ASSERT(key_source_size == sizeof(KeySource)); + return splCryptoGenerateAesKey(std::addressof(access_key), key_source, dst); + } + }