OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /eco32/tags/eco32-0.25/disk/tools/fs-EOS32
    from Rev 232 to Rev 248
    Reverse comparison

Rev 232 → Rev 248

/mkfs/root.fsys
0,0 → 1,32
./bootblk
2236 1500
d--755 1 1
boot d--755 2 1
hello.bin ---644 2 1 ../../stdalone/hello.bin
hello2.bin ---644 2 1 ../../stdalone/hello2.bin
bottles.bin ---644 2 1 ../../stdalone/bottles.bin
memsize.bin ---644 2 1 ../../stdalone/memsize.bin
memtest.bin ---644 2 1 ../../stdalone/memtest.bin
onetask.bin ---644 2 1 ../../stdalone/onetask.bin
twotasks-1.bin ---644 2 1 ../../stdalone/twotasks-1.bin
twotasks-2.bin ---644 2 1 ../../stdalone/twotasks-2.bin
dskchk.bin ---644 2 1 ../../stdalone/dskchk.bin
dskchk2.bin ---644 2 1 ../../stdalone/dskchk2.bin
wrtmbr.bin ---644 2 1 ../../stdalone/wrtmbr.bin
dmpmbr.bin ---644 2 1 ../../stdalone/dmpmbr.bin
mkpart.bin ---644 2 1 ../../stdalone/mkpart.bin
shpart.bin ---644 2 1 ../../stdalone/shpart.bin
dactest.bin ---644 2 1 ../../stdalone/dactest.bin
eos32.bin ---644 2 1 ../../../os-bin/EOS32/eos32.bin
$
bin d--755 2 1
$
dev d--755 2 1
$
etc d--755 2 1
$
tmp d--777 2 1
$
usr d--755 2 1
$
$
/mkfs/Makefile
0,0 → 1,39
#
# Makefile for mkfs utility
#
 
BUILD = ../../../../build
 
CC = gcc -m32
CFLAGS = -g -Wall
LDFLAGS = -g
LDLIBS = -lm
 
SRCS = mkfs.c
OBJS = $(patsubst %.c,%.o,$(SRCS))
BIN = EOS32-mkfs
 
.PHONY: all install clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/bin
cp $(BIN) $(BUILD)/bin
mkdir -p $(BUILD)/run/fs-EOS32
cp root.fsys $(BUILD)/run/fs-EOS32
cp usr.fsys $(BUILD)/run/fs-EOS32
 
$(BIN): $(OBJS)
$(CC) $(LDFLAGS) -o $(BIN) $(OBJS) $(LDLIBS)
 
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
 
depend.mak:
$(CC) -MM -MG $(CFLAGS) $(SRCS) >depend.mak
 
-include depend.mak
 
clean:
rm -f *~ $(OBJS) $(BIN) depend.mak
/mkfs/mkfs.c
0,0 → 1,1153
/*
* mkfs.c -- make an EOS32 file system
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
 
 
/**************************************************************/
 
 
#define SSIZE 512 /* disk sector size in bytes */
#define BSIZE 4096 /* disk block size in bytes */
#define SPB (BSIZE / SSIZE) /* sectors per block */
#define AFS (3 * BSIZE / 2) /* average file size */
 
#define NICINOD 500 /* number of inodes in superblock */
#define NICFREE 500 /* number of free blocks in superblock */
#define NADDR 8 /* number of block addresses in inode */
#define NDADDR 6 /* number of direct block addresses */
#define SINGLE_INDIR (NDADDR + 0) /* index of single indirect block */
#define DOUBLE_INDIR (NDADDR + 1) /* index of double indirect block */
#define DIRSIZ 60 /* max length of a path name component */
 
#define NIPB (BSIZE / sizeof(Dinode))
#define NDIRENT (BSIZE / sizeof(Dirent))
#define NINDIR (BSIZE / sizeof(EOS32_daddr_t))
 
#define SUPER_MAGIC 0x44FCB67D
 
#define IFMT 070000 /* type of file */
#define IFREG 040000 /* regular file */
#define IFDIR 030000 /* directory */
#define IFCHR 020000 /* character special */
#define IFBLK 010000 /* block special */
#define IFFREE 000000 /* reserved (indicates free inode) */
#define ISUID 004000 /* set user id on execution */
#define ISGID 002000 /* set group id on execution */
#define ISVTX 001000 /* save swapped text even after use */
#define IUREAD 000400 /* user's read permission */
#define IUWRITE 000200 /* user's write permission */
#define IUEXEC 000100 /* user's execute permission */
#define IGREAD 000040 /* group's read permission */
#define IGWRITE 000020 /* group's write permission */
#define IGEXEC 000010 /* group's execute permission */
#define IOREAD 000004 /* other's read permission */
#define IOWRITE 000002 /* other's write permission */
#define IOEXEC 000001 /* other's execute permission */
 
/*
* The following two macros convert an inode number to the disk
* block containing the inode and an inode number within the block.
*/
#define itod(i) (2 + (i) / NIPB)
#define itoo(i) ((i) % NIPB)
 
#define TYPE_COPY 0
#define TYPE_INODE 1
#define TYPE_FREE 2
#define TYPE_SUPER 3
#define TYPE_INDIRECT 4
#define TYPE_DIRECTORY 5
 
 
/**************************************************************/
 
 
/* EOS32 types */
 
typedef unsigned long EOS32_ino_t;
typedef unsigned long EOS32_daddr_t;
typedef unsigned long EOS32_off_t;
typedef long EOS32_time_t;
 
 
/* super block */
 
typedef struct {
unsigned int s_magic; /* must be SUPER_MAGIC */
EOS32_daddr_t s_fsize; /* size of file system in blocks */
EOS32_daddr_t s_isize; /* size of inode list in blocks */
EOS32_daddr_t s_freeblks; /* number of free blocks */
EOS32_ino_t s_freeinos; /* number of free inodes */
unsigned int s_ninode; /* number of inodes in s_inode */
EOS32_ino_t s_inode[NICINOD]; /* free inode list */
unsigned int s_nfree; /* number of addresses in s_free */
EOS32_daddr_t s_free[NICFREE]; /* free block list */
EOS32_time_t s_time; /* last super block update */
char s_flock; /* lock for free list manipulation */
char s_ilock; /* lock for i-list manipulation */
char s_fmod; /* super block modified flag */
char s_ronly; /* mounted read-only flag */
char s_pad[BSIZE - 4036]; /* pad to block size */
} Filsys;
 
 
/* inode on disk */
 
typedef struct {
unsigned int di_mode; /* type and mode of file */
unsigned int di_nlink; /* number of links to file */
unsigned int di_uid; /* owner's user id */
unsigned int di_gid; /* owner's group id */
EOS32_time_t di_ctime; /* time created */
EOS32_time_t di_mtime; /* time last modified */
EOS32_time_t di_atime; /* time last accessed */
EOS32_off_t di_size; /* number of bytes in file */
EOS32_daddr_t di_addr[NADDR]; /* block addresses */
} Dinode;
 
 
/* inode in memory */
 
typedef struct {
EOS32_ino_t i_number; /* inode number */
unsigned int i_mode; /* type and mode of file */
unsigned int i_nlink; /* number of links to file */
unsigned int i_uid; /* owner's user id */
unsigned int i_gid; /* owner's group id */
EOS32_off_t i_size; /* number of bytes in file */
EOS32_daddr_t i_addr[NADDR]; /* block addresses */
} Inode;
 
 
/* directory entry */
 
typedef struct {
EOS32_ino_t d_ino; /* directory inode */
char d_name[DIRSIZ]; /* directory name */
} Dirent;
 
 
/* free block */
 
