Very rough initial attempt at a RISC OS filing system based on libsa, to

allow the loading of kernels from a NetBSD file system by a RISC-OS-based
bootloader.  Currently, there's just about enough functionality to allow
BtNetBSD (and hence presumably boot32 on systems where it works) to load
a kernel.  This code has the great advantages over our existing UnixFS
that we actually have the source and can compile it under NetBSD.
This commit is contained in:
bjh21 2006-04-05 21:33:26 +00:00
parent 9a26703601
commit bb2de9ff3d
6 changed files with 496 additions and 0 deletions

View File

@ -0,0 +1,16 @@
# $NetBSD: Makefile,v 1.1 2006/04/05 21:33:26 bjh21 Exp $
PROG= nbfs
PROGSOURCE= rmheader.S rmvers.c nbfs.c rmalloc.c
NEWVERSWHAT= "RISC OS Boot"
MKMODULE= yes
CPPFLAGS+= -DLIBSA_SINGLE_DEVICE=rodisk_
rmvers.c: ${.CURDIR}/version
${HOST_SH} ${.CURDIR}/../lib/newvers_rm.sh ${.CURDIR}/version "NetBSD Boot FS"
.PHONY: rmvers.c
CLEANFILES+= rmvers.c
.include "../Makefile.buildboot"

View File

