1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
|
/*
* This file has been modified for the cdrkit suite.
*
* The behaviour and appearence of the program code below can differ to a major
* extent from the version distributed by the original author(s).
*
* For details, see Changelog file distributed with the cdrkit package. If you
* received this file from another source then ask the distributing person for
* a log of modifications.
*
*/
/*
* Program boot-mips.c - Handle big-endian boot extensions to iso9660.
*
* Written by Steve McIntyre <steve@einval.com> June 2004
*
* Heavily inspired by / borrowed from genisovh:
*
* Copyright: (C) 2002 by Florian Lohoff <flo@rfc822.org>
* (C) 2004 by Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, Version 2, as published by the
* Free Software Foundation.
*
* Format for volume header information
*
* The volume header is a block located at the beginning of all disk
* media (sector 0). It contains information pertaining to physical
* device parameters and logical partition information.
*
* The volume header is manipulated by disk formatters/verifiers,
* partition builders (e.g. fx, dvhtool, and mkfs), and disk drivers.
*
* Previous versions of IRIX wrote a copy of the volume header is
* located at sector 0 of each track of cylinder 0. These copies were
* never used, and reduced the capacity of the volume header to hold large
* files, so this practice was discontinued.
* The volume header is constrained to be less than or equal to 512
* bytes long. A particular copy is assumed valid if no drive errors
* are detected, the magic number is correct, and the 32 bit 2's complement
* of the volume header is correct. The checksum is calculated by initially
* zeroing vh_csum, summing the entire structure and then storing the
* 2's complement of the sum. Thus a checksum to verify the volume header
* should be 0.
*
* The error summary table, bad sector replacement table, and boot blocks are
* located by searching the volume directory within the volume header.
*
* Tables are sized simply by the integral number of table records that
* will fit in the space indicated by the directory entry.
*
* The amount of space allocated to the volume header, replacement blocks,
* and other tables is user defined when the device is formatted.
*/
#include <inttypes.h>
#ifndef MIN
#define MIN(a,b) ( (a<b) ? a : b )
#endif
/*
* device parameters are in the volume header to determine mapping
* from logical block numbers to physical device addresses
*
* Linux doesn't care ...
*/
struct device_parameters {
uint8_t dp_skew; /* spiral addressing skew */
uint8_t dp_gap1; /* words of 0 before header */
uint8_t dp_gap2; /* words of 0 between hdr and data */
uint8_t dp_spares_cyl; /* This is for drives (such as SCSI
that support zone oriented sparing, where the zone is larger
than one track. It gets subracteded from the cylinder size
( dp_trks0 * dp_sec) when doing partition size calculations */
uint16_t dp_cyls; /* number of usable cylinders (i.e.,
doesn't include cylinders reserved by the drive for badblocks,
etc.). For drives with variable geometry, this number may be
decreased so that:
dp_cyls * ((dp_heads * dp_trks0) - dp_spares_cyl) <= actualcapacity
This happens on SCSI drives such as the Wren IV and Toshiba 156
Also see dp_cylshi below */
uint16_t dp_shd0; /* starting head vol 0 */
uint16_t dp_trks0; /* number of tracks / cylinder vol 0*/
uint8_t dp_ctq_depth; /* Depth of CTQ queue */
uint8_t dp_cylshi; /* high byte of 24 bits of cylinder count */
uint16_t dp_unused; /* not used */
uint16_t dp_secs; /* number of sectors/track */
uint16_t dp_secbytes; /* length of sector in bytes */
uint16_t dp_interleave; /* sector interleave */
int32_t dp_flags; /* controller characteristics */
int32_t dp_datarate; /* bytes/sec for kernel stats */
int32_t dp_nretries; /* max num retries on data error */
int32_t dp_mspw; /* ms per word to xfer, for iostat */
uint16_t dp_xgap1; /* Gap 1 for xylogics controllers */
uint16_t dp_xsync; /* sync delay for xylogics controllers */
uint16_t dp_xrdly; /* read delay for xylogics controllers */
uint16_t dp_xgap2; /* gap 2 for xylogics controllers */
uint16_t dp_xrgate; /* read gate for xylogics controllers */
uint16_t dp_xwcont; /* write continuation for xylogics */
};
/*
* Device characterization flags
* (dp_flags)
*/
#define DP_SECTSLIP 0x00000001 /* sector slip to spare sector */
#define DP_SECTFWD 0x00000002 /* forward to replacement sector */
#define DP_TRKFWD 0x00000004 /* forward to replacement track */
#define DP_MULTIVOL 0x00000008 /* multiple volumes per spindle */
#define DP_IGNOREERRORS 0x00000010 /* transfer data regardless of errors */
#define DP_RESEEK 0x00000020 /* recalibrate as last resort */
#define DP_CTQ_EN 0x00000040 /* enable command tag queueing */
/*
* Boot blocks, bad sector tables, and the error summary table, are located
* via the volume_directory.
*/
#define VDNAMESIZE 8
struct volume_directory {
int8_t vd_name[VDNAMESIZE]; /* name */
int32_t vd_lbn; /* logical block number */
int32_t vd_nbytes; /* file length in bytes */
};
/*
* partition table describes logical device partitions
* (device drivers examine this to determine mapping from logical units
* to cylinder groups, device formatters/verifiers examine this to determine
* location of replacement tracks/sectors, etc)
*
* NOTE: pt_firstlbn SHOULD BE CYLINDER ALIGNED
*/
struct partition_table { /* one per logical partition */
int32_t pt_nblks; /* # of logical blks in partition */
int32_t pt_firstlbn; /* first lbn of partition */
int32_t pt_type; /* use of partition */
};
#define PTYPE_VOLHDR 0 /* partition is volume header */
#define PTYPE_TRKREPL 1 /* partition is used for repl trks */
#define PTYPE_SECREPL 2 /* partition is used for repl secs */
#define PTYPE_RAW 3 /* partition is used for data */
#define PTYPE_BSD42 4 /* partition is 4.2BSD file system */
#define PTYPE_BSD 4 /* partition is 4.2BSD file system */
#define PTYPE_SYSV 5 /* partition is SysV file system */
#define PTYPE_VOLUME 6 /* partition is entire volume */
#define PTYPE_EFS 7 /* partition is sgi EFS */
#define PTYPE_LVOL 8 /* partition is part of a logical vol */
#define PTYPE_RLVOL 9 /* part of a "raw" logical vol */
#define PTYPE_XFS 10 /* partition is sgi XFS */
#define PTYPE_XFSLOG 11 /* partition is sgi XFS log */
#define PTYPE_XLV 12 /* partition is part of an XLV vol */
#define PTYPE_XVM 13 /* partition is sgi XVM */
#define PTYPE_LSWAP 0x82 /* partition is Linux swap */
#define PTYPE_LINUX 0x83 /* partition is Linux native */
#define NPTYPES 16
#define VHMAGIC 0xbe5a941 /* randomly chosen value */
#define NPARTAB 16 /* 16 unix partitions */
#define NVDIR 15 /* max of 15 directory entries */
#define BFNAMESIZE 16 /* max 16 chars in boot file name */
/* Partition types for ARCS */
#define NOT_USED 0 /* Not used */
#define FAT_SHORT 1 /* FAT filesystem, 12-bit FAT entries */
#define FAT_LONG 4 /* FAT filesystem, 16-bit FAT entries */
#define EXTENDED 5 /* extended partition */
#define HUGE 6 /* huge partition- MS/DOS 4.0 and later */
/* Active flags for ARCS */
#define BOOTABLE 0x00;
#define NOT_BOOTABLE 0x80;
struct volume_header {
int32_t vh_magic; /* identifies volume header */
int16_t vh_rootpt; /* root partition number */
int16_t vh_swappt; /* swap partition number */
int8_t vh_bootfile[BFNAMESIZE]; /* name of file to boot */
struct device_parameters vh_dp; /* device parameters */
struct volume_directory vh_vd[NVDIR]; /* other vol hdr contents */
struct partition_table vh_pt[NPARTAB]; /* device partition layout */
int32_t vh_csum; /* volume header checksum */
int32_t vh_fill; /* fill out to 512 bytes */
char pad[1536]; /* pad out to 2048 */
};
#include <mconfig.h>
#include "genisoimage.h"
#include <fctldefs.h>
#include <utypes.h>
#include <intcvt.h>
#include "match.h"
#include "diskmbr.h"
#include "bootinfo.h"
#include <schily.h>
#include "endianconv.h"
int add_boot_mips_filename(char *filename);
static int boot_mips_write(FILE *outfile);
#define MAX_NAMES 15
static char *boot_mips_filename[MAX_NAMES] =
{
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL
};
static int boot_mips_num_files = 0;
#define SECTORS_PER_TRACK 32
#define BYTES_PER_SECTOR 512
int add_boot_mips_filename(char *filename)
{
if (boot_mips_num_files < MAX_NAMES)
{
boot_mips_filename[boot_mips_num_files] = filename;
boot_mips_num_files++;
}
else
{
#ifdef USE_LIBSCHILY
comerrno(EX_BAD, "Too many MIPS boot files!\n");
#else
fprintf(stderr, "Too many MIPS boot files!\n");
exit(1);
#endif
}
return 0;
}
static void vh_calc_checksum(struct volume_header *vh)
{
uint32_t newsum = 0;
unsigned char *buffer = (unsigned char *)vh;
unsigned int i;
vh->vh_csum = 0;
for(i = 0; i < sizeof(struct volume_header); i += 4)
newsum -= read_be32(&buffer[i]);
write_be32(newsum, (unsigned char *)&vh->vh_csum);
}
static char *file_base_name(char *path)
{
char *endptr = path;
char *ptr = path;
while (*ptr != '\0')
{
if ('/' == *ptr)
endptr = ++ptr;
else
++ptr;
}
return endptr;
}
static int boot_mips_write(FILE *outfile)
{
struct directory_entry *boot_file; /* Boot file we need to search for */
unsigned long length = 0;
unsigned long extent = 0;
int i;
struct volume_header vh;
unsigned long long iso_size = 0;
char *filename = NULL;
memset(&vh, 0, sizeof(vh));
iso_size = last_extent * 2048;
write_be32(VHMAGIC, (unsigned char *)&vh.vh_magic);
/* Values from an IRIX cd */
write_be16(BYTES_PER_SECTOR, (unsigned char *)&vh.vh_dp.dp_secbytes);
write_be16(SECTORS_PER_TRACK, (unsigned char *)&vh.vh_dp.dp_secs);
write_be32(DP_RESEEK|DP_IGNOREERRORS|DP_TRKFWD, (unsigned char *)&vh.vh_dp.dp_flags);
write_be16(1, (unsigned char *)&vh.vh_dp.dp_trks0);
write_be16((iso_size + BYTES_PER_SECTOR - 1) / (SECTORS_PER_TRACK * BYTES_PER_SECTOR),
(unsigned char *)&vh.vh_dp.dp_cyls);
for(i = 0; i < boot_mips_num_files; i++)
{
boot_file = search_tree_file(root, boot_mips_filename[i]);
if (!boot_file) {
#ifdef USE_LIBSCHILY
comerrno(EX_BAD, "Uh oh, I cant find the MIPS boot file '%s'!\n",
boot_mips_filename[i]);
#else
fprintf(stderr, "Uh oh, I cant find the MIPS boot file '%s'!\n",
boot_mips_filename[i]);
exit(1);
#endif
}
extent = get_733(boot_file->isorec.extent) * 4;
length = ((get_733(boot_file->isorec.size) + 2047) / 2048) * 2048;
filename = file_base_name(boot_mips_filename[i]);
strncpy((char *)vh.vh_vd[i].vd_name, filename, MIN(VDNAMESIZE, strlen(filename)));
write_be32(extent, (unsigned char *)&vh.vh_vd[i].vd_lbn);
write_be32(length, (unsigned char *)&vh.vh_vd[i].vd_nbytes);
fprintf(stderr, "Found mips boot image %s, using extent %lu (0x%lX), #blocks %lu (0x%lX)\n",
filename, extent, extent, length, length);
}
/* Create volume partition on whole cd iso */
write_be32((iso_size + (BYTES_PER_SECTOR - 1))/ BYTES_PER_SECTOR, (unsigned char *)&vh.vh_pt[10].pt_nblks);
write_be32(0, (unsigned char *)&vh.vh_pt[10].pt_firstlbn);
write_be32(PTYPE_VOLUME, (unsigned char *)&vh.vh_pt[10].pt_type);
/* Create volume header partition, also on WHOLE cd iso */
write_be32((iso_size + (BYTES_PER_SECTOR - 1))/ BYTES_PER_SECTOR, (unsigned char *)&vh.vh_pt[8].pt_nblks);
write_be32(0, (unsigned char *)&vh.vh_pt[8].pt_firstlbn);
write_be32(PTYPE_VOLHDR, (unsigned char *)&vh.vh_pt[8].pt_type);
/* Create checksum */
vh_calc_checksum(&vh);
jtwrite(&vh, sizeof(vh), 1, 0, FALSE);
xfwrite(&vh, sizeof(vh), 1, outfile, 0, FALSE);
last_extent_written++;
return 0;
}
struct output_fragment mipsboot_desc = {NULL, oneblock_size, NULL, boot_mips_write, "MIPS boot block"};
|