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

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.22/] [disk/] [tools/] [fs-EOS32/] [mkboot/] [stage2/] [boot.c] - Blame information for rev 21

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 17 hellwig
/*
2
 * boot.c -- the bootstrap (boot loader)
3
 */
4
 
5
 
6
#include "biolib.h"
7
 
8
 
9
/**************************************************************/
10
 
11
/* constants and data types */
12
 
13
 
14
#define DFLT_KERNEL     "/boot/eos32.bin"    /* path of default OS kernel */
15
#define LOAD_ADDR       0xC0000000           /* where to load the kernel */
16
 
17
#define MAX_LINE        100             /* line buffer size */
18
 
19
#define EXEC_MAGIC      0x3AE82DD4      /* magic number for executables */
20
 
21
#define PSHIFT          12              /* ld of page size */
22
#define PSIZE           (1 << PSHIFT)   /* page size in bytes */
23
#define PMASK           (PSIZE - 1)     /* page mask */
24
 
25
#define BSHIFT          12              /* ld of block size */
26
#define BSIZE           (1 << BSHIFT)   /* disk block size in bytes */
27
#define BMASK           (BSIZE - 1)     /* block mask */
28
 
29
#define SSIZE           512             /* disk sector size in bytes */
30
#define SPB             (BSIZE / SSIZE) /* sectors per block */
31
 
32
#define ROOT_INO        1       /* inode number of root directory */
33
#define NADDR           8       /* number of block addresses in inode */
34
#define NDADDR          6       /* number of direct block addresses */
35
#define DIRSIZ          60      /* max length of path name component */
36
 
37
#define NIPB            (BSIZE / sizeof(Dinode))
38
#define NDIRENT         (BSIZE / sizeof(Dirent))
39
#define NINDIR          (BSIZE / sizeof(EOS32_daddr_t))
40
 
41
#define NULL            0
42
 
43
 
44
typedef unsigned long EOS32_ino_t;
45
typedef unsigned long EOS32_daddr_t;
46
typedef unsigned long EOS32_off_t;
47
typedef long EOS32_time_t;
48
 
49
 
50
#define IFMT            070000  /* type of file */
51
#define   IFREG         040000  /* regular file */
52
#define   IFDIR         030000  /* directory */
53
#define   IFCHR         020000  /* character special */
54
#define   IFBLK         010000  /* block special */
55
#define   IFFREE        000000  /* reserved (indicates free inode) */
56
#define ISUID           004000  /* set user id on execution */
57
#define ISGID           002000  /* set group id on execution */
58
#define ISVTX           001000  /* save swapped text even after use */
59
#define IUREAD          000400  /* user's read permission */
60
#define IUWRITE         000200  /* user's write permission */
61
#define IUEXEC          000100  /* user's execute permission */
62
#define IGREAD          000040  /* group's read permission */
63
#define IGWRITE         000020  /* group's write permission */
64
#define IGEXEC          000010  /* group's execute permission */
65
#define IOREAD          000004  /* other's read permission */
66
#define IOWRITE         000002  /* other's write permission */
67
#define IOEXEC          000001  /* other's execute permission */
68
 
69
/*
70
 * The following two macros convert an inode number to the disk
71
 * block containing the inode and an inode number within the block.
72
 */
73
#define itod(i)         (2 + (i) / NIPB)
74
#define itoo(i)         ((i) % NIPB)
75
 
76
 
77
typedef struct {
78
  unsigned int di_mode;         /* type and mode of file */
79
  unsigned int di_nlink;        /* number of links to file */
80
  unsigned int di_uid;          /* owner's user id */
81
  unsigned int di_gid;          /* owner's group id */
82
  EOS32_time_t di_ctime;        /* time created */
83
  EOS32_time_t di_mtime;        /* time last modified */
84
  EOS32_time_t di_atime;        /* time last accessed */
85
  EOS32_off_t di_size;          /* number of bytes in file */
86
  EOS32_daddr_t di_addr[NADDR]; /* disk block addresses */
87
} Dinode;
88
 
89
 
90
typedef struct {
91
  EOS32_ino_t d_ino;            /* directory inode */
92
  char d_name[DIRSIZ];          /* directory name */
93
} Dirent;
94
 
95
 
96
/**************************************************************/
97
 
98
/* string functions */
99
 
100
 
101
int strlen(char *str) {
102
  int i;
103
 
104
  i = 0;
105
  while (*str++ != '\0') {
106
    i++;
107
  }
108
  return i;
109
}
110
 
111
 
