Files
hekate/bootloader/hos/pkg2.h
CTCaer 3630c2a099 pkg2: fix ini size when not using mesosphere
Important in case the same ini1 space is used and stock kernel is new.

Additionally, also set the hash for the 3rd section, even if empty.
2025-01-24 16:11:36 +02:00

167 lines
4.0 KiB
C

/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 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 _PKG2_H_
#define _PKG2_H_
#include <bdk.h>
#define PKG2_MAGIC 0x31324B50
#define PKG2_SEC_BASE 0x80000000
#define PKG2_SEC_KERNEL 0
#define PKG2_SEC_INI1 1
#define PKG2_SEC_UNUSED 2
#define INI1_MAGIC 0x31494E49
//! TODO: Update on kernel change if needed.
// Offset of OP + 12 is the INI1 offset. On v2 with dynamic crt0 it's + 16.
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // MOV X21, #0.
#define PKG2_NEWKERN_START 0x800
#define ATM_MESOSPHERE 0x3053534D
extern u32 pkg2_newkern_ini1_info;
extern u32 pkg2_newkern_ini1_start;
extern u32 pkg2_newkern_ini1_end;
typedef struct _kernel_patch_t
{
u32 id;
u32 off;
u32 val;
const u32 *ptr;
} kernel_patch_t;
#define KERNEL_PATCHSET_DEF(name, ...) \
static const kernel_patch_t name[] = { \
__VA_ARGS__, \
{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32 *)0xFFFFFFFF} \
}
enum
{
// Always applied.
SVC_GENERIC = 0,
// Generic instruction patches.
SVC_VERIFY_DS = 0x10,
DEBUG_MODE_EN = 0x11,
ATM_GEN_PATCH = 0x12,
ATM_SYSM_INCR = ATM_GEN_PATCH,
// >4 bytes patches. Value is a pointer of a u32 array.
ATM_ARR_PATCH = 0x13,
};
typedef struct _pkg2_hdr_t
{
/* 0x000 */ u8 ctr[0x10];
/* 0x010 */ u8 sec_ctr[0x40];
/* 0x050 */ u32 magic;
/* 0x054 */ u32 base;
/* 0x058 */ u32 pad0;
/* 0x05C */ u8 pkg2_ver;
/* 0x05D */ u8 bl_ver;
/* 0x05E */ u16 pad1;
/* 0x060 */ u32 sec_size[4];
/* 0x070 */ u32 sec_off[4];
/* 0x080 */ u8 sec_sha256[0x80];
/* 0x100 */ u8 data[];
} pkg2_hdr_t;
typedef struct _pkg2_ini1_t
{
u32 magic;
u32 size;
u32 num_procs;
u32 pad;
} pkg2_ini1_t;
typedef struct _pkg2_kip1_sec_t
{
u32 offset;
u32 size_decomp;
u32 size_comp;
u32 attrib;
} pkg2_kip1_sec_t;
#define KIP1_NUM_SECTIONS 6
typedef struct _pkg2_kip1_t
{
/* 0x000 */ u32 magic;
/* 0x004 */ u8 name[12];
/* 0x010 */ u64 tid;
/* 0x018 */ u32 proc_cat;
/* 0x01C */ u8 main_thrd_prio;
/* 0x01D */ u8 def_cpu_core;
/* 0x01E */ u8 res;
/* 0x01F */ u8 flags;
/* 0x020 */ pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS];
/* 0x080 */ u32 caps[0x20];
/* 0x100 */ u8 data[];
} pkg2_kip1_t;
typedef struct _pkg2_kip1_info_t
{
pkg2_kip1_t *kip1;
u32 size;
link_t link;
} pkg2_kip1_info_t;
typedef struct _pkg2_kernel_id_t
{
u8 hash[8];
const kernel_patch_t *kernel_patchset;
} pkg2_kernel_id_t;
#define KIP1_PATCH_SRC_NO_CHECK (char *)(-1)
typedef struct _kip1_patch_t
{
u32 offset; // section+offset of patch to apply.
u32 length; // In bytes, 0 means last patch.
char *src_data; // That must match.
char *dst_data; // That it gets replaced by.
} kip1_patch_t;
typedef struct _kip1_patchset_t
{
char *name; // NULL means end.
const kip1_patch_t *patches; // NULL means not necessary.
} kip1_patchset_t;
typedef struct _kip1_id_t
{
const char *name;
u8 hash[8];
const kip1_patchset_t *patchset;
} kip1_id_t;
bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2);
int pkg2_has_kip(link_t *info, u64 tid);
void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1);
void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1);
void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1);
void pkg2_get_ids(kip1_id_t **ids, u32 *entries);
const char *pkg2_patch_kips(link_t *info, char *patch_names);
const pkg2_kernel_id_t *pkg2_identify(const u8 *hash);
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb, bool is_exo);
void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info, bool is_exo);
#endif