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.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 *~ |