typedef struct {
unsigned int df_nfree; /* number of valid block addresses */
EOS32_daddr_t df_free[NICFREE]; /* addresses of free blocks */
char df_pad[BSIZE - 2004]; /* pad to block size */
} Fblk;
 
 
/**************************************************************/
 
 
time_t now; /* timestamp used throughout the file system */
FILE *fs; /* the file which holds the disk image */
Filsys filsys; /* the file system's super block */
EOS32_ino_t lastIno; /* last inode allocated */
 
 
/**************************************************************/
 
 
void error(char *fmt, ...) {
va_list ap;
 
va_start(ap, fmt);
printf("Error: ");
vprintf(fmt, ap);
printf("\n");
va_end(ap);
exit(1);
}
 
 
/**************************************************************/
 
 
unsigned int read4FromEco(unsigned char *p) {
return (unsigned int) p[0] << 24 |
(unsigned int) p[1] << 16 |
(unsigned int) p[2] << 8 |
(unsigned int) p[3] << 0;
}
 
 
void write4ToEco(unsigned char *p, unsigned int data) {
p[0] = data >> 24;
p[1] = data >> 16;
p[2] = data >> 8;
p[3] = data >> 0;
}
 
 
void conv4FromEcoToX86(unsigned char *p) {
unsigned int data;
 
data = read4FromEco(p);
* (unsigned int *) p = data;
}
 
 
void conv4FromX86ToEco(unsigned char *p) {
unsigned int data;
 
data = * (unsigned int *) p;
write4ToEco(p, data);
}
 
 
/**************************************************************/
 
 
void superFromEcoToX86(unsigned char *p) {
int i;
 
/* magic */
conv4FromEcoToX86(p);
p += 4;
/* fsize */
conv4FromEcoToX86(p);
p += 4;
/* isize */
conv4FromEcoToX86(p);
p += 4;
/* freeblks */
conv4FromEcoToX86(p);
p += 4;
/* freeinos */
conv4FromEcoToX86(p);
p += 4;
/* ninode */
conv4FromEcoToX86(p);
p += 4;
/* inode */
for (i = 0; i < NICINOD; i++) {
conv4FromEcoToX86(p);
p += 4;
}
/* nfree */
conv4FromEcoToX86(p);
p += 4;
/* free */
for (i = 0; i < NICFREE; i++) {
conv4FromEcoToX86(p);
p += 4;
}
/* time */
conv4FromEcoToX86(p);
p += 4;
/* flock */
p += 1;
/* ilock */
p += 1;
/* fmod */
p += 1;
/* ronly */
p += 1;
}
 
 
void superFromX86ToEco(unsigned char *p) {
int i;
 
/* magic */
conv4FromX86ToEco(p);
p += 4;
/* fsize */
conv4FromX86ToEco(p);
p += 4;
/* isize */
conv4FromX86ToEco(p);
p += 4;
/* freeblks */
conv4FromX86ToEco(p);
p += 4;
/* freeinos */
conv4FromX86ToEco(p);
p += 4;
/* ninode */
conv4FromX86ToEco(p);
p += 4;
/* inode */
for (i = 0; i < NICINOD; i++) {
conv4FromX86ToEco(p);
p += 4;
}
/* nfree */
conv4FromX86ToEco(p);
p += 4;
/* free */
for (i = 0; i < NICFREE; i++) {
conv4FromX86ToEco(p);
p += 4;
}
/* time */
conv4FromX86ToEco(p);
p += 4;
/* flock */
p += 1;
/* ilock */
p += 1;
/* fmod */
p += 1;
/* ronly */
p += 1;
}
 
 
void inodeFromEcoToX86(unsigned char *p) {
int i, j;
 
for (i = 0; i < NIPB; i++) {
/* mode */
conv4FromEcoToX86(p);
p += 4;
/* nlink */
conv4FromEcoToX86(p);
p += 4;
/* uid */
conv4FromEcoToX86(p);
p += 4;
/* gid */
conv4FromEcoToX86(p);
p += 4;
/* ctime */
conv4FromEcoToX86(p);
p += 4;
/* mtime */
conv4FromEcoToX86(p);
p += 4;
/* atime */
conv4FromEcoToX86(p);
p += 4;
/* size */
conv4FromEcoToX86(p);
p += 4;
/* addr */
for (j = 0; j < NADDR; j++) {
conv4FromEcoToX86(p);
p += 4;
}
}
}
 
 
void inodeFromX86ToEco(unsigned char *p) {
int i, j;
 
for (i = 0; i < NIPB; i++) {
/* mode */
conv4FromX86ToEco(p);
p += 4;
/* nlink */
conv4FromX86ToEco(p);
p += 4;
/* uid */
conv4FromX86ToEco(p);
p += 4;
/* gid */
conv4FromX86ToEco(p);
p += 4;
/* ctime */
conv4FromX86ToEco(p);
p += 4;
/* mtime */
conv4FromX86ToEco(p);
p += 4;
/* atime */
conv4FromX86ToEco(p);
p += 4;
/* size */
conv4FromX86ToEco(p);
p += 4;
/* addr */
for (j = 0; j < NADDR; j++) {
conv4FromX86ToEco(p);
p += 4;
}
}
}
 
 
void freeFromEcoToX86(unsigned char *p) {
int i;
 
/* nfree */
conv4FromEcoToX86(p);
p += 4;
/* free */
for (i = 0; i < NICFREE; i++) {
conv4FromEcoToX86(p);
p += 4;
}
}
 
 
void freeFromX86ToEco(unsigned char *p) {
int i;
 
/* nfree */
conv4FromX86ToEco(p);
p += 4;
/* free */
for (i = 0; i < NICFREE; i++) {
conv4FromX86ToEco(p);
p += 4;
}
}
 
 
void indirectFromEcoToX86(unsigned char *p) {
int i;
 
for (i = 0; i < NINDIR; i++) {
conv4FromEcoToX86(p);
p += 4;
}
}
 
 
void indirectFromX86ToEco(unsigned char *p) {
int i;
 
for (i = 0; i < NINDIR; i++) {
conv4FromX86ToEco(p);
p += 4;
}
}
 
 
void directoryFromEcoToX86(unsigned char *p) {
int i;
 
for (i = 0; i < NDIRENT; i++) {
conv4FromEcoToX86(p);
p += 4;
p += DIRSIZ;
}
}
 
 
void directoryFromX86ToEco(unsigned char *p) {
int i;
 
for (i = 0; i < NDIRENT; i++) {
conv4FromX86ToEco(p);
p += 4;
p += DIRSIZ;
}
}
 
 
/**************************************************************/
 
 
unsigned long fsStart; /* file system start sector */
 
 
void rdfs(EOS32_daddr_t bno, unsigned char *bf, int blkType) {
int n;
 
fseek(fs, fsStart * SSIZE + bno * BSIZE, SEEK_SET);
n = fread(bf, 1, BSIZE, fs);
if (n != BSIZE) {
printf("read error: %ld\n", bno);
exit(1);
}
switch (blkType) {
case TYPE_COPY:
/* nothing to do here */
break;
case TYPE_INODE:
inodeFromEcoToX86(bf);
break;
case TYPE_FREE:
freeFromEcoToX86(bf);
break;
case TYPE_SUPER:
superFromEcoToX86(bf);
break;
case TYPE_INDIRECT:
indirectFromEcoToX86(bf);
break;
case TYPE_DIRECTORY:
directoryFromEcoToX86(bf);
break;
default:
error("illegal block type %d in rdfs()", blkType);
break;
}
}
 
 
void wtfs(EOS32_daddr_t bno, unsigned char *bf, int blkType) {
int n;
 
switch (blkType) {
case TYPE_COPY:
/* nothing to do here */
break;
case TYPE_INODE:
inodeFromX86ToEco(bf);
break;
case TYPE_FREE:
freeFromX86ToEco(bf);
break;
case TYPE_SUPER:
superFromX86ToEco(bf);
break;
case TYPE_INDIRECT:
indirectFromX86ToEco(bf);
break;
case TYPE_DIRECTORY:
directoryFromX86ToEco(bf);
break;
default:
error("illegal block type %d in wtfs()", blkType);
break;
}
fseek(fs, fsStart * SSIZE + bno * BSIZE, SEEK_SET);
n = fwrite(bf, 1, BSIZE, fs);
if(n != BSIZE) {
printf("write error: %ld\n", bno);
exit(1);
}
switch (blkType) {
case TYPE_COPY:
/* nothing to do here */
break;
case TYPE_INODE:
inodeFromEcoToX86(bf);
break;
case TYPE_FREE:
freeFromEcoToX86(bf);
break;
case TYPE_SUPER:
superFromEcoToX86(bf);
break;
case TYPE_INDIRECT:
indirectFromEcoToX86(bf);
break;
case TYPE_DIRECTORY:
directoryFromEcoToX86(bf);
break;
default:
error("illegal block type %d in wtfs()", blkType);
break;
}
}
 
 
/**************************************************************/
 
 
char *charp;
FILE *fin;
char string[100];
 
 
char getChar(void) {
int c;
 
if (charp != NULL) {
/* take character from string */
c = *charp;
if (c != 0) {
charp++;
}
} else {
/* take character from prototype file */
c = getc(fin);
if (c == EOF) {
c = 0;
}
}
return c;
}
 
 
void getStr(void) {
char c;
int i;
 
while (1) {
c = getChar();
if (c == ' ' || c == '\t' || c == '\n') {
continue;
}
if (c == '\0') {
error("unexpected EOF in prototype file");
}
if (c == '#') {
do {
c = getChar();
if (c == '\0') {
error("unexpected EOF in prototype file");
}
} while (c != '\n');
continue;
}
break;
}
i = 0;
do {
string[i++] = c;
c = getChar();
} while (c != ' ' &&
c != '\t' &&
c != '\n' &&
c != '\0');
string[i] = '\0';
}
 
 
void badMode(char c) {
error("%c/%s: bad mode", c, string);
}
 
 
int getMode(char c, char *s, int m0, int m1, int m2, int m3) {
if (s[0] == 0) badMode(c);
if (c == s[0]) return m0;
if (s[1] == 0) badMode(c);
if (c == s[1]) return m1;
if (s[2] == 0) badMode(c);
if (c == s[2]) return m2;
if (s[3] == 0) badMode(c);
if (c == s[3]) return m3;
badMode(c);
/* never reached */
return 0;
}
 
 
long getNum(void) {
int i, c;
long n;
 
getStr();
n = 0;
i = 0;
for (i = 0; (c = string[i]) != '\0'; i++) {
if (c < '0' || c > '9') {
error("%s: bad number", string);
}
n = n * 10 + (c - '0');
}
return n;
}
 
 
/**************************************************************/
 
