Skip to content

Commit

Permalink
fusee: remove ips patch parsing from sd filesystem
Browse files Browse the repository at this point in the history
Parsing the SD fs is very slow. In addition, the only KIPs are either a) atmosphere modules, or b) FS.

The IPS subsystem was originally designed to make nogc/etc patches work for FS,
but these are now internal, and it appears that the literal only kip patches
that exist are for piracy.

It just doesn't make sense to slow down boot for every normal user for a feature
that has no actual usecase, and especially when fusee is already so minimal.
  • Loading branch information
SciresM committed Nov 13, 2023
1 parent 872c18c commit 46a4357
Showing 1 changed file with 0 additions and 181 deletions.
181 changes: 0 additions & 181 deletions fusee/program/source/fusee_stratosphere.cpp
Expand Up @@ -385,15 +385,6 @@ namespace ams::nxboot {
return nullptr;
}

InitialProcessMeta *FindInitialProcess(const se::Sha256Hash &hash) {
for (InitialProcessMeta *cur = std::addressof(g_initial_process_meta); cur != nullptr; cur = cur->next) {
if (std::memcmp(std::addressof(cur->kip_hash), std::addressof(hash), sizeof(hash)) == 0) {
return cur;
}
}
return nullptr;
}

u32 GetPatchSegments(const InitialProcessHeader *kip, u32 offset, size_t size) {
/* Create segment mask. */
u32 segments = 0;
Expand Down Expand Up @@ -474,78 +465,6 @@ namespace ams::nxboot {
meta->patches_tail = new_patch;
}

void AddIps24PatchToKip(InitialProcessMeta *meta, const u8 *ips, s32 size) {
while (size > 0) {
/* Read offset, stopping at EOF */
const u32 offset = (static_cast<u32>(ips[0]) << 16) | (static_cast<u32>(ips[1]) << 8) | (static_cast<u32>(ips[2]) << 0);
if (offset == 0x454F46) {
break;
}

/* Read size. */
const u16 cur_size = (static_cast<u32>(ips[3]) << 8) | (static_cast<u32>(ips[4]) << 0);

if (cur_size > 0) {
/* Add patch. */
AddPatch(meta, offset, ips + 5, cur_size, false);

/* Advance. */
ips += (5 + cur_size);
size -= (5 + cur_size);
} else {
/* Read RLE size */
const u16 rle_size = (static_cast<u32>(ips[5]) << 8) | (static_cast<u32>(ips[6]) << 0);

/* Add patch. */
AddPatch(meta, offset, ips + 7, rle_size, true);

/* Advance. */
ips += 8;
size -= 8;
}
}
}

void AddIps32PatchToKip(InitialProcessMeta *meta, const u8 *ips, s32 size) {
while (size > 0) {
/* Read offset, stopping at EOF */
const u32 offset = (static_cast<u32>(ips[0]) << 24) | (static_cast<u32>(ips[1]) << 16) | (static_cast<u32>(ips[2]) << 8) | (static_cast<u32>(ips[3]) << 0);
if (offset == 0x45454F46) {
break;
}

/* Read size. */
const u16 cur_size = (static_cast<u32>(ips[4]) << 8) | (static_cast<u32>(ips[5]) << 0);

if (cur_size > 0) {
/* Add patch. */
AddPatch(meta, offset, ips + 6, cur_size, false);

/* Advance. */
ips += (6 + cur_size);
size -= (6 + cur_size);
} else {
/* Read RLE size */
const u16 rle_size = (static_cast<u32>(ips[6]) << 8) | (static_cast<u32>(ips[7]) << 0);

/* Add patch. */
AddPatch(meta, offset, ips + 8, rle_size, true);

/* Advance. */
ips += 9;
size -= 9;
}
}
}

void AddIpsPatchToKip(InitialProcessMeta *meta, const u8 *ips, s32 size) {
if (std::memcmp(ips, "PATCH", 5) == 0) {
AddIps24PatchToKip(meta, ips + 5, size - 5);
} else if (std::memcmp(ips, "IPS32", 5) == 0) {
AddIps32PatchToKip(meta, ips + 5, size - 5);
}
}

constexpr const u8 NogcPatch0[] = {
0x80
};
Expand Down Expand Up @@ -891,106 +810,6 @@ namespace ams::nxboot {
}

/* TODO ams.tma2: add mount_host patches. */

/* Add generic patches. */
{
/* Create patch path. */
char patch_path[0x220];
std::memcpy(patch_path, "sdmc:/atmosphere/kip_patches", 0x1D);

fs::DirectoryHandle patch_root_dir;
if (R_SUCCEEDED(fs::OpenDirectory(std::addressof(patch_root_dir), patch_path))) {
ON_SCOPE_EXIT { fs::CloseDirectory(patch_root_dir); };

s64 count;
fs::DirectoryEntry entries[1];
while (R_SUCCEEDED(fs::ReadDirectory(std::addressof(count), entries, patch_root_dir, util::size(entries))) && count > 0) {
/* Check that dir is a dir. */
if (fs::GetEntryType(entries[0]) != fs::DirectoryEntryType_Directory) {
continue;
}

/* For compatibility, ignore the old "default_nogc" patches. */
if (std::strcmp(entries[0].file_name, "default_nogc") == 0) {
continue;
}

/* Get filename length. */
const int dir_len = std::strlen(entries[0].file_name);

/* Adjust patch path. */
patch_path[0x1C] = '/';
std::memcpy(patch_path + 0x1D, entries[0].file_name, dir_len + 1);

/* Try to open the patch subdirectory. */
fs::DirectoryHandle patch_dir;
if (R_SUCCEEDED(fs::OpenDirectory(std::addressof(patch_dir), patch_path))) {
ON_SCOPE_EXIT { fs::CloseDirectory(patch_dir); };

/* Read patches. */
while (R_SUCCEEDED(fs::ReadDirectory(std::addressof(count), entries, patch_dir, util::size(entries))) && count > 0) {
/* Check that file is a file. */
if (fs::GetEntryType(entries[0]) != fs::DirectoryEntryType_File) {
continue;
}

/* Get filename length. */
const int name_len = std::strlen(entries[0].file_name);

/* Adjust patch path. */
patch_path[0x1D + dir_len] = '/';
std::memcpy(patch_path + 0x1D + dir_len + 1, entries[0].file_name, name_len + 1);

/* Check that file is "{hex}.ips" file. */
const int path_len = 0x1D + dir_len + 1 + name_len;
if (name_len != 0x44 || std::memcmp(patch_path + path_len - 4, ".ips", 5) != 0) {
continue;
}

/* Check that the filename is hex. */
bool valid_name = true;
se::Sha256Hash patch_name = {};
u32 shift = 4;
for (int i = 0; i < name_len - 4; ++i) {
const char c = entries[0].file_name[i];

u8 val;
if ('0' <= c && c <= '9') {
val = (c - '0');
} else if ('a' <= c && c <= 'f') {
val = (c - 'a') + 10;
} else if ('A' <= c && c <= 'F') {
val = (c - 'A') + 10;
} else {
valid_name = false;
break;
}

patch_name.bytes[i >> 1] |= val << shift;
shift ^= 4;
}

/* Ignore invalid patches. */
if (!valid_name) {
continue;
}

/* Find kip for the patch. */
auto *kip_meta = FindInitialProcess(patch_name);
if (kip_meta == nullptr) {
continue;
}

/* Read the ips patch. */
s64 file_size;
if (u8 *ips = static_cast<u8 *>(ReadFile(std::addressof(file_size), patch_path)); ips != nullptr) {
AddIpsPatchToKip(kip_meta, ips, static_cast<s32>(file_size));
}
}
}
}
}
}
}

/* Return the fs version we're using. */
Expand Down

2 comments on commit 46a4357

@impeeza
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello there, I wonder, if sysmodules like Mission Control (Bluetooth MiTM), and bootlogo patches will be affected? they do not have IPS patches on the «sdmc:/atmosphere/kip_patches» path but on the «sdmc:/atmosphere/exefs_patches» one thanks.

@borntohonk
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello there, I wonder, if sysmodules like Mission Control (Bluetooth MiTM), and bootlogo patches will be affected? they do not have IPS patches on the «sdmc:/atmosphere/kip_patches» path but on the «sdmc:/atmosphere/exefs_patches» one thanks.

https://github.com/Atmosphere-NX/Atmosphere/blob/master/stratosphere/loader/source/ldr_patcher.cpp#L23

Please sign in to comment.