linuxboot/bin/create-fv
2018-01-21 07:40:03 -05:00

125 lines
2.9 KiB
Perl
Executable File

#!/usr/bin/perl
# Create a UEFI "Firmware Volume" (FV)
# typedef struct {
# UINT8 ZeroVector[16]; // 0x00
# EFI_GUID FileSystemGuid; // 0x10
# UINT64 FvLength; // 0x20
# UINT32 Signature; // 0x28
# EFI_FVB_ATTRIBUTES Attributes; // 0x2C (uint32)
# UINT16 HeaderLength; // 0x30
# UINT16 Checksum; // 0x32
# UINT8 Reserved[3]; // 0x34
# UINT8 Revision; // 0x37
# EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[1]; // 0x38 (unused)
#} EFI_FIRMWARE_VOLUME_HEADER;
use warnings;
use strict;
use FindBin;
use lib "$FindBin::Bin/../lib";
use Getopt::Long;
use Digest::SHA 'sha1';
use EFI;
my $usage = <<"";
Usage:
$0 -o output.fv [options] file.ffs [...]
Options:
-o | --output output.ffs Output file (default is stdout)
-s | --size BYTES Size in bytes (default is 4 MB)
-g | --guid GUID This file GUID (default is hash of Name)
-f | --force Force FV creation even if FFS are corrupted
-v | --verbose Increase verbosity
-z | --compress BYTES Enable LZMA compression to final FV size
my $output = '-';
my $size = 4 * 1024 * 1024;
my $force;
my $verbose = 0;
my $compress_size;
GetOptions(
"o|output=s" => \$output,
#"g|guid=s" => \$guid_str,
"s|size=o" => \$size,
"z|compress=o" => \$compress_size,
"f|force+" => \$force,
"v|verboes+" => \$verbose,
) or die $usage;
#my $guid = EFI::guid($guid_str)
# or die "$guid_str: Unable to parse GUID\n";
my $fv = EFI::fv($size);
# Read entire files at a time and append a new file
# for each input read.
local $/ = undef;
while(<>)
{
my $offset = EFI::fv_append(\$fv, $_)
or die "$ARGV: Unable to append\n";
warn sprintf "%s: 0x%x bytes offset %x\n",
$ARGV,
length $_,
$offset
if $verbose > 1;
}
warn sprintf "%s: 0x%08x out of %08x bytes in FV%s\n",
$output,
length($fv),
$size,
$compress_size ? " (uncompressed)" : "",
if $verbose > 0;
EFI::fv_pad(\$fv)
or die sprintf "%s: data size 0x%x > volume size 0x%x\n",
$output,
length $fv,
$size
;
if ($compress_size)
{
my $sec_lz = EFI::compress(EFI::section(FIRMWARE_VOLUME_IMAGE => $fv));
my $ffs_lz = EFI::ffs(FIRMWARE_VOLUME_IMAGE => $sec_lz);
warn sprintf "%s: 0x%08x out of %08x bytes in FV (compressed)\n",
$output,
length($ffs_lz),
$compress_size,
if $verbose > 0;
my $outer_fv = EFI::fv($compress_size);
EFI::fv_append(\$outer_fv, $ffs_lz)
or die sprintf "%s: Unable to append 0x%08x compressed bytes\n",
$output,
length($ffs_lz),
;
EFI::fv_pad(\$outer_fv)
or die sprintf "%s: Unable to append 0x%08x compressed bytes\n",
$output,
length($ffs_lz),
;
$fv = $outer_fv;
}
if ($output eq '-')
{
print $fv;
} else {
open OUTPUT, ">", $output
or die "$output: Unable to open: $!\n";
print OUTPUT $fv;
close OUTPUT;
}
__END__