--- mkisofs/Makefile
+++ mkisofs/Makefile
@@ -35,7 +35,7 @@
 		getopt.c getopt1.c \
 		scsi.c \
 		scsi_cdr.c cd_misc.c \
-		modes.c \
+		modes.c silo.c \
 		apple.c volume.c desktop.c mac_label.c
 HFILES=		apple.h bootinfo.h config.h defaults.h diskmbr.h exclude.h \
 		fnmatch.h getopt.h iso9660.h mac_label.h mactypes.h match.h \
--- mkisofs/defaults.h
+++ mkisofs/defaults.h
@@ -22,6 +22,10 @@
 #define  VOLUME_ID_DEFAULT 	"CDROM"
 #define  BOOT_CATALOG_DEFAULT   "boot.catalog"
 #define  BOOT_IMAGE_DEFAULT     NULL
+#define  SILO_BOOT_IMAGE_DEFAULT "boot/second.b"
+#define  SILO_BOOTBLOCK_DEFAULT	"boot/cd.b"
+#define  SILO_CONF_FILE_DEFAULT	"/etc/silo.conf"
+
 #ifdef APPLE_HYB
 #define  APPLE_TYPE_DEFAULT	"TEXT"
 #define  APPLE_CREATOR_DEFAULT	"unix"
--- mkisofs/mkisofs.8
+++ mkisofs/mkisofs.8
@@ -85,6 +85,14 @@
 .I boot_catalog
 ]
 [
+.B \-s
+.I silo_conf_file
+]
+[
+.B \-S
+.I silo_bootblock
+]
+[
 .B \-check-oldnames
 ]
 [
@@ -1272,6 +1280,25 @@
 .B \&.m\&kisofsrc
 with SYSI=system_id.
 If specified in both places, the command line version is used.
+.TP
+.BI \-s " silo_conf_file
+Specifies the path and filename of the SILO configuration file to be
+used when making a "SILO" bootable CD. The pathname must be relative to the
+source path specified to
+.B mkisofs
+and start with a slash.
+The default is
+.I /etc/silo.conf
+See SILO documentation for the syntax of this file.
+.TP
+.BI \-S " silo_bootblock
+Specifies the path and filename of the SILO first stage boot image to be
+used when making a "SILO" bootable CD. The pathname must be relative to the
+source path specified to
+.B mkisofs.
+The default is
+.I boot/cd.b
+The boot image must come from SILO 0.8.7 and higher.
 .TP
 .B \-T
 Generate a file TRANS.TBL in each directory on the CDROM, which can be used
--- mkisofs/mkisofs.c
+++ mkisofs/mkisofs.c
@@ -94,6 +94,7 @@
 int	use_genboot = 0;
 int	use_RockRidge = 0;
 int	use_Joliet = 0;
+int     use_silo = 0;
 int	verbose = 1;
 int	gui = 0;
 int	all_files = 1;	/* New default is to include all files */
@@ -131,6 +132,10 @@
 char	*boot_catalog = BOOT_CATALOG_DEFAULT;
 char	*boot_image = BOOT_IMAGE_DEFAULT;
 char	*genboot_image = BOOT_IMAGE_DEFAULT;
+char    *silo_boot_image = SILO_BOOT_IMAGE_DEFAULT;
+char    *silo_bootblock = SILO_BOOTBLOCK_DEFAULT;
+char    *silo_conf_file = SILO_CONF_FILE_DEFAULT;
+
 int	ucs_level = 3;		/* We now have Unicode tables so use level 3 */
 int	volume_set_size = 1;
 int	volume_sequence_number = 1;
@@ -377,6 +382,8 @@
 
 #endif	/* APPLE_HYB */
 
+#define OPTION_SILO_BOOT		2200
+
 static int	save_pname = 0;
 
 static const struct ld_option ld_options[] =
@@ -407,6 +414,8 @@
 	'\0', NULL, "Start specifying alternative El Torito boot parameters", ONE_DASH},
 	{{"sparc-boot", required_argument, NULL, 'B'},
 	'B', "FILES", "Set sparc boot image names", ONE_DASH},
