diff --git a/exosphere/program/source/boot/secmon_boot_key_data.s b/exosphere/program/source/boot/secmon_boot_key_data.s index bd5638060..f418d25c9 100644 --- a/exosphere/program/source/boot/secmon_boot_key_data.s +++ b/exosphere/program/source/boot/secmon_boot_key_data.s @@ -85,10 +85,10 @@ _ZN3ams6secmon4boot15VolatileKeyDataE: /* We can get away with only including latest because exosphere supports newer-than-expected master key in engine. */ /* TODO: Update on next change of keys. */ /* Mariko Development Master Kek Source. */ -.byte 0x11, 0x1C, 0x13, 0x90, 0xD9, 0x5E, 0xB0, 0xA2, 0xE3, 0xD0, 0x0E, 0x5D, 0xC4, 0xFB, 0x9E, 0xDB +.byte 0x2E, 0x27, 0x44, 0xEA, 0x32, 0xF8, 0x2C, 0xF0, 0x6F, 0xCA, 0xCD, 0x77, 0xAE, 0xAE, 0x1A, 0x1B /* Mariko Production Master Kek Source. */ -.byte 0xEB, 0xF3, 0x5B, 0x2D, 0x4A, 0x2D, 0xCE, 0x45, 0x3A, 0x6F, 0x61, 0x38, 0x0B, 0x00, 0x3B, 0x46 +.byte 0x82, 0xE2, 0x0A, 0x59, 0x67, 0xDF, 0xBF, 0x51, 0x47, 0x62, 0x11, 0xF2, 0x41, 0xD3, 0xEE, 0x13 /* Development Master Key Vectors. */ .byte 0x46, 0x22, 0xB4, 0x51, 0x9A, 0x7E, 0xA7, 0x7F, 0x62, 0xA1, 0x1F, 0x8F, 0xC5, 0x3A, 0xDB, 0xFE /* Zeroes encrypted with Master Key 00. */ @@ -112,6 +112,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE: .byte 0x90, 0x64, 0xF9, 0x08, 0x29, 0x88, 0xD4, 0xDC, 0x73, 0xA4, 0xA1, 0x13, 0x9E, 0x59, 0x85, 0xA0 /* Master key 11 encrypted with Master key 12. */ .byte 0x94, 0x46, 0x3B, 0xFA, 0x7D, 0xB9, 0xE2, 0x94, 0xC2, 0x9D, 0xB9, 0xA4, 0xB2, 0x56, 0xCA, 0xFE /* Master key 12 encrypted with Master key 13. */ .byte 0x74, 0xB2, 0x5F, 0xA0, 0x4B, 0x74, 0x6D, 0x47, 0x5B, 0xA9, 0xF5, 0x26, 0x46, 0xD7, 0x4B, 0x6E /* Master key 13 encrypted with Master key 14. */ +.byte 0x97, 0xB3, 0x61, 0x88, 0x5C, 0x0D, 0xA1, 0x38, 0x73, 0xA4, 0x2F, 0x1A, 0x46, 0xA1, 0x09, 0xBF /* Master key 14 encrypted with Master key 15. */ /* Production Master Key Vectors. */ .byte 0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D /* Zeroes encrypted with Master Key 00. */ @@ -135,6 +136,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE: .byte 0x4A, 0x01, 0x3B, 0xC7, 0x44, 0x6E, 0x45, 0xBD, 0xE6, 0x5E, 0x2B, 0xEC, 0x07, 0x37, 0x52, 0x86 /* Master key 11 encrypted with Master key 12. */ .byte 0x97, 0xE4, 0x11, 0xAB, 0x22, 0x72, 0x1A, 0x1F, 0x70, 0x5C, 0x00, 0xB3, 0x96, 0x30, 0x05, 0x28 /* Master key 12 encrypted with Master key 13. */ .byte 0xF7, 0x92, 0xC0, 0xEC, 0xF3, 0xA4, 0x8C, 0xB7, 0x0D, 0xB3, 0xF3, 0xAB, 0x10, 0x9B, 0x18, 0xBA /* Master key 13 encrypted with Master key 14. */ +.byte 0x14, 0xCB, 0x60, 0x29, 0x3D, 0xE0, 0xFB, 0xF2, 0x5B, 0x60, 0xB6, 0xC5, 0x2E, 0x77, 0x8F, 0x98 /* Master key 14 encrypted with Master key 15. */ /* Device Master Key Source Sources. */ .byte 0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D /* 4.0.0 Device Master Key Source Source. */ @@ -155,6 +157,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE: .byte 0x07, 0x38, 0x9A, 0xEC, 0x9C, 0xBD, 0x50, 0x4A, 0x4C, 0x1F, 0x04, 0xDA, 0x40, 0x68, 0x29, 0xE3 /* 19.0.0 Device Master Key Source Source. */ .byte 0xA3, 0x6B, 0x0A, 0xB5, 0x6F, 0x57, 0x4C, 0x5E, 0x00, 0xFD, 0x56, 0x21, 0xF5, 0x06, 0x6B, 0xD1 /* 20.0.0 Device Master Key Source Source. */ .byte 0xF9, 0x62, 0x05, 0x99, 0xE0, 0xB9, 0xA6, 0x9B, 0x9D, 0xAA, 0xB4, 0x12, 0x0B, 0x0F, 0xF5, 0x8F /* 21.0.0 Device Master Key Source Source. */ +.byte 0xF8, 0xF4, 0x22, 0xA4, 0x34, 0xAE, 0x0E, 0x0C, 0x4D, 0x5C, 0x5B, 0xA1, 0x1B, 0x46, 0x1C, 0x78 /* 22.0.0 Device Master Key Source Source. */ /* Development Device Master Kek Sources. */ .byte 0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34 /* 4.0.0 Device Master Kek Source. */ @@ -175,6 +178,7 @@ _ZN3ams6secmon4boot15VolatileKeyDataE: .byte 0xAE, 0x78, 0x36, 0xB6, 0x91, 0xEB, 0xAF, 0x9C, 0x18, 0xF1, 0xC0, 0xD5, 0x8A, 0x0C, 0x7C, 0xA1 /* 19.0.0 Device Master Kek Source. */ .byte 0x09, 0x12, 0x4F, 0x26, 0x90, 0xB9, 0xA6, 0xF5, 0xA5, 0x18, 0x74, 0xB6, 0x8D, 0x80, 0x59, 0x3D /* 20.0.0 Device Master Kek Source. */ .byte 0x7A, 0x4C, 0x38, 0xB7, 0x03, 0x6B, 0x1E, 0x81, 0x20, 0x53, 0x14, 0x99, 0xA4, 0x21, 0x92, 0x9F /* 21.0.0 Device Master Kek Source. */ +.byte 0xF3, 0xBC, 0xB5, 0xB5, 0x5F, 0x01, 0x50, 0x2B, 0x69, 0x69, 0x3A, 0x6B, 0xF9, 0x2C, 0x11, 0x9F /* 22.0.0 Device Master Kek Source. */ /* Production Device Master Kek Sources. */ .byte 0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D /* 4.0.0 Device Master Kek Source. */ @@ -194,4 +198,5 @@ _ZN3ams6secmon4boot15VolatileKeyDataE: .byte 0xE7, 0x85, 0x8C, 0xA2, 0xF4, 0x49, 0xCB, 0x07, 0xD1, 0x8E, 0x48, 0x1B, 0xE8, 0x1E, 0x28, 0x3B /* 18.0.0 Device Master Kek Source. */ .byte 0x9B, 0xA5, 0xFD, 0x74, 0x7F, 0xCD, 0x23, 0xD1, 0xD9, 0xBD, 0x6C, 0x51, 0x72, 0x5F, 0x3D, 0x1F /* 19.0.0 Device Master Kek Source. */ .byte 0xDA, 0xFB, 0x61, 0x39, 0x48, 0x2D, 0xC2, 0x7E, 0x0D, 0x8E, 0x8F, 0x98, 0x57, 0x20, 0xB8, 0x15 /* 20.0.0 Device Master Kek Source. */ -.byte 0x92, 0xBF, 0x37, 0x80, 0x0E, 0x79, 0x56, 0x8C, 0x57, 0x75, 0x72, 0x0A, 0x48, 0xD8, 0x15, 0x39 /* 21.0.0 Device Master Kek Source. */ \ No newline at end of file +.byte 0x92, 0xBF, 0x37, 0x80, 0x0E, 0x79, 0x56, 0x8C, 0x57, 0x75, 0x72, 0x0A, 0x48, 0xD8, 0x15, 0x39 /* 21.0.0 Device Master Kek Source. */ +.byte 0xC4, 0x6F, 0x0E, 0x72, 0x43, 0xCE, 0x87, 0xFC, 0x38, 0x95, 0x9B, 0xC9, 0x31, 0x44, 0x97, 0x63 /* 22.0.0 Device Master Kek Source. */ \ No newline at end of file diff --git a/exosphere/program/source/boot/secmon_package2.cpp b/exosphere/program/source/boot/secmon_package2.cpp index 088f2256e..005549f4a 100644 --- a/exosphere/program/source/boot/secmon_package2.cpp +++ b/exosphere/program/source/boot/secmon_package2.cpp @@ -94,7 +94,7 @@ namespace ams::secmon::boot { } /* Check that the key generation is one that we can use. */ - static_assert(pkg1::KeyGeneration_Count == 21); + static_assert(pkg1::KeyGeneration_Count == 22); if (key_generation >= pkg1::KeyGeneration_Count) { return false; } diff --git a/fusee/program/source/fusee_key_derivation.cpp b/fusee/program/source/fusee_key_derivation.cpp index a3c9b9eb5..f392f67c6 100644 --- a/fusee/program/source/fusee_key_derivation.cpp +++ b/fusee/program/source/fusee_key_derivation.cpp @@ -23,17 +23,17 @@ namespace ams::nxboot { alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSource[se::AesBlockSize] = { /* TODO: Update on next change of keys. */ - 0xEB, 0xF3, 0x5B, 0x2D, 0x4A, 0x2D, 0xCE, 0x45, 0x3A, 0x6F, 0x61, 0x38, 0x0B, 0x00, 0x3B, 0x46 + 0x82, 0xE2, 0x0A, 0x59, 0x67, 0xDF, 0xBF, 0x51, 0x47, 0x62, 0x11, 0xF2, 0x41, 0xD3, 0xEE, 0x13 }; alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSourceDev[se::AesBlockSize] = { /* TODO: Update on next change of keys. */ - 0x11, 0x1C, 0x13, 0x90, 0xD9, 0x5E, 0xB0, 0xA2, 0xE3, 0xD0, 0x0E, 0x5D, 0xC4, 0xFB, 0x9E, 0xDB + 0x2E, 0x27, 0x44, 0xEA, 0x32, 0xF8, 0x2C, 0xF0, 0x6F, 0xCA, 0xCD, 0x77, 0xAE, 0xAE, 0x1A, 0x1B }; alignas(se::AesBlockSize) constexpr inline const u8 EristaMasterKekSource[se::AesBlockSize] = { /* TODO: Update on next change of keys. */ - 0x66, 0xC8, 0xCB, 0x3D, 0xEC, 0xF4, 0x59, 0x73, 0x54, 0x88, 0xE1, 0x2E, 0xE6, 0x3D, 0x68, 0x46 + 0x15, 0xAC, 0x96, 0x34, 0xF5, 0x32, 0x56, 0x68, 0xFE, 0x5B, 0x9D, 0xD7, 0xED, 0x19, 0xB7, 0x8E }; alignas(se::AesBlockSize) constexpr inline const u8 KeyblobKeySource[se::AesBlockSize] = { @@ -75,6 +75,7 @@ namespace ams::nxboot { { 0x07, 0x38, 0x9A, 0xEC, 0x9C, 0xBD, 0x50, 0x4A, 0x4C, 0x1F, 0x04, 0xDA, 0x40, 0x68, 0x29, 0xE3 }, /* 19.0.0 Device Master Key Source Source. */ { 0xA3, 0x6B, 0x0A, 0xB5, 0x6F, 0x57, 0x4C, 0x5E, 0x00, 0xFD, 0x56, 0x21, 0xF5, 0x06, 0x6B, 0xD1 }, /* 20.0.0 Device Master Key Source Source. */ { 0xF9, 0x62, 0x05, 0x99, 0xE0, 0xB9, 0xA6, 0x9B, 0x9D, 0xAA, 0xB4, 0x12, 0x0B, 0x0F, 0xF5, 0x8F }, /* 21.0.0 Device Master Key Source Source. */ + { 0xF8, 0xF4, 0x22, 0xA4, 0x34, 0xAE, 0x0E, 0x0C, 0x4D, 0x5C, 0x5B, 0xA1, 0x1B, 0x46, 0x1C, 0x78 }, /* 22.0.0 Device Master Key Source Source. */ }; alignas(se::AesBlockSize) constexpr inline const u8 DeviceMasterKekSources[pkg1::OldDeviceMasterKeyCount][se::AesBlockSize] = { @@ -96,6 +97,7 @@ namespace ams::nxboot { { 0x9B, 0xA5, 0xFD, 0x74, 0x7F, 0xCD, 0x23, 0xD1, 0xD9, 0xBD, 0x6C, 0x51, 0x72, 0x5F, 0x3D, 0x1F }, /* 19.0.0 Device Master Kek Source. */ { 0xDA, 0xFB, 0x61, 0x39, 0x48, 0x2D, 0xC2, 0x7E, 0x0D, 0x8E, 0x8F, 0x98, 0x57, 0x20, 0xB8, 0x15 }, /* 20.0.0 Device Master Kek Source. */ { 0x92, 0xBF, 0x37, 0x80, 0x0E, 0x79, 0x56, 0x8C, 0x57, 0x75, 0x72, 0x0A, 0x48, 0xD8, 0x15, 0x39 }, /* 21.0.0 Device Master Kek Source. */ + { 0xC4, 0x6F, 0x0E, 0x72, 0x43, 0xCE, 0x87, 0xFC, 0x38, 0x95, 0x9B, 0xC9, 0x31, 0x44, 0x97, 0x63 }, /* 22.0.0 Device Master Kek Source. */ }; alignas(se::AesBlockSize) constexpr inline const u8 DeviceMasterKekSourcesDev[pkg1::OldDeviceMasterKeyCount][se::AesBlockSize] = { @@ -117,6 +119,7 @@ namespace ams::nxboot { { 0xAE, 0x78, 0x36, 0xB6, 0x91, 0xEB, 0xAF, 0x9C, 0x18, 0xF1, 0xC0, 0xD5, 0x8A, 0x0C, 0x7C, 0xA1 }, /* 19.0.0 Device Master Kek Source. */ { 0x09, 0x12, 0x4F, 0x26, 0x90, 0xB9, 0xA6, 0xF5, 0xA5, 0x18, 0x74, 0xB6, 0x8D, 0x80, 0x59, 0x3D }, /* 20.0.0 Device Master Kek Source. */ { 0x7A, 0x4C, 0x38, 0xB7, 0x03, 0x6B, 0x1E, 0x81, 0x20, 0x53, 0x14, 0x99, 0xA4, 0x21, 0x92, 0x9F }, /* 21.0.0 Device Master Kek Source. */ + { 0xF3, 0xBC, 0xB5, 0xB5, 0x5F, 0x01, 0x50, 0x2B, 0x69, 0x69, 0x3A, 0x6B, 0xF9, 0x2C, 0x11, 0x9F }, /* 22.0.0 Device Master Kek Source. */ }; alignas(se::AesBlockSize) constexpr inline const u8 MasterKeySources[pkg1::KeyGeneration_Count][se::AesBlockSize] = { @@ -141,6 +144,7 @@ namespace ams::nxboot { { 0x4A, 0x01, 0x3B, 0xC7, 0x44, 0x6E, 0x45, 0xBD, 0xE6, 0x5E, 0x2B, 0xEC, 0x07, 0x37, 0x52, 0x86 }, /* Master key 11 encrypted with Master key 12. */ { 0x97, 0xE4, 0x11, 0xAB, 0x22, 0x72, 0x1A, 0x1F, 0x70, 0x5C, 0x00, 0xB3, 0x96, 0x30, 0x05, 0x28 }, /* Master key 12 encrypted with Master key 13. */ { 0xF7, 0x92, 0xC0, 0xEC, 0xF3, 0xA4, 0x8C, 0xB7, 0x0D, 0xB3, 0xF3, 0xAB, 0x10, 0x9B, 0x18, 0xBA }, /* Master key 13 encrypted with Master key 14. */ + { 0x14, 0xCB, 0x60, 0x29, 0x3D, 0xE0, 0xFB, 0xF2, 0x5B, 0x60, 0xB6, 0xC5, 0x2E, 0x77, 0x8F, 0x98 }, /* Master key 14 encrypted with Master key 15. */ }; alignas(se::AesBlockSize) constexpr inline const u8 MasterKeySourcesDev[pkg1::KeyGeneration_Count][se::AesBlockSize] = { @@ -165,6 +169,7 @@ namespace ams::nxboot { { 0x90, 0x64, 0xF9, 0x08, 0x29, 0x88, 0xD4, 0xDC, 0x73, 0xA4, 0xA1, 0x13, 0x9E, 0x59, 0x85, 0xA0 }, /* Master key 11 encrypted with Master key 12. */ { 0x94, 0x46, 0x3B, 0xFA, 0x7D, 0xB9, 0xE2, 0x94, 0xC2, 0x9D, 0xB9, 0xA4, 0xB2, 0x56, 0xCA, 0xFE }, /* Master key 12 encrypted with Master key 13. */ { 0x74, 0xB2, 0x5F, 0xA0, 0x4B, 0x74, 0x6D, 0x47, 0x5B, 0xA9, 0xF5, 0x26, 0x46, 0xD7, 0x4B, 0x6E }, /* Master key 13 encrypted with Master key 14. */ + { 0x97, 0xB3, 0x61, 0x88, 0x5C, 0x0D, 0xA1, 0x38, 0x73, 0xA4, 0x2F, 0x1A, 0x46, 0xA1, 0x09, 0xBF }, /* Master key 14 encrypted with Master key 15. */ }; alignas(se::AesBlockSize) constinit u8 MasterKeys[pkg1::OldMasterKeyCount][se::AesBlockSize] = {}; diff --git a/fusee/program/source/fusee_package2.cpp b/fusee/program/source/fusee_package2.cpp index 90d029b73..236413eb7 100644 --- a/fusee/program/source/fusee_package2.cpp +++ b/fusee/program/source/fusee_package2.cpp @@ -80,7 +80,7 @@ namespace ams::nxboot { } /* Check that the key generation is one that we can use. */ - static_assert(pkg1::KeyGeneration_Count == 21); + static_assert(pkg1::KeyGeneration_Count == 22); if (key_generation >= pkg1::KeyGeneration_Count) { return false; } diff --git a/fusee/program/source/fusee_setup_horizon.cpp b/fusee/program/source/fusee_setup_horizon.cpp index 7ec68d4a3..0302895e3 100644 --- a/fusee/program/source/fusee_setup_horizon.cpp +++ b/fusee/program/source/fusee_setup_horizon.cpp @@ -267,6 +267,8 @@ namespace ams::nxboot { return ams::TargetFirmware_20_0_0; } else if (std::memcmp(package1 + 0x10, "20251009", 8) == 0) { return ams::TargetFirmware_21_0_0; + } else if (std::memcmp(package1 + 0x10, "20260123", 8) == 0) { + return ams::TargetFirmware_22_0_0; } break; default: diff --git a/fusee/program/source/fusee_stratosphere.cpp b/fusee/program/source/fusee_stratosphere.cpp index b5221927d..e784cb5e2 100644 --- a/fusee/program/source/fusee_stratosphere.cpp +++ b/fusee/program/source/fusee_stratosphere.cpp @@ -192,6 +192,9 @@ namespace ams::nxboot { FsVersion_21_2_0, FsVersion_21_2_0_Exfat, + FsVersion_22_0_0, + FsVersion_22_0_0_Exfat, + FsVersion_Count, }; @@ -296,6 +299,9 @@ namespace ams::nxboot { { 0xAF, 0x1D, 0xBD, 0xC7, 0x82, 0x98, 0x3C, 0xBD }, /* FsVersion_21_2_0 */ { 0x56, 0x25, 0x17, 0xA1, 0x92, 0xC3, 0xC8, 0xF0 }, /* FsVersion_21_2_0_Exfat */ + + { 0xB7, 0xA2, 0x97, 0x39, 0xB7, 0xED, 0xDE, 0xFC }, /* FsVersion_22_0_0 */ + { 0xFB, 0x0B, 0x68, 0xDB, 0x24, 0x03, 0xD1, 0x19 }, /* FsVersion_22_0_0_Exfat */ }; const InitialProcessBinaryHeader *FindInitialProcessBinary(const pkg2::Package2Header *header, const u8 *data, ams::TargetFirmware target_firmware) { @@ -700,7 +706,7 @@ namespace ams::nxboot { case FsVersion_21_0_0: case FsVersion_21_2_0: AddPatch(fs_meta, 0x1AC9ED, NogcPatch0, sizeof(NogcPatch0)); - AddPatch(fs_meta, 0x1ACA05 , NogcPatch0, sizeof(NogcPatch0)); + AddPatch(fs_meta, 0x1ACA05, NogcPatch0, sizeof(NogcPatch0)); AddPatch(fs_meta, 0x17FBE0, NogcPatch1, sizeof(NogcPatch1)); break; case FsVersion_21_0_0_Exfat: @@ -709,6 +715,16 @@ namespace ams::nxboot { AddPatch(fs_meta, 0x1B7B65, NogcPatch0, sizeof(NogcPatch0)); AddPatch(fs_meta, 0x18AD40, NogcPatch1, sizeof(NogcPatch1)); break; + case FsVersion_22_0_0: + AddPatch(fs_meta, 0x1B023D, NogcPatch0, sizeof(NogcPatch0)); + AddPatch(fs_meta, 0x1B0255, NogcPatch0, sizeof(NogcPatch0)); + AddPatch(fs_meta, 0x183060, NogcPatch1, sizeof(NogcPatch1)); + break; + case FsVersion_22_0_0_Exfat: + AddPatch(fs_meta, 0x1BB42D, NogcPatch0, sizeof(NogcPatch0)); + AddPatch(fs_meta, 0x1BB445, NogcPatch0, sizeof(NogcPatch0)); + AddPatch(fs_meta, 0x18E250, NogcPatch1, sizeof(NogcPatch1)); + break; default: break; } diff --git a/libraries/libexosphere/include/exosphere/pkg1/pkg1_key_generation.hpp b/libraries/libexosphere/include/exosphere/pkg1/pkg1_key_generation.hpp index 9c31c7616..f8480acc2 100644 --- a/libraries/libexosphere/include/exosphere/pkg1/pkg1_key_generation.hpp +++ b/libraries/libexosphere/include/exosphere/pkg1/pkg1_key_generation.hpp @@ -41,6 +41,7 @@ namespace ams::pkg1 { KeyGeneration_19_0_0 = 0x12, KeyGeneration_20_0_0 = 0x13, KeyGeneration_21_0_0 = 0x14, + KeyGeneration_22_0_0 = 0x15, KeyGeneration_Count, diff --git a/libraries/libexosphere/include/exosphere/pkg2.hpp b/libraries/libexosphere/include/exosphere/pkg2.hpp index be84a6ae7..d6649d9d0 100644 --- a/libraries/libexosphere/include/exosphere/pkg2.hpp +++ b/libraries/libexosphere/include/exosphere/pkg2.hpp @@ -24,7 +24,7 @@ namespace ams::pkg2 { constexpr inline int PayloadCount = 3; constexpr inline int MinimumValidDataVersion = 0; /* We allow older package2 to load; this value is currently 0x18 in Nintendo's code. */ - constexpr inline int CurrentBootloaderVersion = 0x18; + constexpr inline int CurrentBootloaderVersion = 0x17; struct Package2Meta { using Magic = util::FourCC<'P','K','2','1'>; diff --git a/libraries/libexosphere/source/fuse/fuse_api.cpp b/libraries/libexosphere/source/fuse/fuse_api.cpp index 1610af0f3..927c611b3 100644 --- a/libraries/libexosphere/source/fuse/fuse_api.cpp +++ b/libraries/libexosphere/source/fuse/fuse_api.cpp @@ -177,6 +177,7 @@ namespace ams::fuse { } constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = { + TargetFirmware_22_0_0, TargetFirmware_21_0_0, TargetFirmware_20_0_0, TargetFirmware_19_0_0, diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp index 9db423f1f..25c149b7f 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -200,6 +200,7 @@ namespace ams::kern { bool m_is_kernel; bool m_enable_aslr; bool m_enable_device_address_space_merge; + bool m_allowed_exec_device_mapping; KMemoryBlockSlabManager *m_memory_block_slab_manager; KBlockInfoManager *m_block_info_manager; KResourceLimit *m_resource_limit; @@ -217,7 +218,7 @@ namespace ams::kern { m_alias_code_region_end(Null), m_code_region_start(Null), m_code_region_end(Null), m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_insecure_memory(), m_mapped_ipc_server_memory(), m_alias_region_extra_size(), m_general_lock(), m_map_physical_memory_lock(), m_device_map_lock(), m_impl(util::ConstantInitialize), m_memory_block_manager(util::ConstantInitialize), - m_allocate_option(), m_address_space_width(), m_is_kernel(), m_enable_aslr(), m_enable_device_address_space_merge(), + m_allocate_option(), m_address_space_width(), m_is_kernel(), m_enable_aslr(), m_enable_device_address_space_merge(), m_allowed_exec_device_mapping(), m_memory_block_slab_manager(), m_block_info_manager(), m_resource_limit(), m_cached_physical_linear_region(), m_cached_physical_heap_region(), m_heap_fill_value(), m_ipc_fill_value(), m_stack_fill_value() { @@ -520,6 +521,8 @@ namespace ams::kern { size_t GetAliasCodeDataSize() const; u32 GetAllocateOption() const { return m_allocate_option; } + + void AllowDeviceMappingOfExecPages() { m_allowed_exec_device_mapping = true; } public: static ALWAYS_INLINE KVirtualAddress GetLinearMappedVirtualAddress(KPhysicalAddress addr) { return KMemoryLayout::GetLinearVirtualAddress(addr); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index 63060f900..0b0622869 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -102,8 +102,8 @@ namespace ams::kern { IoRegionList m_io_region_list; bool m_is_suspended; bool m_is_immortal; - bool m_is_jit_debug; bool m_is_handle_table_initialized; + bool m_is_jit_debug; ams::svc::DebugEvent m_jit_debug_event_type; ams::svc::DebugException m_jit_debug_exception_type; uintptr_t m_jit_debug_params[4]; diff --git a/libraries/libmesosphere/source/kern_initial_process.cpp b/libraries/libmesosphere/source/kern_initial_process.cpp index 60d8881c3..3f692ea9a 100644 --- a/libraries/libmesosphere/source/kern_initial_process.cpp +++ b/libraries/libmesosphere/source/kern_initial_process.cpp @@ -285,7 +285,7 @@ namespace ams::kern { MESOSPHERE_INIT_ABORT_UNLESS(expected_size != 0); /* Ensure that the size we need to reserve is as we expect it to be. */ - const size_t total_size = util::AlignUp(g_initial_process_binary_header.size, PageSize); + const u32 total_size = util::AlignUp(g_initial_process_binary_header.size, PageSize); MESOSPHERE_ABORT_UNLESS(total_size == expected_size); MESOSPHERE_ABORT_UNLESS(total_size <= InitialProcessBinarySizeMax); diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index ea44184fe..5d34dbe1f 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -211,6 +211,7 @@ namespace ams::kern { /* Set other basic fields. */ m_enable_aslr = (flags & ams::svc::CreateProcessFlag_EnableAslr) != 0; m_enable_device_address_space_merge = (flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0; + m_allowed_exec_device_mapping = false; m_address_space_start = start; m_address_space_end = end; m_is_kernel = false; @@ -3077,7 +3078,9 @@ namespace ams::kern { const u32 test_state = (is_aligned ? KMemoryState_FlagCanAlignedDeviceMap : KMemoryState_FlagCanDeviceMap) | (check_heap ? KMemoryState_FlagReferenceCounted : KMemoryState_None); size_t num_allocator_blocks; KMemoryState old_state; - R_TRY(this->CheckMemoryState(std::addressof(old_state), nullptr, nullptr, std::addressof(num_allocator_blocks), address, size, test_state, test_state, perm, perm, KMemoryAttribute_IpcLocked | KMemoryAttribute_Locked, KMemoryAttribute_None, KMemoryAttribute_DeviceShared)); + const KMemoryPermission perm_mask = static_cast(perm | (m_allowed_exec_device_mapping ? KMemoryPermission_None : KMemoryPermission_UserExecute)); + + R_TRY(this->CheckMemoryState(std::addressof(old_state), nullptr, nullptr, std::addressof(num_allocator_blocks), address, size, test_state, test_state, perm_mask, perm, KMemoryAttribute_IpcLocked | KMemoryAttribute_Locked, KMemoryAttribute_None, KMemoryAttribute_DeviceShared)); /* Create an update allocator. */ Result allocator_result; diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index 0d1d4b6dc..91048f4f6 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -185,6 +185,11 @@ namespace ams::kern { /* Validate that the intended kernel version isn't too high for us to support. */ R_UNLESS(m_capabilities.GetIntendedKernelVersion() <= ams::svc::SupportedKernelVersion, svc::ResultInvalidCombination()); + /* Enable mapping device pages as executable on legacy processes. */ + if (m_capabilities.GetIntendedKernelMajorVersion() < 26) { + m_page_table.GetBasePageTable().AllowDeviceMappingOfExecPages(); + } + /* Create and clear the process local region. */ R_TRY(this->CreateThreadLocalRegion(std::addressof(m_plr_address))); m_plr_heap_address = this->GetThreadLocalRegionPointer(m_plr_address); @@ -976,6 +981,9 @@ namespace ams::kern { /* Set the thread arguments. */ main_thread->GetContext().SetArguments(0, thread_handle); + /* Pass the thread handle to the thread local region. */ + static_cast(main_thread->GetThreadLocalRegionHeapAddress())->thread_handle = thread_handle; + /* Update our state. */ this->ChangeState((state == State_Created) ? State_Running : State_RunningAttached); ON_RESULT_FAILURE_2 { this->ChangeState(state); }; diff --git a/libraries/libmesosphere/source/svc/kern_svc_thread.cpp b/libraries/libmesosphere/source/svc/kern_svc_thread.cpp index 6f74dd145..14af1bb11 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_thread.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_thread.cpp @@ -66,6 +66,9 @@ namespace ams::kern::svc { /* Add the thread to the handle table. */ R_TRY(process.GetHandleTable().Add(out, thread)); + /* Pass the thread handle to the thread local region. */ + static_cast(thread->GetThreadLocalRegionHeapAddress())->thread_handle = *out; + R_SUCCEED(); } diff --git a/libraries/libstratosphere/include/stratosphere/erpt/erpt_ids.autogen.hpp b/libraries/libstratosphere/include/stratosphere/erpt/erpt_ids.autogen.hpp index 8544cd3f6..3437f5224 100644 --- a/libraries/libstratosphere/include/stratosphere/erpt/erpt_ids.autogen.hpp +++ b/libraries/libstratosphere/include/stratosphere/erpt/erpt_ids.autogen.hpp @@ -661,7 +661,7 @@ HANDLER(UsbControllerCount, 457, ConnectedControllerInfo, FieldType_NumericU8, FieldFlag_None ) \ HANDLER(ControllerTypeList, 458, ConnectedControllerInfo, FieldType_U8Array, FieldFlag_None ) \ HANDLER(ControllerInterfaceList, 459, ConnectedControllerInfo, FieldType_U8Array, FieldFlag_None ) \ - HANDLER(ControllerStyleList, 460, ConnectedControllerInfo, FieldType_U8Array, FieldFlag_None ) \ + HANDLER(ControllerStyleListDeprecated, 460, ConnectedControllerInfo, FieldType_U8Array, FieldFlag_None ) \ HANDLER(FsPooledBufferPeakFreeSize, 461, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \ HANDLER(FsPooledBufferRetriedCount, 462, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \ HANDLER(FsPooledBufferReduceAllocationCount, 463, FsMemoryInfo, FieldType_NumericU64, FieldFlag_None ) \ @@ -1014,4 +1014,4 @@ HANDLER(ModuleClockEnableFlags, 1032, PowerClockInfo, FieldType_U8Array, FieldFlag_None ) \ HANDLER(ModulePowerEnableFlags, 1033, PowerClockInfo, FieldType_U8Array, FieldFlag_None ) \ HANDLER(BluetoothAudioConnectionCount, 1034, BluetoothAudioInfo, FieldType_NumericU8, FieldFlag_None ) \ - HANDLER(ControllerStyleList, 1035, ConnectedControllerInfo, FieldType_U8Array, FieldFlag_None ) \ No newline at end of file + HANDLER(ControllerStyleList, 1035, ConnectedControllerInfo, FieldType_U8Array, FieldFlag_None ) diff --git a/libraries/libstratosphere/include/stratosphere/erpt/erpt_types.hpp b/libraries/libstratosphere/include/stratosphere/erpt/erpt_types.hpp index 93c68c6f3..9ae14fcef 100644 --- a/libraries/libstratosphere/include/stratosphere/erpt/erpt_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/erpt/erpt_types.hpp @@ -23,7 +23,7 @@ namespace ams::erpt { #define GENERATE_ENUM(NAME, ID, ...) NAME = ID, - enum FieldType { + enum FieldType: u8 { AMS_ERPT_FOREACH_FIELD_TYPE(GENERATE_ENUM) FieldType_Count, }; @@ -243,4 +243,33 @@ namespace ams::erpt { Map16 = 0xDE, }; + constexpr inline u32 ErrorCodeSizeMax = 15; + constexpr inline u32 ProgramIdSizeMax = 17; + + struct RecentReportEntry { + char error_code[ErrorCodeSizeMax]; + char program_id[ProgramIdSizeMax]; + u8 is_visible; + u8 is_system_abort; + u8 is_application_abort; + }; + static_assert(sizeof(RecentReportEntry) == 35); + + struct RecentReportSummary : public sf::LargeData, public sf::PrefersAutoSelectTransferMode { + u32 entry_count; + RecentReportEntry entries[50]; + char firmware_display_version[0x18]; + char private_os_version[96]; + char product_model[16]; + char region_code[34]; + }; + static_assert(sizeof(RecentReportSummary) == 0x784); + + struct SystemInfo { + char os_version[0x18]; + char private_os_version[96]; + char product_model[16]; + const char *region; + }; + } diff --git a/libraries/libstratosphere/include/stratosphere/erpt/sf/erpt_sf_i_manager.hpp b/libraries/libstratosphere/include/stratosphere/erpt/sf/erpt_sf_i_manager.hpp index e75bfb341..b91ade849 100644 --- a/libraries/libstratosphere/include/stratosphere/erpt/sf/erpt_sf_i_manager.hpp +++ b/libraries/libstratosphere/include/stratosphere/erpt/sf/erpt_sf_i_manager.hpp @@ -25,6 +25,7 @@ AMS_SF_METHOD_INFO(C, H, 4, Result, GetStorageUsageStatistics, (ams::sf::Out out), (out), hos::Version_5_0_0) \ AMS_SF_METHOD_INFO(C, H, 5, Result, GetAttachmentListDeprecated, (const ams::sf::OutBuffer &out_buf, const erpt::ReportId &report_id), (out_buf, report_id), hos::Version_8_0_0, hos::Version_19_0_1) \ AMS_SF_METHOD_INFO(C, H, 6, Result, GetAttachmentList, (ams::sf::Out out_count, const ams::sf::OutBuffer &out_buf, const erpt::ReportId &report_id), (out_count, out_buf, report_id), hos::Version_20_0_0) \ + AMS_SF_METHOD_INFO(C, H, 7, Result, GetRecentReportSummary, (ams::sf::Out out), (out), hos::Version_22_0_0) \ AMS_SF_METHOD_INFO(C, H, 10, Result, GetReportSizeMax, (ams::sf::Out out), (out), hos::Version_20_0_0) diff --git a/libraries/libstratosphere/include/stratosphere/erpt/srv/erpt_srv_api.hpp b/libraries/libstratosphere/include/stratosphere/erpt/srv/erpt_srv_api.hpp index 1feb10eeb..3d3ead665 100644 --- a/libraries/libstratosphere/include/stratosphere/erpt/srv/erpt_srv_api.hpp +++ b/libraries/libstratosphere/include/stratosphere/erpt/srv/erpt_srv_api.hpp @@ -21,7 +21,9 @@ namespace ams::erpt::srv { Result Initialize(u8 *mem, size_t mem_size); Result InitializeAndStartService(); - Result SetSerialNumberAndOsVersion(const char *sn, u32 sn_len, const char *os, u32 os_len, const char *os_priv, u32 os_priv_len); + const SystemInfo &GetSystemInfo(); + + Result SetSerialNumber(const char *sn, u32 sn_len); Result SetProductModel(const char *model, u32 model_len); Result SetRegionSetting(const char *region, u32 region_len); diff --git a/libraries/libstratosphere/include/stratosphere/fssrv/sf/fssrv_sf_i_file_system_proxy.hpp b/libraries/libstratosphere/include/stratosphere/fssrv/sf/fssrv_sf_i_file_system_proxy.hpp index 5ccee0cdf..44b54ff12 100644 --- a/libraries/libstratosphere/include/stratosphere/fssrv/sf/fssrv_sf_i_file_system_proxy.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssrv/sf/fssrv_sf_i_file_system_proxy.hpp @@ -132,7 +132,7 @@ AMS_SF_METHOD_INFO(C, H, 1000, Result, SetBisRootForHost, (u32 id, const fssrv::sf::FspPath &path), (id, path), hos::Version_Min, hos::Version_9_2_0) \ AMS_SF_METHOD_INFO(C, H, 1001, Result, SetSaveDataSize, (s64 size, s64 journal_size), (size, journal_size)) \ AMS_SF_METHOD_INFO(C, H, 1002, Result, SetSaveDataRootPath, (const fssrv::sf::FspPath &path), (path)) \ - AMS_SF_METHOD_INFO(C, H, 1003, Result, DisableAutoSaveDataCreation, (), ()) \ + AMS_SF_METHOD_INFO(C, H, 1003, Result, DisableAutoSaveDataCreation, (), (), hos::Version_Min, hos::Version_21_2_0) \ AMS_SF_METHOD_INFO(C, H, 1004, Result, SetGlobalAccessLogMode, (u32 mode), (mode)) \ AMS_SF_METHOD_INFO(C, H, 1005, Result, GetGlobalAccessLogMode, (ams::sf::Out out), (out)) \ AMS_SF_METHOD_INFO(C, H, 1006, Result, OutputAccessLogToSdCard, (const ams::sf::InBuffer &buf), (buf)) \ diff --git a/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp b/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp index 13e1f96a8..e5e58957e 100644 --- a/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/hos/hos_types.hpp @@ -100,6 +100,7 @@ namespace ams::hos { Version_21_0_1 = ::ams::TargetFirmware_21_0_1, Version_21_1_0 = ::ams::TargetFirmware_21_1_0, Version_21_2_0 = ::ams::TargetFirmware_21_2_0, + Version_22_0_0 = ::ams::TargetFirmware_22_0_0, Version_Current = ::ams::TargetFirmware_Current, diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal_for_attachments.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal_for_attachments.cpp index 77c958fbf..d2a9bedfb 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal_for_attachments.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_journal_for_attachments.cpp @@ -84,7 +84,7 @@ namespace ams::erpt::srv { Result JournalForAttachments::GetAttachmentList(u32 *out_count, AttachmentInfo *out_infos, size_t max_out_infos, ReportId report_id) { if (hos::GetVersion() >= hos::Version_20_0_0) { /* TODO: What define gives a minimum of 10? */ - R_UNLESS(max_out_infos >= 10, erpt::ResultInvalidArgument()); + R_UNLESS(max_out_infos >= 10, erpt::ResultTooManyOutAttachments()); } u32 count = 0; diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_main.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_main.cpp index 8447fbb4c..f6103820b 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_main.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_main.cpp @@ -21,6 +21,7 @@ #include "erpt_srv_journal.hpp" #include "erpt_srv_service.hpp" #include "erpt_srv_forced_shutdown.hpp" +#include "erpt_srv_recent_report.hpp" namespace ams::erpt::srv { @@ -33,6 +34,7 @@ namespace ams::erpt::srv { constexpr u32 SystemSaveDataFlags = fs::SaveDataFlags_KeepAfterResettingSystemSaveDataWithoutUserSaveData; constexpr s64 SystemSaveDataSize = 11_MB; constexpr s64 SystemSaveDataJournalSize = 2720_KB; + constexpr u32 DefaultThrottleTimeWindowSeconds = 3; constinit bool g_automatic_report_cleanup_enabled = true; @@ -53,7 +55,9 @@ namespace ams::erpt::srv { } Result MountSystemSaveData() { - fs::DisableAutoSaveDataCreation(); + if (hos::GetVersion() < hos::Version_21_0_0) { + fs::DisableAutoSaveDataCreation(); + } /* Extend the system save data. */ /* NOTE: Nintendo used to not check the result of this; they do now, but . */ @@ -71,6 +75,72 @@ namespace ams::erpt::srv { } + namespace { + + int MakeProductModelString(char *dst, size_t dst_size, settings::system::ProductModel model) { + switch (model) { + case settings::system::ProductModel_Invalid: return util::Strlcpy(dst, "Invalid", static_cast(dst_size)); + case settings::system::ProductModel_Nx: return util::Strlcpy(dst, "NX", static_cast(dst_size)); + default: return util::SNPrintf(dst, dst_size, "%d", static_cast(model)); + } + } + + const char *GetRegionString(settings::system::RegionCode code) { + switch (code) { + case settings::system::RegionCode_Japan: return "Japan"; + case settings::system::RegionCode_Usa: return "Usa"; + case settings::system::RegionCode_Europe: return "Europe"; + case settings::system::RegionCode_Australia: return "Australia"; + case settings::system::RegionCode_HongKongTaiwanKorea: return "HongKongTaiwanKorea"; + case settings::system::RegionCode_China: return "China"; + default: return "RegionUnknown"; + } + } + + } + + const erpt::SystemInfo &GetSystemInfo() { + static const erpt::SystemInfo s_info = [] { + erpt::SystemInfo info = {}; + + settings::system::FirmwareVersion firmware_version = {}; + settings::system::GetFirmwareVersion(std::addressof(firmware_version)); + + util::Strlcpy(info.os_version, firmware_version.display_version, sizeof(info.os_version)); + + const auto os_priv_len = util::SNPrintf(info.private_os_version, sizeof(info.private_os_version), "%s (%.8s)", firmware_version.display_name, firmware_version.revision); + AMS_ASSERT(static_cast(os_priv_len) < sizeof(info.private_os_version)); + AMS_UNUSED(os_priv_len); + + const auto pm_len = MakeProductModelString(info.product_model, sizeof(info.product_model), settings::system::GetProductModel()); + AMS_ASSERT(static_cast(pm_len) < sizeof(info.product_model)); + AMS_UNUSED(pm_len); + + settings::system::RegionCode region_code; + settings::system::GetRegionCode(std::addressof(region_code)); + info.region = GetRegionString(region_code); + + return info; + }(); + return s_info; + } + + u32 GetThrottleTimeWindowSecondsImpl() { + u32 seconds = DefaultThrottleTimeWindowSeconds; + if (settings::fwdbg::GetSettingsItemValue(std::addressof(seconds), sizeof(seconds), "erpt", "throttle_time_window_seconds") != sizeof(seconds)) { + return DefaultThrottleTimeWindowSeconds; + } + return seconds; + } + + void SetReportThrottleTimeSpan() { + u32 seconds = GetThrottleTimeWindowSecondsImpl(); + + const TimeSpan time_span = TimeSpan::FromSeconds(static_cast(seconds)); + + Reporter::SetThrottleTimeSpan(time_span); + } + Result Initialize(u8 *mem, size_t mem_size) { R_ABORT_UNLESS(time::Initialize()); @@ -101,6 +171,10 @@ namespace ams::erpt::srv { } } + if (hos::GetVersion() >= hos::Version_22_0_0) { + SetReportThrottleTimeSpan(); + } + R_ABORT_UNLESS(MountSystemSaveData()); g_sf_allocator.Attach(g_heap_handle); @@ -110,8 +184,18 @@ namespace ams::erpt::srv { AMS_ABORT_UNLESS(ctx != nullptr); } - if (R_FAILED(Journal::Restore())) { - /* TODO: Nintendo deletes system savedata when this fails. Should we?. */ + if (hos::GetVersion() >= hos::Version_21_0_0) { + /* >= 21.0.0, Nintendo checks the result of restore and deletes the save data if it fails. */ + if (R_FAILED(Journal::Restore())) { + /* Delete and recreate the system save data. */ + fs::Unmount(ReportStoragePath); + R_ABORT_UNLESS(fs::DeleteSystemSaveData(fs::SaveDataSpaceId::System, SystemSaveDataId, fs::InvalidUserId)); + + R_ABORT_UNLESS(MountSystemSaveData()); + } + } else{ + /* Pre 21.0.0, Nintendo just calls restore and ignores the result. */ + Journal::Restore(); } Reporter::UpdatePowerOnTime(); @@ -128,8 +212,8 @@ namespace ams::erpt::srv { R_RETURN(InitializeService()); } - Result SetSerialNumberAndOsVersion(const char *sn, u32 sn_len, const char *os, u32 os_len, const char *os_priv, u32 os_priv_len) { - R_RETURN(Reporter::SetSerialNumberAndOsVersion(sn, sn_len, os, os_len, os_priv, os_priv_len)); + Result SetSerialNumber(const char *sn, u32 sn_len) { + R_RETURN(Reporter::SetSerialNumber(sn, sn_len)); } Result SetProductModel(const char *model, u32 model_len) { diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_manager_impl.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_manager_impl.cpp index 668610ba0..62f072e86 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_manager_impl.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_manager_impl.cpp @@ -16,6 +16,7 @@ #include #include "erpt_srv_manager_impl.hpp" #include "erpt_srv_journal.hpp" +#include "erpt_srv_recent_report.hpp" namespace ams::erpt::srv { @@ -59,6 +60,7 @@ namespace ams::erpt::srv { Result ManagerImpl::CleanupReports() { Journal::CleanupReports(); Journal::CleanupAttachments(); + RecentReport::Clear(); R_RETURN(Journal::Commit()); } @@ -99,9 +101,15 @@ namespace ams::erpt::srv { Result ManagerImpl::GetReportSizeMax(ams::sf::Out out) { /* TODO: Where is this size defined? */ - constexpr size_t ReportSizeMax = 0x3FF4F; + constexpr size_t ReportSizeMax = 0x35D3D; *out = ReportSizeMax; R_SUCCEED(); } + Result ManagerImpl::GetRecentReportSummary(ams::sf::Out out) { + RecentReport::GetSummary(out.GetPointer()); + R_SUCCEED(); + } + + } diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_manager_impl.hpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_manager_impl.hpp index a4f55bb30..81b76ef82 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_manager_impl.hpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_manager_impl.hpp @@ -36,6 +36,7 @@ namespace ams::erpt::srv { Result GetStorageUsageStatistics(ams::sf::Out out); Result GetAttachmentListDeprecated(const ams::sf::OutBuffer &out_buf, const ReportId &report_id); Result GetAttachmentList(ams::sf::Out out_count, const ams::sf::OutBuffer &out_buf, const ReportId &report_id); + Result GetRecentReportSummary(ams::sf::Out out); Result GetReportSizeMax(ams::sf::Out out); }; static_assert(erpt::sf::IsIManager); diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_recent_report.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_recent_report.cpp new file mode 100644 index 000000000..ac3815185 --- /dev/null +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_recent_report.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 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 . + */ +#include +#include "erpt_srv_recent_report.hpp" + +namespace ams::erpt::srv { + + namespace { + + constexpr size_t MaxEntriesPerType = 25; + + struct RecentReportState { + u32 report_counts[ReportType_Count]; + RecentReportEntry report_entries[ReportType_Count][MaxEntriesPerType]; + os::Tick last_tick; + u32 consecutive_count; + }; + + constinit RecentReportState g_state = { + .report_counts = {}, + .report_entries = {}, + .last_tick = os::Tick{}, + .consecutive_count = 0, + }; + + } + + void RecentReport::PushEntry(const char *error_code, const char *program_id, ReportType type, bool is_system_abort, bool is_application_abort) { + u32 &count = g_state.report_counts[type]; + RecentReportEntry *entries = g_state.report_entries[type]; + + /* If we're full, shift the oldest entry out. */ + if (count >= MaxEntriesPerType) { + std::memmove(entries, entries + 1, sizeof(RecentReportEntry) * (MaxEntriesPerType - 1)); + count = MaxEntriesPerType - 1; + } + + /* Fill the new entry. */ + RecentReportEntry &entry = entries[count]; + util::Strlcpy(entry.error_code, error_code, sizeof(entry.error_code)); + util::Strlcpy(entry.program_id, program_id, sizeof(entry.program_id)); + entry.is_visible = (type == ReportType_Visible); + entry.is_system_abort = is_system_abort; + entry.is_application_abort = is_application_abort; + + count++; + } + + void RecentReport::GetSummary(RecentReportSummary *out) { + /* Fill basic info from lazily-initialized system info. */ + const auto &sys_info = srv::GetSystemInfo(); + util::Strlcpy(out->firmware_display_version, sys_info.os_version, sizeof(out->firmware_display_version)); + util::Strlcpy(out->private_os_version, sys_info.private_os_version, sizeof(out->private_os_version)); + util::Strlcpy(out->product_model, sys_info.product_model, sizeof(out->product_model)); + util::Strlcpy(out->region_code, sys_info.region, sizeof(out->region_code)); + + u32 total_count = 0; + + /* Copy entries. */ + for (u32 i = 0; i < ReportType_Count; i++) { + if (g_state.report_counts[i] == 0) { + continue; + } + std::memcpy(out->entries + total_count, g_state.report_entries[i], sizeof(RecentReportEntry) * g_state.report_counts[i]); + total_count += g_state.report_counts[i]; + + /* Reset count (destructive read). */ + g_state.report_counts[i] = 0; + } + + out->entry_count = total_count; + } + + void RecentReport::Clear() { + for (u32 i = 0; i < ReportType_Count; i++) { + g_state.report_counts[i] = 0; + } + } + +} \ No newline at end of file diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_recent_report.hpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_recent_report.hpp new file mode 100644 index 000000000..065f82250 --- /dev/null +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_recent_report.hpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 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::erpt::srv { + + class RecentReport { + public: + static void PushEntry(const char *error_code, const char *program_id, ReportType type, bool is_system_abort, bool is_application_abort); + static void GetSummary(RecentReportSummary *out); + static void Clear(); + }; + +} \ No newline at end of file diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp index 995ffe30b..0ef5e2f61 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.cpp @@ -20,13 +20,12 @@ #include "erpt_srv_context_record.hpp" #include "erpt_srv_context.hpp" #include "erpt_srv_fs_info.hpp" +#include "erpt_srv_recent_report.hpp" namespace ams::erpt::srv { constinit bool Reporter::s_redirect_new_reports = true; constinit char Reporter::s_serial_number[24] = "Unknown"; - constinit char Reporter::s_os_version[24] = "Unknown"; - constinit char Reporter::s_private_os_version[96] = "Unknown"; constinit util::optional Reporter::s_application_launch_time; constinit util::optional Reporter::s_awake_time; constinit util::optional Reporter::s_power_on_time; @@ -212,18 +211,83 @@ namespace ams::erpt::srv { } #endif - Result ValidateCreateReportContext(const ContextEntry *ctx) { + Result ValidateAndGetErrorCode(const ContextEntry *ctx, char *out_error_code) { R_UNLESS(ctx->category == CategoryId_ErrorInfo, erpt::ResultRequiredContextMissing()); R_UNLESS(ctx->field_count <= FieldsPerContext, erpt::ResultInvalidArgument()); - const bool found_error_code = util::range::any_of(MakeSpan(ctx->fields, ctx->field_count), [] (const FieldEntry &entry) { - return entry.id == FieldId_ErrorCode; - }); - R_UNLESS(found_error_code, erpt::ResultRequiredFieldMissing()); + const auto fields_span = MakeSpan(ctx->fields, ctx->field_count); + const u8 *array_data = static_cast(ctx->array_buffer); + + const FieldEntry *error_code_field = nullptr; + + for (const auto &field : fields_span) { + if (field.id != FieldId_ErrorCode){ + continue; + } + error_code_field = &field; + break; + } + + R_UNLESS(error_code_field != nullptr, erpt::ResultRequiredFieldMissing()); + R_UNLESS(error_code_field->type == FieldType_String, erpt::ResultFieldTypeMismatch()); + R_UNLESS(error_code_field->value_array.size <= ErrorCodeSizeMax, erpt::ResultArrayFieldTooLarge()); + + const char *error_code = reinterpret_cast(array_data + error_code_field->value_array.start_idx); + util::Strlcpy(out_error_code, error_code, ErrorCodeSizeMax); R_SUCCEED(); } + namespace { + struct ThrottleState { + TimeSpan throttle_time_span; + char last_error_code[ErrorCodeSizeMax]; + u32 consecutive_count; + os::Tick last_tick; + }; + constinit ThrottleState g_throttle_state = { + .throttle_time_span = TimeSpan{}, + .last_error_code = {}, + .consecutive_count = 0, + .last_tick = os::Tick{}, + }; + }; + bool IsThrottledReport(const ContextEntry *ctx, ReportType type, const char *error_code) { + if (hos::GetVersion() < hos::Version_22_0_0) { + return false; + } + + const auto fields_span = MakeSpan(ctx->fields, ctx->field_count); + bool is_crash_report = false; + + for (const auto &field : fields_span) { + if (field.id != FieldId_CrashReportFlag){ + continue; + } + is_crash_report = field.value_bool; + break; + } + + if(type == ReportType_Visible || is_crash_report){ + return false; + } + + const auto now = os::GetSystemTick(); + const TimeSpan elapsed = (now - g_throttle_state.last_tick).ToTimeSpan(); + + if (std::strcmp(g_throttle_state.last_error_code, error_code) == 0 && elapsed < g_throttle_state.throttle_time_span) { + if (g_throttle_state.consecutive_count >= 5) { + return true; + } + g_throttle_state.consecutive_count++; + } else { + util::Strlcpy(g_throttle_state.last_error_code, error_code, sizeof(g_throttle_state.last_error_code)); + g_throttle_state.last_tick = now; + g_throttle_state.consecutive_count = 1; + } + + return false; + } Result SubmitReportDefaults(const ContextEntry *ctx) { AMS_ASSERT(ctx->category == CategoryId_ErrorInfo); @@ -381,6 +445,9 @@ namespace ams::erpt::srv { } + void Reporter::SetThrottleTimeSpan(TimeSpan time_span) { + g_throttle_state.throttle_time_span = time_span; + } Result Reporter::RegisterRunningApplet(ncm::ProgramId program_id) { g_applet_active_time_info_list.Register(program_id); R_SUCCEED(); @@ -427,12 +494,51 @@ namespace ams::erpt::srv { /* Get the context entry pointer. */ const ContextEntry *ctx = record->GetContextEntryPtr(); - /* Validate the context. */ - R_TRY(ValidateCreateReportContext(ctx)); + /* Validate the context and retrieve the error code. */ + char error_code[ErrorCodeSizeMax]; + R_TRY(ValidateAndGetErrorCode(ctx, error_code)); + + if (hos::GetVersion() >= hos::Version_22_0_0) { + /* Check if we should throttle the report. */ + if (IsThrottledReport(ctx, type, error_code)) { + R_SUCCEED(); + } + } /* Submit report defaults. */ R_TRY(SubmitReportDefaults(ctx)); + /* Push to recent reports. */ + if (hos::GetVersion() >= hos::Version_22_0_0) { + const auto fields_span = MakeSpan(ctx->fields, ctx->field_count); + const u8 *array_data = static_cast(ctx->array_buffer); + + char program_id[ProgramIdSizeMax] = {}; + bool is_system_abort = false; + bool is_application_abort = false; + + for (const auto &field : fields_span) { + switch (field.id) { + case FieldId_ProgramId: + if(field.type != FieldType_String){ + break; + } + util::Strlcpy(program_id, reinterpret_cast(array_data + field.value_array.start_idx), sizeof(program_id)); + break; + case FieldId_SystemAbortFlag: + is_system_abort = field.value_bool; + break; + case FieldId_ApplicationAbortFlag: + is_application_abort = field.value_bool; + break; + default: + break; + } + } + + RecentReport::PushEntry(error_code, program_id, type, is_system_abort, is_application_abort); + } + /* Generate report id. */ const ReportId report_id = specified_report_id ? *specified_report_id : ReportId{ .uuid = util::GenerateUuid() }; @@ -480,8 +586,9 @@ namespace ams::erpt::srv { R_ABORT_UNLESS(time::GetStandardSteadyClockCurrentTimePoint(std::addressof(steady_clock_current_timepoint))); /* Add automatic fields. */ - static_cast(auto_record->Add(FieldId_OsVersion, s_os_version, util::Strnlen(s_os_version, sizeof(s_os_version)))); - static_cast(auto_record->Add(FieldId_PrivateOsVersion, s_private_os_version, util::Strnlen(s_private_os_version, sizeof(s_private_os_version)))); + const auto &sys_info = srv::GetSystemInfo(); + static_cast(auto_record->Add(FieldId_OsVersion, sys_info.os_version, util::Strnlen(sys_info.os_version, sizeof(sys_info.os_version)))); + static_cast(auto_record->Add(FieldId_PrivateOsVersion, sys_info.private_os_version, util::Strnlen(sys_info.private_os_version, sizeof(sys_info.private_os_version)))); static_cast(auto_record->Add(FieldId_SerialNumber, s_serial_number, util::Strnlen(s_serial_number, sizeof(s_serial_number)))); static_cast(auto_record->Add(FieldId_ReportIdentifier, identifier_str, util::Strnlen(identifier_str, sizeof(identifier_str)))); static_cast(auto_record->Add(FieldId_OccurrenceTimestamp, timestamp_user.value)); diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.hpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.hpp index 48660542f..324c17c19 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.hpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_reporter.hpp @@ -23,8 +23,6 @@ namespace ams::erpt::srv { private: static bool s_redirect_new_reports; static char s_serial_number[24]; - static char s_os_version[24]; - static char s_private_os_version[96]; static util::optional s_application_launch_time; static util::optional s_awake_time; static util::optional s_power_on_time; @@ -39,14 +37,11 @@ namespace ams::erpt::srv { static void UpdateAwakeTime() { s_awake_time = os::GetSystemTick(); } static void UpdatePowerOnTime() { s_power_on_time = os::GetSystemTick(); } - static Result SetSerialNumberAndOsVersion(const char *sn, u32 sn_len, const char *os, u32 os_len, const char *os_priv, u32 os_priv_len) { - R_UNLESS(sn_len <= sizeof(s_serial_number), erpt::ResultInvalidArgument()); - R_UNLESS(os_len <= sizeof(s_os_version), erpt::ResultInvalidArgument()); - R_UNLESS(os_priv_len <= sizeof(s_private_os_version), erpt::ResultInvalidArgument()); + static void SetThrottleTimeSpan(TimeSpan time_span); + static Result SetSerialNumber(const char *sn, u32 sn_len) { + R_UNLESS(sn_len <= sizeof(s_serial_number), erpt::ResultInvalidArgument()); std::memcpy(s_serial_number, sn, sn_len); - std::memcpy(s_os_version, os, os_len); - std::memcpy(s_private_os_version, os_priv, os_priv_len); R_SUCCEED(); } diff --git a/libraries/libstratosphere/source/fs/fs_save_data_management.cpp b/libraries/libstratosphere/source/fs/fs_save_data_management.cpp index 0e9bdeb1a..5bca5e787 100644 --- a/libraries/libstratosphere/source/fs/fs_save_data_management.cpp +++ b/libraries/libstratosphere/source/fs/fs_save_data_management.cpp @@ -42,6 +42,10 @@ namespace ams::fs { } void DisableAutoSaveDataCreation() { + if (hos::GetVersion() >= hos::Version_22_0_0) { + return; + } + auto fsp = impl::GetFileSystemProxyServiceObject(); AMS_FS_R_ABORT_UNLESS(fsp->DisableAutoSaveDataCreation()); } diff --git a/libraries/libstratosphere/source/fs/impl/fs_id_string_impl.os.generic.cpp b/libraries/libstratosphere/source/fs/impl/fs_id_string_impl.os.generic.cpp index aa8963d97..f38e8b4be 100644 --- a/libraries/libstratosphere/source/fs/impl/fs_id_string_impl.os.generic.cpp +++ b/libraries/libstratosphere/source/fs/impl/fs_id_string_impl.os.generic.cpp @@ -21,7 +21,7 @@ namespace ams::fs::impl { #define ADD_ENUM_CASE(v) case v: return #v template<> const char *IdString::ToString(pkg1::KeyGeneration id) { - static_assert(pkg1::KeyGeneration_Current == pkg1::KeyGeneration_21_0_0); + static_assert(pkg1::KeyGeneration_Current == pkg1::KeyGeneration_22_0_0); switch (id) { using enum pkg1::KeyGeneration; case KeyGeneration_1_0_0: return "1.0.0-2.3.0"; @@ -44,7 +44,8 @@ namespace ams::fs::impl { case KeyGeneration_18_0_0: return "18.0.0-18.1.0"; case KeyGeneration_19_0_0: return "19.0.0-19.0.1"; case KeyGeneration_20_0_0: return "20.0.0-20.5.0"; - case KeyGeneration_21_0_0: return "21.0.0-"; + case KeyGeneration_21_0_0: return "21.0.0-21.2.0"; + case KeyGeneration_22_0_0: return "22.0.0"; default: return "Unknown"; } } diff --git a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp index 84ff19938..827a02c1c 100644 --- a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp +++ b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_board_driver_api.cpp @@ -17,6 +17,7 @@ #include "pinmux_pad_index.hpp" #include "pinmux_board_driver_api.hpp" #include "pinmux_platform_pads.hpp" +#include "pinmux_build_config.hpp" namespace ams::pinmux::driver::board::nintendo::nx { @@ -99,6 +100,31 @@ namespace ams::pinmux::driver::board::nintendo::nx { UpdateSinglePinmuxPad({ PinmuxPadIndex_Sdmmc2Dat6, 0x2000, 0x2000 }); UpdateSinglePinmuxPad({ PinmuxPadIndex_Sdmmc2Dat7, 0x2000, 0x2000 }); } + + #if defined(AMS_PINMUX_CONFIG_RIGHT_RAIL_AS_UART) + UpdateSinglePinmuxPad({ + .index = PinmuxPadIndex_Uart2Tx, + .option = 0, /* PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output */ + .option_mask = (0x7|0x18|0x60), /* PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir */ + }); + UpdateSinglePinmuxPad({ + .index = PinmuxPadIndex_Uart2Cts, + .option = 0x20, /* PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input */ + .option_mask = (0x7|0x18|0x60), /* PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir */ + }); + #endif + #if defined(AMS_PINMUX_CONFIG_LEFT_RAIL_AS_UART) + UpdateSinglePinmuxPad({ + .index = PinmuxPadIndex_Uart3Tx, + .option = 0, /* PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Output */ + .option_mask = (0x7|0x18|0x60), /* PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir */ + }); + UpdateSinglePinmuxPad({ + .index = PinmuxPadIndex_Uart3Cts, + .option = 0x20, /* PinmuxPadPm_Pm0 | PinmuxOpt_NoPupd | PinmuxOpt_Input */ + .option_mask = (0x7|0x18|0x60), /* PinmuxOptBitMask_Pm | PinmuxOptBitMask_Pupd | PinmuxOptBitMask_Dir */ + }); + #endif } void SetInitialDrivePadConfig() { diff --git a/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_build_config.hpp b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_build_config.hpp new file mode 100644 index 000000000..530af4325 --- /dev/null +++ b/libraries/libstratosphere/source/pinmux/driver/board/nintendo/nx/pinmux_build_config.hpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 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 + +// #define AMS_PINMUX_CONFIG_RIGHT_RAIL_AS_UART +// #define AMS_PINMUX_CONFIG_LEFT_RAIL_AS_UART \ No newline at end of file diff --git a/libraries/libvapours/include/vapours/ams/ams_api_version.h b/libraries/libvapours/include/vapours/ams/ams_api_version.h index facb03cfe..b8c678212 100644 --- a/libraries/libvapours/include/vapours/ams/ams_api_version.h +++ b/libraries/libvapours/include/vapours/ams/ams_api_version.h @@ -16,11 +16,11 @@ #pragma once #define ATMOSPHERE_RELEASE_VERSION_MAJOR 1 -#define ATMOSPHERE_RELEASE_VERSION_MINOR 10 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 2 +#define ATMOSPHERE_RELEASE_VERSION_MINOR 11 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 0 #define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO -#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 21 -#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 2 +#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 22 +#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0 diff --git a/libraries/libvapours/include/vapours/ams/ams_target_firmware.h b/libraries/libvapours/include/vapours/ams/ams_target_firmware.h index 55a2bbc2d..279b3dd15 100644 --- a/libraries/libvapours/include/vapours/ams/ams_target_firmware.h +++ b/libraries/libvapours/include/vapours/ams/ams_target_firmware.h @@ -98,8 +98,9 @@ #define ATMOSPHERE_TARGET_FIRMWARE_21_0_1 ATMOSPHERE_TARGET_FIRMWARE(21, 0, 1) #define ATMOSPHERE_TARGET_FIRMWARE_21_1_0 ATMOSPHERE_TARGET_FIRMWARE(21, 1, 0) #define ATMOSPHERE_TARGET_FIRMWARE_21_2_0 ATMOSPHERE_TARGET_FIRMWARE(21, 2, 0) +#define ATMOSPHERE_TARGET_FIRMWARE_22_0_0 ATMOSPHERE_TARGET_FIRMWARE(22, 0, 0) -#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_21_2_0 +#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_22_0_0 #define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT @@ -190,6 +191,7 @@ namespace ams { TargetFirmware_21_0_1 = ATMOSPHERE_TARGET_FIRMWARE_21_0_1, TargetFirmware_21_1_0 = ATMOSPHERE_TARGET_FIRMWARE_21_1_0, TargetFirmware_21_2_0 = ATMOSPHERE_TARGET_FIRMWARE_21_2_0, + TargetFirmware_22_0_0 = ATMOSPHERE_TARGET_FIRMWARE_22_0_0, TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT, diff --git a/libraries/libvapours/include/vapours/results/erpt_results.hpp b/libraries/libvapours/include/vapours/results/erpt_results.hpp index 10c1b9aa9..093f2f25f 100644 --- a/libraries/libvapours/include/vapours/results/erpt_results.hpp +++ b/libraries/libvapours/include/vapours/results/erpt_results.hpp @@ -40,5 +40,6 @@ namespace ams::erpt { R_DEFINE_ERROR_RESULT(InvalidPowerState, 17); R_DEFINE_ERROR_RESULT(ArrayFieldTooLarge, 18); R_DEFINE_ERROR_RESULT(AlreadyOwned, 19); + R_DEFINE_ERROR_RESULT(TooManyOutAttachments, 51); } diff --git a/libraries/libvapours/include/vapours/svc/arch/arm/svc_thread_local_region.hpp b/libraries/libvapours/include/vapours/svc/arch/arm/svc_thread_local_region.hpp index 9fdd954af..69caab7c4 100644 --- a/libraries/libvapours/include/vapours/svc/arch/arm/svc_thread_local_region.hpp +++ b/libraries/libvapours/include/vapours/svc/arch/arm/svc_thread_local_region.hpp @@ -27,8 +27,9 @@ namespace ams::svc::arch::arm { volatile u16 interrupt_flag; volatile u8 cache_maintenance_flag; volatile s64 thread_cpu_time; + volatile ams::svc::Handle thread_handle; /* TODO: Should we bother adding the Nintendo aarch32 thread local context here? */ - uintptr_t TODO[(0x200 - 0x110) / sizeof(uintptr_t)]; + uintptr_t TODO[(0x200 - 0x114) / sizeof(uintptr_t)]; }; ALWAYS_INLINE ThreadLocalRegion *GetThreadLocalRegion() { diff --git a/libraries/libvapours/include/vapours/svc/arch/arm64/svc_thread_local_region.hpp b/libraries/libvapours/include/vapours/svc/arch/arm64/svc_thread_local_region.hpp index f3146dcbf..390d3cb0f 100644 --- a/libraries/libvapours/include/vapours/svc/arch/arm64/svc_thread_local_region.hpp +++ b/libraries/libvapours/include/vapours/svc/arch/arm64/svc_thread_local_region.hpp @@ -27,8 +27,9 @@ namespace ams::svc::arch::arm64 { volatile u16 interrupt_flag; volatile u8 cache_maintenance_flag; volatile s64 thread_cpu_time; + volatile ams::svc::Handle thread_handle; /* TODO: How should we handle libnx vs Nintendo user thread local space? */ - uintptr_t TODO[(0x200 - 0x110) / sizeof(uintptr_t)]; + uintptr_t TODO[(0x200 - 0x114) / sizeof(uintptr_t)]; }; static_assert(__builtin_offsetof(ThreadLocalRegion, disable_count) == 0x100); static_assert(__builtin_offsetof(ThreadLocalRegion, interrupt_flag) == 0x102); diff --git a/libraries/libvapours/include/vapours/svc/svc_version.hpp b/libraries/libvapours/include/vapours/svc/svc_version.hpp index 4ea900fb7..500da0e21 100644 --- a/libraries/libvapours/include/vapours/svc/svc_version.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_version.hpp @@ -57,8 +57,8 @@ namespace ams::svc { /* This is the highest SVC version supported by Atmosphere, to be updated on new kernel releases. */ /* NOTE: Official kernel versions have SVC major = SDK major + 4, SVC minor = SDK minor. */ - constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(20); - constexpr inline u32 SupportedKernelMinorVersion = ConvertToSvcMinorVersion( 5); + constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(22); + constexpr inline u32 SupportedKernelMinorVersion = ConvertToSvcMinorVersion( 2); constexpr inline u32 SupportedKernelVersion = EncodeKernelVersion(SupportedKernelMajorVersion, SupportedKernelMinorVersion); diff --git a/stratosphere/erpt/source/erpt_main.cpp b/stratosphere/erpt/source/erpt_main.cpp index d95a0ae60..93096dbcb 100644 --- a/stratosphere/erpt/source/erpt_main.cpp +++ b/stratosphere/erpt/source/erpt_main.cpp @@ -26,26 +26,6 @@ namespace ams { } - int MakeProductModelString(char *dst, size_t dst_size, settings::system::ProductModel model) { - switch (model) { - case settings::system::ProductModel_Invalid: return util::Strlcpy(dst, "Invalid", static_cast(dst_size)); - case settings::system::ProductModel_Nx: return util::Strlcpy(dst, "NX", static_cast(dst_size)); - default: return util::SNPrintf(dst, dst_size, "%d", static_cast(model)); - } - } - - const char *GetRegionString(settings::system::RegionCode code) { - switch (code) { - case settings::system::RegionCode_Japan: return "Japan"; - case settings::system::RegionCode_Usa: return "Usa"; - case settings::system::RegionCode_Europe: return "Europe"; - case settings::system::RegionCode_Australia: return "Australia"; - case settings::system::RegionCode_HongKongTaiwanKorea: return "HongKongTaiwanKorea"; - case settings::system::RegionCode_China: return "China"; - default: return "RegionUnknown"; - } - } - } namespace init { @@ -94,42 +74,19 @@ namespace ams { /* Atmosphere always wants to redirect new reports to the SD card, to prevent them from being logged. */ erpt::srv::SetRedirectNewReportsToSdCard(true); - /* Configure the OS version. */ + /* Configure the serial number, OS version, product model, and region. */ { - settings::system::FirmwareVersion firmware_version = {}; + const auto &sys_info = erpt::srv::GetSystemInfo(); + settings::system::SerialNumber serial_number = {}; - settings::system::GetFirmwareVersion(std::addressof(firmware_version)); settings::system::GetSerialNumber(std::addressof(serial_number)); - char os_private[0x60]; - const auto os_priv_len = util::SNPrintf(os_private, sizeof(os_private), "%s (%.8s)", firmware_version.display_name, firmware_version.revision); - AMS_ASSERT(static_cast(os_priv_len) < sizeof(os_private)); - AMS_UNUSED(os_priv_len); + R_ABORT_UNLESS(erpt::srv::SetSerialNumber(serial_number.str, + strnlen(serial_number.str, sizeof(serial_number.str) - 1) + 1)); - R_ABORT_UNLESS(erpt::srv::SetSerialNumberAndOsVersion(serial_number.str, - strnlen(serial_number.str, sizeof(serial_number.str) - 1) + 1, - firmware_version.display_version, - strnlen(firmware_version.display_version, sizeof(firmware_version.display_version) - 1) + 1, - os_private, - strnlen(os_private, sizeof(os_private) - 1) + 1)); - } + R_ABORT_UNLESS(erpt::srv::SetProductModel(sys_info.product_model, static_cast(std::strlen(sys_info.product_model)))); - /* Configure the product model. */ - { - char product_model[0x10]; - const auto pm_len = erpt::MakeProductModelString(product_model, sizeof(product_model), settings::system::GetProductModel()); - AMS_ASSERT(static_cast(pm_len) < sizeof(product_model)); - AMS_UNUSED(pm_len); - - R_ABORT_UNLESS(erpt::srv::SetProductModel(product_model, static_cast(std::strlen(product_model)))); - } - - /* Configure the region. */ - { - settings::system::RegionCode code; - settings::system::GetRegionCode(std::addressof(code)); - const char *region_str = erpt::GetRegionString(code); - R_ABORT_UNLESS(erpt::srv::SetRegionSetting(region_str, static_cast(std::strlen(region_str)))); + R_ABORT_UNLESS(erpt::srv::SetRegionSetting(sys_info.region, static_cast(std::strlen(sys_info.region)))); } /* Start the erpt server. */