mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
Fusee: Change package2 loading logic (untested)
This commit is contained in:
parent
5088851de4
commit
1b07a07353
5 changed files with 109 additions and 59 deletions
|
@ -4,17 +4,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "masterkey.h"
|
||||||
/* TODO: Update to 0x6 on release of new master key. */
|
|
||||||
#define MASTERKEY_REVISION_MAX 0x5
|
|
||||||
|
|
||||||
#define MASTERKEY_REVISION_100_230 0x00
|
|
||||||
#define MASTERKEY_REVISION_300 0x01
|
|
||||||
#define MASTERKEY_REVISION_301_302 0x02
|
|
||||||
#define MASTERKEY_REVISION_400_410 0x03
|
|
||||||
#define MASTERKEY_REVISION_500_CURRENT 0x04
|
|
||||||
|
|
||||||
#define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410)
|
|
||||||
|
|
||||||
typedef enum BisPartition {
|
typedef enum BisPartition {
|
||||||
BisPartition_Calibration = 0,
|
BisPartition_Calibration = 0,
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#define MASTERKEY_REVISION_400_410 0x03
|
#define MASTERKEY_REVISION_400_410 0x03
|
||||||
#define MASTERKEY_REVISION_500_CURRENT 0x04
|
#define MASTERKEY_REVISION_500_CURRENT 0x04
|
||||||
|
|
||||||
|
#define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410)
|
||||||
|
|
||||||
/* This should be called during initialization. */
|
/* This should be called during initialization. */
|
||||||
void mkey_detect_revision(void);
|
void mkey_detect_revision(void);
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ static int exosphere_ini_handler(void *user, const char *section, const char *na
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nxboot_configure_exosphere(void) {
|
static void nxboot_configure_exosphere(void) {
|
||||||
exosphere_config_t exo_cfg = {0};
|
exosphere_config_t exo_cfg = {0};
|
||||||
|
|
||||||
exo_cfg.magic = MAGIC_EXOSPHERE_BOOTCONFIG;
|
exo_cfg.magic = MAGIC_EXOSPHERE_BOOTCONFIG;
|
||||||
|
@ -49,11 +49,30 @@ void nxboot_configure_exosphere(void) {
|
||||||
*(MAILBOX_EXOSPHERE_CONFIGURATION) = exo_cfg;
|
*(MAILBOX_EXOSPHERE_CONFIGURATION) = exo_cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nxboot_adjust_exosphere_target_firmware(const package2_header_t *package2) {
|
||||||
|
static const uint32_t mkey_ver_to_target_fw[] = {
|
||||||
|
EXOSPHERE_TARGET_FIRMWARE_100,
|
||||||
|
EXOSPHERE_TARGET_FIRMWARE_200,
|
||||||
|
EXOSPHERE_TARGET_FIRMWARE_300,
|
||||||
|
EXOSPHERE_TARGET_FIRMWARE_300,
|
||||||
|
EXOSPHERE_TARGET_FIRMWARE_400,
|
||||||
|
EXOSPHERE_TARGET_FIRMWARE_500,
|
||||||
|
};
|
||||||
|
uint8_t package2_header_version = package2_meta_get_header_version(&package2->metadata);
|
||||||
|
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == 0) {
|
||||||
|
if (package2_header_version >= 1 && package2_header_version <= sizeof(mkey_ver_to_target_fw)/4) {
|
||||||
|
MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware = mkey_ver_to_target_fw[package2_header_version];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* This is the main function responsible for booting Horizon. */
|
/* This is the main function responsible for booting Horizon. */
|
||||||
static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
|
static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
|
||||||
void nxboot_main(void) {
|
void nxboot_main(void) {
|
||||||
loader_ctx_t *loader_ctx = get_loader_ctx();
|
loader_ctx_t *loader_ctx = get_loader_ctx();
|
||||||
package2_header_t *package2 = NULL;
|
/* void *bootconfig; */
|
||||||
|
package2_header_t *package2;
|
||||||
|
size_t package2_size;
|
||||||
void *tsec_fw;
|
void *tsec_fw;
|
||||||
size_t tsec_fw_size;
|
size_t tsec_fw_size;
|
||||||
void *warmboot_fw;
|
void *warmboot_fw;
|
||||||
|
@ -62,11 +81,77 @@ void nxboot_main(void) {
|
||||||
size_t package1loader_size ;
|
size_t package1loader_size ;
|
||||||
package1_header_t *package1;
|
package1_header_t *package1;
|
||||||
size_t package1_size;
|
size_t package1_size;
|
||||||
uint32_t revision = EXOSPHERE_TARGET_FIRMWARE_MAX;
|
uint32_t available_revision;
|
||||||
FILE *boot0 = fopen("boot0:/", "rb");
|
FILE *boot0;
|
||||||
void *exosphere_memaddr;
|
void *exosphere_memaddr;
|
||||||
|
|
||||||
if (boot0 == NULL || package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &revision, boot0) == -1) {
|
/* TODO: How should we deal with bootconfig? */
|
||||||
|
package2 = memalign(4096, PACKAGE2_SIZE_MAX);
|
||||||
|
if (package2 == NULL) {
|
||||||
|
printf("Error: nxboot: out of memory!\n");
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read Package2 from a file, otherwise from its partition(s). */
|
||||||
|
if (loader_ctx->package2_path[0] != '\0') {
|
||||||
|
package2_size = get_file_size(loader_ctx->package2_path);
|
||||||
|
if (package2_size == 0) {
|
||||||
|
printf("Error: Could not read Package2 from %s!\n", loader_ctx->package2_path);
|
||||||
|
generic_panic();
|
||||||
|
} else if (package2_size > PACKAGE2_SIZE_MAX || package2_size <= sizeof(package2_header_t)) {
|
||||||
|
printf("Error: Package2 from %s is too big or too small!\n", loader_ctx->package2_path);
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_from_file(package2, package2_size, loader_ctx->package2_path) != package2_size) {
|
||||||
|
printf("Error: Could not read Package2 from %s!\n", loader_ctx->package2_path);
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (package2_meta_get_size(&package2->metadata) < package2_size) {
|
||||||
|
printf("Error: Package2 from %s is too small!\n", loader_ctx->package2_path);
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#ifdef I_KNOW_WHAT_IM_DOING_2
|
||||||
|
FILE *bcpkg21 = fopen("bcpkg21:/", "rb");
|
||||||
|
if (bcpkg21 == NULL || fseek(bcpkg21, 0x4000, SEEK_SET) != 0) {
|
||||||
|
printf("Error: Failed to read Package2 from NAND!\n");
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
if (fread(package2, sizeof(package2_header_t), 1, bcpkg21) < 1) {
|
||||||
|
printf("Error: Failed to read Package2 from NAND!\n");
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
package2_size = package2_meta_get_size(&package2->metadata);
|
||||||
|
if (package2_size > PACKAGE2_SIZE_MAX || package2_size <= sizeof(package2_header_t)) {
|
||||||
|
printf("Error: Package2 from NAND is too big or too small!\n");
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread(package2->data, package2_size - sizeof(package2_header_t), 1, bcpkg21) < 1) {
|
||||||
|
printf("Error: Failed to read Package2 from NAND!\n");
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
fclose(bcpkg21);
|
||||||
|
#else
|
||||||
|
printf("Error: Package2 must be loaded from the SD card, unless you know what you are doing!\n");
|
||||||
|
generic_panic();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup boot configuration for Exosphère. */
|
||||||
|
nxboot_configure_exosphere();
|
||||||
|
nxboot_adjust_exosphere_target_firmware(package2);
|
||||||
|
|
||||||
|
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == 0) {
|
||||||
|
printf("Error: Failed to determine which target firmware too use!\n");
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
boot0 = fopen("boot0:/", "rb");
|
||||||
|
if (boot0 == NULL || package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1) {
|
||||||
printf("Error: Couldn't parse boot0: %s!\n", strerror(errno));
|
printf("Error: Couldn't parse boot0: %s!\n", strerror(errno));
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
@ -104,11 +189,8 @@ void nxboot_main(void) {
|
||||||
|
|
||||||
/* TODO: Initialize Boot Reason. */
|
/* TODO: Initialize Boot Reason. */
|
||||||
|
|
||||||
/* Setup boot configuration for Exosphere. */
|
|
||||||
nxboot_configure_exosphere();
|
|
||||||
|
|
||||||
/* Derive keydata. */
|
/* Derive keydata. */
|
||||||
if (derive_nx_keydata(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, g_keyblobs, revision, tsec_fw, tsec_fw_size) != 0) {
|
if (derive_nx_keydata(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, g_keyblobs, available_revision, tsec_fw, tsec_fw_size) != 0) {
|
||||||
printf("Error: Key derivation failed!\n");
|
printf("Error: Key derivation failed!\n");
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
@ -147,41 +229,6 @@ void nxboot_main(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: How should we deal with bootconfig? */
|
|
||||||
package2 = memalign(4096, PACKAGE2_SIZE_MAX);
|
|
||||||
if (package2 == NULL) {
|
|
||||||
printf("Error: nxboot: out of memory!\n");
|
|
||||||
generic_panic();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read Package2 from a file, otherwise from its partition(s). */
|
|
||||||
if (loader_ctx->package2_path[0] != '\0') {
|
|
||||||
size_t package2_size = get_file_size(loader_ctx->package2_path);
|
|
||||||
if (package2_size == 0) {
|
|
||||||
printf("Error: Could not read Package2 from %s!\n", loader_ctx->package2_path);
|
|
||||||
generic_panic();
|
|
||||||
} else if (package2_size > PACKAGE2_SIZE_MAX) {
|
|
||||||
printf("Error: Package2 from %s is too big!\n", loader_ctx->package2_path);
|
|
||||||
generic_panic();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read_from_file(package2, package2_size, loader_ctx->package2_path) != package2_size) {
|
|
||||||
printf("Error: Could not read Package2 from %s!\n", loader_ctx->package2_path);
|
|
||||||
generic_panic();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
FILE *bcpkg21 = fopen("bcpkg21:/", "rb");
|
|
||||||
if (bcpkg21 == NULL) {
|
|
||||||
printf("Error: Failed to read Package2 from NAND!\n");
|
|
||||||
generic_panic();
|
|
||||||
}
|
|
||||||
if (fseek(bcpkg21, 0x4000, SEEK_SET) != 0 || fread(package2, 1, PACKAGE2_SIZE_MAX, bcpkg21) < sizeof(package2_header_t)) {
|
|
||||||
printf("Error: Failed to read Package2 from NAND!\n");
|
|
||||||
generic_panic();
|
|
||||||
}
|
|
||||||
fclose(bcpkg21);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Patch package2, adding Thermosphère + custom KIPs. */
|
/* Patch package2, adding Thermosphère + custom KIPs. */
|
||||||
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware);
|
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware);
|
||||||
|
|
||||||
|
|
|
@ -93,11 +93,11 @@ static bool package2_validate_metadata(package2_meta_t *metadata) {
|
||||||
|
|
||||||
/* Package2 size, version number is stored XORed in header CTR. */
|
/* Package2 size, version number is stored XORed in header CTR. */
|
||||||
/* Nintendo, what the fuck? */
|
/* Nintendo, what the fuck? */
|
||||||
uint32_t package_size = metadata->ctr_dwords[0] ^ metadata->ctr_dwords[2] ^ metadata->ctr_dwords[3];
|
uint32_t package_size = package2_meta_get_size(metadata);
|
||||||
uint8_t header_version = (uint8_t)((metadata->ctr_dwords[1] ^ (metadata->ctr_dwords[1] >> 16) ^ (metadata->ctr_dwords[1] >> 24)) & 0xFF);
|
uint8_t header_version = package2_meta_get_header_version(metadata);
|
||||||
|
|
||||||
/* Ensure package isn't too big or too small. */
|
/* Ensure package isn't too big or too small. */
|
||||||
if (package_size <= sizeof(package2_header_t) || package_size > PACKAGE2_SIZE_MAX - sizeof(package2_header_t)) {
|
if (package_size <= sizeof(package2_header_t) || package_size > PACKAGE2_SIZE_MAX) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,19 @@ typedef struct {
|
||||||
package2_meta_t metadata;
|
package2_meta_t metadata;
|
||||||
uint8_t encrypted_header[0x100];
|
uint8_t encrypted_header[0x100];
|
||||||
};
|
};
|
||||||
|
uint8_t data[];
|
||||||
} package2_header_t;
|
} package2_header_t;
|
||||||
|
|
||||||
|
/* Package2 can be encrypted or unencrypted for these functions: */
|
||||||
|
|
||||||
|
static inline size_t package2_meta_get_size(const package2_meta_t *metadata) {
|
||||||
|
return metadata->ctr_dwords[0] ^ metadata->ctr_dwords[2] ^ metadata->ctr_dwords[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t package2_meta_get_header_version(const package2_meta_t *metadata) {
|
||||||
|
return (uint8_t)((metadata->ctr_dwords[1] ^ (metadata->ctr_dwords[1] >> 16) ^ (metadata->ctr_dwords[1] >> 24)) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firmware);
|
void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firmware);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue