15
15
# You should have received a copy of the GNU General Public License
16
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
170
171
use constant ROM_SIGNATURE => 0xaa55;
171
172
use constant PCI_SIGNATURE => 'PCIR';
173
use constant PCI_LAST_IMAGE => 0x80;
172
174
use constant PNP_SIGNATURE => '$PnP';
175
use constant IPXE_SIGNATURE => 'iPXE';
174
our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PNP_SIGNATURE );
177
our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE
178
PNP_SIGNATURE IPXE_SIGNATURE );
175
179
our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
177
181
use constant JMP_SHORT => 0xeb;
178
182
use constant JMP_NEAR => 0xe9;
183
use constant CALL_NEAR => 0xe8;
181
186
my $dest = shift;
229
237
init => { offset => 0x03, length => 0x03,
230
238
pack => \&pack_init, unpack => \&unpack_init },
231
239
checksum => { offset => 0x06, length => 0x01, pack => "C" },
240
ipxe_header => { offset => 0x10, length => 0x02, pack => "S" },
232
241
bofm_header => { offset => 0x14, length => 0x02, pack => "S" },
233
242
undi_header => { offset => 0x16, length => 0x02, pack => "S" },
234
243
pci_header => { offset => 0x18, length => 0x02, pack => "S" },
253
=item C<< set ( $data ) >>
255
Set option ROM contents.
261
my $self = tied(%$hash);
265
$self->{data} = \$data;
267
# Split out any data belonging to the next image
268
delete $self->{next_image};
269
my $length = ( $hash->{length} * 512 );
270
my $pci_header = $hash->pci_header();
271
if ( ( $length < length $data ) &&
272
( defined $pci_header ) &&
273
( ! ( $pci_header->{last_image} & PCI_LAST_IMAGE ) ) ) {
274
my $remainder = substr ( $data, $length );
275
$data = substr ( $data, 0, $length );
276
$self->{next_image} = new Option::ROM;
277
$self->{next_image}->set ( $remainder );
285
Get option ROM contents.
291
my $self = tied(%$hash);
293
my $data = ${$self->{data}};
294
$data .= $self->{next_image}->get() if $self->{next_image};
244
300
=item C<< load ( $filename ) >>
246
302
Load option ROM contents from the file C<$filename>.
399
=item C<< undi_header () >>
401
Return a C<Option::ROM::UNDI> object representing the ROM's UNDI header,
408
my $self = tied(%$hash);
410
my $offset = $hash->{undi_header};
411
return undef unless $offset != 0;
413
return Option::ROM::UNDI->new ( $self->{data}, $offset );
418
=item C<< ipxe_header () >>
420
Return a C<Option::ROM::iPXE> object representing the ROM's iPXE
427
my $self = tied(%$hash);
429
my $offset = $hash->{ipxe_header};
430
return undef unless $offset != 0;
432
return Option::ROM::iPXE->new ( $self->{data}, $offset );
437
=item C<< next_image () >>
439
Return a C<Option::ROM> object representing the next image within the
446
my $self = tied(%$hash);
448
return $self->{next_image};
342
453
=item C<< checksum () >>
344
455
Calculate the byte checksum of the ROM.
499
610
return unpack ( "Z*", $raw );
613
##############################################################################
617
##############################################################################
619
package Option::ROM::UNDI;
632
tie %$hash, "Option::ROM::Fields", {
637
signature => { offset => 0x00, length => 0x04, pack => "a4" },
638
struct_length => { offset => 0x04, length => 0x01, pack => "C" },
639
checksum => { offset => 0x05, length => 0x01, pack => "C" },
640
struct_revision =>{ offset => 0x06, length => 0x01, pack => "C" },
641
version_revision =>{ offset => 0x07, length => 0x01, pack => "C" },
642
version_minor => { offset => 0x08, length => 0x01, pack => "C" },
643
version_major => { offset => 0x09, length => 0x01, pack => "C" },
644
loader_entry => { offset => 0x0a, length => 0x02, pack => "S" },
645
stack_size => { offset => 0x0c, length => 0x02, pack => "S" },
646
data_size => { offset => 0x0e, length => 0x02, pack => "S" },
647
code_size => { offset => 0x10, length => 0x02, pack => "S" },
648
bus_type => { offset => 0x12, length => 0x04, pack => "a4" },
653
# Retrieve true length of structure
654
my $self = tied ( %$hash );
655
$self->{length} = $hash->{struct_length};
662
my $self = tied(%$hash);
664
return $self->checksum();
669
my $self = tied(%$hash);
671
$hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff );
674
##############################################################################
678
##############################################################################
680
package Option::ROM::iPXE;
693
tie %$hash, "Option::ROM::Fields", {
698
signature => { offset => 0x00, length => 0x04, pack => "a4" },
699
struct_length => { offset => 0x04, length => 0x01, pack => "C" },
700
checksum => { offset => 0x05, length => 0x01, pack => "C" },
701
shrunk_length => { offset => 0x06, length => 0x01, pack => "C" },
702
build_id => { offset => 0x08, length => 0x04, pack => "L" },
707
# Retrieve true length of structure
708
my $self = tied ( %$hash );
709
$self->{length} = $hash->{struct_length};
716
my $self = tied(%$hash);
718
return $self->checksum();
723
my $self = tied(%$hash);
725
$hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff );