From 92e53fd3e50cdbee51d0004477332a38a10b416c Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Thu, 7 Dec 2023 21:43:33 +0100 Subject: [PATCH] open source IPL3 support --- docker_build.sh | 2 +- sw/bootloader/Makefile | 24 +++++++++------- sw/bootloader/N64.ld | 21 ++++---------- sw/bootloader/src/boot.c | 16 ++++++++++- sw/bootloader/src/display.c | 3 +- sw/bootloader/src/init.c | 11 ++++++-- sw/bootloader/src/init.h | 18 +++++++++++- sw/bootloader/src/io.c | 13 --------- sw/bootloader/src/io.h | 49 -------------------------------- sw/bootloader/src/main.c | 2 ++ sw/bootloader/src/menu.c | 39 ------------------------- sw/bootloader/src/startup.S | 46 ++---------------------------- sw/bootloader/src/test.c | 3 +- sw/bootloader/tools/finalize.py | 50 --------------------------------- 14 files changed, 70 insertions(+), 227 deletions(-) delete mode 100644 sw/bootloader/tools/finalize.py diff --git a/docker_build.sh b/docker_build.sh index 32ae7f9..3fb9ace 100755 --- a/docker_build.sh +++ b/docker_build.sh @@ -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 diff --git a/sw/bootloader/Makefile b/sw/bootloader/Makefile index 8d59328..74087ff 100644 --- a/sw/bootloader/Makefile +++ b/sw/bootloader/Makefile @@ -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)/* diff --git a/sw/bootloader/N64.ld b/sw/bootloader/N64.ld index 5ed4b5d..802a781 100644 --- a/sw/bootloader/N64.ld +++ b/sw/bootloader/N64.ld @@ -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.*) } diff --git a/sw/bootloader/src/boot.c b/sw/bootloader/src/boot.c index 6315d4e..b4f6346 100644 --- a/sw/bootloader/src/boot.c +++ b/sw/bootloader/src/boot.c @@ -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) { diff --git a/sw/bootloader/src/display.c b/sw/bootloader/src/display.c index 5a49b05..0ef803b 100644 --- a/sw/bootloader/src/display.c +++ b/sw/bootloader/src/display.c @@ -2,6 +2,7 @@ #include #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); diff --git a/sw/bootloader/src/init.c b/sw/bootloader/src/init.c index 98d6e81..15d1430 100644 --- a/sw/bootloader/src/init.c +++ b/sw/bootloader/src/init.c @@ -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(); diff --git a/sw/bootloader/src/init.h b/sw/bootloader/src/init.h index d6c2dc2..e15411b 100644 --- a/sw/bootloader/src/init.h +++ b/sw/bootloader/src/init.h @@ -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); diff --git a/sw/bootloader/src/io.c b/sw/bootloader/src/io.c index 9ef6264..bb20e99 100644 --- a/sw/bootloader/src/io.c +++ b/sw/bootloader/src/io.c @@ -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()); -} diff --git a/sw/bootloader/src/io.h b/sw/bootloader/src/io.h index 30b3019..d90ef04 100644 --- a/sw/bootloader/src/io.h +++ b/sw/bootloader/src/io.h @@ -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); diff --git a/sw/bootloader/src/main.c b/sw/bootloader/src/main.c index e65dc00..d437bdf 100644 --- a/sw/bootloader/src/main.c +++ b/sw/bootloader/src/main.c @@ -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: diff --git a/sw/bootloader/src/menu.c b/sw/bootloader/src/menu.c index f7ce23f..89daf32 100644 --- a/sw/bootloader/src/menu.c +++ b/sw/bootloader/src/menu.c @@ -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"); } diff --git a/sw/bootloader/src/startup.S b/sw/bootloader/src/startup.S index c4ce0c2..5d211de 100644 --- a/sw/bootloader/src/startup.S +++ b/sw/bootloader/src/startup.S @@ -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 diff --git a/sw/bootloader/src/test.c b/sw/bootloader/src/test.c index 7a0d679..bba6629 100644 --- a/sw/bootloader/src/test.c +++ b/sw/bootloader/src/test.c @@ -2,6 +2,7 @@ #include #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; } diff --git a/sw/bootloader/tools/finalize.py b/sw/bootloader/tools/finalize.py deleted file mode 100644 index 4fa675d..0000000 --- a/sw/bootloader/tools/finalize.py +++ /dev/null @@ -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)