Logo Search packages:      
Sourcecode: palo version File versions  Download package

palo.c

/* 
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) Hewlett-Packard (Paul Bame) paul_bame@hp.com
 */
#define LONG_OPTIONS 1

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#if LONG_OPTIONS
# define _GNU_SOURCE
# include <getopt.h>
#endif
#include "load.h"
#include "palo.h"


#define B32(x)    __be32_to_cpu((x))

static const char Id[] = "$Id: palo.c,v 1.12.4.1 2001/06/13 03:13:17 bame Exp $";

static int Install = 0;
int verbose = 0;

/* compute the sum of words in an 4-byte aligned region */
int
checksum(void *p, size_t len)
{
    int xsum = 0;
    int *x = (int *)p;
    int i;

    if (verbose) printf("checksum(%p, %u) = ", p, len);
    len /= 4;

    for (i = 0; i < len; i++)
    {
      xsum += B32(x[i]);
    }

    if (verbose) printf("0x%08x\n", xsum);

    return (xsum);
}

static void
fb_init(struct firstblock *f)
{
    f->lifmagic0 = 0x80;
    f->lifmagic1 = 0x00;
    f->rd_sz = f->kern32_sz = f->kern64_sz = 0;
    f->rd_offset = f->kern32_offset = f->kern64_offset = 0;
    strcpy(f->palomagic, PALOMAGIC);
    f->version = PALOHDRVERSION;
    f->flags = 0;
    if (Install)
      f->flags |= PFLAG_INSTALL;
}

int
check_bootloader(int media, int line)
{
    struct firstblock f;
    int ipl_words;
    int xsum;
    unsigned int *ipl;

    if (verbose) printf("check_bootloader %d\n", line);

    STRUCTREAD(media, f, 0);

    if (f.lifmagic0 != 0x80 || f.lifmagic1 != 0x00)
    {
      fprintf(stderr, "0x%x 0x%x\n", f.lifmagic0, f.lifmagic1);
      error(6, "LIF header");
    }

    if (B32(f.ipl_addr) < 2048 ||
      (B32(f.ipl_addr) % 2048) != 0)
      error(6, "ipl_addr");

    if (B32(f.ipl_size) <= 0 ||
      B32(f.ipl_size) >= 256 * 1024 ||
      (B32(f.ipl_size) % 2048) != 0)
      error(6, "ipl_size");

    if (B32(f.ipl_entry) >= B32(f.ipl_size) ||
      B32(f.ipl_entry) < 0 ||
      (B32(f.ipl_entry) % 4) != 0)
      error(6, "ipl_entry");

    ipl_words = B32(f.ipl_size) / sizeof ipl[0];

    /* seekread the IPL */
    ipl = calloc(ipl_words, sizeof ipl[0]);

    /* would be a good idea to check this call? */
    if (seekread(media, (char *)ipl, B32(f.ipl_size), B32(f.ipl_addr)) == -1)
      error(6, "read failed");

    /* calculate xsum */
    xsum = checksum(ipl, B32(f.ipl_size));

    if (xsum != 0)
    {
      fprintf(stderr, "calculated xsum 0x%x got 0x%x\n",
            -xsum, ipl[ipl_words - 1]);
      xsum -= B32(ipl[ipl_words - 1]);
      fprintf(stderr, "calculated xsum 0x%x got 0x%x\n",
            -xsum, ipl[ipl_words - 1]);
      exit(2);
    }

    printf("ipl: addr %d size %d entry 0x%x\n",
                  B32(f.ipl_addr),
                  B32(f.ipl_size),
                  B32(f.ipl_entry));

    if (strncmp(f.palomagic, PALOMAGIC, 4) != 0)
    {
      error(6, "bad magic");
    }

    if (f.version != PALOHDRVERSION)
    {
      fprintf(stderr, "Warning!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
                  "Boot loader header version is %d, I only know how\n"
                  "to handle version %d.  It MIGHT work anyway.\n",
                  f.version, PALOHDRVERSION);
    }

#if 1
    printf(" ko 0x%x ksz %d k64o 0x%x k64sz %d rdo %d rdsz %d\n<%s>\n",
      B32(f.kern32_offset), B32(f.kern32_sz),
      B32(f.kern64_offset), B32(f.kern64_sz),
      B32(f.rd_offset), B32(f.rd_sz),
      f.cmdline);
#endif

    return 1;
}


