3 # Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License as
7 # published by the Free Software Foundation; either version 2 of the
8 # License, or any later version.
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 use lib "$FindBin::Bin";
25 use Option::ROM qw ( :all );
27 sub merge_entry_points {
28 my $baserom_entry = \shift;
29 my $rom_entry = \shift;
33 my $old_entry = $$baserom_entry;
34 $$baserom_entry = ( $offset + $$rom_entry );
35 $$rom_entry = $old_entry;
40 my @roms = map { my $rom = new Option::ROM; $rom->load($_); $rom } @romfiles;
42 my $baserom = shift @roms;
43 my $offset = $baserom->length;
45 foreach my $rom ( @roms ) {
47 # Merge initialisation entry point
48 merge_entry_points ( $baserom->{init}, $rom->{init}, $offset );
51 merge_entry_points ( $baserom->{bofm_header}, $rom->{bofm_header}, $offset );
53 # Update PCI header, if present in both
54 my $baserom_pci = $baserom->pci_header;
55 my $rom_pci = $rom->pci_header;
56 if ( $baserom_pci && $rom_pci ) {
59 $baserom_pci->{image_length} += $rom_pci->{image_length};
60 if ( exists $baserom_pci->{runtime_length} ) {
61 if ( exists $rom_pci->{runtime_length} ) {
62 $baserom_pci->{runtime_length} += $rom_pci->{runtime_length};
64 $baserom_pci->{runtime_length} += $rom_pci->{image_length};
68 # Merge CLP entry point
69 if ( exists ( $baserom_pci->{clp_entry} ) &&
70 exists ( $rom_pci->{clp_entry} ) ) {
71 merge_entry_points ( $baserom_pci->{clp_entry}, $rom_pci->{clp_entry},
76 # Update PnP header, if present in both
77 my $baserom_pnp = $baserom->pnp_header;
78 my $rom_pnp = $rom->pnp_header;
79 if ( $baserom_pnp && $rom_pnp ) {
80 merge_entry_points ( $baserom_pnp->{bcv}, $rom_pnp->{bcv}, $offset );
81 merge_entry_points ( $baserom_pnp->{bdv}, $rom_pnp->{bdv}, $offset );
82 merge_entry_points ( $baserom_pnp->{bev}, $rom_pnp->{bev}, $offset );
85 # Update iPXE header, if present
86 my $baserom_ipxe = $baserom->ipxe_header;
87 my $rom_ipxe = $rom->ipxe_header;
88 if ( $baserom_ipxe ) {
90 # Update shrunk length
91 $baserom_ipxe->{shrunk_length} = ( $baserom->{length} +
93 $rom_ipxe->{shrunk_length} :
97 $baserom_ipxe->fix_checksum();
101 $baserom->{length} += $rom->{length};
103 # Fix checksum for this ROM segment
104 $rom->fix_checksum();
106 # Add this ROM to base ROM
107 my $data = substr ( $baserom->get(), 0, $baserom->length() );
108 $data .= $rom->get();
109 $data .= $baserom->next_image()->get() if $baserom->next_image();
110 $baserom->set ( $data );
112 $offset += $rom->length;
115 $baserom->pnp_header->fix_checksum() if $baserom->pnp_header;
116 $baserom->fix_checksum();
117 $baserom->save ( "-" );