Merge ssh://github.com/linuxboot/linuxboot into HEAD

This commit is contained in:
Trammell hudson 2018-03-23 14:45:23 -04:00
commit c20d46ccb4
Failed to extract signature
3 changed files with 289 additions and 5 deletions

104
bin/nvram-compact Executable file
View File

@ -0,0 +1,104 @@
#!/usr/bin/perl
# Remove invalid and non-data entries from an NVRAM section
# This only handles the common cases
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/../lib";
use EFI;
use Getopt::Long;
use File::Basename;
use File::Temp 'tempfile';
use Data::Dumper;
my $nvram_guid = "cef5b9a3-476d-497f-9fdc-e98143e0422c";
my $verbose = 0;
local $/;
my $ffs = <>;
my $file_guid = EFI::read_guid($ffs, 0x00);
die "$file_guid != nvram guid $nvram_guid\n"
unless $file_guid eq $nvram_guid;
# should check for FFS header 2, as well as confirm length
my $offset = 0x18;
my $ffs_hdr = substr($ffs, 0x00, $offset);
my $ffs_len = length($ffs);
my $data = '';
while($offset < $ffs_len - 0x08)
{
my $nvar = EFI::NVRAM::NVAR->parse($ffs, $offset)
or last;
$offset += $nvar->length();
# Decide if we keep it:
# No valid bit? do not keep
next unless $nvar->valid();
# if this is not an ASCII name variable
# we probably have already copied its data by
# following the linked list
my $name = $nvar->name()
or next;
my $guid = $nvar->guid();
my $attr = $nvar->{attr};
# Linked? Superceded. We don't want to keep it
# but we need to follow the linked list to
# find the latest version of the data
while(1)
{
my $next = $nvar->next()
or last;
$nvar = EFI::NVRAM::NVAR->parse($ffs, $next);
die sprintf "offset 0x%x: next failed?\n", $next
unless $nvar;
die sprintf "offset 0x%x: nvar is not valid?\n", $next
unless $nvar->valid();
}
# Replace the name and guid with that of our first one
# in the linked list of nvars
$nvar->{name} = $name;
$nvar->{guid} = $guid;
$nvar->{attr} = $attr;
warn "$name\n"
if $verbose;
$data .= $nvar->output();
}
# Create the new FFS and pad it to the end
my $new_ffs = $ffs_hdr . $data;
$new_ffs .= chr(0xFF) x ($ffs_len - length($new_ffs));
# Look to see if there is a GUID store?
while($offset < $ffs_len)
{
if (substr($ffs, $offset, 1) eq chr(0xFF))
{
$offset++;
next;
}
# Non-empty space. copy it to the end
warn sprintf "offset 0x%x: GUID store found\n", $offset;
my $guid_store = substr($ffs, $offset);
substr($new_ffs, $offset) = $guid_store;
last;
}
print $new_ffs;

View File

@ -29,8 +29,8 @@ $(dixe-files): extract.intermediate
FVS := \
$(BUILD)/rom/0x00000000.ifd \
$(BUILD)/rom/0x00010000.bin \
$(BUILD)/rom/0x00800000.fv \
$(BUILD)/rom/0x00820000.fv \
$(BUILD)/nvram1.vol \
$(BUILD)/nvram2.vol \
$(BUILD)/rom/0x00840000.bin \
$(BUILD)/dxe.vol \
$(BUILD)/rom/0x00f00000.fv \
@ -43,6 +43,16 @@ $(BUILD)/dxe.vol: \
$(BUILD)/Linux.ffs \
$(BUILD)/Initrd.ffs \
nvram1-size := 0x20000
nvram2-size := 0x20000
$(BUILD)/nvram1.vol: $(BUILD)/nvram1.ffs
$(BUILD)/nvram2.vol: $(BUILD)/nvram2.ffs
$(BUILD)/nvram1.ffs: $(BUILD)/rom/0x00800000/cef5b9a3-476d-497f-9fdc-e98143e0422c.ffs
./bin/nvram-compact < $< > $@
$(BUILD)/nvram2.ffs: $(BUILD)/rom/0x00820000/cef5b9a3-476d-497f-9fdc-e98143e0422c.ffs
./bin/nvram-compact < $< > $@
# I wish we could use our own builds of these, but
# the AMI firmware modules do not play nice with us.
NO = \

View File

