summaryrefslogtreecommitdiffstats
path: root/src/util/Option
diff options
context:
space:
mode:
authorMichael Brown2012-06-10 19:23:24 +0200
committerMichael Brown2012-06-12 12:36:20 +0200
commitf2e5f8813e9a867cae76305d4186dcf26e5fa22a (patch)
treea4c6e892e8ffbbaeeb9538d721d005735ae1404c /src/util/Option
parent[cmdline] Use "cpuid --ext" instead of "cpuid --amd" (diff)
downloadipxe-f2e5f8813e9a867cae76305d4186dcf26e5fa22a.tar.gz
ipxe-f2e5f8813e9a867cae76305d4186dcf26e5fa22a.tar.xz
ipxe-f2e5f8813e9a867cae76305d4186dcf26e5fa22a.zip
[util] Allow Option::ROM to access multiple ROM images
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/util/Option')
-rw-r--r--src/util/Option/ROM.pm74
1 files changed, 70 insertions, 4 deletions
diff --git a/src/util/Option/ROM.pm b/src/util/Option/ROM.pm
index 9fea4d34..b2b94c3e 100644
--- a/src/util/Option/ROM.pm
+++ b/src/util/Option/ROM.pm
@@ -169,9 +169,11 @@ use Exporter 'import';
use constant ROM_SIGNATURE => 0xaa55;
use constant PCI_SIGNATURE => 'PCIR';
+use constant PCI_LAST_IMAGE => 0x80;
use constant PNP_SIGNATURE => '$PnP';
-our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PNP_SIGNATURE );
+our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE
+ PNP_SIGNATURE );
our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
use constant JMP_SHORT => 0xeb;
@@ -241,6 +243,53 @@ sub new {
=pod
+=item C<< set ( $data ) >>
+
+Set option ROM contents.
+
+=cut
+
+sub set {
+ my $hash = shift;
+ my $self = tied(%$hash);
+ my $data = shift;
+
+ # Store data
+ $self->{data} = \$data;
+
+ # Split out any data belonging to the next image
+ delete $self->{next_image};
+ my $length = ( $hash->{length} * 512 );
+ my $pci_header = $hash->pci_header();
+ if ( ( $length < length $data ) &&
+ ( defined $pci_header ) &&
+ ( ! ( $pci_header->{last_image} & PCI_LAST_IMAGE ) ) ) {
+ my $remainder = substr ( $data, $length );
+ $data = substr ( $data, 0, $length );
+ $self->{next_image} = new Option::ROM;
+ $self->{next_image}->set ( $remainder );
+ }
+}
+
+=pod
+
+=item C<< get () >>
+
+Get option ROM contents.
+
+=cut
+
+sub get {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ my $data = ${$self->{data}};
+ $data .= $self->{next_image}->get() if $self->{next_image};
+ return $data;
+}
+
+=pod
+
=item C<< load ( $filename ) >>
Load option ROM contents from the file C<$filename>.
@@ -256,8 +305,8 @@ sub load {
open my $fh, "<$filename"
or croak "Cannot open $filename for reading: $!";
- read $fh, my $data, ( 128 * 1024 ); # 128kB is theoretical max size
- $self->{data} = \$data;
+ read $fh, my $data, -s $fh;
+ $hash->set ( $data );
close $fh;
}
@@ -279,7 +328,8 @@ sub save {
open my $fh, ">$filename"
or croak "Cannot open $filename for writing: $!";
- print $fh ${$self->{data}};
+ my $data = $hash->get();
+ print $fh $data;
close $fh;
}
@@ -339,6 +389,22 @@ sub pnp_header {
=pod
+=item C<< next_image () >>
+
+Return a C<Option::ROM> object representing the next image within the
+ROM, if present.
+
+=cut
+
+sub next_image {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ return $self->{next_image};
+}
+
+=pod
+
=item C<< checksum () >>
Calculate the byte checksum of the ROM.