Implement cfg UUID Clock Sequence (#7169)

* Implement cfg UUID Clock Sequence

* Remove unneeded variable.

* Apply suggestions

* Apply suggestions
This commit is contained in:
PabloMK7 2023-11-21 05:05:16 +01:00 committed by GitHub
parent 52254537b7
commit f8ae41dfe3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 102 additions and 1 deletions

View file

@ -220,6 +220,24 @@ void Module::Interface::SecureInfoGetByte101(Kernel::HLERequestContext& ctx) {
rb.Push<u8>(0); rb.Push<u8>(0);
} }
void Module::Interface::SetUUIDClockSequence(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
cfg->mcu_data.clock_sequence = rp.Pop<u16>();
cfg->SaveMCUConfig();
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(RESULT_SUCCESS);
}
void Module::Interface::GetUUIDClockSequence(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
rb.Push(RESULT_SUCCESS);
rb.Push<u16>(static_cast<u16>(cfg->mcu_data.clock_sequence));
}
void Module::Interface::GetTransferableId(Kernel::HLERequestContext& ctx) { void Module::Interface::GetTransferableId(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx); IPC::RequestParser rp(ctx);
const u32 app_id_salt = rp.Pop<u32>() & 0x000FFFFF; const u32 app_id_salt = rp.Pop<u32>() & 0x000FFFFF;
@ -557,8 +575,33 @@ ResultCode Module::LoadConfigNANDSaveFile() {
return FormatConfig(); return FormatConfig();
} }
void Module::LoadMCUConfig() {
FileUtil::IOFile mcu_data_file(
fmt::format("{}/mcu.dat", FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir)), "r");
if (mcu_data_file.IsOpen() && mcu_data_file.GetSize() >= sizeof(MCUData) &&
mcu_data_file.ReadBytes(&mcu_data, sizeof(MCUData)) == sizeof(MCUData)) {
if (mcu_data.IsValid()) {
return;
}
}
mcu_data_file.Close();
mcu_data = MCUData();
SaveMCUConfig();
}
void Module::SaveMCUConfig() {
FileUtil::IOFile mcu_data_file(
fmt::format("{}/mcu.dat", FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir)), "w");
if (mcu_data_file.IsOpen()) {
mcu_data_file.WriteBytes(&mcu_data, sizeof(MCUData));
}
}
Module::Module() { Module::Module() {
LoadConfigNANDSaveFile(); LoadConfigNANDSaveFile();
LoadMCUConfig();
// Check the config savegame EULA Version and update it to 0x7F7F if necessary // Check the config savegame EULA Version and update it to 0x7F7F if necessary
// so users will never get a prompt to accept EULA // so users will never get a prompt to accept EULA
auto version = GetEULAVersion(); auto version = GetEULAVersion();

View file

@ -82,7 +82,7 @@ enum ConfigBlockID {
DebugModeBlockID = 0x00130000, DebugModeBlockID = 0x00130000,
ClockSequenceBlockID = 0x00150000, ClockSequenceBlockID = 0x00150000,
Unknown_0x00150001 = 0x00150001, Unknown_0x00150001 = 0x00150001,
NpnsUrlID = 0x00150002, // Maybe? 3dbrew documentation is weirdly written. ServerType = 0x00150002,
Unknown_0x00160000 = 0x00160000, Unknown_0x00160000 = 0x00160000,
MiiverseAccessKeyBlockID = 0x00170000, MiiverseAccessKeyBlockID = 0x00170000,
QtmInfraredLedRelatedBlockID = 0x00180000, QtmInfraredLedRelatedBlockID = 0x00180000,
@ -230,6 +230,27 @@ public:
*/ */
void SecureInfoGetByte101(Kernel::HLERequestContext& ctx); void SecureInfoGetByte101(Kernel::HLERequestContext& ctx);
/**
* CFG::SetUUIDClockSequence service function
* Inputs:
* 1 : UUID Clock Sequence
* Outputs:
* 0 : Result Header code
* 1 : Result of function, 0 on success, otherwise error code
*/
void SetUUIDClockSequence(Kernel::HLERequestContext& ctx);
/**
* CFG::GetUUIDClockSequence service function
* Inputs:
* 1 : None
* Outputs:
* 0 : Result Header code
* 1 : Result of function, 0 on success, otherwise error code
* 2 : UUID Clock Sequence
*/
void GetUUIDClockSequence(Kernel::HLERequestContext& ctx);
/** /**
* CFG::GetTransferableId service function * CFG::GetTransferableId service function
* Inputs: * Inputs:
@ -338,6 +359,25 @@ public:
}; };
private: private:
// Represents save data that would normally be stored in the MCU
// on real hardware. Try to keep this struct backwards compatible
// if a new version is needed to prevent data loss.
struct MCUData {
struct Header {
static constexpr u32 MAGIC_VALUE = 0x4455434D;
static constexpr u32 VERSION_VALUE = 1;
u32 magic = MAGIC_VALUE;
u32 version = VERSION_VALUE;
u64 reserved = 0;
};
Header header;
u32 clock_sequence = 0;
[[nodiscard]] bool IsValid() const {
return header.magic == Header::MAGIC_VALUE && header.version == Header::VERSION_VALUE;
}
};
ResultVal<void*> GetConfigBlockPointer(u32 block_id, u32 size, AccessFlag accesss_flag); ResultVal<void*> GetConfigBlockPointer(u32 block_id, u32 size, AccessFlag accesss_flag);
/** /**
@ -397,6 +437,11 @@ private:
*/ */
ResultCode LoadConfigNANDSaveFile(); ResultCode LoadConfigNANDSaveFile();
/**
* Loads MCU specific data
*/
void LoadMCUConfig();
public: public:
u32 GetRegionValue(); u32 GetRegionValue();
@ -538,11 +583,17 @@ public:
*/ */
ResultCode UpdateConfigNANDSavegame(); ResultCode UpdateConfigNANDSavegame();
/**
* Saves MCU specific data
*/
void SaveMCUConfig();
private: private:
static constexpr u32 CONFIG_SAVEFILE_SIZE = 0x8000; static constexpr u32 CONFIG_SAVEFILE_SIZE = 0x8000;
std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer; std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
std::unique_ptr<FileSys::ArchiveBackend> cfg_system_save_data_archive; std::unique_ptr<FileSys::ArchiveBackend> cfg_system_save_data_archive;
u32 preferred_region_code = 0; u32 preferred_region_code = 0;
MCUData mcu_data{};
template <class Archive> template <class Archive>
void serialize(Archive& ar, const unsigned int); void serialize(Archive& ar, const unsigned int);

View file

@ -57,6 +57,8 @@ constexpr ConsoleModelInfo DEFAULT_CONSOLE_MODEL{NEW_NINTENDO_3DS_XL, {0, 0, 0}}
constexpr std::array<u8, 0x28> DEFAULT_X_DEVICE_TOKEN = {}; constexpr std::array<u8, 0x28> DEFAULT_X_DEVICE_TOKEN = {};
constexpr u32_le DEFAULT_SYSTEM_SETUP_REQUIRED_FLAG = 1; constexpr u32_le DEFAULT_SYSTEM_SETUP_REQUIRED_FLAG = 1;
constexpr u32_le DEFAULT_DEBUG_MODE_FLAG = 0; constexpr u32_le DEFAULT_DEBUG_MODE_FLAG = 0;
constexpr u32_le DEFAULT_CLOCK_SEQUENCE = 0;
constexpr const char DEFAULT_SERVER_TYPE[4] = {'L', '1', '\0', '\0'};
constexpr u32_le DEFAULT_0x00160000_DATA = 0; constexpr u32_le DEFAULT_0x00160000_DATA = 0;
constexpr u32_le DEFAULT_MIIVERSE_ACCESS_KEY = 0; constexpr u32_le DEFAULT_MIIVERSE_ACCESS_KEY = 0;
@ -108,6 +110,9 @@ static const std::unordered_map<ConfigBlockID, ConfigBlockDefaults> DEFAULT_CONF
sizeof(DEFAULT_SYSTEM_SETUP_REQUIRED_FLAG)}}, sizeof(DEFAULT_SYSTEM_SETUP_REQUIRED_FLAG)}},
{DebugModeBlockID, {DebugModeBlockID,
{AccessFlag::Global, &DEFAULT_DEBUG_MODE_FLAG, sizeof(DEFAULT_DEBUG_MODE_FLAG)}}, {AccessFlag::Global, &DEFAULT_DEBUG_MODE_FLAG, sizeof(DEFAULT_DEBUG_MODE_FLAG)}},
{ClockSequenceBlockID,
{AccessFlag::System, &DEFAULT_CLOCK_SEQUENCE, sizeof(DEFAULT_CLOCK_SEQUENCE)}},
{ServerType, {AccessFlag::Global, DEFAULT_SERVER_TYPE, sizeof(DEFAULT_SERVER_TYPE)}},
{Unknown_0x00160000, {Unknown_0x00160000,
{AccessFlag::Global, &DEFAULT_0x00160000_DATA, sizeof(DEFAULT_0x00160000_DATA)}}, {AccessFlag::Global, &DEFAULT_0x00160000_DATA, sizeof(DEFAULT_0x00160000_DATA)}},
{MiiverseAccessKeyBlockID, {MiiverseAccessKeyBlockID,

View file

@ -34,6 +34,8 @@ CFG_S::CFG_S(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "c
{0x0407, &CFG_S::SecureInfoGetByte101, "SecureInfoGetByte101"}, {0x0407, &CFG_S::SecureInfoGetByte101, "SecureInfoGetByte101"},
{0x0408, nullptr, "SecureInfoGetSerialNo"}, {0x0408, nullptr, "SecureInfoGetSerialNo"},
{0x0409, nullptr, "UpdateConfigBlk00040003"}, {0x0409, nullptr, "UpdateConfigBlk00040003"},
{0x040D, &CFG_S::SetUUIDClockSequence, "SetUUIDClockSequence"},
{0x040E, &CFG_S::GetUUIDClockSequence, "GetUUIDClockSequence"},
// clang-format on // clang-format on
}; };
RegisterHandlers(functions); RegisterHandlers(functions);