mkprep.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:7k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: SCCS/s.mkprep.c 1.7 05/18/01 06:20:29 patch
  3.  */
  4. /*
  5.  * Makes a prep bootable image which can be dd'd onto
  6.  * a disk device to make a bootdisk.  Will take
  7.  * as input a elf executable, strip off the header
  8.  * and write out a boot image as:
  9.  * 1) default - strips elf header
  10.  *      suitable as a network boot image
  11.  * 2) -pbp - strips elf header and writes out prep boot partition image
  12.  *      cat or dd onto disk for booting
  13.  * 3) -asm - strips elf header and writes out as asm data
  14.  *      useful for generating data for a compressed image
  15.  *                  -- Cort
  16.  *
  17.  * Modified for x86 hosted builds by Matt Porter <porter@neta.com>
  18.  */
  19. #include <fcntl.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <sys/stat.h>
  24. #include <unistd.h>
  25. #define cpu_to_le32(x) le32_to_cpu((x))
  26. unsigned long le32_to_cpu(unsigned long x)
  27. {
  28.       return (((x & 0x000000ffU) << 24) |
  29. ((x & 0x0000ff00U) <<  8) |
  30. ((x & 0x00ff0000U) >>  8) |
  31. ((x & 0xff000000U) >> 24));
  32. }
  33. #define cpu_to_le16(x) le16_to_cpu((x))
  34. unsigned short le16_to_cpu(unsigned short x)
  35. {
  36. return (((x & 0x00ff) << 8) |
  37. ((x & 0xff00) >> 8));
  38. }
  39. #define cpu_to_be32(x) (x)
  40. #define be32_to_cpu(x) (x)
  41. #define cpu_to_be16(x) (x)
  42. #define be16_to_cpu(x) (x)
  43. /* size of read buffer */
  44. #define SIZE 0x1000
  45. typedef unsigned long dword_t;
  46. typedef unsigned short word_t;
  47. typedef unsigned char byte_t;
  48. typedef byte_t block_t[512];
  49. typedef byte_t page_t[4096];
  50. /*
  51.  * Partition table entry
  52.  *  - from the PReP spec
  53.  */
  54. typedef struct partition_entry {
  55.   byte_t boot_indicator;
  56.   byte_t starting_head;
  57.   byte_t starting_sector;
  58.   byte_t starting_cylinder;
  59.   byte_t system_indicator;
  60.   byte_t ending_head;
  61.   byte_t ending_sector;
  62.   byte_t ending_cylinder;
  63.   dword_t beginning_sector;
  64.   dword_t number_of_sectors;
  65. } partition_entry_t;
  66. #define BootActive 0x80
  67. #define SystemPrep 0x41
  68. void copy_image(int , int);
  69. void write_prep_partition(int , int );
  70. void write_asm_data( int in, int out );
  71. unsigned int elfhdr_size = 65536;
  72. int main(int argc, char *argv[])
  73. {
  74.   int in_fd, out_fd;
  75.   int argptr = 1;
  76.   unsigned int prep = 0;
  77.   unsigned int asmoutput = 0;
  78.   if ( (argc < 3) || (argc > 4) )
  79.   {
  80.     fprintf(stderr, "usage: %s [-pbp] [-asm] <boot-file> <image>n",argv[0]);
  81.     exit(-1);
  82.   }
  83.   /* needs to handle args more elegantly -- but this is a small/simple program */
  84.   
  85.   /* check for -pbp */
  86.   if ( !strcmp( argv[argptr], "-pbp" ) )
  87.   {
  88.     prep = 1;
  89.     argptr++;
  90.   }
  91.   
  92.   /* check for -asm */
  93.   if ( !strcmp( argv[argptr], "-asm" ) )
  94.   {
  95.     asmoutput = 1;
  96.     argptr++;
  97.   }
  98.   /* input file */
  99.   if ( !strcmp( argv[argptr], "-" ) )
  100.     in_fd = 0; /* stdin */
  101.   else
  102.     if ((in_fd = open( argv[argptr] , 0)) < 0)
  103.       exit(-1);
  104.   argptr++;
  105.   /* output file */
  106.   if ( !strcmp( argv[argptr], "-" ) )
  107.     out_fd = 1; /* stdout */
  108.   else
  109.     if ((out_fd = creat( argv[argptr] , 0755)) < 0)
  110.       exit(-1);
  111.   argptr++;
  112.   /* skip elf header in input file */
  113.   /*if ( !prep )*/
  114.   lseek(in_fd, elfhdr_size, SEEK_SET);
  115.   
  116.   /* write prep partition if necessary */
  117.   if ( prep )
  118.   write_prep_partition( in_fd, out_fd );
  119.   /* write input image to bootimage */
  120.   if ( asmoutput )
  121.   write_asm_data( in_fd, out_fd );
  122.   else
  123.   copy_image(in_fd, out_fd);
  124.   
  125.   return 0;
  126. }
  127. void write_prep_partition(int in, int out)
  128. {
  129.   unsigned char block[512];
  130.   partition_entry_t *pe = (partition_entry_t *)&block[0x1BE];
  131.   dword_t *entry  = (dword_t *)&block[0];
  132.   dword_t *length = (dword_t *)&block[sizeof(long)];
  133.   struct stat info;
  134.   
  135.   if (fstat(in, &info) < 0)
  136.   {
  137.     fprintf(stderr,"info failedn");
  138.     exit(-1);
  139.   }
  140.   
  141.   bzero( block, sizeof block );
  142.  
  143.   /* set entry point and boot image size skipping over elf header */
  144. #ifdef __i386__
  145.   *entry = 0x400/*+65536*/;
  146.   *length = info.st_size-elfhdr_size+0x400;
  147. #else
  148.   *entry = cpu_to_le32(0x400/*+65536*/);
  149.   *length = cpu_to_le32(info.st_size-elfhdr_size+0x400);
  150. #endif /* __i386__ */
  151.   /* sets magic number for msdos partition (used by linux) */
  152.   block[510] = 0x55;
  153.   block[511] = 0xAA;
  154.   
  155.   /*
  156.    * Build a "PReP" partition table entry in the boot record
  157.    *  - "PReP" may only look at the system_indicator
  158.    */
  159.   pe->boot_indicator   = BootActive;
  160.   pe->system_indicator = SystemPrep;
  161.   /*
  162.    * The first block of the diskette is used by this "boot record" which
  163.    * actually contains the partition table. (The first block of the
  164.    * partition contains the boot image, but I digress...)  We'll set up
  165.    * one partition on the diskette and it shall contain the rest of the
  166.    * diskette.
  167.    */
  168.   pe->starting_head     = 0; /* zero-based      */
  169.   pe->starting_sector   = 2; /* one-based      */
  170.   pe->starting_cylinder = 0; /* zero-based      */
  171.   pe->ending_head       = 1; /* assumes two heads      */
  172.   pe->ending_sector     = 18; /* assumes 18 sectors/track      */
  173.   pe->ending_cylinder   = 79; /* assumes 80 cylinders/diskette     */
  174.   /*
  175.    * The "PReP" software ignores the above fields and just looks at
  176.    * the next two.
  177.    *   - size of the diskette is (assumed to be)
  178.    *     (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
  179.    *   - unlike the above sector numbers, the beginning sector is zero-based!
  180.    */
  181. #if 0
  182.   pe->beginning_sector  = cpu_to_le32(1);
  183. #else
  184.   /* This has to be 0 on the PowerStack? */   
  185. #ifdef __i386__
  186.   pe->beginning_sector  = 0;
  187. #else
  188.   pe->beginning_sector  = cpu_to_le32(0);
  189. #endif /* __i386__ */
  190. #endif    
  191. #ifdef __i386__
  192.   pe->number_of_sectors = 2*18*80-1;
  193. #else
  194.   pe->number_of_sectors = cpu_to_le32(2*18*80-1);
  195. #endif /* __i386__ */
  196.   write( out, block, sizeof(block) );
  197.   write( out, entry, sizeof(*entry) );
  198.   write( out, length, sizeof(*length) );  
  199.   /* set file position to 2nd sector where image will be written */
  200.   lseek( out, 0x400, SEEK_SET );
  201. }
  202. void
  203. copy_image(int in, int out)
  204. {
  205.   char buf[SIZE];
  206.   int n;
  207.   while ( (n = read(in, buf, SIZE)) > 0 )
  208.     write(out, buf, n);
  209. }
  210. void
  211. write_asm_data( int in, int out )
  212. {
  213.   int i, cnt, pos, len;
  214.   unsigned int cksum, val;
  215.   unsigned char *lp;
  216.   unsigned char buf[SIZE];
  217.   unsigned char str[256];
  218.   
  219.   write( out, "t.datant.globl input_dataninput_data:n",
  220.  strlen( "t.datant.globl input_dataninput_data:n" ) );
  221.   pos = 0;
  222.   cksum = 0;
  223.   while ((len = read(in, buf, sizeof(buf))) > 0)
  224.   {
  225.     cnt = 0;
  226.     lp = (unsigned char *)buf;
  227.     len = (len + 3) & ~3;  /* Round up to longwords */
  228.     for (i = 0;  i < len;  i += 4)
  229.     {
  230.       if (cnt == 0)
  231.       {
  232. write( out, "t.longt", strlen( "t.longt" ) );
  233.       }
  234.       sprintf( str, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
  235.       write( out, str, strlen(str) );
  236.       val = *(unsigned long *)lp;
  237.       cksum ^= val;
  238.       lp += 4;
  239.       if (++cnt == 4)
  240.       {
  241. cnt = 0;
  242. sprintf( str, " # %x n", pos+i-12);
  243. write( out, str, strlen(str) );
  244.       } else
  245.       {
  246. write( out, ",", 1 );
  247.       }
  248.     }
  249.     if (cnt)
  250.     {
  251.       write( out, "0n", 2 );
  252.     }
  253.     pos += len;
  254.   }
  255.   sprintf(str, "t.globl input_lenninput_len:t.longt0x%xn", pos);
  256.   write( out, str, strlen(str) );
  257.   fprintf(stderr, "cksum = %xn", cksum);
  258. }