/* data block handling */
 
 
EOS32_daddr_t allocBlock(void) {
EOS32_daddr_t bno;
Fblk fbuf;
int i;
 
if (filsys.s_nfree <= 0) {
error("this should never happen (filsys.s_nfree <= 0)");
}
bno = filsys.s_free[--filsys.s_nfree];
if (bno == 0) {
error("out of free disk blocks");
}
if (filsys.s_nfree == 0) {
rdfs(bno, (unsigned char *) &fbuf, TYPE_FREE);
filsys.s_nfree = fbuf.df_nfree;
for (i = 0; i < NICFREE; i++) {
filsys.s_free[i] = fbuf.df_free[i];
}
}
filsys.s_freeblks--;
return bno;
}
 
 
void freeBlock(EOS32_daddr_t bno) {
Fblk fbuf;
int i;
 
if (filsys.s_nfree > NICFREE) {
error("this should never happen (filsys.s_nfree > NICFREE)");
}
if (filsys.s_nfree == NICFREE) {
memset(&fbuf, 0, sizeof(Fblk));
fbuf.df_nfree = NICFREE;
for (i = 0; i < NICFREE; i++) {
fbuf.df_free[i] = filsys.s_free[i];
}
wtfs(bno, (unsigned char *) &fbuf, TYPE_FREE);
filsys.s_nfree = 0;
}
filsys.s_free[filsys.s_nfree++] = bno;
if (bno != 0) {
/* note: block number 0 does not count as free block */
filsys.s_freeblks++;
}
}
 
 
void initFreeList(void) {
EOS32_daddr_t bno;
 
freeBlock(0);
for (bno = filsys.s_fsize - 1; bno >= 2 + filsys.s_isize; bno--) {
freeBlock(bno);
}
}
 
 
/**************************************************************/
 
