From bd3ae47ba7d37ed3691abac6113ea94fa1f448d0 Mon Sep 17 00:00:00 2001 From: jbjohnso Date: Tue, 11 Oct 2011 19:10:08 +0000 Subject: [PATCH] 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 --- .../share/xcat/scripts/extractefiboot.pl | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100755 xCAT-server/share/xcat/scripts/extractefiboot.pl diff --git a/xCAT-server/share/xcat/scripts/extractefiboot.pl b/xCAT-server/share/xcat/scripts/extractefiboot.pl new file mode 100755 index 000000000..ea7124b8d --- /dev/null +++ b/xCAT-server/share/xcat/scripts/extractefiboot.pl @@ -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); +} +