/* * 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 June 2004 * * Heavily inspired by / borrowed from genisovh: * * Copyright: (C) 2002 by Florian Lohoff * (C) 2004 by Thiemo Seufer * * 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 #ifndef MIN #define MIN(a,b) ( (a #include "genisoimage.h" #include #include #include #include "match.h" #include "diskmbr.h" #include "bootinfo.h" #include #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"};