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