mirror of
https://github.com/CTCaer/hekate.git
synced 2024-12-25 15:17:19 +00:00
pkg2: ini patches: reduce heap fragmentation/pressure
This commit is contained in:
parent
781f377083
commit
3b2f438f69
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2021 CTCaer
|
* Copyright (c) 2018-2022 CTCaer
|
||||||
*
|
*
|
||||||
* 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,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@ -72,17 +72,13 @@ void pkg2_get_ids(kip1_id_t **ids, u32 *entries)
|
|||||||
|
|
||||||
static void parse_external_kip_patches()
|
static void parse_external_kip_patches()
|
||||||
{
|
{
|
||||||
static bool ext_patches_done = false;
|
static bool ext_patches_parsed = false;
|
||||||
|
|
||||||
if (ext_patches_done)
|
if (ext_patches_parsed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
u32 curr_kip_idx = 0;
|
|
||||||
char path[64];
|
|
||||||
strcpy(path, "bootloader/patches.ini");
|
|
||||||
|
|
||||||
LIST_INIT(ini_kip_sections);
|
LIST_INIT(ini_kip_sections);
|
||||||
if (ini_patch_parse(&ini_kip_sections, path))
|
if (ini_patch_parse(&ini_kip_sections, "bootloader/patches.ini"))
|
||||||
{
|
{
|
||||||
// Copy ids into a new patchset.
|
// Copy ids into a new patchset.
|
||||||
_kip_id_sets = calloc(sizeof(kip1_id_t), 256); // Max 256 kip ids.
|
_kip_id_sets = calloc(sizeof(kip1_id_t), 256); // Max 256 kip ids.
|
||||||
@ -93,13 +89,15 @@ static void parse_external_kip_patches()
|
|||||||
{
|
{
|
||||||
kip1_id_t* curr_kip = NULL;
|
kip1_id_t* curr_kip = NULL;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (curr_kip_idx = 0; curr_kip_idx < _kip_id_sets_cnt + 1; curr_kip_idx++)
|
for (u32 curr_kip_idx = 0; curr_kip_idx < _kip_id_sets_cnt + 1; curr_kip_idx++)
|
||||||
{
|
{
|
||||||
curr_kip = &_kip_id_sets[curr_kip_idx];
|
curr_kip = &_kip_id_sets[curr_kip_idx];
|
||||||
|
|
||||||
|
// Check if reached the end of predefined list.
|
||||||
if (!curr_kip->name)
|
if (!curr_kip->name)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Check if name and hash match.
|
||||||
if (!strcmp(curr_kip->name, ini_psec->name) && !memcmp(curr_kip->hash, ini_psec->hash, 8))
|
if (!strcmp(curr_kip->name, ini_psec->name) && !memcmp(curr_kip->hash, ini_psec->hash, 8))
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
@ -140,23 +138,18 @@ static void parse_external_kip_patches()
|
|||||||
if (first_ext_patch)
|
if (first_ext_patch)
|
||||||
{
|
{
|
||||||
first_ext_patch = false;
|
first_ext_patch = false;
|
||||||
patchsets[curr_patchset_idx].name = malloc(strlen(pt->name) + 1);
|
patchsets[curr_patchset_idx].name = pt->name;
|
||||||
strcpy(patchsets[curr_patchset_idx].name, pt->name);
|
|
||||||
patchsets[curr_patchset_idx].patches = patches;
|
patchsets[curr_patchset_idx].patches = patches;
|
||||||
}
|
}
|
||||||
else
|
else if (strcmp(pt->name, patchsets[curr_patchset_idx].name))
|
||||||
{
|
{
|
||||||
// Check if new patchset name is found and create a new set.
|
// New patchset name found, create a new set.
|
||||||
if (strcmp(pt->name, patchsets[curr_patchset_idx].name))
|
curr_patchset_idx++;
|
||||||
{
|
curr_patch_idx = 0;
|
||||||
curr_patchset_idx++;
|
patches = calloc(sizeof(kip1_patch_t), 32); // Max 32 patches per set.
|
||||||
curr_patch_idx = 0;
|
|
||||||
patches = calloc(sizeof(kip1_patch_t), 16); // Max 16 patches per set.
|
|
||||||
|
|
||||||
patchsets[curr_patchset_idx].name = malloc(strlen(pt->name) + 1);
|
patchsets[curr_patchset_idx].name = pt->name;
|
||||||
strcpy(patchsets[curr_patchset_idx].name, pt->name);
|
patchsets[curr_patchset_idx].patches = patches;
|
||||||
patchsets[curr_patchset_idx].patches = patches;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pt->length)
|
if (pt->length)
|
||||||
@ -164,10 +157,8 @@ static void parse_external_kip_patches()
|
|||||||
patches[curr_patch_idx].offset = pt->offset;
|
patches[curr_patch_idx].offset = pt->offset;
|
||||||
patches[curr_patch_idx].length = pt->length;
|
patches[curr_patch_idx].length = pt->length;
|
||||||
|
|
||||||
patches[curr_patch_idx].srcData = malloc(pt->length);
|
patches[curr_patch_idx].srcData = (char *)pt->srcData;
|
||||||
patches[curr_patch_idx].dstData = malloc(pt->length);
|
patches[curr_patch_idx].dstData = (char *)pt->dstData;
|
||||||
memcpy(patches[curr_patch_idx].srcData, pt->srcData, pt->length);
|
|
||||||
memcpy(patches[curr_patch_idx].dstData, pt->dstData, pt->length);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
patches[curr_patch_idx].srcData = malloc(1); // Empty patches check. Keep everything else as 0.
|
patches[curr_patch_idx].srcData = malloc(1); // Empty patches check. Keep everything else as 0.
|
||||||
@ -180,7 +171,7 @@ static void parse_external_kip_patches()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ext_patches_done = true;
|
ext_patches_parsed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pkg2_kernel_id_t *pkg2_identify(u8 *hash)
|
const pkg2_kernel_id_t *pkg2_identify(u8 *hash)
|
||||||
@ -436,19 +427,11 @@ static int _kipm_inject(const char *kipm_path, char *target_name, pkg2_kip1_info
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ext_patches_parsed = false;
|
|
||||||
|
|
||||||
const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||||
{
|
{
|
||||||
if (patchNames == NULL || patchNames[0] == 0)
|
if (patchNames == NULL || patchNames[0] == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!ext_patches_parsed)
|
|
||||||
{
|
|
||||||
parse_external_kip_patches();
|
|
||||||
ext_patches_parsed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const u32 MAX_NUM_PATCHES_REQUESTED = sizeof(u32) * 8;
|
static const u32 MAX_NUM_PATCHES_REQUESTED = sizeof(u32) * 8;
|
||||||
char* patches[MAX_NUM_PATCHES_REQUESTED];
|
char* patches[MAX_NUM_PATCHES_REQUESTED];
|
||||||
|
|
||||||
@ -498,6 +481,16 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
|||||||
DPRINTF("Requested patch: '%s'\n", patches[i]);
|
DPRINTF("Requested patch: '%s'\n", patches[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse external patches if needed.
|
||||||
|
for (u32 i = 0; i < numPatches; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(patches[i], "emummc") && strcmp(patches[i], "nogc"))
|
||||||
|
{
|
||||||
|
parse_external_kip_patches();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u32 shaBuf[32 / sizeof(u32)];
|
u32 shaBuf[32 / sizeof(u32)];
|
||||||
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link)
|
LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, info, link)
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2022 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@ -8,12 +24,12 @@
|
|||||||
|
|
||||||
#define KPS(x) ((u32)(x) << 29)
|
#define KPS(x) ((u32)(x) << 29)
|
||||||
|
|
||||||
static u8 *_htoa(u8 *result, const char *ptr, u8 byte_len)
|
static u8 *_htoa(u8 *result, const char *ptr, u8 byte_len, u8 *buf)
|
||||||
{
|
{
|
||||||
char ch = *ptr;
|
char ch = *ptr;
|
||||||
u32 ascii_len = byte_len * 2;
|
u32 ascii_len = byte_len * 2;
|
||||||
if (!result)
|
if (!result)
|
||||||
result = malloc(byte_len);
|
result = buf;
|
||||||
u8 *dst = result;
|
u8 *dst = result;
|
||||||
|
|
||||||
while (ch == ' ' || ch == '\t')
|
while (ch == ' ' || ch == '\t')
|
||||||
@ -46,24 +62,11 @@ static u8 *_htoa(u8 *result, const char *ptr, u8 byte_len)
|
|||||||
return result;
|
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)
|
static u32 _find_patch_section_name(char *lbuf, u32 lblen, char schar)
|
||||||
{
|
{
|
||||||
u32 i;
|
u32 i;
|
||||||
for (i = 0; i < lblen && lbuf[i] != schar && lbuf[i] != '\n' && lbuf[i] != '\r'; i++)
|
// Depends on 'FF_USE_STRFUNC 2' that removes \r.
|
||||||
|
for (i = 0; i < lblen && lbuf[i] != schar && lbuf[i] != '\n'; i++)
|
||||||
;
|
;
|
||||||
lbuf[i] = 0;
|
lbuf[i] = 0;
|
||||||
|
|
||||||
@ -75,12 +78,16 @@ static ini_kip_sec_t *_ini_create_kip_section(link_t *dst, ini_kip_sec_t *ksec,
|
|||||||
if (ksec)
|
if (ksec)
|
||||||
list_append(dst, &ksec->link);
|
list_append(dst, &ksec->link);
|
||||||
|
|
||||||
ksec = (ini_kip_sec_t *)calloc(sizeof(ini_kip_sec_t), 1);
|
// Calculate total allocation size.
|
||||||
u32 i = _find_patch_section_name(name, strlen(name), ':') + 1;
|
u32 len = strlen(name);
|
||||||
ksec->name = _strdup(name);
|
char *buf = calloc(sizeof(ini_kip_sec_t) + len + 1, 1);
|
||||||
|
|
||||||
|
ksec = (ini_kip_sec_t *)buf;
|
||||||
|
u32 i = _find_patch_section_name(name, len, ':') + 1;
|
||||||
|
ksec->name = strcpy_ns(buf + sizeof(ini_kip_sec_t), name);
|
||||||
|
|
||||||
// Get hash section.
|
// Get hash section.
|
||||||
_htoa(ksec->hash, &name[i], 8);
|
_htoa(ksec->hash, &name[i], 8, NULL);
|
||||||
|
|
||||||
return ksec;
|
return ksec;
|
||||||
}
|
}
|
||||||
@ -89,13 +96,15 @@ int ini_patch_parse(link_t *dst, char *ini_path)
|
|||||||
{
|
{
|
||||||
FIL fp;
|
FIL fp;
|
||||||
u32 lblen;
|
u32 lblen;
|
||||||
char lbuf[512];
|
char *lbuf;
|
||||||
ini_kip_sec_t *ksec = NULL;
|
ini_kip_sec_t *ksec = NULL;
|
||||||
|
|
||||||
// Open ini.
|
// Open ini.
|
||||||
if (f_open(&fp, ini_path, FA_READ) != FR_OK)
|
if (f_open(&fp, ini_path, FA_READ) != FR_OK)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
lbuf = malloc(512);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Fetch one line.
|
// Fetch one line.
|
||||||
@ -111,37 +120,47 @@ int ini_patch_parse(link_t *dst, char *ini_path)
|
|||||||
{
|
{
|
||||||
_find_patch_section_name(lbuf, lblen, ']');
|
_find_patch_section_name(lbuf, lblen, ']');
|
||||||
|
|
||||||
|
// Set patchset kip name and hash.
|
||||||
ksec = _ini_create_kip_section(dst, ksec, &lbuf[1]);
|
ksec = _ini_create_kip_section(dst, ksec, &lbuf[1]);
|
||||||
list_init(&ksec->pts);
|
list_init(&ksec->pts);
|
||||||
}
|
}
|
||||||
else if (ksec && lbuf[0] == '.') //Extract key/value.
|
else if (ksec && lbuf[0] == '.') // Extract key/value.
|
||||||
{
|
{
|
||||||
u32 tmp = 0;
|
u32 str_start = 0;
|
||||||
u32 i = _find_patch_section_name(lbuf, lblen, '=');
|
u32 pos = _find_patch_section_name(lbuf, lblen, '=');
|
||||||
|
|
||||||
ini_patchset_t *pt = (ini_patchset_t *)calloc(sizeof(ini_patchset_t), 1);
|
// Calculate total allocation size.
|
||||||
|
char *buf = calloc(sizeof(ini_patchset_t) + strlen(&lbuf[1]) + 1, 1);
|
||||||
|
ini_patchset_t *pt = (ini_patchset_t *)buf;
|
||||||
|
|
||||||
pt->name = _strdup(&lbuf[1]);
|
// Set patch name.
|
||||||
|
pt->name = strcpy_ns(buf + sizeof(ini_patchset_t), &lbuf[1]);
|
||||||
|
|
||||||
u8 kip_sidx = lbuf[i + 1] - '0';
|
u8 kip_sidx = lbuf[pos + 1] - '0';
|
||||||
|
pos += 3;
|
||||||
|
|
||||||
if (kip_sidx < 6)
|
if (kip_sidx < 6)
|
||||||
{
|
{
|
||||||
|
// Set patch offset.
|
||||||
pt->offset = KPS(kip_sidx);
|
pt->offset = KPS(kip_sidx);
|
||||||
tmp = _find_patch_section_name(&lbuf[i + 3], lblen, ':');
|
str_start = _find_patch_section_name(&lbuf[pos], lblen - pos, ':');
|
||||||
pt->offset |= strtol(&lbuf[i + 3], NULL, 16);
|
pt->offset |= strtol(&lbuf[pos], NULL, 16);
|
||||||
|
pos += str_start + 1;
|
||||||
|
|
||||||
i += tmp + 4;
|
// Set patch size.
|
||||||
|
str_start = _find_patch_section_name(&lbuf[pos], lblen - pos, ':');
|
||||||
|
pt->length = strtol(&lbuf[pos], NULL, 16);
|
||||||
|
pos += str_start + 1;
|
||||||
|
|
||||||
tmp = _find_patch_section_name(&lbuf[i], lblen, ':');
|
u8 *buf = malloc(pt->length * 2);
|
||||||
pt->length = strtol(&lbuf[i], NULL, 16);
|
|
||||||
|
|
||||||
i += tmp + 1;
|
// Set patch source data.
|
||||||
|
str_start = _find_patch_section_name(&lbuf[pos], lblen - pos, ',');
|
||||||
|
pt->srcData = _htoa(NULL, &lbuf[pos], pt->length, buf);
|
||||||
|
pos += str_start + 1;
|
||||||
|
|
||||||
tmp = _find_patch_section_name(&lbuf[i], lblen, ',');
|
// Set patch destination data.
|
||||||
pt->srcData = _htoa(NULL, &lbuf[i], pt->length);
|
pt->dstData = _htoa(NULL, &lbuf[pos], pt->length, buf + pt->length);
|
||||||
i += tmp + 1;
|
|
||||||
pt->dstData = _htoa(NULL, &lbuf[i], pt->length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
list_append(&ksec->pts, &pt->link);
|
list_append(&ksec->pts, &pt->link);
|
||||||
@ -153,5 +172,7 @@ int ini_patch_parse(link_t *dst, char *ini_path)
|
|||||||
if (ksec)
|
if (ksec)
|
||||||
list_append(dst, &ksec->link);
|
list_append(dst, &ksec->link);
|
||||||
|
|
||||||
|
free(lbuf);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user