diff --git a/fusee/fusee-secondary/src/fs_utils.c b/fusee/fusee-secondary/src/fs_utils.c index f3f7042b5..1ea1193bb 100644 --- a/fusee/fusee-secondary/src/fs_utils.c +++ b/fusee/fusee-secondary/src/fs_utils.c @@ -1,8 +1,18 @@ #include +#include #include "fs_utils.h" #include "hwinit.h" #include "sdmmc.h" +size_t get_file_size(const char *filename) { + struct stat st; + if (stat(filename, &st) == -1) { + return 0; + } + + return (size_t)st.st_size; +} + size_t read_from_file(void *dst, size_t dst_size, const char *filename) { FILE *file = fopen(filename, "rb"); if (file == NULL) { diff --git a/fusee/fusee-secondary/src/fs_utils.h b/fusee/fusee-secondary/src/fs_utils.h index 9574370e1..6a100fb9d 100644 --- a/fusee/fusee-secondary/src/fs_utils.h +++ b/fusee/fusee-secondary/src/fs_utils.h @@ -4,6 +4,7 @@ #include "utils.h" #include "sdmmc.h" +size_t get_file_size(const char *filename); size_t read_from_file(void *dst, size_t dst_size, const char *filename); size_t dump_to_file(const void *src, size_t src_size, const char *filename); diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index b99a17068..4d7747d32 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -34,9 +34,7 @@ static const uint8_t masterkey_4x_seed[0x10] = { }; static int get_tsec_key(void *dst, const void *tsec_fw, size_t tsec_fw_size, uint32_t revision) { - static uint8_t __attribute__((aligned(256))) tsec_dma_buf[0xF00]; - memcpy(tsec_dma_buf, tsec_fw, tsec_fw_size); - return tsec_query((u32)tsec_dma_buf, dst, revision); + return tsec_query((u32)tsec_fw, dst, revision); } static int get_keyblob(nx_keyblob_t *dst, uint32_t revision, const nx_keyblob_t *keyblobs, uint32_t available_revision) { diff --git a/fusee/fusee-secondary/src/key_derivation.h b/fusee/fusee-secondary/src/key_derivation.h index 7df20b2fa..1ef185417 100644 --- a/fusee/fusee-secondary/src/key_derivation.h +++ b/fusee/fusee-secondary/src/key_derivation.h @@ -31,6 +31,7 @@ typedef struct nx_keyblob_t { }; } nx_keyblob_t; +/* TSEC fw must be 0x100-byte-aligned. */ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_fw, size_t tsec_fw_size); void finalize_nx_keydata(uint32_t target_firmware); diff --git a/fusee/fusee-secondary/src/loader.c b/fusee/fusee-secondary/src/loader.c index d308acfde..e942986d6 100644 --- a/fusee/fusee-secondary/src/loader.c +++ b/fusee/fusee-secondary/src/loader.c @@ -42,13 +42,7 @@ static int loadlist_entry_ini_handler(void *user, const char *section, const cha return 1; } -bool validate_load_address(uintptr_t load_addr) { - /* TODO: Actually validate addresses. */ - (void)(load_addr); - return true; -} - -void load_list_entry(const char *key) { +static void load_list_entry(const char *key) { load_file_t load_file_ctx = {0}; struct stat st; size_t size; @@ -62,7 +56,12 @@ void load_list_entry(const char *key) { } if (load_file_ctx.load_address == 0 || load_file_ctx.path[0] == '\x00') { - printf("Error: Failed to determine where to load %s!\n", key); + printf("Error: Failed to determine where to load %s from!\n", key); + generic_panic(); + } + + if (strlen(load_file_ctx.path) > LOADER_MAX_PATH_SIZE) { + printf("Error: The filename for %s is too long!\n", key); generic_panic(); } @@ -87,26 +86,16 @@ void load_list_entry(const char *key) { entry->load_address = load_file_ctx.load_address; entry->size = size; entry->num = entry_num; - strcpy(get_loader_ctx()->file_paths[entry_num], load_file_ctx.path); - get_loader_ctx()->nb_files++; + get_loader_ctx()->nb_files_to_load++; - /* Check for special keys. */ - if (strcmp(key, LOADER_PACKAGE2_KEY) == 0) { - get_loader_ctx()->package2_loadfile = load_file_ctx; - } else if (strcmp(key, LOADER_EXOSPHERE_KEY) == 0) { - get_loader_ctx()->exosphere_loadfile = load_file_ctx; - } else if (strcmp(key, LOADER_TSECFW_KEY) == 0) { - get_loader_ctx()->tsecfw_loadfile = load_file_ctx; - } else if (strcmp(key, LOADER_WARMBOOT_KEY) == 0) { - get_loader_ctx()->warmboot_loadfile = load_file_ctx; - } + strcpy(get_loader_ctx()->file_paths_to_load[entry_num], load_file_ctx.path); } -void parse_loadlist(const char *ll) { +static void parse_loadlist(const char *ll) { printf("Parsing load list: %s\n", ll); char load_list[0x200] = {0}; - strncpy(load_list, ll, 0x200); + strncpy(load_list, ll, 0x200 - 1); char *entry, *p; @@ -153,7 +142,20 @@ static int loadlist_ini_handler(void *user, const char *section, const char *nam sscanf(value, "%x", &x); loader_ctx->chainload_entrypoint = x; } else if (strcmp(name, LOADER_CUSTOMSPLASH_KEY) == 0) { - strncpy(loader_ctx->custom_splash_path, value, sizeof(loader_ctx->custom_splash_path)); + strncpy(loader_ctx->custom_splash_path, value, LOADER_MAX_PATH_SIZE); + loader_ctx->custom_splash_path[LOADER_MAX_PATH_SIZE] = '\0'; + } else if (strcmp(name, LOADER_PACKAGE2_KEY) == 0) { + strncpy(loader_ctx->package2_path, value, LOADER_MAX_PATH_SIZE); + loader_ctx->package2_path[LOADER_MAX_PATH_SIZE] = '\0'; + } else if (strcmp(name, LOADER_EXOSPHERE_KEY) == 0) { + strncpy(loader_ctx->exosphere_path, value, LOADER_MAX_PATH_SIZE); + loader_ctx->exosphere_path[LOADER_MAX_PATH_SIZE] = '\0'; + } else if (strcmp(name, LOADER_TSECFW_KEY) == 0) { + strncpy(loader_ctx->tsecfw_path, value, LOADER_MAX_PATH_SIZE); + loader_ctx->tsecfw_path[LOADER_MAX_PATH_SIZE] = '\0'; + } else if (strcmp(name, LOADER_WARMBOOT_KEY) == 0) { + strncpy(loader_ctx->warmboot_path, value, LOADER_MAX_PATH_SIZE); + loader_ctx->warmboot_path[LOADER_MAX_PATH_SIZE] = '\0'; } else { return 0; } @@ -209,7 +211,6 @@ void load_payload(const char *bct0) { nonallocatable_entries[5].size = __end__ - __start__; } - /* Set BCT0 global. */ ctx->bct0 = bct0; @@ -218,13 +219,18 @@ void load_payload(const char *bct0) { generic_panic(); } + if (ctx->chainload_entrypoint == 0 || ctx->nb_files_to_load > 0) { + printf("Error: loadlist must be empty when booting Horizon!\n"); + generic_panic(); + } + /* Sort the entries by ascending load addresses */ qsort(g_chainloader_entries, g_chainloader_num_entries, sizeof(chainloader_entry_t), chainloader_entry_comparator); /* Check for possible overlap and find the entrypoint, also determine whether we can load in-place */ - ctx->file_id_of_entrypoint = ctx->nb_files; - for (size_t i = 0; i < ctx->nb_files; i++) { - if (i != ctx->nb_files - 1 && + ctx->file_id_of_entrypoint = ctx->nb_files_to_load; + for (size_t i = 0; i < ctx->nb_files_to_load; i++) { + if (i != ctx->nb_files_to_load - 1 && overlaps( g_chainloader_entries[i].load_address, g_chainloader_entries[i].load_address + g_chainloader_entries[i].size, @@ -234,8 +240,8 @@ void load_payload(const char *bct0) { ) { printf( "Error: Loading ranges for files %s and %s overlap!\n", - ctx->file_paths[g_chainloader_entries[i].num], - ctx->file_paths[g_chainloader_entries[i + 1].num] + ctx->file_paths_to_load[g_chainloader_entries[i].num], + ctx->file_paths_to_load[g_chainloader_entries[i + 1].num] ); generic_panic(); } @@ -252,22 +258,17 @@ void load_payload(const char *bct0) { ); } - if (ctx->chainload_entrypoint != 0 && ctx->file_id_of_entrypoint >= ctx->nb_files) { + if (ctx->chainload_entrypoint != 0 && ctx->file_id_of_entrypoint >= ctx->nb_files_to_load) { printf("Error: Entrypoint not in range of any of the files!\n"); generic_panic(); } - if (ctx->chainload_entrypoint == 0 && !can_load_in_place) { - printf("Error: Files have to be loaded in place when booting Horizon!\n"); - generic_panic(); - } - if (can_load_in_place) { - for (size_t i = 0; i < ctx->nb_files; i++) { + for (size_t i = 0; i < ctx->nb_files_to_load; i++) { chainloader_entry_t *entry = &g_chainloader_entries[i]; entry->src_address = entry->load_address; - if (read_from_file((void *)entry->src_address, entry->size, ctx->file_paths[entry->num]) != entry->size) { - printf("Error: Failed to read file %s: %s!\n", ctx->file_paths[entry->num], strerror(errno)); + if (read_from_file((void *)entry->src_address, entry->size, ctx->file_paths_to_load[entry->num]) != entry->size) { + printf("Error: Failed to read file %s: %s!\n", ctx->file_paths_to_load[entry->num], strerror(errno)); generic_panic(); } } @@ -275,7 +276,7 @@ void load_payload(const char *bct0) { size_t total_size = 0; uintptr_t carveout, min_addr, max_addr, pos; - for (size_t i = 0; i < ctx->nb_files; i++) { + for (size_t i = 0; i < ctx->nb_files_to_load; i++) { total_size += g_chainloader_entries[i].size; } @@ -300,11 +301,11 @@ void load_payload(const char *bct0) { /* Finally, read the files into the carveout */ pos = carveout; - for (size_t i = 0; i < ctx->nb_files; i++) { + for (size_t i = 0; i < ctx->nb_files_to_load; i++) { chainloader_entry_t *entry = &g_chainloader_entries[i]; entry->src_address = pos; - if (read_from_file((void *)entry->src_address, entry->size, ctx->file_paths[entry->num]) != entry->size) { - printf("Error: Failed to read file %s: %s!\n", ctx->file_paths[entry->num], strerror(errno)); + if (read_from_file((void *)entry->src_address, entry->size, ctx->file_paths_to_load[entry->num]) != entry->size) { + printf("Error: Failed to read file %s: %s!\n", ctx->file_paths_to_load[entry->num], strerror(errno)); generic_panic(); } pos += entry->size; diff --git a/fusee/fusee-secondary/src/loader.h b/fusee/fusee-secondary/src/loader.h index b332ba159..b3156736e 100644 --- a/fusee/fusee-secondary/src/loader.h +++ b/fusee/fusee-secondary/src/loader.h @@ -4,6 +4,8 @@ #include "utils.h" #include "chainloader.h" +#define LOADER_MAX_PATH_SIZE 255 + typedef struct { char path[0x100]; const char *key; @@ -15,13 +17,13 @@ typedef struct { const char *bct0; uintptr_t chainload_entrypoint; size_t file_id_of_entrypoint; - size_t nb_files; - load_file_t package2_loadfile; - load_file_t exosphere_loadfile; - load_file_t tsecfw_loadfile; - load_file_t warmboot_loadfile; - char custom_splash_path[0x100]; - char file_paths[CHAINLOADER_MAX_ENTRIES][0x100]; + size_t nb_files_to_load; + char package2_path[LOADER_MAX_PATH_SIZE+1]; + char exosphere_path[LOADER_MAX_PATH_SIZE+1]; + char tsecfw_path[LOADER_MAX_PATH_SIZE+1]; + char warmboot_path[LOADER_MAX_PATH_SIZE+1]; + char custom_splash_path[LOADER_MAX_PATH_SIZE+1]; + char file_paths_to_load[CHAINLOADER_MAX_ENTRIES][LOADER_MAX_PATH_SIZE+1]; } loader_ctx_t; #define LOADER_ENTRYPOINT_KEY "entrypoint" diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index 48a1b68dc..afeab6b51 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -82,7 +82,7 @@ int main(int argc, void **argv) { nxboot_main(); } else { /* TODO: What else do we want to do in terms of argc/argv? */ - const char *path = get_loader_ctx()->file_paths[get_loader_ctx()->file_id_of_entrypoint]; + const char *path = get_loader_ctx()->file_paths_to_load[get_loader_ctx()->file_id_of_entrypoint]; printf("Now chainloading.\n"); g_chainloader_argc = 1; strcpy(g_chainloader_arg_data, path); diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index e1d96ac21..d955dfce7 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -4,6 +4,7 @@ #include #include #include "utils.h" +#include "fs_utils.h" #include "nxboot.h" #include "key_derivation.h" #include "package1.h" @@ -52,18 +53,18 @@ void nxboot_configure_exosphere(void) { static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32]; void nxboot_main(void) { loader_ctx_t *loader_ctx = get_loader_ctx(); - package2_header_t *package2_src = (package2_header_t *)loader_ctx->package2_loadfile.load_address; package2_header_t *package2 = NULL; - void *tsec_fw = (void *)loader_ctx->tsecfw_loadfile.load_address; - size_t tsec_fw_size = loader_ctx->tsecfw_loadfile.load_size; - void *warmboot_fw = (void *)loader_ctx->warmboot_loadfile.load_address; - size_t warmboot_fw_size = loader_ctx->warmboot_loadfile.load_size; - void *package1loader = NULL; - size_t package1loader_size = 0; - package1_header_t *package1 = NULL; - size_t package1_size = 0; + void *tsec_fw; + size_t tsec_fw_size; + void *warmboot_fw; + size_t warmboot_fw_size; + void *package1loader; + size_t package1loader_size ; + package1_header_t *package1; + size_t package1_size; uint32_t revision = EXOSPHERE_TARGET_FIRMWARE_MAX; FILE *boot0 = fopen("boot0:/", "rb"); + void *exosphere_memaddr; if (boot0 == NULL || package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &revision, boot0) == -1) { printf("Error: Couldn't parse boot0: %s!\n", strerror(errno)); @@ -71,7 +72,27 @@ void nxboot_main(void) { } fclose(boot0); - if (tsec_fw == NULL) { + /* Read the TSEC firmware from a file, otherwise from PK1L. */ + if (loader_ctx->tsecfw_path[0] != '\0') { + tsec_fw_size = get_file_size(loader_ctx->tsecfw_path); + if (tsec_fw_size != 0 && tsec_fw_size != 0xF00) { + printf("Error: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path); + generic_panic(); + } else if (tsec_fw_size == 0) { + printf("Error: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); + generic_panic(); + } + + tsec_fw = memalign(0x100, tsec_fw_size); + if (tsec_fw == NULL) { + printf("Error: nxboot_main: out of memory!\n"); + generic_panic(); + } + if (read_from_file(tsec_fw, tsec_fw_size, loader_ctx->tsecfw_path) != tsec_fw_size) { + printf("Error: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); + generic_panic(); + } + } else { tsec_fw_size = package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size); if (tsec_fw_size == 0) { printf("Error: Failed to read the TSEC firmware from Package1loader!\n"); @@ -92,7 +113,24 @@ void nxboot_main(void) { generic_panic(); } - if (warmboot_fw == NULL) { + /* Read the warmboot firmware from a file, otherwise from PK1. */ + if (loader_ctx->warmboot_path[0] != '\0') { + warmboot_fw_size = get_file_size(loader_ctx->warmboot_path); + if (warmboot_fw_size == 0) { + printf("Error: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); + generic_panic(); + } + + warmboot_fw = malloc(warmboot_fw_size); + if (warmboot_fw == NULL) { + printf("Error: nxboot_main: out of memory!\n"); + generic_panic(); + } + if (read_from_file(warmboot_fw, warmboot_fw_size, loader_ctx->warmboot_path) != warmboot_fw_size) { + printf("Error: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); + generic_panic(); + } + } else { uint8_t ctr[16]; package1_size = package1_get_encrypted_package1(&package1, ctr, package1loader, package1loader_size); if(package1_decrypt(package1, package1_size, ctr)) { @@ -104,21 +142,34 @@ void nxboot_main(void) { } if (warmboot_fw_size == 0) { - printf("Error: Failed to read the warmboot firmware from Package1!\n"); + printf("Error: Could not read the warmboot firmware from Package1!\n"); generic_panic(); } } - free(package1loader); - - package2 = memalign(16, PACKAGE2_SIZE_MAX); + /* 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(); } - if (package2_src == NULL) { - /* TODO: How should we deal with bootconfig? */ + /* Read the warmboot firmware from a file, otherwise from PK1. */ + 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"); @@ -126,27 +177,50 @@ void nxboot_main(void) { } 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"); - fclose(bcpkg21); generic_panic(); } fclose(bcpkg21); - } else { - memcpy(package2, package2_src, loader_ctx->package2_loadfile.load_size); } - /* Patch package2, adding thermosphere + custom KIPs. */ + /* Patch package2, adding Thermosphère + custom KIPs. */ package2_rebuild_and_copy(package2); - free(package2); + /* Copy Exophère to a good location (or read it directly to it.) */ + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware <= EXOSPHERE_TARGET_FIRMWARE_400) { + exosphere_memaddr = (void *)0x40020000; + } else { + exosphere_memaddr = (void *)0x40018000; /* 5.x has its secmon's crt0 around this region. */ + } - /* Boot up Exosphere. */ + if (loader_ctx->exosphere_path[0] != '\0') { + size_t exosphere_size = get_file_size(loader_ctx->exosphere_path); + if (exosphere_size == 0) { + printf(u8"Error: Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); + generic_panic(); + } else if (exosphere_size > 0x10000) { + /* The maximum is actually a bit less than that. */ + printf(u8"Error: Exosphère from %s is too big!\n", loader_ctx->exosphere_path); + generic_panic(); + } + + if (read_from_file(exosphere_memaddr, exosphere_size, loader_ctx->exosphere_path) != exosphere_size) { + printf(u8"Error: Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); + generic_panic(); + } + } else { + /*extern const uint8_t exosphere_bin[]; + extern const uint32_t exosphere_bin_size; + memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size);*/ + } + + /* Boot up Exosphère. */ MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0; if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware <= EXOSPHERE_TARGET_FIRMWARE_400) { MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2; } else { MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X; } - cluster_enable_cpu0(loader_ctx->exosphere_loadfile.load_address, 1); + cluster_enable_cpu0((uint64_t)(uintptr_t)exosphere_memaddr, 1); while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) { /* Wait for Exosphere to wake up. */ } @@ -156,6 +230,16 @@ void nxboot_main(void) { MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X; } + /* Clean up. */ + free(package1loader); + if (loader_ctx->tsecfw_path[0] != '\0') { + free(tsec_fw); + } + if (loader_ctx->warmboot_path[0] != '\0') { + free(warmboot_fw); + } + free(package2); + /* Display splash screen. */ display_splash_screen_bmp(loader_ctx->custom_splash_path); diff --git a/fusee/fusee-secondary/src/nxboot.h b/fusee/fusee-secondary/src/nxboot.h index aefa651f9..32710d7eb 100644 --- a/fusee/fusee-secondary/src/nxboot.h +++ b/fusee/fusee-secondary/src/nxboot.h @@ -5,7 +5,7 @@ #define MAILBOX_NX_BOOTLOADER_BASE ((void *)(0x40002000)) -#define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEF8ull) +#define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEF8) #define NX_BOOTLOADER_STATE_INIT 0 #define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1 @@ -18,10 +18,10 @@ #define NX_BOOTLOADER_STATE_FINISHED_4X 4 /* Physaddr 0x40002EFC */ -#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFCULL) +#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFC) -#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10ULL) +#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10) void nxboot_main(void); -#endif \ No newline at end of file +#endif diff --git a/fusee/fusee-secondary/src/package1.c b/fusee/fusee-secondary/src/package1.c index a874dbee4..347bf2333 100644 --- a/fusee/fusee-secondary/src/package1.c +++ b/fusee/fusee-secondary/src/package1.c @@ -33,7 +33,7 @@ int package1_read_and_parse_boot0(void **package1loader, size_t *package1loader_ pk1_offset = 0x4000 * pk1_info->start_blk + 0x200 * pk1_info->start_page; - (*package1loader) = memalign(16, *package1loader_size); + (*package1loader) = memalign(0x10000, *package1loader_size); if (*package1loader == NULL) { errno = ENOMEM;