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

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.22/] [disk/] [tools/] [fs-NetBSD/] [loader/] [loader.c] - Blame information for rev 17

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 17 hellwig
/*
2
 * loader.c -- the NetBSD system loader
3
 */
4
 
5
 
6
#include "types.h"
7
#include "disklabel.h"
8
#include "fs.h"
9
#include "dinode.h"
10
#include "dir.h"
11
#include "stdarg.h"
12
#include "auxlib.h"
13
#include "biolib.h"
14
#include "elf.h"
15
 
16
 
17
/**************************************************************/
18
 
19
/* constants and data types */
20
 
21
 
22
#define DFLT_KERNEL     "/netbsd"       /* default path to kernel */
23
 
24
#define MAX_LINE        100             /* line buffer size */
25
 
26
#define SSHIFT          9               /* ld of sector size */
27
#define SSIZE           (1 << SSHIFT)   /* disk sector size in bytes */
28
#define SMASK           (SSIZE - 1)     /* sector mask */
29
 
30
#define BSHIFT          13              /* ld of block size */
31
#define BSIZE           (1 << BSHIFT)   /* disk block size in bytes */
32
#define BMASK           (BSIZE - 1)     /* block mask */
33
 
34
 
35
typedef struct ufs1_dinode Dinode;
36
typedef struct direct Dirent;
37
typedef unsigned int daddr_t;
38
typedef unsigned int ino_t;
39
 
40
 
41
#define NIPB            (BSIZE / sizeof(Dinode))
42
 
43
#define NULL            0
44
 
45
 
46
/**************************************************************/
47
 
48
/* debugging */
49
 
50
 
51
Bool debugReadSectors = FALSE;
52
Bool debugReadDiskLabel = FALSE;
53
Bool debugReadSuperBlock = FALSE;
54
Bool debugGetInode = FALSE;
55
Bool debugSearchDir = FALSE;
56
Bool debugLoadElf = FALSE;
57
 
58
 
59
/**************************************************************/
60
 
61
/* halt with error message */
62
 
63
 
64
void halt(char *msg) {
65
  printf("%s, machine halted.\n", msg);
66
  while (1) ;
67
}
68
 
69
 
70
/**************************************************************/
71
 
72
/* disk I/O */
73
 
74
 
75
unsigned int bootDisk = 0;       /* gets loaded by previous stage */
76
                                /* never changed */
77
unsigned int startSector = 0;    /* gets loaded by previous stage */
78
                                /* initially holds start of slice */
79
                                /* disklabel read --> start of partition */
80
unsigned int numSectors = 0;     /* gets loaded by previous stage */
81
                                /* initially holds size of slice */
82
                                /* disklabel read --> size of partition */
83
 
84
unsigned int spf;               /* superblock read --> sectors per fragment */
85
unsigned int spb;               /* superblock read --> sectors per block */
86
 
87
 
88
/*
89
 * read disk sectors
90
 *
91
 * NOTE: buffer must be word-aligned
92
 */
93
void readSectors(unsigned int start,
94
                 unsigned int count,
95
                 void *buffer) {
96
  unsigned int sector;
97
  int result;
98
 
99
  if (start + count > numSectors) {
100
    halt("Sector number exceeds slice or partition size");
101
  }
102
  sector = startSector + start;
103
  if (debugReadSectors) {
104
    printf("DEBUG: reading sector 0x%08X, %d sectors\n", sector, count);
105
  }
106
  result = rwscts(bootDisk, 'r', sector,
107
                  (unsigned int) buffer & 0x3FFFFFFF, count);
108
  if (result != 0) {
109
    halt("Load error");
110
  }
111
}
112
 
113
 
114
/**************************************************************/
115
 
116
/* disklabel handling */
117
 
118
 
119
unsigned int diskLabel[SSIZE / sizeof(unsigned int)];
120
DiskLabel *dlp = (DiskLabel *) &diskLabel[0];
121
 
122
unsigned int superStart;        /* partition-relative offset, in sectors */
123
unsigned int superSize;         /* size, in sectors */
124
 
125
 
126
void readDiskLabel(void) {
127
  readSectors(1, 1, dlp);
128
  if (dlp->d_magic != DSKMAGIC ||
129
      dlp->d_magic2 != DSKMAGIC) {
130
    halt("Disklabel corrupted");
131
  }
132
 
133
  startSector = dlp->d_parts[0].p_offset;
134
  numSectors = dlp->d_parts[0].p_size;
135
 
136
  superStart = dlp->d_bbsize;
137
  if ((superStart & SMASK) != 0) {
138
    halt("Superblock offset is not multiple of sector size");
139
  }
140
  superStart >>= SSHIFT;
141
 
142
  superSize = dlp->d_sbsize;
143
  if ((superSize & SMASK) != 0) {
144
    halt("Superblock size is not multiple of sector size");
145
  }
146
  if (superSize > BSIZE) {
147
    halt("Superblock too big");
148
  }
149
  superSize >>= SSHIFT;
150
 
151
  if (debugReadDiskLabel) {
152
    printf("DEBUG: super start = %d sectors, super size = %d sectors\n",
153
           superStart, superSize);
154
  }
155
}
156
 
