|  | @@ -172,9 +172,10 @@ use constant ROM_SIGNATURE => 0xaa55;
 | 
		
	
		
			
			| 172 | 172 |  use constant PCI_SIGNATURE => 'PCIR';
 | 
		
	
		
			
			| 173 | 173 |  use constant PCI_LAST_IMAGE => 0x80;
 | 
		
	
		
			
			| 174 | 174 |  use constant PNP_SIGNATURE => '$PnP';
 | 
		
	
		
			
			|  | 175 | +use constant IPXE_SIGNATURE => 'iPXE';
 | 
		
	
		
			
			| 175 | 176 |  
 | 
		
	
		
			
			| 176 | 177 |  our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE
 | 
		
	
		
			
			| 177 |  | -		      PNP_SIGNATURE );
 | 
		
	
		
			
			|  | 178 | +		      PNP_SIGNATURE IPXE_SIGNATURE );
 | 
		
	
		
			
			| 178 | 179 |  our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
 | 
		
	
		
			
			| 179 | 180 |  
 | 
		
	
		
			
			| 180 | 181 |  use constant JMP_SHORT => 0xeb;
 | 
		
	
	
		
			
			|  | @@ -232,6 +233,7 @@ sub new {
 | 
		
	
		
			
			| 232 | 233 |        init =>		{ offset => 0x03, length => 0x03,
 | 
		
	
		
			
			| 233 | 234 |  			  pack => \&pack_init, unpack => \&unpack_init },
 | 
		
	
		
			
			| 234 | 235 |        checksum =>	{ offset => 0x06, length => 0x01, pack => "C" },
 | 
		
	
		
			
			|  | 236 | +      ipxe_header =>	{ offset => 0x10, length => 0x02, pack => "S" },
 | 
		
	
		
			
			| 235 | 237 |        bofm_header =>	{ offset => 0x14, length => 0x02, pack => "S" },
 | 
		
	
		
			
			| 236 | 238 |        undi_header =>	{ offset => 0x16, length => 0x02, pack => "S" },
 | 
		
	
		
			
			| 237 | 239 |        pci_header =>	{ offset => 0x18, length => 0x02, pack => "S" },
 | 
		
	
	
		
			
			|  | @@ -390,6 +392,25 @@ sub pnp_header {
 | 
		
	
		
			
			| 390 | 392 |  
 | 
		
	
		
			
			| 391 | 393 |  =pod
 | 
		
	
		
			
			| 392 | 394 |  
 | 
		
	
		
			
			|  | 395 | +=item C<< ipxe_header () >>
 | 
		
	
		
			
			|  | 396 | +
 | 
		
	
		
			
			|  | 397 | +Return a C<Option::ROM::iPXE> object representing the ROM's iPXE
 | 
		
	
		
			
			|  | 398 | +header, if present.
 | 
		
	
		
			
			|  | 399 | +
 | 
		
	
		
			
			|  | 400 | +=cut
 | 
		
	
		
			
			|  | 401 | +
 | 
		
	
		
			
			|  | 402 | +sub ipxe_header {
 | 
		
	
		
			
			|  | 403 | +  my $hash = shift;
 | 
		
	
		
			
			|  | 404 | +  my $self = tied(%$hash);
 | 
		
	
		
			
			|  | 405 | +
 | 
		
	
		
			
			|  | 406 | +  my $offset = $hash->{ipxe_header};
 | 
		
	
		
			
			|  | 407 | +  return undef unless $offset != 0;
 | 
		
	
		
			
			|  | 408 | +
 | 
		
	
		
			
			|  | 409 | +  return Option::ROM::iPXE->new ( $self->{data}, $offset );
 | 
		
	
		
			
			|  | 410 | +}
 | 
		
	
		
			
			|  | 411 | +
 | 
		
	
		
			
			|  | 412 | +=pod
 | 
		
	
		
			
			|  | 413 | +
 | 
		
	
		
			
			| 393 | 414 |  =item C<< next_image () >>
 | 
		
	
		
			
			| 394 | 415 |  
 | 
		
	
		
			
			| 395 | 416 |  Return a C<Option::ROM> object representing the next image within the
 | 
		
	
	
		
			
			|  | @@ -566,4 +587,58 @@ sub product {
 | 
		
	
		
			
			| 566 | 587 |    return unpack ( "Z*", $raw );
 | 
		
	
		
			
			| 567 | 588 |  }
 | 
		
	
		
			
			| 568 | 589 |  
 | 
		
	
		
			
			|  | 590 | +##############################################################################
 | 
		
	
		
			
			|  | 591 | +#
 | 
		
	
		
			
			|  | 592 | +# Option::ROM::iPXE
 | 
		
	
		
			
			|  | 593 | +#
 | 
		
	
		
			
			|  | 594 | +##############################################################################
 | 
		
	
		
			
			|  | 595 | +
 | 
		
	
		
			
			|  | 596 | +package Option::ROM::iPXE;
 | 
		
	
		
			
			|  | 597 | +
 | 
		
	
		
			
			|  | 598 | +use strict;
 | 
		
	
		
			
			|  | 599 | +use warnings;
 | 
		
	
		
			
			|  | 600 | +use Carp;
 | 
		
	
		
			
			|  | 601 | +use bytes;
 | 
		
	
		
			
			|  | 602 | +
 | 
		
	
		
			
			|  | 603 | +sub new {
 | 
		
	
		
			
			|  | 604 | +  my $class = shift;
 | 
		
	
		
			
			|  | 605 | +  my $data = shift;
 | 
		
	
		
			
			|  | 606 | +  my $offset = shift;
 | 
		
	
		
			
			|  | 607 | +
 | 
		
	
		
			
			|  | 608 | +  my $hash = {};
 | 
		
	
		
			
			|  | 609 | +  tie %$hash, "Option::ROM::Fields", {
 | 
		
	
		
			
			|  | 610 | +    data => $data,
 | 
		
	
		
			
			|  | 611 | +    offset => $offset,
 | 
		
	
		
			
			|  | 612 | +    length => 0x06,
 | 
		
	
		
			
			|  | 613 | +    fields => {
 | 
		
	
		
			
			|  | 614 | +      signature =>	{ offset => 0x00, length => 0x04, pack => "a4" },
 | 
		
	
		
			
			|  | 615 | +      struct_length =>	{ offset => 0x04, length => 0x01, pack => "C" },
 | 
		
	
		
			
			|  | 616 | +      checksum =>	{ offset => 0x05, length => 0x01, pack => "C" },
 | 
		
	
		
			
			|  | 617 | +      shrunk_length =>	{ offset => 0x06, length => 0x01, pack => "C" },
 | 
		
	
		
			
			|  | 618 | +      build_id =>	{ offset => 0x08, length => 0x04, pack => "L" },
 | 
		
	
		
			
			|  | 619 | +    },
 | 
		
	
		
			
			|  | 620 | +  };
 | 
		
	
		
			
			|  | 621 | +  bless $hash, $class;
 | 
		
	
		
			
			|  | 622 | +
 | 
		
	
		
			
			|  | 623 | +  # Retrieve true length of structure
 | 
		
	
		
			
			|  | 624 | +  my $self = tied ( %$hash );
 | 
		
	
		
			
			|  | 625 | +  $self->{length} = $hash->{struct_length};
 | 
		
	
		
			
			|  | 626 | +
 | 
		
	
		
			
			|  | 627 | +  return $hash;
 | 
		
	
		
			
			|  | 628 | +}
 | 
		
	
		
			
			|  | 629 | +
 | 
		
	
		
			
			|  | 630 | +sub checksum {
 | 
		
	
		
			
			|  | 631 | +  my $hash = shift;
 | 
		
	
		
			
			|  | 632 | +  my $self = tied(%$hash);
 | 
		
	
		
			
			|  | 633 | +
 | 
		
	
		
			
			|  | 634 | +  return $self->checksum();
 | 
		
	
		
			
			|  | 635 | +}
 | 
		
	
		
			
			|  | 636 | +
 | 
		
	
		
			
			|  | 637 | +sub fix_checksum {
 | 
		
	
		
			
			|  | 638 | +  my $hash = shift;
 | 
		
	
		
			
			|  | 639 | +  my $self = tied(%$hash);
 | 
		
	
		
			
			|  | 640 | +
 | 
		
	
		
			
			|  | 641 | +  $hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff );
 | 
		
	
		
			
			|  | 642 | +}
 | 
		
	
		
			
			|  | 643 | +
 | 
		
	
		
			
			| 569 | 644 |  1;
 |