mirror of
https://github.com/linuxboot/linuxboot
synced 2024-11-22 08:09:41 +00:00
125 lines
2.9 KiB
Perl
Executable File
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__
|