157
 
158
/**************************************************************/
159
 
160
/* superblock handling */
161
 
162
 
163
unsigned int superBlock[BSIZE / sizeof(unsigned int)];
164
struct fs *sbp = (struct fs *) &superBlock[0];
165
 
166
 
167
void readSuperBlock(void) {
168
  readSectors(superStart, superSize, sbp);
169
  if (sbp->fs_magic != FS_UFS1_MAGIC) {
170
    halt("Wrong magic number in superblock");
171
  }
172
  spf = sbp->fs_fsize / SSIZE;
173
  spb = sbp->fs_bsize / SSIZE;
174
  if (sbp->fs_inopb != NIPB) {
175
    halt("Wrong number of inodes per block");
176
  }
177
  if (debugReadSuperBlock) {
178
    printf("DEBUG: %d sectors per fragment\n", spf);
179
    printf("DEBUG: %d sectors per block\n", spb);
180
    printf("DEBUG: %d inodes per block\n", NIPB);
181
  }
182
}
183
 
184
 
185
/**************************************************************/
186
 
187
/* file operations */
188
 
189
 
190
unsigned int sibno = 0;
191
unsigned int sib[8192 / sizeof(unsigned int)];
192
unsigned int *sibp = (unsigned int *) &sib[0];
193
 
194
 
195
/*
196
 * read a block of a file
197
 *
198
 * NOTE: addr must be word-aligned
199
 */
200
void readFileBlock(Dinode *ip, int blkno, void *addr) {
201
  unsigned int diskFrag;
202
 
203
  if (blkno < NDADDR) {
204
    /* direct block */
205
    diskFrag = ip->di_db[blkno];
206
  } else
207
  if (blkno - NDADDR < sbp->fs_bsize / sizeof(int32_t)) {
208
    /* single indirect block */
209
    if (sibno != ip->di_ib[0]) {
210
      sibno = ip->di_ib[0];
211
      readSectors(sibno * spf, spb, sibp);
212
    }
213
    diskFrag = sibp[blkno - NDADDR];
214
  } else {
215
    /* double or triple indirect blocks */
216
    halt("Cannot do double or triple indirect blocks");
217
  }
218
  readSectors(diskFrag * spf, spb, addr);
219
}
220
 
221
 
222
/*
223
 * read a number of bytes from a file
224
 */
225
void readFile(Dinode *ip, unsigned int offset,
226
              unsigned int size, void *buffer) {
227
  unsigned int dskblk[8192 / sizeof(unsigned int)];
228
  unsigned char *bufp;
229
  unsigned char *blkp;
230
  unsigned int blkno;
231
  unsigned int index;
232
  unsigned int aux;
233
  unsigned int numBytes;
234
  int i;
235
 
236
  bufp = (unsigned char *) buffer;
237
  blkp = (unsigned char *) dskblk;
238
  blkno = offset / sbp->fs_bsize;
239
  index = offset % sbp->fs_bsize;
240
  aux = sbp->fs_bsize - index;
241
  numBytes = (size <= aux) ? size : aux;
242
  readFileBlock(ip, blkno, blkp);
243
  for (i = 0; i < numBytes; i++) {
244
    *bufp++ = blkp[index++];
245
  }
246
  blkno++;
247
  size -= numBytes;
248
  while (size >= sbp->fs_bsize) {
249
    index = 0;
250
    numBytes = sbp->fs_bsize;
251
    readFileBlock(ip, blkno, blkp);
252
    for (i = 0; i < numBytes; i++) {
253
      *bufp++ = blkp[index++];
254
    }
255
    blkno++;
256
    size -= numBytes;
257
  }
258
  if (size > 0) {
259
    index = 0;
260
    numBytes = size;
261
    readFileBlock(ip, blkno, blkp);
262
    for (i = 0; i < numBytes; i++) {
263
      *bufp++ = blkp[index++];
264
    }
265
  }
266
}
267
 
268
 
269
/**************************************************************/
270
 
271
/* inode handling */
272
 
273
 
