Compare commits

..

2 Commits

Author SHA1 Message Date
Michael Scire
967f14fc7e Implement working prodinfo blanking. 2019-05-23 03:10:32 -07:00
Michael Scire
3bba035b84 Implement blank prodinfo creation.
This is a complete implementation of what PR #532 seeks to do
(thanks @ThatNerdyPikachu). However, it currently blackscreens.

This is because we can't actually mitm settings, because settings
must be able to complete its initialization before the sd card
can be mounted. Thus we end up with a circular dependency and
the console blackscreens. This problem may yet be solvable, but
it's unclear immediately how this dependency might be solved. In any
event, this serves as a reference to use in the event that a solution
arises.
2019-05-10 05:27:30 -07:00
47 changed files with 423 additions and 556 deletions

View File

@@ -19,7 +19,7 @@
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
#define ATMOSPHERE_RELEASE_VERSION_MINOR 8
#define ATMOSPHERE_RELEASE_VERSION_MICRO 10
#define ATMOSPHERE_RELEASE_VERSION_MICRO 9
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 8
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0

View File

@@ -1,20 +1,4 @@
# Changelog
## 0.8.10
+ A bug was fixed that could cause incorrect system memory allocation on 5.0.0.
+ 5.0.0 should now correctly have an additional 12 MiB allocated for sysmodules.
+ Atmosphère features which check button presses now consider all controllers, isntead of just P1.
+ Support was added for configuring language/region on a per-game basis.
+ This is managed by editing `atmosphere/titles/<title id>/config.ini` for the game.
+ To edit title language, edit `override_config!override_language`.
+ The languages supported are `ja`, `en-US`, `fr`, `de`, `it`, `es`, `zh-CN`, `ko`, `nl`, `pt`, `ru`, `zh-TW`, `en-GB`, `fr-CA`, `es-419`, `zh-Hans`, `zh-Hant`.
+ To edit title region, edit `override_config!override_region`.
+ The regions supported are `jpn`, `usa`, `eur`, `aus`, `chn`, `kor`, `twn`.
+ Atmosphère now provides a reimplementation of the `boot` system module.
+ `boot` is responsible for performing hardware initialization, showing the Nintendo logo, and repairing NAND on system update failure.
+ Atmosphère's `boot` implementation preserves AutoRCM during NAND repair.
+ NAND repair occurs when an unexpected shutdown or error happens during a system update.
+ This fixes a final edge case where AutoRCM might be removed by HOS, which could cause a user to burn fuses.
+ General system stability improvements to enhance the user's experience.
## 0.8.9
+ A number of bugs were fixed, including:
+ A data abort was fixed when mounting certain partitions on NAND.

View File

@@ -282,7 +282,11 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue)
break;
case CONFIGITEM_HAS_RCM_BUG_PATCH:
/* UNOFFICIAL: Gets whether this unit has the RCM bug patched. */
*p_outvalue = (int)(fuse_has_rcm_bug_patch());;
*p_outvalue = (int)(fuse_has_rcm_bug_patch());
break;
case CONFIGITEM_SHOULD_BLANK_PROD_INFO:
/* UNOFFICIAL: Gets whether we should blank out certain parts of PRODINFO. */
*p_outvalue = (int)(exosphere_should_blank_prod_info() != 0);
break;
default:
result = 2;

View File

@@ -45,6 +45,7 @@ typedef enum {
CONFIGITEM_NEEDS_SHUTDOWN = 65002,
CONFIGITEM_EXOSPHERE_VERHASH = 65003,
CONFIGITEM_HAS_RCM_BUG_PATCH = 65004,
CONFIGITEM_SHOULD_BLANK_PROD_INFO = 65005,
} ConfigItem;
#define REBOOT_KIND_NO_REBOOT 0

View File

@@ -83,3 +83,11 @@ unsigned int exosphere_should_disable_usermode_exception_handlers(void) {
return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS);
}
unsigned int exosphere_should_blank_prod_info(void) {
if (!g_has_loaded_config) {
generic_panic();
}
return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_SHOULD_BLANK_PRODINFO);
}

View File