@ -467,8 +467,20 @@ sub fv_append
# if the current offset does not align with the block size,
# we should add a pad section until the next block
my $block_unaligned = $fv_block_size - (length($$fv_ref) % $fv_block_size);
$block_unaligned += $fv_block_size if $block_unaligned < $ffs_hdr_len;
# The firmware files can specify their desired alignment
# we just force 4KB is they want anything
my $attr = ord(substr($ffs, 0x13, 1));
my $alignment = ($attr & 0x38) >> 3;
if ($alignment == 0)
{
$alignment = 0x10;
} else {
warn sprintf "alignment attribute %02x\n", $alignment;
$alignment = 0x1000;
}
my $block_unaligned = $alignment - (length($$fv_ref) % $alignment);
$block_unaligned += $alignment if $block_unaligned < $ffs_hdr_len;
$$fv_ref .= EFI::ffs_pad($block_unaligned - $ffs_hdr_len);
my $ffs_offset = length($$fv_ref);
@ -508,6 +520,13 @@ sub fv_pad
# Helpers for reading values from the ROM images
sub read8
{
my $data = shift;
my $offset = shift;
return unpack("C", substr($data, $offset, 1));
}
sub read16
{
my $data = shift;
@ -515,6 +534,15 @@ sub read16
return unpack("v", substr($data, $offset, 2));
}
sub write16
{
my $len = shift;
return ''
. chr(($len >> 0) & 0xFF)
. chr(($len >> 8) & 0xFF)
;
}
sub read24
{
my $data = shift;
@ -526,7 +554,6 @@ sub read24
;
}
sub write24
{
my $len = shift;
@ -545,6 +572,17 @@ sub read32
return unpack("V", substr($data, $offset, 4));
}
sub write32
{
my $len = shift;
return ''
. chr(($len >> 0) & 0xFF)
. chr(($len >> 8) & 0xFF)
. chr(($len >> 16) & 0xFF)
. chr(($len >> 24) & 0xFF)
;
}
sub read64
{
my $data = shift;
@ -580,5 +618,137 @@ sub read_guid
;
}
#
# Parse the older NVAR (non-volatile variable) structures
#
package EFI::NVRAM::NVAR;
my $nvar_sig = 0x5241564e; # 'NVAR'
my $nvar_entry_ascii_name = 0x02;
my $nvar_entry_data_only = 0x08;
my $nvar_entry_valid = 0x80;
#
# Create a NVAR object from an in-memory representation
# of the structure.
#
sub parse
{
my $class = shift;
my $ffs = shift;
my $offset = shift || 0;
my $ffs_len = length($ffs);
my $sig = EFI::read32($ffs, $offset + 0x00);
# we've reached the end of the data;
return if $sig == 0xFFFFFFFF;
die sprintf "0x%x: sig %08x != nvram %08x\n",
$offset, $sig, $nvar_sig
unless $sig eq $nvar_sig;
my $len = EFI::read16($ffs, $offset + 0x04);
die sprintf "0x%x: len %x > length %x\n",
$offset, $len, $ffs_len
unless $offset + $len <= $ffs_len;
my $nvar = substr($ffs, $offset, $len);
my $next = EFI::read24($nvar, 0x06);
my $attr = EFI::read8($nvar, 0x09);
my $data = substr($nvar, 0x0a);
my $name;
my $guid_id;
# depending on the attribute we might have a
# nul terminated string and a guid index in the guidstore
if ($attr & $nvar_entry_ascii_name)
{
$guid_id = EFI::read8($data, 0);
my $name_end = index($data, chr(0), 1);
die sprintf "offset 0x%x: ascii name, but no nul\n", $offset
if $name_end == -1;
$name = substr($data, 1, $name_end-1);
# remove the guid and name from the data
$data = substr($data, $name_end+1);
}
my $self = bless {
nvar => $nvar,
offset => $offset,
attr => $attr,
name => $name,
guid => $guid_id,
next => $next,
data => $data,
}, $class;
return $self;
}
#
# Serialize an NVRAM NVAR structure
#
sub output
{
my $self = shift;
my $data = $self->{data};
my $attr = $self->{attr};
my $name = $self->{name};
if ($name)
{
# update the attribute that we have name
$attr |= $nvar_entry_ascii_name;
$attr &= ~$nvar_entry_data_only;
$data = chr($self->{guid}) . $self->{name} . chr(0x00) . $data;
}
return ''
. EFI::write32($nvar_sig) # 0x00
. EFI::write16(length($data) + 0x0A) # 0x04
. EFI::write24(0xFFFFFF) # no next # 0x06
. chr($attr) # 0x09
. $data; # 0x0A
}
sub length
{
my $self = shift;
return length $self->{nvar};
}
sub valid
{
my $self = shift;
return $self->{attr} & $nvar_entry_valid;
}
sub next
{
my $self = shift;
# all F is no next, since that can be inverted in the flash
return if $self->{next} eq 0xFFFFFF;
# the next pointer is relative to the offset of this one,
# so shift it by the amount that we've advanced
return $self->{next} + $self->{offset};
}
sub name { my $self = shift; return $self->{name}; }
sub guid { my $self = shift; return $self->{guid}; }
sub data { my $self = shift; return $self->{data}; }
"0, but true";
__END__