/* inode handling */
 
 
void iput(Inode *ip) {
EOS32_daddr_t inodeBlock;
Dinode *dp;
unsigned char buf[BSIZE];
int i;
 
inodeBlock = itod(ip->i_number);
if (inodeBlock >= 2 + filsys.s_isize) {
error("too few inodes");
}
rdfs(inodeBlock, buf, TYPE_INODE);
dp = (Dinode *) buf;
dp += itoo(ip->i_number);
dp->di_mode = ip->i_mode;
dp->di_nlink = ip->i_nlink;
dp->di_uid = ip->i_uid;
dp->di_gid = ip->i_gid;
dp->di_ctime = now;
dp->di_mtime = now;
dp->di_atime = now;
dp->di_size = ip->i_size;
for (i = 0; i < NADDR; i++) {
dp->di_addr[i] = ip->i_addr[i];
}
wtfs(inodeBlock, buf, TYPE_INODE);
filsys.s_freeinos--;
}
 
 
void initInodes(void) {
int i;
EOS32_daddr_t n;
unsigned char buf[BSIZE];
Inode in;
 
/* init all inodes to free */
for (i = 0; i < BSIZE; i++) {
buf[i] = '\0';
}
for (n = 0; n < filsys.s_isize; n++) {
wtfs(2 + n, buf, TYPE_INODE);
filsys.s_freeinos += NIPB;
}
/* init inode 0 */
lastIno = 0;
in.i_number = lastIno;
in.i_mode = IFREG;
in.i_nlink = 0;
in.i_uid = 0;
in.i_gid = 0;
in.i_size = 0;
for (i = 0; i < NADDR; i++) {
in.i_addr[i] = 0;
}
iput(&in);
}
 
 
void fillFreeInodeList(EOS32_ino_t numInodes) {
int index;
EOS32_ino_t ino;
int i;
 
/* fill the free inode list starting at the upper end */
index = NICINOD;
for (ino = lastIno + 1; ino < numInodes && index > 0; ino++) {
filsys.s_inode[--index] = ino;
}
filsys.s_ninode = NICINOD - index;
/* if the list is not completely filled, shift entries down */
if (index > 0) {
for (i = 0; i < filsys.s_ninode; i++) {
filsys.s_inode[i] = filsys.s_inode[index++];
}
}
}
 
 
/**************************************************************/
 
 
void appendData(Inode *ip, int blkType, unsigned char *src, int size) {
EOS32_off_t offset;
int index1, index2;
EOS32_daddr_t bno;
unsigned char buf[BSIZE];
EOS32_daddr_t ibno;
EOS32_daddr_t iblk[NINDIR];
EOS32_daddr_t dibno;
EOS32_daddr_t diblk[NINDIR];
 
offset = ip->i_size;
if (offset < NDADDR * BSIZE) {
/* direct block */
index1 = offset / BSIZE;
offset %= BSIZE;
if (ip->i_addr[index1] == 0) {
bno = allocBlock();
ip->i_addr[index1] = bno;
memset(buf, 0, BSIZE);
} else {
bno = ip->i_addr[index1];
rdfs(bno, buf, blkType);
}
} else
if (offset < (NINDIR + NDADDR) * BSIZE) {
/* single indirect block */
offset -= NDADDR * BSIZE;
index1 = offset / BSIZE;
offset %= BSIZE;
if (ip->i_addr[SINGLE_INDIR] == 0) {
ibno = allocBlock();
ip->i_addr[SINGLE_INDIR] = ibno;
memset(iblk, 0, BSIZE);
} else {
ibno = ip->i_addr[SINGLE_INDIR];
rdfs(ibno, (unsigned char *) iblk, TYPE_INDIRECT);
}
if (iblk[index1] == 0) {
bno = allocBlock();
iblk[index1] = bno;
wtfs(ibno, (unsigned char *) iblk, TYPE_INDIRECT);
memset(buf, 0, BSIZE);
} else {
bno = iblk[index1];
rdfs(bno, buf, blkType);
}
} else {
/* double indirect block */
offset -= (NINDIR + NDADDR) * BSIZE;
index1 = offset / BSIZE;
offset %= BSIZE;
index2 = index1 / NINDIR;
index1 %= NINDIR;
if (ip->i_addr[DOUBLE_INDIR] == 0) {
dibno = allocBlock();
ip->i_addr[DOUBLE_INDIR] = dibno;
memset(diblk, 0, BSIZE);
} else {
dibno = ip->i_addr[DOUBLE_INDIR];
rdfs(dibno, (unsigned char *) diblk, TYPE_INDIRECT);
}
if (diblk[index2] == 0) {
ibno = allocBlock();
diblk[index2] = ibno;
wtfs(dibno, (unsigned char *) diblk, TYPE_INDIRECT);
memset(iblk, 0, BSIZE);
} else {
ibno = diblk[index2];
rdfs(ibno, (unsigned char *) iblk, TYPE_INDIRECT);
}
if (iblk[index1] == 0) {
bno = allocBlock();
iblk[index1] = bno;
wtfs(ibno, (unsigned char *) iblk, TYPE_INDIRECT);
memset(buf, 0, BSIZE);
} else {
bno = iblk[index1];
rdfs(bno, buf, blkType);
}
}
memcpy(buf + offset, src, size);
wtfs(bno, buf, blkType);
ip->i_size += size;
}
 
 
void makeDirEntry(Inode *dir, EOS32_ino_t ino, char *name) {
Dirent entry;
 
memset(&entry, 0, sizeof(Dirent));
entry.d_ino = ino;
strcpy(entry.d_name, name);
appendData(dir, TYPE_DIRECTORY, (unsigned char *) &entry, sizeof(Dirent));
}
 
 
void createFile(Inode *parent) {
Inode in;
int i;
char c;
FILE *f;
unsigned char buf[BSIZE];
 
/* get mode, uid and gid */
getStr();
in.i_mode = getMode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
in.i_mode |= getMode(string[1], "-u", 0, ISUID, 0, 0);
in.i_mode |= getMode(string[2], "-g", 0, ISGID, 0, 0);
for (i = 3; i < 6; i++) {
c = string[i];
if (c < '0' || c > '7') {
error("%c/%s: bad octal mode digit", c, string);
}
in.i_mode |= (c - '0') << (15 - 3 * i);
}
in.i_uid = getNum();
in.i_gid = getNum();
/* general initialization prior to switching on format */
lastIno++;
in.i_number = lastIno;
in.i_nlink = 1;
in.i_size = 0;
for (i = 0; i < NADDR; i++) {
in.i_addr[i] = 0;
}
if (parent == NULL) {
parent = &in;
in.i_nlink--;
}
/* now switch on format */
switch (in.i_mode & IFMT) {
case IFREG:
/* regular file:
contents is a file name */
getStr();
f = fopen(string, "rb");
if (f == NULL) {
error("%s: cannot open", string);
}
while ((i = fread(buf, 1, BSIZE, f)) > 0) {
appendData(&in, TYPE_COPY, buf, i);
}
fclose(f);
break;
case IFBLK:
case IFCHR:
/* special file:
contents is major/minor device */
in.i_addr[0] = (getNum() & 0xFFFF) << 16;
in.i_addr[0] |= (getNum() & 0xFFFF);
break;
case IFDIR:
/* directory:
put in extra links, call recursively until name is "$" */
parent->i_nlink++;
in.i_nlink++;
makeDirEntry(&in, in.i_number, ".");
makeDirEntry(&in, parent->i_number, "..");
while (1) {
getStr();
if (string[0] == '$' && string[1] == '\0') {
break;
}
makeDirEntry(&in, lastIno + 1, string);
createFile(&in);
}
break;
default:
error("bad format/mode %o\n", in.i_mode);
break;
}
/* finally write the inode */
iput(&in);
}
 
 
/**************************************************************/
 
 
void showSizes(void) {
printf("BSIZE = %d\n", BSIZE);
printf("NICINOD = %d\n", NICINOD);
printf("NICFREE = %d\n", NICFREE);
printf("NADDR = %d\n", NADDR);
printf("NDADDR = %d\n", NDADDR);
printf("DIRSIZ = %d\n", DIRSIZ);
printf("NIPB = %d\n", NIPB);
printf("NDIRENT = %d\n", NDIRENT);
printf("NINDIR = %d\n", NINDIR);
printf("sizeof(Filsys) = %d\n", sizeof(Filsys));
printf("sizeof(Dinode) = %d\n", sizeof(Dinode));
printf("sizeof(Dirent) = %d\n", sizeof(Dirent));
printf("sizeof(Fblk) = %d\n", sizeof(Fblk));
}
 
 
int main(int argc, char *argv[]) {
char *fsnam;
char *proto;
char protoBuf[20];
unsigned long fsSize;
int part;
char *endptr;
unsigned char partTable[SSIZE];
unsigned char *ptptr;
unsigned long partType;
EOS32_daddr_t maxBlocks;
EOS32_daddr_t numBlocks;
EOS32_ino_t numInodes;
int i;
char c;
FILE *bootblk;
long bootblkSize;
unsigned char buf[BSIZE];
 
if (argc == 2 && strcmp(argv[1], "--sizes") == 0) {
showSizes();
exit(0);
}
if (argc != 3 && argc != 4) {
printf("Usage: %s <disk> <partition or '*'> [<prototype or size>]\n",
argv[0]);
printf(" or: %s --sizes\n", argv[0]);
exit(1);
}
time(&now);
fsnam = argv[1];
fs = fopen(fsnam, "r+b");
if (fs == NULL) {
error("cannot open disk image '%s'", fsnam);
}
if (strcmp(argv[2], "*") == 0) {
/* whole disk contains one single file system */
fsStart = 0;
fseek(fs, 0, SEEK_END);
fsSize = ftell(fs) / SSIZE;
} else {
/* argv[2] is partition number of file system */
part = strtoul(argv[2], &endptr, 10);
if (*endptr != '\0' || part < 0 || part > 15) {
error("illegal partition number '%s'", argv[2]);
}
fseek(fs, 1 * SSIZE, SEEK_SET);
if (fread(partTable, 1, SSIZE, fs) != SSIZE) {
error("cannot read partition table of disk '%s'", fsnam);
}
ptptr = partTable + part * 32;
partType = read4FromEco(ptptr + 0);
if ((partType & 0x7FFFFFFF) != 0x00000058) {
error("partition %d of disk '%s' does not contain an EOS32 file system",
part, fsnam);
}
fsStart = read4FromEco(ptptr + 4);
fsSize = read4FromEco(ptptr + 8);
}
printf("File system space is %lu (0x%lX) sectors of %d bytes each.\n",
fsSize, fsSize, SSIZE);
if (fsSize % SPB != 0) {
printf("File system space is not a multiple of block size.\n");
}
maxBlocks = fsSize / SPB;
printf("This equals %lu (0x%lX) blocks of %d bytes each.\n",
maxBlocks, maxBlocks, BSIZE);
if (argc == 4) {
proto = argv[3];
} else {
proto = protoBuf;
sprintf(protoBuf, "%lu", maxBlocks);
}
/* initialize super block and possibly write boot block */
filsys.s_magic = SUPER_MAGIC;
fin = fopen(proto, "rt");
if (fin == NULL) {
/* cannot open prototype file, perhaps size was specified */
charp = "d--777 0 0 $ ";
numBlocks = 0;
for (i = 0; (c = proto[i]) != '\0'; i++) {
if (c < '0' || c > '9') {
/* neither valid prototype file nor valid size */
error("cannot open prototype '%s'", proto);
}
numBlocks = numBlocks * 10 + (c - '0');
}
numInodes = (numBlocks * BSIZE) / AFS;
} else {
/* prototype file opened */
charp = NULL;
getStr();
if (strcmp(string, "-noboot-") == 0) {
/* boot block not wanted */
} else {
/* string holds the name of the boot block file */
bootblk = fopen(string, "rb");
if (bootblk == NULL) {
error("cannot open boot block file '%s'", string);
}
fseek(bootblk, 0, SEEK_END);
bootblkSize = ftell(bootblk);
fseek(bootblk, 0, SEEK_SET);
if (bootblkSize > BSIZE) {
error("boot block file '%s' is bigger than a block", string);
}
for (i = 0; i < BSIZE; i++) {
buf[i] = '\0';
}
if (fread(buf, 1, bootblkSize, bootblk) != bootblkSize) {
error("cannot read boot block file '%s'", string);
}
wtfs(0, buf, TYPE_COPY);
fclose(bootblk);
}
numBlocks = getNum();
numInodes = getNum();
}
if (numBlocks > maxBlocks) {
error("file system exceeds available space");
}
if (numBlocks < maxBlocks) {
printf("File system does not fully utilize available space.\n");
}
filsys.s_fsize = numBlocks;
filsys.s_isize = (numInodes + NIPB - 1) / NIPB;
numInodes = filsys.s_isize * NIPB;
if (2 + filsys.s_isize >= filsys.s_fsize) {
error("bad block ratio (total/inode = %lu/%lu)",
filsys.s_fsize, filsys.s_isize);
}
printf("File system size = %ld blocks\n", filsys.s_fsize);
printf("Number of inodes = %ld inodes\n", numInodes);
filsys.s_freeblks = 0;
filsys.s_freeinos = 0;
filsys.s_ninode = 0;
for (i = 0; i < NICINOD; i++) {
filsys.s_inode[i] = 0;
}
filsys.s_nfree = 0;
for (i = 0; i < NICFREE; i++) {
filsys.s_free[i] = 0;
}
filsys.s_time = now;
filsys.s_flock = 0;
filsys.s_ilock = 0;
filsys.s_fmod = 0;
filsys.s_ronly = 0;
/* init inodes */
initInodes();
/* init free list */
initFreeList();
/* create files */
createFile(NULL);
/* fill free inode list in super block */
/* note: this isn't strictly necessary, but cuts down file
creation time within the newly created partition or disk */
fillFreeInodeList(numInodes);
/* finally write super block and return */
wtfs(1, (unsigned char *) &filsys, TYPE_SUPER);
return 0;
}
/mkfs/usr.fsys
0,0 → 1,22
-noboot-
6000 4000
d--755 2 1
data d--777 2 1
1 ---644 5 5 ../../data/0x000001
2 ---644 5 5 ../../data/0x000002
4 ---644 5 5 ../../data/0x000004
8 ---644 5 5 ../../data/0x000008
10 ---644 5 5 ../../data/0x000010
20 ---644 5 5 ../../data/0x000020
40 ---644 5 5 ../../data/0x000040
80 ---644 5 5 ../../data/0x000080
100 ---644 5 5 ../../data/0x000100
200 ---644 5 5 ../../data/0x000200
400 ---644 5 5 ../../data/0x000400
800 ---644 5 5 ../../data/0x000800
$
hellwig d--755 6 1
$
src d--755 7 1
$
$
/mkboot/stage1/br.s
0,0 → 1,112
;
; br.s -- the boot record
;
 
; Runtime environment:
;
; This code must be loaded and started at 0xC0010000.
; It allocates a stack from 0xC0011000 downwards. So
; it must run within 4K (code + data + stack).
;
; This code expects the disk number of the boot disk
; in $16, the start sector of the disk or partition
; to be booted in $17 and its size in $18.
;
; The boot loader, which is loaded by this code,
; must be in standalone (headerless) executable
; format, stored at partition relative disk
; sectors 1..7 (i.e., the boot block), and
; gets loaded and started at 0xC0300000.
 
.set stacktop,0xC0011000 ; top of stack
.set loadaddr,0xC0300000 ; where to load the boot loader
 
.set cout,0xC0000020 ; the monitor's console output
.set dskio,0xC0000028 ; the monitor's disk I/O
 
; load the boot loader and start it
start:
add $29,$0,stacktop ; setup stack
add $4,$0,strtmsg ; say what is going on
jal msgout
add $4,$0,1 ; start loading with sector 1
add $5,$0,loadaddr ; where to load the boot loader
and $5,$5,0x3FFFFFFF ; convert to physical address
add $6,$0,7 ; 7 sectors to load
jal rdsct
add $8,$0,loadaddr ; start executing the boot loader
jr $8
 
; read disk sectors
; $4 start sector number (disk or partition relative)
; $5 transfer address
; $6 number of sectors
rdsct:
sub $29,$29,32
stw $31,$29,20
stw $6,$29,16 ; sector count
add $7,$5,$0 ; transfer address
add $6,$4,$17 ; relative sector -> absolute
add $5,$0,'r' ; command
add $4,$0,$16 ; disk number
add $8,$0,dskio
jalr $8
bne $2,$0,rderr ; error?
ldw $31,$29,20
add $29,$29,32
jr $31
 
