patch-2.4.8 linux/arch/s390/tools/silo/silo.c
Next file: linux/arch/s390/tools/silo/silo.conf
Previous file: linux/arch/s390/tools/silo/cfg.h
Back to the patch index
Back to the overall index
- Lines: 587
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.4.7/linux/arch/s390/tools/silo/silo.c
- Orig date:
Wed Apr 11 19:02:27 2001
diff -u --recursive --new-file v2.4.7/linux/arch/s390/tools/silo/silo.c linux/arch/s390/tools/silo/silo.c
@@ -1,586 +0,0 @@
-/*
- * arch/s390/boot/silo.c
- *
- * S390 version
- * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *
- * Report bugs to: <linux390@de.ibm.com>
- *
- * Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>
- * Fritz Elfert <felfert@to.com> contributed support for
- * /etc/silo.conf based on Intel's lilo
- * Changes :
- * 01/15/01 Holger Smolinski <Holger.Smolinski@de.ibm.com>
- * adapted to deal with devices and bootsects of various sizes
- */
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <limits.h>
-#include <dirent.h>
-#include <linux/fs.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <asm/ioctl.h>
-
-#include "cfg.h"
-
-CONFIG cf_options[] = {
- { cft_strg, "append", NULL, NULL,NULL },
- { cft_strg, "image", NULL, NULL,NULL },
- { cft_strg, "ipldevice", NULL, NULL,NULL },
- { cft_strg, "bootsect", NULL, NULL,NULL },
- { cft_strg, "map", NULL, NULL,NULL },
- { cft_strg, "parmfile", NULL, NULL,NULL },
- { cft_strg, "ramdisk", NULL, NULL,NULL },
- { cft_strg, "root", NULL, NULL,NULL },
- { cft_flag, "readonly", NULL, NULL,NULL },
- { cft_strg, "verbose", NULL, NULL,NULL },
- { cft_strg, "testlevel", NULL, NULL,NULL },
- { cft_end, NULL, NULL, NULL,NULL }
-};
-
-/* from dasd.h */
-#define DASD_PARTN_BITS 2
-#define BIODASDRWTB _IOWR('D',0,int)
-/* end */
-
-#define SILO_CFG "/etc/silo.conf"
-#define SILO_IMAGE "./image"
-#define SILO_BOOTMAP "./boot.map"
-#define SILO_PARMFILE "./parmfile"
-#define SILO_BOOTSECT "/boot/ipleckd.boot"
-
-#define PRINT_LEVEL(x,y...) if ( silo_options.verbosity >= x ) printf(y)
-#define ERROR_LEVEL(x,y...) if ( silo_options.verbosity >= x ) fprintf(stderr,y)
-#define TOGGLE(x) ((x)=((x)?(0):(1)))
-#define GETARG(x) {int len=strlen(optarg);x=malloc(len);strncpy(x,optarg,len);PRINT_LEVEL(1,"%s set to %s\n",#x,optarg);}
-
-#define ITRY(x) if ( (x) == -1 ) { ERROR_LEVEL(0,"%s (line:%d) '%s' returned %d='%s'\n", __FILE__,__LINE__,#x,errno,strerror(errno)); usage(); exit(1); }
-#define NTRY(x) if ( (x) == 0 ) { ERROR_LEVEL(0,"%s (line:%d) '%s' returned %d='%s'\n", __FILE__,__LINE__,#x,errno,strerror(errno)); usage(); exit(1); }
-
-#define MAX_CLUSTERS 256
-#define PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
-
-#define SILO_VERSION "1.1"
-
-struct silo_options
- {
- short int verbosity;
- short int testlevel;
- char *image;
- char *ipldevice;
- char *parmfile;
- char *ramdisk;
- char *bootsect;
- char *conffile;
- char *bootmap;
- }
-silo_options =
-{
- 1, /* verbosity */
- 2, /* testlevel */
- SILO_IMAGE, /* image */
- NULL, /* ipldevice */
- SILO_PARMFILE, /* parmfile */
- NULL, /* initrd */
- SILO_BOOTSECT, /* bootsector */
- SILO_CFG, /* silo.conf file */
- SILO_BOOTMAP, /* boot.map */
-};
-
-struct blockdesc
- {
- unsigned long off;
- unsigned short ct;
- unsigned long addr;
- };
-
-struct blocklist
- {
- struct blockdesc blk[MAX_CLUSTERS];
- unsigned short ix;
- };
-
-void
-usage (void)
-{
- printf ("Usage:\n");
- printf ("silo -d ipldevice [additional options]\n");
- printf ("-d /dev/node : set ipldevice to /dev/node\n");
- printf ("-f image : set image to image\n");
- printf ("-F conffile : specify configuration file (/etc/silo.conf)\n");
- printf ("-p parmfile : set parameter file to parmfile\n");
- printf ("-b bootsect : set bootsector to bootsect\n");
- printf ("Additional options\n");
- printf ("-B bootmap:\n");
- printf ("-v: increase verbosity level\n");
- printf ("-v#: set verbosity level to #\n");
- printf ("-t: decrease testing level\n");
- printf ("-h: print this message\n");
- printf ("-?: print this message\n");
- printf ("-V: print version\n");
-}
-
-int
-read_cfg(struct silo_options *o)
-{
- char *tmp;
- if (access(o->conffile, R_OK) && (errno == ENOENT))
- return 0;
- /* If errno != ENOENT, let cfg_open report an error */
- cfg_open(o->conffile);
- cfg_parse(cf_options);
- tmp = cfg_get_strg(cf_options, "ipldevice");
- if ( ! o->ipldevice && tmp )
- o->ipldevice = tmp;
- tmp = cfg_get_strg(cf_options, "image");
- if ( ! strncmp(o-> image,SILO_IMAGE,strlen(SILO_IMAGE)) && tmp )
- o->image = tmp;
- tmp = cfg_get_strg(cf_options, "parmfile");
- if ( !strncmp(o->parmfile,SILO_PARMFILE,strlen(SILO_PARMFILE)) && tmp)
- o->parmfile = tmp;
- if ( ! o -> ramdisk )
- o->ramdisk = cfg_get_strg(cf_options, "ramdisk");
- tmp = cfg_get_strg(cf_options, "bootsect");
- if ( !strncmp(o -> bootsect,SILO_BOOTSECT,strlen(SILO_BOOTSECT))&&tmp)
- o->bootsect = tmp;
- tmp = cfg_get_strg(cf_options, "map") ;
- if ( !strncmp(o -> bootmap,SILO_BOOTMAP,strlen(SILO_BOOTMAP)) && tmp)
- o->bootmap = tmp;
- tmp = cfg_get_strg(cf_options, "verbose");
- if ( tmp ) {
- unsigned short v;
- sscanf (tmp, "%hu", &v);
- o->verbosity = v;
- }
- tmp = cfg_get_strg(cf_options, "testlevel");
- if ( tmp ) {
- unsigned short t;
- sscanf (tmp, "%hu", &t);
- o->testlevel += t;
- }
- return 1;
-}
-
-char *
-gen_tmpparm( char *pfile )
-{
- char *append = cfg_get_strg(cf_options, "append");
- char *root = cfg_get_strg(cf_options, "root");
- int ro = cfg_get_flag(cf_options, "readonly");
- FILE *f,*of;
- char *fn;
- char c;
- char *tmpdir=NULL,*save=NULL;
-
- if (!append && !root && !ro)
- return pfile;
- of = fopen(pfile, "r");
- if ( of ) {
- NTRY( fn = tempnam(NULL,"parm."));
- } else {
- fn = pfile;
- }
- NTRY( f = fopen(fn, "a+"));
- if ( of ) {
- while ( ! feof (of) ) {
- c=fgetc(of);
- fputc(c,f);
- }
- }
- if (root)
- fprintf(f, " root=%s", root);
- if (ro)
- fprintf(f, " ro");
- if (append)
- fprintf(f, " %s", append);
- fprintf(f, "\n");
- fclose(f);
- fclose(of);
- printf ("tempfile is %s\n",fn);
- return strdup(fn);
-}
-
-int
-parse_options (struct silo_options *o, int argc, char *argv[])
-{
- int rc = 0;
- int oc;
-
- while ((oc = getopt (argc, argv, "Vf:F:d:p:r:b:B:h?v::t::")) != -1)
- {
- switch (oc)
- {
- case 'V':
- printf("silo version: %s\n",SILO_VERSION);
- exit(0);
- case 'v':
- {
- unsigned short v;
- if (optarg && sscanf (optarg, "%hu", &v))
- o->verbosity = v;
- else
- o->verbosity++;
- PRINT_LEVEL (1, "Verbosity value is now %hu\n", o->verbosity);
- break;
- }
- case 't':
- {
- unsigned short t;
- if (optarg && sscanf (optarg, "%hu", &t))
- o->testlevel -= t;
- else
- o->testlevel--;
- PRINT_LEVEL (1, "Testonly flag is now %d\n", o->testlevel);
- break;
- }
- case 'h':
- case '?':
- usage ();
- exit(0);
- case 'd':
- GETARG (o->ipldevice);
- break;
- case 'f':
- GETARG (o->image);
- break;
- case 'F':
- GETARG (o->conffile);
- break;
- case 'p':
- GETARG (o->parmfile);
- break;
- case 'r':
- GETARG (o->ramdisk);
- break;
- case 'b':
- GETARG (o->bootsect);
- break;
- case 'B':
- GETARG (o->bootmap);
- default:
- rc = EINVAL;
- break;
- }
- }
- read_cfg(o);
- return rc;
-}
-
-int
-verify_device (char *name)
-{
- int rc = 0;
- struct stat dst;
- struct stat st;
- ITRY (stat (name, &dst));
- if (S_ISBLK (dst.st_mode))
- {
- if (!(MINOR (dst.st_rdev) & PARTN_MASK))
- {
- rc = dst.st_rdev;
- }
- else
- /* invalid MINOR & PARTN_MASK */
- {
- ERROR_LEVEL (1, "Cannot boot from partition %d %d %d",
- (int) PARTN_MASK, (int) MINOR (dst.st_rdev), (int) (PARTN_MASK & MINOR (dst.st_rdev)));
- rc = -1;
- errno = EINVAL;
- }
- }
- else
- /* error S_ISBLK */
- {
- ERROR_LEVEL (1, "%s is no block device\n", name);
- rc = -1;
- errno = EINVAL;
- }
- return rc;
-}
-
-int
-verify_file (char *name, int dev)
-{
- int rc = 0;
- struct stat dst;
- struct stat st;
- int bs = 1024;
- int l;
-
- ITRY(stat ( name, &dst ));
- if (S_ISREG (dst.st_mode))
- {
- if ((unsigned) MAJOR (dev) == (unsigned) MAJOR (dst.st_dev) && (unsigned) MINOR (dev) == (unsigned) (MINOR (dst.st_dev) & ~PARTN_MASK))
- {
- /* whatever to do if all is ok... */
- }
- else
- /* devicenumber doesn't match */
- {
- ERROR_LEVEL (1, "%s is not on device (%d/%d) but on (%d/%d)\n", name, (unsigned) MAJOR (dev), (unsigned) MINOR (dev), (unsigned) MAJOR (dst.st_dev), (unsigned) (MINOR (dst.st_dev) & ~PARTN_MASK));
- rc = -1;
- errno = EINVAL;
- }
- }
- else
- /* error S_ISREG */
- {
- ERROR_LEVEL (1, "%s is neither regular file nor linkto one\n", name);
- rc = -1;
- errno = EINVAL;
- }
- return rc;
-}
-
-int
-verify_options (struct silo_options *o)
-{
- int rc = 0;
- int dev = 0;
- int crc = 0;
- if (!o->ipldevice || !o->image || !o->bootsect)
- {
- if (!o->ipldevice)
- fprintf(stderr,"ipldevice\n");
- if (!o->image)
- fprintf(stderr,"image\n");
- if (!o->bootsect)
- fprintf(stderr,"bootsect\n");
-
- usage ();
- exit (1);
- }
- PRINT_LEVEL (1, "Testlevel is set to %d\n",o->testlevel);
-
- PRINT_LEVEL (1, "IPL device is: '%s'", o->ipldevice);
- ITRY (dev = verify_device (o->ipldevice));
- PRINT_LEVEL (2, "...ok...(%d/%d)", (unsigned short) MAJOR (dev), (unsigned short) MINOR (dev));
- PRINT_LEVEL (1, "\n");
-
- PRINT_LEVEL (0, "bootsector is: '%s'", o->bootsect);
- ITRY (verify_file (o->bootsect, dev));
- PRINT_LEVEL (1, "...ok...");
- PRINT_LEVEL (0, "\n");
-
- if ( o -> testlevel > 0 &&
- ! strncmp( o->bootmap, SILO_BOOTMAP,strlen(SILO_BOOTMAP) )) {
- NTRY( o -> bootmap = tempnam(NULL,"boot."));
- }
- PRINT_LEVEL (0, "bootmap is set to: '%s'", o->bootmap);
- if ( access ( o->bootmap, O_RDWR ) == -1 ) {
- if ( errno == ENOENT ) {
- ITRY (creat ( o-> bootmap, O_RDWR ));
- } else {
- PRINT_LEVEL(1,"Cannot access bootmap file '%s': %s\n",o->bootmap,
- strerror(errno));
- }
- }
- ITRY (verify_file (o->bootmap, dev));
- PRINT_LEVEL (1, "...ok...");
- PRINT_LEVEL (0, "\n");
-
- PRINT_LEVEL (0, "Kernel image is: '%s'", o->image);
- ITRY (verify_file (o->image, dev));
- PRINT_LEVEL (1, "...ok...");
- PRINT_LEVEL (0, "\n");
-
- PRINT_LEVEL (0, "original parameterfile is: '%s'", o->parmfile);
- ITRY (verify_file (o->parmfile, dev));
- PRINT_LEVEL (1, "...ok...");
- o->parmfile = gen_tmpparm(o->parmfile);
- PRINT_LEVEL (0, "final parameterfile is: '%s'", o->parmfile);
- ITRY (verify_file (o->parmfile, dev));
- PRINT_LEVEL (1, "...ok...");
- PRINT_LEVEL (0, "\n");
-
- if (o->ramdisk)
- {
- PRINT_LEVEL (0, "initialramdisk is: '%s'", o->ramdisk);
- ITRY (verify_file (o->ramdisk, dev));
- PRINT_LEVEL (1, "...ok...");
- PRINT_LEVEL (0, "\n");
- }
-
- return crc;
-}
-
-
-int
-add_file_to_blocklist (char *name, struct blocklist *lst, long addr)
-{
- int fd;
- int devfd;
- struct stat fst;
- int i;
- int blk;
- int bs;
- int blocks;
-
- int rc = 0;
-
- ITRY (fd = open (name, O_RDONLY));
- ITRY (fstat (fd, &fst));
- ITRY (mknod ("/tmp/silodev", S_IFBLK | S_IRUSR | S_IWUSR, fst.st_dev));
- ITRY (devfd = open ("/tmp/silodev", O_RDONLY));
- ITRY (ioctl (fd, FIGETBSZ, &bs));
- blocks = (fst.st_size + bs - 1) / bs;
- for (i = 0; i < blocks; i++)
- {
- blk = i;
- ITRY (ioctl (fd, FIBMAP, &blk));
- if (blk)
- {
- int oldblk = blk;
- ITRY (ioctl (devfd, BIODASDRWTB, &blk));
- if (blk <= 0)
- {
- ERROR_LEVEL (0, "BIODASDRWTB on blk %d returned %d\n", oldblk, blk);
- break;
- }
- }
- else
- {
- PRINT_LEVEL (1, "Filled hole on blk %d\n", i);
- }
- if (lst->ix == 0 || i == 0 ||
- lst->blk[lst->ix - 1].ct >= 128 ||
- (lst->blk[lst->ix - 1].off + lst->blk[lst->ix - 1].ct != blk &&
- !(lst->blk[lst->ix - 1].off == 0 && blk == 0)))
- {
- if (lst->ix >= MAX_CLUSTERS)
- {
- rc = 1;
- errno = ENOMEM;
- break;
- }
- lst->blk[lst->ix].off = blk;
- lst->blk[lst->ix].ct = 1;
- lst->blk[lst->ix].addr = addr + i * bs;
- lst->ix++;
- }
- else
- {
- lst->blk[lst->ix - 1].ct++;
- }
- }
- ITRY(unlink("/tmp/silodev"));
- return rc;
-}
-
-int
-write_bootsect (struct silo_options *o, struct blocklist *blklst)
-{
- int i;
- int s_fd, d_fd, b_fd, bd_fd;
- struct stat s_st, d_st, b_st;
- int rc=0;
- int bs, boots;
- char *tmpdev;
- char buffer[4096]={0,};
- int blocksize, sectsize;
- ITRY (d_fd = open (o->ipldevice, O_RDWR | O_SYNC));
- ITRY (fstat (d_fd, &d_st));
- ITRY (s_fd = open (o->bootmap, O_RDWR | O_TRUNC | O_CREAT | O_SYNC));
- ITRY (verify_file (o->bootsect, d_st.st_rdev));
- for (i = 0; i < blklst->ix; i++)
- {
- int offset = blklst->blk[i].off;
- int addrct = blklst->blk[i].addr | (blklst->blk[i].ct & 0xff);
- PRINT_LEVEL (1, "ix %i: offset: %06x count: %02x address: 0x%08x\n", i, offset, blklst->blk[i].ct & 0xff, blklst->blk[i].addr);
- if ( o->testlevel <= 1 ) {
- NTRY (write (s_fd, &offset, sizeof (int)));
- NTRY (write (s_fd, &addrct, sizeof (int)));
- }
- }
- ITRY (ioctl (s_fd,FIGETBSZ, &bs));
- ITRY (stat (o->bootmap, &s_st));
- if (s_st.st_size > bs )
- {
- ERROR_LEVEL (0,"%s is larger than one block\n", o->bootmap);
- rc = -1;
- errno = EINVAL;
- }
- boots=0;
- NTRY ( tmpdev = tmpnam(NULL) );
- ITRY (mknod (tmpdev, S_IFBLK | S_IRUSR | S_IWUSR, s_st.st_dev));
- ITRY (bd_fd = open (tmpdev, O_RDONLY));
- ITRY (ioctl(bd_fd,BLKSSZGET,&blocksize));
- ITRY (ioctl(s_fd,FIBMAP,&boots));
- ITRY (ioctl (bd_fd, BIODASDRWTB, &boots));
- PRINT_LEVEL (1, "Bootmap is in block no: 0x%08x\n", boots);
- close (bd_fd);
- close(s_fd);
- ITRY (unlink(tmpdev));
- /* Now patch the bootsector */
- ITRY (stat (o->bootsect, &b_st));
- if ((sectsize = b_st.st_size) > blocksize )
- {
- ERROR_LEVEL (0,"Bootsector is larger than sectorsize of volume %d vs %d\n", sectsize, blocksize);
- rc = -1;
- errno = EINVAL;
- }
- ITRY (b_fd = open (o->bootsect, O_RDONLY));
- ITRY (read (b_fd, buffer, sectsize));
- memset (buffer + 0xe0, 0, 8);
- *(int *) (buffer + 0xe0) = boots;
- if ( o -> testlevel <= 0 ) {
- ITRY (write (d_fd, buffer, sectsize));
- ITRY (lseek (d_fd, blocksize, SEEK_SET));
- ITRY (write (d_fd, buffer, sectsize));
- }
- close (b_fd);
- close (d_fd);
- return rc;
-}
-
-int
-do_silo (struct silo_options *o)
-{
- int rc = 0;
-
- int device_fd;
- int image_fd;
- struct blocklist blklist;
- memset (&blklist, 0, sizeof (struct blocklist));
- ITRY (add_file_to_blocklist (o->image, &blklist, 0x00000000));
- if (o->parmfile)
- {
- ITRY (add_file_to_blocklist (o->parmfile, &blklist, 0x00008000));
- }
- if (o->ramdisk)
- {
- ITRY (add_file_to_blocklist (o->ramdisk, &blklist, 0x00800000));
- }
- ITRY (write_bootsect (o, &blklist));
- return rc;
-}
-
-int
-main (int argct, char *argv[])
-{
- int rc = 0;
- char *save=NULL;
- char *tmpdir=getenv("TMPDIR");
- if (tmpdir) {
- NTRY( save=(char*)malloc(strlen(tmpdir)));
- NTRY( strncpy(save,tmpdir,strlen(tmpdir)));
- }
- ITRY( setenv("TMPDIR",".",1));
- ITRY (parse_options (&silo_options, argct, argv));
- ITRY (verify_options (&silo_options));
- if ( silo_options.testlevel > 0 ) {
- printf ("WARNING: silo does not modify your volume. Use -t2 to change IPL records\n");
- }
- ITRY (do_silo (&silo_options));
- if ( save )
- ITRY( setenv("TMPDIR",save,1));
- return rc;
-}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)