/* maximum allowed HP boot loader (IPL) size */
#define MAXBLSIZE (256 * 1024)

unsigned
write_bootloader(int media, int bootloader,
      unsigned where,
      unsigned f0end,
      struct firstblock *f)
{
    size_t rblsize;           /* sector-rounded boot loader size */
    struct loadable loadable;
    int xsum1;
    void *blimage;
    int r;
    int wide;

    /* We want prepare_ to fail, otherwise we've been given the output */
    /* of the linker instead of mkbootable */
    r = prepare_loadable(bootloader, &loadable, &wide);
    if (r)
      error(12);

    /* make sure max size boot loader would fit */
    if (where + MAXBLSIZE > f0end) {
      printf("where %d, where+MAX=%d f0end=%d\n",
             where, where + MAXBLSIZE, f0end);
      error(9);
    }
    /* load the boot loader into RAM */
    rblsize = fsize(bootloader);
    assert((rblsize % FW_BLOCKSIZE) == 0);
    blimage = (void *)calloc(1, rblsize);
    assert(blimage != NULL);
    if ((r = seekread(bootloader, blimage, rblsize, 0)) != rblsize)
      error(13);

    /* Is it really a boot loader? */
#define BLWORD1 0xe8000002
    if (BLWORD1 != __be32_to_cpu(*(unsigned *)blimage))
    {
      fprintf(stderr, "ERROR: first word of boot loader was 0x%08x,"
            " expected 0x%08x\n", __be32_to_cpu(*(unsigned *)blimage),
            BLWORD1);
      exit(2);
    }

    /* write it out */
    seekwrite(media, blimage, rblsize, where);
    close(bootloader);

    f->ipl_addr = __cpu_to_be32(where);
    f->ipl_size = __cpu_to_be32(rblsize);
    /* entry point relative to where IPL is loaded in RAM by firmware */
    f->ipl_entry = __cpu_to_be32(loadable.entry - loadable.first);

    STRUCTWRITE(media, *f, 0);

    check_bootloader(media, __LINE__);

    free(blimage);
    return where + rblsize;
}

unsigned
write_kernel32(int media, int kernel, unsigned where, unsigned end,
      struct firstblock *f)
{
    /* always allow max size boot loader */
    f->kern32_offset = __cpu_to_be32(where);
    f->kern32_sz = __cpu_to_be32(fsize(kernel));

    if (B32(f->kern32_sz) + where >= end)
      error(14, "32-bit-kernel");
    lseek(media, where, SEEK_SET);
    return where + cat(media, kernel);
}

unsigned
write_kernel64(int media, int kernel, unsigned where, unsigned end,
      struct firstblock *f)
{
    /* always allow max size boot loader */
    f->kern64_offset = __cpu_to_be32(where);
    f->kern64_sz = __cpu_to_be32(fsize(kernel));

    if (B32(f->kern64_sz) + where >= end)
      error(14, "64-bit-kernel");
    lseek(media, where, SEEK_SET);
    return where + cat(media, kernel);
}

unsigned
write_ramdisk(int media, int rd, unsigned where, unsigned end,
      struct firstblock *f)
{
    /* always allow max size boot loader */
    f->rd_offset = __cpu_to_be32(where);
    f->rd_sz = __cpu_to_be32(fsize(rd));

    if (B32(f->rd_sz) + where >= end)
      error(14, "ramdisk");

    lseek(media, where, SEEK_SET);
    where += cat(media, rd);

    return where;
}

