/* * Copyright (C) Switch-OC-Suite * * Copyright (c) Souldbminer and Horizon OC Contributors * * 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 #ifdef ATMOSPHERE_IS_STRATOSPHERE #include #include #define LOGGING(fmt, ...) ((void)0) #define CRASH(msg, ...) { ams::diag::AbortImpl(msg, __PRETTY_FUNCTION__, "", 0); __builtin_unreachable(); } #else #include "oc_test.hpp" #endif #include "customize.hpp" #define PATCH_OFFSET(offset, value) \ static_assert(sizeof(__typeof__(offset)) <= sizeof(u64)); \ *(offset) = value; namespace ams::ldr { R_DEFINE_ERROR_RESULT(OutOfRange, 1000); R_DEFINE_ERROR_RESULT(InvalidMemPllmEntry, 1001); R_DEFINE_ERROR_RESULT(InvalidMtcMagic, 1002); R_DEFINE_ERROR_RESULT(InvalidMtcTable, 1003); R_DEFINE_ERROR_RESULT(InvalidDvbTable, 1004); R_DEFINE_ERROR_RESULT(InvalidCpuFreqVddEntry, 1005); R_DEFINE_ERROR_RESULT(InvalidCpuVoltDfllEntry, 1006); R_DEFINE_ERROR_RESULT(InvalidCpuDvfs, 1007); R_DEFINE_ERROR_RESULT(InvalidCpuMinVolt, 1008); R_DEFINE_ERROR_RESULT(InvalidGpuDvfs, 1009); R_DEFINE_ERROR_RESULT(InvalidGpuFreqMaxPattern, 1010); R_DEFINE_ERROR_RESULT(InvalidGpuPllEntry, 1011); R_DEFINE_ERROR_RESULT(InvalidRegulatorEntry, 1012); R_DEFINE_ERROR_RESULT(UninitializedPatcher, 1013); R_DEFINE_ERROR_RESULT(UnsuccessfulPatcher, 1014); R_DEFINE_ERROR_RESULT(SafetyCheckFailure, 1015); } namespace ams::ldr::oc { template struct PatcherEntry { using patternFn = bool(*)(Pointer* ptr); using patcherFn = Result(*)(Pointer* ptr); const char* description; patcherFn patcher_fn = nullptr; size_t maximum_patched_count = 0; patternFn pattern_search_fn = nullptr; Pointer value_search; size_t patched_count = 0; Result Apply(Pointer* ptr) { Result res = patcher_fn(ptr); if (R_SUCCEEDED(res)) patched_count++; return res; } Result SearchAndApply(Pointer* ptr) { bool searchOk = false; if (pattern_search_fn) { if (pattern_search_fn(ptr)) searchOk = true; } else { if (value_search == *(ptr)) searchOk = true; } if (searchOk) return Apply(ptr); R_THROW(ldr::ResultUnsuccessfulPatcher()); } Result CheckResult() { #ifndef ATMOSPHERE_IS_STRATOSPHERE R_UNLESS(patched_count > 0, ldr::ResultUnsuccessfulPatcher()); #endif if (maximum_patched_count) R_UNLESS(patched_count <= maximum_patched_count, ldr::ResultUnsuccessfulPatcher()); R_SUCCEED(); } }; }