; disk read error
rderr:
add $4,$0,dremsg
jal msgout
j halt
 
; output message
; $4 pointer to string
msgout:
sub $29,$29,8
stw $31,$29,4
stw $16,$29,0
add $16,$4,0 ; $16: pointer to string
msgout1:
ldbu $4,$16,0 ; get character
beq $4,$0,msgout2 ; done?
jal chrout ; output character
add $16,$16,1 ; bump pointer
j msgout1 ; continue
msgout2:
ldw $16,$29,0
ldw $31,$29,4
add $29,$29,8
jr $31
 
; output character
; $4 character
chrout:
sub $29,$29,4
stw $31,$29,0
add $8,$0,cout
jalr $8
ldw $31,$29,0
add $29,$29,4
jr $31
 
; halt execution by looping
halt:
add $4,$0,hltmsg
jal msgout
halt1:
j halt1
 
; messages
strtmsg:
.byte "BR executing...", 0x0D, 0x0A, 0
dremsg:
.byte "disk read error", 0x0D, 0x0A, 0
hltmsg:
.byte "bootstrap halted", 0x0D, 0x0A, 0
 
; boot record signature
.locate 512-2
.byte 0x55, 0xAA
/mkboot/stage1/Makefile
0,0 → 1,16
#
# Makefile to build the boot record
#
 
BUILD = ../../../../../build
 
all: br.bin
 
br.bin: br.o
$(BUILD)/bin/ld -h -rc 0xC0010000 -o br.bin br.o
 
br.o: br.s
$(BUILD)/bin/as -o br.o br.s
 
clean:
rm -f *~ br.o br.bin
/mkboot/stage2/biolib.s
0,0 → 1,26
;
; biolib.s -- basic I/O library
;
 
.set cin,0xC0000018
.set cout,0xC0000020
.set dskio,0xC0000028
 
.export getc
.export putc
.export rwscts
 
.code
.align 4
 
getc:
add $8,$0,cin
jr $8
 
putc:
add $8,$0,cout
jr $8
 
rwscts:
add $8,$0,dskio
jr $8
/mkboot/stage2/boot.c
0,0 → 1,444
/*
* boot.c -- the bootstrap (boot loader)
*/
 
 
#include "biolib.h"
 
 
/**************************************************************/
 
/* constants and data types */
 
 
#define DFLT_KERNEL "/boot/eos32.bin" /* path of default OS kernel */
#define LOAD_ADDR 0xC0010000 /* where to load the kernel */
 
#define MAX_LINE 100 /* line buffer size */
 
#define EXEC_MAGIC 0x3AE82DD4 /* magic number for executables */
 
#define PSHIFT 12 /* ld of page size */
#define PSIZE (1 << PSHIFT) /* page size in bytes */
#define PMASK (PSIZE - 1) /* page mask */
 
#define BSHIFT 12 /* ld of block size */
#define BSIZE (1 << BSHIFT) /* disk block size in bytes */
#define BMASK (BSIZE - 1) /* block mask */
 
#define SSIZE 512 /* disk sector size in bytes */
#define SPB (BSIZE / SSIZE) /* sectors per block */
 
#define ROOT_INO 1 /* inode number of root directory */
#define NADDR 8 /* number of block addresses in inode */
#define NDADDR 6 /* number of direct block addresses */
#define DIRSIZ 60 /* max length of path name component */
 
#define NIPB (BSIZE / sizeof(Dinode))
#define NDIRENT (BSIZE / sizeof(Dirent))
#define NINDIR (BSIZE / sizeof(EOS32_daddr_t))
 
#define NULL 0
 
 
typedef unsigned long EOS32_ino_t;
typedef unsigned long EOS32_daddr_t;
typedef unsigned long EOS32_off_t;
typedef long EOS32_time_t;
 
 
#define IFMT 070000 /* type of file */
#define IFREG 040000 /* regular file */
#define IFDIR 030000 /* directory */
#define IFCHR 020000 /* character special */
#define IFBLK 010000 /* block special */
#define IFFREE 000000 /* reserved (indicates free inode) */
#define ISUID 004000 /* set user id on execution */
#define ISGID 002000 /* set group id on execution */
#define ISVTX 001000 /* save swapped text even after use */
#define IUREAD 000400 /* user's read permission */
#define IUWRITE 000200 /* user's write permission */
#define IUEXEC 000100 /* user's execute permission */
#define IGREAD 000040 /* group's read permission */
#define IGWRITE 000020 /* group's write permission */
#define IGEXEC 000010 /* group's execute permission */
#define IOREAD 000004 /* other's read permission */
#define IOWRITE 000002 /* other's write permission */
#define IOEXEC 000001 /* other's execute permission */
 
/*
* The following two macros convert an inode number to the disk
* block containing the inode and an inode number within the block.
*/
#define itod(i) (2 + (i) / NIPB)
#define itoo(i) ((i) % NIPB)
 
 
typedef struct {
unsigned int di_mode; /* type and mode of file */
unsigned int di_nlink; /* number of links to file */
unsigned int di_uid; /* owner's user id */
unsigned int di_gid; /* owner's group id */
EOS32_time_t di_ctime; /* time created */
EOS32_time_t di_mtime; /* time last modified */
EOS32_time_t di_atime; /* time last accessed */
EOS32_off_t di_size; /* number of bytes in file */
EOS32_daddr_t di_addr[NADDR]; /* disk block addresses */
} Dinode;
 
 
typedef struct {
EOS32_ino_t d_ino; /* directory inode */
char d_name[DIRSIZ]; /* directory name */
} Dirent;
 
 
/**************************************************************/
 
/* string functions */
 
 
int strlen(char *str) {
int i;
 
i = 0;
while (*str++ != '\0') {
i++;
}
return i;
}
 
 
int strcmp(char *str1, char *str2) {
while (*str1 == *str2) {
if (*str1 == '\0') {
return 0;
}
str1++;
str2++;
}
return (* (unsigned char *) str1) - (* (unsigned char *) str2);
}
 
 
void strcpy(char *dst, char *src) {
while ((*dst++ = *src++) != '\0') ;
}
 
 
/**************************************************************/
 
/* terminal I/O */
 
 
char getchar(void) {
return getc();
}
 
 
void putchar(char c) {
if (c == '\n') {
putchar('\r');
}
putc(c);
}
 
 
void puts(char *s) {
while (*s != '\0') {
putchar(*s++);
}
}
 
 
/**************************************************************/
 
/* get a line from the terminal */
 
 
void getLine(char *prompt, char *line, int max) {
int index;
char c;
 
puts(prompt);
puts(line);
index = strlen(line);
while (1) {
c = getchar();
switch (c) {
case '\r':
putchar('\n');
line[index] = '\0';
return;
case '\b':
case 0x7F:
if (index == 0) {
break;
}
putchar('\b');
putchar(' ');
putchar('\b');
index--;
break;
default:
if (c == '\t') {
c = ' ';
}
if (c < 0x20 || c > 0x7E) {
break;
}
putchar(c);
line[index++] = c;
break;
}
}
}
 
 
/**************************************************************/
 
/* halt with error message */
 
 
void halt(char *msg) {
puts(msg);
puts(", machine halted.\n");
while (1) ;
}
 
 
/**************************************************************/
 
/* disk I/O */
 
 
unsigned int bootDisk = 0; /* gets loaded by previous stage */
unsigned int startSector = 0; /* gets loaded by previous stage */
unsigned int numSectors = 0; /* gets loaded by previous stage */
 
 
/*
* read a disk block
*
* NOTE: buffer must be word-aligned
*/
void readBlock(unsigned int blkno, void *buffer) {
unsigned int sector;
int result;
 
sector = blkno * SPB;
if (sector + SPB > numSectors) {
halt("Sector number exceeds disk or partition size");
}
result = rwscts(bootDisk, 'r', sector + startSector,
(unsigned int) buffer & 0x3FFFFFFF, SPB);
if (result != 0) {
halt("Load error");
}
}
 
 
/**************************************************************/
 
/* file operations*/
 
 
EOS32_daddr_t sibn = -1;
EOS32_daddr_t singleIndirectBlock[NINDIR];
EOS32_daddr_t dibn = -1;
EOS32_daddr_t doubleIndirectBlock[NINDIR];
 
 
/*
* read a block of a file
*
* NOTE: addr must be word-aligned
*/
void readFileBlock(Dinode *ip, int blkno, void *addr) {
EOS32_daddr_t diskBlock;
 
if (blkno < NDADDR) {
/* direct block */
diskBlock = ip->di_addr[blkno];
} else
if (blkno < NDADDR + NINDIR) {
/* single indirect block */
diskBlock = ip->di_addr[NDADDR];
if (sibn != diskBlock) {
readBlock(diskBlock, singleIndirectBlock);
sibn = diskBlock;
}
diskBlock = singleIndirectBlock[blkno - NDADDR];
} else {
/* double indirect block */
diskBlock = ip->di_addr[NDADDR + 1];
if (dibn != diskBlock) {
readBlock(diskBlock, doubleIndirectBlock);
dibn = diskBlock;
}
diskBlock = doubleIndirectBlock[(blkno - NDADDR - NINDIR) / NINDIR];
if (sibn != diskBlock) {
readBlock(diskBlock, singleIndirectBlock);
sibn = diskBlock;
}
diskBlock = singleIndirectBlock[(blkno - NDADDR - NINDIR) % NINDIR];
}
readBlock(diskBlock, addr);
}
 
 
/**************************************************************/
 