/* assumes the previous contents of the file are to be overwritten, */
/* that kernel and bootloader are valid file pointers, and that */
/* commandline will fit given size in fixed_pm. */
void
do_sequential(int media, int kernel32, int kernel64,
      const char *commandline, int bootloader, int ramdisk)
{
    struct firstblock f;
    /* always load IPL at second 2k block on sequential media */
    int where = 1 * FW_BLOCKSIZE;
    unsigned end = 800 * 1024 * 1024;

    /* must have a boot loader for initialization */
    assert(bootloader != -1);
    assert(kernel32 != -1 || kernel64 != 1);

    memset(&f, 0, sizeof f);
    fb_init(&f);

    /* Update the boot loader, ignore size in this case */
    where = write_bootloader(media, bootloader, where, end, &f);

    if (kernel32 != -1)
      where = write_kernel32(media, kernel32, where, end, &f);

    /* write some padding to the 2k boundary */
    where += write(media, &f, FW_BLOCKSIZE - (where % FW_BLOCKSIZE));

    if (kernel64 != -1)
      where = write_kernel64(media, kernel64, where, end, &f);

    /* write some padding to the 2k boundary */
    where += write(media, &f, FW_BLOCKSIZE - (where % FW_BLOCKSIZE));

    if (ramdisk != -1)
      where = write_ramdisk(media, ramdisk, where, end, &f);

    /* write some padding to the 2k boundary */
    where += write(media, &f, FW_BLOCKSIZE - (where % FW_BLOCKSIZE));

    if (commandline != 0)
      strcpy(f.cmdline, commandline);

    STRUCTWRITE(media, f, 0);

    check_bootloader(media, __LINE__);
}

/* look on each 2k boundary for the file 'target' on 'media'.  Assumes
 * that 'target' is at least 2k in length.
 */
static int
lookfor(int media, int target)
{
    char *targetptr;
    char *mbuf;
    int offset;
    int r = -1;
    int targetsize = fsize(target);
    float mediasize = fsize(media);

    targetptr = mmap(0, targetsize, PROT_READ, MAP_SHARED, target, 0);
    if ((long) targetptr == -1)
    {
      perror("mmap(targetptr)");
      return -1;
    }

    mbuf = malloc(targetsize);
    assert(mbuf != NULL);

    for (offset = 0; 1; offset += 2048)
    {
      int n;
      const int PREVIEW = 512;

      n = seekread(media, mbuf, PREVIEW, offset);
      if (n < PREVIEW)
          break;
      if (memcmp(mbuf, targetptr, PREVIEW) == 0)
      {
          n = seekread(media, mbuf, targetsize, offset);
          if (n < targetsize)
            break;
          if (memcmp(mbuf, targetptr, targetsize) == 0)
          {
            r = offset;
            break;
          }
      }
    }

    munmap(targetptr, targetsize);
    free(mbuf);

    return r;
}

/* Given a writeable ISO9660 CD image containing within its file system
 * both the boot loader and kernel specified also on the palo command line,
 * write a "sequential" or "F0" type boot header.
 */
