|
|
|
@ -585,24 +585,6 @@ use strict;
|
|
|
|
|
|
|
|
|
|
use base qw(FL2::base);
|
|
|
|
|
|
|
|
|
|
sub _find_capsule_header {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
my $buf = $self->get_block(0,16);
|
|
|
|
|
return undef if (!defined($buf));
|
|
|
|
|
$buf = $$buf;
|
|
|
|
|
|
|
|
|
|
my $capsule_uuid = "\xbd\x86\x66\x3b\x76\x0d\x30\x40\xb7\x0e\xb5\x51\x9e\x2f\xc5\xa0";
|
|
|
|
|
|
|
|
|
|
if ($buf eq $capsule_uuid) {
|
|
|
|
|
# TODO
|
|
|
|
|
# - while I am reading the capsule signature, I dont understand
|
|
|
|
|
# why the magic offset doesnt match anything in the capsule header
|
|
|
|
|
log::add("capsule_uuid signature found (offset hack applied)");
|
|
|
|
|
return 0x1d0;
|
|
|
|
|
}
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub _find_pfh {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
my $offset = 0;
|
|
|
|
@ -634,7 +616,7 @@ sub _check {
|
|
|
|
|
12587008 => 1,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
my $capsule_offset_hack = $self->_find_capsule_header() ||0;
|
|
|
|
|
my $capsule_offset_hack = $self->{capsule_offset_hack} || 0;
|
|
|
|
|
|
|
|
|
|
my $header_offset = $self->_find_pfh();
|
|
|
|
|
return undef if (!defined($header_offset));
|
|
|
|
@ -723,6 +705,146 @@ sub extract {
|
|
|
|
|
# no insert() will work until we know how to generate the checksums
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1;
|
|
|
|
|
|
|
|
|
|
package EFI::Capsule::PFH_header;
|
|
|
|
|
use warnings;
|
|
|
|
|
use strict;
|
|
|
|
|
#
|
|
|
|
|
# Look for FL1 files that have a known EFI capsule prefix
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
use base qw(FL1::PFH_header);
|
|
|
|
|
|
|
|
|
|
sub _check {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
|
|
$self->{capsule_offset_hack} = 0x1d0;
|
|
|
|
|
# This is probably:
|
|
|
|
|
# header1_size + header2_size + ?
|
|
|
|
|
# 0x50 + 0x168 + 0x18
|
|
|
|
|
#$self->{capsule_offset_hack}
|
|
|
|
|
# = $self->{header1}{HeaderSize} + $self->{header2}{HeaderLength};
|
|
|
|
|
|
|
|
|
|
return $self->SUPER::_check();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
1;
|
|
|
|
|
|
|
|
|
|
package EFI::Capsule;
|
|
|
|
|
use warnings;
|
|
|
|
|
use strict;
|
|
|
|
|
#
|
|
|
|
|
# Look for FL1 files that have a known EFI capsule prefix
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
use base qw(FL2::base);
|
|
|
|
|
|
|
|
|
|
sub _check {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
|
|
# bd86663b760d3040b70eb5519e2fc5a0
|
|
|
|
|
my $capsule_uuid = "\xbd\x86\x66\x3b\x76\x0d\x30\x40\xb7\x0e\xb5\x51\x9e\x2f\xc5\xa0";
|
|
|
|
|
|
|
|
|
|
my $buf = $self->get_block(0,16);
|
|
|
|
|
if (!defined($buf)) {
|
|
|
|
|
log::add("bad get_block");
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
$buf = $$buf;
|
|
|
|
|
|
|
|
|
|
if ($buf ne $capsule_uuid) {
|
|
|
|
|
log::add("no capsule_uuid");
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$buf = $self->get_block(0x10, 4);
|
|
|
|
|
if (!defined($buf)) {
|
|
|
|
|
log::add("bad get_block");
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
my $header1_size = unpack("V", $$buf);
|
|
|
|
|
|
|
|
|
|
$buf = $self->get_block(0, $header1_size);
|
|
|
|
|
|
|
|
|
|
if (!defined($buf)) {
|
|
|
|
|
log::add("bad get_block");
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
my @fields = qw(
|
|
|
|
|
UUID
|
|
|
|
|
HeaderSize Flags CapsuleImageSize SequenceNumber InstanceId
|
|
|
|
|
);
|
|
|
|
|
my @values = unpack("a16VVVVa16",$$buf);
|
|
|
|
|
map { $self->{header1}{$fields[$_]} = $values[$_] } (0..scalar(@fields)-1);
|
|
|
|
|
|
|
|
|
|
if ($self->{header1}{CapsuleImageSize} != $self->{filesize}) {
|
|
|
|
|
log::add("failed header1 filesize");
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# d954937a68044a4481ce0bf617d890df
|
|
|
|
|
my $firmware_uuid = "\xd9\x54\x93\x7a\x68\x04\x4a\x44\x81\xce\x0b\xf6\x17\xd8\x90\xdf";
|
|
|
|
|
|
|
|
|
|
$buf = $self->get_block($header1_size, 0x38);
|
|
|
|
|
|
|
|
|
|
if (!defined($buf)) {
|
|
|
|
|
log::add("bad get_block");
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@fields = qw(
|
|
|
|
|
ZeroVector FileSystemGuid FvLength Signature
|
|
|
|
|
Attributes HeaderLength Checksum
|
|
|
|
|
Reserved
|
|
|
|
|
Revision
|
|
|
|
|
);
|
|
|
|
|
@values = unpack("a16a16Q<a4Vvva3c",$$buf);
|
|
|
|
|
map { $self->{header2}{$fields[$_]} = $values[$_] } (0..scalar(@fields)-1);
|
|
|
|
|
|
|
|
|
|
#if ($self->{header2}{ZeroVector} ne '\x00'x16) {
|
|
|
|
|
# log::add("failed header2 zerovector");
|
|
|
|
|
# return undef;
|
|
|
|
|
#}
|
|
|
|
|
if ($self->{header2}{FileSystemGuid} ne $firmware_uuid) {
|
|
|
|
|
log::add("failed header2 FileSystemGuid");
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
if ($self->{header2}{FvLength} != ($self->{filesize}-$header1_size)) {
|
|
|
|
|
log::add("failed header1 filesize");
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
if ($self->{header2}{Signature} ne '_FVH') {
|
|
|
|
|
log::add("failed header2 Signature");
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# TODO:
|
|
|
|
|
# - check Checksum
|
|
|
|
|
# "A 16-bit checksum of the firmware volume header. A valid header sums to zero"
|
|
|
|
|
|
|
|
|
|
if ($self->{header2}{Revision} == 1) {
|
|
|
|
|
# So far, the only revision 1 headers seen have also had a PFH header
|
|
|
|
|
# (with an annoying offset)
|
|
|
|
|
bless $self, 'EFI::Capsule::PFH_header';
|
|
|
|
|
return $self->_check();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print(Data::Dumper::Dumper($self));
|
|
|
|
|
|
|
|
|
|
log::add("not using unfinished checker ");
|
|
|
|
|
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub extract {
|
|
|
|
|
return shift->_extract(shift);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# no insert() will work until we know how to generate the checksums
|
|
|
|
|
|
|
|
|
|
1;
|
|
|
|
|
|
|
|
|
|
# TODO
|
|
|
|
@ -761,6 +883,9 @@ sub detect_img {
|
|
|
|
|
if (!defined($object)) {
|
|
|
|
|
$object = FL2::prefix_head_EC->new($fh);
|
|
|
|
|
}
|
|
|
|
|
if (!defined($object)) {
|
|
|
|
|
$object = EFI::Capsule->new($fh);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# These checks always do a file search
|
|
|
|
|
if (!defined($object)) {
|
|
|
|
|