linuxboot/bin/create-ffs

100 lines
2.4 KiB
Perl
Executable File

#!/usr/bin/perl
# Create a UEFI "Firmware File" (FFS) with optional features.
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.ffs [options] file.efi [...]
Options:
-o | --output output.ffs Output file (default is stdout)
-n | --name FileName Name to include in UI Section
-t | --type Type FREEFORM|DRIVER|SMM|DXE_CORE|SMM_CORE|PEIM
-v | --version 1.0 Version section
-g | --guid GUID This file GUID (default is hash of Name)
-d | --depex 'guid guid..' Optional dependencies (all ANDed, or TRUE)
-z | --compress Enable LZMA compression
my $output = '-';
my $name;
my $type = 'FREEFORM';
my $version;
my $guid;
my $depex;
my $compress;
GetOptions(
"o|output=s" => \$output,
"n|name=s" => \$name,
"t|type=s" => \$type,
"v|version=s" => \$version,
"g|guid=s" => \$guid,
"d|depex=s" => \$depex,
"z|compress+" => \$compress,
) or die $usage;
die "$type: unknown file type\n"
unless exists $EFI::file_types{$type};
my @sections;
# Read entire files at a time and append a new section
# for each file read. Some special types have their own
# section type; otherwise we're adding a PE32
# The file goes first so that it will be aligned correctly
# on the 4 KB page inside the FV.
local $/ = undef;
while(<>)
{
push @sections, EFI::section($EFI::section_type_map{$type} || 'PE32', $_);
}
# Put the optional parts after the input data
push @sections, EFI::section(USER_INTERFACE => EFI::ucs16($name))
if $name;
push @sections, EFI::section(VERSION => EFI::ucs16(chr(0x00) . $version))
if $version;
push @sections, EFI::depex($type, split /\s+/, $depex)
if $depex;
# If we're compressing, compress the data and wrap it with a GUIDed header
# replacing all of the existing sections.
@sections = ( EFI::compress(@sections) )
if $compress;
# If no GUID was provided, make one from the name
# if there is no name from the data
if ($guid)
{
$guid = EFI::guid($guid);
}
elsif ($name)
{
# Generate a deterministic GUID based on the UI name
$guid = substr(sha1($name), 0, 16);
}
# Create the FFS header for the sections
my $ffs = EFI::ffs($type, $guid, @sections);
if ($output eq '-')
{
print $ffs;
} else {
open OUTPUT, ">", $output
or die "$output: Unable to open: $!\n";
print OUTPUT $ffs;
close OUTPUT;
}