void
do_cdrom(int media, int kernel32, int kernel64,
      const char *commandline, int bootloader, int ramdisk)
{
    struct firstblock f;
    /* always load IPL at second 2k block on sequential media */
    int where = 1 * FW_BLOCKSIZE;
    unsigned end = 800 * 1024 * 1024;
    /* int is safe since CD-ROM is < 2G */
    int bootloader_offset;
    int kernel32_offset;
    int kernel64_offset;
    int ramdisk_offset;

    /* must have a boot loader and kernel */
    assert(bootloader != -1);
    assert(kernel32 != -1 || kernel64 != 1);

    /* read the first block/sector, which is FW_BLOCKSIZE, which also */
    /* conveniently is the CD block size too */
    /* STRUCTREAD(media, f, 0); Probably don't need to read it... */
    memset(&f, 0, sizeof f);
    fb_init(&f);

    /* search the ISO image for the boot loader and kernel files */
    if ((bootloader_offset = lookfor(media, bootloader)) == -1)
    {
      error(15, "boot loader");
    }

    if (kernel32 != -1 && (kernel32_offset = lookfor(media, kernel32)) == -1)
      error(15, "32-bit-kernel image");

    if (kernel64 != -1 && (kernel64_offset = lookfor(media, kernel64)) == -1)
      error(15, "64-bit-kernel image");

    if (ramdisk != -1)
    {
      if ((ramdisk_offset = lookfor(media, ramdisk)) == -1)
          error(15, "ramdisk image");
    }

    /* Overwrite the boot loader because write_bootloader() is easy to use */
    write_bootloader(media, bootloader, bootloader_offset, end, &f);

    /* Overwrite the kernel because write_kernel() is easy to use */
    if (kernel32 != -1)
      write_kernel32(media, kernel32, kernel32_offset, end, &f);

    if (kernel64 != -1)
      write_kernel64(media, kernel64, kernel64_offset, end, &f);

    if (ramdisk != -1)
    {
      write_ramdisk(media, ramdisk, ramdisk_offset, end, &f);
    }

    if (commandline != 0)
      strcpy(f.cmdline, commandline);

    STRUCTWRITE(media, f, 0);

    check_bootloader(media, __LINE__);
}

#define KSIZE (2 * 1024 * 1024)

/* Blocksize for the ext2/3 fs in the palo partition */
#define EXT2_BLOCKSIZE  1024

/* size in ext2 blocks of hole for bootloader */
#define EXT2_HOLE ((MAXBLSIZE + 1) / EXT2_BLOCKSIZE)

/* offset in bytes before start of hole,  ext2 doesn't allow holes at
 * to cover the first four blocks of the filesystem */
#define EXT2_OFFSET     (4*EXT2_BLOCKSIZE)

