mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-12-25 20:41:55 +01:00
[SC64][SW] Changed menu loading procedure, updated boot procedure, 64DD fixes
This commit is contained in:
parent
6eb89688ab
commit
bee41d1d04
@ -22,7 +22,7 @@
|
||||
| `I` | **SD_SECTOR_SET** | sector | --- | --- | --- | Set starting sector for next SD card R/W operation |
|
||||
| `s` | **SD_READ** | pi_address | sector_count | --- | --- | Read sectors from SD card to flashcart |
|
||||
| `S` | **SD_WRITE** | pi_address | sector_count | --- | --- | Write sectors from flashcart to SD card |
|
||||
| `D` | **DD_SD_INFO** | pi_address | table_size | --- | --- | Set 64DD disk SD sector info |
|
||||
| `D` | **DISK_MAPPING_SET** | pi_address | table_size | --- | --- | Set 64DD disk mapping for SD mode |
|
||||
| `w` | **WRITEBACK_PENDING** | pending_status | --- | --- | --- | Get save writeback status (is write queued to the SD card) |
|
||||
| `W` | **WRITEBACK_SD_INFO** | pi_address | --- | --- | --- | Load writeback SD sector table and enable it |
|
||||
| `K` | **FLASH_PROGRAM** | pi_address | length | --- | --- | Program flash with bytes loaded into data buffer |
|
||||
|
@ -28,9 +28,9 @@ SRC_FILES = \
|
||||
init.c \
|
||||
interrupt.c \
|
||||
io.c \
|
||||
ipl2.S \
|
||||
main.c \
|
||||
menu.c \
|
||||
reboot.S \
|
||||
sc64.c \
|
||||
syscalls.c \
|
||||
test.c \
|
||||
|
@ -9,10 +9,6 @@ ENTRY(entry_handler)
|
||||
__exception_stack_size = 8k;
|
||||
__stack_size = 16k;
|
||||
|
||||
__bootloader_start = ORIGIN(ram);
|
||||
__bootloader_size = LENGTH(ram);
|
||||
__bootloader_end = __bootloader_start + __bootloader_size;
|
||||
|
||||
SECTIONS {
|
||||
.boot : {
|
||||
KEEP(*(.text.rom_header));
|
||||
|
@ -4,7 +4,8 @@
|
||||
#include "vr4300.h"
|
||||
|
||||
|
||||
extern uint32_t ipl2 __attribute__((section(".data")));
|
||||
extern uint32_t reboot_start __attribute__((section(".text")));
|
||||
extern size_t reboot_size __attribute__((section(".text")));
|
||||
|
||||
|
||||
typedef struct {
|
||||
@ -29,16 +30,16 @@ static const ipl3_crc32_t ipl3_crc32[] = {
|
||||
};
|
||||
|
||||
|
||||
static io32_t *boot_get_device_base (boot_info_t *info) {
|
||||
static io32_t *boot_get_device_base (boot_params_t *params) {
|
||||
io32_t *device_base_address = ROM_CART;
|
||||
if (info->device_type == BOOT_DEVICE_TYPE_DD) {
|
||||
if (params->device_type == BOOT_DEVICE_TYPE_64DD) {
|
||||
device_base_address = ROM_DDIPL;
|
||||
}
|
||||
return device_base_address;
|
||||
}
|
||||
|
||||
static bool boot_get_cic_seed (boot_info_t *info) {
|
||||
io32_t *base = boot_get_device_base(info);
|
||||
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)));
|
||||
|
||||
@ -48,7 +49,7 @@ static bool boot_get_cic_seed (boot_info_t *info) {
|
||||
|
||||
for (int i = 0; i < sizeof(ipl3_crc32) / sizeof(ipl3_crc32_t); i++) {
|
||||
if (ipl3_crc32[i].crc32 == crc32) {
|
||||
info->cic_seed = ipl3_crc32[i].seed;
|
||||
params->cic_seed = ipl3_crc32[i].seed;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -56,32 +57,49 @@ static bool boot_get_cic_seed (boot_info_t *info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void boot (boot_info_t *info, bool detect_cic_seed) {
|
||||
if (info->tv_type == BOOT_TV_TYPE_PASSTHROUGH) {
|
||||
info->tv_type = OS_INFO->tv_type;
|
||||
void boot (boot_params_t *params) {
|
||||
if (params->tv_type == BOOT_TV_TYPE_PASSTHROUGH) {
|
||||
params->tv_type = OS_INFO->tv_type;
|
||||
}
|
||||
|
||||
if (detect_cic_seed) {
|
||||
if (!boot_get_cic_seed(info)) {
|
||||
info->cic_seed = 0x3F;
|
||||
if (params->detect_cic_seed) {
|
||||
if (!boot_detect_cic_seed(params)) {
|
||||
params->cic_seed = 0x3F;
|
||||
}
|
||||
}
|
||||
|
||||
OS_INFO->mem_size_6105 = OS_INFO->mem_size;
|
||||
|
||||
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);
|
||||
cpu_io_write(&SP->SR,
|
||||
SP_SR_CLR_SIG7 |
|
||||
SP_SR_CLR_SIG6 |
|
||||
SP_SR_CLR_SIG5 |
|
||||
SP_SR_CLR_SIG4 |
|
||||
SP_SR_CLR_SIG3 |
|
||||
SP_SR_CLR_SIG2 |
|
||||
SP_SR_CLR_SIG1 |
|
||||
SP_SR_CLR_SIG0 |
|
||||
SP_SR_CLR_INTR_BREAK |
|
||||
SP_SR_CLR_SSTEP |
|
||||
SP_SR_CLR_INTR |
|
||||
SP_SR_CLR_BROKE |
|
||||
SP_SR_SET_HALT
|
||||
);
|
||||
cpu_io_write(&SP->SEMAPHORE, 0);
|
||||
cpu_io_write(&SP->PC, 0);
|
||||
|
||||
while (cpu_io_read(&SP->DMA_BUSY));
|
||||
|
||||
cpu_io_write(&PI->SR, PI_SR_CLR_INTR | PI_SR_RESET);
|
||||
while ((cpu_io_read(&VI->CURR_LINE) & ~(VI_CURR_LINE_FIELD)) != 0);
|
||||
cpu_io_write(&VI->V_INTR, 0x3FF);
|
||||
cpu_io_write(&VI->H_LIMITS, 0);
|
||||
cpu_io_write(&VI->CURR_LINE, 0);
|
||||
@ -90,11 +108,12 @@ void boot (boot_info_t *info, bool detect_cic_seed) {
|
||||
|
||||
while (cpu_io_read(&SP->SR) & SP_SR_DMA_BUSY);
|
||||
|
||||
uint32_t *ipl2_src = &ipl2;
|
||||
io32_t *ipl2_dst = SP_MEM->IMEM;
|
||||
uint32_t *reboot_src = &reboot_start;
|
||||
io32_t *reboot_dst = SP_MEM->IMEM;
|
||||
size_t reboot_instructions = (size_t) (&reboot_size) / sizeof(uint32_t);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
cpu_io_write(&ipl2_dst[i], ipl2_src[i]);
|
||||
for (int i = 0; i < reboot_instructions; i++) {
|
||||
cpu_io_write(&reboot_dst[i], reboot_src[i]);
|
||||
}
|
||||
|
||||
cpu_io_write(&PI->DOM[0].LAT, 0xFF);
|
||||
@ -102,7 +121,7 @@ void boot (boot_info_t *info, bool detect_cic_seed) {
|
||||
cpu_io_write(&PI->DOM[0].PGS, 0x0F);
|
||||
cpu_io_write(&PI->DOM[0].RLS, 0x03);
|
||||
|
||||
io32_t *base = boot_get_device_base(info);
|
||||
io32_t *base = boot_get_device_base(params);
|
||||
uint32_t pi_config = pi_io_read(base);
|
||||
|
||||
cpu_io_write(&PI->DOM[0].LAT, pi_config & 0xFF);
|
||||
@ -121,32 +140,30 @@ void boot (boot_info_t *info, bool detect_cic_seed) {
|
||||
cpu_io_write(&ipl3_dst[i], pi_io_read(&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 = (info->device_type & 0x01);
|
||||
tv_type = (info->tv_type & 0x03);
|
||||
reset_type = (info->reset_type & 0x01);
|
||||
cic_seed = (info->cic_seed & 0xFF);
|
||||
version = (info->tv_type == BOOT_TV_TYPE_PAL) ? 6 : 1;
|
||||
stack_pointer = (void *) UNCACHED(&SP_MEM->IMEM[1020]);
|
||||
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
|
||||
: (params->tv_type == BOOT_TV_TYPE_NTSC) ? 1
|
||||
: (params->tv_type == BOOT_TV_TYPE_MPAL) ? 4
|
||||
: 0;
|
||||
|
||||
asm volatile (
|
||||
"move $sp, %[stack_pointer] \n"
|
||||
"jr %[entry_point] \n" ::
|
||||
[entry_point] "r" (entry_point),
|
||||
"la $t3, reboot \n"
|
||||
"jr $t3 \n" ::
|
||||
[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)
|
||||
[version] "r" (version) :
|
||||
"t3"
|
||||
);
|
||||
|
||||
while (1);
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
typedef enum {
|
||||
BOOT_DEVICE_TYPE_ROM = 0,
|
||||
BOOT_DEVICE_TYPE_DD = 1,
|
||||
BOOT_DEVICE_TYPE_64DD = 1,
|
||||
} boot_device_type_t;
|
||||
|
||||
typedef enum {
|
||||
@ -29,10 +29,11 @@ typedef struct {
|
||||
boot_reset_type_t reset_type;
|
||||
boot_tv_type_t tv_type;
|
||||
uint8_t cic_seed;
|
||||
} boot_info_t;
|
||||
bool detect_cic_seed;
|
||||
} boot_params_t;
|
||||
|
||||
|
||||
void boot (boot_info_t *info, bool detect_cic_seed);
|
||||
void boot (boot_params_t *params);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -10,7 +10,7 @@ typedef volatile uint8_t io8_t;
|
||||
typedef volatile uint32_t io32_t;
|
||||
|
||||
|
||||
#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1))
|
||||
#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1))
|
||||
|
||||
#define PHYSICAL(address) ((typeof(address)) (((io32_t) (address)) & (0x1FFFFFFFUL)))
|
||||
#define UNCACHED(address) ((typeof(address)) (((io32_t) (address)) | (0xA0000000UL)))
|
||||
@ -38,6 +38,8 @@ typedef struct {
|
||||
io32_t DMA_FULL;
|
||||
io32_t DMA_BUSY;
|
||||
io32_t SEMAPHORE;
|
||||
io32_t __reserved[0xFFF8];
|
||||
io32_t PC;
|
||||
} sp_regs_t;
|
||||
|
||||
#define SP_BASE (0x04040000UL)
|
||||
@ -156,6 +158,8 @@ typedef struct {
|
||||
#define VI_CR_PIXEL_ADVANCE_3 (1 << 15)
|
||||
#define VI_CR_DITHER_FILTER_ON (1 << 16)
|
||||
|
||||
#define VI_CURR_LINE_FIELD (1 << 0)
|
||||
|
||||
|
||||
typedef struct {
|
||||
io32_t MADDR;
|
||||
|
@ -1,17 +0,0 @@
|
||||
.set noat
|
||||
.set noreorder
|
||||
|
||||
|
||||
.section .text.ipl2, "ax", %progbits
|
||||
.type ipl2, %object
|
||||
ipl2:
|
||||
.global ipl2
|
||||
lui $t5, 0xBFC0
|
||||
1:
|
||||
lw $t0, 0x7FC($t5)
|
||||
addiu $t5, $t5, 0x7C0
|
||||
andi $t0, $t0, 0x80
|
||||
bnel $t0, $zero, 1b
|
||||
lui $t5, 0xBFC0
|
||||
lw $t0, 0x24($t5)
|
||||
lui $t3, 0xB000
|
@ -8,37 +8,40 @@
|
||||
|
||||
void main (void) {
|
||||
sc64_error_t error;
|
||||
boot_info_t boot_info;
|
||||
sc64_boot_info_t sc64_boot_info;
|
||||
sc64_boot_params_t sc64_boot_params;
|
||||
|
||||
if ((error = sc64_get_boot_info(&sc64_boot_info)) != SC64_OK) {
|
||||
if ((error = sc64_get_boot_params(&sc64_boot_params)) != SC64_OK) {
|
||||
error_display("Could not obtain boot info: %d", error);
|
||||
}
|
||||
|
||||
switch (sc64_boot_info.boot_mode) {
|
||||
boot_params_t boot_params;
|
||||
|
||||
boot_params.reset_type = OS_INFO->reset_type;
|
||||
boot_params.tv_type = sc64_boot_params.tv_type;
|
||||
boot_params.cic_seed = (sc64_boot_params.cic_seed & 0xFF);
|
||||
boot_params.detect_cic_seed = (sc64_boot_params.cic_seed == CIC_SEED_AUTO);
|
||||
|
||||
switch (sc64_boot_params.boot_mode) {
|
||||
case BOOT_MODE_MENU:
|
||||
menu_load_and_run();
|
||||
menu_load();
|
||||
boot_params.device_type = BOOT_DEVICE_TYPE_ROM;
|
||||
boot_params.reset_type = BOOT_RESET_TYPE_NMI;
|
||||
break;
|
||||
|
||||
case BOOT_MODE_ROM:
|
||||
boot_info.device_type = BOOT_DEVICE_TYPE_ROM;
|
||||
boot_params.device_type = BOOT_DEVICE_TYPE_ROM;
|
||||
break;
|
||||
|
||||
case BOOT_MODE_DDIPL:
|
||||
boot_info.device_type = BOOT_DEVICE_TYPE_DD;
|
||||
boot_params.device_type = BOOT_DEVICE_TYPE_64DD;
|
||||
break;
|
||||
|
||||
default:
|
||||
error_display("Unknown boot mode selected [%d]\n", sc64_boot_info.boot_mode);
|
||||
error_display("Unknown boot mode selected [%d]\n", sc64_boot_params.boot_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
boot_info.reset_type = OS_INFO->reset_type;
|
||||
boot_info.tv_type = sc64_boot_info.tv_type;
|
||||
boot_info.cic_seed = (sc64_boot_info.cic_seed & 0xFF);
|
||||
bool detect_cic_seed = (sc64_boot_info.cic_seed == CIC_SEED_AUTO);
|
||||
|
||||
deinit();
|
||||
|
||||
boot(&boot_info, detect_cic_seed);
|
||||
boot(&boot_params);
|
||||
}
|
||||
|
@ -1,41 +1,35 @@
|
||||
#include "error.h"
|
||||
#include "fatfs/ff.h"
|
||||
#include "init.h"
|
||||
#include "io.h"
|
||||
#include "menu.h"
|
||||
#include "sc64.h"
|
||||
|
||||
|
||||
extern const void __bootloader_start __attribute__((section(".data")));
|
||||
extern const void __bootloader_end __attribute__((section(".data")));
|
||||
|
||||
|
||||
#define ROM_ENTRY_OFFSET (8)
|
||||
#define ROM_CODE_OFFSET (4096)
|
||||
#define ROM_MAX_LOAD_SIZE (1 * 1024 * 1024)
|
||||
#define ROM_ADDRESS (0x10000000)
|
||||
#define FILL_SIZE (0x101000)
|
||||
|
||||
|
||||
static const char *fatfs_error_codes[] = {
|
||||
"Succeeded",
|
||||
"A hard error occurred in the low level disk I/O layer",
|
||||
"Assertion failed",
|
||||
"The physical drive cannot work",
|
||||
"Could not find the file",
|
||||
"Could not find the path",
|
||||
"The path name format is invalid",
|
||||
"Access denied due to prohibited access or directory full",
|
||||
"Access denied due to prohibited access",
|
||||
"The file/directory object is invalid",
|
||||
"The physical drive is write protected",
|
||||
"The logical drive number is invalid",
|
||||
"The volume has no work area",
|
||||
"There is no valid FAT volume",
|
||||
"The f_mkfs() aborted due to any problem",
|
||||
"Could not get a grant to access the volume within defined period",
|
||||
"The operation is rejected according to the file sharing policy",
|
||||
"LFN working buffer could not be allocated",
|
||||
"Number of open files > FF_FS_LOCK",
|
||||
"Given parameter is invalid",
|
||||
"Succeeded",
|
||||
"A hard error occurred in the low level disk I/O layer",
|
||||
"Assertion failed",
|
||||
"The physical drive cannot work",
|
||||
"Could not find the file",
|
||||
"Could not find the path",
|
||||
"The path name format is invalid",
|
||||
"Access denied due to prohibited access or directory full",
|
||||
"Access denied due to prohibited access",
|
||||
"The file/directory object is invalid",
|
||||
"The physical drive is write protected",
|
||||
"The logical drive number is invalid",
|
||||
"The volume has no work area",
|
||||
"There is no valid FAT volume",
|
||||
"The f_mkfs() aborted due to any problem",
|
||||
"Could not get a grant to access the volume within defined period",
|
||||
"The operation is rejected according to the file sharing policy",
|
||||
"LFN working buffer could not be allocated",
|
||||
"Number of open files > FF_FS_LOCK",
|
||||
"Given parameter is invalid",
|
||||
};
|
||||
|
||||
|
||||
@ -47,27 +41,55 @@ static const char *fatfs_error_codes[] = {
|
||||
}
|
||||
|
||||
|
||||
static void menu_check_load_address (void *address, size_t size) {
|
||||
void *menu_start = address;
|
||||
void *menu_end = (address + size);
|
||||
void *usable_ram_start = (void *) (0x80000400UL);
|
||||
void *usable_ram_end = (void *) (0x80400000UL);
|
||||
void *bootloader_start = (void *) (&__bootloader_start);
|
||||
void *bootloader_end = (void *) (&__bootloader_end);
|
||||
static void fix_menu_file_size (FIL *fil) {
|
||||
fil->obj.objsize = ALIGN(f_size(fil), FF_MAX_SS);
|
||||
}
|
||||
|
||||
if ((menu_start < usable_ram_start) || (menu_end > usable_ram_end)) {
|
||||
error_display("Incorrect menu load address/size.\nReason: Outside of usable RAM space\n");
|
||||
static void fill_remaining_menu_space (size_t menu_file_size) {
|
||||
if (menu_file_size >= FILL_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((menu_start < bootloader_end) && (bootloader_start < menu_end)) {
|
||||
error_display("Incorrect menu load address/size.\nReason: Overlapping bootloader space\n");
|
||||
sc64_error_t error;
|
||||
uint32_t rom_write_enable_restore;
|
||||
|
||||
if ((error = sc64_get_config(CFG_ID_ROM_WRITE_ENABLE, &rom_write_enable_restore)) != SC64_OK) {
|
||||
error_display("Command CONFIG_GET [CFG_ID_ROM_WRITE_ENABLE] failed: %d", error);
|
||||
}
|
||||
|
||||
if ((error = sc64_set_config(CFG_ID_ROM_WRITE_ENABLE, true)) != SC64_OK) {
|
||||
error_display("Command CONFIG_SET [CFG_ID_ROM_WRITE_ENABLE] failed: %d", error);
|
||||
}
|
||||
|
||||
uint8_t fill_buffer[4096] __attribute__((aligned(8)));
|
||||
|
||||
for (int i = 0; i < sizeof(fill_buffer); i++) {
|
||||
fill_buffer[i] = 0;
|
||||
}
|
||||
|
||||
uint32_t address = (ROM_ADDRESS + menu_file_size);
|
||||
uint32_t left = (FILL_SIZE - menu_file_size);
|
||||
|
||||
while (left > 0) {
|
||||
size_t block = (left > sizeof(fill_buffer)) ? sizeof(fill_buffer) : left;
|
||||
pi_dma_write((io32_t *) (address), fill_buffer, block);
|
||||
address += block;
|
||||
left -= block;
|
||||
}
|
||||
|
||||
if ((error = sc64_set_config(CFG_ID_ROM_WRITE_ENABLE, rom_write_enable_restore)) != SC64_OK) {
|
||||
error_display("Command CONFIG_SET [CFG_ID_ROM_WRITE_ENABLE] failed: %d", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void menu_load_and_run (void) {
|
||||
void menu_load (void) {
|
||||
sc64_error_t error;
|
||||
bool writeback_pending;
|
||||
FRESULT fresult;
|
||||
FATFS fs;
|
||||
FIL fil;
|
||||
UINT bytes_read;
|
||||
|
||||
do {
|
||||
if ((error = sc64_writeback_pending(&writeback_pending)) != SC64_OK) {
|
||||
@ -79,32 +101,12 @@ void menu_load_and_run (void) {
|
||||
error_display("Could not disable writeback: %d", error);
|
||||
}
|
||||
|
||||
void (* menu)(void);
|
||||
FRESULT fresult;
|
||||
FATFS fs;
|
||||
FIL fil;
|
||||
UINT br;
|
||||
size_t size = ROM_MAX_LOAD_SIZE;
|
||||
|
||||
FF_CHECK(f_mount(&fs, "", 1), "SD card initialize error. No SD card or invalid partition table");
|
||||
FF_CHECK(f_open(&fil, "sc64menu.n64", FA_READ), "Could not open menu executable (sc64menu.n64)");
|
||||
FF_CHECK(f_lseek(&fil, ROM_ENTRY_OFFSET), "Could not seek to entry point offset");
|
||||
FF_CHECK(f_read(&fil, &menu, sizeof(menu), &br), "Could not read entry point");
|
||||
FF_CHECK(f_lseek(&fil, ROM_CODE_OFFSET), "Could not seek to code start offset");
|
||||
if ((f_size(&fil) - ROM_CODE_OFFSET) < size) {
|
||||
size = (size_t) (f_size(&fil) - ROM_CODE_OFFSET);
|
||||
}
|
||||
menu_check_load_address(menu, size);
|
||||
cache_data_hit_writeback_invalidate(menu, size);
|
||||
cache_inst_hit_invalidate(menu, size);
|
||||
FF_CHECK(f_read(&fil, menu, size, &br), "Could not read menu file");
|
||||
FF_CHECK((br != size) ? FR_INT_ERR : FR_OK, "Read size is different than expected");
|
||||
fix_menu_file_size(&fil);
|
||||
FF_CHECK(f_read(&fil, (void *) (ROM_ADDRESS), f_size(&fil), &bytes_read), "Could not read menu file");
|
||||
FF_CHECK((bytes_read != f_size(&fil)) ? FR_INT_ERR : FR_OK, "Read size is different than expected");
|
||||
fill_remaining_menu_space(f_size(&fil));
|
||||
FF_CHECK(f_close(&fil), "Could not close menu file");
|
||||
FF_CHECK(f_unmount(""), "Could not unmount drive");
|
||||
|
||||
deinit();
|
||||
|
||||
menu();
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define MENU_H__
|
||||
|
||||
|
||||
void menu_load_and_run (void);
|
||||
void menu_load (void);
|
||||
|
||||
|
||||
#endif
|
||||
|
114
sw/bootloader/src/reboot.S
Normal file
114
sw/bootloader/src/reboot.S
Normal file
@ -0,0 +1,114 @@
|
||||
#define IPL3_ENTRY 0xA4000040
|
||||
#define REBOOT_ADDRESS 0xA4001000
|
||||
#define STACK_ADDRESS 0xA4001FF0
|
||||
|
||||
#define RI_ADDRESS 0xA4700000
|
||||
|
||||
#define RI_MODE 0x00
|
||||
#define RI_CONFIG 0x04
|
||||
#define RI_CURRENT_LOAD 0x08
|
||||
#define RI_SELECT 0x0C
|
||||
#define RI_REFRESH 0x10
|
||||
#define RI_LATENCY 0x14
|
||||
|
||||
#define RI_MODE_RESET 0x00000000
|
||||
#define RI_MODE_STANDBY 0x0000000E
|
||||
|
||||
#define RDRAM_RESET_DELAY 1024
|
||||
#define RDRAM_STANDBY_DELAY 512
|
||||
|
||||
.set noat
|
||||
.section .text.reboot, "ax", %progbits
|
||||
.type reboot, %object
|
||||
reboot_start:
|
||||
.global reboot_start
|
||||
|
||||
# NOTE: CIC x105 requirement
|
||||
ipl2:
|
||||
.set noreorder
|
||||
lui $t5, 0xBFC0
|
||||
1:
|
||||
lw $t0, 0x7FC($t5)
|
||||
addiu $t5, $t5, 0x7C0
|
||||
andi $t0, $t0, 0x80
|
||||
bnel $t0, $zero, 1b
|
||||
lui $t5, 0xBFC0
|
||||
lw $t0, 0x24($t5)
|
||||
lui $t3, 0xB000
|
||||
.set reorder
|
||||
|
||||
reboot_entry:
|
||||
.set reboot, REBOOT_ADDRESS + (. - reboot_start)
|
||||
.global reboot
|
||||
|
||||
li $sp, STACK_ADDRESS
|
||||
|
||||
bnez $s5, reset_rdram_skip
|
||||
|
||||
reset_rdram:
|
||||
li $t0, RI_ADDRESS
|
||||
|
||||
li $t1, RI_MODE_RESET
|
||||
sw $t1, RI_MODE($t0)
|
||||
|
||||
li $t2, RDRAM_RESET_DELAY
|
||||
1:
|
||||
addiu $t2, (-1)
|
||||
bnez $t2, 1b
|
||||
|
||||
sw $zero, RI_CONFIG($t0)
|
||||
sw $zero, RI_CURRENT_LOAD($t0)
|
||||
sw $zero, RI_SELECT($t0)
|
||||
sw $zero, RI_REFRESH($t0)
|
||||
|
||||
li $t1, RI_MODE_STANDBY
|
||||
sw $t1, RI_MODE($t0)
|
||||
|
||||
li $t2, RDRAM_STANDBY_DELAY
|
||||
1:
|
||||
addiu $t2, (-1)
|
||||
bnez $t2, 1b
|
||||
reset_rdram_skip:
|
||||
|
||||
prepare_registers:
|
||||
la $t0, ra_table
|
||||
sll $t1, $s4, 2
|
||||
add $t0, $t1
|
||||
lw $ra, ($t0)
|
||||
|
||||
move $at, $zero
|
||||
move $v0, $zero
|
||||
move $v1, $zero
|
||||
move $a0, $zero
|
||||
move $a1, $zero
|
||||
move $a2, $zero
|
||||
move $a3, $zero
|
||||
move $t0, $zero
|
||||
move $t1, $zero
|
||||
move $t2, $zero
|
||||
move $t4, $zero
|
||||
move $t5, $zero
|
||||
move $t6, $zero
|
||||
move $t7, $zero
|
||||
move $s0, $zero
|
||||
move $s1, $zero
|
||||
move $s2, $zero
|
||||
move $t8, $zero
|
||||
move $t9, $zero
|
||||
move $k0, $zero
|
||||
move $k1, $zero
|
||||
move $gp, $zero
|
||||
move $fp, $zero
|
||||
|
||||
run_ipl3:
|
||||
li $t3, IPL3_ENTRY
|
||||
jr $t3
|
||||
|
||||
ra_values:
|
||||
.set ra_table, REBOOT_ADDRESS + (. - reboot_start)
|
||||
.word 0xA4001554
|
||||
.word 0xA4001550
|
||||
.word 0xA4001554
|
||||
|
||||
.set reboot_size, (. - reboot_start)
|
||||
.global reboot_size
|
@ -42,7 +42,7 @@ typedef enum {
|
||||
CMD_ID_SD_SECTOR_SET = 'I',
|
||||
CMD_ID_SD_READ = 's',
|
||||
CMD_ID_SD_WRITE = 'S',
|
||||
CMD_ID_DD_SD_INFO = 'D',
|
||||
CMD_ID_DISK_MAPPING_SET = 'D',
|
||||
CMD_ID_WRITEBACK_PENDING = 'w',
|
||||
CMD_ID_WRITEBACK_SD_INFO = 'W',
|
||||
CMD_ID_FLASH_PROGRAM = 'K',
|
||||
@ -174,24 +174,29 @@ sc64_error_t sc64_set_setting (sc64_setting_id_t id, uint32_t value) {
|
||||
return sc64_execute_cmd(&cmd);
|
||||
}
|
||||
|
||||
sc64_error_t sc64_get_boot_info (sc64_boot_info_t *info) {
|
||||
sc64_error_t sc64_get_boot_params (sc64_boot_params_t *params) {
|
||||
sc64_error_t error;
|
||||
uint32_t value;
|
||||
|
||||
if ((error = sc64_get_config(CFG_ID_BOOT_MODE, &value)) != SC64_OK) {
|
||||
return error;
|
||||
}
|
||||
info->boot_mode = value;
|
||||
params->boot_mode = value;
|
||||
|
||||
if ((error = sc64_get_config(CFG_ID_CIC_SEED, &value)) != SC64_OK) {
|
||||
return error;
|
||||
}
|
||||
info->cic_seed = value;
|
||||
if (params->boot_mode != BOOT_MODE_MENU) {
|
||||
if ((error = sc64_get_config(CFG_ID_CIC_SEED, &value)) != SC64_OK) {
|
||||
return error;
|
||||
}
|
||||
params->cic_seed = value;
|
||||
|
||||
if ((error = sc64_get_config(CFG_ID_TV_TYPE, &value)) != SC64_OK) {
|
||||
return error;
|
||||
if ((error = sc64_get_config(CFG_ID_TV_TYPE, &value)) != SC64_OK) {
|
||||
return error;
|
||||
}
|
||||
params->tv_type = value;
|
||||
} else {
|
||||
params->cic_seed = CIC_SEED_AUTO;
|
||||
params->tv_type = TV_TYPE_PASSTHROUGH;
|
||||
}
|
||||
info->tv_type = value;
|
||||
|
||||
return SC64_OK;
|
||||
}
|
||||
@ -361,9 +366,9 @@ sc64_error_t sc64_sd_write_sectors (void *address, uint32_t sector, uint32_t cou
|
||||
}
|
||||
|
||||
|
||||
sc64_error_t sc64_dd_set_sd_info (void *address, uint32_t length) {
|
||||
sc64_error_t sc64_set_disk_mapping (void *address, uint32_t length) {
|
||||
sc64_cmd_t cmd = {
|
||||
.id = CMD_ID_DD_SD_INFO,
|
||||
.id = CMD_ID_DISK_MAPPING_SET,
|
||||
.arg = { (uint32_t) (address), length }
|
||||
};
|
||||
return sc64_execute_cmd(&cmd);
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@ -96,7 +97,7 @@ typedef struct {
|
||||
sc64_boot_mode_t boot_mode;
|
||||
sc64_cic_seed_t cic_seed;
|
||||
sc64_tv_type_t tv_type;
|
||||
} sc64_boot_info_t;
|
||||
} sc64_boot_params_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t second;
|
||||
@ -142,7 +143,7 @@ sc64_error_t sc64_get_config (sc64_cfg_id_t id, uint32_t *value);
|
||||
sc64_error_t sc64_set_config (sc64_cfg_id_t id, uint32_t value);
|
||||
sc64_error_t sc64_get_setting (sc64_setting_id_t id, uint32_t *value);
|
||||
sc64_error_t sc64_set_setting (sc64_setting_id_t id, uint32_t value);
|
||||
sc64_error_t sc64_get_boot_info (sc64_boot_info_t *info);
|
||||
sc64_error_t sc64_get_boot_params (sc64_boot_params_t *params);
|
||||
|
||||
sc64_error_t sc64_get_time (sc64_rtc_time_t *t);
|
||||
sc64_error_t sc64_set_time (sc64_rtc_time_t *t);
|
||||
@ -162,7 +163,7 @@ sc64_error_t sc64_sd_set_byte_swap (bool enabled);
|
||||
sc64_error_t sc64_sd_read_sectors (void *address, uint32_t sector, uint32_t count);
|
||||
sc64_error_t sc64_sd_write_sectors (void *address, uint32_t sector, uint32_t count);
|
||||
|
||||
sc64_error_t sc64_dd_set_sd_info (void *address, uint32_t length);
|
||||
sc64_error_t sc64_set_disk_mapping (void *address, uint32_t length);
|
||||
|
||||
sc64_error_t sc64_writeback_pending (bool *pending);
|
||||
sc64_error_t sc64_writeback_enable (void *address);
|
||||
|
@ -41,12 +41,12 @@ entry_handler:
|
||||
la $sp, _sp
|
||||
|
||||
bss_init:
|
||||
la $a0, _sbss
|
||||
la $a1, _ebss
|
||||
la $a0, _sbss
|
||||
la $a1, _ebss
|
||||
1:
|
||||
sd $zero, 0($a0)
|
||||
addiu $a0, 8
|
||||
bltu $a0, $a1, 1b
|
||||
sd $zero, 0($a0)
|
||||
addiu $a0, 8
|
||||
bltu $a0, $a1, 1b
|
||||
|
||||
la $t0, init
|
||||
jalr $t0
|
||||
|
@ -636,7 +636,7 @@ void cfg_process (void) {
|
||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
||||
return;
|
||||
}
|
||||
dd_set_sd_info(args[0], args[1]);
|
||||
dd_set_disk_mapping(args[0], args[1]);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
|
@ -22,6 +22,9 @@
|
||||
|
||||
#define DD_SPIN_UP_TIME (2000)
|
||||
|
||||
#define DD_THB_UNMAPPED (0xFFFFFFFF)
|
||||
#define DD_THB_WRITABLE_FLAG (1 << 31)
|
||||
|
||||
|
||||
typedef enum {
|
||||
DD_CMD_SEEK_READ = 0x01,
|
||||
@ -100,7 +103,7 @@ static uint16_t dd_track_head_block (void) {
|
||||
return (track | head | block);
|
||||
}
|
||||
|
||||
static uint32_t dd_fill_sd_sector_table (uint32_t index, uint32_t *sector_table) {
|
||||
static uint32_t dd_fill_sd_sector_table (uint32_t index, uint32_t *sector_table, bool is_write) {
|
||||
uint32_t tmp;
|
||||
sd_disk_info_t info = p.sd_disk_info[p.sd_current_disk];
|
||||
if (info.thb_table_address == 0xFFFFFFFF) {
|
||||
@ -109,9 +112,13 @@ static uint32_t dd_fill_sd_sector_table (uint32_t index, uint32_t *sector_table)
|
||||
uint32_t thb_entry_address = (info.thb_table_address + (index * sizeof(uint32_t)));
|
||||
fpga_mem_read(thb_entry_address, sizeof(uint32_t), (uint8_t *) (&tmp));
|
||||
uint32_t start_offset = SWAP32(tmp);
|
||||
if (start_offset == 0xFFFFFFFF) {
|
||||
if (start_offset == DD_THB_UNMAPPED) {
|
||||
return 0;
|
||||
}
|
||||
if (is_write && ((start_offset & DD_THB_WRITABLE_FLAG) == 0)) {
|
||||
return 0;
|
||||
}
|
||||
start_offset &= ~(DD_THB_WRITABLE_FLAG);
|
||||
p.block_offset = (start_offset % SD_SECTOR_SIZE);
|
||||
uint32_t block_length = ((p.sector_info.sector_size + 1) * DD_BLOCK_DATA_SECTORS_NUM);
|
||||
uint32_t end_offset = ((start_offset + block_length) - 1);
|
||||
@ -130,7 +137,7 @@ static bool dd_block_read_request (void) {
|
||||
uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS;
|
||||
if (p.sd_mode) {
|
||||
uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE];
|
||||
uint32_t sectors = dd_fill_sd_sector_table(index, sector_table);
|
||||
uint32_t sectors = dd_fill_sd_sector_table(index, sector_table, false);
|
||||
bool error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_read_sectors);
|
||||
dd_set_block_ready(!error);
|
||||
} else {
|
||||
@ -152,7 +159,7 @@ static bool dd_block_write_request (void) {
|
||||
uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS;
|
||||
if (p.sd_mode) {
|
||||
uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE];
|
||||
uint32_t sectors = dd_fill_sd_sector_table(index, sector_table);
|
||||
uint32_t sectors = dd_fill_sd_sector_table(index, sector_table, true);
|
||||
bool error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_write_sectors);
|
||||
dd_set_block_ready(!error);
|
||||
} else {
|
||||
@ -244,7 +251,7 @@ void dd_set_sd_mode (bool value) {
|
||||
p.sd_mode = value;
|
||||
}
|
||||
|
||||
void dd_set_sd_info (uint32_t address, uint32_t length) {
|
||||
void dd_set_disk_mapping (uint32_t address, uint32_t length) {
|
||||
sd_disk_info_t info;
|
||||
length /= sizeof(info);
|
||||
p.sd_current_disk = 0;
|
||||
@ -289,7 +296,7 @@ void dd_init (void) {
|
||||
p.drive_type = DD_DRIVE_TYPE_RETAIL;
|
||||
p.sd_mode = false;
|
||||
p.sd_current_disk = 0;
|
||||
dd_set_sd_info(0, 0);
|
||||
dd_set_disk_mapping(0, 0);
|
||||
}
|
||||
|
||||
void dd_process (void) {
|
||||
|
@ -25,7 +25,7 @@ dd_disk_state_t dd_get_disk_state (void);
|
||||
bool dd_set_disk_state (dd_disk_state_t state);
|
||||
bool dd_get_sd_mode (void);
|
||||
void dd_set_sd_mode (bool value);
|
||||
void dd_set_sd_info (uint32_t address, uint32_t length);
|
||||
void dd_set_disk_mapping (uint32_t address, uint32_t length);
|
||||
void dd_handle_button (void);
|
||||
void dd_init (void);
|
||||
void dd_process (void);
|
||||
|
@ -58,7 +58,7 @@ typedef enum {
|
||||
} fpga_reg_t;
|
||||
|
||||
|
||||
#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1))
|
||||
#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1))
|
||||
#define SWAP16(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8))
|
||||
#define SWAP32(x) (((x) & 0xFF) << 24 | ((x) & 0xFF00) << 8 | ((x) & 0xFF0000) >> 8 | ((x) & 0xFF000000) >> 24)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user