mirror of
https://github.com/linuxboot/linuxboot
synced 2024-11-21 23:59:59 +00:00
extract names from sections
This commit is contained in:
parent
d07129b7f7
commit
e8c0acaff7
@ -12,9 +12,11 @@ use lib "$FindBin::Bin/../lib";
|
||||
use EFI;
|
||||
use Getopt::Long;
|
||||
use File::Basename;
|
||||
use Data::Dumper;
|
||||
|
||||
|
||||
my $start_offset = 0; # 0x02c00000;
|
||||
my $verbose = 0;
|
||||
|
||||
local $/;
|
||||
while(<>)
|
||||
@ -95,6 +97,12 @@ sub process_fv
|
||||
$guid,
|
||||
;
|
||||
|
||||
if ($guid ne '8c8ce578-8a3d-4f1c-9935-896185c32dd3')
|
||||
{
|
||||
# we can only process normal firmware volumes
|
||||
return;
|
||||
}
|
||||
|
||||
while($offset < $fv_length - 0x20)
|
||||
{
|
||||
my $len = EFI::read24($fv, $offset + 0x14);
|
||||
@ -109,7 +117,7 @@ sub process_fv
|
||||
# the start of free space
|
||||
return 1 if ~$len == 0;
|
||||
|
||||
# Looks good, adjust the starting offset
|
||||
## Looks good, adjust the starting offset
|
||||
$data_offset += 0x8;
|
||||
}
|
||||
|
||||
@ -133,7 +141,7 @@ sub process_fv
|
||||
|
||||
my $data = substr($fv, $offset, $len);
|
||||
|
||||
process_ffs($base, $data);
|
||||
process_ffs($base, $data, $data_offset);
|
||||
|
||||
$offset += $len;
|
||||
|
||||
@ -149,6 +157,7 @@ sub process_ffs
|
||||
{
|
||||
my $base = shift;
|
||||
my $ffs = shift;
|
||||
my $data_offset = shift; # might be 0x18 or 0x20
|
||||
my $len = length($ffs);
|
||||
|
||||
my $guid = EFI::read_guid($ffs, 0x00);
|
||||
@ -160,15 +169,85 @@ sub process_ffs
|
||||
return;
|
||||
}
|
||||
|
||||
warn sprintf "%s/%s: len %x\n",
|
||||
$base,
|
||||
$guid,
|
||||
$len,
|
||||
;
|
||||
|
||||
output("$base/$guid.ffs", $ffs);
|
||||
|
||||
# TODO: recursively expand embedded, compressed fv
|
||||
my @sections = ffs_sections("$base/$guid", $ffs, $data_offset);
|
||||
|
||||
# if this file has a UI section, extract its name
|
||||
my $name = '';
|
||||
for my $sec (@sections)
|
||||
{
|
||||
next unless $sec->[0] eq 'USER_INTERFACE';
|
||||
#$name = Dumper($sec->[1]); # EFI::read_ucs16($sec->[1], 2);
|
||||
$name = EFI::read_ucs16($sec->[1], 0);
|
||||
}
|
||||
|
||||
warn sprintf "%s/%s: %s\n", $base, $guid, $name;
|
||||
|
||||
|
||||
# if ($guid eq '8c8ce578-8a3d-4f1c-9935-896185c32dd3')
|
||||
# {
|
||||
# # recursively expand embedded, compressed fv
|
||||
# process_ffs_fv($base, $ffs, $data_offset);
|
||||
# } else {
|
||||
# # todo: Look for a UI section to produce a nice table
|
||||
# }
|
||||
}
|
||||
|
||||
|
||||
sub ffs_sections
|
||||
{
|
||||
my $base = shift;
|
||||
my $ffs = shift;
|
||||
my $offset = shift;
|
||||
my $ffs_len = length($ffs);
|
||||
|
||||
my @sections;
|
||||
|
||||
# find each section inside
|
||||
while($offset < $ffs_len - 8)
|
||||
{
|
||||
my $len = EFI::read24($ffs, $offset);
|
||||
my $data_offset = 0x4;
|
||||
if ($len == 0xFFFFFF)
|
||||
{
|
||||
# FFSv3 section
|
||||
$len = EFI::read32($ffs, $offset + $data_offset);
|
||||
$data_offset += 4;
|
||||
}
|
||||
|
||||
if ($len < $data_offset)
|
||||
{
|
||||
die sprintf "%s: 0x%x Section length %x invalid\n", $base, $offset, $len;
|
||||
}
|
||||
|
||||
if ($offset + $len > $ffs_len)
|
||||
{
|
||||
die sprintf "%s: Section length %x exceeds FFS len %x\n",
|
||||
$base,
|
||||
$len,
|
||||
$ffs_len,
|
||||
;
|
||||
}
|
||||
|
||||
my $sec = substr($ffs, $offset, $len);
|
||||
|
||||
# move to the next section, keeping a 4-byte alignment
|
||||
$offset = ($offset + $len + 3) & ~3;
|
||||
|
||||
my $sec_type = ord(substr($sec, 3, 1));
|
||||
my $sec_data = substr($sec, $data_offset, $len - $data_offset);
|
||||
|
||||
my $sec_type_name = $EFI::section_types_lookup{$sec_type};
|
||||
$sec_type_name ||= sprintf "0x%02x", $sec_type;
|
||||
|
||||
warn sprintf "%s: %s len %x\n", $base, $sec_type_name, $len
|
||||
if $verbose;
|
||||
|
||||
push @sections, [ $sec_type_name, $sec_data ];
|
||||
}
|
||||
|
||||
return @sections;
|
||||
}
|
||||
|
||||
|
||||
@ -185,58 +264,3 @@ sub output
|
||||
print FILE $data;
|
||||
close FILE;
|
||||
}
|
||||
|
||||
|
||||
__END__
|
||||
sub read16
|
||||
{
|
||||
my $data = shift;
|
||||
my $offset = shift;
|
||||
return unpack("v", substr($data, $offset, 2));
|
||||
}
|
||||
|
||||
sub read24
|
||||
{
|
||||
my $data = shift;
|
||||
my $offset = shift;
|
||||
return 0
|
||||
| ord(substr($data, $offset+2, 1)) << 16
|
||||
| ord(substr($data, $offset+1, 1)) << 8
|
||||
| ord(substr($data, $offset+0, 1)) << 0
|
||||
;
|
||||
}
|
||||
|
||||
sub read32
|
||||
{
|
||||
my $data = shift;
|
||||
my $offset = shift;
|
||||
return unpack("V", substr($data, $offset, 4));
|
||||
}
|
||||
|
||||
sub read64
|
||||
{
|
||||
my $data = shift;
|
||||
my $offset = shift;
|
||||
return read32($data, $offset+4) << 32 | read32($data, $offset+0);
|
||||
}
|
||||
|
||||
sub read_guid
|
||||
{
|
||||
my $data = shift;
|
||||
my $offset = shift;
|
||||
|
||||
my ($g1,$g2,$g3,$g4,@g5) = unpack("VvvnCCCCCC", substr($data, $offset, 16));
|
||||
|
||||
return sprintf "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
|
||||
$g1,
|
||||
$g2,
|
||||
$g3,
|
||||
$g4,
|
||||
$g5[0],
|
||||
$g5[1],
|
||||
$g5[2],
|
||||
$g5[3],
|
||||
$g5[4],
|
||||
$g5[5],
|
||||
;
|
||||
}
|
||||
|
25
lib/EFI.pm
25
lib/EFI.pm
@ -66,6 +66,7 @@ our %file_types = qw/
|
||||
FFS_PAD 0xf0
|
||||
/;
|
||||
|
||||
|
||||
our %section_types = qw/
|
||||
GUID_DEFINED 0x02
|
||||
PE32 0x10
|
||||
@ -82,6 +83,7 @@ our %section_types = qw/
|
||||
SMM_DEPEX 0x1C
|
||||
/;
|
||||
|
||||
|
||||
# Some special cases for non-PE32 sections
|
||||
our %section_type_map = qw/
|
||||
FREEFORM RAW
|
||||
@ -95,6 +97,9 @@ our %depex_type_map = qw/
|
||||
SMM SMM_DEPEX
|
||||
/;
|
||||
|
||||
# Invert the file type and section type maps
|
||||
our %file_types_lookup = map { hex $file_types{$_} => $_ } keys %file_types;
|
||||
our %section_types_lookup = map { hex $section_types{$_} => $_ } keys %section_types;
|
||||
|
||||
# convert text GUID to hex
|
||||
sub guid
|
||||
@ -142,6 +147,26 @@ sub ucs16
|
||||
return $rc;
|
||||
}
|
||||
|
||||
# Convert from UCS-16 back to a normal string
|
||||
sub read_ucs16
|
||||
{
|
||||
my $val = shift;
|
||||
my $offset = shift;
|
||||
my $len = length($val);
|
||||
my $rc = '';
|
||||
|
||||
while($offset < $len-1)
|
||||
{
|
||||
my $word = unpack("n", substr($val, $offset, 2));
|
||||
last if $word == 0x0000;
|
||||
|
||||
$rc .= chr(($word >> 8) & 0xFF);
|
||||
$offset += 2;
|
||||
}
|
||||
|
||||
return $rc;
|
||||
}
|
||||
|
||||
|
||||
# output an EFI Common Section Header
|
||||
# Since we might be dealing with ones larger than 16 MB, we should use extended
|
||||
|
Loading…
Reference in New Issue
Block a user