From bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 Mon Sep 17 00:00:00 2001 From: RajithaY Date: Tue, 25 Apr 2017 03:31:15 -0700 Subject: Adding qemu as a submodule of KVMFORNFV This Patch includes the changes to add qemu as a submodule to kvmfornfv repo and make use of the updated latest qemu for the execution of all testcase Change-Id: I1280af507a857675c7f81d30c95255635667bdd7 Signed-off-by:RajithaY --- qemu/roms/ipxe/src/image/efi_image.c | 316 ----------- qemu/roms/ipxe/src/image/elf.c | 226 -------- qemu/roms/ipxe/src/image/embedded.c | 91 --- qemu/roms/ipxe/src/image/png.c | 1011 ---------------------------------- qemu/roms/ipxe/src/image/pnm.c | 419 -------------- qemu/roms/ipxe/src/image/script.c | 427 -------------- qemu/roms/ipxe/src/image/segment.c | 95 ---- 7 files changed, 2585 deletions(-) delete mode 100644 qemu/roms/ipxe/src/image/efi_image.c delete mode 100644 qemu/roms/ipxe/src/image/elf.c delete mode 100644 qemu/roms/ipxe/src/image/embedded.c delete mode 100644 qemu/roms/ipxe/src/image/png.c delete mode 100644 qemu/roms/ipxe/src/image/pnm.c delete mode 100644 qemu/roms/ipxe/src/image/script.c delete mode 100644 qemu/roms/ipxe/src/image/segment.c (limited to 'qemu/roms/ipxe/src/image') 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 . - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 . - * - * 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 -#include -#include -#include -#include -#include - -/** - * 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 -#include -#include -#include - -/* 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 . - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -/** @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 ( ¤t, png->raw.data, - offset, sizeof ( current ) ); - current = filter->unfilter ( current, left, above, - above_left ); - copy_to_user ( png->raw.data, offset++, - ¤t, 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 ( ¤t, - 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 . - * - * 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 -#include -#include -#include -#include -#include - -/** - * 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 . - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** 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, "