/* inode handling */
 
 
Dinode inodeBlock[NIPB];
 
 
Dinode *getInode(unsigned int inode) {
unsigned int bnum;
unsigned int inum;
 
bnum = itod(inode);
inum = itoo(inode);
readBlock(bnum, inodeBlock);
return &inodeBlock[inum];
}
 
 
/**************************************************************/
 
/* convert path to inode */
 
 
Dirent directoryBlock[NDIRENT];
 
 
Dinode *pathToInode(char *path) {
Dinode *ip;
char c;
char dirBuffer[DIRSIZ];
char *cp;
EOS32_off_t offset;
Dirent *dp;
unsigned int ino;
 
/* get root inode */
ip = getInode(ROOT_INO);
/* traverse file system tree while matching path components */
c = *path++;
while (1) {
/* skip leading slashes in path component */
while (c == '/') {
c = *path++;
}
if (c == '\0') {
/* no more path components */
break;
}
/* if there is another component, gather up its name */
cp = dirBuffer;
while (c != '/' && c != '\0') {
if (cp < &dirBuffer[DIRSIZ]) {
*cp++ = c;
}
c = *path++;
}
*cp++ = '\0';
/* ip must be a directory */
if ((ip->di_mode & IFMT) != IFDIR) {
return NULL;
}
/* search directory */
offset = 0;
while (1) {
if (offset >= ip->di_size) {
/* component not found */
return NULL;
}
if ((offset & BMASK) == 0) {
/* read the next directory block */
readFileBlock(ip, offset >> BSHIFT, directoryBlock);
dp = directoryBlock;
}
ino = dp->d_ino;
if (ino != 0) {
if (strcmp(dirBuffer, dp->d_name) == 0) {
/* component found */
break;
}
}
/* no match, try next entry */
dp++;
offset += sizeof(Dirent);
}
/* get corresponding inode */
ip = getInode(ino);
/* look for more components */
}
return ip;
}
 
 
/**************************************************************/
 
/* load the kernel */
 
 
void loadKernel(Dinode *ip) {
unsigned int numBlocks;
unsigned int nextBlock;
unsigned char *nextAddr;
 
numBlocks = (ip->di_size + (BSIZE - 1)) / BSIZE;
nextBlock = 0;
nextAddr = (unsigned char *) LOAD_ADDR;
while (numBlocks--) {
readFileBlock(ip, nextBlock, nextAddr);
nextBlock++;
nextAddr += BSIZE;
}
}
 
 
/**************************************************************/
 
/* main program */
 
 
unsigned int entryPoint; /* where to continue from main() */
 
 
int main(void) {
char line[MAX_LINE];
Dinode *ip;
 
puts("Bootstrap loader executing...\n");
strcpy(line, DFLT_KERNEL);
while (1) {
getLine("\nPlease enter path to kernel: ", line, MAX_LINE);
ip = pathToInode(line);
if (ip == NULL) {
puts("'");
puts(line);
puts("' not found\n");
continue;
}
if ((ip->di_mode & IFMT) != IFREG) {
puts("'");
puts(line);
puts("' is not a regular file\n");
continue;
}
break;
}
puts("Loading '");
puts(line);
puts("'...\n");
loadKernel(ip);
puts("Starting '");
puts(line);
puts("'...\n");
entryPoint = LOAD_ADDR;
return 0;
}
/mkboot/stage2/c0.s
0,0 → 1,59
;
; c0.s -- startup code and begin-of-segment labels
;
 
.import main
 
.import _ecode
.import _edata
.import _ebss
 
.export _bcode
.export _bdata
.export _bbss
 
.import bootDisk
.import startSector
.import numSectors
.import entryPoint
 
.code
_bcode:
 
start:
add $10,$0,_bdata ; copy data segment
add $8,$0,_edata
sub $9,$8,$10
add $9,$9,_ecode
j cpytest
cpyloop:
ldw $11,$9,0
stw $11,$8,0
cpytest:
sub $8,$8,4
sub $9,$9,4
bgeu $8,$10,cpyloop
add $8,$0,_bbss ; clear bss segment
add $9,$0,_ebss
j clrtest
clrloop:
stw $0,$8,0
add $8,$8,4
clrtest:
bltu $8,$9,clrloop
add $29,$0,0xC0400000 ; setup stack
stw $16,$0,bootDisk ; make arguments available
stw $17,$0,startSector
stw $18,$0,numSectors
jal main ; call 'main' function
ldw $16,$0,bootDisk ; setup arguments for next stage
ldw $17,$0,startSector
ldw $18,$0,numSectors
ldw $31,$0,entryPoint ; jump to loaded program
jr $31
 
.data
_bdata:
 
.bss
_bbss:
/mkboot/stage2/c1.s
0,0 → 1,19
;
; c1.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/mkboot/stage2/biolib.h
0,0 → 1,15
/*
* biolib.h -- basic I/O library
*/
 
 
#ifndef _BIOLIB_H_
#define _BIOLIB_H_
 
 
char getc(void);
void putc(char c);
int rwscts(int dskno, int cmd, int sector, int addr, int count);
 
 
#endif /* _BIOLIB_H_ */
/mkboot/stage2/Makefile
0,0 → 1,26
#
# Makefile to build the bootstrap (boot loader)
#
 
BUILD = ../../../../../build
 
all: boot.bin
 
boot.bin: c0.o boot.o biolib.o c1.o
$(BUILD)/bin/ld -h -rc 0xC0300000 -o boot.bin \
c0.o boot.o biolib.o c1.o
 
c0.o: c0.s
$(BUILD)/bin/as -o c0.o c0.s
 
boot.o: boot.c
$(BUILD)/bin/lcc -A -c -o boot.o boot.c
 
biolib.o: biolib.s
$(BUILD)/bin/as -o biolib.o biolib.s
 
c1.o: c1.s
$(BUILD)/bin/as -o c1.o c1.s
 
clean:
rm -f *~ c0.o boot.o biolib.o c1.o boot.bin
/mkboot/Makefile
0,0 → 1,27
#
# Makefile to build the boot block
#
 
BUILD = ../../../../build
 
.PHONY: all install clean
 
all: bootblk
 
install: bootblk
mkdir -p $(BUILD)/run/fs-EOS32
cp bootblk $(BUILD)/run/fs-EOS32
 
bootblk: stage1/br.bin stage2/boot.bin
cat stage1/br.bin stage2/boot.bin >bootblk
 
stage1/br.bin:
$(MAKE) -C stage1
 
stage2/boot.bin:
$(MAKE) -C stage2
 
clean:
$(MAKE) -C stage1 clean
$(MAKE) -C stage2 clean
rm -f *~ bootblk
/shfs/Makefile
0,0 → 1,36
#
# Makefile for shfs utility
#
 
BUILD = ../../../../build
 
CC = gcc -m32
CFLAGS = -g -Wall
LDFLAGS = -g
LDLIBS = -lm
 
SRCS = shfs.c
OBJS = $(patsubst %.c,%.o,$(SRCS))
BIN = EOS32-shfs
 
.PHONY: all install clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/bin
cp $(BIN) $(BUILD)/bin
 
$(BIN): $(OBJS)
$(CC) $(LDFLAGS) -o $(BIN) $(OBJS) $(LDLIBS)
 
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
 
depend.mak:
$(CC) -MM -MG $(CFLAGS) $(SRCS) >depend.mak
 
-include depend.mak
 
clean:
rm -f *~ $(OBJS) $(BIN) depend.mak
/shfs/shfs.c
0,0 → 1,658
/*
* shfs.c -- show an EOS32 file system
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
 
 
#define SECTOR_SIZE 512 /* disk sector size in bytes */
#define BLOCK_SIZE 4096 /* disk block size in bytes */
#define SPB (BLOCK_SIZE / SECTOR_SIZE)
#define LINE_SIZE 100 /* input line buffer size in bytes */
#define LINES_PER_BATCH 32 /* number of lines output in one batch */
 
#define NICINOD 500 /* number of free inodes in superblock */
#define NICFREE 500 /* number of free blocks in superblock */
#define INOPB 64 /* number of inodes per block */
#define DIRPB 64 /* number of directory entries per block */
#define DIRSIZ 60 /* max length of path name component */
 
