open source IPL3 support

This commit is contained in:
Mateusz Faderewski 2023-12-07 21:43:33 +01:00
parent e91adcdb59
commit 92e53fd3e5
14 changed files with 70 additions and 227 deletions

View File

@ -1,6 +1,6 @@
#!/bin/bash
BUILDER_IMAGE="ghcr.io/polprzewodnikowy/sc64env:v1.6"
BUILDER_IMAGE="ghcr.io/polprzewodnikowy/sc64env:v1.7"
pushd $(dirname $0) > /dev/null

View File

@ -1,9 +1,14 @@
TOOLCHAIN = $(N64_INST)/bin/mips64-elf-
N64_BINDIR = $(N64_INST)/bin
TOOLCHAIN = $(N64_BINDIR)/mips64-elf-
CC = $(TOOLCHAIN)gcc
CXX = $(TOOLCHAIN)g++
OBJCOPY = $(TOOLCHAIN)objcopy
OBJDUMP = $(TOOLCHAIN)objdump
STRIP = $(TOOLCHAIN)strip
SIZE = $(TOOLCHAIN)size
N64_ELFCOMPRESS = $(N64_BINDIR)/n64elfcompress
N64_TOOL = $(N64_BINDIR)/n64tool
PYTHON = python3
FLAGS = -march=vr4300 -mtune=vr4300 $(USER_FLAGS)
@ -69,19 +74,18 @@ $(BUILD_DIR)/%.asset.o: $(BUILD_DIR)/%.asset $(ASSET_DIR)/assets.S
$(BUILD_DIR)/bootloader.elf: $(OBJS) N64.ld
$(CXX) $(FLAGS) $(LDFLAGS) -TN64.ld $(OBJS) -o $@
@$(OBJDUMP) -S $@ > $(BUILD_DIR)/bootloader.lst
$(BUILD_DIR)/bootloader.bin: $(BUILD_DIR)/bootloader.elf tools/finalize.py
@$(OBJCOPY) -O binary $< $@
@$(PYTHON) tools/finalize.py $@ > /dev/null
print_size: $(BUILD_DIR)/bootloader.elf
@echo 'Size of modules:'
@$(SIZE) -B -d -t --common $(OBJS)
@echo 'Size of bootloader:'
@$(SIZE) -B -d $<
@$(SIZE) -B -d $@
@$(OBJDUMP) -S $@ > $(BUILD_DIR)/bootloader.lst
all: $(BUILD_DIR)/bootloader.bin print_size
$(BUILD_DIR)/bootloader.bin: $(BUILD_DIR)/bootloader.elf
@$(STRIP) -s $<
@$(N64_ELFCOMPRESS) -c 2 -o $(dir $<) $<
@$(N64_TOOL) --title "SC64 bootloader" --output $@ --align 256 $<
all: $(BUILD_DIR)/bootloader.bin
clean:
@rm -rf ./$(BUILD_DIR)/*

View File

@ -1,7 +1,6 @@
MEMORY {
ram (rwx) : org = 0x80000400, len = 1M
framebuffer (rw) : org = 0x8026A000, len = 600k
ram (rwx) : org = 0x80300000, len = 1M
rom (r) : org = 0xB0000000, len = 1028k
}
ENTRY(entry_handler)
@ -10,16 +9,6 @@ __exception_stack_size = 8k;
__stack_size = 16k;
SECTIONS {
.boot : {
KEEP(*(.text.rom_header));
KEEP(*(.text.ipl3));
. = ALIGN(4k);
} > rom
.framebuffer (NOLOAD) : SUBALIGN(64) {
*(.framebuffer .framebuffer.*)
} > framebuffer
.text : SUBALIGN(8) {
*(.text.entry_handler)
*(.text .text.* .gnu.linkonce.t.*)
@ -30,17 +19,15 @@ SECTIONS {
_gp = . + 0x8000;
*(.sdata .sdata.* .gnu.linkonce.s.*)
*(.lit8 .lit4)
} > ram AT > rom
} > ram
.bss : {
. = ALIGN(8);
_sbss = .;
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon .scommon.*)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(8);
_ebss = .;
} > ram
_sheap = .;
@ -53,6 +40,10 @@ SECTIONS {
. += __stack_size;
_sp = .;
.framebuffer (NOLOAD) : SUBALIGN(64) {
*(.framebuffer .framebuffer.*)
} > framebuffer
/DISCARD/ : {
*(.MIPS.*)
}

View File

@ -1,5 +1,6 @@
#include "boot.h"
#include "cic.h"
#include "init.h"
#include "io.h"
#include "vr4300.h"
@ -29,7 +30,20 @@ static void boot_detect_cic_seed (boot_params_t *params) {
void boot (boot_params_t *params) {
if (params->tv_type == BOOT_TV_TYPE_PASSTHROUGH) {
params->tv_type = OS_INFO->tv_type;
switch (__tv_type) {
case INIT_TV_TYPE_PAL:
params->tv_type = BOOT_TV_TYPE_PAL;
break;
case INIT_TV_TYPE_NTSC:
params->tv_type = BOOT_TV_TYPE_NTSC;
break;
case INIT_TV_TYPE_MPAL:
params->tv_type = BOOT_TV_TYPE_MPAL;
break;
default:
params->tv_type = BOOT_TV_TYPE_NTSC;
break;
}
}
if (params->detect_cic_seed) {

View File

@ -2,6 +2,7 @@
#include <stdio.h>
#include "display.h"
#include "font.h"
#include "init.h"
#include "io.h"
@ -163,7 +164,7 @@ void display_init (uint32_t *background) {
if (!vi_configured) {
vi_configured = true;
const vi_regs_t *cfg = &vi_config[OS_INFO->tv_type];
const vi_regs_t *cfg = &vi_config[__tv_type];
cpu_io_write(&VI->MADDR, (uint32_t) (display_framebuffer));
cpu_io_write(&VI->H_WIDTH, cfg->H_WIDTH);

View File

@ -1,15 +1,20 @@
#include "error.h"
#include "exception.h"
#include "init.h"
#include "io.h"
#include "sc64.h"
#include "test.h"
void init (void) {
init_tv_type_t __tv_type;
init_reset_type_t __reset_type;
void init (init_tv_type_t tv_type, init_reset_type_t reset_type) {
sc64_error_t error;
uint32_t pifram = si_io_read((io32_t *) (PIFRAM_STATUS));
si_io_write((io32_t *) (PIFRAM_STATUS), pifram | PIFRAM_TERMINATE_BOOT);
__tv_type = tv_type;
__reset_type = reset_type;
exception_install();

View File

@ -2,7 +2,23 @@
#define INIT_H__
void init (void);
typedef enum {
INIT_TV_TYPE_PAL = 0,
INIT_TV_TYPE_NTSC = 1,
INIT_TV_TYPE_MPAL = 2,
} init_tv_type_t;
typedef enum {
INIT_RESET_TYPE_COLD = 0,
INIT_RESET_TYPE_WARM = 1,
} init_reset_type_t;
extern init_tv_type_t __tv_type;
extern init_reset_type_t __reset_type;
void init (init_tv_type_t tv_type, init_reset_type_t reset_type);
void deinit (void);

View File

@ -95,16 +95,3 @@ void pi_dma_write (io32_t *address, void *buffer, size_t length) {
cpu_io_write(&PI->RDMA, length - 1);
while (pi_busy());
}
uint32_t si_busy (void) {
return (cpu_io_read(&SI->SR) & (SI_SR_IO_BUSY | SI_SR_DMA_BUSY));
}
uint32_t si_io_read (io32_t *address) {
return cpu_io_read(address);
}
void si_io_write (io32_t *address, uint32_t value) {
cpu_io_write(address, value);
while (si_busy());
}

View File

@ -202,26 +202,6 @@ typedef struct {
#define PI_SR_CLR_INTR (1 << 1)
typedef struct {
io32_t MADDR;
io32_t RDMA;
io32_t __reserved_1;
io32_t __reserved_2;
io32_t WDMA;
io32_t __reserved_3;
io32_t SR;
} si_regs_t;
#define SI_BASE (0x04800000UL)
#define SI ((si_regs_t *) SI_BASE)
#define SI_SR_DMA_BUSY (1 << 0)
#define SI_SR_IO_BUSY (1 << 1)
#define SI_SR_DMA_ERROR (1 << 3)
#define SI_SR_INTERRUPT (1 << 12)
#define SI_SR_CLEAR_INTERRUPT (0)
#define ROM_DDIPL_BASE (0x06000000UL)
#define ROM_DDIPL ((io32_t *) ROM_DDIPL_BASE)
@ -230,32 +210,6 @@ typedef struct {
#define ROM_CART ((io32_t *) ROM_CART_BASE)
#define PIFRAM_BASE (0x1FC007C0UL)
#define PIFRAM ((io8_t *) PIFRAM_BASE)
#define PIFRAM_STATUS (&PIFRAM[0x3C])
#define PIFRAM_TERMINATE_BOOT (1 << 3)
typedef struct {
uint32_t tv_type;
uint32_t device_type;
uint32_t device_base;
uint32_t reset_type;
uint32_t cic_id;
uint32_t version;
uint32_t mem_size;
uint8_t app_nmi_buffer[64];
} os_info_t;
#define OS_INFO_BASE (0x80000300UL)
#define OS_INFO ((os_info_t *) OS_INFO_BASE)
#define OS_INFO_RESET_TYPE_COLD (0)
#define OS_INFO_RESET_TYPE_NMI (1)
uint32_t c0_count (void);
void delay_ms (int ms);
uint32_t cpu_io_read (io32_t *address);
@ -266,9 +220,6 @@ uint32_t pi_io_read (io32_t *address);
void pi_io_write (io32_t *address, uint32_t value);
void pi_dma_read (io32_t *address, void *buffer, size_t length);
void pi_dma_write (io32_t *address, void *buffer, size_t length);
uint32_t si_busy (void);
uint32_t si_io_read (io32_t *address);
void si_io_write (io32_t *address, uint32_t value);
void cache_data_hit_writeback_invalidate (void *address, size_t length);
void cache_data_hit_writeback (void *address, size_t length);
void cache_inst_hit_invalidate (void *address, size_t length);

View File

@ -26,6 +26,8 @@ void main (void) {
menu_load();
boot_params.device_type = BOOT_DEVICE_TYPE_ROM;
boot_params.reset_type = BOOT_RESET_TYPE_NMI;
boot_params.cic_seed = 0x3F;
boot_params.detect_cic_seed = false;
break;
case BOOT_MODE_ROM:

View File

@ -6,7 +6,6 @@
#define ROM_ADDRESS (0x10000000)
#define FILL_SIZE (0x101000)
static const char *fatfs_error_codes[] = {
@ -45,43 +44,6 @@ static void fix_menu_file_size (FIL *fil) {
fil->obj.objsize = ALIGN(f_size(fil), FF_MAX_SS);
}
static void fill_remaining_menu_space (size_t menu_file_size) {
if (menu_file_size >= FILL_SIZE) {
return;
}
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 (void) {
sc64_error_t error;
@ -106,7 +68,6 @@ void menu_load (void) {
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");
}

View File

@ -1,39 +1,3 @@
#include "vr4300.h"
.section .text.rom_header, "a", %progbits
rom_header:
.type rom_header, %object
header_pi_config:
.word 0x80371240
header_clock_rate:
.word 0x0000000F
header_load_addr:
.word entry_handler
header_sdk_version:
.word 0x00000000
header_crc:
.fill 2, 4, 0
.org 0x20, 0x00
header_text_info:
.ascii "SC64 bootloader"
.org 0x40, 0x00
.section .text.ipl3, "ax", %progbits
ipl3:
.type ipl3, %function
.incbin "header", 0x40
.section .text.entry_handler, "ax", %progbits
entry_handler:
@ -43,13 +7,9 @@ entry_handler:
la $gp, _gp
la $sp, _sp
bss_init:
la $a0, _sbss
la $a1, _ebss
1:
sd $zero, 0($a0)
addiu $a0, 8
bltu $a0, $a1, 1b
lui $t0, 0xA400
lbu $a0, 9($t0) # TV type
lbu $a1, 10($t0) # Reset type
la $t0, init
jalr $t0

View File

@ -2,6 +2,7 @@
#include <stdlib.h>
#include "display.h"
#include "error.h"
#include "init.h"
#include "io.h"
#include "sc64.h"
#include "test.h"
@ -224,7 +225,7 @@ bool test_check (void) {
sc64_error_t error;
uint32_t button_state;
if (OS_INFO->reset_type != OS_INFO_RESET_TYPE_COLD) {
if (__reset_type == INIT_RESET_TYPE_WARM) {
return false;
}

View File

@ -1,50 +0,0 @@
#!/usr/bin/env python3
import subprocess
import sys
if __name__ == '__main__':
if (len(sys.argv) != 2):
print(f'Usage: python {sys.argv[0]} file_path')
sys.exit(1)
ALIGN = 1024
CHECKSUM_SIZE = 0x101000
bin_file = sys.argv[1]
try:
bin_data = b''
with open(bin_file, 'rb') as f:
bin_data = f.read()
pad_size = CHECKSUM_SIZE - len(bin_data)
if (pad_size > 0):
bin_data += b'\xFF' * pad_size
with open(bin_file, 'wb') as f:
f.write(bin_data)
subprocess.run(['chksum64', bin_file])
with open(bin_file, 'rb') as f:
bin_data = f.read()
bin_data = bin_data.strip(b'\xFF')
modulo = len(bin_data) % ALIGN
if (modulo > 0):
bin_data += b'\xFF' * (ALIGN - modulo)
with open(bin_file, 'wb') as f:
f.write(bin_data)
except FileNotFoundError as e:
print(f'Couldn\'t open file "{bin_file}" {e}')
sys.exit(2)
except Exception as e:
print(e)
sys.exit(3)