Detect capsule headers and parse them

pull/177/head
Hamish Coleman 4 years ago
parent b0ac2c3e76
commit 54580e05fc

@ -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)) {

Loading…
Cancel
Save