boot.c
上传用户:xiejiait
上传日期:2007-01-06
资源大小:881k
文件大小:10k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)boot.c 1.2 99/12/19 Copyright 1999 J. Schilling */
  2. #ifndef lint
  3. static char sccsid[] =
  4. "@(#)boot.c 1.2 99/12/19 Copyright 1999 J. Schilling";
  5. #endif
  6. /*
  7.  * Support for generic boot (sector 0..16)
  8.  * and to boot Sun sparc systems.
  9.  *
  10.  * Copyright (c) 1999 J. Schilling
  11.  */
  12. /*
  13.  * This program is free software; you can redistribute it and/or modify
  14.  * it under the terms of the GNU General Public License as published by
  15.  * the Free Software Foundation; either version 2, or (at your option)
  16.  * any later version.
  17.  *
  18.  * This program is distributed in the hope that it will be useful,
  19.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  * GNU General Public License for more details.
  22.  *
  23.  * You should have received a copy of the GNU General Public License
  24.  * along with this program; see the file COPYING.  If not, write to
  25.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  26.  */
  27. #include <mconfig.h>
  28. #include "mkisofs.h"
  29. #include <standard.h>
  30. #include <unixstd.h>
  31. #include <fctldefs.h>
  32. #include <utypes.h>
  33. #include <intcvt.h>
  34. #ifndef howmany
  35. #define howmany(x, y) (((x)+((y)-1))/(y))
  36. #endif
  37. #ifndef roundup
  38. #define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
  39. #endif
  40. #define NDKMAP 8
  41. #define DKL_MAGIC 0xDABE /* magic number */ 
  42. #define DKL_MAGIC_0 0xDA /* magic number high byte */ 
  43. #define DKL_MAGIC_1 0xBE /* magic number low byte  */ 
  44. #define CD_DEFLABEL "CD-ROM Disc with Sun sparc boot created by mkisofs"
  45. /*
  46.  * Define a virtual geometry for the CD disk label.
  47.  * The current values are stolen from Sun install disks and do not seem to be
  48.  * a good idea as they limit the size of the CD to 327680 sectors which is less
  49.  * than 74 minutes.
  50.  * There are 84 minute CD's with 378000 sectors and there will be DVD's with
  51.  * even more.
  52.  */
  53. #define CD_RPM 350
  54. #define CD_PCYL 2048
  55. #define CD_APC 0
  56. #define CD_INTRLV 1
  57. #define CD_NCYL 2048
  58. #define CD_ACYL 0
  59. #define CD_NHEAD 1
  60. #define CD_NSECT 640
  61. /*
  62.  * NOTE: The virtual cylinder size on CD must be a mutiple of 2048.
  63.  *  This is true if CD_NSECT is a multiple of 4.
  64.  */
  65. #define CD_CYLSIZE (CD_NSECT*CD_NHEAD*512)
  66. #define V_VERSION 1 /* The VTOC version  */
  67. #define VTOC_SANE 0x600DDEEE /* Indicates a sane VTOC */
  68. #define V_ROOT 0x02 /* Root partiton  */
  69. #define V_USR 0x04 /* Usr partiton  */
  70. #define V_RONLY 0x10 /* Read only  */
  71. struct sun_label {
  72. char dkl_ascilabel[128];
  73. struct dk_vtoc {
  74. Uchar v_version[4]; /* layout version  */
  75. char v_volume[8]; /* volume name  */
  76. Uchar v_nparts[2]; /* number of partitions  */
  77. struct dk_map2 {
  78. Uchar p_tag[2]; /* ID tag of partition */
  79. Uchar p_flag[2];/* permission flag  */
  80. } v_part[NDKMAP];
  81. Uchar v_xxpad[2]; /* To come over Sun's alignement problem */
  82. Uchar v_bootinfo[3*4];/* info for mboot  */
  83. Uchar v_sanity[4]; /* tp verify vtoc sanity */
  84. Uchar v_reserved[10*4];
  85. Uchar v_timestamp[NDKMAP*4];
  86. } dkl_vtoc; /* vtoc inclusions from AT&T SVr4 */
  87. char dkl_pad[512-(128+sizeof(struct dk_vtoc)+NDKMAP*8+14*2)];
  88. Uchar   dkl_rpm[2]; /* rotations per minute */
  89. Uchar dkl_pcyl[2]; /* # physical cylinders */ 
  90. Uchar dkl_apc[2]; /* alternates per cylinder */
  91. Uchar dkl_obs1[2]; /* obsolete */
  92. Uchar dkl_obs2[2]; /* obsolete */
  93. Uchar dkl_intrlv[2]; /* interleave factor */
  94. Uchar dkl_ncyl[2]; /* # of data cylinders */
  95. Uchar dkl_acyl[2]; /* # of alternate cylinders */
  96. Uchar dkl_nhead[2]; /* # of heads in this partition */
  97. Uchar dkl_nsect[2]; /* # of 512 byte sectors per track */
  98. Uchar dkl_obs3[2]; /* obsolete */
  99. Uchar dkl_obs4[2]; /* obsolete */
  100. struct dk_map { /* logical partitions */
  101. Uchar dkl_cylno[4]; /* starting cylinder */
  102. Uchar dkl_nblk[4]; /* number of blocks */
  103. } dkl_map[NDKMAP];/* logical partition headers */
  104. Uchar dkl_magic[2]; /* identifies this label format */
  105. Uchar dkl_cksum[2]; /* xor checksum of sector */
  106. };
  107. LOCAL struct sun_label cd_label;
  108. LOCAL char *boot_files[NDKMAP];
  109. LOCAL void init_sparc_label __PR((void));
  110. EXPORT void sparc_boot_label __PR((char *label));
  111. EXPORT void scan_sparc_boot __PR((char *files));
  112. EXPORT int make_sun_label __PR((void));
  113. LOCAL int sunboot_write __PR((FILE *outfile));
  114. LOCAL int sunlabel_size __PR((int starting_extent));
  115. LOCAL int sunlabel_write __PR((FILE * outfile));
  116. LOCAL int genboot_size __PR((int starting_extent));
  117. LOCAL int genboot_write __PR((FILE * outfile));
  118. /*
  119.  * Set the virtual geometry in the disk label.
  120.  * If we like to make the geometry variable, we may change
  121.  * dkl_ncyl and dkl_pcyl later.
  122.  */
  123. LOCAL void
  124. init_sparc_label()
  125. {
  126. i_to_4_byte(cd_label.dkl_vtoc.v_version, V_VERSION);
  127. i_to_2_byte(cd_label.dkl_vtoc.v_nparts, NDKMAP);
  128. i_to_4_byte(cd_label.dkl_vtoc.v_sanity, VTOC_SANE);
  129. i_to_2_byte(cd_label.dkl_rpm, CD_RPM);
  130. i_to_2_byte(cd_label.dkl_pcyl, CD_PCYL);
  131. i_to_2_byte(cd_label.dkl_apc, CD_APC);
  132. i_to_2_byte(cd_label.dkl_intrlv, CD_INTRLV);
  133. i_to_2_byte(cd_label.dkl_ncyl, CD_NCYL);
  134. i_to_2_byte(cd_label.dkl_acyl, CD_ACYL);
  135. i_to_2_byte(cd_label.dkl_nhead, CD_NHEAD);
  136. i_to_2_byte(cd_label.dkl_nsect, CD_NSECT);
  137. cd_label.dkl_magic[0] = DKL_MAGIC_0;
  138. cd_label.dkl_magic[1] = DKL_MAGIC_1;
  139. }
  140. /*
  141.  * For command line parser: set ASCII label.
  142.  */
  143. EXPORT void
  144. sparc_boot_label(label)
  145. char *label;
  146. {
  147. strncpy(cd_label.dkl_ascilabel, label, 127);
  148. }
  149. /*
  150.  * Parse the command line argument for boot images.
  151.  */
  152. EXPORT void
  153. scan_sparc_boot(files)
  154. char *files;
  155. {
  156. char *p;
  157. int i = 1;
  158. struct stat statbuf;
  159. int status;
  160. init_sparc_label();
  161. do {
  162. if (i >= NDKMAP)
  163. comerrno(EX_BAD, "Too many boot partitions.n");
  164. boot_files[i++] = files;
  165. if ((p = strchr(files, ',')) != NULL)
  166. *p++ = '';
  167. files = p;
  168. } while (p);
  169. i_to_2_byte(cd_label.dkl_vtoc.v_part[0].p_tag,  V_USR);
  170. i_to_2_byte(cd_label.dkl_vtoc.v_part[0].p_flag, V_RONLY);
  171. for (i=0; i < NDKMAP; i++) {
  172. p = boot_files[i];
  173. if (p == NULL || *p == '')
  174. continue;
  175. status = stat_filter(p, &statbuf);
  176. if (status < 0 || access(p, R_OK) < 0)
  177. comerr("Cannot access '%s'.n", p);
  178. i_to_4_byte(cd_label.dkl_map[i].dkl_nblk,
  179. roundup(statbuf.st_size, CD_CYLSIZE)/512);
  180. i_to_2_byte(cd_label.dkl_vtoc.v_part[i].p_tag,  V_ROOT);
  181. i_to_2_byte(cd_label.dkl_vtoc.v_part[i].p_flag, V_RONLY);
  182. }
  183. }
  184. /*
  185.  * Finish the Sun disk label and compute the size of the additional data.
  186.  */
  187. EXPORT int
  188. make_sun_label()
  189. {
  190. int last;
  191. int cyl = 0;
  192. int nblk;
  193. int bsize;
  194. int i;
  195. /*
  196.  * Compute the size of the padding for the iso9660 image
  197.  * to allow the next partition to start on a cylinder boundary.
  198.  */
  199. last = roundup(last_extent, (CD_CYLSIZE/2048));
  200. i_to_4_byte(cd_label.dkl_map[0].dkl_nblk, last*4);
  201. bsize = 0;
  202. for (i=0; i < NDKMAP; i++) {
  203. if ((nblk = a_to_4_byte(cd_label.dkl_map[i].dkl_nblk)) == 0)
  204. continue;
  205. i_to_4_byte(cd_label.dkl_map[i].dkl_cylno, cyl);
  206. cyl += nblk / (CD_CYLSIZE/512);
  207. if (i > 0)
  208. bsize += nblk;
  209. }
  210. bsize /= 4;
  211. return (last-last_extent+bsize);
  212. }
  213. /*
  214.  * Write out Sun boot partitions.
  215.  */
  216. LOCAL int
  217. sunboot_write(outfile)
  218. FILE *outfile;
  219. {
  220. char buffer[SECTOR_SIZE];
  221. int i;
  222. int n;
  223. int nblk;
  224. int amt;
  225. int f;
  226. memset(buffer, 0, sizeof(buffer));
  227. /*
  228.  * Write padding to the iso9660 image to allow the
  229.  * boot partitions to start on a cylinder boundary.
  230.  */
  231. amt = roundup(last_extent_written, (CD_CYLSIZE/2048)) - last_extent_written;
  232. for (n=0; n < amt; n++) {
  233.   xfwrite(buffer, 1, SECTOR_SIZE, outfile);
  234. last_extent_written++;
  235. }
  236. for (i=1; i < NDKMAP; i++) {
  237. if ((nblk = a_to_4_byte(cd_label.dkl_map[i].dkl_nblk)) == 0)
  238. continue;
  239. if ((f = open(boot_files[i], O_RDONLY| O_BINARY)) < 0)
  240. comerr("Cannot open '%s'.n", boot_files[i]);
  241. amt = nblk / 4;
  242. for (n=0; n < amt; n++) {
  243. memset(buffer, 0, sizeof(buffer));
  244. if (read(f, buffer, SECTOR_SIZE) < 0)
  245. comerr("Read error on '%s'.n", boot_files[i]);
  246.   xfwrite(buffer, 1, SECTOR_SIZE, outfile);
  247. last_extent_written++;
  248. }
  249. close(f);
  250. }
  251. fprintf(stderr, "Total extents including sparc boot = %dn", 
  252. last_extent_written - session_start);
  253. return (0);
  254. }
  255. /*
  256.  * Do size management for the Sun disk label that is located in the first
  257.  * sector of a disk.
  258.  */
  259. LOCAL int
  260. sunlabel_size(starting_extent)
  261. int starting_extent;
  262. {
  263. if (last_extent != 0)
  264. comerrno(EX_BAD, "Cannot create sparc boot on offset != 0.n");
  265. last_extent++;
  266. return 0;
  267. }
  268. /*
  269.  * Cumpute the checksum and write a Sun disk label to the first sector
  270.  * of the disk.
  271.  * If the -generic-boot option has been specified too, overlay the
  272.  * Sun disk label on the firs 512 bytes of the generic boot code.
  273.  */
  274. LOCAL int
  275. sunlabel_write(outfile)
  276. FILE *outfile;
  277. {
  278.  char buffer[SECTOR_SIZE];
  279. register char *p;
  280. register short count = (512/2) - 1;
  281.  int f;
  282. memset(buffer, 0, sizeof(buffer));
  283. if (genboot_image) {
  284. if ((f = open(genboot_image, O_RDONLY| O_BINARY)) < 0)
  285. comerr("Cannot open '%s'.n", genboot_image);
  286. if (read(f, buffer, SECTOR_SIZE) < 0)
  287. comerr("Read error on '%s'.n", genboot_image);
  288. close(f);
  289. }
  290. /*
  291.  * If we don't already have a Sun disk label text
  292.  * set up the default.
  293.  */
  294. if (cd_label.dkl_ascilabel[0] == '')
  295. strcpy(cd_label.dkl_ascilabel, CD_DEFLABEL);
  296. p = (char *)&cd_label;
  297. cd_label.dkl_cksum[0] = 0;
  298. cd_label.dkl_cksum[1] = 0; 
  299. while (count--) {
  300. cd_label.dkl_cksum[0] ^= *p++;
  301. cd_label.dkl_cksum[1] ^= *p++; 
  302. }
  303. memcpy(buffer, &cd_label, 512);
  304.   xfwrite(buffer, 1, SECTOR_SIZE, outfile);
  305. last_extent_written++;
  306. return (0);
  307. }
  308. /*
  309.  * Do size management for the generic boot code on sectors 0..16.
  310.   */
  311. LOCAL int
  312. genboot_size(starting_extent)
  313. int starting_extent;
  314. {
  315. if (last_extent > 1)
  316. comerrno(EX_BAD, "Cannot create generic boot on offset != 0.n");
  317. last_extent = 16;
  318. return 0;
  319. }
  320. /*
  321.  * Write the generic boot code to sectors 0..16.
  322.  * If there is a Sun disk label, start writing at sector 1.
  323.  */
  324. LOCAL int
  325. genboot_write(outfile)
  326. FILE *outfile;
  327. {
  328. char buffer[SECTOR_SIZE];
  329. int i;
  330. int f;
  331. if ((f = open(genboot_image, O_RDONLY| O_BINARY)) < 0)
  332. comerr("Cannot open '%s'.n", genboot_image);
  333. for(i=0; i < 16; i++) {
  334. memset(buffer, 0, sizeof(buffer));
  335. if (read(f, buffer, SECTOR_SIZE) < 0)
  336. comerr("Read error on '%s'.n", genboot_image);
  337. if (i != 0 || last_extent_written == 0) {
  338.   xfwrite(buffer, 1, SECTOR_SIZE, outfile);
  339. last_extent_written++;
  340. }
  341. }
  342. close(f);
  343. return (0);
  344. }
  345. struct output_fragment sunboot_desc = {NULL, NULL, NULL, sunboot_write};
  346. struct output_fragment sunlabel_desc = {NULL, sunlabel_size, NULL, sunlabel_write};
  347. struct output_fragment genboot_desc = {NULL, genboot_size, NULL, genboot_write};