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

mkprep.c

/*
 * Makes a prep bootable image which can be dd'd onto
 * a disk device to make a bootdisk.  Will take
 * as input a elf executable, strip off the header
 * and write out a boot image as:
 * 1) default - strips elf header
 *      suitable as a network boot image
 * 2) -pbp - strips elf header and writes out prep boot partition image
 *      cat or dd onto disk for booting
 * 3) -asm - strips elf header and writes out as asm data
 *      useful for generating data for a compressed image
 *                  -- Cort
 *
 * Modified for x86 hosted builds by Matt Porter <porter@neta.com>
 * Modified for Sparc hosted builds by Peter Wahl <PeterWahl@web.de>
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* size of read buffer */
#define SIZE 0x1000

/*
 * Partition table entry
 *  - from the PReP spec
 */
typedef struct partition_entry {
      unsigned char boot_indicator;
      unsigned char starting_head;
      unsigned char starting_sector;
      unsigned char starting_cylinder;

      unsigned char system_indicator;
      unsigned char ending_head;
      unsigned char ending_sector;
      unsigned char ending_cylinder;

      unsigned char beginning_sector[4];
      unsigned char number_of_sectors[4];
} partition_entry_t;

#define BootActive      0x80
#define SystemPrep      0x41

void copy_image(FILE *, FILE *);
void write_prep_partition(FILE *, FILE *);
void write_asm_data(FILE *, FILE *);

unsigned int elfhdr_size = 65536;

int main(int argc, char *argv[])
{
      FILE *in, *out;
      int argptr = 1;
      int prep = 0;
      int asmoutput = 0;

      if (argc < 3 || argc > 4) {
            fprintf(stderr, "usage: %s [-pbp] [-asm] <boot-file> <image>\n",
                  argv[0]);
            exit(-1);
      }

/* needs to handle args more elegantly -- but this is a small/simple program */

      /* check for -pbp */
      if (!strcmp(argv[argptr], "-pbp")) {
            prep = 1;
            argptr++;
      }

      /* check for -asm */
      if (!strcmp(argv[argptr], "-asm")) {
            asmoutput = 1;
            argptr++;
      }

      /* input file */
      if (!strcmp(argv[argptr], "-"))
            in = stdin;
      else if (!(in = fopen(argv[argptr], "r")))
            exit(-1);
      argptr++;

      /* output file */
      if (!strcmp(argv[argptr], "-"))
            out = stdout;
      else if (!(out = fopen(argv[argptr], "w")))
            exit(-1);
      argptr++;

      /* skip elf header in input file */
      /*if ( !prep )*/
      fseek(in, elfhdr_size, SEEK_SET);

      /* write prep partition if necessary */
      if (prep)
            write_prep_partition(in, out);

      /* write input image to bootimage */
      if (asmoutput)
            write_asm_data(in, out);
      else
            copy_image(in, out);

      return 0;
}

void store_le32(unsigned int v, unsigned char *p)
{
      p[0] = v;
      p[1] = v >>= 8;
      p[2] = v >>= 8;
      p[3] = v >> 8;
}

void write_prep_partition(FILE *in, FILE *out)
{
      unsigned char block[512];
      partition_entry_t pe;
      unsigned char *entry  = block;
      unsigned char *length = block + 4;
      long pos = ftell(in), size;

      if (fseek(in, 0, SEEK_END) < 0) {
            fprintf(stderr,"info failed\n");
            exit(-1);
      }
      size = ftell(in);
      if (fseek(in, pos, SEEK_SET) < 0) {
            fprintf(stderr,"info failed\n");
            exit(-1);
      }

      memset(block, '\0', sizeof(block));

      /* set entry point and boot image size skipping over elf header */
      store_le32(0x400/*+65536*/, entry);
      store_le32(size-elfhdr_size+0x400, length);

      /* sets magic number for msdos partition (used by linux) */
      block[510] = 0x55;
      block[511] = 0xAA;

      /*
      * Build a "PReP" partition table entry in the boot record
      *  - "PReP" may only look at the system_indicator
      */
      pe.boot_indicator   = BootActive;
      pe.system_indicator = SystemPrep;
      /*
      * The first block of the diskette is used by this "boot record" which
      * actually contains the partition table. (The first block of the
      * partition contains the boot image, but I digress...)  We'll set up
      * one partition on the diskette and it shall contain the rest of the
      * diskette.
      */
      pe.starting_head     = 0;     /* zero-based                      */
      pe.starting_sector   = 2;     /* one-based                       */
      pe.starting_cylinder = 0;     /* zero-based                      */
      pe.ending_head       = 1;     /* assumes two heads               */
      pe.ending_sector     = 18;    /* assumes 18 sectors/track        */
      pe.ending_cylinder   = 79;    /* assumes 80 cylinders/diskette     */

      /*
      * The "PReP" software ignores the above fields and just looks at
      * the next two.
      *   - size of the diskette is (assumed to be)
      *     (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
      *   - unlike the above sector numbers, the beginning sector is zero-based!
      */
#if 0
      store_le32(1, pe.beginning_sector);
#else
      /* This has to be 0 on the PowerStack? */
      store_le32(0, pe.beginning_sector);
#endif

      store_le32(2*18*80-1, pe.number_of_sectors);

      memcpy(&block[0x1BE], &pe, sizeof(pe));

      fwrite(block, sizeof(block), 1, out);
      fwrite(entry, 4, 1, out);
      fwrite(length, 4, 1, out);
      /* set file position to 2nd sector where image will be written */
      fseek( out, 0x400, SEEK_SET );
}



void copy_image(FILE *in, FILE *out)
{
      char buf[SIZE];
      int n;

      while ( (n = fread(buf, 1, SIZE, in)) > 0 )
            fwrite(buf, 1, n, out);
}


void
write_asm_data(FILE *in, FILE *out)
{
      int i, cnt, pos = 0;
      unsigned int cksum = 0, val;
      unsigned char *lp;
      unsigned char buf[SIZE];
      size_t len;

      fputs("\t.data\n\t.globl input_data\ninput_data:\n", out);
      while ((len = fread(buf, 1, sizeof(buf), in)) > 0) {
            cnt = 0;
            lp = buf;
            /* Round up to longwords */
            while (len & 3)
                  buf[len++] = '\0';
            for (i = 0;  i < len;  i += 4) {
                  if (cnt == 0)
                        fputs("\t.long\t", out);
                  fprintf(out, "0x%02X%02X%02X%02X",
                        lp[0], lp[1], lp[2], lp[3]);
                  val = *(unsigned long *)lp;
                  cksum ^= val;
                  lp += 4;
                  if (++cnt == 4) {
                        cnt = 0;
                        fprintf(out, " # %x \n", pos+i-12);
                  } else {
                        fputs(",", out);
                  }
            }
            if (cnt)
                  fputs("0\n", out);
            pos += len;
      }
      fprintf(out, "\t.globl input_len\ninput_len:\t.long\t0x%x\n", pos);
      fprintf(stderr, "cksum = %x\n", cksum);
}

Generated by  Doxygen 1.6.0   Back to index