Annotation of qemu/roms/ipxe/src/util/efirom.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (C) 2009 Michael Brown <[email protected]>.
                      3:  *
                      4:  * This program is free software; you can redistribute it and/or
                      5:  * modify it under the terms of the GNU General Public License as
                      6:  * published by the Free Software Foundation; either version 2 of the
                      7:  * License, or any later version.
                      8:  *
                      9:  * This program is distributed in the hope that it will be useful, but
                     10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     12:  * General Public License for more details.
                     13:  *
                     14:  * You should have received a copy of the GNU General Public License
                     15:  * along with this program; if not, write to the Free Software
                     16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17:  */
                     18: 
                     19: #include <stdint.h>
                     20: #include <stddef.h>
                     21: #include <stdlib.h>
                     22: #include <stdio.h>
                     23: #include <string.h>
                     24: #include <sys/stat.h>
                     25: #include <unistd.h>
                     26: #include <errno.h>
                     27: #include <assert.h>
                     28: #include <getopt.h>
                     29: #include <ipxe/efi/efi.h>
                     30: #include <ipxe/efi/IndustryStandard/PeImage.h>
                     31: #include <ipxe/efi/IndustryStandard/Pci22.h>
                     32: 
                     33: #define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
                     34: 
                     35: /** Command-line options */
                     36: struct options {
                     37:        uint16_t vendor;
                     38:        uint16_t device;
                     39: };
                     40: 
                     41: /**
                     42:  * Allocate memory
                     43:  *
                     44:  * @v len              Length of memory to allocate
                     45:  * @ret ptr            Pointer to allocated memory
                     46:  */
                     47: static void * xmalloc ( size_t len ) {
                     48:        void *ptr;
                     49: 
                     50:        ptr = malloc ( len );
                     51:        if ( ! ptr ) {
                     52:                eprintf ( "Could not allocate %zd bytes\n", len );
                     53:                exit ( 1 );
                     54:        }
                     55: 
                     56:        return ptr;
                     57: }
                     58: 
                     59: /**
                     60:  * Get file size
                     61:  *
                     62:  * @v file             File
                     63:  * @v len              File size
                     64:  */
                     65: static size_t file_size ( FILE *file ) {
                     66:        ssize_t len;
                     67: 
                     68:        return len;
                     69: }
                     70: 
                     71: /**
                     72:  * Read information from PE headers
                     73:  *
                     74:  * @v pe               PE file
                     75:  * @ret machine                Machine type
                     76:  * @ret subsystem      EFI subsystem
                     77:  */
                     78: static void read_pe_info ( void *pe, uint16_t *machine,
                     79:                           uint16_t *subsystem ) {
                     80:        EFI_IMAGE_DOS_HEADER *dos;
                     81:        union {
                     82:                EFI_IMAGE_NT_HEADERS32 nt32;
                     83:                EFI_IMAGE_NT_HEADERS64 nt64;
                     84:        } *nt;
                     85: 
                     86:        /* Locate NT header */
                     87:        dos = pe;
                     88:        nt = ( pe + dos->e_lfanew );
                     89: 
                     90:        /* Parse out PE information */
                     91:        *machine = nt->nt32.FileHeader.Machine;
                     92:        switch ( *machine ) {
                     93:        case EFI_IMAGE_MACHINE_IA32:
                     94:                *subsystem = nt->nt32.OptionalHeader.Subsystem;
                     95:                break;
                     96:        case EFI_IMAGE_MACHINE_X64:
                     97:                *subsystem = nt->nt64.OptionalHeader.Subsystem;
                     98:                break;
                     99:        default:
                    100:                eprintf ( "Unrecognised machine type %04x\n", *machine );
                    101:                exit ( 1 );
                    102:        }
                    103: }
                    104: 
                    105: /**
                    106:  * Convert EFI image to ROM image
                    107:  *
                    108:  * @v pe               EFI file
                    109:  * @v rom              ROM file
                    110:  */
                    111: static void make_efi_rom ( FILE *pe, FILE *rom, struct options *opts ) {
                    112:        struct {
                    113:                EFI_PCI_EXPANSION_ROM_HEADER rom;
                    114:                PCI_DATA_STRUCTURE pci __attribute__ (( aligned ( 4 ) ));
                    115:                uint8_t checksum;
                    116:        } *headers;
                    117:        struct stat pe_stat;
                    118:        size_t pe_size;
                    119:        size_t rom_size;
                    120:        void *buf;
                    121:        void *payload;
                    122:        unsigned int i;
                    123:        uint8_t checksum;
                    124: 
                    125:        /* Determine PE file size */
                    126:        if ( fstat ( fileno ( pe ), &pe_stat ) != 0 ) {
                    127:                eprintf ( "Could not stat PE file: %s\n",
                    128:                          strerror ( errno ) );
                    129:                exit ( 1 );
                    130:        }
                    131:        pe_size = pe_stat.st_size;
                    132: 
                    133:        /* Determine ROM file size */
                    134:        rom_size = ( ( pe_size + sizeof ( *headers ) + 511 ) & ~511 );
                    135: 
                    136:        /* Allocate ROM buffer and read in PE file */
                    137:        buf = xmalloc ( rom_size );
                    138:        memset ( buf, 0, rom_size );
                    139:        headers = buf;
                    140:        payload = ( buf + sizeof ( *headers ) );
                    141:        if ( fread ( payload, pe_size, 1, pe ) != 1 ) {
                    142:                eprintf ( "Could not read PE file: %s\n",
                    143:                          strerror ( errno ) );
                    144:                exit ( 1 );
                    145:        }
                    146: 
                    147:        /* Construct ROM header */
                    148:        headers->rom.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE;
                    149:        headers->rom.InitializationSize = ( rom_size / 512 );
                    150:        headers->rom.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;
                    151:        read_pe_info ( payload, &headers->rom.EfiMachineType,
                    152:                       &headers->rom.EfiSubsystem );
                    153:        headers->rom.EfiImageHeaderOffset = sizeof ( *headers );
                    154:        headers->rom.PcirOffset =
                    155:                offsetof ( typeof ( *headers ), pci );
                    156:        headers->pci.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
                    157:        headers->pci.VendorId = opts->vendor;
                    158:        headers->pci.DeviceId = opts->device;
                    159:        headers->pci.Length = sizeof ( headers->pci );
                    160:        headers->pci.ClassCode[0] = PCI_CLASS_NETWORK;
                    161:        headers->pci.ImageLength = ( rom_size / 512 );
                    162:        headers->pci.CodeType = 0x03; /* No constant in EFI headers? */
                    163:        headers->pci.Indicator = 0x80; /* No constant in EFI headers? */
                    164: 
                    165:        /* Fix image checksum */
                    166:        for ( i = 0, checksum = 0 ; i < rom_size ; i++ )
                    167:                checksum += *( ( uint8_t * ) buf + i );
                    168:        headers->checksum -= checksum;
                    169: 
                    170:        /* Write out ROM */
                    171:        if ( fwrite ( buf, rom_size, 1, rom ) != 1 ) {
                    172:                eprintf ( "Could not write ROM file: %s\n",
                    173:                          strerror ( errno ) );
                    174:                exit ( 1 );
                    175:        }
                    176: }
                    177: 
                    178: /**
                    179:  * Print help
                    180:  *
                    181:  * @v program_name     Program name
                    182:  */
                    183: static void print_help ( const char *program_name ) {
                    184:        eprintf ( "Syntax: %s [--vendor=VVVV] [--device=DDDD] "
                    185:                  "infile outfile\n", program_name );
                    186: }
                    187: 
                    188: /**
                    189:  * Parse command-line options
                    190:  *
                    191:  * @v argc             Argument count
                    192:  * @v argv             Argument list
                    193:  * @v opts             Options structure to populate
                    194:  */
                    195: static int parse_options ( const int argc, char **argv,
                    196:                           struct options *opts ) {
                    197:        char *end;
                    198:        int c;
                    199: 
                    200:        while (1) {
                    201:                int option_index = 0;
                    202:                static struct option long_options[] = {
                    203:                        { "vendor", required_argument, NULL, 'v' },
                    204:                        { "device", required_argument, NULL, 'd' },
                    205:                        { "help", 0, NULL, 'h' },
                    206:                        { 0, 0, 0, 0 }
                    207:                };
                    208: 
                    209:                if ( ( c = getopt_long ( argc, argv, "v:d:h",
                    210:                                         long_options,
                    211:                                         &option_index ) ) == -1 ) {
                    212:                        break;
                    213:                }
                    214: 
                    215:                switch ( c ) {
                    216:                case 'v':
                    217:                        opts->vendor = strtoul ( optarg, &end, 16 );
                    218:                        if ( *end ) {
                    219:                                eprintf ( "Invalid vendor \"%s\"\n", optarg );
                    220:                                exit ( 2 );
                    221:                        }
                    222:                        break;
                    223:                case 'd':
                    224:                        opts->device = strtoul ( optarg, &end, 16 );
                    225:                        if ( *end ) {
                    226:                                eprintf ( "Invalid device \"%s\"\n", optarg );
                    227:                                exit ( 2 );
                    228:                        }
                    229:                        break;
                    230:                case 'h':
                    231:                        print_help ( argv[0] );
                    232:                        exit ( 0 );
                    233:                case '?':
                    234:                default:
                    235:                        exit ( 2 );
                    236:                }
                    237:        }
                    238:        return optind;
                    239: }
                    240: 
                    241: int main ( int argc, char **argv ) {
                    242:        struct options opts = {
                    243:        };
                    244:        unsigned int infile_index;
                    245:        const char *infile_name;
                    246:        const char *outfile_name;
                    247:        FILE *infile;
                    248:        FILE *outfile;
                    249: 
                    250:        /* Parse command-line arguments */
                    251:        infile_index = parse_options ( argc, argv, &opts );
                    252:        if ( argc != ( infile_index + 2 ) ) {
                    253:                print_help ( argv[0] );
                    254:                exit ( 2 );
                    255:        }
                    256:        infile_name = argv[infile_index];
                    257:        outfile_name = argv[infile_index + 1];
                    258: 
                    259:        /* Open input and output files */
                    260:        infile = fopen ( infile_name, "r" );
                    261:        if ( ! infile ) {
                    262:                eprintf ( "Could not open %s for reading: %s\n",
                    263:                          infile_name, strerror ( errno ) );
                    264:                exit ( 1 );
                    265:        }
                    266:        outfile = fopen ( outfile_name, "w" );
                    267:        if ( ! outfile ) {
                    268:                eprintf ( "Could not open %s for writing: %s\n",
                    269:                          outfile_name, strerror ( errno ) );
                    270:                exit ( 1 );
                    271:        }
                    272: 
                    273:        /* Convert file */
                    274:        make_efi_rom ( infile, outfile, &opts );
                    275: 
                    276:        fclose ( outfile );
                    277:        fclose ( infile );
                    278: 
                    279:        return 0;
                    280: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.