|
@@ -396,6 +396,25 @@ sub pnp_header {
|
396
|
396
|
|
397
|
397
|
=pod
|
398
|
398
|
|
|
399
|
+=item C<< undi_header () >>
|
|
400
|
+
|
|
401
|
+Return a C<Option::ROM::UNDI> object representing the ROM's UNDI header,
|
|
402
|
+if present.
|
|
403
|
+
|
|
404
|
+=cut
|
|
405
|
+
|
|
406
|
+sub undi_header {
|
|
407
|
+ my $hash = shift;
|
|
408
|
+ my $self = tied(%$hash);
|
|
409
|
+
|
|
410
|
+ my $offset = $hash->{undi_header};
|
|
411
|
+ return undef unless $offset != 0;
|
|
412
|
+
|
|
413
|
+ return Option::ROM::UNDI->new ( $self->{data}, $offset );
|
|
414
|
+}
|
|
415
|
+
|
|
416
|
+=pod
|
|
417
|
+
|
399
|
418
|
=item C<< ipxe_header () >>
|
400
|
419
|
|
401
|
420
|
Return a C<Option::ROM::iPXE> object representing the ROM's iPXE
|
|
@@ -591,6 +610,67 @@ sub product {
|
591
|
610
|
return unpack ( "Z*", $raw );
|
592
|
611
|
}
|
593
|
612
|
|
|
613
|
+##############################################################################
|
|
614
|
+#
|
|
615
|
+# Option::ROM::UNDI
|
|
616
|
+#
|
|
617
|
+##############################################################################
|
|
618
|
+
|
|
619
|
+package Option::ROM::UNDI;
|
|
620
|
+
|
|
621
|
+use strict;
|
|
622
|
+use warnings;
|
|
623
|
+use Carp;
|
|
624
|
+use bytes;
|
|
625
|
+
|
|
626
|
+sub new {
|
|
627
|
+ my $class = shift;
|
|
628
|
+ my $data = shift;
|
|
629
|
+ my $offset = shift;
|
|
630
|
+
|
|
631
|
+ my $hash = {};
|
|
632
|
+ tie %$hash, "Option::ROM::Fields", {
|
|
633
|
+ data => $data,
|
|
634
|
+ offset => $offset,
|
|
635
|
+ length => 0x16,
|
|
636
|
+ 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" },
|
|
649
|
+ },
|
|
650
|
+ };
|
|
651
|
+ bless $hash, $class;
|
|
652
|
+
|
|
653
|
+ # Retrieve true length of structure
|
|
654
|
+ my $self = tied ( %$hash );
|
|
655
|
+ $self->{length} = $hash->{struct_length};
|
|
656
|
+
|
|
657
|
+ return $hash;
|
|
658
|
+}
|
|
659
|
+
|
|
660
|
+sub checksum {
|
|
661
|
+ my $hash = shift;
|
|
662
|
+ my $self = tied(%$hash);
|
|
663
|
+
|
|
664
|
+ return $self->checksum();
|
|
665
|
+}
|
|
666
|
+
|
|
667
|
+sub fix_checksum {
|
|
668
|
+ my $hash = shift;
|
|
669
|
+ my $self = tied(%$hash);
|
|
670
|
+
|
|
671
|
+ $hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff );
|
|
672
|
+}
|
|
673
|
+
|
594
|
674
|
##############################################################################
|
595
|
675
|
#
|
596
|
676
|
# Option::ROM::iPXE
|