[PKG2] Add external kip1 patches support via .ini

The format is described in patches.ini.
For now it only supports the kips defined in hekate's code.

Next versions will add support for defining other kips.
This commit is contained in:
ctcaer@gmail.com 2019-06-30 03:45:18 +03:00
parent f3dcfab095
commit ba0f29bc5c
5 changed files with 445 additions and 117 deletions

View file

@ -19,6 +19,8 @@
#include <string.h>
#include "pkg2.h"
#include "pkg2_ini_kippatch.h"
#include "../config/config.h"
#include "../libs/fatfs/ff.h"
#include "../utils/aarch64_util.h"
@ -30,7 +32,7 @@
#include "../gfx/gfx.h"
extern hekate_config h_cfg;
extern void *sd_file_read(const char *path, u32 *fsize);
#ifdef KIP1_PATCH_DEBUG
#include "../utils/util.h"
@ -334,88 +336,41 @@ static kip1_patch_t _fs_emummc[] =
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_100[] =
{
{ KPS(KIP_TEXT) | 0x194A0, 4, "\xBA\x09\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x3A79C, 4, "\xE0\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_100[] =
{
{ "nosigchk", _fs_nosigchk_100 },
{ "nogc", NULL },
{ "emummc", _fs_emummc },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_200[] =
{
{ KPS(KIP_TEXT) | 0x15DF4, 4, "\xBC\x0A\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x3F720, 4, "\x00\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_200[] =
{
{ "nosigchk", _fs_nosigchk_200 },
{ "nogc", NULL },
{ "emummc", _fs_emummc },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_210[] =
{
{ KPS(KIP_TEXT) | 0x15F64, 4, "\xDF\x0A\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x3FAF8, 4, "\x00\x06\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_210[] =
{
{ "nosigchk", _fs_nosigchk_210 },
{ "nogc", NULL },
{ "emummc", _fs_emummc },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_300[] =
{
{ KPS(KIP_TEXT) | 0x18E24, 4, "\x52\x0C\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x49EC8, 4, "\x40\x04\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_300[] =
{
{ "nosigchk", _fs_nosigchk_300 },
{ "nogc", NULL },
{ "emummc", _fs_emummc },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_30x[] =
{
{ KPS(KIP_TEXT) | 0x18E90, 4, "\x52\x0C\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x49F34, 4, "\xE0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_30x[] =
{
{ "nosigchk", _fs_nosigchk_30x },
{ "nogc", NULL },
{ "emummc", _fs_emummc },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_4xx[] =
{
{ KPS(KIP_TEXT) | 0x1C4FC, 4, "\x3C\x2F\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x57934, 4, "\xE0\x02\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nogc_40x[] =
{
{ KPS(KIP_TEXT) | 0xA3458, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" },
@ -425,7 +380,6 @@ static kip1_patch_t _fs_nogc_40x[] =
static kip1_patchset_t _fs_patches_40x[] =
{
{ "nosigchk", _fs_nosigchk_4xx },
{ "nogc", _fs_nogc_40x },
{ "emummc", _fs_emummc },
{ NULL, NULL }
@ -440,19 +394,11 @@ static kip1_patch_t _fs_nogc_410[] =
static kip1_patchset_t _fs_patches_410[] =
{
{ "nosigchk", _fs_nosigchk_4xx },
{ "nogc", _fs_nogc_410 },
{ "emummc", _fs_emummc },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_50x[] =
{
{ KPS(KIP_TEXT) | 0x22DDC, 4, "\x7D\x3E\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x7D490, 4, "\x40\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nogc_50x[] =
{
{ KPS(KIP_TEXT) | 0xCF3C4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
@ -462,19 +408,11 @@ static kip1_patch_t _fs_nogc_50x[] =
static kip1_patchset_t _fs_patches_50x[] =
{
{ "nosigchk", _fs_nosigchk_50x },
{ "nogc", _fs_nogc_50x },
{ "emummc", _fs_emummc },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_510[] =
{
{ KPS(KIP_TEXT) | 0x22E0C, 4, "\x85\x3E\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0x7D860, 4, "\x40\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nogc_510[] =
{
{ KPS(KIP_TEXT) | 0xCF794, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
@ -484,26 +422,11 @@ static kip1_patch_t _fs_nogc_510[] =
static kip1_patchset_t _fs_patches_510[] =
{
{ "nosigchk", _fs_nosigchk_510 },
{ "nogc", _fs_nogc_510 },
{ "emummc", _fs_emummc },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_600[] =
{
{ KPS(KIP_TEXT) | 0x712A8, 4, "\x8E\x3E\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0xEB08C, 4, "\xC0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_600_exfat[] =
{
{ KPS(KIP_TEXT) | 0x7C9A8, 4, "\x8E\x3E\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0xF678C, 4, "\xC0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nogc_600[] =
{
{ KPS(KIP_TEXT) | 0x12CC20, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
@ -520,7 +443,6 @@ static kip1_patch_t _fs_nogc_600_exfat[] =
static kip1_patchset_t _fs_patches_600[] =
{
{ "nosigchk", _fs_nosigchk_600 },
{ "nogc", _fs_nogc_600 },
{ "emummc", _fs_emummc },
{ NULL, NULL }
@ -528,26 +450,11 @@ static kip1_patchset_t _fs_patches_600[] =
static kip1_patchset_t _fs_patches_600_exfat[] =
{
{ "nosigchk", _fs_nosigchk_600_exfat },
{ "nogc", _fs_nogc_600_exfat },
{ "emummc", _fs_emummc },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_700[] =
{
{ KPS(KIP_TEXT) | 0x74A2C, 4, "\x31\x43\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0xF25E4, 4, "\xC0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_700_exfat[] =
{
{ KPS(KIP_TEXT) | 0x7FFDC, 4, "\x31\x43\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0xFDB94, 4, "\xC0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nogc_700[] =
{
{ KPS(KIP_TEXT) | 0x134160, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
@ -564,7 +471,6 @@ static kip1_patch_t _fs_nogc_700_exfat[] =
static kip1_patchset_t _fs_patches_700[] =
{
{ "nosigchk", _fs_nosigchk_700 },
{ "nogc", _fs_nogc_700 },
{ "emummc", _fs_emummc },
{ NULL, NULL }
@ -572,26 +478,11 @@ static kip1_patchset_t _fs_patches_700[] =
static kip1_patchset_t _fs_patches_700_exfat[] =
{
{ "nosigchk", _fs_nosigchk_700_exfat },
{ "nogc", _fs_nogc_700_exfat },
{ "emummc", _fs_emummc },
{ NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_800[] =
{
{ KPS(KIP_TEXT) | 0x7630C, 4, "\x51\x44\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0xF49A4, 4, "\xC0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nosigchk_800_exfat[] =
{
{ KPS(KIP_TEXT) | 0x818BC, 4, "\x51\x44\x00\x94", "\xE0\x03\x1F\x2A" },
{ KPS(KIP_TEXT) | 0xFFF54, 4, "\xC0\x03\x00\x36", "\x1F\x20\x03\xD5" },
{ 0, 0, NULL, NULL }
};
static kip1_patch_t _fs_nogc_800[] =
{
{ KPS(KIP_TEXT) | 0x136800, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
@ -608,7 +499,6 @@ static kip1_patch_t _fs_nogc_800_exfat[] =
static kip1_patchset_t _fs_patches_800[] =
{
{ "nosigchk", _fs_nosigchk_800 },
{ "nogc", _fs_nogc_800 },
{ "emummc", _fs_emummc },
{ NULL, NULL }
@ -616,7 +506,6 @@ static kip1_patchset_t _fs_patches_800[] =
static kip1_patchset_t _fs_patches_800_exfat[] =
{
{ "nosigchk", _fs_nosigchk_800_exfat },
{ "nogc", _fs_nogc_800_exfat },
{ "emummc", _fs_emummc },
{ NULL, NULL }
@ -655,6 +544,82 @@ static kip1_id_t _kip_ids[] =
{ "FS", "\xB4\xCA\xE1\xF2\x49\x65\xD9\x2E", _fs_patches_800_exfat } // FS 8.1.0 exfat
};
static void parse_external_kip_patches()
{
u32 curr_kip_idx = 0;
LIST_INIT(ini_kip_sections);
if (ini_patch_parse(&ini_kip_sections, "bootloader/patches.ini"))
{
// Parse patchsets and glue them together.
LIST_FOREACH_ENTRY(ini_kip_sec_t, ini_psec, &ini_kip_sections, link)
{
kip1_id_t* curr_kip = &_kip_ids[curr_kip_idx];
if (!strcmp(curr_kip->name, ini_psec->name) && !memcmp(curr_kip->hash, ini_psec->hash, 8))
{
kip1_patchset_t *patchsets = (kip1_patchset_t *)calloc(sizeof(kip1_patchset_t), 8);
u32 curr_patchset_idx;
for(curr_patchset_idx = 0; curr_kip->patchset[curr_patchset_idx].name != NULL; curr_patchset_idx++)
{
patchsets[curr_patchset_idx].name = curr_kip->patchset[curr_patchset_idx].name;
patchsets[curr_patchset_idx].patches = curr_kip->patchset[curr_patchset_idx].patches;
}
curr_kip->patchset = patchsets;
bool first_ext_patch = true;
u32 curr_patch_idx = 0;
// Parse patches and glue them together to a patchset.
kip1_patch_t *patches = calloc(sizeof(kip1_patch_t), 16);
LIST_FOREACH_ENTRY(ini_patchset_t, pt, &ini_psec->pts, link)
{
if (first_ext_patch)
{
first_ext_patch = false;
patchsets[curr_patchset_idx].name = malloc(strlen(pt->name) + 1);
strcpy(patchsets[curr_patchset_idx].name, pt->name);
patchsets[curr_patchset_idx].patches = patches;
}
else
{
if (strcmp(pt->name, patchsets[curr_patchset_idx].name))
{
curr_patchset_idx++;
curr_patch_idx = 0;
patches = calloc(sizeof(kip1_patch_t), 16);
patchsets[curr_patchset_idx].name = malloc(strlen(pt->name) + 1);
strcpy(patchsets[curr_patchset_idx].name, pt->name);
patchsets[curr_patchset_idx].patches = patches;
}
}
if (pt->length)
{
patches[curr_patch_idx].offset = pt->offset;
patches[curr_patch_idx].length = pt->length;
patches[curr_patch_idx].srcData = malloc(pt->length);
patches[curr_patch_idx].dstData = malloc(pt->length);
memcpy(patches[curr_patch_idx].srcData, pt->srcData, pt->length);
memcpy(patches[curr_patch_idx].dstData, pt->dstData, pt->length);
}
curr_patch_idx++;
}
curr_patchset_idx++;
patchsets[curr_patchset_idx].name = NULL;
patchsets[curr_patchset_idx].patches = NULL;
}
curr_kip_idx++;
if (!(curr_kip_idx < (sizeof(_kip_ids) / sizeof(_kip_ids[0]))))
break;
}
}
}
const pkg2_kernel_id_t *pkg2_identify(u8 *hash)
{
for (u32 i = 0; i < (sizeof(_pkg2_kernel_ids) / sizeof(pkg2_kernel_id_t)); i++)
@ -872,11 +837,19 @@ static int _kipm_inject(const char *kipm_path, char *target_name, pkg2_kip1_info
return 1;
}
static bool ext_patches_parsed = false;
const char* pkg2_patch_kips(link_t *info, char* patchNames)
{
if (patchNames == NULL || patchNames[0] == 0)
return NULL;
if (!ext_patches_parsed)
{
parse_external_kip_patches();
ext_patches_parsed = true;
}
static const u32 MAX_NUM_PATCHES_REQUESTED = sizeof(u32) * 8;
char* patches[MAX_NUM_PATCHES_REQUESTED];

View file

@ -122,13 +122,13 @@ typedef struct _kip1_patch_t
{
u32 offset; // section+offset of patch to apply.
u32 length; // In bytes, 0 means last patch.
const char* srcData; // That must match.
const char* dstData; // That it gets replaced by.
char* srcData; // That must match.
char* dstData; // That it gets replaced by.
} kip1_patch_t;
typedef struct _kip1_patchset_t
{
const char* name; // NULL means end.
char* name; // NULL means end.
kip1_patch_t* patches; // NULL means not necessary.
} kip1_patchset_t;

View file

@ -0,0 +1,165 @@
#include <string.h>
#include <stdlib.h>
#include "pkg2_ini_kippatch.h"
#include "../libs/fatfs/ff.h"
#include "../mem/heap.h"
#define KPS(x) ((u32)(x) << 29)
static u8 *_htoa(u8 *result, const char *ptr, u8 byte_len)
{
char ch = *ptr;
u32 ascii_len = byte_len * 2;
if (!result)
result = malloc(byte_len);
u8 *dst = result;
while (ch == ' ' || ch == '\t')
ch = *(++ptr);
bool shift = true;
while (ascii_len)
{
u8 tmp = 0;
if (ch >= '0' && ch <= '9')
tmp = (ch - '0');
else if (ch >= 'A' && ch <= 'F')
tmp = (ch - 'A' + 10);
else if (ch >= 'a' && ch <= 'f')
tmp = (ch - 'a' + 10);
if (shift)
*dst = (tmp << 4) & 0xF0;
else
{
*dst |= (tmp & 0x0F);
dst++;
}
ascii_len--;
ch = *(++ptr);
shift = !shift;
}
return result;
}
static char *_strdup(char *str)
{
if (!str)
return NULL;
if (str[0] == ' ' && (strlen(str) > 1))
str++;
char *res = (char *)malloc(strlen(str) + 1);
strcpy(res, str);
if (res[strlen(res) - 1] == ' ' && (strlen(res) > 1))
res[strlen(res) - 1] = 0;
return res;
}
static u32 _find_patch_section_name(char *lbuf, u32 lblen, char schar)
{
u32 i;
for (i = 0; i < lblen && lbuf[i] != schar && lbuf[i] != '\n' && lbuf[i] != '\r'; i++)
;
lbuf[i] = 0;
return i;
}
static ini_kip_sec_t *_ini_create_kip_section(link_t *dst, ini_kip_sec_t *ksec, char *name)
{
if (ksec)
{
list_append(dst, &ksec->link);
ksec = NULL;
}
ksec = (ini_kip_sec_t *)malloc(sizeof(ini_kip_sec_t));
u32 i = _find_patch_section_name(name, strlen(name), ':') + 1;
ksec->name = _strdup(name);
// Get hash section.
_htoa(ksec->hash, &name[i], 8);
return ksec;
}
int ini_patch_parse(link_t *dst, char *ini_path)
{
u32 lblen;
char lbuf[512];
FIL fp;
ini_kip_sec_t *ksec = NULL;
// Open ini.
if (f_open(&fp, ini_path, FA_READ) != FR_OK)
return 0;
do
{
// Fetch one line.
lbuf[0] = 0;
f_gets(lbuf, 512, &fp);
lblen = strlen(lbuf);
// Remove trailing newline.
if (lbuf[lblen - 1] == '\n' || lbuf[lblen - 1] == '\r')
lbuf[lblen - 1] = 0;
if (lblen > 2 && lbuf[0] == '[') // Create new section.
{
_find_patch_section_name(lbuf, lblen, ']');
ksec = _ini_create_kip_section(dst, ksec, &lbuf[1]);
list_init(&ksec->pts);
}
else if (ksec && lbuf[0] == '.') //Extract key/value.
{
u32 tmp = 0;
u32 i = _find_patch_section_name(lbuf, lblen, '=');
ini_patchset_t *pt = (ini_patchset_t *)malloc(sizeof(ini_patchset_t));
pt->name = _strdup(&lbuf[1]);
u8 kip_sidx = lbuf[i + 1] - '0';
if (kip_sidx < 6)
{
pt->offset = KPS(kip_sidx);
tmp = _find_patch_section_name(&lbuf[i + 3], lblen, ':');
pt->offset |= strtol(&lbuf[i + 3], NULL, 16);
i += tmp + 4;
tmp = _find_patch_section_name(&lbuf[i], lblen, ':');
pt->length = strtol(&lbuf[i], NULL, 16);
i += tmp + 1;
tmp = _find_patch_section_name(&lbuf[i], lblen, ',');
pt->srcData = _htoa(NULL, &lbuf[i], pt->length);
i += tmp + 1;
pt->dstData = _htoa(NULL, &lbuf[i], pt->length);
}
else
{
pt->offset = 0;
pt->length = 0;
pt->srcData = NULL;
pt->dstData = NULL;
}
list_append(&ksec->pts, &pt->link);
}
} while (!f_eof(&fp));
f_close(&fp);
if (ksec)
list_append(dst, &ksec->link);
return 1;
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2019 CTCaer
*
* 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/>.
*/
#ifndef _INIPATCH_H_
#define _INIPATCH_H_
#include "../utils/types.h"
#include "../utils/list.h"
typedef struct _ini_patchset_t
{
char *name;
u32 offset; // section + offset of patch to apply.
u32 length; // In bytes, 0 means last patch.
u8 *srcData; // That must match.
u8 *dstData; // Gets replaced with.
link_t link;
} ini_patchset_t;
typedef struct _ini_kip_sec_t
{
char *name;
u8 hash[8];
link_t pts;
link_t link;
} ini_kip_sec_t;
int ini_patch_parse(link_t *dst, char *ini_path);
#endif

147
res/patches.ini Normal file
View file

@ -0,0 +1,147 @@
# UTF-8
# A KIP section is [kip1_name:sha256_hex_8bytes]
# A patchset is .patch_name=kip_section_dec:offset_hex_0x:length_hex_0x:src_data_hex,dst_data_hex
# _dec: 1 char decimal | _hex_0x: max u32 prefixed with 0x | _hex: hex array.
# Kip1 section decimals: TEXT: 0, RODATA: 1, DATA: 2.
#
# Care when editing this, otherwise it will fail to be parsed.
#FS Patches for 1.0.0
[FS:de9fdda4085dd5fe]
.nosigchk=0:0x194A0:0x4:BA090094,E0031F2A
.nosigchk=0:0x3A79C:0x4:E0060036,1F2003D5
#FS Patches for 1.0.0 exfat
[FS:fc3e80991dca1796]
.nosigchk=0:0x194A0:0x4:BA090094,E0031F2A
.nosigchk=0:0x3A79C:0x4:E0060036,1F2003D5
#FS Patches for 2.0.0
[FS:cd7bbe18d6130b28]
.nosigchk=0:0x15DF4:0x4:BC0A0094,E0031F2A
.nosigchk=0:0x3F720:0x4:00060036,1F2003D5
#FS Patches for 2.0.0 exfat
[FS:e76692dfaa0420e9]
.nosigchk=0:0x15DF4:0x4:BC0A0094,E0031F2A
.nosigchk=0:0x3F720:0x4:00060036,1F2003D5
#FS Patches for 2.1.0
[FS:0d7005627b07767c]
.nosigchk=0:0x15F64:0x4:DF0A0094,E0031F2A
.nosigchk=0:0x3FAF8:0x4:00060036,1F2003D5
#FS Patches for 2.1.0 exfat
[FS:dbd85fcacc193da8]
.nosigchk=0:0x15F64:0x4:DF0A0094,E0031F2A
.nosigchk=0:0x3FAF8:0x4:00060036,1F2003D5
#FS Patches for 3.0.0
[FS:a86da5e87ef1097b]
.nosigchk=0:0x18E24:0x4:520C0094,E0031F2A
.nosigchk=0:0x49EC8:0x4:40040036,1F2003D5
#FS Patches for 3.0.0 exfat
[FS:981c57e7f02f70f7]
.nosigchk=0:0x18E24:0x4:520C0094,E0031F2A
.nosigchk=0:0x49EC8:0x4:40040036,1F2003D5
#FS Patches for 3.0.1
[FS:57397c063f10b631]
.nosigchk=0:0x18E90:0x4:520C0094,E0031F2A
.nosigchk=0:0x49F34:0x4:E0030036,1F2003D5
#FS Patches for 3.0.1 exfat
[FS:073099d7c6ad7d89]
.nosigchk=0:0x18E90:0x4:520C0094,E0031F2A
.nosigchk=0:0x49F34:0x4:E0030036,1F2003D5
#FS Patches for 4.0.0
[FS:06e90719595a010c]
.nosigchk=0:0x1C4FC:0x4:3C2F0094,E0031F2A
.nosigchk=0:0x57934:0x4:E0020036,1F2003D5
#FS Patches for 4.0.0 exfat
[FS:549b0f8d6f72c4e9]
.nosigchk=0:0x1C4FC:0x4:3C2F0094,E0031F2A
.nosigchk=0:0x57934:0x4:E0020036,1F2003D5
#FS Patches for 4.1.0
[FS:8096af7c6a35aa82]
.nosigchk=0:0x1C4FC:0x4:3C2F0094,E0031F2A
.nosigchk=0:0x57934:0x4:E0020036,1F2003D5
#FS Patches for 4.1.0 exfat
[FS:02d5abaafd20c8b0]
.nosigchk=0:0x1C4FC:0x4:3C2F0094,E0031F2A
.nosigchk=0:0x57934:0x4:E0020036,1F2003D5
#FS Patches for 5.0.0
[FS:a6f27ad9ac7c73ad]
.nosigchk=0:0x22DDC:0x4:7D3E0094,E0031F2A
.nosigchk=0:0x7D490:0x4:40030036,1F2003D5
#FS Patches for 5.0.0 exfat
[FS:ce3ecba2f2f062f5]
.nosigchk=0:0x22DDC:0x4:7D3E0094,E0031F2A
.nosigchk=0:0x7D490:0x4:40030036,1F2003D5
#FS Patches for 5.1.0
[FS:76f87402c9387c0f]
.nosigchk=0:0x22E0C:0x4:853E0094,E0031F2A
.nosigchk=0:0x7D860:0x4:40030036,1F2003D5
#FS Patches for 5.1.0 exfat
[FS:10b2d81605488599]
.nosigchk=0:0x22E0C:0x4:853E0094,E0031F2A
.nosigchk=0:0x7D860:0x4:40030036,1F2003D5
#FS Patches for 6.0.0 - 4
[FS:1b82cb221867cb52]
.nosigchk=0:0x712A8:0x4:8E3E0094,E0031F2A
.nosigchk=0:0xEB08C:0x4:C0030036,1F2003D5
#FS Patches for 6.0.0 - 4 exfat
[FS:966add3d20b62713]
.nosigchk=0:0x7C9A8:0x4:8E3E0094,E0031F2A
.nosigchk=0:0xF678C:0x4:C0030036,1F2003D5
#FS Patches for 6.0.0 - 5
[FS:3a574d436186191d]
.nosigchk=0:0x712A8:0x4:8E3E0094,E0031F2A
.nosigchk=0:0xEB08C:0x4:C0030036,1F2003D5
#FS Patches for 6.0.0 - 5 exfat
[FS:330553f6b5fb55c4]
.nosigchk=0:0x7C9A8:0x4:8E3E0094,E0031F2A
.nosigchk=0:0xF678C:0x4:C0030036,1F2003D5
#FS Patches for 7.0.0
[FS:2ADBE97E9B5F4177]
.nosigchk=0:0x74A2C:0x4:31430094,E0031F2A
.nosigchk=0:0xF25E4:0x4:C0030036,1F2003D5
#FS Patches for 7.0.0 exfat
[FS:2CCE659CEC536A8E]
.nosigchk=0:0x7FFDC:0x4:31430094,E0031F2A
.nosigchk=0:0xFDB94:0x4:C0030036,1F2003D5
#FS Patches for 8.0.0
[FS:B2F5176B3548364D]
.nosigchk=0:0x7630C:0x4:51440094,E0031F2A
.nosigchk=0:0xF49A4:0x4:C0030036,1F2003D5
#FS Patches for 8.0.0 exfat
[FS:DBD941C0C53C52CC]
.nosigchk=0:0x818BC:0x4:51440094,E0031F2A
.nosigchk=0:0xFFF54:0x4:C0030036,1F2003D5
#FS Patches for 8.1.0
[FS:6B09B67B29C02024]
.nosigchk=0:0x7630C:0x4:51440094,E0031F2A
.nosigchk=0:0xF49A4:0x4:C0030036,1F2003D5
#FS Patches for 8.1.0 exfat
[FS:B4CAE1F24965D92E]
.nosigchk=0:0x818BC:0x4:51440094,E0031F2A
.nosigchk=0:0xFFF54:0x4:C0030036,1F2003D5