diff --git a/Makefile b/Makefile index ddd9252..278bdd3 100644 --- a/Makefile +++ b/Makefile @@ -237,6 +237,14 @@ AMIGA_ASM_SRCS = platform/amiga/startup.S endif AMIGA_ASM_OBJS = $(patsubst %.S,$(AMIGA_BUILD)/%.o,$(AMIGA_ASM_SRCS)) +# The resident/romtag object is linked directly into the handler right after +# startup.o, not archived into libodfs.a +ifeq ($(AMIGA_TARGET),os4) +AMIGA_RESIDENT_OBJ = +else +AMIGA_RESIDENT_OBJ = $(AMIGA_BUILD)/platform/amiga/resident.o +endif + HOST_LIB_SRCS = $(CORE_SRCS) $(HOST_SRCS) HOST_LIB_OBJS = $(patsubst %.c,$(HOST_BUILD)/%.o,$(HOST_LIB_SRCS)) HOST_LIB_DEPS = $(HOST_LIB_OBJS:.o=.d) @@ -593,10 +601,10 @@ $(AMIGA_TEST_TOOL): $(AMIGA_TEST_BUILD)/tests/amiga/test_handler.o # ---- Amiga handler ---- -$(HANDLER): $(AMIGA_ASM_OBJS) $(AMIGA_BUILD)/libodfs.a +$(HANDLER): $(AMIGA_ASM_OBJS) $(AMIGA_RESIDENT_OBJ) $(AMIGA_BUILD)/libodfs.a @mkdir -p $(@D) @echo " LINK $@" - @$(CC) $(LDFLAGS) $(HANDLER_LDFLAGS) -o $@ $(AMIGA_ASM_OBJS) -L$(AMIGA_BUILD) -lodfs $(HANDLER_LIBS) + @$(CC) $(LDFLAGS) $(HANDLER_LDFLAGS) -o $@ $(AMIGA_ASM_OBJS) $(AMIGA_RESIDENT_OBJ) -L$(AMIGA_BUILD) -lodfs $(HANDLER_LIBS) @echo " STRIP $@" @$(STRIP) $@ diff --git a/platform/amiga/handler_main.c b/platform/amiga/handler_main.c index ad5c645..51537b1 100644 --- a/platform/amiga/handler_main.c +++ b/platform/amiga/handler_main.c @@ -53,7 +53,7 @@ #define ODFS_GIT_VERSION "unknown" #endif -static const char version_string[] __attribute__((used)) = +const char version_string[] __attribute__((used)) = "$VER: ODFileSystem " ODFS_GIT_VERSION " (" ODFS_AMIGA_DATE ")"; @@ -83,6 +83,7 @@ static void copy_pure_audio_volume_name(handler_global_t *g); #endif static int scsi_is_unsupported_command(const uint8_t *sense); + /* ------------------------------------------------------------------ */ /* Amiga media adapter */ /* ------------------------------------------------------------------ */ diff --git a/platform/amiga/resident.c b/platform/amiga/resident.c new file mode 100644 index 0000000..1a396df --- /dev/null +++ b/platform/amiga/resident.c @@ -0,0 +1,94 @@ +/* + * resident.c + * + * Resident (romtag) initialisation for the m68k ODFileSystem handler. + * + * On coldstart the OS scans the binary for this romtag and calls rt_init, + * which registers ODFileSystem with FileSystem.resource by adding a + * FileSysEntry for our DosType. This lets DOS mount and (re)load the + * filesystem from the resource -- required when the handler lives in a + * custom ROM, and harmless when loaded from disk. The entry is only added + * if one for the same DosType isn't already present. + * + * SPDX-License-Identifier: BSD-2-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DOSTYPE 0x43443031 +#define MAJOR_VER 0 +#define MINOR_VER 6 + +extern const char version_string[]; +static const char name_string[] = "ODFileSystem"; + +void entrypoint(void); +static int rt_init(BPTR seglist asm("a0"), struct ExecBase *SysBase asm("a6")); + +static const struct Resident __attribute__((used,no_reorder)) romtag = { + .rt_MatchWord = RTC_MATCHWORD, + .rt_MatchTag = (APTR)&romtag, + .rt_EndSkip = (APTR)(&romtag+1), + .rt_Flags = RTF_COLDSTART, + .rt_Version = MAJOR_VER, + .rt_Type = NT_UNKNOWN, + .rt_Pri = 10, + .rt_Name = (APTR)&name_string, + .rt_IdString = (APTR)&version_string, + .rt_Init = (APTR)rt_init +}; + +static int rt_init(BPTR seglist asm("a0"), struct ExecBase *SysBase asm("a6")) { + struct FileSysResource *fsr = OpenResource((STRPTR)FSRNAME); + struct FileSysEntry *fse = NULL; + BOOL found = FALSE; + + if (fsr) { + /* Check if there's already a CDFS in FileSystem.resource */ + Forbid(); + for (fse = (struct FileSysEntry*)fsr->fsr_FileSysEntries.lh_Head; + fse->fse_Node.ln_Succ != NULL; + fse = (struct FileSysEntry*)fse->fse_Node.ln_Succ) + { + if (fse->fse_DosType == DOSTYPE) { + /* Already one there, don't bother adding this */ + found = TRUE; + break; + } + } + Permit(); + + if (!found) { + fse = AllocMem(sizeof(struct FileSysEntry), MEMF_PUBLIC | MEMF_CLEAR); + if (fse) { + // seglist will be NULL if this was part of a custom ROM + // Back up from the entrypoint to fake the seglist + if (seglist == NULL) { + seglist = MKBADDR((UBYTE *)entrypoint - 4); + } + fse->fse_Node.ln_Name = (char *)name_string; + fse->fse_DosType = DOSTYPE; + fse->fse_GlobalVec = -1; + fse->fse_PatchFlags = 0x190; + fse->fse_StackSize = 16384; + fse->fse_Version = MAJOR_VER << 16 | MINOR_VER; + fse->fse_SegList = (BPTR)seglist; + fse->fse_Priority = 10; + + Forbid(); + AddHead(&fsr->fsr_FileSysEntries,(struct Node *)fse); + Permit(); + } + } + + } + + return 0; +}