[SC64][SW] Changed menu loading procedure, updated boot procedure, 64DD fixes

This commit is contained in:
Mateusz Faderewski 2023-09-15 20:51:57 +02:00
parent 6eb89688ab
commit bee41d1d04
18 changed files with 302 additions and 169 deletions

View File

@ -22,7 +22,7 @@
| `I` | **SD_SECTOR_SET** | sector | --- | --- | --- | Set starting sector for next SD card R/W operation | | `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_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 | | `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_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 | | `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 | | `K` | **FLASH_PROGRAM** | pi_address | length | --- | --- | Program flash with bytes loaded into data buffer |

View File

@ -28,9 +28,9 @@ SRC_FILES = \
init.c \ init.c \
interrupt.c \ interrupt.c \
io.c \ io.c \
ipl2.S \
main.c \ main.c \
menu.c \ menu.c \
reboot.S \
sc64.c \ sc64.c \
syscalls.c \ syscalls.c \
test.c \ test.c \

View File

@ -9,10 +9,6 @@ ENTRY(entry_handler)
__exception_stack_size = 8k; __exception_stack_size = 8k;
__stack_size = 16k; __stack_size = 16k;
__bootloader_start = ORIGIN(ram);
__bootloader_size = LENGTH(ram);
__bootloader_end = __bootloader_start + __bootloader_size;
SECTIONS { SECTIONS {
.boot : { .boot : {
KEEP(*(.text.rom_header)); KEEP(*(.text.rom_header));

View File

@ -4,7 +4,8 @@
#include "vr4300.h" #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 { 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; 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; device_base_address = ROM_DDIPL;
} }
return device_base_address; return device_base_address;
} }
static bool boot_get_cic_seed (boot_info_t *info) { static bool boot_detect_cic_seed (boot_params_t *params) {
io32_t *base = boot_get_device_base(info); io32_t *base = boot_get_device_base(params);
uint32_t ipl3[1008] __attribute__((aligned(8))); 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++) { for (int i = 0; i < sizeof(ipl3_crc32) / sizeof(ipl3_crc32_t); i++) {
if (ipl3_crc32[i].crc32 == crc32) { if (ipl3_crc32[i].crc32 == crc32) {
info->cic_seed = ipl3_crc32[i].seed; params->cic_seed = ipl3_crc32[i].seed;
return true; return true;
} }
} }
@ -56,32 +57,49 @@ static bool boot_get_cic_seed (boot_info_t *info) {
return false; return false;
} }
void boot (boot_info_t *info, bool detect_cic_seed) { void boot (boot_params_t *params) {
if (info->tv_type == BOOT_TV_TYPE_PASSTHROUGH) { if (params->tv_type == BOOT_TV_TYPE_PASSTHROUGH) {
info->tv_type = OS_INFO->tv_type; params->tv_type = OS_INFO->tv_type;
} }
if (detect_cic_seed) { if (params->detect_cic_seed) {
if (!boot_get_cic_seed(info)) { if (!boot_detect_cic_seed(params)) {
info->cic_seed = 0x3F; params->cic_seed = 0x3F;
} }
} }
OS_INFO->mem_size_6105 = OS_INFO->mem_size;
asm volatile ( asm volatile (
"li $t1, %[status] \n" "li $t1, %[status] \n"
"mtc0 $t1, $12 \n" :: "mtc0 $t1, $12 \n" ::
[status] "i" (C0_SR_CU1 | C0_SR_CU0 | C0_SR_FR) [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)); 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)); while (cpu_io_read(&SP->DMA_BUSY));
cpu_io_write(&PI->SR, PI_SR_CLR_INTR | PI_SR_RESET); 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->V_INTR, 0x3FF);
cpu_io_write(&VI->H_LIMITS, 0); cpu_io_write(&VI->H_LIMITS, 0);
cpu_io_write(&VI->CURR_LINE, 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); while (cpu_io_read(&SP->SR) & SP_SR_DMA_BUSY);
uint32_t *ipl2_src = &ipl2; uint32_t *reboot_src = &reboot_start;
io32_t *ipl2_dst = SP_MEM->IMEM; 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++) { for (int i = 0; i < reboot_instructions; i++) {
cpu_io_write(&ipl2_dst[i], ipl2_src[i]); cpu_io_write(&reboot_dst[i], reboot_src[i]);
} }
cpu_io_write(&PI->DOM[0].LAT, 0xFF); 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].PGS, 0x0F);
cpu_io_write(&PI->DOM[0].RLS, 0x03); 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); uint32_t pi_config = pi_io_read(base);
cpu_io_write(&PI->DOM[0].LAT, pi_config & 0xFF); 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])); 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 boot_device asm ("s3");
register uint32_t tv_type asm ("s4"); register uint32_t tv_type asm ("s4");
register uint32_t reset_type asm ("s5"); register uint32_t reset_type asm ("s5");
register uint32_t cic_seed asm ("s6"); register uint32_t cic_seed asm ("s6");
register uint32_t version asm ("s7"); register uint32_t version asm ("s7");
void *stack_pointer;
entry_point = (void (*)(void)) UNCACHED(&SP_MEM->DMEM[16]); boot_device = (params->device_type & 0x01);
boot_device = (info->device_type & 0x01); tv_type = (params->tv_type & 0x03);
tv_type = (info->tv_type & 0x03); reset_type = (params->reset_type & 0x01);
reset_type = (info->reset_type & 0x01); cic_seed = (params->cic_seed & 0xFF);
cic_seed = (info->cic_seed & 0xFF); version = (params->tv_type == BOOT_TV_TYPE_PAL) ? 6
version = (info->tv_type == BOOT_TV_TYPE_PAL) ? 6 : 1; : (params->tv_type == BOOT_TV_TYPE_NTSC) ? 1
stack_pointer = (void *) UNCACHED(&SP_MEM->IMEM[1020]); : (params->tv_type == BOOT_TV_TYPE_MPAL) ? 4
: 0;
asm volatile ( asm volatile (
"move $sp, %[stack_pointer] \n" "la $t3, reboot \n"
"jr %[entry_point] \n" :: "jr $t3 \n" ::
[entry_point] "r" (entry_point),
[boot_device] "r" (boot_device), [boot_device] "r" (boot_device),
[tv_type] "r" (tv_type), [tv_type] "r" (tv_type),
[reset_type] "r" (reset_type), [reset_type] "r" (reset_type),
[cic_seed] "r" (cic_seed), [cic_seed] "r" (cic_seed),
[version] "r" (version), [version] "r" (version) :
[stack_pointer] "r" (stack_pointer) "t3"
); );
while (1); while (1);

View File

@ -8,7 +8,7 @@
typedef enum { typedef enum {
BOOT_DEVICE_TYPE_ROM = 0, BOOT_DEVICE_TYPE_ROM = 0,
BOOT_DEVICE_TYPE_DD = 1, BOOT_DEVICE_TYPE_64DD = 1,
} boot_device_type_t; } boot_device_type_t;
typedef enum { typedef enum {
@ -29,10 +29,11 @@ typedef struct {
boot_reset_type_t reset_type; boot_reset_type_t reset_type;
boot_tv_type_t tv_type; boot_tv_type_t tv_type;
uint8_t cic_seed; 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 #endif

View File

@ -10,7 +10,7 @@ typedef volatile uint8_t io8_t;
typedef volatile uint32_t io32_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 PHYSICAL(address) ((typeof(address)) (((io32_t) (address)) & (0x1FFFFFFFUL)))
#define UNCACHED(address) ((typeof(address)) (((io32_t) (address)) | (0xA0000000UL))) #define UNCACHED(address) ((typeof(address)) (((io32_t) (address)) | (0xA0000000UL)))
@ -38,6 +38,8 @@ typedef struct {
io32_t DMA_FULL; io32_t DMA_FULL;
io32_t DMA_BUSY; io32_t DMA_BUSY;
io32_t SEMAPHORE; io32_t SEMAPHORE;
io32_t __reserved[0xFFF8];
io32_t PC;
} sp_regs_t; } sp_regs_t;
#define SP_BASE (0x04040000UL) #define SP_BASE (0x04040000UL)
@ -156,6 +158,8 @@ typedef struct {
#define VI_CR_PIXEL_ADVANCE_3 (1 << 15) #define VI_CR_PIXEL_ADVANCE_3 (1 << 15)
#define VI_CR_DITHER_FILTER_ON (1 << 16) #define VI_CR_DITHER_FILTER_ON (1 << 16)
#define VI_CURR_LINE_FIELD (1 << 0)
typedef struct { typedef struct {
io32_t MADDR; io32_t MADDR;

View File

@ -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

View File

@ -8,37 +8,40 @@
void main (void) { void main (void) {
sc64_error_t error; sc64_error_t error;
boot_info_t boot_info; sc64_boot_params_t sc64_boot_params;
sc64_boot_info_t sc64_boot_info;
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); 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: 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; break;
case BOOT_MODE_ROM: case BOOT_MODE_ROM:
boot_info.device_type = BOOT_DEVICE_TYPE_ROM; boot_params.device_type = BOOT_DEVICE_TYPE_ROM;
break; break;
case BOOT_MODE_DDIPL: case BOOT_MODE_DDIPL:
boot_info.device_type = BOOT_DEVICE_TYPE_DD; boot_params.device_type = BOOT_DEVICE_TYPE_64DD;
break; break;
default: 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; 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(); deinit();
boot(&boot_info, detect_cic_seed); boot(&boot_params);
} }

View File

@ -1,41 +1,35 @@
#include "error.h" #include "error.h"
#include "fatfs/ff.h" #include "fatfs/ff.h"
#include "init.h"
#include "io.h" #include "io.h"
#include "menu.h" #include "menu.h"
#include "sc64.h" #include "sc64.h"
extern const void __bootloader_start __attribute__((section(".data"))); #define ROM_ADDRESS (0x10000000)
extern const void __bootloader_end __attribute__((section(".data"))); #define FILL_SIZE (0x101000)
#define ROM_ENTRY_OFFSET (8)
#define ROM_CODE_OFFSET (4096)
#define ROM_MAX_LOAD_SIZE (1 * 1024 * 1024)
static const char *fatfs_error_codes[] = { static const char *fatfs_error_codes[] = {
"Succeeded", "Succeeded",
"A hard error occurred in the low level disk I/O layer", "A hard error occurred in the low level disk I/O layer",
"Assertion failed", "Assertion failed",
"The physical drive cannot work", "The physical drive cannot work",
"Could not find the file", "Could not find the file",
"Could not find the path", "Could not find the path",
"The path name format is invalid", "The path name format is invalid",
"Access denied due to prohibited access or directory full", "Access denied due to prohibited access or directory full",
"Access denied due to prohibited access", "Access denied due to prohibited access",
"The file/directory object is invalid", "The file/directory object is invalid",
"The physical drive is write protected", "The physical drive is write protected",
"The logical drive number is invalid", "The logical drive number is invalid",
"The volume has no work area", "The volume has no work area",
"There is no valid FAT volume", "There is no valid FAT volume",
"The f_mkfs() aborted due to any problem", "The f_mkfs() aborted due to any problem",
"Could not get a grant to access the volume within defined period", "Could not get a grant to access the volume within defined period",
"The operation is rejected according to the file sharing policy", "The operation is rejected according to the file sharing policy",
"LFN working buffer could not be allocated", "LFN working buffer could not be allocated",
"Number of open files > FF_FS_LOCK", "Number of open files > FF_FS_LOCK",
"Given parameter is invalid", "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) { static void fix_menu_file_size (FIL *fil) {
void *menu_start = address; fil->obj.objsize = ALIGN(f_size(fil), FF_MAX_SS);
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);
if ((menu_start < usable_ram_start) || (menu_end > usable_ram_end)) { static void fill_remaining_menu_space (size_t menu_file_size) {
error_display("Incorrect menu load address/size.\nReason: Outside of usable RAM space\n"); if (menu_file_size >= FILL_SIZE) {
return;
} }
if ((menu_start < bootloader_end) && (bootloader_start < menu_end)) { sc64_error_t error;
error_display("Incorrect menu load address/size.\nReason: Overlapping bootloader space\n"); 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; sc64_error_t error;
bool writeback_pending; bool writeback_pending;
FRESULT fresult;
FATFS fs;
FIL fil;
UINT bytes_read;
do { do {
if ((error = sc64_writeback_pending(&writeback_pending)) != SC64_OK) { 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); 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_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_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"); fix_menu_file_size(&fil);
FF_CHECK(f_read(&fil, &menu, sizeof(menu), &br), "Could not read entry point"); FF_CHECK(f_read(&fil, (void *) (ROM_ADDRESS), f_size(&fil), &bytes_read), "Could not read menu file");
FF_CHECK(f_lseek(&fil, ROM_CODE_OFFSET), "Could not seek to code start offset"); FF_CHECK((bytes_read != f_size(&fil)) ? FR_INT_ERR : FR_OK, "Read size is different than expected");
if ((f_size(&fil) - ROM_CODE_OFFSET) < size) { fill_remaining_menu_space(f_size(&fil));
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");
FF_CHECK(f_close(&fil), "Could not close menu file"); FF_CHECK(f_close(&fil), "Could not close menu file");
FF_CHECK(f_unmount(""), "Could not unmount drive"); FF_CHECK(f_unmount(""), "Could not unmount drive");
deinit();
menu();
while (1);
} }

View File

@ -2,7 +2,7 @@
#define MENU_H__ #define MENU_H__
void menu_load_and_run (void); void menu_load (void);
#endif #endif

114
sw/bootloader/src/reboot.S Normal file
View 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

View File

@ -42,7 +42,7 @@ typedef enum {
CMD_ID_SD_SECTOR_SET = 'I', CMD_ID_SD_SECTOR_SET = 'I',
CMD_ID_SD_READ = 's', CMD_ID_SD_READ = 's',
CMD_ID_SD_WRITE = '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_PENDING = 'w',
CMD_ID_WRITEBACK_SD_INFO = 'W', CMD_ID_WRITEBACK_SD_INFO = 'W',
CMD_ID_FLASH_PROGRAM = 'K', 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); 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; sc64_error_t error;
uint32_t value; uint32_t value;
if ((error = sc64_get_config(CFG_ID_BOOT_MODE, &value)) != SC64_OK) { if ((error = sc64_get_config(CFG_ID_BOOT_MODE, &value)) != SC64_OK) {
return error; return error;
} }
info->boot_mode = value; params->boot_mode = value;
if ((error = sc64_get_config(CFG_ID_CIC_SEED, &value)) != SC64_OK) { if (params->boot_mode != BOOT_MODE_MENU) {
return error; if ((error = sc64_get_config(CFG_ID_CIC_SEED, &value)) != SC64_OK) {
} return error;
info->cic_seed = value; }
params->cic_seed = value;
if ((error = sc64_get_config(CFG_ID_TV_TYPE, &value)) != SC64_OK) { if ((error = sc64_get_config(CFG_ID_TV_TYPE, &value)) != SC64_OK) {
return error; 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; 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 = { sc64_cmd_t cmd = {
.id = CMD_ID_DD_SD_INFO, .id = CMD_ID_DISK_MAPPING_SET,
.arg = { (uint32_t) (address), length } .arg = { (uint32_t) (address), length }
}; };
return sc64_execute_cmd(&cmd); return sc64_execute_cmd(&cmd);

View File

@ -3,6 +3,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
@ -96,7 +97,7 @@ typedef struct {
sc64_boot_mode_t boot_mode; sc64_boot_mode_t boot_mode;
sc64_cic_seed_t cic_seed; sc64_cic_seed_t cic_seed;
sc64_tv_type_t tv_type; sc64_tv_type_t tv_type;
} sc64_boot_info_t; } sc64_boot_params_t;
typedef struct { typedef struct {
uint8_t second; 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_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_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_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_get_time (sc64_rtc_time_t *t);
sc64_error_t sc64_set_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_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_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_pending (bool *pending);
sc64_error_t sc64_writeback_enable (void *address); sc64_error_t sc64_writeback_enable (void *address);

View File

@ -41,12 +41,12 @@ entry_handler:
la $sp, _sp la $sp, _sp
bss_init: bss_init:
la $a0, _sbss la $a0, _sbss
la $a1, _ebss la $a1, _ebss
1: 1:
sd $zero, 0($a0) sd $zero, 0($a0)
addiu $a0, 8 addiu $a0, 8
bltu $a0, $a1, 1b bltu $a0, $a1, 1b
la $t0, init la $t0, init
jalr $t0 jalr $t0

View File

@ -636,7 +636,7 @@ void cfg_process (void) {
cfg_set_error(CFG_ERROR_BAD_ADDRESS); cfg_set_error(CFG_ERROR_BAD_ADDRESS);
return; return;
} }
dd_set_sd_info(args[0], args[1]); dd_set_disk_mapping(args[0], args[1]);
break; break;
case 'w': case 'w':

View File

@ -22,6 +22,9 @@
#define DD_SPIN_UP_TIME (2000) #define DD_SPIN_UP_TIME (2000)
#define DD_THB_UNMAPPED (0xFFFFFFFF)
#define DD_THB_WRITABLE_FLAG (1 << 31)
typedef enum { typedef enum {
DD_CMD_SEEK_READ = 0x01, DD_CMD_SEEK_READ = 0x01,
@ -100,7 +103,7 @@ static uint16_t dd_track_head_block (void) {
return (track | head | block); 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; uint32_t tmp;
sd_disk_info_t info = p.sd_disk_info[p.sd_current_disk]; sd_disk_info_t info = p.sd_disk_info[p.sd_current_disk];
if (info.thb_table_address == 0xFFFFFFFF) { 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))); 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)); fpga_mem_read(thb_entry_address, sizeof(uint32_t), (uint8_t *) (&tmp));
uint32_t start_offset = SWAP32(tmp); uint32_t start_offset = SWAP32(tmp);
if (start_offset == 0xFFFFFFFF) { if (start_offset == DD_THB_UNMAPPED) {
return 0; 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); 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 block_length = ((p.sector_info.sector_size + 1) * DD_BLOCK_DATA_SECTORS_NUM);
uint32_t end_offset = ((start_offset + block_length) - 1); 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; uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS;
if (p.sd_mode) { if (p.sd_mode) {
uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE]; 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); bool error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_read_sectors);
dd_set_block_ready(!error); dd_set_block_ready(!error);
} else { } else {
@ -152,7 +159,7 @@ static bool dd_block_write_request (void) {
uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS; uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS;
if (p.sd_mode) { if (p.sd_mode) {
uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE]; 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); bool error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_write_sectors);
dd_set_block_ready(!error); dd_set_block_ready(!error);
} else { } else {
@ -244,7 +251,7 @@ void dd_set_sd_mode (bool value) {
p.sd_mode = 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; sd_disk_info_t info;
length /= sizeof(info); length /= sizeof(info);
p.sd_current_disk = 0; p.sd_current_disk = 0;
@ -289,7 +296,7 @@ void dd_init (void) {
p.drive_type = DD_DRIVE_TYPE_RETAIL; p.drive_type = DD_DRIVE_TYPE_RETAIL;
p.sd_mode = false; p.sd_mode = false;
p.sd_current_disk = 0; p.sd_current_disk = 0;
dd_set_sd_info(0, 0); dd_set_disk_mapping(0, 0);
} }
void dd_process (void) { void dd_process (void) {

View File

@ -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_set_disk_state (dd_disk_state_t state);
bool dd_get_sd_mode (void); bool dd_get_sd_mode (void);
void dd_set_sd_mode (bool value); 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_handle_button (void);
void dd_init (void); void dd_init (void);
void dd_process (void); void dd_process (void);

View File

@ -58,7 +58,7 @@ typedef enum {
} fpga_reg_t; } 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 SWAP16(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8))
#define SWAP32(x) (((x) & 0xFF) << 24 | ((x) & 0xFF00) << 8 | ((x) & 0xFF0000) >> 8 | ((x) & 0xFF000000) >> 24) #define SWAP32(x) (((x) & 0xFF) << 24 | ((x) & 0xFF00) << 8 | ((x) & 0xFF0000) >> 8 | ((x) & 0xFF000000) >> 24)