int
do_formatted(int init, int media, const char *medianame, int partition,
           int f0start, int f0length, int bootloaderfd, int do_format,
           const char *commandline)
{
    char partitionname[256];
    struct firstblock f;
    int partitionfd;

    /* FIXME: assuming we can simply add the partition to the end
     * of the whole disc device isn't always true */
    snprintf(partitionname, sizeof(partitionname), "%s%d", medianame,
           partition);

    if ((partitionfd = open(partitionname, O_RDWR)) < 0) {
      perror(partitionname);
      exit(1);
    }
    close(partitionfd);

    if (init) {
      /* make the bootloader align at 256k */
      unsigned int holestart = (f0start + 0x3ffff + EXT2_OFFSET) & ~0x3ffff;
      unsigned int partition_offset = holestart - f0start;
      char badblockfilename[256];
      int fd, i;
      char cmd[512];

      printf("Initializing %s as ext%d\n", partitionname, do_format);

      if (verbose)
          printf("f0 partition starts %d, hole %d-%d, end %d\n",
               f0start, holestart, holestart + EXT2_HOLE*EXT2_BLOCKSIZE,
               f0start + f0length);

      if(partition_offset + EXT2_HOLE > f0length)
          error(14, "bootloader");

      sprintf(badblockfilename, "/tmp/paloblk-%d", getpid());
      if ((fd = open(badblockfilename, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) {
          perror(badblockfilename);
          exit(1);
      }
    
      for (i = (holestart - f0start)/EXT2_BLOCKSIZE;
           i < (holestart - f0start)/EXT2_BLOCKSIZE + EXT2_HOLE; i++) {
          char buf[128];
          sprintf(buf, "%d\n", i);
          write(fd, buf, strlen(buf));
      }

      sprintf(cmd, "mke2fs %s -b %d -l %s %s", do_format == 3 ? "-j" : "",
            EXT2_BLOCKSIZE, badblockfilename, partitionname);

      if (verbose)
          printf("Executing: %s\n", cmd);
      else
          strcat(cmd, " > /dev/null 2>&1");

      i = system(cmd);
      unlink(badblockfilename);

      if(WEXITSTATUS(i) != 0)
          error(19, WEXITSTATUS(i));

      

      STRUCTREAD(media, f, 0);
      fb_init(&f);
      f.flags |= PFLAG_EXT2;

      if(commandline)
          strncpy(f.cmdline, commandline, sizeof(f.cmdline));

      write_bootloader(media, bootloaderfd, holestart,
                   holestart + EXT2_HOLE*EXT2_BLOCKSIZE, &f);
      
      STRUCTWRITE(media, f, 0);

    } else {
      STRUCTREAD(media, f, 0);

      if(verbose)
          printf("Updating formatted ver=%d, start=%d\n",
               f.version, f.ipl_addr);

      if ((f.version < 4) || (!f.flags & PFLAG_EXT2)) {
            printf("Can not update %s. Please initialize first.\n",
                        partitionname);
            return -1;
      }

      if(commandline)
          strncpy(f.cmdline, commandline, sizeof(f.cmdline));

      write_bootloader(media, bootloaderfd, f.ipl_addr,
                   f.ipl_addr + EXT2_HOLE*EXT2_BLOCKSIZE, &f);

      STRUCTWRITE(media, f, 0);
    }
    return 0;
}

void
do_randomaccess(int init, int media, int kernel32, int kernel64,
      const char *commandline, int bootloader, int ramdisk,
      unsigned f0start, unsigned f0length)
{
    struct firstblock f;
    int bstart = 0;

    if (verbose) printf("do_ra(%d, %d, %d, %d, '%s', %d, %d, %u, %u)\n",
      init, media, kernel32, kernel64, commandline, bootloader, ramdisk, f0start,
      f0length);

    assert((f0start % 512) == 0);

    /* figure out where the boot loader should be */
    /* f0start is a sector (512-byte) multiple.  IPL must be aligned 2k */
    bstart = (f0start + 2047) & ~2047;

    if (init)
    {
      /* initialize a partitioned medium */
      unsigned where = bstart;
      unsigned end = f0start + f0length;

      /* must have a boot loader for initialization */
      assert(bootloader != -1);

      STRUCTREAD(media, f, 0);
      fb_init(&f);

      /* Update the boot loader, ignore size in this case */
      write_bootloader(media, bootloader, where, end, &f);

      where += MAXBLSIZE;

      if (kernel32 != -1)
      {
          unsigned p, ksize;
          p = write_kernel32(media, kernel32, where, end, &f);

          ksize = p - where;

          /* allow for bigger kernels */
          if (ksize < KSIZE)
            ksize = KSIZE;

          where = p;
      }

      if (kernel64 != -1)
      {
          unsigned p, ksize;
          p = write_kernel64(media, kernel64, where, end, &f);

          ksize = p - where;

          /* allow for bigger kernels */
          if (ksize < KSIZE)
            ksize = KSIZE;

          where = p;
      }

      if (ramdisk != -1)
          where = write_ramdisk(media, ramdisk, where, end, &f);

      if (commandline != 0)
          strcpy(f.cmdline, commandline);

      STRUCTWRITE(media, f, 0);
    }
    else    /* update */
    {
      unsigned end = f0start + f0length;

      fprintf(stderr, "palo -U on unformatted (non-ext2) palo partitions doesn't work yet\n"); exit(2);
#if 0

      /* make sure we have a good bootloader on there now */
      check_bootloader(media, __LINE__);

      /* update a partitioned medium */
      STRUCTREAD(media, f, 0);

      if (bootloader != -1)
      {
          write_bootloader(media, bootloader, bstart, B32(f.kern_offset), &f);
      }

      if (kernel != -1)
      {
          write_kernel(media, kernel, B32(f.kern_offset),
            B32(f.rd_offset), &f);
      }

      if (kernel != -1)
      {
          write_kernel(media, kernel, B32(f.kern_offset),
            B32(f.rd_offset), &f);
      }

      if (ramdisk != -1)
      {
          write_ramdisk(media, ramdisk, B32(f.rd_offset), end, &f);
      }

      if (commandline != 0)
          strcpy(f.cmdline, commandline);

      STRUCTWRITE(media, f, 0);
#endif
    }

    check_bootloader(media, __LINE__);
}

#define MAXARGS 200

#if LONG_OPTIONS
static struct option Longopts[] =
{
    {"configfile", 1, 0, 'f'},
    {"commandline", 1, 0, 'c'},
    {"recoverykernel", 1, 0, 'k'},
    {"bootloader", 1, 0, 'b'},
    {"ramdisk", 1, 0, 'r'},
    {"init-partitioned", 1, 0, 'I'},
    {"format-as", 1, 0, 'e'},
    {"update-partitioned", 1, 0, 'U'},
    {"init-tape", 1, 0, 's'},
    {"init-cdrom", 1, 0, 'C'},
    {"verbose", 0, 0, 'v'},
    {"help", 0, 0, '?'},
    {0, 0, 0, 0}
};
# define GETOPT(argc, argv, optstring) \
      getopt_long(argc, argv, optstring, Longopts, 0)
#else
# define GETOPT(argc, argv, optstring) getopt(argc, argv, optstring)
#endif

int
main(int argc, char *argv[])
{
    int c;
    enum {SEQUENTIAL, PARTITIONED, CDROM} mediatype = PARTITIONED;
    int bootloader = -1;
    int kernel32 = -1;
    int kernel64 = -1;
    int fd;
    struct loadable loadable;
    int wide;
    char *commandline = 0;
    int media = -1;
    int ramdisk = -1;
    int cdrom = 0;
    char *medianame = NULL;
    char *bootloaderfile = "/usr/share/palo/iplboot";
    int init = 0;
    extern char *bld_info;
    const char gargs[] = "f:C:s:b:k:c:r:I:e:U:v?";
    char *config_file = "/etc/palo.conf";
    char *newargv[MAXARGS];
    int newargc, format_as = 0;
    FILE *fconfig;

    assert(sizeof (struct firstblock) == 2048);
    {
      struct firstblock f;
      assert((unsigned long)&f.kern32_offset - (unsigned long)&f == 8);
      assert((unsigned long)&f.ipl_addr - (unsigned long)&f == 0xf0);
    }

    fputs("palo version " PALOVERSION " ", stdout);
    puts(bld_info);

    /* do we have a -f? */
    while ((c = GETOPT(argc, argv, gargs)) != EOF)
    {
      switch(c)
      {
      case 'f':
          config_file = optarg;
          break;
      case '?':
          error(0, argv[0]);
      }
    }

    newargc = 0;
    newargv[newargc++] = argv[0];
    /* grab args from the config file */
    if ((fconfig = fopen(config_file, "r")) == NULL)
    {
      fprintf(stderr, "Warning: ");
        perror(config_file);
    }
    else
    {
        char buf[256];

      while(newargc < MAXARGS && fgets(buf, sizeof buf, fconfig) != NULL)
      {
          char *ptr = buf;
          char *end;

          /* skip over leading whitespace */
          while (isspace(*ptr))
            ptr++;

          /* skip comment */
          if (*ptr == '#')
            continue;

          /* strip trailing whitespace */
          end = ptr + strlen(ptr) - 1;
          while (isspace(*end))
            end--;
          *++end = '\0';

          /* skip blank lines */
          if (*ptr == '\0')
              continue;

          newargv[newargc++] = strdup(buf);
      }
      fclose(fconfig);
    }

    /* add the original command-line args */
    for (c = 1; c < argc && newargc < MAXARGS; c++)
    {
        newargv[newargc++] = argv[c];
    }

    /* NULL pointer for good measure */
    if (newargc < MAXARGS)
        newargv[newargc] = 0;

    /* convince getopt to re-start */
    optind = 1;

    while ((c = GETOPT(newargc, newargv, gargs)) != EOF)
    {
      switch(c)
      {
      case 'f':
          break;
      case 'C':
          mediatype = CDROM;
          medianame = optarg;
          break;
      case 'I':
          init = 1;
          mediatype = PARTITIONED;
          medianame = optarg;
          break;
      case 'U':
          init = 0;
          mediatype = PARTITIONED;
          medianame = optarg;
          break;
      case 's':
          mediatype = SEQUENTIAL;
          medianame = optarg;
          break;
      case 'b':
          bootloaderfile = optarg;
          break;
      case 'k':
          if ((fd = open(optarg, O_RDONLY)) == -1)
          {
            perror(optarg);
            return 2;
          }
          if (!prepare_loadable(fd, &loadable, &wide))
            error(16, optarg);
          if ((wide && kernel64 != -1) || (!wide && kernel32 != -1))
              error(17, optarg);
          lseek(fd, 0, SEEK_SET); /* rewind */
          if (wide)
              kernel64 = fd;
          else
              kernel32 = fd;
          break;
      case 'r':
          if ((ramdisk = open(optarg, O_RDONLY)) == -1)
          {
            perror(optarg);
            return 2;
          }
          break;
      case 'c':
          commandline = optarg;
          if (strlen(commandline) > 127)
            error(3,127,strlen(commandline));
          break;
      case 'e':
          if(strcmp(optarg, "2") == 0)
            format_as = 2;
          else if(strcmp(optarg, "3") == 0)
            format_as = 3;
          else
            error(0, argv[0]);
          break;
      case 'v':
          verbose = 1;
          break;
      default:
          error(0, argv[0]);
          break;
      }
    }

    if ((bootloader = open(bootloaderfile, O_RDONLY)) == -1)
    {
      perror(bootloaderfile);
      return 2;
    }

    if (optind < argc)
    {
      error(0, argv[0]);
    }

    if (medianame == NULL)
    {
      fprintf(stderr, "%s: Need one of -CIs or -U\n", argv[0]);
        error(0, argv[0]);
    }

    switch (mediatype)
    {
    case SEQUENTIAL:
      if ((media = open(medianame, O_RDWR|O_CREAT, 0666)) == -1)
      {
          perror(medianame);
          return 2;
      }
      do_sequential(media, kernel32, kernel64, commandline, bootloader, ramdisk);
      break;
    case PARTITIONED:
    {
          struct diskpartition ptab[MAXPARTS];
          int partitioned;
          int f0;
          struct firstblock f;

          memset(ptab, 0, sizeof ptab);

          /* non-sequential boot creation requires a file/device */
          if ((media = open(medianame, O_RDWR)) == -1)
          {
            perror(medianame);
            if (errno == ENOENT)    /* file probably doesn't exist */
            {
                error(1);
            }
            return 2;
          }

          /* it better have a partition table too... */
          partitioned = load_partitions(media, ptab, MAXPARTS);
          if (!partitioned)
          {
            error(10);
          }

          /* find the F0 partition */
          for (f0 = 0; f0 < MAXPARTS; f0++)
          {
            if (ptab[f0].id == PALO_PARTITION)
                break;
          }
          if (f0 == MAXPARTS)
            error(11);
          if(verbose) {
            print_ptab_pretty(ptab, MAXPARTS);

            printf("F0 partition start sector %d length %d\n",
                ptab[f0].start, ptab[f0].length);
          }

          if (format_as) {
            /* if we're going to be a formatted partition, we can't
             * load anything into it, so check we haven't been asked
             * to */
            if(kernel32 != -1 || kernel64 != -1 || ramdisk != -1)
                  error(18);

            if (do_formatted(init, media, medianame, f0 + 1,
                       ptab[f0].start * 512, ptab[f0].length * 512,
                       bootloader, format_as, commandline))
                  error(20);
          } else
            do_randomaccess(init, media, kernel32, kernel64, commandline,
                        bootloader, ramdisk, ptab[f0].start * 512,
                        ptab[f0].length * 512);
      }
      break;
    case CDROM:
      if ((media = open(medianame, O_RDWR)) == -1)
      {
          perror(medianame);
          return 2;
      }
      do_cdrom(media, kernel32, kernel64, commandline, bootloader, ramdisk);
      break;
    }

    fsync(media);
    close(media);

    return 0;
}

Generated by  Doxygen 1.6.0   Back to index