mkprep.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * Makes a prep bootable image which can be dd'd onto
  3. * a disk device to make a bootdisk. Will take
  4. * as input a elf executable, strip off the header
  5. * and write out a boot image as:
  6. * 1) default - strips elf header
  7. * suitable as a network boot image
  8. * 2) -pbp - strips elf header and writes out prep boot partition image
  9. * cat or dd onto disk for booting
  10. * 3) -asm - strips elf header and writes out as asm data
  11. * useful for generating data for a compressed image
  12. * -- Cort
  13. *
  14. * Modified for x86 hosted builds by Matt Porter <porter@neta.com>
  15. * Modified for Sparc hosted builds by Peter Wahl <PeterWahl@web.de>
  16. */
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. /* size of read buffer */
  21. #define SIZE 0x1000
  22. /*
  23. * Partition table entry
  24. * - from the PReP spec
  25. */
  26. typedef struct partition_entry {
  27. unsigned char boot_indicator;
  28. unsigned char starting_head;
  29. unsigned char starting_sector;
  30. unsigned char starting_cylinder;
  31. unsigned char system_indicator;
  32. unsigned char ending_head;
  33. unsigned char ending_sector;
  34. unsigned char ending_cylinder;
  35. unsigned char beginning_sector[4];
  36. unsigned char number_of_sectors[4];
  37. } partition_entry_t;
  38. #define BootActive 0x80
  39. #define SystemPrep 0x41
  40. void copy_image(FILE *, FILE *);
  41. void write_prep_partition(FILE *, FILE *);
  42. void write_asm_data(FILE *, FILE *);
  43. unsigned int elfhdr_size = 65536;
  44. int main(int argc, char *argv[])
  45. {
  46. FILE *in, *out;
  47. int argptr = 1;
  48. int prep = 0;
  49. int asmoutput = 0;
  50. if (argc < 3 || argc > 4) {
  51. fprintf(stderr, "usage: %s [-pbp] [-asm] <boot-file> <image>\n",
  52. argv[0]);
  53. exit(-1);
  54. }
  55. /* needs to handle args more elegantly -- but this is a small/simple program */
  56. /* check for -pbp */
  57. if (!strcmp(argv[argptr], "-pbp")) {
  58. prep = 1;
  59. argptr++;
  60. }
  61. /* check for -asm */
  62. if (!strcmp(argv[argptr], "-asm")) {
  63. asmoutput = 1;
  64. argptr++;
  65. }
  66. /* input file */
  67. if (!strcmp(argv[argptr], "-"))
  68. in = stdin;
  69. else if (!(in = fopen(argv[argptr], "r")))
  70. exit(-1);
  71. argptr++;
  72. /* output file */
  73. if (!strcmp(argv[argptr], "-"))
  74. out = stdout;
  75. else if (!(out = fopen(argv[argptr], "w")))
  76. exit(-1);
  77. argptr++;
  78. /* skip elf header in input file */
  79. /*if ( !prep )*/
  80. fseek(in, elfhdr_size, SEEK_SET);
  81. /* write prep partition if necessary */
  82. if (prep)
  83. write_prep_partition(in, out);
  84. /* write input image to bootimage */
  85. if (asmoutput)
  86. write_asm_data(in, out);
  87. else
  88. copy_image(in, out);
  89. return 0;
  90. }
  91. void store_le32(unsigned int v, unsigned char *p)
  92. {
  93. p[0] = v;
  94. p[1] = v >>= 8;
  95. p[2] = v >>= 8;
  96. p[3] = v >> 8;
  97. }
  98. void write_prep_partition(FILE *in, FILE *out)
  99. {
  100. unsigned char block[512];
  101. partition_entry_t pe;
  102. unsigned char *entry = block;
  103. unsigned char *length = block + 4;
  104. long pos = ftell(in), size;
  105. if (fseek(in, 0, SEEK_END) < 0) {
  106. fprintf(stderr,"info failed\n");
  107. exit(-1);
  108. }
  109. size = ftell(in);
  110. if (fseek(in, pos, SEEK_SET) < 0) {
  111. fprintf(stderr,"info failed\n");
  112. exit(-1);
  113. }
  114. memset(block, '\0', sizeof(block));
  115. /* set entry point and boot image size skipping over elf header */
  116. store_le32(0x400/*+65536*/, entry);
  117. store_le32(size-elfhdr_size+0x400, length);
  118. /* sets magic number for msdos partition (used by linux) */
  119. block[510] = 0x55;
  120. block[511] = 0xAA;
  121. /*
  122. * Build a "PReP" partition table entry in the boot record
  123. * - "PReP" may only look at the system_indicator
  124. */
  125. pe.boot_indicator = BootActive;
  126. pe.system_indicator = SystemPrep;
  127. /*
  128. * The first block of the diskette is used by this "boot record" which
  129. * actually contains the partition table. (The first block of the
  130. * partition contains the boot image, but I digress...) We'll set up
  131. * one partition on the diskette and it shall contain the rest of the
  132. * diskette.
  133. */
  134. pe.starting_head = 0; /* zero-based */
  135. pe.starting_sector = 2; /* one-based */
  136. pe.starting_cylinder = 0; /* zero-based */
  137. pe.ending_head = 1; /* assumes two heads */
  138. pe.ending_sector = 18; /* assumes 18 sectors/track */
  139. pe.ending_cylinder = 79; /* assumes 80 cylinders/diskette */
  140. /*
  141. * The "PReP" software ignores the above fields and just looks at
  142. * the next two.
  143. * - size of the diskette is (assumed to be)
  144. * (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
  145. * - unlike the above sector numbers, the beginning sector is zero-based!
  146. */
  147. #if 0
  148. store_le32(1, pe.beginning_sector);
  149. #else
  150. /* This has to be 0 on the PowerStack? */
  151. store_le32(0, pe.beginning_sector);
  152. #endif
  153. store_le32(2*18*80-1, pe.number_of_sectors);
  154. memcpy(&block[0x1BE], &pe, sizeof(pe));
  155. fwrite(block, sizeof(block), 1, out);
  156. fwrite(entry, 4, 1, out);
  157. fwrite(length, 4, 1, out);
  158. /* set file position to 2nd sector where image will be written */
  159. fseek( out, 0x400, SEEK_SET );
  160. }
  161. void copy_image(FILE *in, FILE *out)
  162. {
  163. char buf[SIZE];
  164. int n;
  165. while ( (n = fread(buf, 1, SIZE, in)) > 0 )
  166. fwrite(buf, 1, n, out);
  167. }
  168. void
  169. write_asm_data(FILE *in, FILE *out)
  170. {
  171. int i, cnt, pos = 0;
  172. unsigned int cksum = 0, val;
  173. unsigned char *lp;
  174. unsigned char buf[SIZE];
  175. size_t len;
  176. fputs("\t.data\n\t.globl input_data\ninput_data:\n", out);
  177. while ((len = fread(buf, 1, sizeof(buf), in)) > 0) {
  178. cnt = 0;
  179. lp = buf;
  180. /* Round up to longwords */
  181. while (len & 3)
  182. buf[len++] = '\0';
  183. for (i = 0; i < len; i += 4) {
  184. if (cnt == 0)
  185. fputs("\t.long\t", out);
  186. fprintf(out, "0x%02X%02X%02X%02X",
  187. lp[0], lp[1], lp[2], lp[3]);
  188. val = *(unsigned long *)lp;
  189. cksum ^= val;
  190. lp += 4;
  191. if (++cnt == 4) {
  192. cnt = 0;
  193. fprintf(out, " # %x \n", pos+i-12);
  194. } else {
  195. fputs(",", out);
  196. }
  197. }
  198. if (cnt)
  199. fputs("0\n", out);
  200. pos += len;
  201. }
  202. fprintf(out, "\t.globl input_len\ninput_len:\t.long\t0x%x\n", pos);
  203. fprintf(stderr, "cksum = %x\n", cksum);
  204. }