summaryrefslogblamecommitdiffstats
path: root/c/src/lib/libbsp/i386/pc386/tools/bin2boot.c
blob: af614e10e25d18c41b2d83fffad32ef530325d64 (plain) (tree)
1
2
3
4
5
6
7
8
9



                                          


                   

                   
 
 






















                                                                               
 


                                







                                                        
 























                                                  
                             














                                                             
 














                                                                      
  


                            
                            









































































































                                                                           
                            





























































































































































































                                                                           

/*
 * Simplyfied version of original bin2boot
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <memory.h>


static unsigned char buf[512];

static void usage(void)
{
  printf("usage: bin2boot [-h][-v] <outFile> <headerAddr> \n");
  printf("<imFile1> <imAddr1> <imSize1> [<imFile2> <imAddr2> <imSize2>]\n");
  printf("this function makes image bootable by netboot\n");
  printf("from one or two binary images\n");
  printf("-h         - prints this message\n");
  printf("-v         - verbose output\n");
  printf("outFile    - output file\n");
  printf("headerAddr - address to place header in memory\n");
  printf("             it should be below or equal 0x97e00\n");
  printf("imFile1    - first image\n");
  printf("imAddr1    - its start address, image has to be placed whole\n");
  printf("             below 0x98000 and should not overlap with header\n");
  printf("imSize1    - actual size of compressed image, 0 for uncompressed\n");
  printf("imFile2    - second image\n");
  printf("imAddr2    - its start address\n");
  printf("imSize2    - actual size of compressed image, 0 for uncompressed\n");

  return;
}


int main(int argc, char* argv[])
{
  int      c, verbose;
  extern   int optind;
  FILE     *ofp, *ifp;
  unsigned long headerAddr, addr1, addr2;
  int      size1, size2, len1, len2, len, imageCnt, cnt;
  char     *ofile, *ifile, *end;
  
  verbose = 0;

  /* parse command line options */
  while ((c = getopt(argc, argv, "hv")) >= 0)
    {
      switch (c)
	{
	case 'v':
	  verbose = 1;
	  break;
	case 'h':
	  usage();
	  return 0;
	default:
	  usage();
	  return 1;
	}
    }
  
  if((argc - optind) != 8 && (argc - optind) != 5)
    {
      usage();
      return 1;
    }
  
  ofile = argv[optind];
  ofp   = fopen(ofile, "wb");
  if(ofp == NULL)
    {
      fprintf(stderr, "unable to open file %s\n", ofile);
      return 1;
    }
  
  /* 
   * Layout is very simple first 512 is header shared by all 
   * images, then images at 512 bytes border
   */
  
  /* Fill buffer with 0's */
  memset(buf, 0, sizeof(buf));
  
  fwrite(buf, 1, sizeof(buf), ofp);

  optind++;
  headerAddr = strtoul(argv[optind], &end, 0);
  if(end == argv[optind])
    {
      fprintf(stderr, "bad headerAddr %s\n", argv[optind]);
      fclose(ofp);
      return 1;
    }

  if(headerAddr > 0x97e00)
    {
      fprintf(stderr, "headerAddr is too high 0x%08lx\n", headerAddr);
      fclose(ofp);
      return 1;
    }
  
  /* Copy the first image */
  optind++;
  ifile = argv[optind];
  ifp   = fopen(ifile,"rb");
  if(ifp == NULL)
    {
      fprintf(stderr, "unable to open output file %s\n", ifile);
      fclose(ofp);
      return 1;
    }

  optind++;
  addr1 = strtoul(argv[optind], &end, 0);
  if(end == argv[optind])
    {
      fprintf(stderr, "bad image address %s\n", argv[optind]);
      fclose(ofp);
      return 1;
    }

  optind++;
  size1 = strtoul(argv[optind], &end, 0);
  if(end == argv[optind])
    {
      fprintf(stderr, "bad image size %s\n", argv[optind]);
      fclose(ofp);
      return 1;
    }


  /* Copy first image out and remember its length */
  cnt  = 0;
  for(;;)
    {
      len = fread(buf, 1, sizeof(buf), ifp);

      if(len != 0)
	{
	  fwrite(buf, 1, len, ofp);
	  cnt += sizeof(buf);

          if(len != sizeof(buf))
	    {
	      memset(buf, 0, sizeof(buf) - len);
	      fwrite(buf, 1, sizeof(buf) - len, ofp);
	      break;
	    }

	}
      else
	{
	  break;
	}
    }

  fclose(ifp);

  len1 = cnt;

  if(size1 == 0)
    {
      size1 = cnt;
    }
  else
    {
      memset(buf, 0, sizeof(buf));

      while(cnt < size1)
	{
	  fwrite(buf, 1, sizeof(buf), ofp);
	  cnt += sizeof(buf);
	}

      size1 = cnt;
    }


  /* Let us check agains overlapping */
  if(!(addr1 >= (headerAddr + sizeof(buf)) || (headerAddr >= addr1+size1)))
    {
      /* Areas overlapped */
      printf("area overlapping: \n");
      printf("header address      0x%08lx, its memory size 0x%08x\n", 
	     headerAddr, sizeof(buf));
      printf("first image address 0x%08lx, its memory size 0x%08x\n",
	     addr1, size1);

      fclose(ofp);
      return 1;
    }

  if((addr1 + size1) > 0x98000)
    {
      fprintf(stderr, "imAddr1 is too high 0x%08lx\n", addr1);
      fclose(ofp);
      return 1;
    }
      

  if(optind == (argc - 1))
    {
      imageCnt = 1;
      goto writeHeader;
    }

  imageCnt = 2;

  /* Copy Second Image */
  optind++;
  ifile = argv[optind];
  ifp   = fopen(ifile,"rb");
  if(ifp == NULL)
    {
      fprintf(stderr, "unable to open output file %s\n", ifile);
      fclose(ofp);
      return 1;
    }

  optind++;
  addr2 = strtoul(argv[optind], &end, 0);
  if(end == argv[optind])
    {
      fprintf(stderr, "bad image address %s\n", argv[optind]);
      fclose(ofp);
      return 1;
    }

  optind++;
  size2 = strtoul(argv[optind], &end, 0);
  if(end == argv[optind])
    {
      fprintf(stderr, "bad image size %s\n", argv[optind]);
      fclose(ofp);
      return 1;
    }

  /* Copy second image out and remember its length */
  cnt  = 0;
  for(;;)
    {
      len = fread(buf, 1, sizeof(buf), ifp);
      
      if(len != 0)
	{
	  fwrite(buf, len, 1, ofp);
	  cnt  += sizeof(buf);
	 
	  if(len != sizeof(buf))
	    {
	      memset(buf, 0, sizeof(buf) - len);
	      fwrite(buf, 1, sizeof(buf) - len, ofp);
	      break;
	    }
	}
      else
	{
	  break;
	}
    }

  fclose(ifp);

  len2 = cnt;

  if(size2 == 0)
    {
      size2 = cnt;
    }
  else
    {
      memset(buf, 0, sizeof(buf));

      while(cnt < size2)
	{
	  fwrite(buf, 1, sizeof(buf), ofp);
	  cnt += sizeof(buf);
	}

      size2 = cnt;
    }

  /* Let us check against overlapping */
  if(!((addr2 >= (addr1 + size1) && addr2 >= (headerAddr + sizeof(buf))) ||
       (addr2 < addr1 && addr2 < headerAddr) ||
       (addr1 > headerAddr && addr2 > (headerAddr + sizeof(buf)) &&
	(addr2 + size2) <= addr1) ||
       (addr1 < headerAddr && addr2 > (addr1 + size1) && 
	(addr2 + size2) <= headerAddr)))
     
    {
      /* Areas overlapped */
      printf("area overlapping: \n");
      printf("header address       0x%08lx, its memory size 0x%08x\n", 
	     headerAddr, sizeof(buf));
      printf("first  image address 0x%08lx, its memory size 0x%08x\n",
	     addr1, size1);
      printf("second image address 0x%08lx, its memory size 0x%08x\n",
	     addr2, size2);

      fclose(ofp);
      return 1;
    }

