diff --git a/src/boot/boot.c b/src/boot/boot.c index 0ad9b4a0..22016ba8 100644 --- a/src/boot/boot.c +++ b/src/boot/boot.c @@ -1,161 +1,162 @@ -#include - -#include "boot.h" -#include "boot_io.h" -#include "crc32.h" - - -extern uint32_t ipl2 __attribute__((section(".data"))); - - -typedef struct { - const uint32_t crc32; - const uint8_t seed; -} ipl3_crc32_t; - -static const ipl3_crc32_t ipl3_crc32[] = { - { .crc32 = 0x587BD543, .seed = 0xAC }, // 5101 - { .crc32 = 0x6170A4A1, .seed = 0x3F }, // 6101 - { .crc32 = 0x009E9EA3, .seed = 0x3F }, // 7102 - { .crc32 = 0x90BB6CB5, .seed = 0x3F }, // 6102/7101 - { .crc32 = 0x0B050EE0, .seed = 0x78 }, // x103 - { .crc32 = 0x98BC2C86, .seed = 0x91 }, // x105 - { .crc32 = 0xACC8580A, .seed = 0x85 }, // x106 - { .crc32 = 0x0E018159, .seed = 0xDD }, // 5167 - { .crc32 = 0x10C68B18, .seed = 0xDD }, // NDXJ0 - { .crc32 = 0xBC605D0A, .seed = 0xDD }, // NDDJ0 - { .crc32 = 0x502C4466, .seed = 0xDD }, // NDDJ1 - { .crc32 = 0x0C965795, .seed = 0xDD }, // NDDJ2 - { .crc32 = 0x8FEBA21E, .seed = 0xDE }, // NDDE0 -}; - - -static io32_t *boot_get_device_base (boot_params_t *params) { - io32_t *device_base_address = ROM_CART; - if (params->device_type == BOOT_DEVICE_TYPE_DD) { - device_base_address = ROM_DDIPL; - } - return device_base_address; -} - -static bool boot_detect_cic_seed (boot_params_t *params) { - io32_t *base = boot_get_device_base(params); - - uint32_t ipl3[1008] __attribute__((aligned(8))); - - data_cache_hit_writeback_invalidate(ipl3, sizeof(ipl3)); - dma_read_raw_async(ipl3, (uint32_t) (&base[16]), sizeof(ipl3)); - dma_wait(); - - uint32_t crc32 = crc32_calculate(ipl3, sizeof(ipl3)); - - for (int i = 0; i < sizeof(ipl3_crc32) / sizeof(ipl3_crc32_t); i++) { - if (ipl3_crc32[i].crc32 == crc32) { - params->cic_seed = ipl3_crc32[i].seed; - return true; - } - } - - return false; -} - - -bool boot_is_warm (void) { - return (OS_INFO->reset_type == OS_INFO_RESET_TYPE_NMI); -} - -void boot (boot_params_t *params) { - if (params->tv_type == BOOT_TV_TYPE_PASSTHROUGH) { - params->tv_type = OS_INFO->tv_type; - } - - if (params->detect_cic_seed) { - if (!boot_detect_cic_seed(params)) { - params->cic_seed = 0x3F; - } - } - - // asm volatile ( - // "li $t1, %[status] \n" - // "mtc0 $t1, $12 \n" :: - // [status] "i" (C0_SR_CU1 | C0_SR_CU0 | C0_SR_FR) - // ); - - OS_INFO->mem_size_6105 = OS_INFO->mem_size; - - while (!(cpu_io_read(&SP->SR) & SP_SR_HALT)); - - cpu_io_write(&SP->SR, SP_SR_CLR_INTR | SP_SR_SET_HALT); - - while (cpu_io_read(&SP->DMA_BUSY)); - - cpu_io_write(&PI->SR, PI_SR_CLR_INTR | PI_SR_RESET); - cpu_io_write(&VI->V_INTR, 0x3FF); - cpu_io_write(&VI->H_LIMITS, 0); - cpu_io_write(&VI->CURR_LINE, 0); - cpu_io_write(&AI->MADDR, 0); - cpu_io_write(&AI->LEN, 0); - - while (cpu_io_read(&SP->SR) & SP_SR_DMA_BUSY); - - uint32_t *ipl2_src = &ipl2; - io32_t *ipl2_dst = SP_MEM->IMEM; - - for (int i = 0; i < 8; i++) { - cpu_io_write(&ipl2_dst[i], ipl2_src[i]); - } - - cpu_io_write(&PI->DOM[0].LAT, 0xFF); - cpu_io_write(&PI->DOM[0].PWD, 0xFF); - cpu_io_write(&PI->DOM[0].PGS, 0x0F); - cpu_io_write(&PI->DOM[0].RLS, 0x03); - - io32_t *base = boot_get_device_base(params); - uint32_t pi_config = io_read((uint32_t) (base)); - - cpu_io_write(&PI->DOM[0].LAT, pi_config & 0xFF); - cpu_io_write(&PI->DOM[0].PWD, pi_config >> 8); - cpu_io_write(&PI->DOM[0].PGS, pi_config >> 16); - cpu_io_write(&PI->DOM[0].RLS, pi_config >> 20); - - if (cpu_io_read(&DPC->SR) & DPC_SR_XBUS_DMEM_DMA) { - while (cpu_io_read(&DPC->SR) & DPC_SR_PIPE_BUSY); - } - - io32_t *ipl3_src = base; - io32_t *ipl3_dst = SP_MEM->DMEM; - - for (int i = 16; i < 1024; i++) { - cpu_io_write(&ipl3_dst[i], io_read((uint32_t) (&ipl3_src[i]))); - } - - register void (*entry_point)(void) asm ("t3"); - register uint32_t boot_device asm ("s3"); - register uint32_t tv_type asm ("s4"); - register uint32_t reset_type asm ("s5"); - register uint32_t cic_seed asm ("s6"); - register uint32_t version asm ("s7"); - void *stack_pointer; - - entry_point = (void (*)(void)) UNCACHED(&SP_MEM->DMEM[16]); - boot_device = (params->device_type & 0x01); - tv_type = (params->tv_type & 0x03); - reset_type = (params->reset_type & 0x01); - cic_seed = (params->cic_seed & 0xFF); - version = (params->tv_type == BOOT_TV_TYPE_PAL) ? 6 : 1; - stack_pointer = (void *) UNCACHED(&SP_MEM->IMEM[1020]); - - asm volatile ( - "move $sp, %[stack_pointer] \n" - "jr %[entry_point] \n" :: - [entry_point] "r" (entry_point), - [boot_device] "r" (boot_device), - [tv_type] "r" (tv_type), - [reset_type] "r" (reset_type), - [cic_seed] "r" (cic_seed), - [version] "r" (version), - [stack_pointer] "r" (stack_pointer) - ); - - while (1); -} +#include + +#include "boot.h" +#include "boot_io.h" +#include "crc32.h" + + +#define C0_STATUS_FR (1 << 26) +#define C0_STATUS_CU0 (1 << 28) +#define C0_STATUS_CU1 (1 << 29) + + +extern uint32_t ipl2 __attribute__((section(".data"))); + + +typedef struct { + const uint32_t crc32; + const uint8_t seed; +} ipl3_crc32_t; + +static const ipl3_crc32_t ipl3_crc32[] = { + { .crc32 = 0x587BD543, .seed = 0xAC }, // 5101 + { .crc32 = 0x6170A4A1, .seed = 0x3F }, // 6101 + { .crc32 = 0x009E9EA3, .seed = 0x3F }, // 7102 + { .crc32 = 0x90BB6CB5, .seed = 0x3F }, // 6102/7101 + { .crc32 = 0x0B050EE0, .seed = 0x78 }, // x103 + { .crc32 = 0x98BC2C86, .seed = 0x91 }, // x105 + { .crc32 = 0xACC8580A, .seed = 0x85 }, // x106 + { .crc32 = 0x0E018159, .seed = 0xDD }, // 5167 + { .crc32 = 0x10C68B18, .seed = 0xDD }, // NDXJ0 + { .crc32 = 0xBC605D0A, .seed = 0xDD }, // NDDJ0 + { .crc32 = 0x502C4466, .seed = 0xDD }, // NDDJ1 + { .crc32 = 0x0C965795, .seed = 0xDD }, // NDDJ2 + { .crc32 = 0x8FEBA21E, .seed = 0xDE }, // NDDE0 +}; + + +static io32_t *boot_get_device_base (boot_params_t *params) { + io32_t *device_base_address = ROM_CART; + if (params->device_type == BOOT_DEVICE_TYPE_DD) { + device_base_address = ROM_DDIPL; + } + return device_base_address; +} + +static bool boot_detect_cic_seed (boot_params_t *params) { + io32_t *base = boot_get_device_base(params); + + uint32_t ipl3[1008] __attribute__((aligned(8))); + + data_cache_hit_writeback_invalidate(ipl3, sizeof(ipl3)); + dma_read_raw_async(ipl3, (uint32_t) (&base[16]), sizeof(ipl3)); + dma_wait(); + + uint32_t crc32 = crc32_calculate(ipl3, sizeof(ipl3)); + + for (int i = 0; i < sizeof(ipl3_crc32) / sizeof(ipl3_crc32_t); i++) { + if (ipl3_crc32[i].crc32 == crc32) { + params->cic_seed = ipl3_crc32[i].seed; + return true; + } + } + + return false; +} + + +bool boot_is_warm (void) { + return (OS_INFO->reset_type == OS_INFO_RESET_TYPE_NMI); +} + +void boot (boot_params_t *params) { + if (params->tv_type == BOOT_TV_TYPE_PASSTHROUGH) { + params->tv_type = OS_INFO->tv_type; + } + + if (params->detect_cic_seed) { + if (!boot_detect_cic_seed(params)) { + params->cic_seed = 0x3F; + } + } + + OS_INFO->mem_size_6105 = OS_INFO->mem_size; + + C0_WRITE_STATUS(C0_STATUS_CU1 | C0_STATUS_CU0 | C0_STATUS_FR); + + while (!(cpu_io_read(&SP->SR) & SP_SR_HALT)); + + cpu_io_write(&SP->SR, SP_SR_CLR_INTR | SP_SR_SET_HALT); + + while (cpu_io_read(&SP->DMA_BUSY)); + + cpu_io_write(&PI->SR, PI_SR_CLR_INTR | PI_SR_RESET); + cpu_io_write(&VI->V_INTR, 0x3FF); + cpu_io_write(&VI->H_LIMITS, 0); + cpu_io_write(&VI->CURR_LINE, 0); + cpu_io_write(&AI->MADDR, 0); + cpu_io_write(&AI->LEN, 0); + + while (cpu_io_read(&SP->SR) & SP_SR_DMA_BUSY); + + uint32_t *ipl2_src = &ipl2; + io32_t *ipl2_dst = SP_MEM->IMEM; + + for (int i = 0; i < 8; i++) { + cpu_io_write(&ipl2_dst[i], ipl2_src[i]); + } + + cpu_io_write(&PI->DOM[0].LAT, 0xFF); + cpu_io_write(&PI->DOM[0].PWD, 0xFF); + cpu_io_write(&PI->DOM[0].PGS, 0x0F); + cpu_io_write(&PI->DOM[0].RLS, 0x03); + + io32_t *base = boot_get_device_base(params); + uint32_t pi_config = io_read((uint32_t) (base)); + + cpu_io_write(&PI->DOM[0].LAT, pi_config & 0xFF); + cpu_io_write(&PI->DOM[0].PWD, pi_config >> 8); + cpu_io_write(&PI->DOM[0].PGS, pi_config >> 16); + cpu_io_write(&PI->DOM[0].RLS, pi_config >> 20); + + if (cpu_io_read(&DPC->SR) & DPC_SR_XBUS_DMEM_DMA) { + while (cpu_io_read(&DPC->SR) & DPC_SR_PIPE_BUSY); + } + + io32_t *ipl3_src = base; + io32_t *ipl3_dst = SP_MEM->DMEM; + + for (int i = 16; i < 1024; i++) { + cpu_io_write(&ipl3_dst[i], io_read((uint32_t) (&ipl3_src[i]))); + } + + register void (*entry_point)(void) asm ("t3"); + register uint32_t boot_device asm ("s3"); + register uint32_t tv_type asm ("s4"); + register uint32_t reset_type asm ("s5"); + register uint32_t cic_seed asm ("s6"); + register uint32_t version asm ("s7"); + void *stack_pointer; + + entry_point = (void (*)(void)) UNCACHED(&SP_MEM->DMEM[16]); + boot_device = (params->device_type & 0x01); + tv_type = (params->tv_type & 0x03); + reset_type = (params->reset_type & 0x01); + cic_seed = (params->cic_seed & 0xFF); + version = (params->tv_type == BOOT_TV_TYPE_PAL) ? 6 : 1; + stack_pointer = (void *) UNCACHED(&SP_MEM->IMEM[1020]); + + asm volatile ( + "move $sp, %[stack_pointer] \n" + "jr %[entry_point] \n" :: + [entry_point] "r" (entry_point), + [boot_device] "r" (boot_device), + [tv_type] "r" (tv_type), + [reset_type] "r" (reset_type), + [cic_seed] "r" (cic_seed), + [version] "r" (version), + [stack_pointer] "r" (stack_pointer) + ); + + while (1); +} diff --git a/src/flashcart/flashcart.c b/src/flashcart/flashcart.c index 52529f1e..a5a9cf36 100644 --- a/src/flashcart/flashcart.c +++ b/src/flashcart/flashcart.c @@ -39,6 +39,7 @@ static flashcart_t *flashcart = &((flashcart_t) { flashcart_error_t flashcart_init (void) { + bool sd_initialized; flashcart_error_t error; // HACK: Because libcart reads PI config from address 0x10000000 when initializing @@ -48,9 +49,7 @@ flashcart_error_t flashcart_init (void) { extern uint32_t cart_dom1; cart_dom1 = 0x80371240; - if (!debug_init_sdfs("sd:/", -1)) { - return FLASHCART_ERROR_NOT_DETECTED; - } + sd_initialized = debug_init_sdfs("sd:/", -1); // NOTE: Flashcart model is extracted from libcart after debug_init_sdfs call is made extern int cart_type; @@ -66,13 +65,17 @@ flashcart_error_t flashcart_init (void) { break; default: - return FLASHCART_ERROR_UNSUPPORTED; + return FLASHCART_ERROR_NOT_DETECTED; } if ((error = flashcart->init()) != FLASHCART_OK) { return error; } + if (!sd_initialized) { + return FLASHCART_ERROR_SD_CARD; + } + #ifndef MENU_NO_USB_LOG // NOTE: Some flashcarts doesn't have USB port, can't throw error here debug_init_usblog(); diff --git a/src/flashcart/flashcart.h b/src/flashcart/flashcart.h index 3138fef9..3833a1c3 100644 --- a/src/flashcart/flashcart.h +++ b/src/flashcart/flashcart.h @@ -16,8 +16,8 @@ typedef enum { FLASHCART_OK, FLASHCART_ERROR_NOT_DETECTED, - FLASHCART_ERROR_UNSUPPORTED, FLASHCART_ERROR_OUTDATED, + FLASHCART_ERROR_SD_CARD, FLASHCART_ERROR_ARGS, FLASHCART_ERROR_LOAD, FLASHCART_ERROR_INT, diff --git a/src/menu/views/fault.c b/src/menu/views/fault.c index 959da0ab..366a95e3 100644 --- a/src/menu/views/fault.c +++ b/src/menu/views/fault.c @@ -11,10 +11,10 @@ static char *format_flashcart_error (flashcart_error_t error) { return "No error"; case FLASHCART_ERROR_NOT_DETECTED: return "No flashcart hardware was detected"; - case FLASHCART_ERROR_UNSUPPORTED: - return "Unsupported flashcart"; case FLASHCART_ERROR_OUTDATED: return "Outdated flashcart firmware"; + case FLASHCART_ERROR_SD_CARD: + return "Error during SD card initialization"; case FLASHCART_ERROR_ARGS: return "Invalid argument passed to flashcart function"; case FLASHCART_ERROR_LOAD: diff --git a/src/menu/views/load.c b/src/menu/views/load.c index f4028ea8..91835ace 100644 --- a/src/menu/views/load.c +++ b/src/menu/views/load.c @@ -181,7 +181,7 @@ static void load (menu_t *menu) { path_free(path); menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM; - menu->boot_params->reset_type = BOOT_RESET_TYPE_COLD; + menu->boot_params->reset_type = BOOT_RESET_TYPE_NMI; menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH; menu->boot_params->detect_cic_seed = true; }