+	{{"silo-boot", required_argument, NULL, OPTION_SILO_BOOT},
+	'\0', "FILE", "Set SILO second stage boot image name" , ONE_DASH },
 	{{"generic-boot", required_argument, NULL, 'G'},
 	'G', "FILE", "Set generic boot image name", ONE_DASH},
 	{{"sparc-label", required_argument, NULL, OPTION_SPARCLABEL},
@@ -513,7 +522,10 @@
 	{ {"sort", required_argument, NULL, OPTION_SORT},
 	'\0', "FILE", "Sort file content locations according to rules in FILE" , ONE_DASH },
 #endif /* SORTING */
-
+	{ {"silo-conf-file", required_argument, NULL, 's'},
+	  's', "FILE", "Set name of SILO configuration file on the CD", ONE_DASH },
+	{ {"silo-bootblock", required_argument, NULL, 'S'},
+	  'S', "FILE", "Set SILO first stage bootblock image name", ONE_DASH },
 	{{"split-output", no_argument, NULL, OPTION_SPLIT_OUTPUT},
 	'\0', NULL, "Split output into files of approx. 1GB size", ONE_DASH},
 	{{"sysid", required_argument, NULL, OPTION_SYSID},
@@ -1288,6 +1300,34 @@
 #endif
 			}
 			break;
+		  case OPTION_SILO_BOOT:
+		    use_silo++;
+		    silo_boot_image = optarg;  /* pathname of the boot image on cd */
+		    if (silo_boot_image == NULL) {
+		      fprintf(stderr,"Required boot image pathname missing\n");
+		      exit(1);
+		    }
+		    break;
+		  case 'S':
+		    use_silo++;
+		    silo_bootblock = optarg;  /* pathname of the boot image on cd */
+		    if (silo_bootblock == NULL) {
+		      fprintf(stderr,"Required bootblock pathname missing\n");
+		      exit(1);
+		    }
+		    break;
+		  case 's':
+		    use_silo++;
+		    silo_conf_file = optarg;  /* pathname of the boot image on cd */
+		    if (silo_conf_file == NULL) {
+		      fprintf(stderr,"Required SILO config file pathname missing\n");
+		      exit(1);
+		    }
+		    if (*silo_conf_file != '/') {
+		      fprintf(stderr,"SILO config file pathname must start with /\n");
+		      exit(1);
+		    }
+		    break;
 		case OPTION_ABSTRACT:
 			abstract = optarg;
 			if (strlen(abstract) > 37) {
@@ -2742,7 +2782,10 @@
 		outputlist_insert(&sunlabel_desc);
 	if (use_genboot)
 		outputlist_insert(&genboot_desc);
-	outputlist_insert(&padblock_desc);
+        if (use_silo)
+	  outputlist_insert(&silo_desc);
+	else
+	  outputlist_insert(&padblock_desc);
 
 	/* PVD for disc. */
 	outputlist_insert(&voldesc_desc);
--- mkisofs/mkisofs.h
+++ mkisofs/mkisofs.h
@@ -160,6 +160,7 @@
 extern struct output_fragment *out_tail;
 
 extern struct output_fragment padblock_desc;
+extern struct output_fragment silo_desc;
 extern struct output_fragment voldesc_desc;
 extern struct output_fragment joliet_desc;
 extern struct output_fragment torito_desc;
@@ -228,8 +229,15 @@
 	struct directory_entry *s_entry;
 	unsigned int    pad;
 	off_t		off;
+#ifdef __STDC__
+        int           (*filter)(char *, int, int);
+#else
+	int           (*filter)();
+#endif
 };
 
+extern struct deferred_write * dw_head, * dw_tail;
+
 struct eltorito_boot_entry_info {
 	struct eltorito_boot_entry_info *next; 
 	char		*boot_image;
@@ -565,6 +573,9 @@
 extern char    *boot_catalog;
 extern char    *boot_image;
 extern char    *genboot_image;
+extern char    *silo_boot_image;
+extern char    *silo_bootblock;
+extern char    *silo_conf_file;
 extern int	ucs_level;
 extern int      volume_set_size;
 extern int      volume_sequence_number;
--- mkisofs/silo.c
+++ mkisofs/silo.c
@@ -0,0 +1,255 @@
+/*
+ * Program silo.c - Handle SILO bootable iso9660 CD-ROMs.
+ * 
+
+   Copyright (C) 1999 Jakub Jelinek <jakub@redhat.com>.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */
+
+
+static char rcsid[] ="$Id: cdrtools-1.11a06-silo.patch,v 1.1 2001/11/19 17:07:00 bencollins Exp $";
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include "mkisofs.h"
+#include "iso9660.h"
+#include <schily.h>
+
+/* used by Win32 for opening binary file - not used by Unix */
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif /* O_BINARY */
+
+struct sun_disklabel {
+    char	info[128];	/* Informative text string */
+    char	spare0[14];
+    struct sun_info {
+	char	spare1;
+	char	id;
+	char	spare2;
+	char	flags;
+    } infos[8];
+    char	spare1[246];	/* Boot information etc. */
+    char	rspeed[2];      /* 722 - Disk rotational speed */
+    char	pcylcount[2];   /* 722 - Physical cylinder count */
+    char	sparecyl[2];    /* 722 - extra sects per cylinder */
+    char	spare2[4];	/* More magic... */
+    char	ilfact[2];      /* 722 - Interleave factor */
+    char	ncyl[2];        /* 722 - Data cylinder count */
+    char	nacyl[2];       /* 722 - Alt. cylinder count */
+    char	ntrks[2];       /* 722 - Tracks per cylinder */
+    char	nsect[2];       /* 722 - Sectors per track */
+    char	spare3[4];	/* Even more magic... */
+    struct sun_partition {
+        char start_cylinder[4];	/* 732 */
+	char num_sectors[4];	/* 732 */
+    } partitions[8];
+    char	magic[2];       /* 722 - Magic number */
+    char	csum[2];        /* 722 - Label xor'd checksum */
+    struct bootblock_header {
+	char	magic[4];	/* 732 */
+	char	aout[20];
+	char	siloid[8];
+	char	insn[16];
+	char	extent[4];	/* 732 */
+	char	size[4];	/* 732 */
+	char	text[2048-512-56];
+    } bootblock;
+};
+
+static struct {
+    char id;
+    char conf_part;
+    char part;
+    char pad;
+    char conf_file[256];
+} silo_info;
+
+static int silo_size(int starting_extent)
+{
+    last_extent += 16;
+    return 0;
+}
+
+static int silo_filter(char * buffer, int size, int offset)
+{
+    if (offset < 0x808 + sizeof(silo_info)
+	&& offset + size > 0x808)
+    {
+	int i;
+	if (offset < 0x808)
+	{
+	    offset = 0x808 - offset;
+	    size -= offset;
+	    buffer += offset;
+	    offset = 0;
+	}
+	else
+	    offset -= 0x808;
+	i = sizeof(silo_info) - offset;
+	if (i > size) i = size;
+	memcpy (buffer, ((char *)&silo_info) + offset, i);
+    }
+    return 0;
+}
+
+static int silo_write(FILE * outfile)
+{
+    struct directory_entry      * de;
+    struct directory_entry      * de2;
+    struct deferred_write	* dwpnt;
+    int bootblock, i, should_write;
+    struct sun_disklabel	silo_bb;
+    
+    memset (&silo_bb, 0, sizeof (silo_bb));
+    
+    if (*silo_bootblock == '/') silo_bootblock++;
+    if (*silo_boot_image == '/') silo_boot_image++;
+
+    /*
+     * search from root of iso fs to find boot catalog 
+     */
+    de2 = search_tree_file(root, silo_bootblock);
+    if (!de2) 
+    {
+	fprintf(stderr,"Uh oh, I cant find the SILO bootblock!\n");
+	exit(1);
+    }
+
+    /*
+     * now read it from disk
+     */
+    bootblock = open(de2->whole_name, O_RDWR | O_BINARY);
+    if (bootblock == -1) 
+    {
+	fprintf(stderr,"Error opening SILO bootblock for reading.\n");
+	perror("");
+	exit(1);
+    }
+    
+    if (read (bootblock, (char *)&silo_bb.bootblock, 1024) != 1024)
+    {
+	fprintf(stderr,"Error reading SILO bootblock.\n");
+	perror("");
+	exit(1);
+    }
+
+    close (bootblock);
+
+    if (get_732 (silo_bb.bootblock.magic) != 0x01030107
+	|| strncmp (silo_bb.bootblock.siloid, "SILO", 4)
+	|| silo_bb.bootblock.siloid[5] != '.'
+	|| silo_bb.bootblock.siloid[4] < '0'
+	|| silo_bb.bootblock.siloid[4] > '9'
+	|| silo_bb.bootblock.siloid[6] < '0'
+	|| silo_bb.bootblock.siloid[6] > '9'
+	|| silo_bb.bootblock.siloid[7] < '0'
+	|| silo_bb.bootblock.siloid[7] > '9')
+    {
+	fprintf(stderr,"Error: the file %s is not a valid SILO bootblock.\n", silo_bootblock);
+	perror("");
+	exit(1);
+    }
+    
+    /* Check version number. Only SILO 0.87 and up is valid. */
+    if (silo_bb.bootblock.siloid[4] == '0'
+	&& (silo_bb.bootblock.siloid[6] < '8'
+	    || (silo_bb.bootblock.siloid[6] == '8'
+		&& silo_bb.bootblock.siloid[7] <= '6')))
+    {
+	fprintf(stderr,"Error: SILO bootblock is too old. Must be at least 0.8.7.\n");
+	perror("");
+	exit(1);
+    }
+
+    /*
+     * search from root of iso fs to find boot catalog 
+     */
+    de = search_tree_file(root, silo_boot_image);
+    if (!de) 
+    {
+	fprintf(stderr,"Uh oh, I cant find the SILO boot image!\n");
+	exit(1);
+    }
+
+    /*
+     * need to filter second.b, so that we can seed
+     * silo.conf location and other stuff.
+     * We could write it into the de->whole_name file,
+     * but I prefer filtering it like this because
+     * then the tree can be e.g. read only NFS mounted.
+     */
+    for (dwpnt = dw_head; dwpnt; dwpnt = dwpnt->next)
+    {
+	if (!dwpnt->name) continue;
+	if (!strcmp (dwpnt->name, de->whole_name))
+	    dwpnt->filter = silo_filter;
+    }
+
+    set_732 (silo_bb.bootblock.extent, de->starting_block);
+    set_732 (silo_bb.bootblock.size, de->size);
+
+    strcpy (silo_bb.info, "SPARC bootable CD-ROM: ");
+    strcat (silo_bb.info, volume_id);
+
+    should_write = (last_extent - session_start) << 2;
+
+    /* Now some magic */
+    silo_bb.spare0[3] = 1;
+    silo_bb.spare0[13] = 8;
+    for (i = 0; i < 8; i++) {
+	silo_bb.infos[i].id = 0x83;
+	silo_bb.infos[i].flags = 0x18;
+    }
+    set_732 (silo_bb.spare1 + 14, 0x600ddeee);
+    set_722 (silo_bb.rspeed, 0x15e);
+    set_722 (silo_bb.pcylcount, (should_write + 639) / 640);
+    set_722 (silo_bb.ilfact, 1);
+    set_722 (silo_bb.ncyl, (should_write + 639) / 640);
+    set_722 (silo_bb.ntrks, 1);
+    set_722 (silo_bb.nsect, 640);
+    set_732 (silo_bb.partitions[0].num_sectors, should_write);
+    set_722 (silo_bb.magic, 0xdabe);
+    for (i = 0; i < 510; i+=2) {
+	silo_bb.csum[0] ^= silo_bb.info[i];
+	silo_bb.csum[1] ^= silo_bb.info[i+1];
+    }
+
+    xfwrite(&silo_bb, 1, sizeof(silo_bb), outfile);
+    memset (&silo_bb, 0, sizeof(silo_bb));
+
+    for(i=1; i<16; i++)
+    {
+	xfwrite(&silo_bb, 1, sizeof(silo_bb), outfile);
+    }
+
+    memset (&silo_info, 0, sizeof(silo_info));
+    silo_info.id = 'L';
+    silo_info.conf_part = 1;
+    strncpy (silo_info.conf_file, silo_conf_file, 256);
+    silo_info.conf_file[259] = '\0';
+
+    last_extent_written += 16;
+    
+    return 0;
+}
+
+struct output_fragment silo_desc  = {NULL, silo_size, NULL,     silo_write};
--- mkisofs/vms.c
+++ mkisofs/vms.c
@@ -288,7 +288,7 @@
 extern unsigned int last_extent_written;
 
 int
-vms_write_one_file(char *filename, int size, FILE * outfile)
+vms_write_one_file(struct deferred_write * dwpnt, FILE * outfile)
 {
 	int		status,
 			i;
@@ -296,10 +296,12 @@
 	int		count;
 	int		use;
 	int		remain;
+	int             offset = 0;
 
-	open_file(filename);
 
-	remain = size;
+	open_file(dwpnt->name);
+
+	remain = dwpnt->size;
 
 	while (remain > 0) {
 		use = (remain > SECTOR_SIZE * NSECT - 1 ? NSECT * SECTOR_SIZE : remain);
@@ -308,11 +310,14 @@
 		rab->rab$l_ubf = buffer;
 		rab->rab$w_usz = sizeof(buffer);
 		status = sys$read(rab);
+		if (dwpnt->filter)
+		  (* dwpnt->filter)(buffer, use, offset);
 		fwrite(buffer, 1, use, outfile);
 		last_extent_written += use / SECTOR_SIZE;
 		if ((last_extent_written % 1000) < use / SECTOR_SIZE)
 			fprintf(stderr, "%d..", last_extent_written);
 		remain -= use;
+		offset += use;
 	};
 
 	close_file(rab);
--- mkisofs/write.c
+++ mkisofs/write.c
@@ -78,10 +78,10 @@
 						FILE *file));
 static	int	assign_directory_addresses __PR((struct directory *node));
 #ifdef APPLE_HYB
-static	void	write_one_file	__PR((char *filename, unsigned int size,
+static	void	write_one_file	__PR((struct deferred_write *dwpnt,
 					FILE *outfile, off_t off));
 #else
-static	void	write_one_file	__PR((char *filename, unsigned int size,
+static	void	write_one_file	__PR((struct deferred_write *dwpnt,
 					FILE *outfile));
 #endif
 static	void	write_files	__PR((FILE *outfile));
@@ -292,7 +292,7 @@
 static struct deferred_write mac_boot;
 
 #endif	/* APPLE_HYB */
-static struct deferred_write	*dw_head = NULL,
+struct deferred_write	*dw_head = NULL,
 				*dw_tail = NULL;
 
 unsigned int	last_extent_written = 0;
@@ -350,16 +350,14 @@
 
 #ifdef APPLE_HYB
 static void
-write_one_file(filename, size, outfile, off)
-	char		*filename;
-	unsigned int	size;
+write_one_file(dwpnt, outfile, off)
+        struct deferred_write *dwpnt;
 	FILE		*outfile;
 	off_t		off;
 #else
 static void
-write_one_file(filename, size, outfile)
-	char		*filename;
-	unsigned int	size;
+write_one_file(dwpnt, outfile)
+        struct deferred_write *dwpnt;
 	FILE		*outfile;
 #endif	/* APPLE_HYB */
 {
@@ -375,18 +373,19 @@
 	FILE		*infile;
 	int		remain;
 	int	use;
+        int             offset;
 
 
-	if ((infile = fopen(filename, "rb")) == NULL) {
+	if ((infile = fopen(dwpnt->name, "rb")) == NULL) {
 #ifdef	USE_LIBSCHILY
-		comerr("cannot open '%s'\n", filename);
+		comerr("cannot open '%s'\n", dwpnt->name);
 #else
 #if defined(sun) || defined(_AUX_SOURCE)
 		fprintf(stderr, "cannot open %s: (%d)\n",
-				filename, errno);
+				dwpnt->name, errno);
 #else
 		fprintf(stderr, "cannot open %s: %s\n",
-				filename, strerror(errno));
+				dwpnt->name, strerror(errno));
 #endif
 		exit(1);
 #endif
@@ -394,8 +393,8 @@
 #ifdef APPLE_HYB
 	fseek(infile, off, SEEK_SET);
 #endif	/* APPLE_HYB */
-	remain = size;
-
+	remain = dwpnt->size;
+	offset = 0; 
 	while (remain > 0) {
 		use = (remain > SECTOR_SIZE * NSECT - 1 ?
 				NSECT * SECTOR_SIZE : remain);
@@ -404,13 +403,16 @@
 		memset(buffer, 0, use);
 		if (fread(buffer, 1, use, infile) == 0) {
 #ifdef	USE_LIBSCHILY
-			comerr("cannot read from %s\n", filename);
+			comerr("cannot read from %s\n", dwpnt->name);
 #else
-			fprintf(stderr, "cannot read from %s\n", filename);
+			fprintf(stderr, "cannot read from %s\n", dwpnt->name);
 			exit(1);
 #endif
 		}
+		if (dwpnt->filter)
+		  (* dwpnt->filter)(buffer, use, offset);
 		xfwrite(buffer, 1, use, outfile);
+		offset += use;
 		last_extent_written += use / SECTOR_SIZE;
 #if 0
 		if ((last_extent_written % 1000) < use / SECTOR_SIZE) {
@@ -465,13 +467,12 @@
 		} else {
 
 #ifdef VMS
-			vms_write_one_file(dwpnt->name, dwpnt->size, outfile);
+			vms_write_one_file(dwpnt, outfile);
 #else
 #ifdef APPLE_HYB
-			write_one_file(dwpnt->name, dwpnt->size, outfile,
-								dwpnt->off);
+			write_one_file(dwpnt, outfile,dwpnt->off);
 #else
-			write_one_file(dwpnt->name, dwpnt->size, outfile);
+			write_one_file(dwpnt, outfile);
 #endif	/* APPLE_HYB */
 #endif
 			free(dwpnt->name);
@@ -1054,6 +1055,7 @@
 				dwpnt->next = NULL;
 				dwpnt->size = s_entry->size;
 				dwpnt->extent = last_extent;
+				dwpnt->filter = NULL;
 				set_733((char *) s_entry->isorec.extent,
 								last_extent);
 				s_entry->starting_block = last_extent;
@@ -1613,8 +1615,7 @@
 
 		/* write out HFS boot block */
 		if (mac_boot.name)
-			write_one_file(mac_boot.name, mac_boot.size, outfile,
-								mac_boot.off);
+			write_one_file(&mac_boot, outfile, mac_boot.off);
 	}
 #endif	/* APPLE_HYB */
 