@ -0,0 +1,275 @@
/* $NetBSD: nbfs.c,v 1.1 2006/04/05 21:33:26 bjh21 Exp $ */
/*-
* Copyright (c) 2006 Ben Harris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/disklabel.h>
#include <sys/queue.h>
#include <lib/libkern/libkern.h>
#include <lib/libsa/stand.h>
#include <lib/libsa/ufs.h>
#include <riscoscalls.h>
#include <riscosdisk.h>
#include "nbfs.h"
struct fs_ops file_system[] = { FS_OPS(ffsv1), FS_OPS(ffsv2) };
int nfsys = __arraycount(file_system);
struct nbfs_open_file {
struct open_file f;
int fileswitch_handle;
LIST_ENTRY(nbfs_open_file) link;
};
static LIST_HEAD(, nbfs_open_file) nbfs_open_files;
/*
* Given a RISC OS special field and pathname, open the relevant
* device and return a pointer to the remainder of the pathname.
*/
static int
nbfs_devopen(struct open_file *f, char const *special, char const *fname,
char const **rest)
{
unsigned int drive = 0, part = RAW_PART;
int err;
if (*fname++ != ':')
return EINVAL;
while (isdigit((unsigned char)*fname))
drive = drive * 10 + *fname++ - '0';
if (islower((unsigned char)*fname))
part = *fname++ - 'a';
else if (isupper((unsigned char)*fname))
part = *fname++ - 'A';
if (*fname != '.' && *fname != '\0')
return EINVAL;
err = rodisk_open(f, special, drive, part);
if (err != 0) return err;
*rest = fname;
if (**rest == '.') (*rest)++;
return 0;
}
static int
nbfs_fileopen(struct open_file *f, char const *tail)
{
char *file, *p;
int i, error = ENOENT;
if (tail[0] == '$' && tail[1] == '.')
tail += 2;
file = alloc(strlen(tail) + 2);
strcpy(file, "/");
strcat(file, tail);
for (p = file + 1; *p != '\0'; p++) {
if (*p == '.') *p = '/';
else if (*p == '/') *p = '.';
}
if (strcmp(tail, "$") == 0)
strcpy(file, "/");
for (i = 0; i < nfsys; i++) {
error = FS_OPEN(&file_system[i])(file, f);
if (error == 0 || error == ENOENT) {
f->f_ops = &file_system[i];
break;
}
}
dealloc(file, strlen(file) + 1);
return error;
}
static int
nbfs_fopen(struct open_file *f, char const *special, char const *path)
{
char const *tail;
int err;
err = nbfs_devopen(f, special, path, &tail);
if (err != 0) return err;
err = nbfs_fileopen(f, tail);
if (err != 0)
DEV_CLOSE(f->f_dev)(f);
return err;
}
static int
nbfs_fclose(struct open_file *f)
{
int ferr, derr;
ferr = FS_CLOSE(f->f_ops)(f);
derr = DEV_CLOSE(f->f_dev)(f);
return ferr != 0 ? ferr : derr;
}
os_error *
nbfs_open(struct nbfs_reg *r)
{
static os_error error = {0, "nbfs_open"};
int reason = r->r0;
char const *fname = (char const *)r->r1;
int fh = r->r3;
char const *special = (char const *)r->r6;
int err;
struct nbfs_open_file *nof = NULL;
struct stat st;
if (reason == 0) {
nof = alloc(sizeof(*nof));
memset(nof, 0, sizeof(*nof));
err = nbfs_fopen(&nof->f, special, fname);
if (err != 0) goto fail;
err = FS_STAT(nof->f.f_ops)(&nof->f, &st);
if (err != 0) goto fail;
nof->fileswitch_handle = fh;
LIST_INSERT_HEAD(&nbfs_open_files, nof, link);
r->r0 = 0x40000000;
if (S_ISDIR(st.st_mode)) r->r0 |= 0x20000000;
r->r1 = (uint32_t)nof;
r->r2 = DEV_BSIZE;
r->r3 = st.st_size;
r->r4 = st.st_size;
return NULL;
}
fail:
if (nof != NULL)
dealloc(nof, sizeof(*nof));
return &error;
}
os_error *
nbfs_getbytes(struct nbfs_reg *r)
{
static os_error error = {0, "nbfs_getbytes"};
struct nbfs_open_file *nof = (struct nbfs_open_file *)r->r1;
void *buf = (void *)r->r2;
size_t size = r->r3;
off_t off = r->r4;
int err;
err = FS_SEEK(nof->f.f_ops)(&nof->f, off, SEEK_SET);
if (err == -1) return &error;
err = FS_READ(nof->f.f_ops)(&nof->f, buf, size, NULL);
if (err != 0) return &error;
return NULL;
}
os_error *
nbfs_putbytes(struct nbfs_reg *r)
{
static os_error err = {0, "nbfs_putbytes"};
return &err;
}
os_error *
nbfs_args(struct nbfs_reg *r)
{
static os_error err = {0, "nbfs_args"};
return &err;
}
os_error *
nbfs_close(struct nbfs_reg *r)
{
static os_error error = {0, "nbfs_close"};
struct nbfs_open_file *nof = (struct nbfs_open_file *)r->r1;
/* uint32_t loadaddr = r->r2; */
/* uint32_t execaddr = r->r3; */
int err;
err = nbfs_fclose(&nof->f);
if (err != 0) return &error;
LIST_REMOVE(nof, link);
dealloc(nof, sizeof(*nof));
return NULL;
}
os_error *
nbfs_file(struct nbfs_reg *r)
{
static os_error error = {0, "nbfs_file"};
int reason = r->r0;
char const *fname = (char const *)r->r1;
char const *special = (char const *)r->r6;
struct open_file f;
int err;
struct stat st;
memset(&f, 0, sizeof(f));
err = nbfs_fopen(&f, special, fname);
if (err != 0 && err != ENOENT)
return &error;
switch (reason) {
case 5:
if (err == ENOENT)
r->r0 = r->r2 = r->r3 = r->r4 = r->r5 = 0;
else {
err = FS_STAT(f.f_ops)(&f, &st);
if (err != 0) goto fail;
if (S_ISDIR(st.st_mode)) {
r->r0 = 2;
r->r2 = r->r3 = 0;
r->r4 = st.st_size;
r->r5 = 0x11;
} else {
r->r0 = 1;
r->r2 = r->r3 = 0;
r->r4 = st.st_size;
r->r5 = 0x11;
}
}
break;
default:
goto fail;
}
nbfs_fclose(&f);
return NULL;
fail:
nbfs_fclose(&f);
return &error;
}
os_error *
nbfs_func(struct nbfs_reg *r)
{
static os_error err = {0, "nbfs_func"};
int reason = r->r0;
/* We do nothing on shutdown */
if (reason == 16) return NULL;
return &err;
}

View File

@ -0,0 +1,15 @@
/* $NetBSD: nbfs.h,v 1.1 2006/04/05 21:33:26 bjh21 Exp $ */
/* Structure passed to and from FSEntry_* entry points */
struct nbfs_reg {
uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
};
extern os_error *nbfs_open (struct nbfs_reg *);
extern os_error *nbfs_getbytes(struct nbfs_reg *);
extern os_error *nbfs_putbytes(struct nbfs_reg *);
extern os_error *nbfs_args (struct nbfs_reg *);
extern os_error *nbfs_close (struct nbfs_reg *);
extern os_error *nbfs_file (struct nbfs_reg *);
extern os_error *nbfs_func (struct nbfs_reg *);

View File

@ -0,0 +1,18 @@
#include <lib/libsa/stand.h>
#include <riscoscalls.h>
void *
alloc(size_t size)
{
void *ret;
if (xosmodule_alloc(size, &ret) != NULL)
return NULL;
return ret;
}
void dealloc(void *ptr, size_t size)
{
xosmodule_free(ptr);
}

View File

