vh.c 4.68 KB
/*
 * Copyright (C) 1996-1998 by the Board of Trustees
 *    of Leland Stanford Junior University.
 * 
 * This file is part of the SimOS distribution. 
 * See LICENSE file for terms of the license. 
 *
 */

/*
 * vh -  program to make a fake volume header for a disk file
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <bstring.h>
#include <sys/immu.h>		/* for NBPP */
#include <sys/dvh.h>		/* for volume header */
#include <sys/fs/efs_sb.h>	/* for super block */
#include <sys/mman.h>		/* for mmap() */
#include <sys/stat.h>		/* for open() */
#include <fcntl.h>		/* for open() */

#define HP_DISK_MODEL
#ifdef HP_DISK_MODEL
#include "diskmodel.param"
#include "diskdevices.h"

#define SECTOR_BYTES            SECTOR_SIZE
#define SECTORS_PER_TRACK       NSECTORS
#define TRACKS_PER_CYL          NTRACKS_PER_CYL         

#else
#define SECTOR_BYTES		512
/*
 * XXX Just picked these from the root disk on morse XXX 
 */
#define SECTORS_PER_TRACK	65
#define TRACKS_PER_CYL		15
#endif


void 
usage(char *progname)
{
  printf("Usage: %s [-r <size of swap partition in Mbytes>] <file name>\n", progname);
}

main(int argc, char **argv)
{
  register int			csum;
  int				fd;
  char				*filename;
  int				filesize, newFileSize;
  void				*map_addr;
  register int			*p;
  register struct volume_header	*vh;
  uint				tblks, eblks, sblks;
  extern char                   *optarg;
  extern int                    optind;
  int                           c, swapPartition = 0;

  if (argc < 1) {
    usage(argv[0]);
    exit(1);
  }

  while ((c = getopt(argc, argv, "r:")) != EOF) {
     switch (c) {
     case 'r':
        swapPartition = ((atoi(optarg)*1000000 + SECTOR_BYTES - 1) / SECTOR_BYTES) * SECTOR_BYTES;
        break;
        
     default:
        usage(argv[0]);
        exit(1);
        break;
     }
  }

  filename = argv[optind];
  fd = open(filename, O_RDWR, 0644);
  if (fd == -1) {
    perror("open");
    exit(2);
  }

  filesize = (int)lseek(fd, 0, SEEK_END);
  if (filesize < 0) {
    perror("lseek");
    exit(3);
  }
  filesize = ((filesize + SECTOR_BYTES - 1) / SECTOR_BYTES) * SECTOR_BYTES;

  if (swapPartition) {
     char zero = (char)0;

     newFileSize = filesize + swapPartition;
     if ((newFileSize = (int)lseek(fd, newFileSize, SEEK_SET)) < 0) {
        perror("lseek");
        exit(3);
     }
     if (write(fd, &zero, 1) < 0) {
        perror("write");
        exit(3);
     }
  } else {
     newFileSize = filesize;
  }

  map_addr = mmap(0, NBPP, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  if (map_addr == (void *)-1) {
    perror("mmap");
    exit(3);
  }

  vh = (struct volume_header *)map_addr;
  bzero(vh, sizeof(struct volume_header));

  vh->vh_magic = VHMAGIC;

  vh->vh_bootfile[0] = '/';
  vh->vh_bootfile[1] = 'u';
  vh->vh_bootfile[2] = 'n';
  vh->vh_bootfile[3] = 'i';
  vh->vh_bootfile[4] = 'x';
  vh->vh_bootfile[5] = '\0';


  vh->vh_dp.dp_secbytes = SECTOR_BYTES;

  vh->vh_dp.dp_trks0 = TRACKS_PER_CYL;
  vh->vh_dp.dp_secs = SECTORS_PER_TRACK;
  vh->vh_dp.dp_spares_cyl = 0;

  vh->vh_dp.dp_cyls = (newFileSize + (TRACKS_PER_CYL * SECTORS_PER_TRACK * SECTOR_BYTES) - 1) /
    (TRACKS_PER_CYL * SECTORS_PER_TRACK * SECTOR_BYTES);

  /* Use the standard partition method for a sgi disk with exceptions
     for backward compatibility. We have been using partition 1 as the
     main efs partition, instead of 0 which is more standard. So
     1 - EFS (size of the disk - 1 block)
     8 - Volume header (1 blocks)
     10 - Entire volume
     0 - is swap, same as EFS if not a root disk
         else 0 is a separate swap partition
   */

  eblks = (filesize) / SECTOR_BYTES;
  tblks = (newFileSize) / SECTOR_BYTES;
  sblks = swapPartition / SECTOR_BYTES;

  if (swapPartition) {
     /* EFS */
     vh->vh_rootpt = 0;
     vh->vh_swappt = 1;

     vh->vh_pt[0].pt_nblks = eblks;
     vh->vh_pt[0].pt_firstlbn = 0;
     vh->vh_pt[0].pt_type = PTYPE_EFS;

     /* Swap */
     vh->vh_pt[1].pt_nblks = sblks;
     vh->vh_pt[1].pt_firstlbn = eblks;
     vh->vh_pt[1].pt_type = PTYPE_RAW;
  } else {
     vh->vh_rootpt = 1;
     vh->vh_swappt = 0;

     /* EFS */
     vh->vh_pt[1].pt_nblks = eblks;
     vh->vh_pt[1].pt_firstlbn = 0;
     vh->vh_pt[1].pt_type = PTYPE_EFS;

     /* Swap */
     vh->vh_pt[0].pt_nblks = tblks - 1;
     vh->vh_pt[0].pt_firstlbn = 1;
     vh->vh_pt[0].pt_type = PTYPE_RAW;
  }

  /* Volume header */
  vh->vh_pt[8].pt_nblks = 1;
  vh->vh_pt[8].pt_firstlbn = 0;
  vh->vh_pt[8].pt_type = PTYPE_VOLHDR;

  /* Entire volume */
  vh->vh_pt[10].pt_nblks = tblks;
  vh->vh_pt[10].pt_firstlbn = 0;
  vh->vh_pt[10].pt_type = PTYPE_VOLUME;

  csum = 0;
  for (p = (int *)vh; p < (int *)(vh + 1); p++)
    csum += *p;

  vh->vh_csum = -csum;

  close(fd);

  exit(0);
}