274
unsigned int inodeBlock[BSIZE / sizeof(unsigned int)];
275
Dinode *ibp = (Dinode *) &inodeBlock[0];
276
 
277
 
278
Dinode *getInode(unsigned int inode) {
279
  unsigned int fnum;
280
  unsigned int inum;
281
  Dinode *ip;
282
 
283
  fnum = ino_to_fsba(sbp, inode);
284
  inum = ino_to_fsbo(sbp, inode);
285
  if (debugGetInode) {
286
    printf("DEBUG: getting inode 0x%08X\n", inode);
287
    printf("DEBUG: this is in fragment %d, inode %d\n", fnum, inum);
288
  }
289
  readSectors(fnum * spf, spb, ibp);
290
  ip = ibp + inum;
291
  if (ip->di_size[0] != 0) {
292
    halt("File too big");
293
  }
294
  if (debugGetInode) {
295
    printf("DEBUG: mode of file = 0x%04X\n", ip->di_mode);
296
    printf("DEBUG: size of file = 0x%08X\n", ip->di_size[1]);
297
  }
298
  return ip;
299
}
300
 
301
 
302
/**************************************************************/
303
 
304
/* convert path to inode */
305
 
306
 
307
unsigned int directoryBlock[BSIZE / sizeof(unsigned int)];
308
Dirent *dbp = (Dirent *) &directoryBlock[0];
309
 
310
 
311
Dinode *pathToInode(char *path) {
312
  Dinode *ip;
313
  char c;
314
  char dirBuffer[FFS_MAXNAMLEN];
315
  char *cp;
316
  unsigned int offset;
317
  Dirent *dp;
318
  unsigned int ino;
319
  unsigned int len;
320
 
321
  /* get root inode */
322
  ip = getInode(ROOTINO);
323
  /* traverse file system tree while matching path components */
324
  c = *path++;
325
  while (1) {
326
    /* skip leading slashes in path component */
327
    while (c == '/') {
328
      c = *path++;
329
    }
330
    if (c == '\0') {
331
      /* no more path components */
332
      break;
333
    }
334
    /* if there is another component, gather up its name */
335
    cp = dirBuffer;
336
    while (c != '/' && c != '\0') {
337
      if (cp < &dirBuffer[FFS_MAXNAMLEN]) {
338
        *cp++ = c;
339
      }
340
      c = *path++;
341
    }
342
    *cp++ = '\0';
343
    /* ip must be a directory */
344
    if ((ip->di_mode & IFMT) != IFDIR) {
345
      return NULL;
346
    }
347
    if (debugSearchDir) {
348
      printf("DEBUG: this is a directory, ok\n");
349
      printf("DEBUG: path component to search for = '%s'\n", dirBuffer);
350
    }
351
    /* search directory */
352
    offset = 0;
353
    while (1) {
354
      if (offset >= ip->di_size[1]) {
355
        /* component not found */
356
        return NULL;
357
      }
358
      if ((offset & BMASK) == 0) {
359
        /* read the next directory block */
360
        readFileBlock(ip, offset >> BSHIFT, dbp);
361
        dp = dbp;
362
      }
363
      ino = dp->d_fileno;
364
      len = dp->d_reclen;
365
      if (debugSearchDir) {
366
        printf("DEBUG: ino = %4d, len = %4d, ", ino, len);
367
        printf("dirsiz = %4d, name = %s\n", DIRSIZ(0, dp, 0), dp->d_name);
368
      }
369
      if (ino != 0) {
370
        if (strcmp(dirBuffer, dp->d_name) == 0) {
371
          /* component found */
372
          break;
373
        }
374
      }
375
      /* no match, try next entry */
376
      dp = (Dirent *) ((unsigned char *) dp + len);
377
      offset += len;
378
    }
379
    /* get corresponding inode */
380
    ip = getInode(ino);
381
    /* look for more components */
382
  }
383
  return ip;
384
}
385
 
386
 
387
/**************************************************************/
388
 
389
/* load an ELF executable */
390
 
391
 
392
#define MAX_PHDR_SIZE   100
393
 
394
 
