mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 05:12:30 +00:00 
			
		
		
		
	Script to extract EFI el torito image (e.g. needed to get ISO9660 efi driver from vmware media)
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@10747 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
		
							
								
								
									
										96
									
								
								xCAT-server/share/xcat/scripts/extractefiboot.pl
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										96
									
								
								xCAT-server/share/xcat/scripts/extractefiboot.pl
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
#!/usr/bin/env perl
 | 
			
		||||
#This is a utility to scrape out the EFI boot image from an el torito enabled disk
 | 
			
		||||
use strict;
 | 
			
		||||
use Fcntl qw/SEEK_SET/;
 | 
			
		||||
my $iso;
 | 
			
		||||
my $outfile;
 | 
			
		||||
GetOptions("out=s" => \$outfile,
 | 
			
		||||
	   "iso=s" => \$iso);
 | 
			
		||||
my $emul;
 | 
			
		||||
my $blksize=2048;
 | 
			
		||||
my $istream;
 | 
			
		||||
use Getopt::Long;
 | 
			
		||||
sub grabimage {
 | 
			
		||||
	my $bootcat = shift;
 | 
			
		||||
	my $image;
 | 
			
		||||
	my @recdata = unpack("C2vC2vV",$bootcat);
 | 
			
		||||
	unless ($recdata[0] == 0x88) { printf "Error: EFI torito record not bootable\n"; exit; }
 | 
			
		||||
	$emul=$recdata[1];
 | 
			
		||||
	#for now, ignore load segment, system type
 | 
			
		||||
	seek($istream,$recdata[6]*$blksize,SEEK_SET);
 | 
			
		||||
	my $size=$recdata[5];
 | 
			
		||||
	if ($size==0) { $size = 1; } #if 0/1, it's auto-detect time
 | 
			
		||||
	my $readbytes=read($istream,$image,$size*512);
 | 
			
		||||
	if ($size == 1) { #we have to interpret the FAT header to get the real size
 | 
			
		||||
		seek($istream,$recdata[6]*$blksize,SEEK_SET); # go back to beginning
 | 
			
		||||
		my @fatheader = unpack("C11vCvC3vC11V",$image);
 | 
			
		||||
		my $secsize=$fatheader[11];
 | 
			
		||||
		if ($fatheader[17]) {
 | 
			
		||||
			$size=$secsize*($fatheader[17]);
 | 
			
		||||
		} else {
 | 
			
		||||
			die "Unsupported FAT header, requires test of commented code segment";
 | 
			
		||||
		}
 | 
			
		||||
#		} elsif ($fatheader[-1]) {
 | 
			
		||||
#			$size=$secsize*$fatheader[-1];
 | 
			
		||||
#		}
 | 
			
		||||
		$readbytes=read($istream,$image,$size);
 | 
			
		||||
	}
 | 
			
		||||
	my $outh;
 | 
			
		||||
	open($outh,">",$outfile);
 | 
			
		||||
	print $outh $image;
 | 
			
		||||
	close($outh);
 | 
			
		||||
}
 | 
			
		||||
if (! -r $iso) { 
 | 
			
		||||
	printf "Error, $iso does not seem to exist or is not readable";
 | 
			
		||||
	exit 1;
 | 
			
		||||
}
 | 
			
		||||
open($istream,"<",$iso) || die "Error opening $iso";
 | 
			
		||||
my $bootsect;
 | 
			
		||||
seek($istream,17*$blksize,SEEK_SET);
 | 
			
		||||
my $readbytes = read($istream,$bootsect,0x4b);
 | 
			
		||||
unless ($readbytes == 0x4b) {
 | 
			
		||||
	printf "Error reading boot record volume from $iso\n";
 | 
			
		||||
	exit 1;
 | 
			
		||||
}
 | 
			
		||||
my @recdata;
 | 
			
		||||
@recdata = unpack("CA5CA32C32V",$bootsect); #it would have been nice if the el torito actually said little endian on it..
 | 
			
		||||
unless ($recdata[0] == 0 and $recdata[1] eq 'CD001'
 | 
			
		||||
	and $recdata[2] == 1 and $recdata[3] eq "EL TORITO SPECIFICATION") { 
 | 
			
		||||
	printf "Error: Boot record volume format invalid\n";
 | 
			
		||||
	exit 1;
 | 
			
		||||
}
 | 
			
		||||
my $bootcatidx=$recdata[-1];
 | 
			
		||||
my $bootcat;
 | 
			
		||||
seek($istream,$bootcatidx*$blksize,SEEK_SET);
 | 
			
		||||
$readbytes = read($istream,$bootcat,0x20);
 | 
			
		||||
unless ($readbytes == 0x20) { printf "Error reading boot catalog at $bootcatidx\n"; exit 1; }
 | 
			
		||||
@recdata = unpack("C*",$bootcat);
 | 
			
		||||
unless ($recdata[0] == 1 and $recdata[0x1e] == 0x55 and $recdata[0x1f] == 0xaa) {
 | 
			
		||||
	printf "Boot catalog has invalid header\n"; exit 1; 
 | 
			
		||||
}
 | 
			
		||||
$readbytes = read($istream,$bootcat,0x20);
 | 
			
		||||
my $image;
 | 
			
		||||
unless ($readbytes == 0x20) { printf "Error reading default El torito record\n"; exit; }
 | 
			
		||||
if ($recdata[1] == 0xef) { #wow, the efi record came first, actually interpret that first record
 | 
			
		||||
	grabimage($bootcat);
 | 
			
		||||
} else { # keep looking for an *EFI* record
 | 
			
		||||
	#read in first header
 | 
			
		||||
	read($istream,$bootcat,0x20);
 | 
			
		||||
	@recdata = unpack("CCv",$bootcat);
 | 
			
		||||
	while ($recdata[0] == 0x90 and $recdata[1] != 0xef) { 	
 | 
			
		||||
		my $additionalrecords=$recdata[2];
 | 
			
		||||
		while ($additionalrecords) {
 | 
			
		||||
		 	read($istream,$bootcat,0x20); #throw away irrelevant sectors
 | 
			
		||||
			$additionalrecords -= 1;
 | 
			
		||||
		}
 | 
			
		||||
		read($istream,$bootcat,0x20); #throw away irrelevant sectors
 | 
			
		||||
		@recdata = unpack("CCv",$bootcat);
 | 
			
		||||
	}
 | 
			
		||||
	if ($recdata[1] != 0xef) {
 | 
			
		||||
		printf "No EFI boot image found\n";
 | 
			
		||||
		exit 1;
 | 
			
		||||
	}
 | 
			
		||||
	$readbytes=read($istream,$bootcat,0x20);
 | 
			
		||||
	grabimage($bootcat);
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
		Reference in New Issue
	
	Block a user