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

Subversion Repositories eco32

[/] [eco32/] [trunk/] [disk/] [tools/] [mkpart/] [mkpart.c] - Rev 108

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

/*
 * mkpart.c -- make partitions on a disk
 */
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
 
 
#define SECTOR_SIZE	512
#define NPE		(SECTOR_SIZE / sizeof(PartEntry))
#define DESCR_SIZE	20
 
#define LINE_SIZE	100
 
 
unsigned char buf[32 * SECTOR_SIZE];
 
 
typedef struct {
  unsigned long type;
  unsigned long start;
  unsigned long size;
  char descr[DESCR_SIZE];
} PartEntry;
 
PartEntry ptr[NPE];
 
 
/**************************************************************/
 
 
void error(char *fmt, ...) {
  va_list ap;
 
  va_start(ap, fmt);
  printf("Error: ");
  vprintf(fmt, ap);
  printf("\n");
  va_end(ap);
  exit(1);
}
 
 
/**************************************************************/
 
 
void convertNumber(unsigned char *p, unsigned long val) {
  *(p + 0) = val >> 24;
  *(p + 1) = val >> 16;
  *(p + 2) = val >>  8;
  *(p + 3) = val >>  0;
}
 
 
void convertPartitionTable(PartEntry *e, int n) {
  int i;
  unsigned char *p;
 
  for (i = 0; i < n; i++) {
    p = (unsigned char *) &e[i];
    convertNumber(p + 0, e[i].type);
    convertNumber(p + 4, e[i].start);
    convertNumber(p + 8, e[i].size);
  }
}
 
 
/**************************************************************/
 
 
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 parseString(char **pc, char *dst) {
  char *p;
 
  p = *pc;
  while (*p == ' ' || *p == '\t') {
    p++;
  }
  if (*p != '\"') {
    return 0;
  }
  p++;
  while (*p != '\"' && *p != '\0' && *p != '\n') {
    *dst++ = *p++;
  }
  if (*p != '\"') {
    return 0;
  }
  p++;
  while (*p == ' ' || *p == '\t') {
    p++;
  }
  *pc = p;
  *dst = '\0';
  return 1;
}
 
 
/**************************************************************/
 
 
int main(int argc, char *argv[]) {
  char *diskName;
  char *confName;
  FILE *disk;
  FILE *conf;
  unsigned long diskSize;
  unsigned long numSectors;
  char line[LINE_SIZE];
  char *p, *q;
  int lineNumber;
  FILE *mbootblk;
  long mbootblkSize;
  int i;
  unsigned long partNum;
  unsigned long bootable;
  unsigned long partType;
  unsigned long partStart;
  unsigned long partLast;
  unsigned long partSize;
  char descr[LINE_SIZE];
 
  /* check command line arguments */
  if (argc != 3) {
    printf("Usage: %s <disk image file> <configuration file>\n", argv[0]);
    exit(1);
  }
  diskName = argv[1];
  confName = argv[2];
  /* determine disk size */
  disk = fopen(diskName, "rb");
  if (disk == NULL) {
    error("cannot open disk image '%s'", diskName);
  }
  fseek(disk, 0, SEEK_END);
  diskSize = ftell(disk);
  numSectors = diskSize / SECTOR_SIZE;
  fclose(disk);
  printf("Disk '%s' has %lu (0x%lX) sectors.\n",
         diskName, numSectors, numSectors);
  if (numSectors < 32) {
    error("disk is too small");
  }
  if (diskSize % SECTOR_SIZE != 0) {
    printf("Warning: disk size is not a multiple of sector size!\n");
  }
  /* create partition table */
  conf = fopen(confName, "rt");
  if (conf == NULL) {
    error("cannot open configuration file '%s'", confName);
  }
  lineNumber = 0;
  /* first, handle master boot block specification */
  while (fgets(line, LINE_SIZE, conf) != NULL) {
    lineNumber++;
    p = line;
    while (*p == ' ' || *p == '\t') {
      p++;
    }
    if (*p == '\0' || *p == '\n' || *p == '#') {
      continue;
    }
    q = p;
    while (*q > 0x20 && *q < 0x7F) {
      q++;
    }
    *q = '\0';
    if (strcmp(p, "-noboot-") == 0) {
      /* master boot block not wanted */
    } else {
      /* p points to name of master boot block file */
      mbootblk = fopen(p, "rb");
      if (mbootblk == NULL) {
        error("cannot open master boot block file '%s'", p);
      }
      fseek(mbootblk, 0, SEEK_END);
      mbootblkSize = ftell(mbootblk);
      fseek(mbootblk, 0, SEEK_SET);
      if (mbootblkSize > 32 * SECTOR_SIZE) {
        error("master boot block file '%s' is bigger than 32 sectors", p);
      }
      for (i = 0; i < 32 * SECTOR_SIZE; i++) {
        buf[i] = '\0';
      }
      if (fread(buf, 1, mbootblkSize, mbootblk) != mbootblkSize) {
        error("cannot read master boot block file '%s'", p);
      }
      fclose(mbootblk);
      disk = fopen(diskName, "r+b");
      if (disk == NULL) {
        error("cannot open disk image '%s'", diskName);
      }
      if (fwrite(buf, 1, 32 * SECTOR_SIZE, disk) != 32 * SECTOR_SIZE) {
        error("cannot write master boot block to disk image '%s'", diskName);
      }
      fclose(disk);
    }
    break;
  }
  /* then, handle partition table entries */
  while (fgets(line, LINE_SIZE, conf) != NULL) {
    lineNumber++;
    p = line;
    while (*p == ' ' || *p == '\t') {
      p++;
    }
    if (*p == '\0' || *p == '\n' || *p == '#') {
      continue;
    }
    if (!parseNumber(&p, &partNum)) {
      error("cannot read partition number in config file '%s', line %d",
            confName, lineNumber);
    }
    if (partNum >= 16) {
      error("illegal partition number in config file '%s', line %d",
            confName, lineNumber);
    }
    if (*p == '*') {
      p++;
      bootable = 0x80000000;
    } else {
      bootable = 0x00000000;
    }
    if (!parseNumber(&p, &partType)) {
      error("cannot read partition type in config file '%s', line %d",
            confName, lineNumber);
    }
    if ((partType & 0x80000000) != 0) {
      error("illegal partition type in config file '%s', line %d",
            confName, lineNumber);
    }
    if (!parseNumber(&p, &partStart)) {
      error("cannot read start sector in config file '%s', line %d",
            confName, lineNumber);
    }
    if (partStart < 32 || partStart >= numSectors) {
      error("illegal start sector in config file '%s', line %d",
            confName, lineNumber);
    }
    if (!parseNumber(&p, &partLast)) {
      error("cannot read last sector in config file '%s', line %d",
            confName, lineNumber);
    }
    if (partLast < partStart || partLast >= numSectors) {
      error("illegal last sector in config file '%s', line %d",
            confName, lineNumber);
    }
    partSize = partLast - partStart + 1;
    if (!parseString(&p, descr)) {
      error("cannot read description in config file '%s', line %d",
            confName, lineNumber);
    }
    if (strlen(descr) >= DESCR_SIZE) {
      error("description too long in config file '%s', line %d",
            confName, lineNumber);
    }
    if (partType != 0) {
      ptr[partNum].type = bootable | partType;
      ptr[partNum].start = partStart;
      ptr[partNum].size = partSize;
      memset(ptr[partNum].descr, 0, DESCR_SIZE);
      strcpy(ptr[partNum].descr, descr);
    } else {
      ptr[partNum].type = 0;
      ptr[partNum].start = 0;
      ptr[partNum].size = 0;
      memset(ptr[partNum].descr, 0, DESCR_SIZE);
    }
  }
  fclose(conf);
  /* next, show partition table */
  printf("Partitions:\n");
  printf(" # b type       start      last       size       description\n");
  for (partNum = 0; partNum < NPE; partNum++) {
    if (ptr[partNum].type != 0) {
      partLast = ptr[partNum].start + ptr[partNum].size - 1;
    } else {
      partLast = 0;
    }
    printf("%2lu %s 0x%08lX 0x%08lX 0x%08lX 0x%08lX %s\n",
           partNum,
           ptr[partNum].type & 0x80000000 ? "*" : " ",
           ptr[partNum].type & 0x7FFFFFFF,
           ptr[partNum].start,
           partLast,
           ptr[partNum].size,
           ptr[partNum].descr);
  }
  /* finally, write partition table record */
  convertPartitionTable(ptr, NPE);
  disk = fopen(diskName, "r+b");
  if (disk == NULL) {
    error("cannot open disk image '%s'", diskName);
  }
  fseek(disk, 1 * SECTOR_SIZE, SEEK_SET);
  if (fwrite(ptr, 1, SECTOR_SIZE, disk) != SECTOR_SIZE) {
    error("cannot write partition table to disk image '%s'", diskName);
  }
  fclose(disk);
  /* done */
  return 0;
}
 

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

powered by: WebSVN 2.1.0

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