Add IDE boot rom

This commit is contained in:
Matt Harlum 2023-02-23 10:38:00 +00:00
parent fae07c034a
commit 061e307e06
8 changed files with 571 additions and 0 deletions

5
iderom/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
obj/**
at
*.rom
**/*.o
**/*.out

37
iderom/Makefile Normal file
View File

@ -0,0 +1,37 @@
PROGRAM=cider.rom
INCLUDE=/opt/amiga/m68k-amigaos/ndk-include
AS=vasmm68k_mot
ASFLAGS=-Fhunk -I$(INCLUDE) -quiet -align
LINKER=vlink
LINKFLAGS=-brawbin1 -s -sc -sd -mrel
OBJDIR=obj
.PHONY: all clean rom
SRCS = bootldr.S
OBJS = $(SRCS:%.S=$(OBJDIR)/%.o)
all: $(PROGRAM)
$(OBJDIR)/mungerom: mungerom.c
@mkdir -p $(OBJDIR)
$(CC) $< -Wall -o $@
$(OBJDIR)/%.o: %.S
@mkdir -p $(OBJDIR)
$(AS) $(ASFLAGS) -o $@ $<
$(OBJDIR)/bootldr: $(OBJDIR)/bootldr.o
$(LINKER) $(LINKFLAGS) -o $@ $<
$(OBJDIR)/bootnibbles: $(OBJDIR)/bootldr $(OBJDIR)/mungerom
@mkdir -p $(OBJDIR)
./obj/mungerom
$(PROGRAM): $(OBJDIR)/bootnibbles $(OBJDIR)/assets.o
$(LINKER) $(LINKFLAGS) -Trom.ld -o $@ $(OBJDIR)/assets.o
clean:
rm -f $(OBJDIR)/*
rm -f $(PROGRAM)
rm -f mungerom

3
iderom/README.md Normal file
View File

@ -0,0 +1,3 @@
## ide boot rom
WIP for the IDE driver, currently just loads Oktapus driver from ROM

5
iderom/assets.S Normal file
View File

@ -0,0 +1,5 @@
section BOOTLDR
incbin "obj/bootnibbles"
section DEVICE
incbin "cider.device"

147
iderom/bootldr.S Normal file
View File

@ -0,0 +1,147 @@
; Based on rom.S from Open Source A4091.device by Stefan Reinauer & Chris Hooper
include libraries/configvars.i
include exec/resident.i
include lvo/exec_lib.i
VERSION = 0
REVISION = 1
ROMOFFSET = $2000
******* DiagStart **************************************************
DiagStart
; This is the DiagArea structure whose relative offset from
; your board base appears as the Init Diag vector in your
; autoconfig ID information. This structure is designed
; to use all relative pointers (no patching needed).
dc.b DAC_NIBBLEWIDE+DAC_CONFIGTIME ; da_Config
dc.b 0 ; da_Flags
dc.w EndCopy-DiagStart ; da_Size
dc.w DiagEntry-DiagStart ; da_DiagPoint
dc.w BootEntry-DiagStart ; da_BootPoint
dc.w DevName-DiagStart ; da_Name
dc.w 0 ; da_Reserved01
dc.w 0 ; da_Reserved02
******* DiagEntry **************************************************
**********************************************************************
*
* success = DiagEntry(BoardBase,DiagCopy, configDev)
* d0 a0 a2 a3
*
* Called by expansion architecture to relocate any pointers
* in the copied diagnostic area. We will patch the romtag.
* If you have pre-coded your MakeDosNode packet, BootNode,
* or device initialization structures, they would also need
* to be within this copy area, and patched by this routine.
*
**********************************************************************
* These are the calling conventions for the Diag routine
*
* A7 -- points to at least 2K of stack
* A6 -- ExecBase
* A5 -- ExpansionBase
* A3 -- your board's ConfigDev structure
* A2 -- Base of diag/init area that was copied
* A0 -- Base of your board
*
* The Diag routine shall return a non-zero value in D0 for success.
* If this value is NULL, then the diag/init area that was copied
* will be returned to the free memory pool.
*
DiagEntry
movem.l d2-d7/a2-a6,-(sp)
; Patch up Romtag Resident Structure in memory
lea.l Romtag(pc),a4 ; find Romtag in memory
move.l a4,RT_MATCHTAG(a4) ; pointer to itself
lea.l EndCopy(pc),a1
move.l a1,RT_ENDSKIP(a4)
lea.l DevName(pc),a1
move.l a1,RT_NAME(a4)
lea.l IdString(pc),a1
move.l a1,RT_IDSTRING(a4)
move.l #ROMOFFSET,d0
bsr _relocate
tst.l d0
bne.s .ok
.err
******* Show checkered purple failure screen **************************
movem.l d2-d3,-(sp)
move.w #$0020,d2
.fc1
move.w #$ffff,d3
.fc2
move.w #$0000,$dff180 ; black
move.w #$0f0c,$dff180 ; purple
dbra d3,.fc2
dbra d2,.fc1
movem.l (sp)+,d2-d3
******* End checkered purple failure screen **************************
moveq.l #0,d0
movem.l (sp)+,d2-d7/a2-a6
rts
.ok
move.l #$1000,d3
move.l d0,a2
.findrt cmpi.w #$4AFC,(a2)
beq.s .found
addq.l #2,a2
dbra d3,.findrt
bra.s .err
.found lea.l Romtag(pc),a4 ; find Romtag in memory
move.l RT_INIT(a2),d0
move.l d0,RT_INIT(a4)
moveq.l #1,d0 ; indicate "success"
.done
movem.l (sp)+,d2-d7/a2-a6
rts
******* BootEntry **************************************************
**********************************************************************
BootEntry
lea DosName(PC),a1 ; 'dos.library',0
jsr _LVOFindResident(a6) ; find the DOS resident tag
tst.l d0
beq.s .BadBoot
move.l d0,a0 ; in order to bootstrap
move.l RT_INIT(A0),a0 ; set vector to DOS INIT
jsr (a0) ; and initialize DOS
.BadBoot
rts
******* Resident Structure *****************************************
**********************************************************************
Romtag
dc.w RTC_MATCHWORD ; UWORD RT_MATCHWORD
dc.l 0 ; APTR RT_MATCHTAG
dc.l 0 ; APTR RT_ENDSKIP
dc.b RTF_COLDSTART ; UBYTE RT_FLAGS
dc.b VERSION ; UBYTE RT_VERSION
dc.b 0 ; UBYTE RT_TYPE
dc.b 0 ; BYTE RT_PRI
dc.l 0 ; APTR RT_NAME
dc.l 0 ; APTR RT_IDSTRING
dc.l 0 ; APTR RT_INIT
******* Strings referenced in Diag Copy area **************************
*************************************************************************
DevName
dc.b 'Oktagon',0 ; Name string
align 1
IdString
dc.b 'Oktagon',0
DosName
dc.b 'dos.library',0 ; DOS library name
align 1 ; word align
include reloc.S
EndCopy:

33
iderom/mungerom.c Normal file
View File

@ -0,0 +1,33 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
// Chop up the bootrom section into nibbles for Z2 nibblewise bootrom - Kick 1.3 and below don't support DAC_BYTEWIDE :(
// The device driver will be loaded bytewise by reloc
int main () {
FILE *fh = fopen("obj/bootldr","r");
char *src,*dst = NULL;
src = malloc(2048);
dst = malloc(4096);
int len = fread(src,1,2048,fh);
fclose(fh);
for (int i=0; i<len;i++) {
char hi = *(src+i) & 0xF0;
char lo = *(src+i) & 0x0F;
lo <<= 4;
dst[i<<1] = hi;
dst[(i<<1)+1] = lo;
}
fh = fopen("obj/bootnibbles","w");
fwrite(dst,1,len*2,fh);
fclose(fh);
free(src);
free(dst);
}

328
iderom/reloc.S Normal file
View File

@ -0,0 +1,328 @@
; reloc
; Modified from Open Source A4091.device reloc.S by Stefan Reinauer & Chris Hooper
INCLUDE "exec/memory.i"
INCLUDE "lvo/exec_lib.i"
NUM_ENTRIES EQU 5
; API:
; Z2 ROM access:
; a0: rombase
; d0: offset
; Memory (RAM) access:
; a0: pointer to binary
; d0: 0
public _relocate
_relocate
movem.l d1-d7/a0-a6,-(sp)
bsr InitHandle
; fetch file header
bsr RomFetch32
cmp.l #$3f3,d0 ; We only know hunk_hdr
bne .RelocateFail
; consume the header and remember number of hunks
bsr RomFetch32
bsr RomFetch32
move.l d0,d7 ; table size
subq.l #1,d7
move.l d7,d6 ; for HUNK_END
bsr RomFetch32
bsr RomFetch32
; Go through hunk header and allocate all segments
move.l 4,a6 ; execbase
move.l pHunks(pc),a2 ; segment pointers
lea.l 4*NUM_ENTRIES(a2),a3 ; segment lengths
.AllocateLoop
moveq.l #MEMF_PUBLIC,d1
bsr RomFetch32
lsl.l #2,d0
move.l d0,(a3)+ ; segment length
addq.l #8,d0 ; Add 8 for seglist overhead
jsr _LVOAllocMem(a6)
tst.l d0
beq.s .RelocateFail
addq.l #8,d0 ; Skip seglist overhead
move.l d0,(a2)+ ; segment pointer
dbra d7,.AllocateLoop
move.l pHunks(pc),a5
.HunkLoop
move.l (a5),a0 ; current hunk
bsr RomFetch32
cmp.l #$3e9,d0
beq .HunkCode
cmp.l #$3ea,d0
beq .HunkData
cmp.l #$3eb,d0
beq .HunkBSS
cmp.l #$3ec,d0
beq .HunkReloc32
cmp.l #$3fc,d0
beq .HunkReloc32Short
cmp.l #$3f7,d0
beq .HunkDRel32
cmp.l #$3f0,d0
beq .HunkSymbol
cmp.l #$3f2,d0
beq .HunkEnd
; We don't know this hunk
.RelocateFail
IFD HAVE_ERRNO
; Save hunk number in rErrno as error code
lea _rErrno(pc),a0
move.l d0,(a0)
ENDIF
bsr .RelocateCleanup
moveq.l #0,d0 ; NULL = Failure
movem.l (sp)+,d1-d7/a0-a6
rts
; ---------------------
.HunkData
.HunkCode
bsr RomFetch32
move.l d0,d7
subq.l #1,d7
.CopyHunk
bsr RomFetch32
move.l d0,(a0)+
dbra d7,.CopyHunk
bra .HunkLoop
; ---------------------
.HunkBSS
bsr RomFetch32
move.l d0,d7
subq.l #1,d7
; hunk address in a0
.ClearBSS
move.l #$0,(a0)+
dbra d7,.ClearBSS
bra .HunkLoop
; ---------------------
.HunkReloc32
bsr RomFetch32
tst.l d0 ; if len is zero the reloc32 block is done
beq .HunkLoop
move.l d0,d1 ; len ; number of offsets for a given hunk
subq.l #1,d1 ; for dbra
bsr RomFetch32
move.l d0,d2 ; num ; number of the hunk the offsets are to point into
lsl.l #2,d2 ; *4 ; offset from Hunks
move.l pHunks(pc),a2
add.l d2,a2 ; hunk number num
move.l (a2),d3 ; base address of hunk
.Reloc32Tight
bsr RomFetch32
; get baseaddr + d0, add d3 to the data there.
move.l a0,a4
add.l d0,a4
add.l d3,(a4)
dbra d1,.Reloc32Tight
bra .HunkReloc32
; ---------------------
.HunkDRel32
.HunkReloc32Short
bsr RomFetch16
tst.l d0 ; if len is zero the reloc32 block is done
beq .HunkLoopPrep
move.l d0,d1 ; len ; number of offsets for a given hunk
subq.l #1,d1 ; for dbra
bsr RomFetch16
move.l d0,d2 ; num ; number of the hunk the offsets are to point into
lsl.l #2,d2 ; *4 ; offset from Hunks
move.l pHunks(pc),a2
add.l d2,a2 ; hunk number num
move.l (a2),d3 ; base address of hunk
.Reloc32ShortTight
bsr RomFetch16
; get baseaddr + d0, add d3 to the data there.
move.l a0,a4
add.l d0,a4
add.l d3,(a4)
dbra d1,.Reloc32ShortTight
bra .HunkReloc32Short
.HunkLoopPrep
lea ReadHandle(pc),a2
move.l (a2),d0 ; align pointer to longword
addq.l #2,d0 ; in case we had an odd number
and.l #$fffffffc,d0 ; of relocations
move.l d0,(a2)
bra .HunkLoop
; ---------------------
.HunkSymbol
bsr RomFetch32
tst.l d0
beq .HunkLoop
move.l d0,d7
.SkipSymbol
bsr RomFetch32
dbra d7,.SkipSymbol
bra .HunkSymbol
; ---------------------
.HunkEnd
addq.l #4,a5
dbra d6,.HunkLoop
IFD HAVE_ERRNO
lea _rErrno(pc),a0
move.l #0,(a0)
ENDIF
bsr.s CreateSegList
move.l pHunks(pc),a0
move.l (a0),d2
subq.l #4,d2
bsr.s .RelocateCleanup
move.l d2,d0
movem.l (sp)+,d1-d7/a0-a6
rts
.RelocateCleanup
move.l pHunks(pc),a1
moveq.l #(8*NUM_ENTRIES),d0
jsr _LVOFreeMem(a6)
rts
; ---------------------
; +--------------------+
; | seg length (longs) | <-- = pHunks[x+NUM_ENTRIES]
; +--------------------+ <-- seglist returned
; | bptr to next seg | <-- = pHunks[x+1]
; +--------------------+ <-- pHunks[x] points here
; | segment data (also |
; | first entry point) |
; |/\/\/\/\/\/\/\/\/\/\|
; pHunks -+ Hunk Pointers Hunk Lengths
; | +--+--+--+--+ +--+--+--+--+
; +->| | | | 0| | | | | 0|
; +--+--+--+--+ +--+--+--+--+
CreateSegList:
move.l pHunks(pc),a0
.NextSeg
move.l (a0),a1 ; Hunks[x]
move.l 4*NUM_ENTRIES(a0),d0 ; length of current hunk
addq.l #8,d0 ; add header size
lsr.l #2,d0 ; MKBADDR
move.l d0,-8(a1) ; write seg size
addq.l #4,a0
move.l (a0),d0 ; next hunk
tst.l d0 ; hunk addr zero?
beq .SegListDone ; we're done
subq.l #4,d0 ; else: point to linked list
lsr.l #2,d0 ; MKBADDR
move.l d0,-4(a1) ; write BPTR to next hunk
bra.s .NextSeg
.SegListDone
move.l d0,-4(a1) ; terminate seglist
rts
; ---------------------
; data = RomFetch32(void)
; d0
RomFetch16
moveq #1,d0
bra.s RomFetch
RomFetch32
moveq #3,d0
RomFetch
movem.l a0-a1/d1-d3,-(sp)
lea ReadHandle(pc),a1
move.l (a1),a0
tst.l 4(a1) ; access type ZorroII?
bne.s .RomFetchZ2
cmp.b #3,d0
bne.b .RomFetchWord
move.l (a0)+,d0 ; access type is memory
bra.s .RomFetchDone
.RomFetchWord
move.w (a0)+,d0
bra.s .RomFetchDone
.RomFetchZ2 ; access type is ZorroII
move.l d0,d3
.nextbyte
lsl.l #8,d0
move.b (a0),d0
addq #2,a0
dbra d3,.nextbyte
.RomFetchDone
move.l a0,(a1)
movem.l (sp)+,a0-a1/d1-d3
rts
InitHandle
; initialize readhandle to beginning of device driver
; ROM_OFFSET needs to be multiplied by 4 because of the
; nibble mapped nature of the AutoConfig ROM.
; ROM_ADDRESS is passed in a0
; ROM_OFFSET is passed in d0
;lsl.l #2,d0
add.l d0,a0
lea ReadHandle(pc),a1
move.l a0,(a1) ; memory location passed in a0
move.l d0,4(a1) ; Set access type: 0 = memory, Z2 otherwise
moveq.l #(8*NUM_ENTRIES),d0
move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
jsr _LVOAllocMem(a6)
lea pHunks(pc),a1
move.l d0,(a1)
rts
ReadHandle
dc.l 0 ; Current address
dc.l 0 ; 0=memory, otherwise Z2
pHunks
dc.l 0
IFD HAVE_ERRNO
public _rErrno
_rErrno
dc.l 0
ENDIF
CODE

13
iderom/rom.ld Normal file
View File

@ -0,0 +1,13 @@
SECTIONS {
rom = .;
.bootldr : {
*(BOOTLDR)
}
.device 0x1000 : {
*(DEVICE)
}
.fill : {
FILL8(0xFF);
RESERVE(0x8000-.);
} =0xffff
}