writeHeader:

  /* We know everything so it is time to write buffer */
  memset(buf, 0, 0x30);

  buf[0x0]  = 0x36;
  buf[0x1]  = 0x13;
  buf[0x2]  = 0x03;
  buf[0x3]  = 0x1b;

  buf[0x4]  = 4;

  /* Header address in ds:bx format */
  buf[0x8]  = headerAddr & 0xf;
  buf[0x9]  = 0;
  buf[0xa]  = (headerAddr >> 4) & 0xff;
  buf[0xb]  = (headerAddr >> 12) & 0xff;

  /* 
   * Execute address in cs:ip format, which addr1 
   */
  buf[0xc] = addr1 & 0xf;
  buf[0xd] = 0;
  buf[0xe] = (addr1 >> 4) & 0xff;
  buf[0xf] = (addr1 >> 12) & 0xff;

  /* Flags, tags and lengths */
  buf[0x10] = 4;

  if(imageCnt == 1)
    {
      buf[0x13] = 4;
    }

  /* Load address */
  buf[0x14] = addr1 & 0xff;
  buf[0x15] = (addr1 >> 8) & 0xff;
  buf[0x16] = (addr1 >> 16) & 0xff;
  buf[0x17] = (addr1 >> 24) & 0xff;

  /* Image Length */
  buf[0x18] = len1 & 0xff;
  buf[0x19] = (len1 >> 8) & 0xff;
  buf[0x1a] = (len1 >> 16) & 0xff;
  buf[0x1b] = (len1 >> 24) & 0xff;

  /* Memory Size */
  buf[0x1c] = size1 & 0xff;
  buf[0x1d] = (size1 >> 8) & 0xff;
  buf[0x1e] = (size1 >> 16) & 0xff;
  buf[0x1f] = (size1 >> 24) & 0xff;

  if(imageCnt != 1)
    {

      /* Flags, tags and lengths */
      buf[0x20] = 4;
      
      buf[0x23] = 4;


      /* Load address */
      buf[0x24] = addr2 & 0xff;
      buf[0x25] = (addr2 >> 8) & 0xff;
      buf[0x26] = (addr2 >> 16) & 0xff;
      buf[0x27] = (addr2 >> 24) & 0xff;
      
      /* Image Length */
      buf[0x28] = len2 & 0xff;
      buf[0x29] = (len2 >> 8) & 0xff;
      buf[0x2a] = (len2 >> 16) & 0xff;
      buf[0x2b] = (len2 >> 24) & 0xff;
      
      /* Memory Size */
      buf[0x2c] = size2 & 0xff;
      buf[0x2d] = (size2 >> 8) & 0xff;
      buf[0x2e] = (size2 >> 16) & 0xff;
      buf[0x2f] = (size2 >> 24) & 0xff;
    }

  rewind(ofp);

  fwrite(buf, 1, 0x30, ofp);

  fclose(ofp);

  if(verbose)
    {
      printf("header address       0x%08lx, its memory size 0x%08x\n", 
	     headerAddr, sizeof(buf));
      printf("first  image address 0x%08lx, its memory size 0x%08x\n",
	     addr1, size1);
      printf("second image address 0x%08lx, its memory size 0x%08x\n",
	     addr2, size2);
    }

  return 0;
}