@@ -39,6 +39,7 @@
#define EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV (1 << 1u)
#define EXOSPHERE_FLAG_IS_DEBUGMODE_USER (1 << 2u)
#define EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS (1 << 3u)
#define EXOSPHERE_FLAG_SHOULD_BLANK_PRODINFO (1 << 4u)
#define EXOSPHERE_FLAGS_DEFAULT (EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV)
typedef struct {
@@ -54,6 +55,7 @@ unsigned int exosphere_should_perform_620_keygen(void);
unsigned int exosphere_should_override_debugmode_priv(void);
unsigned int exosphere_should_override_debugmode_user(void);
unsigned int exosphere_should_disable_usermode_exception_handlers(void);
unsigned int exosphere_should_blank_prod_info(void);
static inline unsigned int exosphere_get_target_firmware_for_init(void) {
const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic;

View File

@@ -668,7 +668,7 @@ static int sdmmc_int_clk_enable(sdmmc_t *sdmmc)
/* Clock failed to stabilize. */
if (is_timeout) {
sdmmc_error(sdmmc, "Clock never stabilized!");
sdmmc_error(sdmmc, "clock never stabilized!");
return 0;
}
@@ -1353,11 +1353,8 @@ static int sdmmc_dma_init(sdmmc_t *sdmmc, sdmmc_request_t *req)
{
/* Invalid block count or size. */
if (!req->blksz || !req->num_blocks)
{
sdmmc_error(sdmmc, "Empty DMA request!");
return 0;
}
uint32_t blkcnt = req->num_blocks;
/* Truncate block count. Length can't be over 65536 bytes. */
@@ -1369,11 +1366,8 @@ static int sdmmc_dma_init(sdmmc_t *sdmmc, sdmmc_request_t *req)
/* DMA buffer address must be aligned to 4 bytes. */
if ((4 - (dma_base_addr & 0x03)) & 0x03)
{
sdmmc_error(sdmmc, "Invalid DMA request data buffer: 0x%08X", dma_base_addr);
return 0;
}
/* Write our address to the registers. */
if (sdmmc->use_adma)
{

View File

@@ -28,6 +28,7 @@
#define EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV (1 << 1u)
#define EXOSPHERE_FLAG_IS_DEBUGMODE_USER (1 << 2u)
#define EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS (1 << 3u)
#define EXOSPHERE_FLAG_SHOULD_BLANK_PRODINFO (1 << 4u)
#define EXOSPHERE_FLAGS_DEFAULT (EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV)
typedef struct {

View File

@@ -39,7 +39,6 @@
extern void (*__program_exit_callback)(int rc);
static __attribute__((__aligned__(0x200))) stage2_args_t g_stage2_args_store;
static stage2_args_t *g_stage2_args;
static bool g_do_nxboot;
@@ -85,8 +84,7 @@ int main(int argc, void **argv) {
generic_panic();
}
g_stage2_args = &g_stage2_args_store;
memcpy(g_stage2_args, (stage2_args_t *)argv[STAGE2_ARGV_ARGUMENT_STRUCT], sizeof(*g_stage2_args));
g_stage2_args = (stage2_args_t *)argv[STAGE2_ARGV_ARGUMENT_STRUCT];
if (g_stage2_args->version != 0) {
generic_panic();
@@ -103,11 +101,10 @@ int main(int argc, void **argv) {
/* Load BCT0 from SD if needed. */
if (strcmp(g_stage2_args->bct0, "") == 0) {
uint32_t bct_tmp_buf[sizeof(g_stage2_args->bct0) / sizeof(uint32_t)] = {0};
if (!read_from_file(bct_tmp_buf, sizeof(bct_tmp_buf) - 1, "atmosphere/BCT.ini")) {
read_from_file(g_stage2_args->bct0, sizeof(g_stage2_args->bct0) - 1, "atmosphere/BCT.ini");
if (!read_from_file(g_stage2_args->bct0, sizeof(g_stage2_args->bct0) - 1, "atmosphere/BCT.ini")) {
fatal_error("Failed to read BCT0 from SD!\n");
}
memcpy(g_stage2_args->bct0, bct_tmp_buf, sizeof(bct_tmp_buf));
}
/* This will load all remaining binaries off of the SD. */

View File

@@ -199,6 +199,14 @@ static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int ke
fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n");
}
{
FILE *flag = fopen("atmosphere/flags/blank_prodinfo.flag", "rb");
if (flag != NULL) {
exo_cfg.flags |= EXOSPHERE_FLAG_SHOULD_BLANK_PRODINFO;
fclose(flag);
}
}
if ((exo_cfg.target_firmware < ATMOSPHERE_TARGET_FIRMWARE_MIN) || (exo_cfg.target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX)) {
fatal_error("[NXBOOT]: Invalid Exosphere target firmware!\n");
}

View File

@@ -668,7 +668,7 @@ static int sdmmc_int_clk_enable(sdmmc_t *sdmmc)
/* Clock failed to stabilize. */
if (is_timeout) {
sdmmc_error(sdmmc, "Clock never stabilized!");
sdmmc_error(sdmmc, "clock never stabilized!");
return 0;
}
@@ -1353,11 +1353,8 @@ static int sdmmc_dma_init(sdmmc_t *sdmmc, sdmmc_request_t *req)
{
/* Invalid block count or size. */
if (!req->blksz || !req->num_blocks)
{
sdmmc_error(sdmmc, "Empty DMA request!");
return 0;
}
uint32_t blkcnt = req->num_blocks;
/* Truncate block count. Length can't be over 65536 bytes. */
@@ -1369,11 +1366,8 @@ static int sdmmc_dma_init(sdmmc_t *sdmmc, sdmmc_request_t *req)
/* DMA buffer address must be aligned to 4 bytes. */
if ((4 - (dma_base_addr & 0x03)) & 0x03)
{
sdmmc_error(sdmmc, "Invalid DMA request data buffer: 0x%08X", dma_base_addr);
return 0;
}
/* Write our address to the registers. */
if (sdmmc->use_adma)
{

View File

@@ -668,7 +668,7 @@ static int sdmmc_int_clk_enable(sdmmc_t *sdmmc)
/* Clock failed to stabilize. */
if (is_timeout) {
sdmmc_error(sdmmc, "Clock never stabilized!");
sdmmc_error(sdmmc, "clock never stabilized!");
return 0;
}
@@ -1353,11 +1353,8 @@ static int sdmmc_dma_init(sdmmc_t *sdmmc, sdmmc_request_t *req)
{
/* Invalid block count or size. */
if (!req->blksz || !req->num_blocks)
{
sdmmc_error(sdmmc, "Empty DMA request!");
return 0;
}
uint32_t blkcnt = req->num_blocks;
/* Truncate block count. Length can't be over 65536 bytes. */
@@ -1369,11 +1366,8 @@ static int sdmmc_dma_init(sdmmc_t *sdmmc, sdmmc_request_t *req)
/* DMA buffer address must be aligned to 4 bytes. */
if ((4 - (dma_base_addr & 0x03)) & 0x03)
{
sdmmc_error(sdmmc, "Invalid DMA request data buffer: 0x%08X", dma_base_addr);
return 0;
}
/* Write our address to the registers. */
if (sdmmc->use_adma)
{

View File

@@ -78,16 +78,6 @@ void __appInit(void) {
if (R_FAILED(rc)) {
std::abort();
}
rc = pmdmntInitialize();
if (R_FAILED(rc)) {
std::abort();
}
rc = pminfoInitialize();
if (R_FAILED(rc)) {
std::abort();
}
});
CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION);

View File

@@ -112,7 +112,6 @@ class IROStorage : public IStorage {
virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) = 0;
};
class ProxyStorage : public IStorage {
private:
FsStorage *base_storage;
@@ -172,4 +171,4 @@ class ROProxyStorage : public IROStorage {
virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override {
return fsStorageOperateRange(this->base_storage, operation_type, offset, size, out_range_info);
};
};
};

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2018-2019 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <switch.h>
#include <stratosphere.hpp>
#include "fs_shim.h"
#include "../debug.hpp"
#include "fs_istorage.hpp"
class MemoryStorage : public IStorage {
private:
u8 * const buffer;
const u64 size;
public:
MemoryStorage(void *b, u64 sz) : buffer(static_cast<u8 *>(b)), size(sz) {
/* ... */
}
virtual ~MemoryStorage() {
/* ... */
}
public:
virtual Result Read(void *buffer, size_t size, u64 offset) override {
if (size == 0) {
return ResultSuccess;
}
if (buffer == nullptr) {
return ResultFsNullptrArgument;
}
if (!IStorage::IsRangeValid(offset, size, this->size)) {
return ResultFsOutOfRange;
}
std::memcpy(buffer, this->buffer + offset, size);
return ResultSuccess;
}
virtual Result Write(void *buffer, size_t size, u64 offset) override {
if (size == 0) {
return ResultSuccess;
}
if (buffer == nullptr) {
return ResultFsNullptrArgument;
}
if (!IStorage::IsRangeValid(offset, size, this->size)) {
return ResultFsOutOfRange;
}
std::memcpy(this->buffer + offset, buffer, size);
return ResultSuccess;
}
virtual Result Flush() override {
return ResultSuccess;
}
virtual Result GetSize(u64 *out_size) override {
*out_size = this->size;
return ResultSuccess;
}
virtual Result SetSize(u64 size) override {
return ResultFsUnsupportedOperation;
}
virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override {
switch (operation_type) {
case 2: /* TODO: OperationType_Invalidate */
return ResultSuccess;
case 3: /* TODO: OperationType_Query */
if (out_range_info == nullptr) {
return ResultFsNullptrArgument;
}
/* N checks for size == sizeof(*out_range_info) here, but that's because their wrapper api is bad. */
std::memset(out_range_info, 0, sizeof(*out_range_info));
return ResultSuccess;
default:
return ResultFsUnsupportedOperation;
}
}
};
class ReadOnlyMemoryStorage : public MemoryStorage {
public:
ReadOnlyMemoryStorage(const void *b, u64 sz) : MemoryStorage(const_cast<void *>(b), sz) {
/* ... */
}
virtual ~ReadOnlyMemoryStorage() {
/* ... */
}
public:
virtual Result Write(void *buffer, size_t size, u64 offset) override {
return ResultFsUnsupportedOperation;
}
};

View File

@@ -27,11 +27,14 @@
#include "fsmitm_boot0storage.hpp"
#include "fsmitm_romstorage.hpp"
#include "fsmitm_layeredrom.hpp"
#include "fsmitm_utils.hpp"
#include "fs_dir_utils.hpp"
#include "fs_save_utils.hpp"
#include "fs_subdirectory_filesystem.hpp"
#include "fs_directory_savedata_filesystem.hpp"
#include "fs_file_storage.hpp"
#include "fs_memory_storage.hpp"
#include "../debug.hpp"
@@ -163,13 +166,12 @@ Result FsMitmService::OpenFileSystemWithId(Out<std::shared_ptr<IFileSystemInterf
Result FsMitmService::OpenSaveDataFileSystem(Out<std::shared_ptr<IFileSystemInterface>> out_fs, u8 space_id, FsSave save_struct) {
bool should_redirect_saves = false;
const bool has_redirect_save_flags = Utils::HasFlag(this->title_id, "redirect_save");
if (R_FAILED(Utils::GetSettingsItemBooleanValue("atmosphere", "fsmitm_redirect_saves_to_sd", &should_redirect_saves))) {
return ResultAtmosphereMitmShouldForwardToSession;
}
/* For now, until we're sure this is robust, only intercept normal savedata , check if flag exist*/
if (!has_redirect_save_flags || !should_redirect_saves || save_struct.SaveDataType != FsSaveDataType_SaveData) {
/* For now, until we're sure this is robust, only intercept normal savedata. */
if (!should_redirect_saves || save_struct.SaveDataType != FsSaveDataType_SaveData) {
return ResultAtmosphereMitmShouldForwardToSession;
}
@@ -262,11 +264,14 @@ Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out
const bool is_sysmodule = TitleIdIsSystem(this->title_id);
const bool has_bis_write_flag = Utils::HasFlag(this->title_id, "bis_write");
const bool has_cal0_read_flag = Utils::HasFlag(this->title_id, "cal_read");
const bool has_blank_cal0_flag = ShouldBlankProdInfo();
if (bis_partition_id == BisStorageId_Boot0) {
storage = std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, this->title_id));
} else if (bis_partition_id == BisStorageId_Prodinfo) {
/* PRODINFO should *never* be writable. */
if (is_sysmodule || has_cal0_read_flag) {
if (has_blank_cal0_flag) {
storage = std::make_shared<IStorageInterface>(new MitmProxyStorage(std::make_unique<ReadOnlyMemoryStorage>(Utils::GetBlankProdInfoBuffer(), ProdInfoSize), bis_storage.s));
} else if (is_sysmodule || has_cal0_read_flag) {
storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage));
} else {
/* Do not allow non-sysmodules to read *or* write CAL0. */
@@ -431,4 +436,4 @@ Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterf
}
return rc;
}
}

View File

@@ -44,7 +44,7 @@ class FsMitmService : public IMitmServiceObject {
bool should_override_contents;
public:
FsMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) {
if (Utils::HasSdDisableMitMFlag(this->title_id)) {
if (this->title_id == TitleId_Settings || Utils::HasSdDisableMitMFlag(this->title_id)) {
this->should_override_contents = false;
} else {
this->should_override_contents = (this->title_id >= TitleId_ApplicationStart || Utils::HasSdMitMFlag(this->title_id)) && Utils::HasOverrideButton(this->title_id);
@@ -65,7 +65,7 @@ class FsMitmService : public IMitmServiceObject {
has_launched_qlaunch = true;
}
return has_launched_qlaunch || tid == TitleId_Ns || tid >= TitleId_ApplicationStart || Utils::HasSdMitMFlag(tid);
return has_launched_qlaunch || tid == TitleId_Settings || tid == TitleId_Ns || tid >= TitleId_ApplicationStart || Utils::HasSdMitMFlag(tid);
}
static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx);

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2018-2019 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <switch.h>
#include "fs_istorage.hpp"
class MitmProxyStorage : public IStorage {
private:
Service srv_holder;
std::unique_ptr<IStorage> fwd_storage;
public:
MitmProxyStorage(std::unique_ptr<IStorage> st, Service sr = {}) : srv_holder(sr), fwd_storage(std::move(st)) {
/* ... */
}
virtual ~MitmProxyStorage() {
if (serviceIsActive(&srv_holder)) {
serviceClose(&srv_holder);
}
}
public:
virtual Result Read(void *buffer, size_t size, u64 offset) override {
return this->fwd_storage->Read(buffer, size, offset);
}
virtual Result Write(void *buffer, size_t size, u64 offset) override {
return this->fwd_storage->Write(buffer, size, offset);
}
virtual Result Flush() override {
return this->fwd_storage->Flush();
}
virtual Result GetSize(u64 *out_size) override {
return this->fwd_storage->GetSize(out_size);
}
virtual Result SetSize(u64 size) override {
return this->fwd_storage->SetSize(size);
}
virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override {
return this->fwd_storage->OperateRange(operation_type, offset, size, out_range_info);
}
};

View File

@@ -1,113 +0,0 @@
/*
* Copyright (c) 2018-2019 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 <http://www.gnu.org/licenses/>.
*/
#include <mutex>
#include <algorithm>
#include <switch.h>
#include "set_mitm_service.hpp"
#include "set_shim.h"
void SetMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) {
/* No commands need postprocessing. */
}
bool SetMitmService::IsValidLanguageCode(u64 lang_code) {
static constexpr u64 s_valid_language_codes[] = {
LanguageCode_Japanese,
LanguageCode_AmericanEnglish,
LanguageCode_French,
LanguageCode_German,
LanguageCode_Italian,
LanguageCode_Spanish,
LanguageCode_Chinese,
LanguageCode_Korean,
LanguageCode_Dutch,
LanguageCode_Portuguese,
LanguageCode_Russian,
LanguageCode_Taiwanese,
LanguageCode_BritishEnglish,
LanguageCode_CanadianFrench,
LanguageCode_LatinAmericanSpanish,
LanguageCode_SimplifiedChinese,
LanguageCode_TraditionalChinese,
};
size_t num_language_codes = sizeof(s_valid_language_codes) / sizeof(s_valid_language_codes[0]);
if (GetRuntimeFirmwareVersion() < FirmwareVersion_400) {
/* 4.0.0 added simplified and traditional chinese. */
num_language_codes -= 2;
}
for (size_t i = 0; i < num_language_codes; i++) {
if (lang_code == s_valid_language_codes[i]) {
return true;
}
}
return false;
}
bool SetMitmService::IsValidRegionCode(u32 region_code) {
return region_code < RegionCode_Max;
}
void SetMitmService::EnsureLocale() {
std::scoped_lock<HosMutex> lk(this->lock);
if (!this->got_locale) {
std::memset(&this->locale, 0xCC, sizeof(this->locale));
if (this->title_id == TitleId_Ns) {
u64 app_pid = 0;
u64 app_tid = 0;
Result rc;
if (R_FAILED((rc = pmdmntGetApplicationPid(&app_pid)))) {
return;
}
if (R_FAILED((rc = pminfoGetTitleId(&app_tid, app_pid)))) {
return;
}
this->locale = Utils::GetTitleOverrideLocale(app_tid);
} else {
this->locale = Utils::GetTitleOverrideLocale(this->title_id);
this->got_locale = true;
}
}
}
Result SetMitmService::GetLanguageCode(Out<u64> out_lang_code) {
this->EnsureLocale();
if (!IsValidLanguageCode(this->locale.language_code)) {
return ResultAtmosphereMitmShouldForwardToSession;
}
out_lang_code.SetValue(this->locale.language_code);
return ResultSuccess;
}
Result SetMitmService::GetRegionCode(Out<u32> out_region_code) {
this->EnsureLocale();
if (!IsValidRegionCode(this->locale.region_code)) {
return ResultAtmosphereMitmShouldForwardToSession;
}
out_region_code.SetValue(this->locale.region_code);
return ResultSuccess;
}
Result SetMitmService::GetAvailableLanguageCodes(OutPointerWithClientSize<u64> out_language_codes, Out<s32> out_count) {
return setGetAvailableLanguageCodesFwd(this->forward_service.get(), out_count.GetPointer(), out_language_codes.pointer, out_language_codes.num_elements);
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright (c) 2018-2019 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <switch.h>
#include <stratosphere.hpp>
#include "../utils.hpp"
enum SetCmd : u32 {
SetCmd_GetLanguageCode = 0,
SetCmd_GetRegionCode = 4,
/* Commands for which set:sys *must* act as a passthrough. */
/* TODO: Solve the relevant IPC detection problem. */
SetCmd_GetAvailableLanguageCodes = 1,
};
class SetMitmService : public IMitmServiceObject {
private:
HosMutex lock;
OverrideLocale locale;
bool got_locale;
public:
SetMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) {
this->got_locale = false;
}
static bool ShouldMitm(u64 pid, u64 tid) {
/* Mitm all applications. */
return tid == TitleId_Ns || TitleIdIsApplication(tid);
}
static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx);
protected:
static bool IsValidLanguageCode(u64 lang_code);
static bool IsValidRegionCode(u32 region_code);
void EnsureLocale();
protected:
/* Overridden commands. */
Result GetLanguageCode(Out<u64> out_lang_code);
Result GetRegionCode(Out<u32> out_region_code);
/* Forced passthrough commands. */
Result GetAvailableLanguageCodes(OutPointerWithClientSize<u64> out_language_codes, Out<s32> out_count);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<SetCmd_GetLanguageCode, &SetMitmService::GetLanguageCode>(),
MakeServiceCommandMeta<SetCmd_GetRegionCode, &SetMitmService::GetRegionCode>(),
MakeServiceCommandMeta<SetCmd_GetAvailableLanguageCodes, &SetMitmService::GetAvailableLanguageCodes>(),
};
};

View File

@@ -1,59 +0,0 @@
/*
* Copyright (c) 2018-2019 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 <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <switch.h>
#include "setsys_shim.h"
/* Command forwarders. */
Result setGetAvailableLanguageCodesFwd(Service* s, s32 *total_entries, u64 *language_codes, size_t max_entries) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvStatic(&c, language_codes, max_entries * sizeof(*language_codes), 0);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1;
Result rc = serviceIpcDispatch(s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
s32 total_entries;
} *resp;
serviceIpcParse(s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*total_entries = resp->total_entries;
}
}
return rc;
}

View File

@@ -1,19 +0,0 @@
/**
* @file set_shim.h
* @brief Settings Services (set) IPC wrapper. To be merged into libnx, eventually.
* @author SciresM
* @copyright libnx Authors
*/
#pragma once
#include <switch.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Command forwarders. */
Result setGetAvailableLanguageCodesFwd(Service* s, s32 *total_entries, u64 *language_codes, size_t max_entries);
#ifdef __cplusplus
}
#endif

View File

@@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cstdint>
#include <cstring>
@@ -28,8 +28,6 @@
#include "setsys_settings_items.hpp"
#include "setsys_firmware_version.hpp"
#include "set_mitm_service.hpp"
#include "../utils.hpp"
struct SetSysManagerOptions {
@@ -46,20 +44,17 @@ void SetMitmMain(void *arg) {
/* Initialize version manager. */
VersionManager::Initialize();
/* Create server manager */
auto server_manager = new SetMitmManager(4);
auto server_manager = new SetMitmManager(3);
/* Create set:sys mitm. */
AddMitmServerToManager<SetSysMitmService>(server_manager, "set:sys", 60);
/* Create set mitm. */
AddMitmServerToManager<SetMitmService>(server_manager, "set", 60);
/* Loop forever, servicing our services. */
server_manager->Process();
delete server_manager;
}

View File

@@ -55,7 +55,7 @@ Result setsysGetEdidFwd(Service* s, SetSysEdid* out) {
Result setsysGetSettingsItemValueFwd(Service *s, const char *name, const char *item_key, void *value_out, size_t value_out_size, u64 *size_out) {
char send_name[SET_MAX_NAME_SIZE];
char send_item_key[SET_MAX_NAME_SIZE];
memset(send_name, 0, SET_MAX_NAME_SIZE);
memset(send_item_key, 0, SET_MAX_NAME_SIZE);
strncpy(send_name, name, SET_MAX_NAME_SIZE-1);

View File

@@ -60,10 +60,13 @@ static HblOverrideConfig g_hbl_override_config = {
static char g_config_ini_data[0x800];
/* Backup file for CAL0 partition. */
static constexpr size_t ProdinfoSize = 0x8000;
static FsFile g_cal0_file = {0};
static u8 g_cal0_storage_backup[ProdinfoSize];
static u8 g_cal0_backup[ProdinfoSize];
static u8 g_cal0_storage_backup[ProdInfoSize];
static u8 g_cal0_backup[ProdInfoSize];
static HosMutex g_blank_cal0_lock;
static bool g_initialized_blank_cal0 = false;
static u8 g_blank_cal0[ProdInfoSize];
static bool IsHexadecimal(const char *str) {
while (*str) {
@@ -99,7 +102,7 @@ void Utils::InitializeThreadFunc(void *args) {
fsFsCreateDirectory(&g_sd_filesystem, "/atmosphere/automatic_backups");
{
FsStorage cal0_storage;
if (R_FAILED(fsOpenBisStorage(&cal0_storage, BisStorageId_Prodinfo)) || R_FAILED(fsStorageRead(&cal0_storage, 0, g_cal0_storage_backup, ProdinfoSize))) {
if (R_FAILED(fsOpenBisStorage(&cal0_storage, BisStorageId_Prodinfo)) || R_FAILED(fsStorageRead(&cal0_storage, 0, g_cal0_storage_backup, ProdInfoSize))) {
std::abort();
}
fsStorageClose(&cal0_storage);
@@ -115,7 +118,7 @@ void Utils::InitializeThreadFunc(void *args) {
snprintf(prodinfo_backup_path, sizeof(prodinfo_backup_path) - 1, "/atmosphere/automatic_backups/PRODINFO.bin");
}
fsFsCreateFile(&g_sd_filesystem, prodinfo_backup_path, ProdinfoSize, 0);
fsFsCreateFile(&g_sd_filesystem, prodinfo_backup_path, ProdInfoSize, 0);
if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, prodinfo_backup_path, FS_OPEN_READ | FS_OPEN_WRITE, &g_cal0_file))) {
bool has_auto_backup = false;
size_t read = 0;
@@ -124,7 +127,7 @@ void Utils::InitializeThreadFunc(void *args) {
is_cal0_valid &= memcmp(g_cal0_backup, "CAL0", 4) == 0;
is_cal0_valid &= memcmp(g_cal0_backup + 0x250, serial_number, 0x18) == 0;
u32 cal0_size = ((u32 *)g_cal0_backup)[2];
is_cal0_valid &= cal0_size + 0x40 <= ProdinfoSize;
is_cal0_valid &= cal0_size + 0x40 <= ProdInfoSize;
if (is_cal0_valid) {
u8 calc_hash[0x20];
sha256CalculateHash(calc_hash, g_cal0_backup + 0x40, cal0_size);
@@ -134,14 +137,14 @@ void Utils::InitializeThreadFunc(void *args) {
}
if (!has_auto_backup) {
fsFileSetSize(&g_cal0_file, ProdinfoSize);
fsFileWrite(&g_cal0_file, 0, g_cal0_storage_backup, ProdinfoSize);
fsFileSetSize(&g_cal0_file, ProdInfoSize);
fsFileWrite(&g_cal0_file, 0, g_cal0_storage_backup, ProdInfoSize);
fsFileFlush(&g_cal0_file);
}
/* NOTE: g_cal0_file is intentionally not closed here. This prevents any other process from opening it. */
memset(g_cal0_storage_backup, 0, sizeof(g_cal0_storage_backup));
memset(g_cal0_backup, 0, sizeof(g_cal0_backup));
std::memset(g_cal0_storage_backup, 0, sizeof(g_cal0_storage_backup));
std::memset(g_cal0_backup, 0, sizeof(g_cal0_backup));
}
}
@@ -460,11 +463,7 @@ Result Utils::GetKeysHeld(u64 *keys) {
}
hidScanInput();
*keys = 0;
for (int controller = 0; controller < 10; controller++) {
*keys |= hidKeysHeld((HidControllerID) controller);
}
*keys = hidKeysHeld(CONTROLLER_P1_AUTO);
return ResultSuccess;
}
@@ -624,64 +623,6 @@ OverrideKey Utils::GetTitleOverrideKey(u64 tid) {
return cfg;
}
static int FsMitmTitleSpecificLocaleIniHandler(void *user, const char *section, const char *name, const char *value) {
/* We'll output an override locale when relevant. */
OverrideLocale *user_locale = reinterpret_cast<OverrideLocale *>(user);
if (strcasecmp(section, "override_config") == 0) {
if (strcasecmp(name, "override_language") == 0) {
user_locale->language_code = EncodeLanguageCode(value);
} else if (strcasecmp(name, "override_region") == 0) {
if (strcasecmp(value, "jpn") == 0) {
user_locale->region_code = RegionCode_Japan;
} else if (strcasecmp(value, "usa") == 0) {
user_locale->region_code = RegionCode_America;
} else if (strcasecmp(value, "eur") == 0) {
user_locale->region_code = RegionCode_Europe;
} else if (strcasecmp(value, "aus") == 0) {
user_locale->region_code = RegionCode_Australia;
} else if (strcasecmp(value, "chn") == 0) {
user_locale->region_code = RegionCode_China;
} else if (strcasecmp(value, "kor") == 0) {
user_locale->region_code = RegionCode_Korea;
} else if (strcasecmp(value, "twn") == 0) {
user_locale->region_code = RegionCode_Taiwan;
}
}
} else {
return 0;
}
return 1;
}
OverrideLocale Utils::GetTitleOverrideLocale(u64 tid) {
OverrideLocale locale;
std::memset(&locale, 0xCC, sizeof(locale));
char path[FS_MAX_PATH+1] = {0};
snprintf(path, FS_MAX_PATH, "/atmosphere/titles/%016lx/config.ini", tid);
FsFile cfg_file;
if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, path, FS_OPEN_READ, &cfg_file))) {
ON_SCOPE_EXIT { fsFileClose(&cfg_file); };
size_t config_file_size = 0x20000;
fsFileGetSize(&cfg_file, &config_file_size);
char *config_buf = reinterpret_cast<char *>(calloc(1, config_file_size + 1));
if (config_buf != NULL) {
ON_SCOPE_EXIT { free(config_buf); };
/* Read title ini contents. */
fsFileRead(&cfg_file, 0, config_buf, config_file_size, &config_file_size);
/* Parse title ini. */
ini_parse_string(config_buf, FsMitmTitleSpecificLocaleIniHandler, &locale);
}
}
return locale;
}
void Utils::RefreshConfiguration() {
FsFile config_file;
if (R_FAILED(fsFsOpenFile(&g_sd_filesystem, "/atmosphere/loader.ini", FS_OPEN_READ, &config_file))) {
@@ -727,3 +668,86 @@ Result Utils::GetSettingsItemBooleanValue(const char *name, const char *key, boo
void Utils::RebootToFatalError(AtmosphereFatalErrorContext *ctx) {
BpcRebootManager::RebootForFatalError(ctx);
}
void Utils::EnsureBlankProdInfo() {
std::scoped_lock<HosMutex> lk(g_blank_cal0_lock);
if (g_initialized_blank_cal0) {
return;
}
/* Read CAL0 in from NAND. */
{
FsStorage cal0_storage;
if (R_FAILED(fsOpenBisStorage(&cal0_storage, BisStorageId_Prodinfo)) || R_FAILED(fsStorageRead(&cal0_storage, 0, g_blank_cal0, ProdInfoSize))) {
std::abort();
}
fsStorageClose(&cal0_storage);
}
if (!IsCal0Valid(g_blank_cal0)) {
std::abort();
}
const char blank_serial[] = "XAW00000000000";
std::memcpy(&g_blank_cal0[0x250], blank_serial, sizeof(blank_serial) - 1);
static constexpr size_t NumErase = 7;
for (size_t i = 0; i < NumErase; i++) {
static constexpr size_t s_erase_offsets[NumErase] = {0xAE0, 0x3AE0, 0x35E1, 0x36E1, 0x2B0, 0x3D70, 0x3FC0};
static constexpr size_t s_erase_sizes[NumErase] = {0x800, 0x130, 0x6, 0x6, 0x180, 0x240, 0x240};
std::memset(&g_blank_cal0[s_erase_offsets[i]], 0, s_erase_sizes[i]);
}
static constexpr size_t NumHashes = 2;
{
static constexpr size_t s_hash_offsets[NumHashes] = {0x12E0, 0x20};
static constexpr size_t s_data_offsets[NumHashes] = {0xAE0, 0x40};
const size_t data_sizes[NumHashes] = {*reinterpret_cast<u32 *>(&g_blank_cal0[0xAD0]), *reinterpret_cast<u32 *>(&g_blank_cal0[0x8])};
for (size_t i = 0; i < NumHashes; i++) {
u8 hash[SHA256_HASH_SIZE];
sha256CalculateHash(hash, &g_blank_cal0[s_data_offsets[i]], data_sizes[i]);
std::memcpy(&g_blank_cal0[s_hash_offsets[i]], hash, sizeof(hash));
}
}
g_initialized_blank_cal0 = true;
}
bool Utils::IsCal0Valid(const u8 *cal0) {
bool is_cal0_valid = true;
is_cal0_valid &= std::memcmp(cal0, "CAL0", 4) == 0;
u32 cal0_size = ((u32 *)cal0)[2];
is_cal0_valid &= cal0_size + 0x40 <= ProdInfoSize;
if (is_cal0_valid) {
u8 calc_hash[0x20];
sha256CalculateHash(calc_hash, cal0 + 0x40, cal0_size);
is_cal0_valid &= std::memcmp(calc_hash, cal0 + 0x20, sizeof(calc_hash)) == 0;
}
return is_cal0_valid;
}
u16 Utils::GetCrc16(const void *data, size_t size) {
static constexpr u16 s_crc_table[0x10] = {
0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400
};
if (data == nullptr) {
std::abort();
}
u16 crc16 = 0x55AA;
const u8 *data_u8 = reinterpret_cast<const u8 *>(data);
for (size_t i = 0; i < size; i++) {
crc16 = (crc16 >> 4) ^ (s_crc_table[crc16 & 0xF]) ^ (s_crc_table[data_u8[i] & 0xF]);
crc16 = (crc16 >> 4) ^ (s_crc_table[crc16 & 0xF]) ^ (s_crc_table[(data_u8[i] >> 4) & 0xF]);
}
return crc16;
}
const void *Utils::GetBlankProdInfoBuffer() {
EnsureBlankProdInfo();
return g_blank_cal0;
}

View File

@@ -37,61 +37,13 @@ enum BisStorageId : u32 {
BisStorageId_SystemProperPartition = 33,
};
static constexpr size_t ProdInfoSize = 0x8000;
struct OverrideKey {
u64 key_combination;
bool override_by_default;
};
struct OverrideLocale {
u64 language_code;
u32 region_code;
};
enum RegionCode : u32 {
RegionCode_Japan = 0,
RegionCode_America = 1,
RegionCode_Europe = 2,
RegionCode_Australia = 3,
RegionCode_China = 4,
RegionCode_Korea = 5,
RegionCode_Taiwan = 6,
RegionCode_Max,
};
static constexpr inline u64 EncodeLanguageCode(const char *code) {
u64 lang_code = 0;
for (size_t i = 0; i < sizeof(lang_code); i++) {
if (code[i] == '\x00') {
break;
}
lang_code |= static_cast<u64>(code[i]) << (8ul * i);
}
return lang_code;
}
enum LanguageCode : u64 {
LanguageCode_Japanese = EncodeLanguageCode("ja"),
LanguageCode_AmericanEnglish = EncodeLanguageCode("en-US"),
LanguageCode_French = EncodeLanguageCode("fr"),
LanguageCode_German = EncodeLanguageCode("de"),
LanguageCode_Italian = EncodeLanguageCode("it"),
LanguageCode_Spanish = EncodeLanguageCode("es"),
LanguageCode_Chinese = EncodeLanguageCode("zh-CN"),
LanguageCode_Korean = EncodeLanguageCode("ko"),
LanguageCode_Dutch = EncodeLanguageCode("nl"),
LanguageCode_Portuguese = EncodeLanguageCode("pt"),
LanguageCode_Russian = EncodeLanguageCode("ru"),
LanguageCode_Taiwanese = EncodeLanguageCode("zh-TW"),
LanguageCode_BritishEnglish = EncodeLanguageCode("en-GB"),
LanguageCode_CanadianFrench = EncodeLanguageCode("fr-CA"),
LanguageCode_LatinAmericanSpanish = EncodeLanguageCode("es-419"),
/* 4.0.0+ */
LanguageCode_SimplifiedChinese = EncodeLanguageCode("zh-Hans"),
LanguageCode_TraditionalChinese = EncodeLanguageCode("zh-Hant"),
};
class Utils {
public:
static bool IsSdInitialized();
@@ -111,6 +63,8 @@ class Utils {
static bool HasSdRomfsContent(u64 title_id);
static const void *GetBlankProdInfoBuffer();
/* Delayed Initialization + MitM detection. */
static void InitializeThreadFunc(void *args);
@@ -132,16 +86,20 @@ class Utils {
static OverrideKey GetTitleOverrideKey(u64 tid);
static bool HasOverrideButton(u64 tid);
static OverrideLocale GetTitleOverrideLocale(u64 tid);
/* Settings! */
static Result GetSettingsItemValueSize(const char *name, const char *key, u64 *out_size);
static Result GetSettingsItemValue(const char *name, const char *key, void *out, size_t max_size, u64 *out_size);
static Result GetSettingsItemBooleanValue(const char *name, const char *key, bool *out);
/* CRC util. */
static u16 GetCrc16(const void *data, size_t size);
/* Error occurred. */
static void RebootToFatalError(AtmosphereFatalErrorContext *ctx);
private:
static void RefreshConfiguration();
static void EnsureBlankProdInfo();
static bool IsCal0Valid(const u8 *cal0);
};

View File

@@ -32,7 +32,6 @@ class ChargerDriver {
I2cDriver::Initialize();
I2cDriver::OpenSession(&this->i2c_session, I2cDevice_Bq24193);
Boot::GpioConfigure(GpioPadName_Bq24193Charger);
Boot::GpioSetDirection(GpioPadName_Bq24193Charger, GpioDirection_Output);
}

View File

@@ -20,7 +20,6 @@ static constexpr u32 GpioPadName_FanEnable = 0x4B;
void Boot::SetFanEnabled() {
if (Boot::GetHardwareType() == HardwareType_Copper) {
Boot::GpioConfigure(GpioPadName_FanEnable);
Boot::GpioSetDirection(GpioPadName_FanEnable, GpioDirection_Output);
Boot::GpioSetValue(GpioPadName_FanEnable, GpioValue_High);
}

View File

@@ -56,7 +56,6 @@ class Boot {
static u32 PinmuxUpdatePark(u32 pinmux_name);
static u32 PinmuxUpdatePad(u32 pinmux_name, u32 config_val, u32 config_mask);
static u32 PinmuxUpdateDrivePad(u32 pinmux_drivepad_name, u32 config_val, u32 config_mask);
static u32 PinmuxDummyReadDrivePad(u32 pinmux_drivepad_name);
static void ConfigurePinmuxInitialPads();
static void ConfigurePinmuxInitialDrivePads();

View File

@@ -74,9 +74,7 @@ void Boot::SetInitialGpioConfiguration() {
/* Set the GPIO's direction. */
Boot::GpioSetDirection(configs[i].pad_name, configs[i].direction);
if (configs[i].direction == GpioDirection_Output) {
/* Set the GPIO's value. */
Boot::GpioSetValue(configs[i].pad_name, configs[i].value);
}
/* Set the GPIO's value. */
Boot::GpioSetValue(configs[i].pad_name, configs[i].value);
}
}

View File

@@ -28,11 +28,6 @@ void Boot::ConfigurePinmux() {
Boot::PinmuxUpdatePark(static_cast<u32>(i));
}
/* Dummy read all drive pads. */
for (size_t i = 0; i < PinmuxDrivePadNameMax; i++) {
Boot::PinmuxDummyReadDrivePad(static_cast<u32>(i));
}
/* Set initial pad configs. */
Boot::ConfigurePinmuxInitialPads();

View File

@@ -361,4 +361,4 @@ static constexpr PinmuxDrivePadDefinition PinmuxDrivePadMap[] = {
{0x00000B6C, 0x01F1F000}, /* WifiWakeAp */
};
static constexpr u32 PinmuxDrivePadNameMax = (sizeof(PinmuxDrivePadMap) / sizeof(PinmuxDrivePadMap[0]));
static constexpr u32 PinmuxDrivePadNameMax = (sizeof(PinmuxDrivePadMap) / sizeof(PinmuxDrivePadMap[0]));

View File

@@ -98,16 +98,20 @@ u32 Boot::PinmuxUpdatePad(u32 pinmux_name, u32 pinmux_config_val, u32 pinmux_con
u32 pinmux_val = *pinmux_reg;
/* This PINMUX register is locked */
if (pinmux_val & 0x80) {
std::abort();
}
if (pinmux_val & 0x80)
return pinmux_val;
u32 pm_val = (pinmux_config_val & 0x07);
u32 pm_config_val = (pinmux_config_val & 0x07);
u32 pm_val = pm_config_val;
/* Adjust PM */
if (pinmux_config_mask_val & 0x07) {
/* Default to safe value */
if (pm_config_val >= 0x06)
pm_val = 0x04;
/* Apply additional changes first */
if (pm_val == 0x05) {
if (pm_config_val == 0x05) {
/* This pin supports PUPD change */
if (pinmux_mask_val & 0x0C) {
/* Change PUPD */
@@ -132,15 +136,14 @@ u32 Boot::PinmuxUpdatePad(u32 pinmux_name, u32 pinmux_config_val, u32 pinmux_con
pinmux_val &= 0xFFFFFFBF;
}
}
} else if (pm_val >= 0x06) {
/* Default to safe value */
pm_val = 0x04;
}
/* Translate PM value if necessary */
if (pm_val == 0x04 || pm_val == 0x05) {
if ((pm_val & 0xFF) == 0x04)
pm_val = pinmux_def->pm_val;
}
/* This pin supports PM change */
if (pinmux_mask_val & 0x03) {
@@ -160,7 +163,7 @@ u32 Boot::PinmuxUpdatePad(u32 pinmux_name, u32 pinmux_config_val, u32 pinmux_con
/* This pin supports PUPD change */
if (pinmux_mask_val & 0x0C) {
/* Change PUPD */
if (((pinmux_val >> 0x02) & 0x03) != (pupd_config_val >> 0x03)) {
if ((pinmux_val & 0x0C) != (pupd_config_val >> 0x03)) {
pinmux_val &= 0xFFFFFFF3;
pinmux_val |= (pupd_config_val >> 0x01);
}
@@ -285,7 +288,7 @@ u32 Boot::PinmuxUpdatePad(u32 pinmux_name, u32 pinmux_config_val, u32 pinmux_con
}
}
u32 ioreset_config_val = (((pinmux_config_val >> 0x08) & 0x1) << 0x10);
u32 ioreset_config_val = ((pinmux_config_val >> 0x08) & 0x10000);
/* Adjust IoReset */
if (pinmux_config_mask_val & 0x100) {
@@ -293,13 +296,12 @@ u32 Boot::PinmuxUpdatePad(u32 pinmux_name, u32 pinmux_config_val, u32 pinmux_con
if (pinmux_mask_val & 0x10000) {
/* Change IoReset */
if (((pinmux_val >> 0x10) ^ (pinmux_config_val >> 0x08)) & 0x01) {
pinmux_val &= 0xFFFEFFFF;
pinmux_val |= ioreset_config_val;
}
}
}
u32 park_config_val = (((pinmux_config_val >> 0x0A) & 0x1) << 0x5);
u32 park_config_val = ((pinmux_config_val >> 0x0A) & 0x20);
/* Adjust Park */
if (pinmux_config_mask_val & 0x400) {
@@ -307,13 +309,12 @@ u32 Boot::PinmuxUpdatePad(u32 pinmux_name, u32 pinmux_config_val, u32 pinmux_con
if (pinmux_mask_val & 0x20) {
/* Change Park */
if (((pinmux_val >> 0x05) ^ (pinmux_config_val >> 0x0A)) & 0x01) {
pinmux_val &= 0xFFFFFFDF;
pinmux_val |= park_config_val;
}
}
}
u32 elpdr_config_val = (((pinmux_config_val >> 0x0B) & 0x1) << 0x08);
u32 elpdr_config_val = ((pinmux_config_val >> 0x0B) & 0x100);
/* Adjust ELpdr */
if (pinmux_config_mask_val & 0x800) {
@@ -321,13 +322,12 @@ u32 Boot::PinmuxUpdatePad(u32 pinmux_name, u32 pinmux_config_val, u32 pinmux_con
if (pinmux_mask_val & 0x100) {
/* Change ELpdr */
if (((pinmux_val >> 0x08) ^ (pinmux_config_val >> 0x0B)) & 0x01) {
pinmux_val &= 0xFFFFFEFF;
pinmux_val |= elpdr_config_val;
}
}
}
u32 ehsm_config_val = (((pinmux_config_val >> 0x0C) & 0x1) << 0x09);
u32 ehsm_config_val = ((pinmux_config_val >> 0x0C) & 0x200);
/* Adjust EHsm */
if (pinmux_config_mask_val & 0x1000) {
@@ -335,13 +335,12 @@ u32 Boot::PinmuxUpdatePad(u32 pinmux_name, u32 pinmux_config_val, u32 pinmux_con
if (pinmux_mask_val & 0x200) {
/* Change EHsm */
if (((pinmux_val >> 0x09) ^ (pinmux_config_val >> 0x0C)) & 0x01) {
pinmux_val &= 0xFFFFFDFF;
pinmux_val |= ehsm_config_val;
}
}
}
u32 eiohv_config_val = (((pinmux_config_val >> 0x09) & 0x1) << 0x0A);
u32 eiohv_config_val = ((pinmux_config_val >> 0x09) & 0x400);
/* Adjust EIoHv */
if (pinmux_config_mask_val & 0x200) {
@@ -349,13 +348,12 @@ u32 Boot::PinmuxUpdatePad(u32 pinmux_name, u32 pinmux_config_val, u32 pinmux_con
if (pinmux_mask_val & 0x400) {
/* Change EIoHv */
if (((pinmux_val >> 0x0A) ^ (pinmux_config_val >> 0x09)) & 0x01) {
pinmux_val &= 0xFFFFFBFF;
pinmux_val |= eiohv_config_val;
}
}
}
u32 eschmt_config_val = (((pinmux_config_val >> 0x0D) & 0x1) << 0x0C);
u32 eschmt_config_val = ((pinmux_config_val >> 0x0D) & 0x1000);
/* Adjust ESchmt */
if (pinmux_config_mask_val & 0x2000) {
@@ -363,13 +361,12 @@ u32 Boot::PinmuxUpdatePad(u32 pinmux_name, u32 pinmux_config_val, u32 pinmux_con
if (pinmux_mask_val & 0x1000) {
/* Change ESchmt */
if (((pinmux_val >> 0x0C) ^ (pinmux_config_val >> 0x0D)) & 0x01) {
pinmux_val &= 0xFFFFEFFF;
pinmux_val |= eschmt_config_val;
}
}
}
u32 preemp_config_val = (((pinmux_config_val >> 0x10) & 0x1) << 0xF);
u32 preemp_config_val = ((pinmux_config_val >> 0x0D) & 0x8000);
/* Adjust Preemp */
if (pinmux_config_mask_val & 0x10000) {
@@ -377,13 +374,12 @@ u32 Boot::PinmuxUpdatePad(u32 pinmux_name, u32 pinmux_config_val, u32 pinmux_con
if (pinmux_mask_val & 0x8000) {
/* Change Preemp */
if (((pinmux_val >> 0x0F) ^ (pinmux_config_val >> 0x10)) & 0x01) {
pinmux_val &= 0xFFFF7FFF;
pinmux_val |= preemp_config_val;
}
}
}
u32 drvtype_config_val = (((pinmux_config_val >> 0x0E) & 0x3) << 0xD);
u32 drvtype_config_val = ((pinmux_config_val >> 0x0E) & 0x6000);
/* Adjust DrvType */
if (pinmux_config_mask_val & 0xC000) {
@@ -391,7 +387,6 @@ u32 Boot::PinmuxUpdatePad(u32 pinmux_name, u32 pinmux_config_val, u32 pinmux_con
if (pinmux_mask_val & 0x6000) {
/* Change DrvType */
if (((pinmux_val >> 0x0D) ^ (pinmux_config_val >> 0x0E)) & 0x03) {
pinmux_val &= 0xFFFF9FFF;
pinmux_val |= drvtype_config_val;
}
}
@@ -489,17 +484,4 @@ u32 Boot::PinmuxUpdateDrivePad(u32 pinmux_drivepad_name, u32 pinmux_drivepad_con
pinmux_drivepad_val = *pinmux_drivepad_reg;
return pinmux_drivepad_val;
}
u32 Boot::PinmuxDummyReadDrivePad(u32 pinmux_drivepad_name) {
const uintptr_t pinmux_base_vaddr = GetPinmuxBaseAddress();
const PinmuxDrivePadDefinition *pinmux_drivepad_def = GetPinmuxDrivePadDefinition(pinmux_drivepad_name);
/* Fetch this PINMUX drive group's register offset */
u32 pinmux_drivepad_reg_offset = pinmux_drivepad_def->reg_offset;
/* Get current register ptr. */
volatile u32 *pinmux_drivepad_reg = reinterpret_cast<volatile u32 *>(pinmux_base_vaddr + pinmux_drivepad_reg_offset);
return *pinmux_drivepad_reg;
}

View File

@@ -1,12 +1,16 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* 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
* ANY WARRANTY{
} without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*

View File

@@ -1,12 +1,16 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* 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
* ANY WARRANTY{
} without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*

View File

@@ -1,12 +1,16 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* 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
* ANY WARRANTY{
} without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*

View File

@@ -1,12 +1,16 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* 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
* ANY WARRANTY{
} without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*

View File

@@ -1,12 +1,16 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* 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
* ANY WARRANTY{
} without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*

View File

@@ -1,12 +1,16 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* 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
* ANY WARRANTY{
} without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*

View File

@@ -1,12 +1,16 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* 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
* ANY WARRANTY{
} without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*

View File

@@ -1,12 +1,16 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* 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
* ANY WARRANTY{
} without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*

View File

@@ -1,12 +1,16 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* 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
* ANY WARRANTY{
} without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*

View File

@@ -26,11 +26,7 @@ Result HidManagement::GetKeysDown(u64 *keys) {
std::scoped_lock<HosMutex> lk(g_hid_keys_down_lock);
hidScanInput();
*keys = 0;
for (int controller = 0; controller < 10; controller++) {
*keys |= hidKeysHeld((HidControllerID) controller);
}
*keys = hidKeysHeld(CONTROLLER_P1_AUTO);
return ResultSuccess;
}
}

View File

@@ -36,11 +36,7 @@ Result HidManagement::GetKeysHeld(u64 *keys) {
}
hidScanInput();
*keys = 0;
for (int controller = 0; controller < 10; controller++) {
*keys |= hidKeysHeld((HidControllerID) controller);
}
*keys = hidKeysHeld(CONTROLLER_P1_AUTO);
return ResultSuccess;
}

View File

@@ -175,9 +175,9 @@ int main(int argc, char **argv)
/* TODO: Create services. */
s_server_manager.AddWaitable(new ServiceServer<ShellService>("pm:shell", 3));
s_server_manager.AddWaitable(new ServiceServer<DebugMonitorService>("pm:dmnt", 3));
s_server_manager.AddWaitable(new ServiceServer<DebugMonitorService>("pm:dmnt", 2));
s_server_manager.AddWaitable(new ServiceServer<BootModeService>("pm:bm", 6));
s_server_manager.AddWaitable(new ServiceServer<InformationService>("pm:info", 3));
s_server_manager.AddWaitable(new ServiceServer<InformationService>("pm:info", 2));
/* Loop forever, servicing our services. */
s_server_manager.Process();

View File

@@ -79,12 +79,8 @@ int main(int argc, char **argv)
//Scan all the inputs. This should be done once for each frame
hidScanInput();
u64 kDown = 0;
for (int controller = 0; controller < 10; controller++) {
// hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
kDown |= hidKeysDown((HidControllerID) controller);
}
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
if (can_reboot && kDown & KEY_MINUS) {
reboot_to_payload();