#define IFMT 070000 /* type of file */
#define IFREG 040000 /* regular file */
#define IFDIR 030000 /* directory */
#define IFCHR 020000 /* character special */
#define IFBLK 010000 /* block special */
#define IFFREE 000000 /* reserved (indicates free inode) */
#define ISUID 004000 /* set user id on execution */
#define ISGID 002000 /* set group id on execution */
#define ISVTX 001000 /* save swapped text even after use */
#define IUREAD 000400 /* user's read permission */
#define IUWRITE 000200 /* user's write permission */
#define IUEXEC 000100 /* user's execute permission */
#define IGREAD 000040 /* group's read permission */
#define IGWRITE 000020 /* group's write permission */
#define IGEXEC 000010 /* group's execute permission */
#define IOREAD 000004 /* other's read permission */
#define IOWRITE 000002 /* other's write permission */
#define IOEXEC 000001 /* other's execute permission */
 
 
typedef unsigned long EOS32_ino_t;
typedef unsigned long EOS32_daddr_t;
typedef unsigned long EOS32_off_t;
typedef long EOS32_time_t;
 
 
void error(char *fmt, ...) {
va_list ap;
 
va_start(ap, fmt);
printf("Error: ");
vprintf(fmt, ap);
printf("\n");
va_end(ap);
exit(1);
}
 
 
unsigned long fsStart; /* file system start sector */
 
 
void readBlock(FILE *disk,
EOS32_daddr_t blockNum,
unsigned char *blockBuffer) {
fseek(disk, fsStart * SECTOR_SIZE + blockNum * BLOCK_SIZE, SEEK_SET);
if (fread(blockBuffer, BLOCK_SIZE, 1, disk) != 1) {
error("cannot read block %lu (0x%lX)", blockNum, blockNum);
}
}
 
 
unsigned long get4Bytes(unsigned char *addr) {
return (unsigned long) addr[0] << 24 |
(unsigned long) addr[1] << 16 |
(unsigned long) addr[2] << 8 |
(unsigned long) addr[3] << 0;
}
 
 
int waitForReturn(void) {
char line[LINE_SIZE];
 
printf("press <enter> to continue, <esc> to break, q to quit: ");
fflush(stdout);
if (fgets(line, LINE_SIZE, stdin) == NULL) {
printf("\n");
exit(0);
}
if (line[0] == 'q') {
exit(0);
}
if (line[0] == 0x1B) {
return 1;
}
return 0;
}
 
 
int checkBatch(int numLines) {
static int lines;
int r;
 
r = 0;
if (numLines == 0) {
/* initialize */
lines = 0;
} else {
/* output numLines lines */
lines += numLines;
if (lines >= LINES_PER_BATCH) {
r = waitForReturn();
lines = 0;
}
}
return r;
}
 
 
void rawBlock(unsigned char *p) {
int i, j;
unsigned char c;
 
checkBatch(0);
for (i = 0; i < BLOCK_SIZE / 16; i++) {
printf("%04X ", i * 16);
for (j = 0; j < 16; j++) {
c = p[i * 16 + j];
printf("%02X ", c);
}
printf(" ");
for (j = 0; j < 16; j++) {
c = p[i * 16 + j];
if (c < 0x20 || c >= 0x7F) {
printf(".");
} else {
printf("%c", c);
}
}
printf("\n");
if (checkBatch(1)) return;
}
}
 
 
void superBlock(unsigned char *p) {
unsigned int magic;
EOS32_daddr_t fsize;
EOS32_daddr_t isize;
EOS32_daddr_t freeblks;
EOS32_ino_t freeinos;
unsigned int ninode;
EOS32_ino_t ino;
unsigned int nfree;
EOS32_daddr_t free;
EOS32_time_t tim;
char *dat;
unsigned char flag;
int i;
 
checkBatch(0);
magic = get4Bytes(p);
p += 4;
printf("magic number = %u (0x%08X)\n", magic, magic);
if (checkBatch(1)) return;
fsize = get4Bytes(p);
p += 4;
printf("file system size = %lu (0x%lX) blocks\n", fsize, fsize);
if (checkBatch(1)) return;
isize = get4Bytes(p);
p += 4;
printf("inode list size = %lu (0x%lX) blocks\n", isize, isize);
if (checkBatch(1)) return;
freeblks = get4Bytes(p);
p += 4;
printf("free blocks = %lu (0x%lX)\n", freeblks, freeblks);
if (checkBatch(1)) return;
freeinos = get4Bytes(p);
p += 4;
printf("free inodes = %lu (0x%lX)\n", freeinos, freeinos);
if (checkBatch(1)) return;
ninode = get4Bytes(p);
p += 4;
printf("number of entries in free inode list = %u (0x%X)\n", ninode, ninode);
if (checkBatch(1)) return;
for (i = 0; i < NICINOD; i++) {
ino = get4Bytes(p);
p += 4;
if (i < ninode) {
printf(" free inode[%3d] = %lu (0x%lX)\n", i, ino, ino);
if (checkBatch(1)) return;
}
}
nfree = get4Bytes(p);
p += 4;
printf("number of entries in free block list = %u (0x%X)\n", nfree, nfree);
if (checkBatch(1)) return;
for (i = 0; i < NICFREE; i++) {
free = get4Bytes(p);
p += 4;
if (i < nfree) {
printf(" %s block[%3d] = %lu (0x%lX)\n",
i == 0 ? "link" : "free", i, free, free);
if (checkBatch(1)) return;
}
}
tim = get4Bytes(p);
p += 4;
dat = ctime((time_t *) &tim);
dat[strlen(dat) - 1] = '\0';
printf("last super block update = %ld (%s)\n", tim, dat);
if (checkBatch(1)) return;
flag = *p++;
printf("free list locked flag = %d\n", (int) flag);
if (checkBatch(1)) return;
flag = *p++;
printf("inode list locked flag = %d\n", (int) flag);
if (checkBatch(1)) return;
flag = *p++;
printf("super block modified flag = %d\n", (int) flag);
if (checkBatch(1)) return;
flag = *p++;
printf("fs mounted read-only flag = %d\n", (int) flag);
if (checkBatch(1)) return;
}
 
 
void inodeBlock(unsigned char *p) {
unsigned int mode;
unsigned int nlink;
unsigned int uid;
unsigned int gid;
EOS32_time_t tim;
char *dat;
EOS32_off_t size;
EOS32_daddr_t addr;
int i, j;
 
checkBatch(0);
for (i = 0; i < INOPB; i++) {
printf("inode %d:", i);
mode = get4Bytes(p);
p += 4;
if (mode != 0) {
printf(" type/mode = 0x%08X = ", mode);
if ((mode & IFMT) == IFREG) {
printf("-");
} else
if ((mode & IFMT) == IFDIR) {
printf("d");
} else
if ((mode & IFMT) == IFCHR) {
printf("c");
} else
if ((mode & IFMT) == IFBLK) {
printf("b");
} else {
printf("?");
}
printf("%c", mode & IUREAD ? 'r' : '-');
printf("%c", mode & IUWRITE ? 'w' : '-');
printf("%c", mode & IUEXEC ? 'x' : '-');
printf("%c", mode & IGREAD ? 'r' : '-');
printf("%c", mode & IGWRITE ? 'w' : '-');
printf("%c", mode & IGEXEC ? 'x' : '-');
printf("%c", mode & IOREAD ? 'r' : '-');
printf("%c", mode & IOWRITE ? 'w' : '-');
printf("%c", mode & IOEXEC ? 'x' : '-');
if (mode & ISUID) {
printf(", set uid");
}
if (mode & ISGID) {
printf(", set gid");
}
if (mode & ISVTX) {
printf(", save text");
}
} else {
printf(" <free>");
}
printf("\n");
if (checkBatch(1)) return;
nlink = get4Bytes(p);
p += 4;
if (mode != 0) {
printf(" nlnk = %u (0x%08X)\n", nlink, nlink);
if (checkBatch(1)) return;
}
uid = get4Bytes(p);
p += 4;
if (mode != 0) {
printf(" uid = %u (0x%08X)\n", uid, uid);
if (checkBatch(1)) return;
}
gid = get4Bytes(p);
p += 4;
if (mode != 0) {
printf(" gid = %u (0x%08X)\n", gid, gid);
if (checkBatch(1)) return;
}
tim = get4Bytes(p);
p += 4;
dat = ctime((time_t *) &tim);
dat[strlen(dat) - 1] = '\0';
if (mode != 0) {
printf(" time inode created = %ld (%s)\n", tim, dat);
if (checkBatch(1)) return;
}
tim = get4Bytes(p);
p += 4;
dat = ctime((time_t *) &tim);
dat[strlen(dat) - 1] = '\0';
if (mode != 0) {
printf(" time last modified = %ld (%s)\n", tim, dat);
if (checkBatch(1)) return;
}
tim = get4Bytes(p);
p += 4;
dat = ctime((time_t *) &tim);
dat[strlen(dat) - 1] = '\0';
if (mode != 0) {
printf(" time last accessed = %ld (%s)\n", tim, dat);
if (checkBatch(1)) return;
}
size = get4Bytes(p);
p += 4;
if (mode != 0) {
printf(" size = %lu (0x%lX)\n", size, size);
if (checkBatch(1)) return;
}
for (j = 0; j < 6; j++) {
addr = get4Bytes(p);
p += 4;
if (mode != 0) {
printf(" direct block[%1d] = %lu (0x%lX)\n", j, addr, addr);
if (checkBatch(1)) return;
}
}
addr = get4Bytes(p);
p += 4;
if (mode != 0) {
printf(" single indirect = %lu (0x%lX)\n", addr, addr);
if (checkBatch(1)) return;
}
addr = get4Bytes(p);
p += 4;
if (mode != 0) {
printf(" double indirect = %lu (0x%lX)\n", addr, addr);
if (checkBatch(1)) return;
}
}
}
 
 
void directoryBlock(unsigned char *p) {
EOS32_ino_t ino;
int i, j;
unsigned char c;
 
checkBatch(0);
for (i = 0; i < DIRPB; i++) {
printf("%02d: ", i);
ino = get4Bytes(p);
p += 4;
printf("inode = %lu (0x%lX)\n", ino, ino);
if (checkBatch(1)) return;
printf(" name = ");
if (*p == '\0') {
printf("<empty>");
} else {
for (j = 0; j < DIRSIZ; j++) {
c = *(p + j);
if (c == '\0') {
break;
}
if (c < 0x20 || c >= 0x7F) {
printf(".");
} else {
printf("%c", c);
}
}
}
printf("\n");
if (checkBatch(1)) return;
p += DIRSIZ;
}
}
 
 
void freeBlock(unsigned char *p) {
unsigned int nfree;
EOS32_daddr_t addr;
int i;
 
checkBatch(0);
nfree = get4Bytes(p);
p += 4;
printf("nfree = %u (0x%X)\n", nfree, nfree);
if (checkBatch(1)) return;
for (i = 0; i < NICFREE; i++) {
addr = get4Bytes(p);
p += 4;
if (i < nfree) {
printf(" %s block[%3d] = %lu (0x%lX)\n",
i == 0 ? "link" : "free", i, addr, addr);
if (checkBatch(1)) return;
}
}
}
 
 
void indirectBlock(unsigned char *p) {
EOS32_daddr_t addr;
int i;
 
checkBatch(0);
for (i = 0; i < BLOCK_SIZE / sizeof(EOS32_daddr_t); i++) {
addr = get4Bytes(p);
p += 4;
printf("block[%4d] = %lu (0x%lX)\n", i, addr, addr);
if (checkBatch(1)) return;
}
}
 
 
void help(void) {
printf("Commands are:\n");
printf(" h help\n");
printf(" q quit\n");
printf(" r show block as raw data\n");
printf(" s show block as super block\n");
printf(" i show block as inode block\n");
printf(" d show block as directory block\n");
printf(" f show block as block on the free list\n");
printf(" * show block as indirect block\n");
printf(" b <num> set current block to <num>\n");
printf(" + increment current block\n");
printf(" - decrement current block\n");
printf(" t <num> translate inode <num> to block number\n");
printf(" and relative inode number within block\n");
}
 
 
int parseNumber(char **pc, unsigned long *pi) {
char *p;
unsigned int base, dval;
unsigned long n;
 
p = *pc;
while (*p == ' ' || *p == '\t') {
p++;
}
if (*p == '\0' || *p == '\n') {
printf("Error: number is missing!\n");
return 0;
}
base = 10;
if (*p == '0') {
p++;
if (*p != '\0' && *p != '\n') {
if (*p == 'x' || *p == 'X') {
base = 16;
p++;
} else {
base = 8;
}
}
}
n = 0;
while ((*p >= '0' && *p <= '9') ||
(*p >= 'a' && *p <= 'f') ||
(*p >= 'A' && *p <= 'F')) {
if (*p >= '0' && *p <= '9') {
dval = (*p - '0');
} else
if (*p >= 'a' && *p <= 'f') {
dval = (*p - 'a' + 10);
} else
if (*p >= 'A' && *p <= 'F') {
dval = (*p - 'A' + 10);
}
if (dval >= base) {
printf("Error: digit value %d is illegal in number base %d\n",
dval, base);
return 0;
}
n *= base;
n += dval;
p++;
}
while (*p == ' ' || *p == '\t') {
p++;
}
*pc = p;
*pi = n;
return 1;
}
 
 
int main(int argc, char *argv[]) {
FILE *disk;
unsigned long fsSize;
int part;
char *endptr;
unsigned char partTable[SECTOR_SIZE];
unsigned char *ptptr;
unsigned long partType;
EOS32_daddr_t numBlocks;
EOS32_daddr_t currBlock;
unsigned char blockBuffer[BLOCK_SIZE];
char line[LINE_SIZE];
int quit;
char *p;
unsigned long n;
 
if (argc != 3) {
printf("Usage: %s <disk> <partition>\n", argv[0]);
printf(" <disk> is a disk image file name\n");
printf(" <partition> is a partition number ");
printf("(or '*' for the whole disk)\n");
exit(1);
}
disk = fopen(argv[1], "rb");
if (disk == NULL) {
error("cannot open disk image file '%s'", argv[1]);
}
if (strcmp(argv[2], "*") == 0) {
/* whole disk contains one single file system */
fsStart = 0;
fseek(disk, 0, SEEK_END);
fsSize = ftell(disk) / SECTOR_SIZE;
} else {
/* argv[2] is partition number of file system */
part = strtoul(argv[2], &endptr, 10);
if (*endptr != '\0' || part < 0 || part > 15) {
error("illegal partition number '%s'", argv[2]);
}
fseek(disk, 1 * SECTOR_SIZE, SEEK_SET);
if (fread(partTable, 1, SECTOR_SIZE, disk) != SECTOR_SIZE) {
error("cannot read partition table of disk '%s'", argv[1]);
}
ptptr = partTable + part * 32;
partType = get4Bytes(ptptr + 0);
if ((partType & 0x7FFFFFFF) != 0x00000058) {
error("partition %d of disk '%s' does not contain an EOS32 file system",
part, argv[1]);
}
fsStart = get4Bytes(ptptr + 4);
fsSize = get4Bytes(ptptr + 8);
}
printf("File system has size %lu (0x%lX) sectors of %d bytes each.\n",
fsSize, fsSize, SECTOR_SIZE);
if (fsSize % SPB != 0) {
printf("File system size is not a multiple of block size.\n");
}
numBlocks = fsSize / SPB;
printf("This equals %lu (0x%lX) blocks of %d bytes each.\n",
numBlocks, numBlocks, BLOCK_SIZE);
if (numBlocks < 2) {
error("file system has less than 2 blocks");
}
currBlock = 1;
readBlock(disk, currBlock, blockBuffer);
help();
quit = 0;
while (!quit) {
printf("shfs [block %lu (0x%lX)] > ", currBlock, currBlock);
fflush(stdout);
if (fgets(line, LINE_SIZE, stdin) == NULL) {
printf("\n");
break;
}
if (line[0] == '\0' || line[0] == '\n') {
continue;
}
switch (line[0]) {
case 'h':
case '?':
help();
break;
case 'q':
quit = 1;
break;
case 'r':
rawBlock(blockBuffer);
break;
case 's':
superBlock(blockBuffer);
break;
case 'i':
inodeBlock(blockBuffer);
break;
case 'd':
directoryBlock(blockBuffer);
break;
case 'f':
freeBlock(blockBuffer);
break;
case '*':
indirectBlock(blockBuffer);
break;
case 'b':
p = line + 1;
if (!parseNumber(&p, &n)) {
break;
}
if (*p != '\0' && *p != '\n') {
printf("Error: cannot parse block number!\n");
break;
}
if (n >= numBlocks) {
printf("Error: block number too big for file system!\n");
break;
}
currBlock = n;
readBlock(disk, currBlock, blockBuffer);
break;
case '+':
n = currBlock + 1;
if (n >= numBlocks) {
printf("Error: block number too big for file system!\n");
break;
}
currBlock = n;
readBlock(disk, currBlock, blockBuffer);
break;
case '-':
n = currBlock - 1;
if (n >= numBlocks) {
printf("Error: block number too big for file system!\n");
break;
}
currBlock = n;
readBlock(disk, currBlock, blockBuffer);
break;
case 't':
p = line + 1;
if (!parseNumber(&p, &n)) {
break;
}
if (*p != '\0' && *p != '\n') {
printf("Error: cannot parse inode number!\n");
break;
}
printf("inode %lu (0x%lX) is in block %lu (0x%lX), inode %lu\n",
n, n, n / INOPB + 2, n / INOPB + 2, n % INOPB);
break;
default:
printf("Unknown command, type 'h' for help!\n");
break;
}
}
fclose(disk);
return 0;
}
/Makefile.run
0,0 → 1,12
#
# Makefile for building an EOS32 file system
#
 
BUILD = ../..
 
all:
$(BUILD)/bin/EOS32-mkfs ../disk.img 0 root.fsys
$(BUILD)/bin/EOS32-mkfs ../disk.img 2 usr.fsys
 
clean:
rm -f *~
/Makefile
0,0 → 1,27
#
# Makefile for EOS32 disk tools
#
 
BUILD = ../../../build
 
DIRS = mkboot mkfs shfs
 
.PHONY: all install clean
 
all:
for i in $(DIRS) ; do \
$(MAKE) -C $$i all ; \
done
 
install:
for i in $(DIRS) ; do \
$(MAKE) -C $$i install ; \
done
mkdir -p $(BUILD)/run/fs-EOS32
cp Makefile.run $(BUILD)/run/fs-EOS32/Makefile
 
clean:
for i in $(DIRS) ; do \
$(MAKE) -C $$i clean ; \
done
rm -f *~

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.