395
Bool loadElf(Dinode *ip, unsigned int *entryPointPtr) {
396
  Elf32_Ehdr fileHeader;
397
  Elf32_Addr entry;
398
  Elf32_Off phoff;
399
  Elf32_Half phentsize;
400
  Elf32_Half phnum;
401
  int i;
402
  unsigned int phdrBuf[MAX_PHDR_SIZE / sizeof(unsigned int)];
403
  Elf32_Phdr *phdrPtr;
404
  Elf32_Word ptype;
405
  Elf32_Off offset;
406
  Elf32_Addr address;
407
  Elf32_Word filesize;
408
  Elf32_Word memsize;
409
  Elf32_Word flags;
410
  Elf32_Word align;
411
  unsigned char *memPtr;
412
  int j;
413
 
414
  readFile(ip, 0, sizeof(Elf32_Ehdr), &fileHeader);
415
  if (fileHeader.e_ident[EI_MAG0] != ELFMAG0 ||
416
      fileHeader.e_ident[EI_MAG1] != ELFMAG1 ||
417
      fileHeader.e_ident[EI_MAG2] != ELFMAG2 ||
418
      fileHeader.e_ident[EI_MAG3] != ELFMAG3 ||
419
      fileHeader.e_ident[EI_CLASS] != ELFCLASS32 ||
420
      fileHeader.e_ident[EI_DATA] != ELFDATA2MSB ||
421
      fileHeader.e_type != ET_EXEC ||
422
      fileHeader.e_machine != EM_ECO32) {
423
    /* file is not in ECO32-ELF executable format */
424
    return FALSE;
425
  }
426
  entry = fileHeader.e_entry;
427
  phoff = fileHeader.e_phoff;
428
  phentsize = fileHeader.e_phentsize;
429
  phnum = fileHeader.e_phnum;
430
  if (debugLoadElf) {
431
    printf("DEBUG: entry point (virtual addr) : 0x%08X\n", entry);
432
    printf("DEBUG: program header table at    : %d\n", phoff);
433
    printf("DEBUG: prog hdr tbl entry size    : %d\n", phentsize);
434
    printf("DEBUG: num prog hdr tbl entries   : %d\n", phnum);
435
  }
436
  for (i = 0 ; i < phnum; i++) {
437
    printf("Processing program header %d\n", i);
438
    readFile(ip, phoff + i * phentsize, phentsize, phdrBuf);
439
    phdrPtr = (Elf32_Phdr *) phdrBuf;
440
    ptype = phdrPtr->p_type;
441
    if (ptype != PT_LOAD) {
442
      printf("    type is %u, ignored\n", ptype);
443
      continue;
444
    }
445
    offset = phdrPtr->p_offset;
446
    address = phdrPtr->p_vaddr;
447
    filesize = phdrPtr->p_filesz;
448
    memsize = phdrPtr->p_memsz;
449
    flags = phdrPtr->p_flags;
450
    align = phdrPtr->p_align;
451
    if (debugLoadElf) {
452
      printf("DEBUG: offset   : 0x%08X bytes\n", offset);
453
      printf("DEBUG: address  : 0x%08X\n", address);
454
      printf("DEBUG: filesize : 0x%08X bytes\n", filesize);
455
      printf("DEBUG: memsize  : 0x%08X bytes\n", memsize);
456
      printf("DEBUG: flags    : 0x%08X\n", flags);
457
      printf("DEBUG: align    : 0x%08X\n", align);
458
    }
459
    memPtr = (unsigned char *) address;
460
    readFile(ip, offset, filesize, memPtr);
461
    for (j = filesize; j < memsize; j++) {
462
      memPtr[j] = 0;
463
    }
464
    printf("    segment of %u bytes read", filesize);
465
    printf(" (+ %u bytes zeroed)", memsize - filesize);
466
    printf(", vaddr = 0x%08X\n", address);
467
  }
468
  *entryPointPtr = entry;
469
  return TRUE;
470
}
471
 
472
 
473
/**************************************************************/
474
 
475
/* main program */
476
 
477
 
478
unsigned int entryPoint;        /* where to continue from main() */
479
 
480
 
481
int main(void) {
482
  char line[MAX_LINE];
483
  Dinode *ip;
484
 
485
  printf("\n");
486
  printf("NetBSD system loader\n");
487
  readDiskLabel();
488
  readSuperBlock();
489
  strcpy(line, DFLT_KERNEL);
490
  while (1) {
491
    getLine("\nPlease enter path to kernel: ", line, MAX_LINE);
492
    ip = pathToInode(line);
493
    if (ip == NULL) {
494
      printf("'%s' not found\n", line);
495
      continue;
496
    }
497
    if ((ip->di_mode & IFMT) != IFREG) {
498
      printf("'%s' is not a regular file\n", line);
499
      continue;
500
    }
501
    printf("Loading '%s'...\n", line);
502
    if (!loadElf(ip, &entryPoint)) {
503
      printf("'%s' cannot be loaded\n", line);
504
      continue;
505
    }
506
    /* kernel successfully loaded */
507
    break;
508
  }
509
  printf("Starting '%s' at address 0x%08X...\n", line, entryPoint);
510
  return 0;
511
}

powered by: WebSVN 2.1.0

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