summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/image
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/ipxe/src/image')
-rw-r--r--qemu/roms/ipxe/src/image/efi_image.c316
-rw-r--r--qemu/roms/ipxe/src/image/elf.c226
-rw-r--r--qemu/roms/ipxe/src/image/embedded.c91
-rw-r--r--qemu/roms/ipxe/src/image/png.c1011
-rw-r--r--qemu/roms/ipxe/src/image/pnm.c419
-rw-r--r--qemu/roms/ipxe/src/image/script.c427
-rw-r--r--qemu/roms/ipxe/src/image/segment.c95
7 files changed, 0 insertions, 2585 deletions
diff --git a/qemu/roms/ipxe/src/image/efi_image.c b/qemu/roms/ipxe/src/image/efi_image.c
deleted file mode 100644
index b7d8f9c6e..000000000
--- a/qemu/roms/ipxe/src/image/efi_image.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <errno.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <ipxe/efi/efi.h>
-#include <ipxe/efi/efi_snp.h>
-#include <ipxe/efi/efi_download.h>
-#include <ipxe/efi/efi_file.h>
-#include <ipxe/efi/efi_utils.h>
-#include <ipxe/efi/efi_strings.h>
-#include <ipxe/efi/efi_wrap.h>
-#include <ipxe/image.h>
-#include <ipxe/init.h>
-#include <ipxe/features.h>
-#include <ipxe/uri.h>
-
-FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 );
-
-/* Disambiguate the various error causes */
-#define EINFO_EEFI_LOAD \
- __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \
- "Could not load image" )
-#define EINFO_EEFI_LOAD_PROHIBITED \
- __einfo_platformify ( EINFO_EEFI_LOAD, EFI_SECURITY_VIOLATION, \
- "Image prohibited by security policy" )
-#define EEFI_LOAD_PROHIBITED \
- __einfo_error ( EINFO_EEFI_LOAD_PROHIBITED )
-#define EEFI_LOAD( efirc ) EPLATFORM ( EINFO_EEFI_LOAD, efirc, \
- EEFI_LOAD_PROHIBITED )
-#define EINFO_EEFI_START \
- __einfo_uniqify ( EINFO_EPLATFORM, 0x02, \
- "Could not start image" )
-#define EEFI_START( efirc ) EPLATFORM ( EINFO_EEFI_START, efirc )
-
-/**
- * Create device path for image
- *
- * @v image EFI image
- * @v parent Parent device path
- * @ret path Device path, or NULL on failure
- *
- * The caller must eventually free() the device path.
- */
-static EFI_DEVICE_PATH_PROTOCOL *
-efi_image_path ( struct image *image, EFI_DEVICE_PATH_PROTOCOL *parent ) {
- EFI_DEVICE_PATH_PROTOCOL *path;
- FILEPATH_DEVICE_PATH *filepath;
- EFI_DEVICE_PATH_PROTOCOL *end;
- size_t name_len;
- size_t prefix_len;
- size_t filepath_len;
- size_t len;
-
- /* Calculate device path lengths */
- end = efi_devpath_end ( parent );
- prefix_len = ( ( void * ) end - ( void * ) parent );
- name_len = strlen ( image->name );
- filepath_len = ( SIZE_OF_FILEPATH_DEVICE_PATH +
- ( name_len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
- len = ( prefix_len + filepath_len + sizeof ( *end ) );
-
- /* Allocate device path */
- path = zalloc ( len );
- if ( ! path )
- return NULL;
-
- /* Construct device path */
- memcpy ( path, parent, prefix_len );
- filepath = ( ( ( void * ) path ) + prefix_len );
- filepath->Header.Type = MEDIA_DEVICE_PATH;
- filepath->Header.SubType = MEDIA_FILEPATH_DP;
- filepath->Header.Length[0] = ( filepath_len & 0xff );
- filepath->Header.Length[1] = ( filepath_len >> 8 );
- efi_snprintf ( filepath->PathName, ( name_len + 1 /* NUL */ ),
- "%s", image->name );
- end = ( ( ( void * ) filepath ) + filepath_len );
- end->Type = END_DEVICE_PATH_TYPE;
- end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
- end->Length[0] = sizeof ( *end );
-
- return path;
-}
-
-/**
- * Create command line for image
- *
- * @v image EFI image
- * @ret cmdline Command line, or NULL on failure
- */
-static wchar_t * efi_image_cmdline ( struct image *image ) {
- wchar_t *cmdline;
- size_t len;
-
- len = ( strlen ( image->name ) +
- ( image->cmdline ?
- ( 1 /* " " */ + strlen ( image->cmdline ) ) : 0 ) );
- cmdline = zalloc ( ( len + 1 /* NUL */ ) * sizeof ( wchar_t ) );
- if ( ! cmdline )
- return NULL;
- efi_snprintf ( cmdline, ( len + 1 /* NUL */ ), "%s%s%s",
- image->name,
- ( image->cmdline ? " " : "" ),
- ( image->cmdline ? image->cmdline : "" ) );
- return cmdline;
-}
-
-/**
- * Execute EFI image
- *
- * @v image EFI image
- * @ret rc Return status code
- */
-static int efi_image_exec ( struct image *image ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
- struct efi_snp_device *snpdev;
- EFI_DEVICE_PATH_PROTOCOL *path;
- union {
- EFI_LOADED_IMAGE_PROTOCOL *image;
- void *interface;
- } loaded;
- EFI_HANDLE handle;
- wchar_t *cmdline;
- EFI_STATUS efirc;
- int rc;
-
- /* Find an appropriate device handle to use */
- snpdev = last_opened_snpdev();
- if ( ! snpdev ) {
- DBGC ( image, "EFIIMAGE %p could not identify SNP device\n",
- image );
- rc = -ENODEV;
- goto err_no_snpdev;
- }
-
- /* Install file I/O protocols */
- if ( ( rc = efi_file_install ( snpdev->handle ) ) != 0 ) {
- DBGC ( image, "EFIIMAGE %p could not install file protocol: "
- "%s\n", image, strerror ( rc ) );
- goto err_file_install;
- }
-
- /* Install iPXE download protocol */
- if ( ( rc = efi_download_install ( snpdev->handle ) ) != 0 ) {
- DBGC ( image, "EFIIMAGE %p could not install iPXE download "
- "protocol: %s\n", image, strerror ( rc ) );
- goto err_download_install;
- }
-
- /* Create device path for image */
- path = efi_image_path ( image, snpdev->path );
- if ( ! path ) {
- DBGC ( image, "EFIIMAGE %p could not create device path\n",
- image );
- rc = -ENOMEM;
- goto err_image_path;
- }
-
- /* Create command line for image */
- cmdline = efi_image_cmdline ( image );
- if ( ! cmdline ) {
- DBGC ( image, "EFIIMAGE %p could not create command line\n",
- image );
- rc = -ENOMEM;
- goto err_cmdline;
- }
-
- /* Attempt loading image */
- if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path,
- user_to_virt ( image->data, 0 ),
- image->len, &handle ) ) != 0 ) {
- /* Not an EFI image */
- rc = -EEFI_LOAD ( efirc );
- DBGC ( image, "EFIIMAGE %p could not load: %s\n",
- image, strerror ( rc ) );
- goto err_load_image;
- }
-
- /* Get the loaded image protocol for the newly loaded image */
- efirc = bs->OpenProtocol ( handle, &efi_loaded_image_protocol_guid,
- &loaded.interface, efi_image_handle,
- NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL );
- if ( efirc ) {
- /* Should never happen */
- rc = -EEFI ( efirc );
- goto err_open_protocol;
- }
-
- /* Some EFI 1.10 implementations seem not to fill in DeviceHandle */
- if ( loaded.image->DeviceHandle == NULL ) {
- DBGC ( image, "EFIIMAGE %p filling in missing DeviceHandle\n",
- image );
- loaded.image->DeviceHandle = snpdev->handle;
- }
-
- /* Sanity checks */
- assert ( loaded.image->ParentHandle == efi_image_handle );
- assert ( loaded.image->DeviceHandle == snpdev->handle );
- assert ( loaded.image->LoadOptionsSize == 0 );
- assert ( loaded.image->LoadOptions == NULL );
-
- /* Set command line */
- loaded.image->LoadOptions = cmdline;
- loaded.image->LoadOptionsSize =
- ( ( wcslen ( cmdline ) + 1 /* NUL */ ) * sizeof ( wchar_t ) );
-
- /* Release network devices for use via SNP */
- efi_snp_release();
-
- /* Wrap calls made by the loaded image (for debugging) */
- efi_wrap ( handle );
-
- /* Start the image */
- if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) {
- rc = -EEFI_START ( efirc );
- DBGC ( image, "EFIIMAGE %p could not start (or returned with "
- "error): %s\n", image, strerror ( rc ) );
- goto err_start_image;
- }
-
- /* Success */
- rc = 0;
-
- err_start_image:
- efi_snp_claim();
- err_open_protocol:
- /* If there was no error, then the image must have been
- * started and returned successfully. It either unloaded
- * itself, or it intended to remain loaded (e.g. it was a
- * driver). We therefore do not unload successful images.
- *
- * If there was an error, attempt to unload the image. This
- * may not work. In particular, there is no way to tell
- * whether an error returned from StartImage() was due to
- * being unable to start the image (in which case we probably
- * should call UnloadImage()), or due to the image itself
- * returning an error (in which case we probably should not
- * call UnloadImage()). We therefore ignore any failures from
- * the UnloadImage() call itself.
- */
- if ( rc != 0 )
- bs->UnloadImage ( handle );
- err_load_image:
- free ( cmdline );
- err_cmdline:
- free ( path );
- err_image_path:
- efi_download_uninstall ( snpdev->handle );
- err_download_install:
- efi_file_uninstall ( snpdev->handle );
- err_file_install:
- err_no_snpdev:
- return rc;
-}
-
-/**
- * Probe EFI image
- *
- * @v image EFI file
- * @ret rc Return status code
- */
-static int efi_image_probe ( struct image *image ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
- static EFI_DEVICE_PATH_PROTOCOL empty_path = {
- .Type = END_DEVICE_PATH_TYPE,
- .SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE,
- .Length[0] = sizeof ( empty_path ),
- };
- EFI_HANDLE handle;
- EFI_STATUS efirc;
- int rc;
-
- /* Attempt loading image */
- if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, &empty_path,
- user_to_virt ( image->data, 0 ),
- image->len, &handle ) ) != 0 ) {
- /* Not an EFI image */
- rc = -EEFI_LOAD ( efirc );
- DBGC ( image, "EFIIMAGE %p could not load: %s\n",
- image, strerror ( rc ) );
- return rc;
- }
-
- /* Unload the image. We can't leave it loaded, because we
- * have no "unload" operation.
- */
- bs->UnloadImage ( handle );
-
- return 0;
-}
-
-/** EFI image type */
-struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = {
- .name = "EFI",
- .probe = efi_image_probe,
- .exec = efi_image_exec,
-};
diff --git a/qemu/roms/ipxe/src/image/elf.c b/qemu/roms/ipxe/src/image/elf.c
deleted file mode 100644
index 5c2f9db25..000000000
--- a/qemu/roms/ipxe/src/image/elf.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/**
- * @file
- *
- * ELF image format
- *
- * A "pure" ELF image is not a bootable image. There are various
- * bootable formats based upon ELF (e.g. Multiboot), which share
- * common ELF-related functionality.
- */
-
-#include <errno.h>
-#include <elf.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/segment.h>
-#include <ipxe/image.h>
-#include <ipxe/elf.h>
-
-/**
- * Load ELF segment into memory
- *
- * @v image ELF file
- * @v phdr ELF program header
- * @v dest Destination address
- * @ret rc Return status code
- */
-static int elf_load_segment ( struct image *image, Elf_Phdr *phdr,
- physaddr_t dest ) {
- userptr_t buffer = phys_to_user ( dest );
- int rc;
-
- DBGC ( image, "ELF %p loading segment [%x,%x) to [%lx,%lx,%lx)\n",
- image, phdr->p_offset, ( phdr->p_offset + phdr->p_filesz ),
- dest, ( dest + phdr->p_filesz ), ( dest + phdr->p_memsz ) );
-
- /* Verify and prepare segment */
- if ( ( rc = prep_segment ( buffer, phdr->p_filesz,
- phdr->p_memsz ) ) != 0 ) {
- DBGC ( image, "ELF %p could not prepare segment: %s\n",
- image, strerror ( rc ) );
- return rc;
- }
-
- /* Copy image to segment */
- memcpy_user ( buffer, 0, image->data, phdr->p_offset, phdr->p_filesz );
-
- return 0;
-}
-
-/**
- * Process ELF segment
- *
- * @v image ELF file
- * @v ehdr ELF executable header
- * @v phdr ELF program header
- * @v process Segment processor
- * @ret entry Entry point, if found
- * @ret max Maximum used address
- * @ret rc Return status code
- */
-static int elf_segment ( struct image *image, Elf_Ehdr *ehdr, Elf_Phdr *phdr,
- int ( * process ) ( struct image *image,
- Elf_Phdr *phdr, physaddr_t dest ),
- physaddr_t *entry, physaddr_t *max ) {
- physaddr_t dest;
- physaddr_t end;
- unsigned long e_offset;
- int rc;
-
- /* Do nothing for non-PT_LOAD segments */
- if ( phdr->p_type != PT_LOAD )
- return 0;
-
- /* Check segment lies within image */
- if ( ( phdr->p_offset + phdr->p_filesz ) > image->len ) {
- DBGC ( image, "ELF %p segment outside image\n", image );
- return -ENOEXEC;
- }
-
- /* Find start address: use physical address for preference,
- * fall back to virtual address if no physical address
- * supplied.
- */
- dest = phdr->p_paddr;
- if ( ! dest )
- dest = phdr->p_vaddr;
- if ( ! dest ) {
- DBGC ( image, "ELF %p segment loads to physical address 0\n",
- image );
- return -ENOEXEC;
- }
- end = ( dest + phdr->p_memsz );
-
- /* Update maximum used address, if applicable */
- if ( end > *max )
- *max = end;
-
- /* Process segment */
- if ( ( rc = process ( image, phdr, dest ) ) != 0 )
- return rc;
-
- /* Set execution address, if it lies within this segment */
- if ( ( e_offset = ( ehdr->e_entry - dest ) ) < phdr->p_filesz ) {
- *entry = ehdr->e_entry;
- DBGC ( image, "ELF %p found physical entry point at %lx\n",
- image, *entry );
- } else if ( ( e_offset = ( ehdr->e_entry - phdr->p_vaddr ) )
- < phdr->p_filesz ) {
- if ( ! *entry ) {
- *entry = ( dest + e_offset );
- DBGC ( image, "ELF %p found virtual entry point at %lx"
- " (virt %lx)\n", image, *entry,
- ( ( unsigned long ) ehdr->e_entry ) );
- }
- }
-
- return 0;
-}
-
-/**
- * Process ELF segments
- *
- * @v image ELF file
- * @v ehdr ELF executable header
- * @v process Segment processor
- * @ret entry Entry point, if found
- * @ret max Maximum used address
- * @ret rc Return status code
- */
-int elf_segments ( struct image *image, Elf_Ehdr *ehdr,
- int ( * process ) ( struct image *image, Elf_Phdr *phdr,
- physaddr_t dest ),
- physaddr_t *entry, physaddr_t *max ) {
- Elf_Phdr phdr;
- Elf_Off phoff;
- unsigned int phnum;
- int rc;
-
- /* Initialise maximum used address */
- *max = 0;
-
- /* Invalidate entry point */
- *entry = 0;
-
- /* Read and process ELF program headers */
- for ( phoff = ehdr->e_phoff , phnum = ehdr->e_phnum ; phnum ;
- phoff += ehdr->e_phentsize, phnum-- ) {
- if ( phoff > image->len ) {
- DBGC ( image, "ELF %p program header %d outside "
- "image\n", image, phnum );
- return -ENOEXEC;
- }
- copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) );
- if ( ( rc = elf_segment ( image, ehdr, &phdr, process,
- entry, max ) ) != 0 )
- return rc;
- }
-
- /* Check for a valid execution address */
- if ( ! *entry ) {
- DBGC ( image, "ELF %p entry point %lx outside image\n",
- image, ( ( unsigned long ) ehdr->e_entry ) );
- return -ENOEXEC;
- }
-
- return 0;
-}
-
-/**
- * Load ELF image into memory
- *
- * @v image ELF file
- * @ret entry Entry point
- * @ret max Maximum used address
- * @ret rc Return status code
- */
-int elf_load ( struct image *image, physaddr_t *entry, physaddr_t *max ) {
- static const uint8_t e_ident[] = {
- [EI_MAG0] = ELFMAG0,
- [EI_MAG1] = ELFMAG1,
- [EI_MAG2] = ELFMAG2,
- [EI_MAG3] = ELFMAG3,
- [EI_CLASS] = ELFCLASS,
- };
- Elf_Ehdr ehdr;
- int rc;
-
- /* Read ELF header */
- copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
- if ( memcmp ( &ehdr.e_ident[EI_MAG0], e_ident,
- sizeof ( e_ident ) ) != 0 ) {
- DBGC ( image, "ELF %p has invalid signature\n", image );
- return -ENOEXEC;
- }
-
- /* Load ELF segments into memory */
- if ( ( rc = elf_segments ( image, &ehdr, elf_load_segment,
- entry, max ) ) != 0 )
- return rc;
-
- return 0;
-}
diff --git a/qemu/roms/ipxe/src/image/embedded.c b/qemu/roms/ipxe/src/image/embedded.c
deleted file mode 100644
index 48dd86851..000000000
--- a/qemu/roms/ipxe/src/image/embedded.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/** @file
- *
- * Embedded image support
- *
- * Embedded images are images built into the iPXE binary and do not require
- * fetching over the network.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <string.h>
-#include <ipxe/image.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/init.h>
-
-/* Raw image data for all embedded images */
-#undef EMBED
-#define EMBED( _index, _path, _name ) \
- extern char embedded_image_ ## _index ## _data[]; \
- extern char embedded_image_ ## _index ## _len[]; \
- __asm__ ( ".section \".rodata\", \"a\", @progbits\n\t" \
- "\nembedded_image_" #_index "_data:\n\t" \
- ".incbin \"" _path "\"\n\t" \
- "\nembedded_image_" #_index "_end:\n\t" \
- ".equ embedded_image_" #_index "_len, " \
- "( embedded_image_" #_index "_end - " \
- " embedded_image_" #_index "_data )\n\t" \
- ".previous\n\t" );
-EMBED_ALL
-
-/* Image structures for all embedded images */
-#undef EMBED
-#define EMBED( _index, _path, _name ) { \
- .refcnt = REF_INIT ( ref_no_free ), \
- .name = _name, \
- .data = ( userptr_t ) ( embedded_image_ ## _index ## _data ), \
- .len = ( size_t ) embedded_image_ ## _index ## _len, \
-},
-static struct image embedded_images[] = {
- EMBED_ALL
-};
-
-/**
- * Register all embedded images
- */
-static void embedded_init ( void ) {
- int i;
- struct image *image;
- void *data;
- int rc;
-
- /* Skip if we have no embedded images */
- if ( ! sizeof ( embedded_images ) )
- return;
-
- /* Fix up data pointers and register images */
- for ( i = 0 ; i < ( int ) ( sizeof ( embedded_images ) /
- sizeof ( embedded_images[0] ) ) ; i++ ) {
- image = &embedded_images[i];
-
- /* virt_to_user() cannot be used in a static
- * initialiser, so we cast the pointer to a userptr_t
- * in the initialiser and fix it up here. (This will
- * actually be a no-op on most platforms.)
- */
- data = ( ( void * ) image->data );
- image->data = virt_to_user ( data );
-
- DBG ( "Embedded image \"%s\": %zd bytes at %p\n",
- image->name, image->len, data );
-
- if ( ( rc = register_image ( image ) ) != 0 ) {
- DBG ( "Could not register embedded image \"%s\": "
- "%s\n", image->name, strerror ( rc ) );
- return;
- }
- }
-
- /* Select the first image */
- image = &embedded_images[0];
- if ( ( rc = image_select ( image ) ) != 0 ) {
- DBG ( "Could not select embedded image \"%s\": %s\n",
- image->name, strerror ( rc ) );
- return;
- }
-}
-
-/** Embedded image initialisation function */
-struct init_fn embedded_init_fn __init_fn ( INIT_LATE ) = {
- .initialise = embedded_init,
-};
diff --git a/qemu/roms/ipxe/src/image/png.c b/qemu/roms/ipxe/src/image/png.c
deleted file mode 100644
index 5c4bcb3a0..000000000
--- a/qemu/roms/ipxe/src/image/png.c
+++ /dev/null
@@ -1,1011 +0,0 @@
-/*
- * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <byteswap.h>
-#include <ipxe/umalloc.h>
-#include <ipxe/pixbuf.h>
-#include <ipxe/deflate.h>
-#include <ipxe/png.h>
-
-/** @file
- *
- * Portable Network Graphics (PNG) format
- *
- * The PNG format is defined in RFC 2083.
- */
-
-/** PNG context */
-struct png_context {
- /** Offset within image */
- size_t offset;
-
- /** Pixel buffer */
- struct pixel_buffer *pixbuf;
-
- /** Bit depth */
- unsigned int depth;
- /** Colour type */
- unsigned int colour_type;
- /** Number of channels */
- unsigned int channels;
- /** Number of interlace passes */
- unsigned int passes;
- /** Palette, in iPXE's pixel buffer format */
- uint32_t palette[PNG_PALETTE_COUNT];
-
- /** Decompression buffer for raw PNG data */
- struct deflate_chunk raw;
- /** Decompressor */
- struct deflate deflate;
-};
-
-/** A PNG interlace pass */
-struct png_interlace {
- /** Pass number */
- unsigned int pass;
- /** X starting indent */
- unsigned int x_indent;
- /** Y starting indent */
- unsigned int y_indent;
- /** X stride */
- unsigned int x_stride;
- /** Y stride */
- unsigned int y_stride;
- /** Width */
- unsigned int width;
- /** Height */
- unsigned int height;
-};
-
-/** PNG file signature */
-static struct png_signature png_signature = PNG_SIGNATURE;
-
-/** Number of interlacing passes */
-static uint8_t png_interlace_passes[] = {
- [PNG_INTERLACE_NONE] = 1,
- [PNG_INTERLACE_ADAM7] = 7,
-};
-
-/**
- * Transcribe PNG chunk type name (for debugging)
- *
- * @v type Chunk type
- * @ret name Chunk type name
- */
-static const char * png_type_name ( uint32_t type ) {
- static union {
- uint32_t type;
- char name[ sizeof ( uint32_t ) + 1 /* NUL */ ];
- } u;
-
- u.type = type;
- return u.name;
-}
-
-/**
- * Calculate PNG interlace pass parameters
- *
- * @v png PNG context
- * @v pass Pass number (0=first pass)
- * @v interlace Interlace pass to fill in
- */
-static void png_interlace ( struct png_context *png, unsigned int pass,
- struct png_interlace *interlace ) {
- unsigned int grid_width_log2;
- unsigned int grid_height_log2;
- unsigned int x_indent;
- unsigned int y_indent;
- unsigned int x_stride_log2;
- unsigned int y_stride_log2;
- unsigned int x_stride;
- unsigned int y_stride;
- unsigned int width;
- unsigned int height;
-
- /* Sanity check */
- assert ( png->passes > 0 );
-
- /* Store pass number */
- interlace->pass = pass;
-
- /* Calculate interlace grid dimensions */
- grid_width_log2 = ( png->passes / 2 );
- grid_height_log2 = ( ( png->passes - 1 ) / 2 );
-
- /* Calculate starting indents */
- interlace->x_indent = x_indent =
- ( ( pass & 1 ) ?
- ( 1 << ( grid_width_log2 - ( pass / 2 ) - 1 ) ) : 0 );
- interlace->y_indent = y_indent =
- ( ( pass && ! ( pass & 1 ) ) ?
- ( 1 << ( grid_height_log2 - ( ( pass - 1 ) / 2 ) - 1 ) ) : 0);
-
- /* Calculate strides */
- x_stride_log2 = ( grid_width_log2 - ( pass / 2 ) );
- y_stride_log2 =
- ( grid_height_log2 - ( pass ? ( ( pass - 1 ) / 2 ) : 0 ) );
- interlace->x_stride = x_stride = ( 1 << x_stride_log2 );
- interlace->y_stride = y_stride = ( 1 << y_stride_log2 );
-
- /* Calculate pass dimensions */
- width = png->pixbuf->width;
- height = png->pixbuf->height;
- interlace->width =
- ( ( width - x_indent + x_stride - 1 ) >> x_stride_log2 );
- interlace->height =
- ( ( height - y_indent + y_stride - 1 ) >> y_stride_log2 );
-}
-
-/**
- * Calculate PNG pixel length
- *
- * @v png PNG context
- * @ret pixel_len Pixel length
- */
-static unsigned int png_pixel_len ( struct png_context *png ) {
-
- return ( ( ( png->channels * png->depth ) + 7 ) / 8 );
-}
-
-/**
- * Calculate PNG scanline length
- *
- * @v png PNG context
- * @v interlace Interlace pass
- * @ret scanline_len Scanline length (including filter byte)
- */
-static size_t png_scanline_len ( struct png_context *png,
- struct png_interlace *interlace ) {
-
- return ( 1 /* Filter byte */ +
- ( ( interlace->width * png->channels * png->depth ) + 7 ) / 8);
-}
-
-/**
- * Handle PNG image header chunk
- *
- * @v image PNG image
- * @v png PNG context
- * @v len Chunk length
- * @ret rc Return status code
- */
-static int png_image_header ( struct image *image, struct png_context *png,
- size_t len ) {
- struct png_image_header ihdr;
- struct png_interlace interlace;
- unsigned int pass;
-
- /* Sanity check */
- if ( len != sizeof ( ihdr ) ) {
- DBGC ( image, "PNG %s invalid IHDR length %zd\n",
- image->name, len );
- return -EINVAL;
- }
- if ( png->pixbuf ) {
- DBGC ( image, "PNG %s duplicate IHDR\n", image->name );
- return -EINVAL;
- }
-
- /* Extract image header */
- copy_from_user ( &ihdr, image->data, png->offset, len );
- DBGC ( image, "PNG %s %dx%d depth %d type %d compression %d filter %d "
- "interlace %d\n", image->name, ntohl ( ihdr.width ),
- ntohl ( ihdr.height ), ihdr.depth, ihdr.colour_type,
- ihdr.compression, ihdr.filter, ihdr.interlace );
-
- /* Sanity checks */
- if ( ihdr.compression >= PNG_COMPRESSION_UNKNOWN ) {
- DBGC ( image, "PNG %s unknown compression method %d\n",
- image->name, ihdr.compression );
- return -ENOTSUP;
- }
- if ( ihdr.filter >= PNG_FILTER_UNKNOWN ) {
- DBGC ( image, "PNG %s unknown filter method %d\n",
- image->name, ihdr.filter );
- return -ENOTSUP;
- }
- if ( ihdr.interlace >= PNG_INTERLACE_UNKNOWN ) {
- DBGC ( image, "PNG %s unknown interlace method %d\n",
- image->name, ihdr.interlace );
- return -ENOTSUP;
- }
-
- /* Allocate pixel buffer */
- png->pixbuf = alloc_pixbuf ( ntohl ( ihdr.width ),
- ntohl ( ihdr.height ) );
- if ( ! png->pixbuf ) {
- DBGC ( image, "PNG %s could not allocate pixel buffer\n",
- image->name );
- return -ENOMEM;
- }
-
- /* Extract bit depth */
- png->depth = ihdr.depth;
- if ( ( png->depth == 0 ) ||
- ( ( png->depth & ( png->depth - 1 ) ) != 0 ) ) {
- DBGC ( image, "PNG %s invalid depth %d\n",
- image->name, png->depth );
- return -EINVAL;
- }
-
- /* Calculate number of channels */
- png->colour_type = ihdr.colour_type;
- png->channels = 1;
- if ( ! ( ihdr.colour_type & PNG_COLOUR_TYPE_PALETTE ) ) {
- if ( ihdr.colour_type & PNG_COLOUR_TYPE_RGB )
- png->channels += 2;
- if ( ihdr.colour_type & PNG_COLOUR_TYPE_ALPHA )
- png->channels += 1;
- }
-
- /* Calculate number of interlace passes */
- png->passes = png_interlace_passes[ihdr.interlace];
-
- /* Calculate length of raw data buffer */
- for ( pass = 0 ; pass < png->passes ; pass++ ) {
- png_interlace ( png, pass, &interlace );
- if ( interlace.width == 0 )
- continue;
- png->raw.len += ( interlace.height *
- png_scanline_len ( png, &interlace ) );
- }
-
- /* Allocate raw data buffer */
- png->raw.data = umalloc ( png->raw.len );
- if ( ! png->raw.data ) {
- DBGC ( image, "PNG %s could not allocate data buffer\n",
- image->name );
- return -ENOMEM;
- }
-
- return 0;
-}
-
-/**
- * Handle PNG palette chunk
- *
- * @v image PNG image
- * @v png PNG context
- * @v len Chunk length
- * @ret rc Return status code
- */
-static int png_palette ( struct image *image, struct png_context *png,
- size_t len ) {
- size_t offset = png->offset;
- struct png_palette_entry palette;
- unsigned int i;
-
- /* Populate palette */
- for ( i = 0 ; i < ( sizeof ( png->palette ) /
- sizeof ( png->palette[0] ) ) ; i++ ) {
-
- /* Stop when we run out of palette data */
- if ( len < sizeof ( palette ) )
- break;
-
- /* Extract palette entry */
- copy_from_user ( &palette, image->data, offset,
- sizeof ( palette ) );
- png->palette[i] = ( ( palette.red << 16 ) |
- ( palette.green << 8 ) |
- ( palette.blue << 0 ) );
- DBGC2 ( image, "PNG %s palette entry %d is %#06x\n",
- image->name, i, png->palette[i] );
-
- /* Move to next entry */
- offset += sizeof ( palette );
- len -= sizeof ( palette );
- }
-
- return 0;
-}
-
-/**
- * Handle PNG image data chunk
- *
- * @v image PNG image
- * @v png PNG context
- * @v len Chunk length
- * @ret rc Return status code
- */
-static int png_image_data ( struct image *image, struct png_context *png,
- size_t len ) {
- struct deflate_chunk in;
- int rc;
-
- /* Deflate this chunk */
- deflate_chunk_init ( &in, image->data, png->offset,
- ( png->offset + len ) );
- if ( ( rc = deflate_inflate ( &png->deflate, &in, &png->raw ) ) != 0 ) {
- DBGC ( image, "PNG %s could not decompress: %s\n",
- image->name, strerror ( rc ) );
- return rc;
- }
-
- return 0;
-}
-
-/**
- * Unfilter byte using the "None" filter
- *
- * @v current Filtered current byte
- * @v left Unfiltered left byte
- * @v above Unfiltered above byte
- * @v above_left Unfiltered above-left byte
- * @ret current Unfiltered current byte
- */
-static unsigned int png_unfilter_none ( unsigned int current,
- unsigned int left __unused,
- unsigned int above __unused,
- unsigned int above_left __unused ) {
-
- return current;
-}
-
-/**
- * Unfilter byte using the "Sub" filter
- *
- * @v current Filtered current byte
- * @v left Unfiltered left byte
- * @v above Unfiltered above byte
- * @v above_left Unfiltered above-left byte
- * @ret current Unfiltered current byte
- */
-static unsigned int png_unfilter_sub ( unsigned int current,
- unsigned int left,
- unsigned int above __unused,
- unsigned int above_left __unused ) {
-
- return ( current + left );
-}
-
-/**
- * Unfilter byte using the "Up" filter
- *
- * @v current Filtered current byte
- * @v left Unfiltered left byte
- * @v above Unfiltered above byte
- * @v above_left Unfiltered above-left byte
- * @ret current Unfiltered current byte
- */
-static unsigned int png_unfilter_up ( unsigned int current,
- unsigned int left __unused,
- unsigned int above,
- unsigned int above_left __unused ) {
-
- return ( current + above );
-}
-
-/**
- * Unfilter byte using the "Average" filter
- *
- * @v current Filtered current byte
- * @v left Unfiltered left byte
- * @v above Unfiltered above byte
- * @v above_left Unfiltered above-left byte
- * @ret current Unfiltered current byte
- */
-static unsigned int png_unfilter_average ( unsigned int current,
- unsigned int left,
- unsigned int above,
- unsigned int above_left __unused ) {
-
- return ( current + ( ( above + left ) >> 1 ) );
-}
-
-/**
- * Paeth predictor function (defined in RFC 2083)
- *
- * @v a Pixel A
- * @v b Pixel B
- * @v c Pixel C
- * @ret predictor Predictor pixel
- */
-static unsigned int png_paeth_predictor ( unsigned int a, unsigned int b,
- unsigned int c ) {
- unsigned int p;
- unsigned int pa;
- unsigned int pb;
- unsigned int pc;
-
- /* Algorithm as defined in RFC 2083 section 6.6 */
- p = ( a + b - c );
- pa = abs ( p - a );
- pb = abs ( p - b );
- pc = abs ( p - c );
- if ( ( pa <= pb ) && ( pa <= pc ) ) {
- return a;
- } else if ( pb <= pc ) {
- return b;
- } else {
- return c;
- }
-}
-
-/**
- * Unfilter byte using the "Paeth" filter
- *
- * @v current Filtered current byte
- * @v above_left Unfiltered above-left byte
- * @v above Unfiltered above byte
- * @v left Unfiltered left byte
- * @ret current Unfiltered current byte
- */
-static unsigned int png_unfilter_paeth ( unsigned int current,
- unsigned int left,
- unsigned int above,
- unsigned int above_left ) {
-
- return ( current + png_paeth_predictor ( left, above, above_left ) );
-}
-
-/** A PNG filter */
-struct png_filter {
- /**
- * Unfilter byte
- *
- * @v current Filtered current byte
- * @v left Unfiltered left byte
- * @v above Unfiltered above byte
- * @v above_left Unfiltered above-left byte
- * @ret current Unfiltered current byte
- */
- unsigned int ( * unfilter ) ( unsigned int current,
- unsigned int left,
- unsigned int above,
- unsigned int above_left );
-};
-
-/** PNG filter types */
-static struct png_filter png_filters[] = {
- [PNG_FILTER_BASIC_NONE] = { png_unfilter_none },
- [PNG_FILTER_BASIC_SUB] = { png_unfilter_sub },
- [PNG_FILTER_BASIC_UP] = { png_unfilter_up },
- [PNG_FILTER_BASIC_AVERAGE] = { png_unfilter_average },
- [PNG_FILTER_BASIC_PAETH] = { png_unfilter_paeth },
-};
-
-/**
- * Unfilter one interlace pass of PNG raw data
- *
- * @v image PNG image
- * @v png PNG context
- * @v interlace Interlace pass
- * @ret rc Return status code
- *
- * This routine may assume that it is impossible to overrun the raw
- * data buffer, since the size is determined by the image dimensions.
- */
-static int png_unfilter_pass ( struct image *image, struct png_context *png,
- struct png_interlace *interlace ) {
- size_t offset = png->raw.offset;
- size_t pixel_len = png_pixel_len ( png );
- size_t scanline_len = png_scanline_len ( png, interlace );
- struct png_filter *filter;
- unsigned int scanline;
- unsigned int byte;
- uint8_t filter_type;
- uint8_t left;
- uint8_t above;
- uint8_t above_left;
- uint8_t current;
-
- /* On the first scanline of a pass, above bytes are assumed to
- * be zero.
- */
- above = 0;
-
- /* Iterate over each scanline in turn */
- for ( scanline = 0 ; scanline < interlace->height ; scanline++ ) {
-
- /* Extract filter byte and determine filter type */
- copy_from_user ( &filter_type, png->raw.data, offset++,
- sizeof ( filter_type ) );
- if ( filter_type >= ( sizeof ( png_filters ) /
- sizeof ( png_filters[0] ) ) ) {
- DBGC ( image, "PNG %s unknown filter type %d\n",
- image->name, filter_type );
- return -ENOTSUP;
- }
- filter = &png_filters[filter_type];
- assert ( filter->unfilter != NULL );
- DBGC2 ( image, "PNG %s pass %d scanline %d filter type %d\n",
- image->name, interlace->pass, scanline, filter_type );
-
- /* At the start of a line, both above-left and left
- * bytes are taken to be zero.
- */
- left = 0;
- above_left = 0;
-
- /* Iterate over each byte (not pixel) in turn */
- for ( byte = 0 ; byte < ( scanline_len - 1 ) ; byte++ ) {
-
- /* Extract predictor bytes, if applicable */
- if ( byte >= pixel_len ) {
- copy_from_user ( &left, png->raw.data,
- ( offset - pixel_len ),
- sizeof ( left ) );
- }
- if ( scanline > 0 ) {
- copy_from_user ( &above, png->raw.data,
- ( offset - scanline_len ),
- sizeof ( above ) );
- }
- if ( ( scanline > 0 ) && ( byte >= pixel_len ) ) {
- copy_from_user ( &above_left, png->raw.data,
- ( offset - scanline_len -
- pixel_len ),
- sizeof ( above_left ) );
- }
-
- /* Unfilter current byte */
- copy_from_user ( &current, png->raw.data,
- offset, sizeof ( current ) );
- current = filter->unfilter ( current, left, above,
- above_left );
- copy_to_user ( png->raw.data, offset++,
- &current, sizeof ( current ) );
- }
- }
-
- /* Update offset */
- png->raw.offset = offset;
-
- return 0;
-}
-
-/**
- * Unfilter PNG raw data
- *
- * @v image PNG image
- * @v png PNG context
- * @ret rc Return status code
- *
- * This routine may assume that it is impossible to overrun the raw
- * data buffer, since the size is determined by the image dimensions.
- */
-static int png_unfilter ( struct image *image, struct png_context *png ) {
- struct png_interlace interlace;
- unsigned int pass;
- int rc;
-
- /* Process each interlace pass */
- png->raw.offset = 0;
- for ( pass = 0 ; pass < png->passes ; pass++ ) {
-
- /* Calculate interlace pass parameters */
- png_interlace ( png, pass, &interlace );
-
- /* Skip zero-width rows (which have no filter bytes) */
- if ( interlace.width == 0 )
- continue;
-
- /* Unfilter this pass */
- if ( ( rc = png_unfilter_pass ( image, png,
- &interlace ) ) != 0 )
- return rc;
- }
- assert ( png->raw.offset == png->raw.len );
-
- return 0;
-}
-
-/**
- * Calculate PNG pixel component value
- *
- * @v raw Raw component value
- * @v alpha Alpha value
- * @v max Maximum raw/alpha value
- * @ret value Component value in range 0-255
- */
-static inline unsigned int png_pixel ( unsigned int raw, unsigned int alpha,
- unsigned int max ) {
-
- /* The basic calculation is 255*(raw/max)*(value/max). We use
- * fixed-point arithmetic (scaling up to the maximum range for
- * a 32-bit integer), in order to get the same results for
- * alpha blending as the test cases (produced using
- * ImageMagick).
- */
- return ( ( ( ( ( 0xff00 * raw * alpha ) / max ) / max ) + 0x80 ) >> 8 );
-}
-
-/**
- * Fill one interlace pass of PNG pixels
- *
- * @v image PNG image
- * @v png PNG context
- * @v interlace Interlace pass
- *
- * This routine may assume that it is impossible to overrun either the
- * raw data buffer or the pixel buffer, since the sizes of both are
- * determined by the image dimensions.
- */
-static void png_pixels_pass ( struct image *image,
- struct png_context *png,
- struct png_interlace *interlace ) {
- size_t raw_offset = png->raw.offset;
- uint8_t channel[png->channels];
- int is_indexed = ( png->colour_type & PNG_COLOUR_TYPE_PALETTE );
- int is_rgb = ( png->colour_type & PNG_COLOUR_TYPE_RGB );
- int has_alpha = ( png->colour_type & PNG_COLOUR_TYPE_ALPHA );
- size_t pixbuf_y_offset;
- size_t pixbuf_offset;
- size_t pixbuf_x_stride;
- size_t pixbuf_y_stride;
- size_t raw_stride;
- unsigned int y;
- unsigned int x;
- unsigned int c;
- unsigned int bits;
- unsigned int depth;
- unsigned int max;
- unsigned int alpha;
- unsigned int raw;
- unsigned int value;
- uint8_t current = 0;
- uint32_t pixel;
-
- /* We only ever use the top byte of 16-bit pixels. Model this
- * as a bit depth of 8 with a stride of more than one.
- */
- depth = png->depth;
- raw_stride = ( ( depth + 7 ) / 8 );
- if ( depth > 8 )
- depth = 8;
- max = ( ( 1 << depth ) - 1 );
-
- /* Calculate pixel buffer offset and strides */
- pixbuf_y_offset = ( ( ( interlace->y_indent * png->pixbuf->width ) +
- interlace->x_indent ) * sizeof ( pixel ) );
- pixbuf_x_stride = ( interlace->x_stride * sizeof ( pixel ) );
- pixbuf_y_stride = ( interlace->y_stride * png->pixbuf->width *
- sizeof ( pixel ) );
- DBGC2 ( image, "PNG %s pass %d %dx%d at (%d,%d) stride (%d,%d)\n",
- image->name, interlace->pass, interlace->width,
- interlace->height, interlace->x_indent, interlace->y_indent,
- interlace->x_stride, interlace->y_stride );
-
- /* Iterate over each scanline in turn */
- for ( y = 0 ; y < interlace->height ; y++ ) {
-
- /* Skip filter byte */
- raw_offset++;
-
- /* Iterate over each pixel in turn */
- bits = depth;
- pixbuf_offset = pixbuf_y_offset;
- for ( x = 0 ; x < interlace->width ; x++ ) {
-
- /* Extract sample value */
- for ( c = 0 ; c < png->channels ; c++ ) {
-
- /* Get sample value into high bits of current */
- current <<= depth;
- bits -= depth;
- if ( ! bits ) {
- copy_from_user ( &current,
- png->raw.data,
- raw_offset,
- sizeof ( current ) );
- raw_offset += raw_stride;
- bits = 8;
- }
-
- /* Extract sample value */
- channel[c] = ( current >> ( 8 - depth ) );
- }
-
- /* Convert to native pixel format */
- if ( is_indexed ) {
-
- /* Indexed */
- pixel = png->palette[channel[0]];
-
- } else {
-
- /* Determine alpha value */
- alpha = ( has_alpha ?
- channel[ png->channels - 1 ] : max );
-
- /* Convert to RGB value */
- pixel = 0;
- for ( c = 0 ; c < 3 ; c++ ) {
- raw = channel[ is_rgb ? c : 0 ];
- value = png_pixel ( raw, alpha, max );
- assert ( value <= 255 );
- pixel = ( ( pixel << 8 ) | value );
- }
- }
-
- /* Store pixel */
- copy_to_user ( png->pixbuf->data, pixbuf_offset,
- &pixel, sizeof ( pixel ) );
- pixbuf_offset += pixbuf_x_stride;
- }
-
- /* Move to next output row */
- pixbuf_y_offset += pixbuf_y_stride;
- }
-
- /* Update offset */
- png->raw.offset = raw_offset;
-}
-
-/**
- * Fill PNG pixels
- *
- * @v image PNG image
- * @v png PNG context
- *
- * This routine may assume that it is impossible to overrun either the
- * raw data buffer or the pixel buffer, since the sizes of both are
- * determined by the image dimensions.
- */
-static void png_pixels ( struct image *image, struct png_context *png ) {
- struct png_interlace interlace;
- unsigned int pass;
-
- /* Process each interlace pass */
- png->raw.offset = 0;
- for ( pass = 0 ; pass < png->passes ; pass++ ) {
-
- /* Calculate interlace pass parameters */
- png_interlace ( png, pass, &interlace );
-
- /* Skip zero-width rows (which have no filter bytes) */
- if ( interlace.width == 0 )
- continue;
-
- /* Unfilter this pass */
- png_pixels_pass ( image, png, &interlace );
- }
- assert ( png->raw.offset == png->raw.len );
-}
-
-/**
- * Handle PNG image end chunk
- *
- * @v image PNG image
- * @v png PNG context
- * @v len Chunk length
- * @ret rc Return status code
- */
-static int png_image_end ( struct image *image, struct png_context *png,
- size_t len ) {
- int rc;
-
- /* Sanity checks */
- if ( len != 0 ) {
- DBGC ( image, "PNG %s invalid IEND length %zd\n",
- image->name, len );
- return -EINVAL;
- }
- if ( ! png->pixbuf ) {
- DBGC ( image, "PNG %s missing pixel buffer (no IHDR?)\n",
- image->name );
- return -EINVAL;
- }
- if ( ! deflate_finished ( &png->deflate ) ) {
- DBGC ( image, "PNG %s decompression not complete\n",
- image->name );
- return -EINVAL;
- }
- if ( png->raw.offset != png->raw.len ) {
- DBGC ( image, "PNG %s incorrect decompressed length (expected "
- "%zd, got %zd)\n", image->name, png->raw.len,
- png->raw.offset );
- return -EINVAL;
- }
-
- /* Unfilter raw data */
- if ( ( rc = png_unfilter ( image, png ) ) != 0 )
- return rc;
-
- /* Fill pixel buffer */
- png_pixels ( image, png );
-
- return 0;
-}
-
-/** A PNG chunk handler */
-struct png_chunk_handler {
- /** Chunk type */
- uint32_t type;
- /**
- * Handle chunk
- *
- * @v image PNG image
- * @v png PNG context
- * @v len Chunk length
- * @ret rc Return status code
- */
- int ( * handle ) ( struct image *image, struct png_context *png,
- size_t len );
-};
-
-/** PNG chunk handlers */
-static struct png_chunk_handler png_chunk_handlers[] = {
- { htonl ( PNG_TYPE_IHDR ), png_image_header },
- { htonl ( PNG_TYPE_PLTE ), png_palette },
- { htonl ( PNG_TYPE_IDAT ), png_image_data },
- { htonl ( PNG_TYPE_IEND ), png_image_end },
-};
-
-/**
- * Handle PNG chunk
- *
- * @v image PNG image
- * @v png PNG context
- * @v type Chunk type
- * @v len Chunk length
- * @ret rc Return status code
- */
-static int png_chunk ( struct image *image, struct png_context *png,
- uint32_t type, size_t len ) {
- struct png_chunk_handler *handler;
- unsigned int i;
-
- DBGC ( image, "PNG %s chunk type %s offset %zd length %zd\n",
- image->name, png_type_name ( type ), png->offset, len );
-
- /* Handle according to chunk type */
- for ( i = 0 ; i < ( sizeof ( png_chunk_handlers ) /
- sizeof ( png_chunk_handlers[0] ) ) ; i++ ) {
- handler = &png_chunk_handlers[i];
- if ( handler->type == type )
- return handler->handle ( image, png, len );
- }
-
- /* Fail if unknown chunk type is critical */
- if ( ! ( type & htonl ( PNG_CHUNK_ANCILLARY ) ) ) {
- DBGC ( image, "PNG %s unknown critical chunk type %s\n",
- image->name, png_type_name ( type ) );
- return -ENOTSUP;
- }
-
- /* Ignore non-critical unknown chunk types */
- return 0;
-}
-
-/**
- * Convert PNG image to pixel buffer
- *
- * @v image PNG image
- * @v pixbuf Pixel buffer to fill in
- * @ret rc Return status code
- */
-static int png_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) {
- struct png_context *png;
- struct png_chunk_header header;
- struct png_chunk_footer footer;
- size_t remaining;
- size_t chunk_len;
- int rc;
-
- /* Allocate and initialise context */
- png = zalloc ( sizeof ( *png ) );
- if ( ! png ) {
- rc = -ENOMEM;
- goto err_alloc;
- }
- png->offset = sizeof ( struct png_signature );
- deflate_init ( &png->deflate, DEFLATE_ZLIB );
-
- /* Process chunks */
- do {
-
- /* Extract chunk header */
- remaining = ( image->len - png->offset );
- if ( remaining < sizeof ( header ) ) {
- DBGC ( image, "PNG %s truncated chunk header at offset "
- "%zd\n", image->name, png->offset );
- rc = -EINVAL;
- goto err_truncated;
- }
- copy_from_user ( &header, image->data, png->offset,
- sizeof ( header ) );
- png->offset += sizeof ( header );
-
- /* Validate chunk length */
- chunk_len = ntohl ( header.len );
- if ( remaining < ( sizeof ( header ) + chunk_len +
- sizeof ( footer ) ) ) {
- DBGC ( image, "PNG %s truncated chunk data/footer at "
- "offset %zd\n", image->name, png->offset );
- rc = -EINVAL;
- goto err_truncated;
- }
-
- /* Handle chunk */
- if ( ( rc = png_chunk ( image, png, header.type,
- chunk_len ) ) != 0 )
- goto err_chunk;
-
- /* Move to next chunk */
- png->offset += ( chunk_len + sizeof ( footer ) );
-
- } while ( png->offset < image->len );
-
- /* Check that we finished with an IEND chunk */
- if ( header.type != htonl ( PNG_TYPE_IEND ) ) {
- DBGC ( image, "PNG %s did not finish with IEND\n",
- image->name );
- rc = -EINVAL;
- goto err_iend;
- }
-
- /* Return pixel buffer */
- *pixbuf = pixbuf_get ( png->pixbuf );
-
- /* Success */
- rc = 0;
-
- err_iend:
- err_chunk:
- err_truncated:
- pixbuf_put ( png->pixbuf );
- ufree ( png->raw.data );
- free ( png );
- err_alloc:
- return rc;
-}
-
-/**
- * Probe PNG image
- *
- * @v image PNG image
- * @ret rc Return status code
- */
-static int png_probe ( struct image *image ) {
- struct png_signature signature;
-
- /* Sanity check */
- if ( image->len < sizeof ( signature ) ) {
- DBGC ( image, "PNG %s is too short\n", image->name );
- return -ENOEXEC;
- }
-
- /* Check signature */
- copy_from_user ( &signature, image->data, 0, sizeof ( signature ) );
- if ( memcmp ( &signature, &png_signature, sizeof ( signature ) ) != 0 ){
- DBGC ( image, "PNG %s has invalid signature\n", image->name );
- return -ENOEXEC;
- }
-
- return 0;
-}
-
-/** PNG image type */
-struct image_type png_image_type __image_type ( PROBE_NORMAL ) = {
- .name = "PNG",
- .probe = png_probe,
- .pixbuf = png_pixbuf,
-};
diff --git a/qemu/roms/ipxe/src/image/pnm.c b/qemu/roms/ipxe/src/image/pnm.c
deleted file mode 100644
index f24b28841..000000000
--- a/qemu/roms/ipxe/src/image/pnm.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/** @file
- *
- * Portable anymap format (PNM)
- *
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-#include <ipxe/image.h>
-#include <ipxe/pixbuf.h>
-#include <ipxe/pnm.h>
-
-/**
- * Extract PNM ASCII value
- *
- * @v image PNM image
- * @v pnm PNM context
- * @ret value Value, or negative error
- */
-static int pnm_ascii ( struct image *image, struct pnm_context *pnm ) {
- char buf[ pnm->ascii_len + 1 /* NUL */ ];
- char *endp;
- size_t len;
- int value;
- int in_comment = 0;
-
- /* Skip any leading whitespace and comments */
- for ( ; pnm->offset < image->len ; pnm->offset++ ) {
- copy_from_user ( &buf[0], image->data, pnm->offset,
- sizeof ( buf[0] ) );
- if ( in_comment ) {
- if ( buf[0] == '\n' )
- in_comment = 0;
- } else {
- if ( buf[0] == '#' ) {
- in_comment = 1;
- } else if ( ! isspace ( buf[0] ) ) {
- break;
- }
- }
- }
-
- /* Fail if no value is present */
- len = ( image->len - pnm->offset );
- if ( len == 0 ) {
- DBGC ( image, "PNM %s ran out of ASCII data\n", image->name );
- return -EINVAL;
- }
-
- /* Copy ASCII value to buffer and ensure string is NUL-terminated */
- if ( len > ( sizeof ( buf ) - 1 /* NUL */ ) )
- len = ( sizeof ( buf ) - 1 /* NUL */ );
- copy_from_user ( buf, image->data, pnm->offset, len );
- buf[len] = '\0';
-
- /* Parse value and update offset */
- value = strtoul ( buf, &endp, 0 );
- pnm->offset += ( endp - buf );
-
- /* Check and skip terminating whitespace character, if present */
- if ( ( pnm->offset != image->len ) && ( *endp != '\0' ) ) {
- if ( ! isspace ( *endp ) ) {
- DBGC ( image, "PNM %s invalid ASCII integer\n",
- image->name );
- return -EINVAL;
- }
- pnm->offset++;
- }
-
- return value;
-}
-
-/**
- * Extract PNM binary value
- *
- * @v image PNM image
- * @v pnm PNM context
- * @ret value Value, or negative error
- */
-static int pnm_binary ( struct image *image, struct pnm_context *pnm ) {
- uint8_t value;
-
- /* Sanity check */
- if ( pnm->offset == image->len ) {
- DBGC ( image, "PNM %s ran out of binary data\n",
- image->name );
- return -EINVAL;
- }
-
- /* Extract value */
- copy_from_user ( &value, image->data, pnm->offset, sizeof ( value ) );
- pnm->offset++;
-
- return value;
-}
-
-/**
- * Scale PNM scalar value
- *
- * @v image PNM image
- * @v pnm PNM context
- * @v value Raw value
- * @ret value Scaled value (in range 0-255)
- */
-static int pnm_scale ( struct image *image, struct pnm_context *pnm,
- unsigned int value ) {
-
- if ( value > pnm->max ) {
- DBGC ( image, "PNM %s has out-of-range value %d (max %d)\n",
- image->name, value, pnm->max );
- return -EINVAL;
- }
- return ( ( 255 * value ) / pnm->max );
-}
-
-/**
- * Convert PNM bitmap composite value to RGB
- *
- * @v composite Composite value
- * @v index Pixel index within this composite value
- * @ret rgb 24-bit RGB value
- */
-static uint32_t pnm_bitmap ( uint32_t composite, unsigned int index ) {
-
- /* Composite value is an 8-bit bitmask */
- return ( ( ( composite << index ) & 0x80 ) ? 0x000000 : 0xffffff );
-}
-
-/**
- * Convert PNM greymap composite value to RGB
- *
- * @v composite Composite value
- * @v index Pixel index within this composite value
- * @ret rgb 24-bit RGB value
- */
-static uint32_t pnm_greymap ( uint32_t composite, unsigned int index __unused ){
-
- /* Composite value is an 8-bit greyscale value */
- return ( ( composite << 16 ) | ( composite << 8 ) | composite );
-}
-
-/**
- * Convert PNM pixmap composite value to RGB
- *
- * @v composite Composite value
- * @v index Pixel index within this composite value
- * @ret rgb 24-bit RGB value
- */
-static uint32_t pnm_pixmap ( uint32_t composite, unsigned int index __unused ) {
-
- /* Composite value is already an RGB value */
- return composite;
-}
-
-/**
- * Extract PNM pixel data
- *
- * @v image PNM image
- * @v pnm PNM context
- * @v pixbuf Pixel buffer
- * @ret rc Return status code
- */
-static int pnm_data ( struct image *image, struct pnm_context *pnm,
- struct pixel_buffer *pixbuf ) {
- struct pnm_type *type = pnm->type;
- size_t offset = 0;
- unsigned int xpos = 0;
- int scalar;
- uint32_t composite;
- uint32_t rgb;
- unsigned int i;
-
- /* Fill pixel buffer */
- while ( offset < pixbuf->len ) {
-
- /* Extract a scaled composite scalar value from the file */
- composite = 0;
- for ( i = 0 ; i < type->depth ; i++ ) {
- scalar = type->scalar ( image, pnm );
- if ( scalar < 0 )
- return scalar;
- scalar = pnm_scale ( image, pnm, scalar );
- if ( scalar < 0 )
- return scalar;
- composite = ( ( composite << 8 ) | scalar );
- }
-
- /* Extract 24-bit RGB values from composite value */
- for ( i = 0 ; i < type->packing ; i++ ) {
- if ( offset >= pixbuf->len ) {
- DBGC ( image, "PNM %s has too many pixels\n",
- image->name );
- return -EINVAL;
- }
- rgb = type->rgb ( composite, i );
- copy_to_user ( pixbuf->data, offset, &rgb,
- sizeof ( rgb ) );
- offset += sizeof ( rgb );
- if ( ++xpos == pixbuf->width ) {
- xpos = 0;
- break;
- }
- }
- }
-
- return 0;
-}
-
-/** PNM image types */
-static struct pnm_type pnm_types[] = {
- {
- .type = '1',
- .depth = 1,
- .packing = 1,
- .flags = PNM_BITMAP,
- .scalar = pnm_ascii,
- .rgb = pnm_bitmap,
- },
- {
- .type = '2',
- .depth = 1,
- .packing = 1,
- .scalar = pnm_ascii,
- .rgb = pnm_greymap,
- },
- {
- .type = '3',
- .depth = 3,
- .packing = 1,
- .scalar = pnm_ascii,
- .rgb = pnm_pixmap,
- },
- {
- .type = '4',
- .depth = 1,
- .packing = 8,
- .flags = PNM_BITMAP,
- .scalar = pnm_binary,
- .rgb = pnm_bitmap,
- },
- {
- .type = '5',
- .depth = 1,
- .packing = 1,
- .scalar = pnm_binary,
- .rgb = pnm_greymap,
- },
- {
- .type = '6',
- .depth = 3,
- .packing = 1,
- .scalar = pnm_binary,
- .rgb = pnm_pixmap,
- },
-};
-
-/**
- * Determine PNM image type
- *
- * @v image PNM image
- * @ret type PNM image type, or NULL if not found
- */
-static struct pnm_type * pnm_type ( struct image *image ) {
- struct pnm_signature signature;
- struct pnm_type *type;
- unsigned int i;
-
- /* Extract signature */
- assert ( image->len >= sizeof ( signature ) );
- copy_from_user ( &signature, image->data, 0, sizeof ( signature ) );
-
- /* Check for supported types */
- for ( i = 0 ; i < ( sizeof ( pnm_types ) /
- sizeof ( pnm_types[0] ) ) ; i++ ) {
- type = &pnm_types[i];
- if ( type->type == signature.type )
- return type;
- }
- return NULL;
-}
-
-/**
- * Convert PNM image to pixel buffer
- *
- * @v image PNM image
- * @v pixbuf Pixel buffer to fill in
- * @ret rc Return status code
- */
-static int pnm_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) {
- struct pnm_context pnm;
- int width;
- int height;
- int max;
- int rc;
-
- /* Initialise PNM context */
- pnm.type = pnm_type ( image );
- if ( ! pnm.type ) {
- rc = -ENOTSUP;
- goto err_type;
- }
- pnm.offset = sizeof ( struct pnm_signature );
- pnm.ascii_len = PNM_ASCII_LEN;
-
- /* Extract width */
- if ( ( width = pnm_ascii ( image, &pnm ) ) < 0 ) {
- rc = width;
- goto err_width;
- }
-
- /* Extract height */
- if ( ( height = pnm_ascii ( image, &pnm ) ) < 0 ) {
- rc = height;
- goto err_height;
- }
-
- /* Extract maximum scalar value, if not predefined */
- if ( pnm.type->flags & PNM_BITMAP ) {
- pnm.max = ( ( 1 << pnm.type->packing ) - 1 );
- pnm.ascii_len = 1;
- } else {
- if ( ( max = pnm_ascii ( image, &pnm ) ) < 0 ) {
- rc = max;
- goto err_max;
- }
- pnm.max = max;
- }
- if ( pnm.max == 0 ) {
- DBGC ( image, "PNM %s has invalid maximum value 0\n",
- image->name );
- rc = -EINVAL;
- goto err_max;
- }
- DBGC ( image, "PNM %s is type %c width %d height %d max %d\n",
- image->name, pnm.type->type, width, height, pnm.max );
-
- /* Allocate pixel buffer */
- *pixbuf = alloc_pixbuf ( width, height );
- if ( ! *pixbuf ) {
- rc = -ENOMEM;
- goto err_alloc_pixbuf;
- }
-
- /* Extract pixel data */
- if ( ( rc = pnm_data ( image, &pnm, *pixbuf ) ) != 0 )
- goto err_data;
-
- return 0;
-
- err_data:
- pixbuf_put ( *pixbuf );
- err_alloc_pixbuf:
- err_max:
- err_height:
- err_width:
- err_type:
- return rc;
-}
-
-/**
- * Probe PNM image
- *
- * @v image PNM image
- * @ret rc Return status code
- */
-static int pnm_probe ( struct image *image ) {
- struct pnm_signature signature;
-
- /* Sanity check */
- if ( image->len < sizeof ( signature ) ) {
- DBGC ( image, "PNM %s is too short\n", image->name );
- return -ENOEXEC;
- }
-
- /* Check signature */
- copy_from_user ( &signature, image->data, 0, sizeof ( signature ) );
- if ( ! ( ( signature.magic == PNM_MAGIC ) &&
- ( isdigit ( signature.type ) ) &&
- ( isspace ( signature.space ) ) ) ) {
- DBGC ( image, "PNM %s has invalid signature\n", image->name );
- return -ENOEXEC;
- }
- DBGC ( image, "PNM %s is type %c\n", image->name, signature.type );
-
- return 0;
-}
-
-/** PNM image type */
-struct image_type pnm_image_type __image_type ( PROBE_NORMAL ) = {
- .name = "PNM",
- .probe = pnm_probe,
- .pixbuf = pnm_pixbuf,
-};
diff --git a/qemu/roms/ipxe/src/image/script.c b/qemu/roms/ipxe/src/image/script.c
deleted file mode 100644
index 28050868a..000000000
--- a/qemu/roms/ipxe/src/image/script.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/**
- * @file
- *
- * iPXE scripts
- *
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-#include <getopt.h>
-#include <ipxe/command.h>
-#include <ipxe/parseopt.h>
-#include <ipxe/image.h>
-#include <ipxe/shell.h>
-#include <usr/prompt.h>
-#include <ipxe/script.h>
-
-/** Offset within current script
- *
- * This is a global in order to allow goto_exec() to update the
- * offset.
- */
-static size_t script_offset;
-
-/**
- * Process script lines
- *
- * @v image Script
- * @v process_line Line processor
- * @v terminate Termination check
- * @ret rc Return status code
- */
-static int process_script ( struct image *image,
- int ( * process_line ) ( struct image *image,
- size_t offset,
- const char *label,
- const char *command ),
- int ( * terminate ) ( int rc ) ) {
- size_t len = 0;
- char *line = NULL;
- size_t line_offset;
- char *label;
- char *command;
- off_t eol;
- size_t frag_len;
- char *tmp;
- int rc;
-
- /* Initialise script and line offsets */
- script_offset = 0;
- line_offset = 0;
-
- do {
-
- /* Find length of next line, excluding any terminating '\n' */
- eol = memchr_user ( image->data, script_offset, '\n',
- ( image->len - script_offset ) );
- if ( eol < 0 )
- eol = image->len;
- frag_len = ( eol - script_offset );
-
- /* Allocate buffer for line */
- tmp = realloc ( line, ( len + frag_len + 1 /* NUL */ ) );
- if ( ! tmp ) {
- rc = -ENOMEM;
- goto err_alloc;
- }
- line = tmp;
-
- /* Copy line */
- copy_from_user ( ( line + len ), image->data, script_offset,
- frag_len );
- len += frag_len;
-
- /* Move to next line in script */
- script_offset += ( frag_len + 1 );
-
- /* Strip trailing CR, if present */
- if ( len && ( line[ len - 1 ] == '\r' ) )
- len--;
-
- /* Handle backslash continuations */
- if ( len && ( line[ len - 1 ] == '\\' ) ) {
- len--;
- rc = -EINVAL;
- continue;
- }
-
- /* Terminate line */
- line[len] = '\0';
-
- /* Split line into (optional) label and command */
- command = line;
- while ( isspace ( *command ) )
- command++;
- if ( *command == ':' ) {
- label = ++command;
- while ( *command && ! isspace ( *command ) )
- command++;
- if ( *command )
- *(command++) = '\0';
- } else {
- label = NULL;
- }
-
- /* Process line */
- rc = process_line ( image, line_offset, label, command );
- if ( terminate ( rc ) )
- goto err_process;
-
- /* Free line */
- free ( line );
- line = NULL;
- len = 0;
-
- /* Update line offset */
- line_offset = script_offset;
-
- } while ( script_offset < image->len );
-
- err_process:
- err_alloc:
- free ( line );
- return rc;
-}
-
-/**
- * Terminate script processing on shell exit or command failure
- *
- * @v rc Line processing status
- * @ret terminate Terminate script processing
- */
-static int terminate_on_exit_or_failure ( int rc ) {
-
- return ( shell_stopped ( SHELL_STOP_COMMAND_SEQUENCE ) ||
- ( rc != 0 ) );
-}
-
-/**
- * Execute script line
- *
- * @v image Script
- * @v offset Offset within script
- * @v label Label, or NULL
- * @v command Command
- * @ret rc Return status code
- */
-static int script_exec_line ( struct image *image, size_t offset,
- const char *label __unused,
- const char *command ) {
- int rc;
-
- DBGC ( image, "[%04zx] $ %s\n", offset, command );
-
- /* Execute command */
- if ( ( rc = system ( command ) ) != 0 )
- return rc;
-
- return 0;
-}
-
-/**
- * Execute script
- *
- * @v image Script
- * @ret rc Return status code
- */
-static int script_exec ( struct image *image ) {
- size_t saved_offset;
- int rc;
-
- /* Temporarily de-register image, so that a "boot" command
- * doesn't throw us into an execution loop.
- */
- unregister_image ( image );
-
- /* Preserve state of any currently-running script */
- saved_offset = script_offset;
-
- /* Process script */
- rc = process_script ( image, script_exec_line,
- terminate_on_exit_or_failure );
-
- /* Restore saved state */
- script_offset = saved_offset;
-
- /* Re-register image (unless we have been replaced) */
- if ( ! image->replacement )
- register_image ( image );
-
- return rc;
-}
-
-/**
- * Probe script image
- *
- * @v image Script
- * @ret rc Return status code
- */
-static int script_probe ( struct image *image ) {
- static const char ipxe_magic[] = "#!ipxe";
- static const char gpxe_magic[] = "#!gpxe";
- linker_assert ( sizeof ( ipxe_magic ) == sizeof ( gpxe_magic ),
- magic_size_mismatch );
- char test[ sizeof ( ipxe_magic ) - 1 /* NUL */
- + 1 /* terminating space */];
-
- /* Sanity check */
- if ( image->len < sizeof ( test ) ) {
- DBGC ( image, "Too short to be a script\n" );
- return -ENOEXEC;
- }
-
- /* Check for magic signature */
- copy_from_user ( test, image->data, 0, sizeof ( test ) );
- if ( ! ( ( ( memcmp ( test, ipxe_magic, sizeof ( test ) - 1 ) == 0 ) ||
- ( memcmp ( test, gpxe_magic, sizeof ( test ) - 1 ) == 0 )) &&
- isspace ( test[ sizeof ( test ) - 1 ] ) ) ) {
- DBGC ( image, "Invalid magic signature\n" );
- return -ENOEXEC;
- }
-
- return 0;
-}
-
-/** Script image type */
-struct image_type script_image_type __image_type ( PROBE_NORMAL ) = {
- .name = "script",
- .probe = script_probe,
- .exec = script_exec,
-};
-
-/** "goto" options */
-struct goto_options {};
-
-/** "goto" option list */
-static struct option_descriptor goto_opts[] = {};
-
-/** "goto" command descriptor */
-static struct command_descriptor goto_cmd =
- COMMAND_DESC ( struct goto_options, goto_opts, 1, 1, "<label>" );
-
-/**
- * Current "goto" label
- *
- * Valid only during goto_exec(). Consider this part of a closure.
- */
-static const char *goto_label;
-
-/**
- * Check for presence of label
- *
- * @v image Script
- * @v offset Offset within script
- * @v label Label
- * @v command Command
- * @ret rc Return status code
- */
-static int goto_find_label ( struct image *image, size_t offset,
- const char *label, const char *command __unused ) {
-
- /* Check label exists */
- if ( ! label )
- return -ENOENT;
-
- /* Check label matches */
- if ( strcmp ( goto_label, label ) != 0 )
- return -ENOENT;
-
- /* Update script offset */
- script_offset = offset;
- DBGC ( image, "[%04zx] Gone to :%s\n", offset, label );
-
- return 0;
-}
-
-/**
- * Terminate script processing when label is found
- *
- * @v rc Line processing status
- * @ret terminate Terminate script processing
- */
-static int terminate_on_label_found ( int rc ) {
- return ( rc == 0 );
-}
-
-/**
- * "goto" command
- *
- * @v argc Argument count
- * @v argv Argument list
- * @ret rc Return status code
- */
-static int goto_exec ( int argc, char **argv ) {
- struct goto_options opts;
- size_t saved_offset;
- int rc;
-
- /* Parse options */
- if ( ( rc = parse_options ( argc, argv, &goto_cmd, &opts ) ) != 0 )
- return rc;
-
- /* Sanity check */
- if ( ! current_image ) {
- rc = -ENOTTY;
- printf ( "Not in a script: %s\n", strerror ( rc ) );
- return rc;
- }
-
- /* Parse label */
- goto_label = argv[optind];
-
- /* Find label */
- saved_offset = script_offset;
- if ( ( rc = process_script ( current_image, goto_find_label,
- terminate_on_label_found ) ) != 0 ) {
- script_offset = saved_offset;
- DBGC ( current_image, "[%04zx] No such label :%s\n",
- script_offset, goto_label );
- return rc;
- }
-
- /* Terminate processing of current command */
- shell_stop ( SHELL_STOP_COMMAND );
-
- return 0;
-}
-
-/** "goto" command */
-struct command goto_command __command = {
- .name = "goto",
- .exec = goto_exec,
-};
-
-/** "prompt" options */
-struct prompt_options {
- /** Key to wait for */
- unsigned int key;
- /** Timeout */
- unsigned long timeout;
-};
-
-/** "prompt" option list */
-static struct option_descriptor prompt_opts[] = {
- OPTION_DESC ( "key", 'k', required_argument,
- struct prompt_options, key, parse_key ),
- OPTION_DESC ( "timeout", 't', required_argument,
- struct prompt_options, timeout, parse_timeout ),
-};
-
-/** "prompt" command descriptor */
-static struct command_descriptor prompt_cmd =
- COMMAND_DESC ( struct prompt_options, prompt_opts, 0, MAX_ARGUMENTS,
- "[<text>]" );
-
-/**
- * "prompt" command
- *
- * @v argc Argument count
- * @v argv Argument list
- * @ret rc Return status code
- */
-static int prompt_exec ( int argc, char **argv ) {
- struct prompt_options opts;
- char *text;
- int rc;
-
- /* Parse options */
- if ( ( rc = parse_options ( argc, argv, &prompt_cmd, &opts ) ) != 0 )
- goto err_parse;
-
- /* Parse prompt text */
- text = concat_args ( &argv[optind] );
- if ( ! text ) {
- rc = -ENOMEM;
- goto err_concat;
- }
-
- /* Display prompt and wait for key */
- if ( ( rc = prompt ( text, opts.timeout, opts.key ) ) != 0 )
- goto err_prompt;
-
- /* Free prompt text */
- free ( text );
-
- return 0;
-
- err_prompt:
- free ( text );
- err_concat:
- err_parse:
- return rc;
-}
-
-/** "prompt" command */
-struct command prompt_command __command = {
- .name = "prompt",
- .exec = prompt_exec,
-};
diff --git a/qemu/roms/ipxe/src/image/segment.c b/qemu/roms/ipxe/src/image/segment.c
deleted file mode 100644
index 2d0f2f0fc..000000000
--- a/qemu/roms/ipxe/src/image/segment.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/**
- * @file
- *
- * Executable image segments
- *
- */
-
-#include <errno.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/io.h>
-#include <ipxe/errortab.h>
-#include <ipxe/segment.h>
-
-/**
- * Segment-specific error messages
- *
- * This error happens sufficiently often to merit a user-friendly
- * description.
- */
-#define ERANGE_SEGMENT __einfo_error ( EINFO_ERANGE_SEGMENT )
-#define EINFO_ERANGE_SEGMENT \
- __einfo_uniqify ( EINFO_ERANGE, 0x01, "Requested memory not available" )
-struct errortab segment_errors[] __errortab = {
- __einfo_errortab ( EINFO_ERANGE_SEGMENT ),
-};
-
-/**
- * Prepare segment for loading
- *
- * @v segment Segment start
- * @v filesz Size of the "allocated bytes" portion of the segment
- * @v memsz Size of the segment
- * @ret rc Return status code
- */
-int prep_segment ( userptr_t segment, size_t filesz, size_t memsz ) {
- struct memory_map memmap;
- physaddr_t start = user_to_phys ( segment, 0 );
- physaddr_t mid = user_to_phys ( segment, filesz );
- physaddr_t end = user_to_phys ( segment, memsz );
- unsigned int i;
-
- DBG ( "Preparing segment [%lx,%lx,%lx)\n", start, mid, end );
-
- /* Sanity check */
- if ( filesz > memsz ) {
- DBG ( "Insane segment [%lx,%lx,%lx)\n", start, mid, end );
- return -EINVAL;
- }
-
- /* Get a fresh memory map. This allows us to automatically
- * avoid treading on any regions that Etherboot is currently
- * editing out of the memory map.
- */
- get_memmap ( &memmap );
-
- /* Look for a suitable memory region */
- for ( i = 0 ; i < memmap.count ; i++ ) {
- if ( ( start >= memmap.regions[i].start ) &&
- ( end <= memmap.regions[i].end ) ) {
- /* Found valid region: zero bss and return */
- memset_user ( segment, filesz, 0, ( memsz - filesz ) );
- return 0;
- }
- }
-
- /* No suitable memory region found */
- DBG ( "Segment [%lx,%lx,%lx) does not fit into available memory\n",
- start, mid, end );
- return -ERANGE_SEGMENT;
-}