112
int strcmp(char *str1, char *str2) {
113
  while (*str1 == *str2) {
114
    if (*str1 == '\0') {
115
      return 0;
116
    }
117
    str1++;
118
    str2++;
119
  }
120
  return (* (unsigned char *) str1) - (* (unsigned char *) str2);
121
}
122
 
123
 
124
void strcpy(char *dst, char *src) {
125
  while ((*dst++ = *src++) != '\0') ;
126
}
127
 
128
 
129
/**************************************************************/
130
 
131
/* terminal I/O */
132
 
133
 
134
char getchar(void) {
135
  return getc();
136
}
137
 
138
 
139
void putchar(char c) {
140
  if (c == '\n') {
141
    putchar('\r');
142
  }
143
  putc(c);
144
}
145
 
146
 
147
void puts(char *s) {
148
  while (*s != '\0') {
149
    putchar(*s++);
150
  }
151
}
152
 
153
 
154
/**************************************************************/
155
 
156
/* get a line from the terminal */
157
 
158
 
159
void getLine(char *prompt, char *line, int max) {
160
  int index;
161
  char c;
162
 
163
  puts(prompt);
164
  puts(line);
165
  index = strlen(line);
166
  while (1) {
167
    c = getchar();
168
    switch (c) {
169
      case '\r':
170
        putchar('\n');
171
        line[index] = '\0';
172
        return;
173
      case '\b':
174
      case 0x7F:
175
        if (index == 0) {
176
          break;
177
        }
178
        putchar('\b');
179
        putchar(' ');
180
        putchar('\b');
181
        index--;
182
        break;
183
      default:
184
        if (c == '\t') {
185
          c = ' ';
186
        }
187
        if (c < 0x20 || c > 0x7E) {
188
          break;
189
        }
190
        putchar(c);
191
        line[index++] = c;
192
        break;
193
    }
194
  }
195
}
196
 
197
 
198
/**************************************************************/
199
 
200
/* halt with error message */
201
 
202
 
203
void halt(char *msg) {
204
  puts(msg);
205
  puts(", machine halted.\n");
206
  while (1) ;
207
}
208
 
209
 
210
/**************************************************************/
211
 
212
/* disk I/O */
213
 
214
 
215
unsigned int bootDisk = 0;       /* gets loaded by previous stage */
216
unsigned int startSector = 0;    /* gets loaded by previous stage */
217
unsigned int numSectors = 0;     /* gets loaded by previous stage */
218
 
219
 
220
/*
221
 * read a disk block
222
 *
223
 * NOTE: buffer must be word-aligned
224
 */
225
void readBlock(unsigned int blkno, void *buffer) {
226
  unsigned int sector;
227
  int result;
228
 
229
  sector = blkno * SPB;
230
  if (sector + SPB > numSectors) {
231
    halt("Sector number exceeds disk or partition size");
232
  }
233
  result = rwscts(bootDisk, 'r', sector + startSector,
234
                  (unsigned int) buffer & 0x3FFFFFFF, SPB);
235
  if (result != 0) {
236
    halt("Load error");
237
  }
238
}
239
 
240
 
241
/**************************************************************/
242
 
243
/* file operations*/
244
 
245
 
246
EOS32_daddr_t sibn = -1;
247
EOS32_daddr_t singleIndirectBlock[NINDIR];
248
EOS32_daddr_t dibn = -1;
249
EOS32_daddr_t doubleIndirectBlock[NINDIR];
250
 
251
 
252
/*
253
 * read a block of a file
254
 *
255
 * NOTE: addr must be word-aligned
256
 */
257
void readFileBlock(Dinode *ip, int blkno, void *addr) {
258
  EOS32_daddr_t diskBlock;
259
 
260
  if (blkno < NDADDR) {
261
    /* direct block */
262
    diskBlock = ip->di_addr[blkno];
263
  } else
264
  if (blkno < NDADDR + NINDIR) {
265
    /* single indirect block */
266
    diskBlock = ip->di_addr[NDADDR];
267
    if (sibn != diskBlock) {
268
      readBlock(diskBlock, singleIndirectBlock);
269
      sibn = diskBlock;
270
    }
271
    diskBlock = singleIndirectBlock[blkno - NDADDR];
272
  } else {
273
    /* double indirect block */
274
    diskBlock = ip->di_addr[NDADDR + 1];
275
    if (dibn != diskBlock) {
276
      readBlock(diskBlock, doubleIndirectBlock);
277
      dibn = diskBlock;
278
    }
279
    diskBlock = doubleIndirectBlock[(blkno - NDADDR - NINDIR) / NINDIR];
280
    if (sibn != diskBlock) {
281
      readBlock(diskBlock, singleIndirectBlock);
282
      sibn = diskBlock;
283
    }
284
    diskBlock = singleIndirectBlock[(blkno - NDADDR - NINDIR) % NINDIR];
285
  }
286
  readBlock(diskBlock, addr);
287
}
288
 
