From 3630c2a099599009a63fb4f26d1b62b316e7fce4 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Fri, 24 Jan 2025 16:11:36 +0200 Subject: [PATCH] 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. --- bootloader/hos/pkg2.c | 32 ++++++++++++++++++++------------ bootloader/hos/pkg2.h | 38 +++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/bootloader/hos/pkg2.c b/bootloader/hos/pkg2.c index 5158f6e..2f2f6fc 100644 --- a/bootloader/hos/pkg2.c +++ b/bootloader/hos/pkg2.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2024 CTCaer + * 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, @@ -37,6 +37,7 @@ extern const u8 package2_keyseed[]; u32 pkg2_newkern_ini1_info; u32 pkg2_newkern_ini1_start; u32 pkg2_newkern_ini1_end; +u32 pkg2_newkern_ini1_rela; enum kip_offset_section { @@ -188,11 +189,12 @@ static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1) return size; } -void pkg2_get_newkern_info(u8 *kern_data) +static void _pkg2_get_newkern_info(u8 *kern_data) { - u32 crt_start = 0; + u32 crt_start = 0; pkg2_newkern_ini1_info = 0; pkg2_newkern_ini1_start = 0; + pkg2_newkern_ini1_rela = 0; u32 first_op = *(u32 *)kern_data; if ((first_op & 0xFE000000) == 0x14000000) @@ -229,6 +231,7 @@ void pkg2_get_newkern_info(u8 *kern_data) // On v2 kernel with dynamic crt, values are relative to value address. if (crt_start) { + pkg2_newkern_ini1_rela = pkg2_newkern_ini1_info; pkg2_newkern_ini1_start += pkg2_newkern_ini1_info; pkg2_newkern_ini1_end += pkg2_newkern_ini1_info + 0x8; } @@ -240,7 +243,7 @@ bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2) // Check for new pkg2 type. if (!pkg2->sec_size[PKG2_SEC_INI1]) { - pkg2_get_newkern_info(pkg2->data); + _pkg2_get_newkern_info(pkg2->data); if (!pkg2_newkern_ini1_start) return false; @@ -845,10 +848,15 @@ DPRINTF("%s @ %08X (%08X)\n", is_meso ? "Mesosphere": "kernel",(u32)ctxt->kernel // Set new INI1 offset to kernel. u32 meso_meta_offset = *(u32 *)(pdst + 8); - if (is_meso && (meso_magic & 0xF000000)) // MSS1. + if (is_meso && (meso_magic & 0x0F000000)) // MSS1. *(u32 *)(pdst + meso_meta_offset) = kernel_size - meso_meta_offset; else if (ini1_size) - *(u32 *)(pdst + (is_meso ? 8 : pkg2_newkern_ini1_info)) = kernel_size; + { + if (is_meso) // MSS0. + *(u32 *)(pdst + 8) = kernel_size; + else + *(u32 *)(pdst + pkg2_newkern_ini1_info) = kernel_size - pkg2_newkern_ini1_rela; + } kernel_size += ini1_size; } @@ -865,13 +873,13 @@ DPRINTF("INI1 encrypted\n"); if (!is_exo) // Not needed on Exosphere 1.0.0 and up. { - // Calculate SHA256 over encrypted Kernel and INI1. + // Calculate SHA256 over encrypted sections. Only 3 have valid hashes. u8 *pk2_hash_data = (u8 *)dst + 0x100 + sizeof(pkg2_hdr_t); - se_calc_sha256_oneshot(&hdr->sec_sha256[SE_SHA_256_SIZE * PKG2_SEC_KERNEL], - (void *)pk2_hash_data, hdr->sec_size[PKG2_SEC_KERNEL]); - pk2_hash_data += hdr->sec_size[PKG2_SEC_KERNEL]; - se_calc_sha256_oneshot(&hdr->sec_sha256[SE_SHA_256_SIZE * PKG2_SEC_INI1], - (void *)pk2_hash_data, hdr->sec_size[PKG2_SEC_INI1]); + for (u32 i = PKG2_SEC_KERNEL; i <= PKG2_SEC_UNUSED; i++) + { + se_calc_sha256_oneshot(&hdr->sec_sha256[SE_SHA_256_SIZE * i], (void *)pk2_hash_data, hdr->sec_size[i]); + pk2_hash_data += hdr->sec_size[i]; + } } // Encrypt header. diff --git a/bootloader/hos/pkg2.h b/bootloader/hos/pkg2.h index e99b20e..551e46e 100644 --- a/bootloader/hos/pkg2.h +++ b/bootloader/hos/pkg2.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2024 CTCaer + * 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, @@ -20,16 +20,17 @@ #include -#define PKG2_MAGIC 0x31324B50 -#define PKG2_SEC_BASE 0x80000000 +#define PKG2_MAGIC 0x31324B50 +#define PKG2_SEC_BASE 0x80000000 #define PKG2_SEC_KERNEL 0 -#define PKG2_SEC_INI1 1 +#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 +#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // MOV X21, #0. #define PKG2_NEWKERN_START 0x800 #define ATM_MESOSPHERE 0x3053534D @@ -67,18 +68,18 @@ enum typedef struct _pkg2_hdr_t { - u8 ctr[0x10]; - u8 sec_ctr[0x40]; - u32 magic; - u32 base; - u32 pad0; - u8 pkg2_ver; - u8 bl_ver; - u16 pad1; - u32 sec_size[4]; - u32 sec_off[4]; - u8 sec_sha256[0x80]; - u8 data[]; +/* 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 @@ -102,7 +103,7 @@ typedef struct _pkg2_kip1_sec_t typedef struct _pkg2_kip1_t { /* 0x000 */ u32 magic; -/* 0x004*/ u8 name[12]; +/* 0x004 */ u8 name[12]; /* 0x010 */ u64 tid; /* 0x018 */ u32 proc_cat; /* 0x01C */ u8 main_thrd_prio; @@ -150,7 +151,6 @@ typedef struct _kip1_id_t const kip1_patchset_t *patchset; } kip1_id_t; -void pkg2_get_newkern_info(u8 *kern_data); 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);