@ -0,0 +1,169 @@
/* $NetBSD: rmheader.S,v 1.1 2006/04/05 21:33:26 bjh21 Exp $ */
/*-
* Copyright (c) 2001, 2006 Ben Harris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Relocatable module header for NBFS.
*/
#include <arm/armreg.h>
#include <riscoscalls.h>
rmbase:
.word 0 /* Start code */
.word rminit - rmbase /* Initialisation code */
.word rmfinal - rmbase /* Finalisation code */
.word 0 /* Service call handler */
.word rmtitle - rmbase /* Title string */
.word rmhelp - rmbase /* Help string */
.word 0 /* Help and command keyword table */
.word 0 /* SWI chunk base number */
.word 0 /* SWI handler code offset */
.word 0 /* SWI decoding table offset */
.word 0 /* SWI decoding code offset */
.word 0 /* Messages filename offset */
.word flags - rmbase /* Module flags extension offset */
fsib: /* Filing system information block */
.word rmtitle - rmbase /* Filing system name */
.word rmtitle - rmbase /* Filing system boot text */
.word fsentry_open - rmbase
.word fsentry_getbytes - rmbase
.word fsentry_putbytes - rmbase
.word fsentry_args - rmbase
.word fsentry_close - rmbase
.word fsentry_file - rmbase
.word fileswitch_SUPPORTS_SPECIAL | fileswitch_READ_ONLY | \
0xf0 /* borrow UnixFS's number for now */
.word fsentry_func - rmbase
.word 0 /* FSEntry_GBPB */
.word 0 /* Extra information word */
rmtitle:
.asciz "NBFS"
.align
flags:
.word 0 /* not 32 bit compatible */
rminit:
/*
* Module initialisation code
*
* On entry:
* r10 = pointer to environment string
* r11 = I/O base or instantiation number
* r12 = pointer to private word
* r14 = return address
*/
stmfd r13!, {r14}
ldr r1, Loldbase /* Get old base address */
adr r2, rmbase /* Get new base address */
str r2, Loldbase /* New is the new old */
ldr r0, L_DYNAMIC /* Pointer to the dynamic table */
add r0, r0, r2 /* ... relocated appropriately */
bl relocate_self /* Call the relocation code */
cmp r0, #0
bne Lerror
mov r0, #OSFSControl_AddFS
adr r1, rmbase
mov r2, #(fsib - rmbase)
mov r3, #0
swi XOS_FSControl
ldmfd r13!, {pc} /* If that failed, so do we */
rmfinal:
stmfd r13!, {r14}
mov r0, #OSFSControl_RemoveFS
adr r1, rmtitle
swi XOS_FSControl
cmp r0, r0 /* Clear V flag */
ldmfd r13!, {pc}
Lerror:
teq pc, pc /* In 26-bit mode? */
ldmneia r13!, {r14} /* If so, load up return address */
orrnes pc, r14, #R15_FLAG_V /* and return setting V flag */
mrs r14, cpsr /* Otherwise get cpsr */
orr r14, r14, #PSR_V_bit /* set V flag */
msr cpsr_c, r14 /* put it back */
ldmfd r13!, {pc} /* and return */
Loldbase:
.word 0
L_DYNAMIC:
.word _DYNAMIC - rmbase
fsentry_open:
stmfd r13!, {r0-r7, r14}
mov r0, r13
adr r14, fsentry_ret
b nbfs_open
fsentry_getbytes:
stmfd r13!, {r0-r7, r14}
mov r0, r13
adr r14, fsentry_ret
b nbfs_getbytes
fsentry_putbytes:
stmfd r13!, {r0-r7, r14}
mov r0, r13
adr r14, fsentry_ret
b nbfs_putbytes
fsentry_args:
stmfd r13!, {r0-r7, r14}
mov r0, r13
adr r14, fsentry_ret
b nbfs_args
fsentry_close:
stmfd r13!, {r0-r7, r14}
mov r0, r13
adr r14, fsentry_ret
b nbfs_close
fsentry_file:
stmfd r13!, {r0-r7, r14}
mov r0, r13
adr r14, fsentry_ret
b nbfs_file
fsentry_func:
stmfd r13!, {r0-r7, r14}
mov r0, r13
adr r14, fsentry_ret
b nbfs_func
fsentry_ret:
cmp r0, #0
ldmeqfd r13!, {r0-r7, pc}
add r13, r13, #4
ldmfd r13!, {r1-r7}
b Lerror

View File

@ -0,0 +1,3 @@
$NetBSD: version,v 1.1 2006/04/05 21:33:26 bjh21 Exp $
0.01: Just about enough code to launch a kernel from it.