289
 
290
/**************************************************************/
291
 
292
/* inode handling */
293
 
294
 
295
Dinode inodeBlock[NIPB];
296
 
297
 
298
Dinode *getInode(unsigned int inode) {
299
  unsigned int bnum;
300
  unsigned int inum;
301
 
302
  bnum = itod(inode);
303
  inum = itoo(inode);
304
  readBlock(bnum, inodeBlock);
305
  return &inodeBlock[inum];
306
}
307
 
308
 
309
/**************************************************************/
310
 
311
/* convert path to inode */
312
 
313
 
314
Dirent directoryBlock[NDIRENT];
315
 
316
 
317
Dinode *pathToInode(char *path) {
318
  Dinode *ip;
319
  char c;
320
  char dirBuffer[DIRSIZ];
321
  char *cp;
322
  EOS32_off_t offset;
323
  Dirent *dp;
324
  unsigned int ino;
325
 
326
  /* get root inode */
327
  ip = getInode(ROOT_INO);
328
  /* traverse file system tree while matching path components */
329
  c = *path++;
330
  while (1) {
331
    /* skip leading slashes in path component */
332
    while (c == '/') {
333
      c = *path++;
334
    }
335
    if (c == '\0') {
336
      /* no more path components */
337
      break;
338
    }
339
    /* if there is another component, gather up its name */
340
    cp = dirBuffer;
341
    while (c != '/' && c != '\0') {
342
      if (cp < &dirBuffer[DIRSIZ]) {
343
        *cp++ = c;
344
      }
345
      c = *path++;
346
    }
347
    *cp++ = '\0';
348
    /* ip must be a directory */
349
    if ((ip->di_mode & IFMT) != IFDIR) {
350
      return NULL;
351
    }
352
    /* search directory */
353
    offset = 0;
354
    while (1) {
355
      if (offset >= ip->di_size) {
356
        /* component not found */
357
        return NULL;
358
      }
359
      if ((offset & BMASK) == 0) {
360
        /* read the next directory block */
361
        readFileBlock(ip, offset >> BSHIFT, directoryBlock);
362
        dp = directoryBlock;
363
      }
364
      ino = dp->d_ino;
365
      if (ino != 0) {
366
        if (strcmp(dirBuffer, dp->d_name) == 0) {
367
          /* component found */
368
          break;
369
        }
370
      }
371
      /* no match, try next entry */
372
      dp++;
373
      offset += sizeof(Dirent);
374
    }
375
    /* get corresponding inode */
376
    ip = getInode(ino);
377
    /* look for more components */
378
  }
379
  return ip;
380
}
381
 
382
 
383
/**************************************************************/
384
 
385
/* load the kernel */
386
 
387
 
388
void loadKernel(Dinode *ip) {
389
  unsigned int numBlocks;
390
  unsigned int nextBlock;
391
  unsigned char *nextAddr;
392
 
393
  numBlocks = (ip->di_size + (BSIZE - 1)) / BSIZE;
394
  nextBlock = 0;
395
  nextAddr = (unsigned char *) LOAD_ADDR;
396
  while (numBlocks--) {
397
    readFileBlock(ip, nextBlock, nextAddr);
398
    nextBlock++;
399
    nextAddr += BSIZE;
400
  }
401
}
402
 
403
 
404
/**************************************************************/
405
 
406
/* main program */
407
 
408
 
409
unsigned int entryPoint;        /* where to continue from main() */
410
 
411
 
412
int main(void) {
413
  char line[MAX_LINE];
414
  Dinode *ip;
415
 
416
  puts("Bootstrap loader executing...\n");
417
  strcpy(line, DFLT_KERNEL);
418
  while (1) {
419
    getLine("\nPlease enter path to kernel: ", line, MAX_LINE);
420
    ip = pathToInode(line);
421
    if (ip == NULL) {
422
      puts("'");
423
      puts(line);
424
      puts("' not found\n");
425
      continue;
426
    }
427
    if ((ip->di_mode & IFMT) != IFREG) {
428
      puts("'");
429
      puts(line);
430
      puts("' is not a regular file\n");
431
      continue;
432
    }
433
    break;
434
  }
435
  puts("Loading '");
436
  puts(line);
437
  puts("'...\n");
438
  loadKernel(ip);
439
  puts("Starting '");
440
  puts(line);
441
  puts("'...\n");
442
  entryPoint = LOAD_ADDR;
443
  return 0;
444
}

powered by: WebSVN 2.1.0

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