diff --git a/fxcp_hh2.ld.c b/fxcp_hh2.ld.c index 8403219..6f19dad 100644 --- a/fxcp_hh2.ld.c +++ b/fxcp_hh2.ld.c @@ -8,14 +8,19 @@ ENTRY(_start_header) MEMORY { - /* Everything mixed together loaded as one */ - ram (rwx): o = 0x8cff0000, l = 61184 /* 64k - 0x1100 */ + /* VRAM backup - our main fixed area to load code, size 320x528x2 */ + ram (rwx): o = 0x8c052800, l = 337920 + /* End-of-RAM area, 64 kB are safe to use according to experience */ + eram (rwx): o = 0x8cff0000, l = 61184 /* 64k - 0x1100 */ /* Space for the vbr */ vbr (rwx): o = 0x8cffef00, l = 0x1100 /* On-chip IL memory */ ilram (rwx): o = 0xe5200000, l = 4k /* On-chip X and Y memory */ xyram (rwx): o = 0xe500e000, l = 16k + /* Flat binary space, used to have everything in the correct order in the + binary. This is just for the bin file layout. */ + bin (rwx): o = 0x00000000, l = 1M } SECTIONS @@ -34,11 +39,17 @@ SECTIONS - Entry function (.text.entry) - Compiler-provided constructors (.ctors) and destructors (.dtors) - All text from .text and .text.* (including user code) */ - .text : { + .hh2 : { KEEP(*(.hh2.header)) KEEP(*(.hh2.info)) KEEP(*(.hh2.stage2)) + . = ALIGN(16); + } > eram AT> bin + _gint_hh2_stage2_offset = SIZEOF(.hh2); + _gint_hh2_stage2_load = ORIGIN(ram); + + .text : { *(.text.entry) _bctors = . ; @@ -49,42 +60,44 @@ SECTIONS *(.dtors .dtors.*) _edtors = . ; + . = ALIGN(0x10); _gint_exch_start = . ; *(.gint.exch) _gint_exch_size = ABSOLUTE(. - _gint_exch_start); + . = ALIGN(0x10); _gint_tlbh_start = . ; *(.gint.tlbh) _gint_tlbh_size = ABSOLUTE(. - _gint_tlbh_start); *(.text .text.*) - } > ram + } > ram AT> bin /* gint's interrupt handler blocks (.gint.blocks) Although gint's blocks end up in VBR space, they are relocated at startup by the library/drivers, so we store them here for now */ - .gint.blocks : { + .gint.blocks ALIGN(4) : ALIGN(4) { KEEP(*(.gint.blocks)); - } > ram + } > ram AT> bin /* Exposed driver interfaces (.gint.drivers) The driver information is required to start and configure the driver, even if the symbols are not referenced */ - .gint.drivers : { + .gint.drivers ALIGN(4) : ALIGN(4) { _gint_drivers = . ; KEEP(*(SORT_BY_NAME(.gint.drivers.*))); _gint_drivers_end = . ; - } > ram + } > ram AT> bin /* Read-only data going to ROM: - Resources or assets from fxconv or similar converters - Data marked read-only by the compiler (.rodata and .rodata.*) */ - .rodata : SUBALIGN(4) { + .rodata ALIGN(4) : ALIGN(4) SUBALIGN(4) { /* Put these first, they need to be 4-aligned */ *(.rodata.4) *(.rodata .rodata.*) - } > ram + } > ram AT> bin @@ -92,8 +105,6 @@ SECTIONS ** RAM sections */ - . = ALIGN(16); /* No effect? */ - /* Read-write data sections going to RAM (.data and .data.*) */ .data ALIGN(4) : ALIGN(4) { _ldata = LOADADDR(.data); @@ -106,13 +117,13 @@ SECTIONS *(.gint.mappedrel) . = ALIGN(16); - } > ram + } > ram AT> bin /* Read-write data sub-aligned to 4 bytes (mainly from fxconv) */ - .data.4 : SUBALIGN(4) { + .data.4 ALIGN(4) : ALIGN(4) SUBALIGN(4) { *(.data.4) . = ALIGN(16); - } > ram + } > ram AT> bin _sdata = SIZEOF(.data) + SIZEOF(.data.4); @@ -120,23 +131,27 @@ SECTIONS . = ORIGIN(ilram); .ilram ALIGN(4) : ALIGN(4) { - _lilram = LOADADDR(.ilram); + _lilram = ABSOLUTE(LOADADDR(.ilram) + ORIGIN(ram)); _rilram = . ; *(.ilram) . = ALIGN(16); - } > ilram AT> ram + } > ilram AT> bin . = ORIGIN(xyram); .xyram ALIGN(4) : ALIGN(4) { - _lxyram = LOADADDR(.xyram); + _lxyram = ABSOLUTE(LOADADDR(.xyram) + ORIGIN(ram)); _rxyram = . ; *(.xram .yram .xyram) . = ALIGN(16); - } > xyram AT> ram + + } > xyram AT> bin + + /* .text and .xyram are the first and last section in the stage-2 load. */ + _gint_hh2_stage2_size = LOADADDR(.xyram) + SIZEOF(.xyram) - LOADADDR(.text); _silram = SIZEOF(.ilram); _sxyram = SIZEOF(.xyram); @@ -171,8 +186,6 @@ SECTIONS _sgbss = SIZEOF(.gint.bss); - - /* ** Unused sections */ diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index eec13fb..47fe93e 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -121,6 +121,7 @@ void kinit(void) /* Allocate VRAMs, which is important for panic screens */ extern bool dvram_init(void); + // TODO: Cannot _Exit() yet, the gint_exitbuf isn't setup! if(!dvram_init()) abort(); diff --git a/src/kernel/start.S b/src/kernel/start.S index facb300..ecbc009 100644 --- a/src/kernel/start.S +++ b/src/kernel/start.S @@ -34,7 +34,7 @@ _start_header: jmp @r0 nop /* Offset to hardcoded filename, used to patch binary after linking */ - .word (.stage2_filename - _start_header) + .word .stage2_filename /* Address of stage-2 */ 1: .long _stage2 /* Stage-1 load address at end of RAM (specified in linker script) */ @@ -48,14 +48,72 @@ _start_header: .align 2 _stage2: - /* No-op load */ + mov.l r8, @-r15 + sts.l pr, @-r15 + + /* Open the binary file in read mode */ + mov.l .open, r1 + mov.l .path, r4 + jsr @r1 + mov #1, r5 /* OPEN_READ */ + + cmp/pz r0 + bf .end + mov r0, r8 + + /* Seek to required offset */ + mov.l .lseek, r1 + mov r8, r4 + mov.l .off, r5 + jsr @r1 + mov #0, r6 /* SEEK_SET */ + + /* Load the binary */ + mov.l .read, r1 + mov.l .load, r5 + mov.l .size, r6 + jsr @r1 + mov r8, r4 + + /* Close the file regardless of read result */ + mov.l r0, @-r15 + mov.l .close, r1 + jsr @r1 + mov r8, r4 + + mov.l .size, r1 + mov.l @r15+, r0 + cmp/eq r0, r1 + bf .end + + lds.l @r15+, pr mov.l 1f, r0 jmp @r0 - nop - nop + mov.l @r15+, r8 + +.end: + lds.l @r15+, pr + rts + mov.l @r15+, r8 + +.balign 4 1: .long _start + /* Filepath */ +.path: .long .stage2_path + /* Offset of segment in file */ +.off: .long _gint_hh2_stage2_offset + /* Segment size */ +.size: .long _gint_hh2_stage2_size + /* Load address */ +.load: .long _gint_hh2_stage2_load + +.open: .long 0x80057854 +.lseek: .long 0x80057a96 +.read: .long 0x800578a2 +.close: .long 0x80057912 + .align 2 .zero 2 .stage2_path: