Changes of Revision 27
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/Makefile |
@@ -108,7 +108,11 @@ # helpfully suggestive message # ALL := bin/blib.a bin/ipxe.dsk bin/ipxe.lkrn bin/ipxe.iso \ - bin/ipxe.usb bin/ipxe.pxe bin/undionly.kpxe bin/rtl8139.rom + bin/ipxe.usb bin/ipxe.pxe bin/undionly.kpxe bin/rtl8139.rom \ + bin/8086100e.mrom bin/80861209.rom bin/10500940.rom \ + bin/10222000.rom bin/10ec8139.rom bin/1af41000.rom \ + bin/8086100f.mrom bin/808610d3.mrom bin/15ad07b0.rom + all : $(ALL) @$(ECHO) '===========================================================' @$(ECHO) | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/image/multiboot.c ^ |
@@ -152,8 +152,7 @@ size_t len; /* Copy image URI to base memory buffer as start of command line */ - len = ( unparse_uri ( buf, remaining, image->uri, - URI_ALL ) + 1 /* NUL */ ); + len = ( format_uri ( image->uri, buf, remaining ) + 1 /* NUL */ ); if ( len > remaining ) len = remaining; mb_cmdline_offset += len; | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/include/librm.h ^ |
@@ -88,6 +88,13 @@ trivial_memmove_user ( dest, dest_off, src, src_off, len ); } +static inline __always_inline int +UACCESS_INLINE ( librm, memcmp_user ) ( userptr_t first, off_t first_off, + userptr_t second, off_t second_off, + size_t len ) { + return trivial_memcmp_user ( first, first_off, second, second_off, len); +} + static inline __always_inline void UACCESS_INLINE ( librm, memset_user ) ( userptr_t buffer, off_t offset, int c, size_t len ) { | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/interface/pcbios/vesafb.c ^ |
@@ -76,6 +76,8 @@ physaddr_t start; /** Pixel geometry */ struct fbcon_geometry pixel; + /** Margin */ + struct fbcon_margin margin; /** Colour mapping */ struct fbcon_colour_map map; /** Font definition */ @@ -372,18 +374,35 @@ } /** + * Restore video mode + * + */ +static void vesafb_restore ( void ) { + uint32_t discard_a; + + /* Restore saved VGA mode */ + __asm__ __volatile__ ( REAL_CODE ( "int $0x10" ) + : "=a" ( discard_a ) + : "a" ( VBE_SET_VGA_MODE | vesafb.saved_mode ) ); + DBGC ( &vbe_buf, "VESAFB restored VGA mode %#02x\n", + vesafb.saved_mode ); +} + +/** * Initialise VESA frame buffer * - * @v min_width Minimum required width (in pixels) - * @v min_height Minimum required height (in pixels) - * @v min_bpp Minimum required colour depth (in bits per pixel) - * @v pixbuf Background picture (if any) + * @v config Console configuration, or NULL to reset * @ret rc Return status code */ -static int vesafb_init ( unsigned int min_width, unsigned int min_height, - unsigned int min_bpp, struct pixel_buffer *pixbuf ) { +static int vesafb_init ( struct console_configuration *config ) { uint32_t discard_b; uint16_t *mode_numbers; + unsigned int xgap; + unsigned int ygap; + unsigned int left; + unsigned int right; + unsigned int top; + unsigned int bottom; int mode_number; int rc; @@ -398,8 +417,9 @@ goto err_mode_list; /* Select mode */ - if ( ( mode_number = vesafb_select_mode ( mode_numbers, min_width, - min_height, min_bpp ) ) < 0 ){ + if ( ( mode_number = vesafb_select_mode ( mode_numbers, config->width, + config->height, + config->depth ) ) < 0 ) { rc = mode_number; goto err_select_mode; } @@ -408,14 +428,40 @@ if ( ( rc = vesafb_set_mode ( mode_number ) ) != 0 ) goto err_set_mode; + /* Calculate margin. If the actual screen size is larger than + * the requested screen size, then update the margins so that + * the margin remains relative to the requested screen size. + * (As an exception, if a zero margin was specified then treat + * this as meaning "expand to edge of actual screen".) + */ + xgap = ( vesafb.pixel.width - config->width ); + ygap = ( vesafb.pixel.height - config->height ); + left = ( xgap / 2 ); + right = ( xgap - left ); + top = ( ygap / 2 ); + bottom = ( ygap - top ); + vesafb.margin.left = ( config->left + ( config->left ? left : 0 ) ); + vesafb.margin.right = ( config->right + ( config->right ? right : 0 ) ); + vesafb.margin.top = ( config->top + ( config->top ? top : 0 ) ); + vesafb.margin.bottom = + ( config->bottom + ( config->bottom ? bottom : 0 ) ); + /* Get font data */ vesafb_font(); /* Initialise frame buffer console */ - fbcon_init ( &vesafb.fbcon, phys_to_user ( vesafb.start ), - &vesafb.pixel, &vesafb.map, &vesafb.font, pixbuf ); + if ( ( rc = fbcon_init ( &vesafb.fbcon, phys_to_user ( vesafb.start ), + &vesafb.pixel, &vesafb.margin, &vesafb.map, + &vesafb.font, config->pixbuf ) ) != 0 ) + goto err_fbcon_init; + + free ( mode_numbers ); + return 0; + fbcon_fini ( &vesafb.fbcon ); + err_fbcon_init: err_set_mode: + vesafb_restore(); err_select_mode: free ( mode_numbers ); err_mode_list: @@ -427,17 +473,12 @@ * */ static void vesafb_fini ( void ) { - uint32_t discard_a; /* Finalise frame buffer console */ fbcon_fini ( &vesafb.fbcon ); - /* Restore VGA mode */ - __asm__ __volatile__ ( REAL_CODE ( "int $0x10" ) - : "=a" ( discard_a ) - : "a" ( VBE_SET_VGA_MODE | vesafb.saved_mode ) ); - DBGC ( &vbe_buf, "VESAFB restored VGA mode %#02x\n", - vesafb.saved_mode ); + /* Restore saved VGA mode */ + vesafb_restore(); } /** @@ -474,8 +515,7 @@ } /* Initialise VESA frame buffer */ - if ( ( rc = vesafb_init ( config->width, config->height, config->bpp, - config->pixbuf ) ) != 0 ) + if ( ( rc = vesafb_init ( config ) ) != 0 ) return rc; /* Mark console as enabled */ | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/config/config.c ^ |
@@ -200,6 +200,9 @@ #ifdef IMAGE_PNM REQUIRE_OBJECT ( pnm ); #endif +#ifdef IMAGE_PNG +REQUIRE_OBJECT ( png ); +#endif /* * Drag in all requested commands | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/config/general.h ^ |
@@ -104,6 +104,7 @@ //#define IMAGE_EFI /* EFI image support */ //#define IMAGE_SDI /* SDI image support */ //#define IMAGE_PNM /* PNM image support */ +//#define IMAGE_PNG /* PNG image support */ /* * Command-line commands to include | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/debug.c ^ |
@@ -22,6 +22,7 @@ #include <stdio.h> #include <stdint.h> #include <stdarg.h> +#include <ctype.h> #include <ipxe/console.h> /** @@ -96,9 +97,7 @@ continue; } byte = bytes[i]; - if ( ( byte < 0x20 ) || ( byte >= 0x7f ) ) - byte = '.'; - dbg_printf ( "%c", byte ); + dbg_printf ( "%c", ( isprint ( byte ) ? byte : '.' ) ); } dbg_printf ( "\n" ); } | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/downloader.c ^ |
@@ -20,7 +20,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stdlib.h> -#include <stdarg.h> #include <errno.h> #include <syslog.h> #include <ipxe/iobuf.h> @@ -229,17 +228,13 @@ * * @v job Job control interface * @v image Image to fill with downloaded file - * @v type Location type to pass to xfer_open() - * @v ... Remaining arguments to pass to xfer_open() * @ret rc Return status code * - * Instantiates a downloader object to download the specified URI into - * the specified image object. + * Instantiates a downloader object to download the content of the + * specified image from its URI. */ -int create_downloader ( struct interface *job, struct image *image, - int type, ... ) { +int create_downloader ( struct interface *job, struct image *image ) { struct downloader *downloader; - va_list args; int rc; /* Allocate and initialise structure */ @@ -252,21 +247,18 @@ intf_init ( &downloader->xfer, &downloader_xfer_desc, &downloader->refcnt ); downloader->image = image_get ( image ); - va_start ( args, type ); /* Instantiate child objects and attach to our interfaces */ - if ( ( rc = xfer_vopen ( &downloader->xfer, type, args ) ) != 0 ) + if ( ( rc = xfer_open_uri ( &downloader->xfer, image->uri ) ) != 0 ) goto err; /* Attach parent interface, mortalise self, and return */ intf_plug_plug ( &downloader->job, job ); ref_put ( &downloader->refcnt ); - va_end ( args ); return 0; err: downloader_finished ( downloader, rc ); ref_put ( &downloader->refcnt ); - va_end ( args ); return rc; } | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/fbcon.c ^ |
@@ -99,6 +99,32 @@ } /** + * Clear rows of characters + * + * @v fbcon Frame buffer console + * @v ypos Starting Y position + */ +static void fbcon_clear ( struct fbcon *fbcon, unsigned int ypos ) { + struct fbcon_text_cell cell = { + .foreground = fbcon->foreground, + .background = fbcon->background, + .character = ' ', + }; + size_t offset; + unsigned int xpos; + + /* Clear stored character array */ + for ( ; ypos < fbcon->character.height ; ypos++ ) { + offset = ( ypos * fbcon->character.width * sizeof ( cell ) ); + for ( xpos = 0 ; xpos < fbcon->character.width ; xpos++ ) { + copy_to_user ( fbcon->text.start, offset, &cell, + sizeof ( cell ) ); + offset += sizeof ( cell ); + } + } +} + +/** * Store character at specified position * * @v fbcon Frame buffer console @@ -106,9 +132,8 @@ * @v xpos X position * @v ypos Y position */ -static void fbcon_store_character ( struct fbcon *fbcon, - struct fbcon_text_cell *cell, - unsigned int xpos, unsigned int ypos ) { +static void fbcon_store ( struct fbcon *fbcon, struct fbcon_text_cell *cell, + unsigned int xpos, unsigned int ypos ) { size_t offset; /* Store cell */ @@ -125,14 +150,9 @@ * @v xpos X position * @v ypos Y position */ -static void fbcon_draw_character ( struct fbcon *fbcon, - struct fbcon_text_cell *cell, - unsigned int xpos, unsigned int ypos ) { - static uint32_t black[FBCON_CHAR_WIDTH]; +static void fbcon_draw ( struct fbcon *fbcon, struct fbcon_text_cell *cell, + unsigned int xpos, unsigned int ypos ) { struct fbcon_font_glyph glyph; - userptr_t picture_start; - size_t picture_offset; - size_t picture_stride; size_t offset; size_t pixel_len; size_t skip_len; @@ -154,30 +174,23 @@ pixel_len = fbcon->pixel->len; skip_len = ( fbcon->pixel->stride - fbcon->character.len ); - /* Calculate background picture geometry */ - if ( ( xpos < fbcon->picture.character.width ) && - ( ypos < fbcon->picture.character.height ) ) { - picture_start = fbcon->picture.start; - picture_offset = ( fbcon->picture.indent + - ( ypos * fbcon->picture.character.stride ) + - ( xpos * fbcon->picture.character.len ) ); - picture_stride = fbcon->picture.pixel.stride; - } else { - picture_start = virt_to_user ( black ); - picture_offset = 0; - picture_stride = 0; - } - assert ( fbcon->character.len <= sizeof ( black ) ); - /* Check for transparent background colour */ transparent = ( cell->background == FBCON_TRANSPARENT ); /* Draw character rows */ for ( row = 0 ; row < FBCON_CHAR_HEIGHT ; row++ ) { - /* Draw background picture */ - memcpy_user ( fbcon->start, offset, picture_start, - picture_offset, fbcon->character.len ); + /* Draw background picture, if applicable */ + if ( transparent ) { + if ( fbcon->picture.start ) { + memcpy_user ( fbcon->start, offset, + fbcon->picture.start, offset, + fbcon->character.len ); + } else { + memset_user ( fbcon->start, offset, 0, + fbcon->character.len ); + } + } /* Draw character row */ for ( column = FBCON_CHAR_WIDTH, bitmask = glyph.bitmask[row] ; @@ -194,63 +207,15 @@ /* Move to next row */ offset += skip_len; - picture_offset += picture_stride; - } -} - -/** - * Redraw margins - * - * @v fbcon Frame buffer console - */ -static void fbcon_redraw_margins ( struct fbcon *fbcon ) { - struct fbcon_picture *picture = &fbcon->picture; - size_t pixel_len = fbcon->pixel->len; - size_t offset = 0; - size_t picture_offset = 0; - size_t row_len; - size_t left_len; - size_t right_len; - size_t right_offset; - unsigned int y; - - /* Calculate margin parameters */ - row_len = ( picture->pixel.width * pixel_len ); - left_len = ( picture->margin.left * pixel_len ); - right_offset = ( picture->margin.right * pixel_len ); - right_len = ( ( picture->pixel.width - picture->margin.right ) * - pixel_len ); - - /* Redraw margins */ - for ( y = 0 ; y < picture->pixel.height ; y++ ) { - if ( ( y < picture->margin.top ) || - ( y >= picture->margin.bottom ) ) { - - /* Within top or bottom margin: draw whole row */ - memcpy_user ( fbcon->start, offset, picture->start, - picture_offset, row_len ); - - } else { - - /* Otherwise, draw left and right margins */ - memcpy_user ( fbcon->start, offset, picture->start, - picture_offset, left_len ); - memcpy_user ( fbcon->start, ( offset + right_offset ), - picture->start, - ( picture_offset + right_offset ), - right_len ); - } - offset += fbcon->pixel->stride; - picture_offset += picture->pixel.stride; } } /** - * Redraw characters + * Redraw all characters * * @v fbcon Frame buffer console */ -static void fbcon_redraw_characters ( struct fbcon *fbcon ) { +static void fbcon_redraw ( struct fbcon *fbcon ) { struct fbcon_text_cell cell; size_t offset = 0; unsigned int xpos; @@ -261,53 +226,10 @@ for ( xpos = 0 ; xpos < fbcon->character.width ; xpos++ ) { copy_from_user ( &cell, fbcon->text.start, offset, sizeof ( cell ) ); - fbcon_draw_character ( fbcon, &cell, xpos, ypos ); - offset += sizeof ( cell ); - } - } -} - -/** - * Redraw screen - * - * @v fbcon Frame buffer console - */ -static void fbcon_redraw ( struct fbcon *fbcon ) { - - /* Redraw margins */ - fbcon_redraw_margins ( fbcon ); - - /* Redraw characters */ - fbcon_redraw_characters ( fbcon ); -} - -/** - * Clear portion of screen - * - * @v fbcon Frame buffer console - * @v ypos Starting Y position - */ -static void fbcon_clear ( struct fbcon *fbcon, unsigned int ypos ) { - struct fbcon_text_cell cell = { - .foreground = fbcon->foreground, - .background = fbcon->background, - .character = ' ', - }; - size_t offset; - unsigned int xpos; - - /* Clear stored character array */ - for ( ; ypos < fbcon->character.height ; ypos++ ) { - offset = ( ypos * fbcon->character.width * sizeof ( cell ) ); - for ( xpos = 0 ; xpos < fbcon->character.width ; xpos++ ) { - copy_to_user ( fbcon->text.start, offset, &cell, - sizeof ( cell ) ); + fbcon_draw ( fbcon, &cell, xpos, ypos ); offset += sizeof ( cell ); } } - - /* Redraw screen */ - fbcon_redraw ( fbcon ); } /** @@ -329,6 +251,9 @@ /* Update cursor position */ fbcon->ypos--; + + /* Redraw all characters */ + fbcon_redraw ( fbcon ); } /** @@ -349,7 +274,7 @@ cell.foreground = ( ( fbcon->background == FBCON_TRANSPARENT ) ? 0 : fbcon->background ); } - fbcon_draw_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos ); + fbcon_draw ( fbcon, &cell, fbcon->xpos, fbcon->ypos ); } /** @@ -369,10 +294,10 @@ fbcon_draw_cursor ( fbcon, 0 ); fbcon->xpos = cx; if ( fbcon->xpos >= fbcon->character.width ) - fbcon->xpos = ( fbcon->character.width - 1 ); + fbcon->xpos = 0; fbcon->ypos = cy; if ( fbcon->ypos >= fbcon->character.height ) - fbcon->ypos = ( fbcon->character.height - 1 ); + fbcon->ypos = 0; fbcon_draw_cursor ( fbcon, fbcon->show_cursor ); } @@ -391,9 +316,12 @@ /* We assume that we always clear the whole screen */ assert ( params[0] == ANSIESC_ED_ALL ); - /* Clear screen */ + /* Clear character array */ fbcon_clear ( fbcon, 0 ); + /* Redraw all characters */ + fbcon_redraw ( fbcon ); + /* Reset cursor position */ fbcon->xpos = 0; fbcon->ypos = 0; @@ -541,8 +469,8 @@ cell.foreground = ( fbcon->foreground | fbcon->bold ); cell.background = fbcon->background; cell.character = character; - fbcon_store_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos); - fbcon_draw_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos ); + fbcon_store ( fbcon, &cell, fbcon->xpos, fbcon->ypos ); + fbcon_draw ( fbcon, &cell, fbcon->xpos, fbcon->ypos ); /* Advance cursor */ fbcon->xpos++; @@ -562,72 +490,6 @@ } /** - * Calculate character geometry from pixel geometry - * - * @v pixel Pixel geometry - * @v character Character geometry to fill in - */ -static void fbcon_char_geometry ( const struct fbcon_geometry *pixel, - struct fbcon_geometry *character ) { - - character->width = ( pixel->width / FBCON_CHAR_WIDTH ); - character->height = ( pixel->height / FBCON_CHAR_HEIGHT ); - character->len = ( pixel->len * FBCON_CHAR_WIDTH ); - character->stride = ( pixel->stride * FBCON_CHAR_HEIGHT ); -} - -/** - * Calculate margins from pixel geometry - * - * @v pixel Pixel geometry - * @v margin Margins to fill in - */ -static void fbcon_margin ( const struct fbcon_geometry *pixel, - struct fbcon_margin *margin ) { - unsigned int xgap; - unsigned int ygap; - - xgap = ( pixel->width % FBCON_CHAR_WIDTH ); - ygap = ( pixel->height % FBCON_CHAR_HEIGHT ); - margin->left = ( xgap / 2 ); - margin->top = ( ygap / 2 ); - margin->right = ( pixel->width - ( xgap - margin->left ) ); - margin->bottom = ( pixel->height - ( ygap - margin->top ) ); -} - -/** - * Align to first indented boundary - * - * @v value Original value - * @v blocksize Block size - * @v indent Indent - * @v max Maximum allowed value - * @ret value Aligned value - */ -static unsigned int fbcon_align ( unsigned int value, unsigned int blocksize, - unsigned int indent, unsigned int max ) { - unsigned int overhang; - - /* Special case: 0 is always a boundary regardless of the indent */ - if ( value == 0 ) - return value; - - /* Special case: first boundary is the indent */ - if ( value < indent ) - return indent; - - /* Round up to next indented boundary */ - overhang = ( ( value - indent ) % blocksize ); - value = ( value + ( ( blocksize - overhang ) % blocksize ) ); - - /* Limit to maximum value */ - if ( value > max ) - value = max; - - return value; -} - -/** * Initialise background picture * * @v fbcon Frame buffer console @@ -636,52 +498,26 @@ */ static int fbcon_picture_init ( struct fbcon *fbcon, struct pixel_buffer *pixbuf ) { + struct fbcon_geometry *pixel = fbcon->pixel; struct fbcon_picture *picture = &fbcon->picture; - size_t pixel_len = fbcon->pixel->len; size_t len; + size_t pixbuf_stride; + size_t indent; + size_t pixbuf_indent; size_t offset; size_t pixbuf_offset; uint32_t rgb; uint32_t raw; unsigned int x; unsigned int y; + unsigned int width; + unsigned int height; + int xgap; + int ygap; int rc; - /* Calculate pixel geometry */ - picture->pixel.width = fbcon_align ( pixbuf->width, FBCON_CHAR_WIDTH, - fbcon->margin.left, - fbcon->pixel->width ); - picture->pixel.height = fbcon_align ( pixbuf->height, FBCON_CHAR_HEIGHT, - fbcon->margin.top, - fbcon->pixel->height ); - picture->pixel.len = pixel_len; - picture->pixel.stride = ( picture->pixel.width * picture->pixel.len ); - - /* Calculate character geometry */ - fbcon_char_geometry ( &picture->pixel, &picture->character ); - - /* Calculate margins */ - memcpy ( &picture->margin, &fbcon->margin, sizeof ( picture->margin ) ); - if ( picture->margin.left > picture->pixel.width ) - picture->margin.left = picture->pixel.width; - if ( picture->margin.top > picture->pixel.height ) - picture->margin.top = picture->pixel.height; - if ( picture->margin.right > picture->pixel.width ) - picture->margin.right = picture->pixel.width; - if ( picture->margin.bottom > picture->pixel.height ) - picture->margin.bottom = picture->pixel.height; - picture->indent = ( ( picture->margin.top * picture->pixel.stride ) + - ( picture->margin.left * picture->pixel.len ) ); - DBGC ( fbcon, "FBCON %p picture is pixel %dx%d, char %dx%d at " - "[%d-%d),[%d-%d)\n", fbcon, picture->pixel.width, - picture->pixel.height, picture->character.width, - picture->character.height, picture->margin.left, - picture->margin.right, picture->margin.top, - picture->margin.bottom ); - /* Allocate buffer */ - len = ( picture->pixel.width * picture->pixel.height * - picture->pixel.len ); + len = ( pixel->height * pixel->stride ); picture->start = umalloc ( len ); if ( ! picture->start ) { DBGC ( fbcon, "FBCON %p could not allocate %zd bytes for " @@ -690,20 +526,36 @@ goto err_umalloc; } + /* Centre picture on console */ + pixbuf_stride = ( pixbuf->width * sizeof ( rgb ) ); + xgap = ( ( ( int ) ( pixel->width - pixbuf->width ) ) / 2 ); + ygap = ( ( ( int ) ( pixel->height - pixbuf->height ) ) / 2 ); + indent = ( ( ( ( ygap >= 0 ) ? ygap : 0 ) * pixel->stride ) + + ( ( ( xgap >= 0 ) ? xgap : 0 ) * pixel->len ) ); + pixbuf_indent = ( ( ( ( ygap < 0 ) ? -ygap : 0 ) * pixbuf_stride ) + + ( ( ( xgap < 0 ) ? -xgap : 0 ) * sizeof ( rgb ) ) ); + width = pixbuf->width; + if ( width > pixel->width ) + width = pixel->width; + height = pixbuf->height; + if ( height > pixel->height ) + height = pixel->height; + DBGC ( fbcon, "FBCON %p picture is pixel %dx%d at [%d,%d),[%d,%d)\n", + fbcon, width, height, xgap, ( xgap + pixbuf->width ), ygap, + ( ygap + pixbuf->height ) ); + /* Convert to frame buffer raw format */ memset_user ( picture->start, 0, 0, len ); - pixbuf_offset = 0; - for ( y = 0 ; ( y < pixbuf->height ) && - ( y < picture->pixel.height ) ; y++ ) { - offset = ( y * picture->pixel.stride ); - pixbuf_offset = ( y * pixbuf->width * sizeof ( rgb ) ); - for ( x = 0 ; ( x < pixbuf->width ) && - ( x < picture->pixel.width ) ; x++ ) { + for ( y = 0 ; y < height ; y++ ) { + offset = ( indent + ( y * pixel->stride ) ); + pixbuf_offset = ( pixbuf_indent + ( y * pixbuf_stride ) ); + for ( x = 0 ; x < width ; x++ ) { copy_from_user ( &rgb, pixbuf->data, pixbuf_offset, sizeof ( rgb ) ); raw = fbcon_colour ( fbcon, rgb ); - copy_to_user ( picture->start, offset, &raw, pixel_len); - offset += pixel_len; + copy_to_user ( picture->start, offset, &raw, + pixel->len ); + offset += pixel->len; pixbuf_offset += sizeof ( rgb ); } } @@ -721,6 +573,7 @@ * @v fbcon Frame buffer console * @v start Start address * @v pixel Pixel geometry + * @v margin Minimum margin * @v map Colour mapping * @v font Font definition * @v pixbuf Background picture (if any) @@ -728,9 +581,14 @@ */ int fbcon_init ( struct fbcon *fbcon, userptr_t start, struct fbcon_geometry *pixel, + struct fbcon_margin *margin, struct fbcon_colour_map *map, struct fbcon_font *font, struct pixel_buffer *pixbuf ) { + int width; + int height; + unsigned int xgap; + unsigned int ygap; int rc; /* Initialise data structure */ @@ -749,22 +607,44 @@ user_to_phys ( fbcon->start, 0 ), user_to_phys ( fbcon->start, fbcon->len ) ); - /* Derive character geometry from pixel geometry */ - fbcon_char_geometry ( pixel, &fbcon->character ); - fbcon_margin ( pixel, &fbcon->margin ); + /* Expand margin to accommodate whole characters */ + width = ( pixel->width - margin->left - margin->right ); + height = ( pixel->height - margin->top - margin->bottom ); + if ( ( width < FBCON_CHAR_WIDTH ) || ( height < FBCON_CHAR_HEIGHT ) ) { + DBGC ( fbcon, "FBCON %p has unusable character area " + "[%d-%d),[%d-%d)\n", fbcon, + margin->left, ( pixel->width - margin->right ), + margin->top, ( pixel->height - margin->bottom ) ); + rc = -EINVAL; + goto err_margin; + } + xgap = ( width % FBCON_CHAR_WIDTH ); + ygap = ( height % FBCON_CHAR_HEIGHT ); + fbcon->margin.left = ( margin->left + ( xgap / 2 ) ); + fbcon->margin.top = ( margin->top + ( ygap / 2 ) ); + fbcon->margin.right = ( margin->right + ( xgap - ( xgap / 2 ) ) ); + fbcon->margin.bottom = ( margin->bottom + ( ygap - ( ygap / 2 ) ) ); fbcon->indent = ( ( fbcon->margin.top * pixel->stride ) + ( fbcon->margin.left * pixel->len ) ); + + /* Derive character geometry from pixel geometry */ + fbcon->character.width = ( width / FBCON_CHAR_WIDTH ); + fbcon->character.height = ( height / FBCON_CHAR_HEIGHT ); + fbcon->character.len = ( pixel->len * FBCON_CHAR_WIDTH ); + fbcon->character.stride = ( pixel->stride * FBCON_CHAR_HEIGHT ); DBGC ( fbcon, "FBCON %p is pixel %dx%d, char %dx%d at " "[%d-%d),[%d-%d)\n", fbcon, fbcon->pixel->width, fbcon->pixel->height, fbcon->character.width, - fbcon->character.height, fbcon->margin.left, fbcon->margin.right, - fbcon->margin.top, fbcon->margin.bottom ); + fbcon->character.height, fbcon->margin.left, + ( fbcon->pixel->width - fbcon->margin.right ), + fbcon->margin.top, + ( fbcon->pixel->height - fbcon->margin.bottom ) ); /* Set default colours */ fbcon_set_default_foreground ( fbcon ); fbcon_set_default_background ( fbcon ); - /* Allocate stored character array */ + /* Allocate and initialise stored character array */ fbcon->text.start = umalloc ( fbcon->character.width * fbcon->character.height * sizeof ( struct fbcon_text_cell ) ); @@ -772,13 +652,20 @@ rc = -ENOMEM; goto err_text; } + fbcon_clear ( fbcon, 0 ); + + /* Set framebuffer to all black (including margins) */ + memset_user ( fbcon->start, 0, 0, fbcon->len ); /* Generate pixel buffer from background image, if applicable */ if ( pixbuf && ( ( rc = fbcon_picture_init ( fbcon, pixbuf ) ) != 0 ) ) goto err_picture; - /* Clear screen */ - fbcon_clear ( fbcon, 0 ); + /* Draw background picture (including margins), if applicable */ + if ( fbcon->picture.start ) { + memcpy_user ( fbcon->start, 0, fbcon->picture.start, 0, + fbcon->len ); + } /* Update console width and height */ console_set_size ( fbcon->character.width, fbcon->character.height ); @@ -789,6 +676,7 @@ err_picture: ufree ( fbcon->text.start ); err_text: + err_margin: return rc; } | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/params.c ^ |
@@ -33,6 +33,29 @@ static LIST_HEAD ( parameters ); /** + * Free form parameter list + * + * @v refcnt Reference count + */ +static void free_parameters ( struct refcnt *refcnt ) { + struct parameters *params = + container_of ( refcnt, struct parameters, refcnt ); + struct parameter *param; + struct parameter *tmp; + + DBGC ( params, "PARAMS \"%s\" destroyed\n", params->name ); + + /* Free all parameters */ + list_for_each_entry_safe ( param, tmp, ¶ms->entries, list ) { + list_del ( ¶m->list ); + free ( param ); + } + + /* Free parameter list */ + free ( params ); +} + +/** * Find form parameter list by name * * @v name Parameter list name (may be NULL) @@ -63,14 +86,17 @@ /* Destroy any existing parameter list of this name */ params = find_parameters ( name ); - if ( params ) - destroy_parameters ( params ); + if ( params ) { + claim_parameters ( params ); + params_put ( params ); + } /* Allocate parameter list */ name_len = ( name ? ( strlen ( name ) + 1 /* NUL */ ) : 0 ); params = zalloc ( sizeof ( *params ) + name_len ); if ( ! params ) return NULL; + ref_init ( ¶ms->refcnt, free_parameters ); name_copy = ( ( void * ) ( params + 1 ) ); /* Populate parameter list */ @@ -125,41 +151,3 @@ params->name, param->key, param->value ); return param; } - -/** - * Destroy form parameter list - * - * @v params Parameter list - */ -void destroy_parameters ( struct parameters *params ) { - struct parameter *param; - struct parameter *tmp; - - DBGC ( params, "PARAMS \"%s\" destroyed\n", params->name ); - - /* Free all parameters */ - list_for_each_entry_safe ( param, tmp, ¶ms->entries, list ) { - list_del ( ¶m->list ); - free ( param ); - } - - /* Free parameter list */ - list_del ( ¶ms->list ); - free ( params ); -} - -/** - * Claim ownership of form parameter list - * - * @v params Parameter list - */ -void claim_parameters ( struct parameters *params ) { - - DBGC ( params, "PARAMS \"%s\" claimed\n", params->name ); - - /* Remove from list of parameter lists */ - list_del ( ¶ms->list ); - - /* Reinitialise list to allow for subsequent destroy_parameters() */ - INIT_LIST_HEAD ( ¶ms->list ); -} | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/settings.c ^ |
@@ -1658,59 +1658,15 @@ .format = format_string_setting, }; -/** - * Parse URI-encoded string setting value - * - * @v type Setting type - * @v value Formatted setting value - * @v buf Buffer to contain raw value - * @v len Length of buffer - * @ret len Length of raw value, or negative error - */ -static int parse_uristring_setting ( const struct setting_type *type __unused, - const char *value, void *buf, size_t len ){ - char tmp[ len + 1 /* NUL */ ]; - size_t raw_len; - - /* Decode to temporary buffer (including NUL) */ - raw_len = uri_decode ( value, tmp, sizeof ( tmp ) ); - - /* Copy to output buffer (excluding NUL) */ - if ( len > raw_len ) - len = raw_len; - memcpy ( buf, tmp, len ); - - return raw_len; -} - -/** - * Format URI-encoded string setting value +/** A URI-encoded string setting type * - * @v type Setting type - * @v raw Raw setting value - * @v raw_len Length of raw setting value - * @v buf Buffer to contain formatted value - * @v len Length of buffer - * @ret len Length of formatted value, or negative error + * This setting type is obsolete; the name ":uristring" is retained to + * avoid breaking existing scripts. */ -static int format_uristring_setting ( const struct setting_type *type __unused, - const void *raw, size_t raw_len, - char *buf, size_t len ) { - char tmp[ raw_len + 1 /* NUL */ ]; - - /* Copy to temporary buffer and terminate */ - memcpy ( tmp, raw, raw_len ); - tmp[raw_len] = '\0'; - - /* Encode directly into output buffer */ - return uri_encode ( tmp, buf, len, URI_FRAGMENT ); -} - -/** A URI-encoded string setting type */ const struct setting_type setting_type_uristring __setting_type = { .name = "uristring", - .parse = parse_uristring_setting, - .format = format_uristring_setting, + .parse = parse_string_setting, + .format = format_string_setting, }; /** | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/uri.c ^ |
@@ -35,33 +35,183 @@ #include <ipxe/uri.h> /** + * Decode URI field (in place) + * + * @v string String + * + * URI decoding can never increase the length of a string; we can + * therefore safely decode in place. + */ +static void uri_decode ( char *string ) { + char *dest = string; + char hexbuf[3]; + char *hexbuf_end; + char c; + char decoded; + unsigned int skip; + + /* Copy string, decoding escaped characters as necessary */ + do { + c = *(string++); + if ( c == '%' ) { + snprintf ( hexbuf, sizeof ( hexbuf ), "%s", string ); + decoded = strtoul ( hexbuf, &hexbuf_end, 16 ); + skip = ( hexbuf_end - hexbuf ); + string += skip; + if ( skip ) + c = decoded; + } + *(dest++) = c; + } while ( c ); +} + +/** + * Check if character should be escaped within a URI field + * + * @v c Character + * @v field URI field index + * @ret escaped Character should be escaped + */ +static int uri_character_escaped ( char c, unsigned int field ) { + + /* Non-printing characters and whitespace should always be + * escaped, since they cannot sensibly be displayed as part of + * a coherent URL string. (This test also catches control + * characters such as CR and LF, which could affect the + * operation of line-based protocols such as HTTP.) + * + * We should also escape characters which would alter the + * interpretation of the URL if not escaped, i.e. characters + * which have significance to the URL parser. We should not + * blindly escape all such characters, because this would lead + * to some very strange-looking URLs (e.g. if we were to + * always escape '/' as "%2F" even within the URI path). + * + * We do not need to be perfect. Our primary role is as a + * consumer of URIs rather than a producer; the main situation + * in which we produce a URI string is for display to a human + * user, who can probably tolerate some variance from the + * formal specification. The only situation in which we + * currently produce a URI string to be consumed by a computer + * is when constructing an HTTP request URI, which contains + * only the path and query fields. + * + * We can therefore sacrifice some correctness for the sake of + * code size. For example, colons within the URI host should + * be escaped unless they form part of an IPv6 literal + * address; doing this correctly would require the URI + * formatter to be aware of whether or not the URI host + * contained an IPv4 address, an IPv6 address, or a host name. + * We choose to simplify and never escape colons within the + * URI host field: in the event of a pathological hostname + * containing colons, this could potentially produce a URI + * string which could not be reparsed. + * + * After excluding non-printing characters, whitespace, and + * '%', the full set of characters with significance to the + * URL parser is "/#:@?". We choose for each URI field which + * of these require escaping in our use cases. + */ + static const char *escaped[URI_FIELDS] = { + /* Scheme: escape everything */ + [URI_SCHEME] = "/#:@?", + /* Opaque part: escape characters which would affect + * the reparsing of the URI, allowing everything else + * (e.g. ':', which will appear in iSCSI URIs). + */ + [URI_OPAQUE] = "/#", + /* User name: escape everything */ + [URI_USER] = "/#:@?", + /* Password: escape everything */ + [URI_PASSWORD] = "/#:@?", + /* Host name: escape everything except ':', which may + * appear as part of an IPv6 literal address. + */ + [URI_HOST] = "/#@?", + /* Port number: escape everything */ + [URI_PORT] = "/#:@?", + /* Path: escape everything except '/', which usually + * appears within paths. + */ + [URI_PATH] = "#:@?", + /* Query: escape everything except '/', which + * sometimes appears within queries. + */ + [URI_QUERY] = "#:@?", + /* Fragment: escape everything */ + [URI_FRAGMENT] = "/#:@?", + }; + + return ( /* Always escape non-printing characters and whitespace */ + ( ! isprint ( c ) ) || ( c == ' ' ) || + /* Always escape '%' */ + ( c == '%' ) || + /* Escape field-specific characters */ + strchr ( escaped[field], c ) ); +} + +/** + * Encode URI field + * + * @v uri URI + * @v field URI field index + * @v buf Buffer to contain encoded string + * @v len Length of buffer + * @ret len Length of encoded string (excluding NUL) + */ +size_t uri_encode ( const char *string, unsigned int field, + char *buf, ssize_t len ) { + ssize_t remaining = len; + size_t used; + char c; + + /* Ensure encoded string is NUL-terminated even if empty */ + if ( len > 0 ) + buf[0] = '\0'; + + /* Copy string, escaping as necessary */ + while ( ( c = *(string++) ) ) { + if ( uri_character_escaped ( c, field ) ) { + used = ssnprintf ( buf, remaining, "%%%02X", c ); + } else { + used = ssnprintf ( buf, remaining, "%c", c ); + } + buf += used; + remaining -= used; + } + + return ( len - remaining ); +} + +/** * Dump URI for debugging * * @v uri URI */ -static void dump_uri ( struct uri *uri ) { +static void uri_dump ( const struct uri *uri ) { + if ( ! uri ) return; if ( uri->scheme ) - DBG ( " scheme \"%s\"", uri->scheme ); + DBGC ( uri, " scheme \"%s\"", uri->scheme ); if ( uri->opaque ) - DBG ( " opaque \"%s\"", uri->opaque ); + DBGC ( uri, " opaque \"%s\"", uri->opaque ); if ( uri->user ) - DBG ( " user \"%s\"", uri->user ); + DBGC ( uri, " user \"%s\"", uri->user ); if ( uri->password ) - DBG ( " password \"%s\"", uri->password ); + DBGC ( uri, " password \"%s\"", uri->password ); if ( uri->host ) - DBG ( " host \"%s\"", uri->host ); + DBGC ( uri, " host \"%s\"", uri->host ); if ( uri->port ) - DBG ( " port \"%s\"", uri->port ); + DBGC ( uri, " port \"%s\"", uri->port ); if ( uri->path ) - DBG ( " path \"%s\"", uri->path ); + DBGC ( uri, " path \"%s\"", uri->path ); if ( uri->query ) - DBG ( " query \"%s\"", uri->query ); + DBGC ( uri, " query \"%s\"", uri->query ); if ( uri->fragment ) - DBG ( " fragment \"%s\"", uri->fragment ); + DBGC ( uri, " fragment \"%s\"", uri->fragment ); if ( uri->params ) - DBG ( " params \"%s\"", uri->params->name ); + DBGC ( uri, " params \"%s\"", uri->params->name ); } /** @@ -69,11 +219,10 @@ * * @v refcnt Reference count */ -static void free_uri ( struct refcnt *refcnt ) { +static void uri_free ( struct refcnt *refcnt ) { struct uri *uri = container_of ( refcnt, struct uri, refcnt ); - if ( uri->params ) - destroy_parameters ( uri->params ); + params_put ( uri->params ); free ( uri ); } @@ -89,20 +238,21 @@ */ struct uri * parse_uri ( const char *uri_string ) { struct uri *uri; + struct parameters *params; char *raw; char *tmp; char *path; char *authority; - int i; size_t raw_len; + unsigned int field; /* Allocate space for URI struct and a copy of the string */ raw_len = ( strlen ( uri_string ) + 1 /* NUL */ ); uri = zalloc ( sizeof ( *uri ) + raw_len ); if ( ! uri ) return NULL; - ref_init ( &uri->refcnt, free_uri ); - raw = ( ( ( char * ) uri ) + sizeof ( *uri ) ); + ref_init ( &uri->refcnt, uri_free ); + raw = ( ( ( void * ) uri ) + sizeof ( *uri ) ); /* Copy in the raw string */ memcpy ( raw, uri_string, raw_len ); @@ -111,9 +261,9 @@ if ( ( tmp = strstr ( raw, "##params" ) ) ) { *tmp = '\0'; tmp += 8 /* "##params" */; - uri->params = find_parameters ( *tmp ? ( tmp + 1 ) : NULL ); - if ( uri->params ) { - claim_parameters ( uri->params ); + params = find_parameters ( *tmp ? ( tmp + 1 ) : NULL ); + if ( params ) { + uri->params = claim_parameters ( params ); } else { /* Ignore non-existent submission blocks */ } @@ -125,12 +275,8 @@ uri->fragment = tmp; } - /* Identify absolute/relative URI. We ignore schemes that are - * apparently only a single character long, since otherwise we - * misinterpret a DOS-style path name ("C:\path\to\file") as a - * URI with scheme="C",opaque="\path\to\file". - */ - if ( ( tmp = strchr ( raw, ':' ) ) && ( tmp > ( raw + 1 ) ) ) { + /* Identify absolute/relative URI */ + if ( ( tmp = strchr ( raw, ':' ) ) ) { /* Absolute URI: identify hierarchical/opaque */ uri->scheme = raw; *(tmp++) = '\0'; @@ -159,6 +305,12 @@ uri->query = tmp; } + /* If we have no path remaining, then we're already finished + * processing. + */ + if ( ! path[0] ) + goto done; + /* Identify net/absolute/relative path */ if ( strncmp ( path, "//", 2 ) == 0 ) { /* Net path. If this is terminated by the first '/' @@ -205,23 +357,22 @@ } /* Split host into host[:port] */ - if ( ( tmp = strchr ( uri->host, ':' ) ) ) { + if ( ( uri->host[ strlen ( uri->host ) - 1 ] != ']' ) && + ( tmp = strrchr ( uri->host, ':' ) ) ) { *(tmp++) = '\0'; uri->port = tmp; } - /* Decode fields that should be decoded */ - for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) { - const char *field = uri_get_field ( uri, i ); - if ( field && ( URI_ENCODED & ( 1 << i ) ) ) - uri_decode ( field, ( char * ) field, - strlen ( field ) + 1 /* NUL */ ); + /* Decode fields in-place */ + for ( field = 0 ; field < URI_FIELDS ; field++ ) { + if ( uri_field ( uri, field ) ) + uri_decode ( ( char * ) uri_field ( uri, field ) ); } done: - DBG ( "URI \"%s\" split into", uri_string ); - dump_uri ( uri ); - DBG ( "\n" ); + DBGC ( uri, "URI parsed \"%s\" to", uri_string ); + uri_dump ( uri ); + DBGC ( uri, "\n" ); return uri; } @@ -233,83 +384,138 @@ * @v default_port Default port to use if none specified in URI * @ret port Port */ -unsigned int uri_port ( struct uri *uri, unsigned int default_port ) { +unsigned int uri_port ( const struct uri *uri, unsigned int default_port ) { + if ( ( ! uri ) || ( ! uri->port ) ) return default_port; + return ( strtoul ( uri->port, NULL, 0 ) ); } /** - * Unparse URI + * Format URI * + * @v uri URI * @v buf Buffer to fill with URI string * @v size Size of buffer - * @v uri URI to write into buffer, or NULL - * @v fields Bitmask of fields to include in URI string, or URI_ALL * @ret len Length of URI string */ -int unparse_uri ( char *buf, size_t size, struct uri *uri, - unsigned int fields ) { - /* List of characters that typically go before certain fields */ - static char separators[] = { /* scheme */ 0, /* opaque */ ':', - /* user */ 0, /* password */ ':', - /* host */ '@', /* port */ ':', - /* path */ 0, /* query */ '?', - /* fragment */ '#' }; - int used = 0; - int i; - - DBG ( "URI unparsing" ); - dump_uri ( uri ); - DBG ( "\n" ); +size_t format_uri ( const struct uri *uri, char *buf, size_t len ) { + static const char prefixes[URI_FIELDS] = { + [URI_OPAQUE] = ':', + [URI_PASSWORD] = ':', + [URI_PORT] = ':', + [URI_PATH] = '/', + [URI_QUERY] = '?', + [URI_FRAGMENT] = '#', + }; + char prefix; + size_t used = 0; + unsigned int field; /* Ensure buffer is NUL-terminated */ - if ( size ) + if ( len ) buf[0] = '\0'; /* Special-case NULL URI */ if ( ! uri ) return 0; - /* Iterate through requested fields */ - for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) { - const char *field = uri_get_field ( uri, i ); - char sep = separators[i]; - - /* Ensure `fields' only contains bits for fields that exist */ - if ( ! field ) - fields &= ~( 1 << i ); - - /* Store this field if we were asked to */ - if ( fields & ( 1 << i ) ) { - /* Print :// if we're non-opaque and had a scheme */ - if ( ( fields & URI_SCHEME_BIT ) && - ( i > URI_OPAQUE ) ) { - used += ssnprintf ( buf + used, size - used, - "://" ); - /* Only print :// once */ - fields &= ~URI_SCHEME_BIT; - } + /* Generate fields */ + for ( field = 0 ; field < URI_FIELDS ; field++ ) { - /* Only print separator if an earlier field exists */ - if ( sep && ( fields & ( ( 1 << i ) - 1 ) ) ) - used += ssnprintf ( buf + used, size - used, - "%c", sep ); - - /* Print contents of field, possibly encoded */ - if ( URI_ENCODED & ( 1 << i ) ) - used += uri_encode ( field, buf + used, - size - used, i ); - else - used += ssnprintf ( buf + used, size - used, - "%s", field ); + /* Skip non-existent fields */ + if ( ! uri_field ( uri, field ) ) + continue; + + /* Prefix this field, if applicable */ + prefix = prefixes[field]; + if ( ( field == URI_HOST ) && ( uri->user != NULL ) ) + prefix = '@'; + if ( ( field == URI_PATH ) && ( uri->path[0] == '/' ) ) + prefix = '\0'; + if ( prefix ) { + used += ssnprintf ( ( buf + used ), ( len - used ), + "%c", prefix ); } + + /* Encode this field */ + used += uri_encode ( uri_field ( uri, field ), field, + ( buf + used ), ( len - used ) ); + + /* Suffix this field, if applicable */ + if ( ( field == URI_SCHEME ) && ( ! uri->opaque ) ) { + used += ssnprintf ( ( buf + used ), ( len - used ), + "://" ); + } + } + + if ( len ) { + DBGC ( uri, "URI formatted" ); + uri_dump ( uri ); + DBGC ( uri, " to \"%s%s\"\n", buf, + ( ( used > len ) ? "<TRUNCATED>" : "" ) ); } return used; } /** + * Format URI + * + * @v uri URI + * @ret string URI string, or NULL on failure + * + * The caller is responsible for eventually freeing the allocated + * memory. + */ +char * format_uri_alloc ( const struct uri *uri ) { + size_t len; + char *string; + + len = ( format_uri ( uri, NULL, 0 ) + 1 /* NUL */ ); + string = malloc ( len ); + if ( string ) + format_uri ( uri, string, len ); + return string; +} + +/** + * Copy URI fields + * + * @v src Source URI + * @v dest Destination URI, or NULL to calculate length + * @ret len Length of raw URI + */ +static size_t uri_copy_fields ( const struct uri *src, struct uri *dest ) { + size_t len = sizeof ( *dest ); + char *out = ( ( void * ) dest + len ); + unsigned int field; + size_t field_len; + + /* Copy existent fields */ + for ( field = 0 ; field < URI_FIELDS ; field++ ) { + + /* Skip non-existent fields */ + if ( ! uri_field ( src, field ) ) + continue; + + /* Calculate field length */ + field_len = ( strlen ( uri_field ( src, field ) ) + + 1 /* NUL */ ); + len += field_len; + + /* Copy field, if applicable */ + if ( dest ) { + memcpy ( out, uri_field ( src, field ), field_len ); + uri_field ( dest, field ) = out; + out += field_len; + } + } + return len; +} + +/** * Duplicate URI * * @v uri URI @@ -317,12 +523,28 @@ * * Creates a modifiable copy of a URI. */ -struct uri * uri_dup ( struct uri *uri ) { - size_t len = ( unparse_uri ( NULL, 0, uri, URI_ALL ) + 1 ); - char buf[len]; +struct uri * uri_dup ( const struct uri *uri ) { + struct uri *dup; + size_t len; + + /* Allocate new URI */ + len = uri_copy_fields ( uri, NULL ); + dup = zalloc ( len ); + if ( ! dup ) + return NULL; + ref_init ( &dup->refcnt, uri_free ); + + /* Copy fields */ + uri_copy_fields ( uri, dup ); - unparse_uri ( buf, len, uri, URI_ALL ); - return parse_uri ( buf ); + /* Copy parameters */ + dup->params = params_get ( uri->params ); + + DBGC ( uri, "URI duplicated" ); + uri_dump ( uri ); + DBGC ( uri, "\n" ); + + return dup; } /** @@ -398,7 +620,7 @@ * relative URI (e.g. "../initrds/initrd.gz") and produces a new URI * (e.g. "http://ipxe.org/initrds/initrd.gz"). */ -struct uri * resolve_uri ( struct uri *base_uri, +struct uri * resolve_uri ( const struct uri *base_uri, struct uri *relative_uri ) { struct uri tmp_uri; char *tmp_path = NULL; @@ -417,11 +639,16 @@ tmp_uri.path = tmp_path; tmp_uri.query = relative_uri->query; tmp_uri.fragment = relative_uri->fragment; + tmp_uri.params = relative_uri->params; } else if ( relative_uri->query ) { tmp_uri.query = relative_uri->query; tmp_uri.fragment = relative_uri->fragment; + tmp_uri.params = relative_uri->params; } else if ( relative_uri->fragment ) { tmp_uri.fragment = relative_uri->fragment; + tmp_uri.params = relative_uri->params; + } else if ( relative_uri->params ) { + tmp_uri.params = relative_uri->params; } /* Create demangled URI */ @@ -431,100 +658,23 @@ } /** - * Test for unreserved URI characters + * Construct TFTP URI from next-server and filename * - * @v c Character to test - * @v field Field of URI in which character lies - * @ret is_unreserved Character is an unreserved character - */ -static int is_unreserved_uri_char ( int c, int field ) { - /* According to RFC3986, the unreserved character set is - * - * A-Z a-z 0-9 - _ . ~ - * - * but we also pass & ; = in queries, / in paths, - * and everything in opaques - */ - int ok = ( isupper ( c ) || islower ( c ) || isdigit ( c ) || - ( c == '-' ) || ( c == '_' ) || - ( c == '.' ) || ( c == '~' ) ); - - if ( field == URI_QUERY ) - ok = ok || ( c == ';' ) || ( c == '&' ) || ( c == '=' ); - - if ( field == URI_PATH ) - ok = ok || ( c == '/' ); - - if ( field == URI_OPAQUE ) - ok = 1; - - return ok; -} - -/** - * URI-encode string - * - * @v raw_string String to be URI-encoded - * @v buf Buffer to contain encoded string - * @v len Length of buffer - * @v field Field of URI in which string lies - * @ret len Length of encoded string (excluding NUL) - */ -size_t uri_encode ( const char *raw_string, char *buf, ssize_t len, - int field ) { - ssize_t remaining = len; - size_t used; - unsigned char c; - - if ( len > 0 ) - buf[0] = '\0'; - - while ( ( c = *(raw_string++) ) ) { - if ( is_unreserved_uri_char ( c, field ) ) { - used = ssnprintf ( buf, remaining, "%c", c ); - } else { - used = ssnprintf ( buf, remaining, "%%%02X", c ); - } - buf += used; - remaining -= used; - } - - return ( len - remaining ); -} - -/** - * Decode URI-encoded string - * - * @v encoded_string URI-encoded string - * @v buf Buffer to contain decoded string - * @v len Length of buffer - * @ret len Length of decoded string (excluding NUL) - * - * This function may be used in-place, with @a buf the same as - * @a encoded_string. - */ -size_t uri_decode ( const char *encoded_string, char *buf, ssize_t len ) { - ssize_t remaining; - char hexbuf[3]; - char *hexbuf_end; - unsigned char c; - - for ( remaining = len; *encoded_string; remaining-- ) { - if ( *encoded_string == '%' ) { - encoded_string++; - snprintf ( hexbuf, sizeof ( hexbuf ), "%s", - encoded_string ); - c = strtoul ( hexbuf, &hexbuf_end, 16 ); - encoded_string += ( hexbuf_end - hexbuf ); - } else { - c = *(encoded_string++); - } - if ( remaining > 1 ) - *buf++ = c; - } - - if ( len ) - *buf = 0; - - return ( len - remaining ); + * @v next_server Next-server address + * @v filename Filename + * @ret uri URI, or NULL on failure + * + * TFTP filenames specified via the DHCP next-server field often + * contain characters such as ':' or '#' which would confuse the + * generic URI parser. We provide a mechanism for directly + * constructing a TFTP URI from the next-server and filename. + */ +struct uri * tftp_uri ( struct in_addr next_server, const char *filename ) { + struct uri uri; + + memset ( &uri, 0, sizeof ( uri ) ); + uri.scheme = "tftp"; + uri.host = inet_ntoa ( next_server ); + uri.path = filename; + return uri_dup ( &uri ); } | ||
[-] [+] | Added | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/crypto/deflate.c ^ |
@@ -0,0 +1,1045 @@ +/* + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <string.h> +#include <strings.h> +#include <errno.h> +#include <assert.h> +#include <ctype.h> +#include <ipxe/uaccess.h> +#include <ipxe/deflate.h> + +/** @file + * + * DEFLATE decompression algorithm + * + * This file implements the decompression half of the DEFLATE + * algorithm specified in RFC 1951. + * + * Portions of this code are derived from wimboot's xca.c. + * + */ + +/** + * Byte reversal table + * + * For some insane reason, the DEFLATE format stores some values in + * bit-reversed order. + */ +static uint8_t deflate_reverse[256]; + +/** Literal/length base values + * + * We include entries only for literal/length codes 257-284. Code 285 + * does not fit the pattern (it represents a length of 258; following + * the pattern from the earlier codes would give a length of 259), and + * has no extra bits. Codes 286-287 are invalid, but can occur. We + * treat any code greater than 284 as meaning "length 285, no extra + * bits". + */ +static uint8_t deflate_litlen_base[28]; + +/** Distance base values + * + * We include entries for all possible codes 0-31, avoiding the need + * to check for undefined codes 30 and 31 before performing the + * lookup. Codes 30 and 31 are never initialised, and will therefore + * be treated as meaning "14 extra bits, base distance 0". + */ +static uint16_t deflate_distance_base[32]; + +/** Code length map */ +static uint8_t deflate_codelen_map[19] = { + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 +}; + +/** Static Huffman alphabet length patterns */ +static struct deflate_static_length_pattern deflate_static_length_patterns[] = { + /* Literal/length code lengths */ + { 0x88, ( ( ( 143 - 0 ) + 1 ) / 2 ) }, + { 0x99, ( ( ( 255 - 144 ) + 1 ) / 2 ) }, + { 0x77, ( ( ( 279 - 256 ) + 1 ) / 2 ) }, + { 0x88, ( ( ( 287 - 280 ) + 1 ) / 2 ) }, + /* Distance code lengths */ + { 0x55, ( ( ( 31 - 0 ) + 1 ) / 2 ) }, + /* End marker */ + { 0, 0 } +}; + +/** + * Transcribe binary value (for debugging) + * + * @v value Value + * @v bits Length of value (in bits) + * @ret string Transcribed value + */ +static const char * deflate_bin ( unsigned long value, unsigned int bits ) { + static char buf[ ( 8 * sizeof ( value ) ) + 1 /* NUL */ ]; + char *out = buf; + + /* Sanity check */ + assert ( bits < sizeof ( buf ) ); + + /* Transcribe value */ + while ( bits-- ) + *(out++) = ( ( value & ( 1 << bits ) ) ? '1' : '0' ); + *out = '\0'; + + return buf; +} + +/** + * Set Huffman symbol length + * + * @v deflate Decompressor + * @v index Index within lengths + * @v bits Symbol length (in bits) + */ +static void deflate_set_length ( struct deflate *deflate, unsigned int index, + unsigned int bits ) { + + deflate->lengths[ index / 2 ] |= ( bits << ( 4 * ( index % 2 ) ) ); +} + +/** + * Get Huffman symbol length + * + * @v deflate Decompressor + * @v index Index within lengths + * @ret bits Symbol length (in bits) + */ +static unsigned int deflate_length ( struct deflate *deflate, + unsigned int index ) { + + return ( ( deflate->lengths[ index / 2 ] >> ( 4 * ( index % 2 ) ) ) + & 0x0f ); +} + +/** + * Determine Huffman alphabet name (for debugging) + * + * @v deflate Decompressor + * @v alphabet Huffman alphabet + * @ret name Alphabet name + */ +static const char * deflate_alphabet_name ( struct deflate *deflate, + struct deflate_alphabet *alphabet ){ + + if ( alphabet == &deflate->litlen ) { + return "litlen"; + } else if ( alphabet == &deflate->distance_codelen ) { + return "distance/codelen"; + } else { + return "<UNKNOWN>"; + } +} + +/** + * Dump Huffman alphabet (for debugging) + * + * @v deflate Decompressor + * @v alphabet Huffman alphabet + */ +static void deflate_dump_alphabet ( struct deflate *deflate, + struct deflate_alphabet *alphabet ) { + struct deflate_huf_symbols *huf_sym; + unsigned int bits; + unsigned int huf; + unsigned int i; + + /* Do nothing unless debugging is enabled */ + if ( ! DBG_EXTRA ) + return; + + /* Dump symbol table for each utilised length */ + for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) / + sizeof ( alphabet->huf[0] ) ) ; bits++ ) { + huf_sym = &alphabet->huf[ bits - 1 ]; + if ( huf_sym->freq == 0 ) + continue; + huf = ( huf_sym->start >> huf_sym->shift ); + DBGC2 ( alphabet, "DEFLATE %p \"%s\" length %d start \"%s\" " + "freq %d:", deflate, + deflate_alphabet_name ( deflate, alphabet ), bits, + deflate_bin ( huf, huf_sym->bits ), huf_sym->freq ); + for ( i = 0 ; i < huf_sym->freq ; i++ ) { + DBGC2 ( alphabet, " %03x", + huf_sym->raw[ huf + i ] ); + } + DBGC2 ( alphabet, "\n" ); + } + + /* Dump quick lookup table */ + DBGC2 ( alphabet, "DEFLATE %p \"%s\" quick lookup:", deflate, + deflate_alphabet_name ( deflate, alphabet ) ); + for ( i = 0 ; i < ( sizeof ( alphabet->lookup ) / + sizeof ( alphabet->lookup[0] ) ) ; i++ ) { + DBGC2 ( alphabet, " %d", ( alphabet->lookup[i] + 1 ) ); + } + DBGC2 ( alphabet, "\n" ); +} + +/** + * Construct Huffman alphabet + * + * @v deflate Decompressor + * @v alphabet Huffman alphabet + * @v count Number of symbols + * @v offset Starting offset within length table + * @ret rc Return status code + */ +static int deflate_alphabet ( struct deflate *deflate, + struct deflate_alphabet *alphabet, + unsigned int count, unsigned int offset ) { + struct deflate_huf_symbols *huf_sym; + unsigned int huf; + unsigned int cum_freq; + unsigned int bits; + unsigned int raw; + unsigned int adjustment; + unsigned int prefix; + int complete; + + /* Clear symbol table */ + memset ( alphabet->huf, 0, sizeof ( alphabet->huf ) ); + + /* Count number of symbols with each Huffman-coded length */ + for ( raw = 0 ; raw < count ; raw++ ) { + bits = deflate_length ( deflate, ( raw + offset ) ); + if ( bits ) + alphabet->huf[ bits - 1 ].freq++; + } + + /* Populate Huffman-coded symbol table */ + huf = 0; + cum_freq = 0; + for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) / + sizeof ( alphabet->huf[0] ) ) ; bits++ ) { + huf_sym = &alphabet->huf[ bits - 1 ]; + huf_sym->bits = bits; + huf_sym->shift = ( 16 - bits ); + huf_sym->start = ( huf << huf_sym->shift ); + huf_sym->raw = &alphabet->raw[cum_freq]; + huf += huf_sym->freq; + if ( huf > ( 1U << bits ) ) { + DBGC ( alphabet, "DEFLATE %p \"%s\" has too many " + "symbols with lengths <=%d\n", deflate, + deflate_alphabet_name ( deflate, alphabet ), + bits ); + return -EINVAL; + } + huf <<= 1; + cum_freq += huf_sym->freq; + } + complete = ( huf == ( 1U << bits ) ); + + /* Populate raw symbol table */ + for ( raw = 0 ; raw < count ; raw++ ) { + bits = deflate_length ( deflate, ( raw + offset ) ); + if ( bits ) { + huf_sym = &alphabet->huf[ bits - 1 ]; + *(huf_sym->raw++) = raw; + } + } + + /* Adjust Huffman-coded symbol table raw pointers and populate + * quick lookup table. + */ + for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) / + sizeof ( alphabet->huf[0] ) ) ; bits++ ) { + huf_sym = &alphabet->huf[ bits - 1 ]; + + /* Adjust raw pointer */ + huf_sym->raw -= huf_sym->freq; /* Reset to first symbol */ + adjustment = ( huf_sym->start >> huf_sym->shift ); + huf_sym->raw -= adjustment; /* Adjust for quick indexing */ + + /* Populate quick lookup table */ + for ( prefix = ( huf_sym->start >> DEFLATE_HUFFMAN_QL_SHIFT ) ; + prefix < ( 1 << DEFLATE_HUFFMAN_QL_BITS ) ; prefix++ ) { + alphabet->lookup[prefix] = ( bits - 1 ); + } + } + + /* Dump alphabet (for debugging) */ + deflate_dump_alphabet ( deflate, alphabet ); + + /* Check that there are no invalid codes */ + if ( ! complete ) { + DBGC ( alphabet, "DEFLATE %p \"%s\" is incomplete\n", deflate, + deflate_alphabet_name ( deflate, alphabet ) ); + return -EINVAL; + } + + return 0; +} + +/** + * Attempt to accumulate bits from input stream + * + * @v deflate Decompressor + * @v in Compressed input data + * @v target Number of bits to accumulate + * @ret excess Number of excess bits accumulated (may be negative) + */ +static int deflate_accumulate ( struct deflate *deflate, + struct deflate_chunk *in, + unsigned int target ) { + uint8_t byte; + + while ( deflate->bits < target ) { + + /* Check for end of input */ + if ( in->offset >= in->len ) + break; + + /* Acquire byte from input */ + copy_from_user ( &byte, in->data, in->offset++, + sizeof ( byte ) ); + deflate->accumulator = ( deflate->accumulator | + ( byte << deflate->bits ) ); + deflate->rotalumucca = ( deflate->rotalumucca | + ( deflate_reverse[byte] << + ( 24 - deflate->bits ) ) ); + deflate->bits += 8; + + /* Sanity check */ + assert ( deflate->bits <= + ( 8 * sizeof ( deflate->accumulator ) ) ); + } + + return ( deflate->bits - target ); +} + +/** + * Consume accumulated bits from the input stream + * + * @v deflate Decompressor + * @v count Number of accumulated bits to consume + * @ret data Consumed bits + */ +static int deflate_consume ( struct deflate *deflate, unsigned int count ) { + int data; + + /* Sanity check */ + assert ( count <= deflate->bits ); + + /* Extract data and consume bits */ + data = ( deflate->accumulator & ( ( 1 << count ) - 1 ) ); + deflate->accumulator >>= count; + deflate->rotalumucca <<= count; + deflate->bits -= count; + + return data; +} + +/** + * Attempt to extract a fixed number of bits from input stream + * + * @v deflate Decompressor + * @v in Compressed input data + * @v target Number of bits to extract + * @ret data Extracted bits (or negative if not yet accumulated) + */ +static int deflate_extract ( struct deflate *deflate, struct deflate_chunk *in, + unsigned int target ) { + int excess; + int data; + + /* Return immediately if we are attempting to extract zero bits */ + if ( target == 0 ) + return 0; + + /* Attempt to accumulate bits */ + excess = deflate_accumulate ( deflate, in, target ); + if ( excess < 0 ) + return excess; + + /* Extract data and consume bits */ + data = deflate_consume ( deflate, target ); + DBGCP ( deflate, "DEFLATE %p extracted %s = %#x = %d\n", deflate, + deflate_bin ( data, target ), data, data ); + + return data; +} + +/** + * Attempt to decode a Huffman-coded symbol from input stream + * + * @v deflate Decompressor + * @v in Compressed input data + * @v alphabet Huffman alphabet + * @ret code Raw code (or negative if not yet accumulated) + */ +static int deflate_decode ( struct deflate *deflate, + struct deflate_chunk *in, + struct deflate_alphabet *alphabet ) { + struct deflate_huf_symbols *huf_sym; + uint16_t huf; + unsigned int lookup_index; + int excess; + unsigned int raw; + + /* Attempt to accumulate maximum required number of bits. + * There may be fewer bits than this remaining in the stream, + * even if the stream still contains some complete + * Huffman-coded symbols. + */ + deflate_accumulate ( deflate, in, DEFLATE_HUFFMAN_BITS ); + + /* Normalise the bit-reversed accumulated value to 16 bits */ + huf = ( deflate->rotalumucca >> 16 ); + + /* Find symbol set for this length */ + lookup_index = ( huf >> DEFLATE_HUFFMAN_QL_SHIFT ); + huf_sym = &alphabet->huf[ alphabet->lookup[ lookup_index ] ]; + while ( huf < huf_sym->start ) + huf_sym--; + + /* Calculate number of excess bits, and return if not yet complete */ + excess = ( deflate->bits - huf_sym->bits ); + if ( excess < 0 ) + return excess; + + /* Consume bits */ + deflate_consume ( deflate, huf_sym->bits ); + + /* Look up raw symbol */ + raw = huf_sym->raw[ huf >> huf_sym->shift ]; + DBGCP ( deflate, "DEFLATE %p decoded %s = %#x = %d\n", deflate, + deflate_bin ( ( huf >> huf_sym->shift ), huf_sym->bits ), + raw, raw ); + + return raw; +} + +/** + * Discard bits up to the next byte boundary + * + * @v deflate Decompressor + */ +static void deflate_discard_to_byte ( struct deflate *deflate ) { + + deflate_consume ( deflate, ( deflate->bits & 7 ) ); +} + +/** + * Copy data to output buffer (if available) + * + * @v out Output data buffer + * @v start Source data + * @v offset Starting offset within source data + * @v len Length to copy + */ +static void deflate_copy ( struct deflate_chunk *out, + userptr_t start, size_t offset, size_t len ) { + size_t out_offset = out->offset; + size_t copy_len; + + /* Copy data one byte at a time, to allow for overlap */ + if ( out_offset < out->len ) { + copy_len = ( out->len - out_offset ); + if ( copy_len > len ) + copy_len = len; + while ( copy_len-- ) { + memcpy_user ( out->data, out_offset++, + start, offset++, 1 ); + } + } + out->offset += len; +} + +/** + * Inflate compressed data + * + * @v deflate Decompressor + * @v in Compressed input data + * @v out Output data buffer + * @ret rc Return status code + * + * The caller can use deflate_finished() to determine whether a + * successful return indicates that the decompressor is merely waiting + * for more input. + * + * Data will not be written beyond the specified end of the output + * data buffer, but the offset within the output data buffer will be + * updated to reflect the amount that should have been written. The + * caller can use this to find the length of the decompressed data + * before allocating the output data buffer. + */ +int deflate_inflate ( struct deflate *deflate, + struct deflate_chunk *in, + struct deflate_chunk *out ) { + + /* This could be implemented more neatly if gcc offered a + * means for enforcing tail recursion. + */ + if ( deflate->resume ) { + goto *(deflate->resume); + } else switch ( deflate->format ) { + case DEFLATE_RAW: goto block_header; + case DEFLATE_ZLIB: goto zlib_header; + default: assert ( 0 ); + } + + zlib_header: { + int header; + int cm; + + /* Extract header */ + header = deflate_extract ( deflate, in, ZLIB_HEADER_BITS ); + if ( header < 0 ) { + deflate->resume = &&zlib_header; + return 0; + } + + /* Parse header */ + cm = ( ( header >> ZLIB_HEADER_CM_LSB ) & ZLIB_HEADER_CM_MASK ); + if ( cm != ZLIB_HEADER_CM_DEFLATE ) { + DBGC ( deflate, "DEFLATE %p unsupported ZLIB " + "compression method %d\n", deflate, cm ); + return -ENOTSUP; + } + if ( header & ( 1 << ZLIB_HEADER_FDICT_BIT ) ) { + DBGC ( deflate, "DEFLATE %p unsupported ZLIB preset " + "dictionary\n", deflate ); + return -ENOTSUP; + } + + /* Process first block header */ + goto block_header; + } + + block_header: { + int header; + int bfinal; + int btype; + + /* Extract block header */ + header = deflate_extract ( deflate, in, DEFLATE_HEADER_BITS ); + if ( header < 0 ) { + deflate->resume = &&block_header; + return 0; + } + + /* Parse header */ + deflate->header = header; + bfinal = ( header & ( 1 << DEFLATE_HEADER_BFINAL_BIT ) ); + btype = ( header >> DEFLATE_HEADER_BTYPE_LSB ); + DBGC ( deflate, "DEFLATE %p found %sblock type %#x\n", + deflate, ( bfinal ? "final " : "" ), btype ); + switch ( btype ) { + case DEFLATE_HEADER_BTYPE_LITERAL: + goto literal_block; + case DEFLATE_HEADER_BTYPE_STATIC: + goto static_block; + case DEFLATE_HEADER_BTYPE_DYNAMIC: + goto dynamic_block; + default: + DBGC ( deflate, "DEFLATE %p unsupported block type " + "%#x\n", deflate, btype ); + return -ENOTSUP; + } + } + + literal_block: { + + /* Discard any bits up to the next byte boundary */ + deflate_discard_to_byte ( deflate ); + } + + literal_len: { + int len; + + /* Extract LEN field */ + len = deflate_extract ( deflate, in, DEFLATE_LITERAL_LEN_BITS ); + if ( len < 0 ) { + deflate->resume = &&literal_len; + return 0; + } + + /* Record length of literal data */ + deflate->remaining = len; + DBGC2 ( deflate, "DEFLATE %p literal block length %#04zx\n", + deflate, deflate->remaining ); + } + + literal_nlen: { + int nlen; + + /* Extract NLEN field */ + nlen = deflate_extract ( deflate, in, DEFLATE_LITERAL_LEN_BITS); + if ( nlen < 0 ) { + deflate->resume = &&literal_nlen; + return 0; + } + + /* Verify NLEN */ + if ( ( ( deflate->remaining ^ ~nlen ) & + ( ( 1 << DEFLATE_LITERAL_LEN_BITS ) - 1 ) ) != 0 ) { + DBGC ( deflate, "DEFLATE %p invalid len/nlen " + "%#04zx/%#04x\n", deflate, + deflate->remaining, nlen ); + return -EINVAL; + } + } + + literal_data: { + size_t in_remaining; + size_t len; + + /* Calculate available amount of literal data */ + in_remaining = ( in->len - in->offset ); + len = deflate->remaining; + if ( len > in_remaining ) + len = in_remaining; + + /* Copy data to output buffer */ + deflate_copy ( out, in->data, in->offset, len ); + + /* Consume data from input buffer */ + in->offset += len; + deflate->remaining -= len; + + /* Finish processing if we are blocked */ + if ( deflate->remaining ) { + deflate->resume = &&literal_data; + return 0; + } + + /* Otherwise, finish block */ + goto block_done; + } + + static_block: { + struct deflate_static_length_pattern *pattern; + uint8_t *lengths = deflate->lengths; + + /* Construct static Huffman lengths as per RFC 1950 */ + for ( pattern = deflate_static_length_patterns ; + pattern->count ; pattern++ ) { + memset ( lengths, pattern->fill, pattern->count ); + lengths += pattern->count; + } + deflate->litlen_count = 288; + deflate->distance_count = 32; + goto construct_alphabets; + } + + dynamic_block: + + dynamic_header: { + int header; + unsigned int hlit; + unsigned int hdist; + unsigned int hclen; + + /* Extract block header */ + header = deflate_extract ( deflate, in, DEFLATE_DYNAMIC_BITS ); + if ( header < 0 ) { + deflate->resume = &&dynamic_header; + return 0; + } + + /* Parse header */ + hlit = ( ( header >> DEFLATE_DYNAMIC_HLIT_LSB ) & + DEFLATE_DYNAMIC_HLIT_MASK ); + hdist = ( ( header >> DEFLATE_DYNAMIC_HDIST_LSB ) & + DEFLATE_DYNAMIC_HDIST_MASK ); + hclen = ( ( header >> DEFLATE_DYNAMIC_HCLEN_LSB ) & + DEFLATE_DYNAMIC_HCLEN_MASK ); + deflate->litlen_count = ( hlit + 257 ); + deflate->distance_count = ( hdist + 1 ); + deflate->length_index = 0; + deflate->length_target = ( hclen + 4 ); + DBGC2 ( deflate, "DEFLATE %p dynamic block %d codelen, %d " + "litlen, %d distance\n", deflate, + deflate->length_target, deflate->litlen_count, + deflate->distance_count ); + + /* Prepare for decoding code length code lengths */ + memset ( &deflate->lengths, 0, sizeof ( deflate->lengths ) ); + } + + dynamic_codelen: { + int len; + unsigned int index; + int rc; + + /* Extract all code lengths */ + while ( deflate->length_index < deflate->length_target ) { + + /* Extract code length length */ + len = deflate_extract ( deflate, in, + DEFLATE_CODELEN_BITS ); + if ( len < 0 ) { + deflate->resume = &&dynamic_codelen; + return 0; + } + + /* Store code length */ + index = deflate_codelen_map[deflate->length_index++]; + deflate_set_length ( deflate, index, len ); + DBGCP ( deflate, "DEFLATE %p codelen for %d is %d\n", + deflate, index, len ); + } + + /* Generate code length alphabet */ + if ( ( rc = deflate_alphabet ( deflate, + &deflate->distance_codelen, + ( DEFLATE_CODELEN_MAX_CODE + 1 ), + 0 ) ) != 0 ) + return rc; + + /* Prepare for decoding literal/length/distance code lengths */ + memset ( &deflate->lengths, 0, sizeof ( deflate->lengths ) ); + deflate->length_index = 0; + deflate->length_target = ( deflate->litlen_count + + deflate->distance_count ); + deflate->length = 0; + } + + dynamic_litlen_distance: { + int len; + int index; + + /* Decode literal/length/distance code length */ + len = deflate_decode ( deflate, in, &deflate->distance_codelen); + if ( len < 0 ) { + deflate->resume = &&dynamic_litlen_distance; + return 0; + } + + /* Prepare for extra bits */ + if ( len < 16 ) { + deflate->length = len; + deflate->extra_bits = 0; + deflate->dup_len = 1; + } else { + static const uint8_t dup_len[3] = { 3, 3, 11 }; + static const uint8_t extra_bits[3] = { 2, 3, 7 }; + index = ( len - 16 ); + deflate->dup_len = dup_len[index]; + deflate->extra_bits = extra_bits[index]; + if ( index ) + deflate->length = 0; + } + } + + dynamic_litlen_distance_extra: { + int extra; + unsigned int dup_len; + + /* Extract extra bits */ + extra = deflate_extract ( deflate, in, deflate->extra_bits ); + if ( extra < 0 ) { + deflate->resume = &&dynamic_litlen_distance_extra; + return 0; + } + + /* Store code lengths */ + dup_len = ( deflate->dup_len + extra ); + while ( ( deflate->length_index < deflate->length_target ) && + dup_len-- ) { + deflate_set_length ( deflate, deflate->length_index++, + deflate->length ); + } + + /* Process next literal/length or distance code + * length, if more are required. + */ + if ( deflate->length_index < deflate->length_target ) + goto dynamic_litlen_distance; + + /* Construct alphabets */ + goto construct_alphabets; + } + + construct_alphabets: { + unsigned int distance_offset = deflate->litlen_count; + unsigned int distance_count = deflate->distance_count; + int rc; + + /* Generate literal/length alphabet */ + if ( ( rc = deflate_alphabet ( deflate, &deflate->litlen, + deflate->litlen_count, 0 ) ) !=0) + return rc; + + /* Handle degenerate case of a single distance code + * (for which it is impossible to construct a valid, + * complete Huffman alphabet). RFC 1951 states: + * + * If only one distance code is used, it is encoded + * using one bit, not zero bits; in this case there + * is a single code length of one, with one unused + * code. One distance code of zero bits means that + * there are no distance codes used at all (the data + * is all literals). + * + * If we have only a single distance code, then we + * instead use two distance codes both with length 1. + * This results in a valid Huffman alphabet. The code + * "0" will mean distance code 0 (which is either + * correct or irrelevant), and the code "1" will mean + * distance code 1 (which is always irrelevant). + */ + if ( deflate->distance_count == 1 ) { + + deflate->lengths[0] = 0x11; + distance_offset = 0; + distance_count = 2; + } + + /* Generate distance alphabet */ + if ( ( rc = deflate_alphabet ( deflate, + &deflate->distance_codelen, + distance_count, + distance_offset ) ) != 0 ) + return rc; + } + + lzhuf_litlen: { + int code; + uint8_t byte; + unsigned int extra; + unsigned int bits; + + /* Decode Huffman codes */ + while ( 1 ) { + + /* Decode Huffman code */ + code = deflate_decode ( deflate, in, &deflate->litlen ); + if ( code < 0 ) { + deflate->resume = &&lzhuf_litlen; + return 0; + } + + /* Handle according to code type */ + if ( code < DEFLATE_LITLEN_END ) { + + /* Literal value: copy to output buffer */ + byte = code; + DBGCP ( deflate, "DEFLATE %p literal %#02x " + "('%c')\n", deflate, byte, + ( isprint ( byte ) ? byte : '.' ) ); + deflate_copy ( out, virt_to_user ( &byte ), 0, + sizeof ( byte ) ); + + } else if ( code == DEFLATE_LITLEN_END ) { + + /* End of block */ + goto block_done; + + } else { + + /* Length code: process extra bits */ + extra = ( code - DEFLATE_LITLEN_END - 1 ); + if ( extra < 28 ) { + bits = ( extra / 4 ); + if ( bits ) + bits--; + deflate->extra_bits = bits; + deflate->dup_len = + deflate_litlen_base[extra]; + } else { + deflate->extra_bits = 0; + deflate->dup_len = 258; + } + goto lzhuf_litlen_extra; + } + } + } + + lzhuf_litlen_extra: { + int extra; + + /* Extract extra bits */ + extra = deflate_extract ( deflate, in, deflate->extra_bits ); + if ( extra < 0 ) { + deflate->resume = &&lzhuf_litlen_extra; + return 0; + } + + /* Update duplicate length */ + deflate->dup_len += extra; + } + + lzhuf_distance: { + int code; + unsigned int extra; + unsigned int bits; + + /* Decode Huffman code */ + code = deflate_decode ( deflate, in, + &deflate->distance_codelen ); + if ( code < 0 ) { + deflate->resume = &&lzhuf_distance; + return 0; + } + + /* Process extra bits */ + extra = code; + bits = ( extra / 2 ); + if ( bits ) + bits--; + deflate->extra_bits = bits; + deflate->dup_distance = deflate_distance_base[extra]; + } + + lzhuf_distance_extra: { + int extra; + size_t dup_len; + size_t dup_distance; + + /* Extract extra bits */ + extra = deflate_extract ( deflate, in, deflate->extra_bits ); + if ( extra < 0 ) { + deflate->resume = &&lzhuf_distance_extra; + return 0; + } + + /* Update duplicate distance */ + dup_distance = ( deflate->dup_distance + extra ); + dup_len = deflate->dup_len; + DBGCP ( deflate, "DEFLATE %p duplicate length %zd distance " + "%zd\n", deflate, dup_len, dup_distance ); + + /* Sanity check */ + if ( dup_distance > out->offset ) { + DBGC ( deflate, "DEFLATE %p bad distance %zd (max " + "%zd)\n", deflate, dup_distance, out->offset ); + return -EINVAL; + } + + /* Copy data, allowing for overlap */ + deflate_copy ( out, out->data, ( out->offset - dup_distance ), + dup_len ); + + /* Process next literal/length symbol */ + goto lzhuf_litlen; + } + + block_done: { + + DBGCP ( deflate, "DEFLATE %p end of block\n", deflate ); + + /* If this was not the final block, process next block header */ + if ( ! ( deflate->header & ( 1 << DEFLATE_HEADER_BFINAL_BIT ) )) + goto block_header; + + /* Otherwise, process footer (if any) */ + switch ( deflate->format ) { + case DEFLATE_RAW: goto finished; + case DEFLATE_ZLIB: goto zlib_footer; + default: assert ( 0 ); + } + } + + zlib_footer: { + + /* Discard any bits up to the next byte boundary */ + deflate_discard_to_byte ( deflate ); + } + + zlib_adler32: { + int excess; + + /* Accumulate the 32 bits of checksum. We don't check + * the value, stop processing immediately afterwards, + * and so don't have to worry about the nasty corner + * cases involved in calling deflate_extract() to + * obtain a full 32 bits. + */ + excess = deflate_accumulate ( deflate, in, ZLIB_ADLER32_BITS ); + if ( excess < 0 ) { + deflate->resume = &&zlib_adler32; + return 0; + } + + /* Finish processing */ + goto finished; + } + + finished: { + /* Mark as finished and terminate */ + DBGCP ( deflate, "DEFLATE %p finished\n", deflate ); + deflate->resume = NULL; + return 0; + } +} + +/** + * Initialise decompressor + * + * @v deflate Decompressor + * @v format Compression format code + */ +void deflate_init ( struct deflate *deflate, enum deflate_format format ) { + static int global_init_done; + uint8_t i; + uint8_t bit; + uint8_t byte; + unsigned int base; + unsigned int bits; + + /* Perform global initialisation if required */ + if ( ! global_init_done ) { + + /* Initialise byte reversal table */ + for ( i = 255 ; i ; i-- ) { + for ( bit = 1, byte = 0 ; bit ; bit <<= 1 ) { + byte <<= 1; + if ( i & bit ) + byte |= 1; + } + deflate_reverse[i] = byte; + } + + /* Initialise literal/length extra bits table */ + base = 3; + for ( i = 0 ; i < 28 ; i++ ) { + bits = ( i / 4 ); + if ( bits ) + bits--; + deflate_litlen_base[i] = base; + base += ( 1 << bits ); + } + assert ( base == 259 ); /* sic */ + + /* Initialise distance extra bits table */ + base = 1; + for ( i = 0 ; i < 30 ; i++ ) { + bits = ( i / 2 ); + if ( bits ) + bits--; + deflate_distance_base[i] = base; + base += ( 1 << bits ); + } + assert ( base == 32769 ); + + /* Record global initialisation as complete */ + global_init_done = 1; + } + + /* Initialise structure */ + memset ( deflate, 0, sizeof ( *deflate ) ); + deflate->format = format; +} | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/crypto/ocsp.c ^ |
@@ -206,11 +206,12 @@ * @ret rc Return status code */ static int ocsp_uri_string ( struct ocsp_check *ocsp ) { + struct uri path_uri; char *base_uri_string; - char *base64_request; - size_t base64_request_len; - size_t uri_string_len; - size_t prefix_len; + char *path_base64_string; + char *path_uri_string; + size_t path_len; + int len; int rc; /* Sanity check */ @@ -222,44 +223,43 @@ goto err_no_uri; } - /* Base64-encode the request */ - base64_request_len = ( base64_encoded_len ( ocsp->request.builder.len ) - + 1 /* NUL */ ); - base64_request = malloc ( base64_request_len ); - if ( ! base64_request ) { + /* Base64-encode the request as the URI path */ + path_len = ( base64_encoded_len ( ocsp->request.builder.len ) + + 1 /* NUL */ ); + path_base64_string = malloc ( path_len ); + if ( ! path_base64_string ) { rc = -ENOMEM; - goto err_alloc_base64; + goto err_path_base64; } base64_encode ( ocsp->request.builder.data, ocsp->request.builder.len, - base64_request ); + path_base64_string ); - /* Allocate URI string */ - uri_string_len = ( strlen ( base_uri_string ) + 1 /* "/" */ + - uri_encode ( base64_request, NULL, 0, URI_FRAGMENT ) - + 1 /* NUL */ ); - ocsp->uri_string = malloc ( uri_string_len ); - if ( ! ocsp->uri_string ) { + /* URI-encode the Base64-encoded request */ + memset ( &path_uri, 0, sizeof ( path_uri ) ); + path_uri.path = path_base64_string; + path_uri_string = format_uri_alloc ( &path_uri ); + if ( ! path_uri_string ) { rc = -ENOMEM; - goto err_alloc_uri; + goto err_path_uri; } /* Construct URI string */ - prefix_len = snprintf ( ocsp->uri_string, uri_string_len, - "%s/", base_uri_string ); - uri_encode ( base64_request, ( ocsp->uri_string + prefix_len ), - ( uri_string_len - prefix_len ), URI_FRAGMENT ); + if ( ( len = asprintf ( &ocsp->uri_string, "%s/%s", base_uri_string, + path_uri_string ) ) < 0 ) { + rc = len; + goto err_ocsp_uri; + } DBGC2 ( ocsp, "OCSP %p \"%s\" URI is %s\n", ocsp, ocsp->cert->subject.name, ocsp->uri_string ); - /* Free base64-encoded request */ - free ( base64_request ); - base64_request = NULL; - - return 0; - - err_alloc_uri: - free ( base64_request ); - err_alloc_base64: + /* Success */ + rc = 0; + + err_ocsp_uri: + free ( path_uri_string ); + err_path_uri: + free ( path_base64_string ); + err_path_base64: err_no_uri: return rc; } | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/net/intelx.c ^ |
@@ -454,6 +454,8 @@ /** PCI device IDs */ static struct pci_device_id intelx_nics[] = { PCI_ROM ( 0x8086, 0x10fb, "82599", "82599", 0 ), + PCI_ROM ( 0x8086, 0x1528, "x540at2", "X540-AT2", 0 ), + PCI_ROM ( 0x8086, 0x154d, "x520", "X520", 0 ), }; /** PCI driver */ | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/hci/commands/console_cmd.c ^ |
@@ -32,6 +32,7 @@ #include <ipxe/console.h> #include <ipxe/image.h> #include <ipxe/pixbuf.h> +#include <ipxe/ansiesc.h> #include <ipxe/ansicol.h> #include <usr/imgmgmt.h> @@ -51,8 +52,16 @@ struct console_options, config.width, parse_integer ), OPTION_DESC ( "y", 'y', required_argument, struct console_options, config.height, parse_integer ), - OPTION_DESC ( "bpp", 'b', required_argument, - struct console_options, config.bpp, parse_integer ), + OPTION_DESC ( "left", 'l', required_argument, + struct console_options, config.left, parse_integer ), + OPTION_DESC ( "right", 'r', required_argument, + struct console_options, config.right, parse_integer ), + OPTION_DESC ( "top", 't', required_argument, + struct console_options, config.top, parse_integer ), + OPTION_DESC ( "bottom", 'b', required_argument, + struct console_options, config.bottom, parse_integer ), + OPTION_DESC ( "depth", 'd', required_argument, + struct console_options, config.depth, parse_integer ), OPTION_DESC ( "picture", 'p', required_argument, struct console_options, picture, parse_string ), OPTION_DESC ( "keep", 'k', no_argument, @@ -106,6 +115,10 @@ goto err_configure; } + /* Reapply default colour pair and clear screen */ + ansicol_set_pair ( CPAIR_DEFAULT ); + printf ( CSI "2J" CSI "H" ); + err_configure: pixbuf_put ( opts.config.pixbuf ); err_pixbuf: | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/hci/commands/param_cmd.c ^ |
@@ -74,8 +74,10 @@ return -ENOMEM; /* Destroy parameter list, if applicable */ - if ( opts.delete ) - destroy_parameters ( params ); + if ( opts.delete ) { + claim_parameters ( params ); + params_put ( params ); + } return 0; } | ||
[-] [+] | Added | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/image/png.c ^ |
@@ -0,0 +1,1007 @@ +/* + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#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 ( ¤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, +}; | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ctype.h ^ |
@@ -12,6 +12,7 @@ #define islower(c) ((c) >= 'a' && (c) <= 'z') #define isupper(c) ((c) >= 'A' && (c) <= 'Z') #define isxdigit(c) (isdigit(c) || ((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f')) +#define isprint(c) ((c) >= ' ' && (c) <= '~' ) static inline unsigned char tolower(unsigned char c) { | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/console.h ^ |
@@ -27,7 +27,15 @@ /** Height */ unsigned int height; /** Colour depth */ - unsigned int bpp; + unsigned int depth; + /** Left margin */ + unsigned int left; + /** Right margin */ + unsigned int right; + /** Top margin */ + unsigned int top; + /** Bottom margin */ + unsigned int bottom; /** Background picture, if any */ struct pixel_buffer *pixbuf; }; | ||
[-] [+] | Added | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/deflate.h ^ |
@@ -0,0 +1,283 @@ +#ifndef _IPXE_DEFLATE_H +#define _IPXE_DEFLATE_H + +/** @file + * + * DEFLATE decompression algorithm + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <string.h> +#include <ipxe/uaccess.h> + +/** Compression formats */ +enum deflate_format { + /** Raw DEFLATE data (no header or footer) */ + DEFLATE_RAW, + /** ZLIB header and footer */ + DEFLATE_ZLIB, +}; + +/** Block header length (in bits) */ +#define DEFLATE_HEADER_BITS 3 + +/** Block header final block flags bit */ +#define DEFLATE_HEADER_BFINAL_BIT 0 + +/** Block header type LSB */ +#define DEFLATE_HEADER_BTYPE_LSB 1 + +/** Block header type mask */ +#define DEFLATE_HEADER_BTYPE_MASK 0x03 + +/** Block header type: literal data */ +#define DEFLATE_HEADER_BTYPE_LITERAL 0 + +/** Block header type: static Huffman alphabet */ +#define DEFLATE_HEADER_BTYPE_STATIC 1 + +/** Block header type: dynamic Huffman alphabet */ +#define DEFLATE_HEADER_BTYPE_DYNAMIC 2 + +/** Literal header LEN/NLEN field length (in bits) */ +#define DEFLATE_LITERAL_LEN_BITS 16 + +/** Dynamic header length (in bits) */ +#define DEFLATE_DYNAMIC_BITS 14 + +/** Dynamic header HLIT field LSB */ +#define DEFLATE_DYNAMIC_HLIT_LSB 0 + +/** Dynamic header HLIT field mask */ +#define DEFLATE_DYNAMIC_HLIT_MASK 0x1f + +/** Dynamic header HDIST field LSB */ +#define DEFLATE_DYNAMIC_HDIST_LSB 5 + +/** Dynamic header HDIST field mask */ +#define DEFLATE_DYNAMIC_HDIST_MASK 0x1f + +/** Dynamic header HCLEN field LSB */ +#define DEFLATE_DYNAMIC_HCLEN_LSB 10 + +/** Dynamic header HCLEN field mask */ +#define DEFLATE_DYNAMIC_HCLEN_MASK 0x0f + +/** Dynamic header code length length (in bits) */ +#define DEFLATE_CODELEN_BITS 3 + +/** Maximum length of a Huffman symbol (in bits) */ +#define DEFLATE_HUFFMAN_BITS 15 + +/** Quick lookup length for a Huffman symbol (in bits) + * + * This is a policy decision. + */ +#define DEFLATE_HUFFMAN_QL_BITS 7 + +/** Quick lookup shift */ +#define DEFLATE_HUFFMAN_QL_SHIFT ( 16 - DEFLATE_HUFFMAN_QL_BITS ) + +/** Literal/length end of block code */ +#define DEFLATE_LITLEN_END 256 + +/** Maximum value of a literal/length code */ +#define DEFLATE_LITLEN_MAX_CODE 287 + +/** Maximum value of a distance code */ +#define DEFLATE_DISTANCE_MAX_CODE 31 + +/** Maximum value of a code length code */ +#define DEFLATE_CODELEN_MAX_CODE 18 + +/** ZLIB header length (in bits) */ +#define ZLIB_HEADER_BITS 16 + +/** ZLIB header compression method LSB */ +#define ZLIB_HEADER_CM_LSB 0 + +/** ZLIB header compression method mask */ +#define ZLIB_HEADER_CM_MASK 0x0f + +/** ZLIB header compression method: DEFLATE */ +#define ZLIB_HEADER_CM_DEFLATE 8 + +/** ZLIB header preset dictionary flag bit */ +#define ZLIB_HEADER_FDICT_BIT 13 + +/** ZLIB ADLER32 length (in bits) */ +#define ZLIB_ADLER32_BITS 32 + +/** A Huffman-coded set of symbols of a given length */ +struct deflate_huf_symbols { + /** Length of Huffman-coded symbols */ + uint8_t bits; + /** Shift to normalise symbols of this length to 16 bits */ + uint8_t shift; + /** Number of Huffman-coded symbols having this length */ + uint16_t freq; + /** First symbol of this length (normalised to 16 bits) + * + * Stored as a 32-bit value to allow the value 0x10000 to be + * used for empty sets of symbols longer than the maximum + * utilised length. + */ + uint32_t start; + /** Raw symbols having this length */ + uint16_t *raw; +}; + +/** A Huffman-coded alphabet */ +struct deflate_alphabet { + /** Huffman-coded symbol set for each length */ + struct deflate_huf_symbols huf[DEFLATE_HUFFMAN_BITS]; + /** Quick lookup table */ + uint8_t lookup[ 1 << DEFLATE_HUFFMAN_QL_BITS ]; + /** Raw symbols + * + * Ordered by Huffman-coded symbol length, then by symbol + * value. This field has a variable length. + */ + uint16_t raw[0]; +}; + +/** A static Huffman alphabet length pattern */ +struct deflate_static_length_pattern { + /** Length pair */ + uint8_t fill; + /** Repetition count */ + uint8_t count; +} __attribute__ (( packed )); + +/** Decompressor */ +struct deflate { + /** Resume point + * + * Used as the target of a computed goto to jump to the + * appropriate point within the state machine. + */ + void *resume; + /** Format */ + enum deflate_format format; + + /** Accumulator */ + uint32_t accumulator; + /** Bit-reversed accumulator + * + * Don't ask. + */ + uint32_t rotalumucca; + /** Number of bits within the accumulator */ + unsigned int bits; + + /** Current block header */ + unsigned int header; + /** Remaining length of data (e.g. within a literal block) */ + size_t remaining; + /** Current length index within a set of code lengths */ + unsigned int length_index; + /** Target length index within a set of code lengths */ + unsigned int length_target; + /** Current length within a set of code lengths */ + unsigned int length; + /** Number of extra bits required */ + unsigned int extra_bits; + /** Length of a duplicated string */ + size_t dup_len; + /** Distance of a duplicated string */ + size_t dup_distance; + + /** Literal/length Huffman alphabet */ + struct deflate_alphabet litlen; + /** Literal/length raw symbols + * + * Must immediately follow the literal/length Huffman alphabet. + */ + uint16_t litlen_raw[ DEFLATE_LITLEN_MAX_CODE + 1 ]; + /** Number of symbols in the literal/length Huffman alphabet */ + unsigned int litlen_count; + + /** Distance and code length Huffman alphabet + * + * The code length Huffman alphabet has a maximum Huffman + * symbol length of 7 and a maximum code value of 18, and is + * thus strictly smaller than the distance Huffman alphabet. + * Since we never need both alphabets simultaneously, we can + * reuse the storage space for the distance alphabet to + * temporarily hold the code length alphabet. + */ + struct deflate_alphabet distance_codelen; + /** Distance and code length raw symbols + * + * Must immediately follow the distance and code length + * Huffman alphabet. + */ + uint16_t distance_codelen_raw[ DEFLATE_DISTANCE_MAX_CODE + 1 ]; + /** Number of symbols in the distance Huffman alphabet */ + unsigned int distance_count; + + /** Huffman code lengths + * + * The literal/length and distance code lengths are + * constructed as a single set of lengths. + * + * The code length Huffman alphabet has a maximum code value + * of 18 and the set of lengths is thus strictly smaller than + * the combined literal/length and distance set of lengths. + * Since we never need both alphabets simultaneously, we can + * reuse the storage space for the literal/length and distance + * code lengths to temporarily hold the code length code + * lengths. + */ + uint8_t lengths[ ( ( DEFLATE_LITLEN_MAX_CODE + 1 ) + + ( DEFLATE_DISTANCE_MAX_CODE + 1 ) + + 1 /* round up */ ) / 2 ]; +}; + +/** A chunk of data */ +struct deflate_chunk { + /** Data */ + userptr_t data; + /** Current offset */ + size_t offset; + /** Length of data */ + size_t len; +}; + +/** + * Initialise chunk of data + * + * @v chunk Chunk of data to initialise + * @v data Data + * @v offset Starting offset + * @v len Length + */ +static inline __attribute__ (( always_inline )) void +deflate_chunk_init ( struct deflate_chunk *chunk, userptr_t data, + size_t offset, size_t len ) { + + chunk->data = data; + chunk->offset = offset; + chunk->len = len; +} + +/** + * Check if decompression has finished + * + * @v deflate Decompressor + * @ret finished Decompression has finished + */ +static inline int deflate_finished ( struct deflate *deflate ) { + return ( deflate->resume == NULL ); +} + +extern void deflate_init ( struct deflate *deflate, + enum deflate_format format ); +extern int deflate_inflate ( struct deflate *deflate, + struct deflate_chunk *in, + struct deflate_chunk *out ); + +#endif /* _IPXE_DEFLATE_H */ | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/dhcp.h ^ |
@@ -290,6 +290,9 @@ #define DHCP_CLIENT_UUID_TYPE 0 +/** DNS domain search list */ +#define DHCP_DOMAIN_SEARCH 119 + /** Etherboot-specific encapsulated options * * This encapsulated options field is used to contain all options | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/dns.h ^ |
@@ -12,88 +12,144 @@ #include <stdint.h> #include <ipxe/in.h> -/* - * Constants +/** DNS server port */ +#define DNS_PORT 53 + +/** An RFC1035-encoded DNS name */ +struct dns_name { + /** Start of data */ + void *data; + /** Offset of name within data */ + size_t offset; + /** Total length of data */ + size_t len; +}; + +/** + * Test for a DNS compression pointer * + * @v byte Initial byte + * @ret is_compressed Is a compression pointer */ +#define DNS_IS_COMPRESSED( byte ) ( (byte) & 0xc0 ) -#define DNS_TYPE_A 1 -#define DNS_TYPE_CNAME 5 -#define DNS_TYPE_AAAA 28 -#define DNS_TYPE_ANY 255 - -#define DNS_CLASS_IN 1 -#define DNS_CLASS_CS 2 -#define DNS_CLASS_CH 3 -#define DNS_CLASS_HS 4 - -#define DNS_FLAG_QUERY ( 0x00 << 15 ) -#define DNS_FLAG_RESPONSE ( 0x01 << 15 ) -#define DNS_FLAG_QR(flags) ( (flags) & ( 0x01 << 15 ) ) -#define DNS_FLAG_OPCODE_QUERY ( 0x00 << 11 ) -#define DNS_FLAG_OPCODE_IQUERY ( 0x01 << 11 ) -#define DNS_FLAG_OPCODE_STATUS ( 0x02 << 11 ) -#define DNS_FLAG_OPCODE(flags) ( (flags) & ( 0x0f << 11 ) ) -#define DNS_FLAG_RD ( 0x01 << 8 ) -#define DNS_FLAG_RA ( 0x01 << 7 ) -#define DNS_FLAG_RCODE_OK ( 0x00 << 0 ) -#define DNS_FLAG_RCODE_NX ( 0x03 << 0 ) -#define DNS_FLAG_RCODE(flags) ( (flags) & ( 0x0f << 0 ) ) - -#define DNS_PORT 53 -#define DNS_MAX_RETRIES 3 -#define DNS_MAX_CNAME_RECURSION 0x30 +/** + * Extract DNS compression pointer + * + * @v word Initial word + * @ret offset Offset + */ +#define DNS_COMPRESSED_OFFSET( word ) ( (word) & ~0xc000 ) -/* - * DNS protocol structures +/** + * Extract DNS label length * + * @v byte Initial byte + * @ret len Label length */ -struct dns_header { - uint16_t id; - uint16_t flags; - uint16_t qdcount; - uint16_t ancount; - uint16_t nscount; - uint16_t arcount; -} __attribute__ (( packed )); +#define DNS_LABEL_LEN( byte ) ( (byte) & ~0xc0 ) -struct dns_query_info { - uint16_t qtype; - uint16_t qclass; -} __attribute__ (( packed )); +/** Maximum length of a single DNS label */ +#define DNS_MAX_LABEL_LEN 0x3f -struct dns_query { - struct dns_header dns; - char payload[ 256 + sizeof ( struct dns_query_info ) ]; -} __attribute__ (( packed )); +/** Maximum length of a DNS name (mandated by RFC1035 section 2.3.4) */ +#define DNS_MAX_NAME_LEN 255 -struct dns_rr_info_common { - uint16_t type; - uint16_t class; - uint32_t ttl; - uint16_t rdlength; -} __attribute__ (( packed )); +/** Maximum depth of CNAME recursion + * + * This is a policy decision. + */ +#define DNS_MAX_CNAME_RECURSION 32 -struct dns_rr_info_a { - struct dns_rr_info_common common; +/** A DNS packet header */ +struct dns_header { + /** Query identifier */ + uint16_t id; + /** Flags */ + uint16_t flags; + /** Number of question records */ + uint16_t qdcount; + /** Number of answer records */ + uint16_t ancount; + /** Number of name server records */ + uint16_t nscount; + /** Number of additional records */ + uint16_t arcount; +} __attribute__ (( packed )); + +/** Recursion desired flag */ +#define DNS_FLAG_RD 0x0100 + +/** A DNS question */ +struct dns_question { + /** Query type */ + uint16_t qtype; + /** Query class */ + uint16_t qclass; +} __attribute__ (( packed )); + +/** DNS class "IN" */ +#define DNS_CLASS_IN 1 + +/** A DNS resource record */ +struct dns_rr_common { + /** Type */ + uint16_t type; + /** Class */ + uint16_t class; + /** Time to live */ + uint32_t ttl; + /** Resource data length */ + uint16_t rdlength; +} __attribute__ (( packed )); + +/** Type of a DNS "A" record */ +#define DNS_TYPE_A 1 + +/** A DNS "A" record */ +struct dns_rr_a { + /** Common fields */ + struct dns_rr_common common; + /** IPv4 address */ struct in_addr in_addr; } __attribute__ (( packed )); -struct dns_rr_info_aaaa { - struct dns_rr_info_common common; +/** Type of a DNS "AAAA" record */ +#define DNS_TYPE_AAAA 28 + +/** A DNS "AAAA" record */ +struct dns_rr_aaaa { + /** Common fields */ + struct dns_rr_common common; + /** IPv6 address */ struct in6_addr in6_addr; } __attribute__ (( packed )); -struct dns_rr_info_cname { - struct dns_rr_info_common common; - char cname[0]; -} __attribute__ (( packed )); +/** Type of a DNS "NAME" record */ +#define DNS_TYPE_CNAME 5 -union dns_rr_info { - struct dns_rr_info_common common; - struct dns_rr_info_a a; - struct dns_rr_info_aaaa aaaa; - struct dns_rr_info_cname cname; +/** A DNS "CNAME" record */ +struct dns_rr_cname { + /** Common fields */ + struct dns_rr_common common; +} __attribute__ (( packed )); + +/** A DNS resource record */ +union dns_rr { + /** Common fields */ + struct dns_rr_common common; + /** "A" record */ + struct dns_rr_a a; + /** "AAAA" record */ + struct dns_rr_aaaa aaaa; + /** "CNAME" record */ + struct dns_rr_cname cname; }; +extern int dns_encode ( const char *string, struct dns_name *name ); +extern int dns_decode ( struct dns_name *name, char *data, size_t len ); +extern int dns_compare ( struct dns_name *first, struct dns_name *second ); +extern int dns_copy ( struct dns_name *src, struct dns_name *dst ); +extern int dns_skip ( struct dns_name *name ); + #endif /* _IPXE_DNS_H */ | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/downloader.h ^ |
@@ -12,7 +12,6 @@ struct interface; struct image; -extern int create_downloader ( struct interface *job, struct image *image, - int type, ... ); +extern int create_downloader ( struct interface *job, struct image *image ); #endif /* _IPXE_DOWNLOADER_H */ | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/efi/efi_uaccess.h ^ |
@@ -76,6 +76,13 @@ trivial_memmove_user ( dest, dest_off, src, src_off, len ); } +static inline __always_inline int +UACCESS_INLINE ( efi, memcmp_user ) ( userptr_t first, off_t first_off, + userptr_t second, off_t second_off, + size_t len ) { + return trivial_memcmp_user ( first, first_off, second, second_off, len); +} + static inline __always_inline void UACCESS_INLINE ( efi, memset_user ) ( userptr_t buffer, off_t offset, int c, size_t len ) { | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/errfile.h ^ |
@@ -231,6 +231,7 @@ #define ERRFILE_efi_image ( ERRFILE_IMAGE | 0x00040000 ) #define ERRFILE_embedded ( ERRFILE_IMAGE | 0x00050000 ) #define ERRFILE_pnm ( ERRFILE_IMAGE | 0x00060000 ) +#define ERRFILE_png ( ERRFILE_IMAGE | 0x00070000 ) #define ERRFILE_asn1 ( ERRFILE_OTHER | 0x00000000 ) #define ERRFILE_chap ( ERRFILE_OTHER | 0x00010000 ) @@ -297,6 +298,7 @@ #define ERRFILE_efi_reboot ( ERRFILE_OTHER | 0x003e0000 ) #define ERRFILE_memmap_settings ( ERRFILE_OTHER | 0x003f0000 ) #define ERRFILE_param_cmd ( ERRFILE_OTHER | 0x00400000 ) +#define ERRFILE_deflate ( ERRFILE_OTHER | 0x00410000 ) /** @} */ | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/fbcon.h ^ |
@@ -103,14 +103,6 @@ struct fbcon_picture { /** Start address */ userptr_t start; - /** Pixel geometry */ - struct fbcon_geometry pixel; - /** Character geometry */ - struct fbcon_geometry character; - /** Margin */ - struct fbcon_margin margin; - /** Indent to first character (in bytes) */ - size_t indent; }; /** A frame buffer console */ @@ -153,6 +145,7 @@ extern int fbcon_init ( struct fbcon *fbcon, userptr_t start, struct fbcon_geometry *pixel, + struct fbcon_margin *margin, struct fbcon_colour_map *map, struct fbcon_font *font, struct pixel_buffer *pixbuf ); | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/linux/linux_uaccess.h ^ |
@@ -89,6 +89,12 @@ trivial_memmove_user(dest, dest_off, src, src_off, len); } +static inline __always_inline int +UACCESS_INLINE(linux, memcmp_user)(userptr_t first, off_t first_off, userptr_t second, off_t second_off, size_t len) +{ + return trivial_memcmp_user(first, first_off, second, second_off, len); +} + static inline __always_inline void UACCESS_INLINE(linux, memset_user)(userptr_t buffer, off_t offset, int c, size_t len) { | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/params.h ^ |
@@ -14,6 +14,8 @@ /** A form parameter list */ struct parameters { + /** Reference count */ + struct refcnt refcnt; /** List of all parameter lists */ struct list_head list; /** Name */ @@ -32,6 +34,43 @@ const char *value; }; +/** + * Increment form parameter list reference count + * + * @v params Parameter list, or NULL + * @ret params Parameter list as passed in + */ +static inline __attribute__ (( always_inline )) struct parameters * +params_get ( struct parameters *params ) { + ref_get ( ¶ms->refcnt ); + return params; +} + +/** + * Decrement form parameter list reference count + * + * @v params Parameter list, or NULL + */ +static inline __attribute__ (( always_inline )) void +params_put ( struct parameters *params ) { + ref_put ( ¶ms->refcnt ); +} + +/** + * Claim ownership of form parameter list + * + * @v params Parameter list + * @ret params Parameter list + */ +static inline __attribute__ (( always_inline )) struct parameters * +claim_parameters ( struct parameters *params ) { + + /* Remove from list of parameter lists */ + list_del ( ¶ms->list ); + + return params; +} + /** Iterate over all form parameters in a list */ #define for_each_param( param, params ) \ list_for_each_entry ( (param), &(params)->entries, list ) @@ -40,7 +79,5 @@ extern struct parameters * create_parameters ( const char *name ); extern struct parameter * add_parameter ( struct parameters *params, const char *key, const char *value ); -extern void destroy_parameters ( struct parameters *params ); -extern void claim_parameters ( struct parameters *params ); #endif /* _IPXE_PARAMS_H */ | ||
[-] [+] | Added | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/png.h ^ |
@@ -0,0 +1,179 @@ +#ifndef _IPXE_PNG_H +#define _IPXE_PNG_H + +/** @file + * + * Portable Network Graphics (PNG) format + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <byteswap.h> +#include <ipxe/image.h> + +/** A PNG file signature */ +struct png_signature { + /** Signature bytes */ + uint8_t bytes[8]; +} __attribute__ (( packed )); + +/** PNG file signature */ +#define PNG_SIGNATURE { { 0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n' } } + +/** A PNG chunk header */ +struct png_chunk_header { + /** Length of the chunk (excluding header and footer) */ + uint32_t len; + /** Chunk type */ + uint32_t type; +} __attribute__ (( packed )); + +/** A PNG chunk footer */ +struct png_chunk_footer { + /** CRC */ + uint32_t crc; +} __attribute__ (( packed )); + +/** PNG chunk type property bits */ +enum png_chunk_type_bits { + /** Chunk is ancillary */ + PNG_CHUNK_ANCILLARY = 0x20000000UL, + /** Chunk is private */ + PNG_CHUNK_PRIVATE = 0x00200000UL, + /** Reserved */ + PNG_CHUNK_RESERVED = 0x00002000UL, + /** Chunk is safe to copy */ + PNG_CHUNK_SAFE = 0x00000020UL, +}; + +/** + * Canonicalise PNG chunk type + * + * @v type Raw chunk type + * @ret type Canonicalised chunk type (excluding property bits) + */ +static inline __attribute__ (( always_inline )) uint32_t +png_canonical_type ( uint32_t type ) { + return ( type & ~( htonl ( PNG_CHUNK_ANCILLARY | PNG_CHUNK_PRIVATE | + PNG_CHUNK_RESERVED | PNG_CHUNK_SAFE ) ) ); +} + +/** + * Define a canonical PNG chunk type + * + * @v first First letter (in upper case) + * @v second Second letter (in upper case) + * @v third Third letter (in upper case) + * @v fourth Fourth letter (in upper case) + * @ret type Canonical chunk type + */ +#define PNG_TYPE( first, second, third, fourth ) \ + ( ( (first) << 24 ) | ( (second) << 16 ) | ( (third) << 8 ) | (fourth) ) + +/** PNG image header chunk type */ +#define PNG_TYPE_IHDR PNG_TYPE ( 'I', 'H', 'D', 'R' ) + +/** A PNG image header */ +struct png_image_header { + /** Width */ + uint32_t width; + /** Height */ + uint32_t height; + /** Bit depth */ + uint8_t depth; + /** Colour type */ + uint8_t colour_type; + /** Compression method */ + uint8_t compression; + /** Filter method */ + uint8_t filter; + /** Interlace method */ + uint8_t interlace; +} __attribute__ (( packed )); + +/** PNG colour type bits */ +enum png_colour_type { + /** Palette is used */ + PNG_COLOUR_TYPE_PALETTE = 0x01, + /** RGB colour is used */ + PNG_COLOUR_TYPE_RGB = 0x02, + /** Alpha channel is used */ + PNG_COLOUR_TYPE_ALPHA = 0x04, +}; + +/** PNG colour type mask */ +#define PNG_COLOUR_TYPE_MASK 0x07 + +/** PNG compression methods */ +enum png_compression_method { + /** DEFLATE compression with 32kB sliding window */ + PNG_COMPRESSION_DEFLATE = 0x00, + /** First unknown compression method */ + PNG_COMPRESSION_UNKNOWN = 0x01, +}; + +/** PNG filter methods */ +enum png_filter_method { + /** Adaptive filtering with five basic types */ + PNG_FILTER_BASIC = 0x00, + /** First unknown filter method */ + PNG_FILTER_UNKNOWN = 0x01, +}; + +/** PNG interlace methods */ +enum png_interlace_method { + /** No interlacing */ + PNG_INTERLACE_NONE = 0x00, + /** Adam7 interlacing */ + PNG_INTERLACE_ADAM7 = 0x01, + /** First unknown interlace method */ + PNG_INTERLACE_UNKNOWN = 0x02, +}; + +/** PNG palette chunk type */ +#define PNG_TYPE_PLTE PNG_TYPE ( 'P', 'L', 'T', 'E' ) + +/** A PNG palette entry */ +struct png_palette_entry { + /** Red */ + uint8_t red; + /** Green */ + uint8_t green; + /** Blue */ + uint8_t blue; +} __attribute__ (( packed )); + +/** A PNG palette chunk */ +struct png_palette { + /** Palette entries */ + struct png_palette_entry entries[0]; +} __attribute__ (( packed )); + +/** Maximum number of PNG palette entries */ +#define PNG_PALETTE_COUNT 256 + +/** PNG image data chunk type */ +#define PNG_TYPE_IDAT PNG_TYPE ( 'I', 'D', 'A', 'T' ) + +/** PNG basic filter types */ +enum png_basic_filter_type { + /** No filtering */ + PNG_FILTER_BASIC_NONE = 0, + /** Left byte used as predictor */ + PNG_FILTER_BASIC_SUB = 1, + /** Above byte used as predictor */ + PNG_FILTER_BASIC_UP = 2, + /** Above and left bytes used as predictors */ + PNG_FILTER_BASIC_AVERAGE = 3, + /** Paeth filter */ + PNG_FILTER_BASIC_PAETH = 4, +}; + +/** PNG image end chunk type */ +#define PNG_TYPE_IEND PNG_TYPE ( 'I', 'E', 'N', 'D' ) + +extern struct image_type png_image_type __image_type ( PROBE_NORMAL ); + +#endif /* _IPXE_PNG_H */ | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/settings.h ^ |
@@ -417,6 +417,7 @@ extern const struct setting_type setting_type_hexraw __setting_type; extern const struct setting_type setting_type_uuid __setting_type; extern const struct setting_type setting_type_busdevfn __setting_type; +extern const struct setting_type setting_type_dnssl __setting_type; extern const struct setting ip_setting __setting ( SETTING_IP, ip ); | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/test.h ^ |
@@ -38,9 +38,12 @@ * Report test result * * @v success Test succeeded + * @v file File name + * @v line Line number */ -#define ok( success ) do { \ - test_ok ( (success), __FILE__, __LINE__, #success ); \ - } while ( 0 ) +#define okx( success, file, line ) \ + test_ok ( success, file, line, #success ) +#define ok( success ) \ + okx ( success, __FILE__, __LINE__ ) #endif /* _IPXE_TEST_H */ | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/uaccess.h ^ |
@@ -127,6 +127,23 @@ } /** + * Compare data between user buffers + * + * @v first First buffer + * @v first_off First buffer offset + * @v second Second buffer + * @v second_off Second buffer offset + * @v len Length + * @ret diff Difference + */ +static inline __always_inline int +trivial_memcmp_user ( userptr_t first, off_t first_off, + userptr_t second, off_t second_off, size_t len ) { + return memcmp ( ( ( void * ) first + first_off ), + ( ( void * ) second + second_off ), len ); +} + +/** * Fill user buffer with a constant byte * * @v buffer User buffer @@ -334,6 +351,19 @@ userptr_t src, off_t src_off, size_t len ); /** + * Compare data between user buffers + * + * @v first First buffer + * @v first_off First buffer offset + * @v second Second buffer + * @v second_off Second buffer offset + * @v len Length + * @ret diff Difference + */ +int memcmp_user ( userptr_t first, off_t first_off, + userptr_t second, off_t second_off, size_t len ); + +/** * Fill user buffer with a constant byte * * @v userptr User buffer | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/uri.h ^ |
@@ -12,6 +12,7 @@ #include <stddef.h> #include <stdlib.h> #include <ipxe/refcnt.h> +#include <ipxe/in.h> struct parameters; @@ -71,38 +72,39 @@ struct parameters *params; } __attribute__ (( packed )); -/** A field in a URI +/** + * Access URI field * - * The order of the indices in this enumeration must match the order - * of the fields in the URI structure. - */ -enum { - URI_SCHEME = 0, URI_SCHEME_BIT = ( 1 << URI_SCHEME ), - URI_OPAQUE = 1, URI_OPAQUE_BIT = ( 1 << URI_OPAQUE ), - URI_USER = 2, URI_USER_BIT = ( 1 << URI_USER ), - URI_PASSWORD = 3, URI_PASSWORD_BIT = ( 1 << URI_PASSWORD ), - URI_HOST = 4, URI_HOST_BIT = ( 1 << URI_HOST ), - URI_PORT = 5, URI_PORT_BIT = ( 1 << URI_PORT ), - URI_PATH = 6, URI_PATH_BIT = ( 1 << URI_PATH ), - URI_QUERY = 7, URI_QUERY_BIT = ( 1 << URI_QUERY ), - URI_FRAGMENT = 8, URI_FRAGMENT_BIT = ( 1 << URI_FRAGMENT ), - - URI_FIRST_FIELD = URI_SCHEME, - URI_LAST_FIELD = URI_FRAGMENT, + * @v uri URI + * @v field URI field index + * @ret field URI field (as an lvalue) + */ +#define uri_field( uri, field ) (&uri->scheme)[field] + +/** + * Calculate index of a URI field + * + * @v name URI field name + * @ret field URI field index + */ +#define URI_FIELD( name ) \ + ( ( offsetof ( struct uri, name ) - \ + offsetof ( struct uri, scheme ) ) / sizeof ( void * ) ) + +/** URI fields */ +enum uri_fields { + URI_SCHEME = URI_FIELD ( scheme ), + URI_OPAQUE = URI_FIELD ( opaque ), + URI_USER = URI_FIELD ( user ), + URI_PASSWORD = URI_FIELD ( password ), + URI_HOST = URI_FIELD ( host ), + URI_PORT = URI_FIELD ( port ), + URI_PATH = URI_FIELD ( path ), + URI_QUERY = URI_FIELD ( query ), + URI_FRAGMENT = URI_FIELD ( fragment ), + URI_FIELDS }; -/** Extract field from URI */ -#define uri_get_field( uri, field ) (&uri->scheme)[field] - -/** All URI fields */ -#define URI_ALL ( URI_SCHEME_BIT | URI_OPAQUE_BIT | URI_USER_BIT | \ - URI_PASSWORD_BIT | URI_HOST_BIT | URI_PORT_BIT | \ - URI_PATH_BIT | URI_QUERY_BIT | URI_FRAGMENT_BIT ) - -/** URI fields that should be decoded on storage */ -#define URI_ENCODED ( URI_USER_BIT | URI_PASSWORD_BIT | URI_HOST_BIT | \ - URI_PATH_BIT | URI_QUERY_BIT | URI_FRAGMENT_BIT ) - /** * URI is an absolute URI * @@ -125,8 +127,8 @@ */ static inline int uri_has_opaque ( const struct uri *uri ) { return ( uri->opaque && ( uri->opaque[0] != '\0' ) ); - } + /** * URI has a path * @@ -189,18 +191,20 @@ extern struct uri *cwuri; +extern size_t uri_encode ( const char *string, unsigned int field, + char *buf, ssize_t len ); extern struct uri * parse_uri ( const char *uri_string ); -extern unsigned int uri_port ( struct uri *uri, unsigned int default_port ); -extern int unparse_uri ( char *buf, size_t size, struct uri *uri, - unsigned int fields ); -extern struct uri * uri_dup ( struct uri *uri ); +extern size_t format_uri ( const struct uri *uri, char *buf, size_t len ); +extern char * format_uri_alloc ( const struct uri *uri ); +extern unsigned int uri_port ( const struct uri *uri, + unsigned int default_port ); +extern struct uri * uri_dup ( const struct uri *uri ); extern char * resolve_path ( const char *base_path, const char *relative_path ); -extern struct uri * resolve_uri ( struct uri *base_uri, +extern struct uri * resolve_uri ( const struct uri *base_uri, struct uri *relative_uri ); +extern struct uri * tftp_uri ( struct in_addr next_server, + const char *filename ); extern void churi ( struct uri *uri ); -extern size_t uri_encode ( const char *raw_string, char *buf, ssize_t len, - int field ); -extern size_t uri_decode ( const char *encoded_string, char *buf, ssize_t len ); #endif /* _IPXE_URI_H */ | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/stdlib.h ^ |
@@ -93,6 +93,10 @@ **************************************************************************** */ +static inline __attribute__ (( always_inline )) int abs ( int value ) { + return __builtin_abs ( value ); +} + extern int system ( const char *command ); extern __asmcall int main ( void ); | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/dhcpopts.c ^ |
@@ -202,7 +202,6 @@ size_t new_encapsulator_len; void *source; void *dest; - void *end; int rc; /* Check for sufficient space */ @@ -245,8 +244,7 @@ option = dhcp_option ( options, offset ); source = ( ( ( void * ) option ) + old_len ); dest = ( ( ( void * ) option ) + new_len ); - end = ( options->data + options->alloc_len ); - memmove ( dest, source, ( end - dest ) ); + memmove ( dest, source, ( new_used_len - offset - new_len ) ); /* Shrink options block, if applicable */ if ( new_used_len < options->alloc_len ) { | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/ndp.c ^ |
@@ -786,6 +786,16 @@ .scope = &ndp_settings_scope, }; +/** DNS search list setting */ +const struct setting ndp_dnssl_setting __setting ( SETTING_IP_EXTRA, dnssl ) = { + .name = "dnssl", + .description = "DNS search list", + .tag = NDP_TAG ( NDP_OPT_DNSSL, + offsetof ( struct ndp_dnssl_option, names ) ), + .type = &setting_type_dnssl, + .scope = &ndp_settings_scope, +}; + /**************************************************************************** * * IPv6 autoconfiguration | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/tcp/ftp.c ^ |
@@ -23,6 +23,7 @@ #include <string.h> #include <assert.h> #include <errno.h> +#include <ctype.h> #include <byteswap.h> #include <ipxe/socket.h> #include <ipxe/tcpip.h> @@ -460,6 +461,25 @@ */ /** + * Check validity of FTP control channel string + * + * @v string String + * @ret rc Return status code + */ +static int ftp_check_string ( const char *string ) { + char c; + + /* The FTP control channel is line-based. Check for invalid + * non-printable characters (e.g. newlines). + */ + while ( ( c = *(string++) ) ) { + if ( ! isprint ( c ) ) + return -EINVAL; + } + return 0; +} + +/** * Initiate an FTP connection * * @v xfer Data transfer interface @@ -472,10 +492,17 @@ int rc; /* Sanity checks */ - if ( ! uri->path ) - return -EINVAL; if ( ! uri->host ) return -EINVAL; + if ( ! uri->path ) + return -EINVAL; + if ( ( rc = ftp_check_string ( uri->path ) ) != 0 ) + return rc; + if ( uri->user && ( ( rc = ftp_check_string ( uri->user ) ) != 0 ) ) + return rc; + if ( uri->password && + ( ( rc = ftp_check_string ( uri->password ) ) != 0 ) ) + return rc; /* Allocate and populate structure */ ftp = zalloc ( sizeof ( *ftp ) ); | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/tcp/httpcore.c ^ |
@@ -958,8 +958,8 @@ */ static char * http_basic_auth ( struct http_request *http ) { const char *user = http->uri->user; - const char *password = - ( http->uri->password ? http->uri->password : "" ); + const char *password = ( http->uri->password ? + http->uri->password : "" ); size_t user_pw_len = ( strlen ( user ) + 1 /* ":" */ + strlen ( password ) ); char user_pw[ user_pw_len + 1 /* NUL */ ]; @@ -1000,8 +1000,8 @@ static char * http_digest_auth ( struct http_request *http, const char *method, const char *uri ) { const char *user = http->uri->user; - const char *password = - ( http->uri->password ? http->uri->password : "" ); + const char *password = ( http->uri->password ? + http->uri->password : "" ); const char *realm = http->auth_realm; const char *nonce = http->auth_nonce; const char *opaque = http->auth_opaque; @@ -1088,7 +1088,7 @@ } /* URI-encode the key */ - frag_len = uri_encode ( param->key, buf, remaining, 0 ); + frag_len = uri_encode ( param->key, 0, buf, remaining ); buf += frag_len; len += frag_len; remaining -= frag_len; @@ -1101,7 +1101,7 @@ remaining--; /* URI-encode the value */ - frag_len = uri_encode ( param->value, buf, remaining, 0 ); + frag_len = uri_encode ( param->value, 0, buf, remaining ); buf += frag_len; len += frag_len; remaining -= frag_len; @@ -1149,9 +1149,11 @@ */ static void http_step ( struct http_request *http ) { struct io_buffer *post; - size_t uri_len; + struct uri host_uri; + struct uri path_uri; + char *host_uri_string; + char *path_uri_string; char *method; - char *uri; char *range; char *auth; char *content; @@ -1176,19 +1178,24 @@ method = ( ( http->flags & HTTP_HEAD_ONLY ) ? "HEAD" : ( http->uri->params ? "POST" : "GET" ) ); - /* Construct path?query request */ - uri_len = ( unparse_uri ( NULL, 0, http->uri, - URI_PATH_BIT | URI_QUERY_BIT ) - + 1 /* possible "/" */ + 1 /* NUL */ ); - uri = malloc ( uri_len ); - if ( ! uri ) { + /* Construct host URI */ + memset ( &host_uri, 0, sizeof ( host_uri ) ); + host_uri.host = http->uri->host; + host_uri.port = http->uri->port; + host_uri_string = format_uri_alloc ( &host_uri ); + if ( ! host_uri_string ) { rc = -ENOMEM; - goto err_uri; + goto err_host_uri; } - unparse_uri ( uri, uri_len, http->uri, URI_PATH_BIT | URI_QUERY_BIT ); - if ( ! uri[0] ) { - uri[0] = '/'; - uri[1] = '\0'; + + /* Construct path URI */ + memset ( &path_uri, 0, sizeof ( path_uri ) ); + path_uri.path = ( http->uri->path ? http->uri->path : "/" ); + path_uri.query = http->uri->query; + path_uri_string = format_uri_alloc ( &path_uri ); + if ( ! path_uri_string ) { + rc = -ENOMEM; + goto err_path_uri; } /* Calculate range request parameters if applicable */ @@ -1213,7 +1220,7 @@ goto err_auth; } } else if ( http->flags & HTTP_DIGEST_AUTH ) { - auth = http_digest_auth ( http, method, uri ); + auth = http_digest_auth ( http, method, path_uri_string ); if ( ! auth ) { rc = -ENOMEM; goto err_auth; @@ -1248,14 +1255,11 @@ if ( ( rc = xfer_printf ( &http->socket, "%s %s HTTP/1.1\r\n" "User-Agent: iPXE/%s\r\n" - "Host: %s%s%s\r\n" + "Host: %s\r\n" "%s%s%s%s" "\r\n", - method, uri, product_version, http->uri->host, - ( http->uri->port ? - ":" : "" ), - ( http->uri->port ? - http->uri->port : "" ), + method, path_uri_string, product_version, + host_uri_string, ( ( http->flags & HTTP_CLIENT_KEEPALIVE ) ? "Connection: keep-alive\r\n" : "" ), ( range ? range : "" ), @@ -1281,8 +1285,10 @@ err_auth: free ( range ); err_range: - free ( uri ); - err_uri: + free ( path_uri_string ); + err_path_uri: + free ( host_uri_string ); + err_host_uri: if ( rc != 0 ) http_close ( http, rc ); } | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/udp/dhcp.c ^ |
@@ -86,6 +86,7 @@ DHCP_LOG_SERVERS, DHCP_HOST_NAME, DHCP_DOMAIN_NAME, DHCP_ROOT_PATH, DHCP_VENDOR_ENCAP, DHCP_VENDOR_CLASS_ID, DHCP_TFTP_SERVER_NAME, DHCP_BOOTFILE_NAME, + DHCP_DOMAIN_SEARCH, 128, 129, 130, 131, 132, 133, 134, 135, /* for PXE */ DHCP_EB_ENCAP, DHCP_ISCSI_INITIATOR_IQN ), DHCP_END | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/udp/dhcpv6.c ^ |
@@ -979,3 +979,12 @@ .type = &setting_type_string, .scope = &ipv6_scope, }; + +/** DNS search list setting */ +const struct setting dnssl6_setting __setting ( SETTING_IP_EXTRA, dnssl ) = { + .name = "dnssl", + .description = "DNS search list", + .tag = DHCPV6_DOMAIN_LIST, + .type = &setting_type_dnssl, + .scope = &ipv6_scope, +}; | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/udp/dns.c ^ |
@@ -26,6 +26,7 @@ #include <stdlib.h> #include <string.h> #include <stdio.h> +#include <ctype.h> #include <errno.h> #include <byteswap.h> #include <ipxe/refcnt.h> @@ -69,8 +70,366 @@ }, }; -/** The local domain */ -static char *localdomain; +/** The DNS search list */ +static struct dns_name dns_search; + +/** + * Encode a DNS name using RFC1035 encoding + * + * @v string DNS name as a string + * @v name DNS name to fill in + * @ret len Length of DNS name, or negative error + */ +int dns_encode ( const char *string, struct dns_name *name ) { + uint8_t *start = ( name->data + name->offset ); + uint8_t *end = ( name->data + name->len ); + uint8_t *dst = start; + size_t len = 0; + char c; + + /* Encode name */ + while ( ( c = *(string++) ) ) { + + /* Handle '.' separators */ + if ( c == '.' ) { + + /* Reject consecutive '.' */ + if ( ( len == 0 ) && ( dst != start ) ) + return -EINVAL; + + /* Terminate if this is the trailing '.' */ + if ( *string == '\0' ) + break; + + /* Reject initial non-terminating '.' */ + if ( len == 0 ) + return -EINVAL; + + /* Reset length */ + len = 0; + + } else { + + /* Increment length */ + len++; + + /* Check for overflow */ + if ( len > DNS_MAX_LABEL_LEN ) + return -EINVAL; + } + + /* Copy byte, update length */ + if ( ++dst < end ) { + *dst = c; + dst[-len] = len; + } + } + + /* Add terminating root marker */ + if ( len ) + dst++; + if ( dst < end ) + *dst = '\0'; + dst++; + + return ( dst - start ); +} + +/** + * Find start of valid label within an RFC1035-encoded DNS name + * + * @v name DNS name + * @v offset Current offset + * @ret offset Offset of label, or negative error + */ +static int dns_label ( struct dns_name *name, size_t offset ) { + const uint8_t *byte; + const uint16_t *word; + size_t len; + size_t ptr; + + while ( 1 ) { + + /* Fail if we have overrun the DNS name */ + if ( ( offset + sizeof ( *byte) ) > name->len ) + return -EINVAL; + byte = ( name->data + offset ); + + /* Follow compression pointer, if applicable */ + if ( DNS_IS_COMPRESSED ( *byte ) ) { + + /* Fail if we have overrun the DNS name */ + if ( ( offset + sizeof ( *word ) ) > name->len ) + return -EINVAL; + word = ( name->data + offset ); + + /* Extract pointer to new offset */ + ptr = DNS_COMPRESSED_OFFSET ( ntohs ( *word ) ); + + /* Fail if pointer does not point backwards. + * (This guarantees termination of the + * function.) + */ + if ( ptr >= offset ) + return -EINVAL; + + /* Continue from new offset */ + offset = ptr; + continue; + } + + /* Fail if we have overrun the DNS name */ + len = *byte; + if ( ( offset + sizeof ( *byte ) + len ) > name->len ) + return -EINVAL; + + /* We have a valid label */ + return offset; + } +} + +/** + * Decode RFC1035-encoded DNS name + * + * @v name DNS name + * @v data Output buffer + * @v len Length of output buffer + * @ret len Length of decoded DNS name, or negative error + */ +int dns_decode ( struct dns_name *name, char *data, size_t len ) { + unsigned int recursion_limit = name->len; /* Generous upper bound */ + int offset = name->offset; + const uint8_t *label; + size_t decoded_len = 0; + size_t label_len; + size_t copy_len; + + while ( recursion_limit-- ) { + + /* Find valid DNS label */ + offset = dns_label ( name, offset ); + if ( offset < 0 ) + return offset; + + /* Terminate if we have reached the root */ + label = ( name->data + offset ); + label_len = *(label++); + if ( label_len == 0 ) { + if ( decoded_len < len ) + *data = '\0'; + return decoded_len; + } + + /* Prepend '.' if applicable */ + if ( decoded_len && ( decoded_len++ < len ) ) + *(data++) = '.'; + + /* Copy label to output buffer */ + copy_len = ( ( decoded_len < len ) ? ( len - decoded_len ) : 0); + if ( copy_len > label_len ) + copy_len = label_len; + memcpy ( data, label, copy_len ); + data += copy_len; + decoded_len += label_len; + + /* Move to next label */ + offset += ( sizeof ( *label ) + label_len ); + } + + /* Recursion limit exceeded */ + return -EINVAL; +} + +/** + * Compare DNS names for equality + * + * @v first First DNS name + * @v second Second DNS name + * @ret rc Return status code + */ +int dns_compare ( struct dns_name *first, struct dns_name *second ) { + unsigned int recursion_limit = first->len; /* Generous upper bound */ + int first_offset = first->offset; + int second_offset = second->offset; + const uint8_t *first_label; + const uint8_t *second_label; + size_t label_len; + size_t len; + + while ( recursion_limit-- ) { + + /* Find valid DNS labels */ + first_offset = dns_label ( first, first_offset ); + if ( first_offset < 0 ) + return first_offset; + second_offset = dns_label ( second, second_offset ); + if ( second_offset < 0 ) + return second_offset; + + /* Compare label lengths */ + first_label = ( first->data + first_offset ); + second_label = ( second->data + second_offset ); + label_len = *(first_label++); + if ( label_len != *(second_label++) ) + return -ENOENT; + len = ( sizeof ( *first_label ) + label_len ); + + /* Terminate if we have reached the root */ + if ( label_len == 0 ) + return 0; + + /* Compare label contents (case-insensitively) */ + while ( label_len-- ) { + if ( tolower ( *(first_label++) ) != + tolower ( *(second_label++) ) ) + return -ENOENT; + } + + /* Move to next labels */ + first_offset += len; + second_offset += len; + } + + /* Recursion limit exceeded */ + return -EINVAL; +} + +/** + * Copy a DNS name + * + * @v src Source DNS name + * @v dst Destination DNS name + * @ret len Length of copied DNS name, or negative error + */ +int dns_copy ( struct dns_name *src, struct dns_name *dst ) { + unsigned int recursion_limit = src->len; /* Generous upper bound */ + int src_offset = src->offset; + size_t dst_offset = dst->offset; + const uint8_t *label; + size_t label_len; + size_t copy_len; + size_t len; + + while ( recursion_limit-- ) { + + /* Find valid DNS label */ + src_offset = dns_label ( src, src_offset ); + if ( src_offset < 0 ) + return src_offset; + + /* Copy as an uncompressed label */ + label = ( src->data + src_offset ); + label_len = *label; + len = ( sizeof ( *label ) + label_len ); + copy_len = ( ( dst_offset < dst->len ) ? + ( dst->len - dst_offset ) : 0 ); + if ( copy_len > len ) + copy_len = len; + memcpy ( ( dst->data + dst_offset ), label, copy_len ); + src_offset += len; + dst_offset += len; + + /* Terminate if we have reached the root */ + if ( label_len == 0 ) + return ( dst_offset - dst->offset ); + } + + /* Recursion limit exceeded */ + return -EINVAL; +} + +/** + * Skip RFC1035-encoded DNS name + * + * @v name DNS name + * @ret offset Offset to next name, or negative error + */ +int dns_skip ( struct dns_name *name ) { + unsigned int recursion_limit = name->len; /* Generous upper bound */ + int offset = name->offset; + int prev_offset; + const uint8_t *label; + size_t label_len; + + while ( recursion_limit-- ) { + + /* Find valid DNS label */ + prev_offset = offset; + offset = dns_label ( name, prev_offset ); + if ( offset < 0 ) + return offset; + + /* Terminate if we have reached a compression pointer */ + if ( offset != prev_offset ) + return ( prev_offset + sizeof ( uint16_t ) ); + + /* Skip this label */ + label = ( name->data + offset ); + label_len = *label; + offset += ( sizeof ( *label ) + label_len ); + + /* Terminate if we have reached the root */ + if ( label_len == 0 ) + return offset; + } + + /* Recursion limit exceeded */ + return -EINVAL; +} + +/** + * Skip RFC1035-encoded DNS name in search list + * + * @v name DNS name + * @ret offset Offset to next non-empty name, or negative error + */ +static int dns_skip_search ( struct dns_name *name ) { + int offset; + + /* Find next name */ + offset = dns_skip ( name ); + if ( offset < 0 ) + return offset; + + /* Skip over any subsequent empty names (e.g. due to padding + * bytes used in the NDP DNSSL option). + */ + while ( ( offset < ( ( int ) name->len ) ) && + ( *( ( uint8_t * ) ( name->data + offset ) ) == 0 ) ) { + offset++; + } + + return offset; +} + +/** + * Transcribe DNS name (for debugging) + * + * @v name DNS name + * @ret string Transcribed DNS name + */ +static const char * dns_name ( struct dns_name *name ) { + static char buf[256]; + int len; + + len = dns_decode ( name, buf, sizeof ( buf ) ); + return ( ( len < 0 ) ? "<INVALID>" : buf ); +} + +/** + * Name a DNS query type (for debugging) + * + * @v type Query type (in network byte order) + * @ret name Type name + */ +static const char * dns_type ( uint16_t type ) { + switch ( type ) { + case htons ( DNS_TYPE_A ): return "A"; + case htons ( DNS_TYPE_AAAA ): return "AAAA"; + case htons ( DNS_TYPE_CNAME ): return "CNAME"; + default: return "<UNKNOWN>"; + } +} /** A DNS request */ struct dns_request { @@ -91,14 +450,25 @@ } address; /** Initial query type */ uint16_t qtype; - /** Current query packet */ - struct dns_query query; - /** Location of query info structure within current packet - * - * The query info structure is located immediately after the - * compressed name. - */ - struct dns_query_info *qinfo; + /** Buffer for current query */ + struct { + /** Query header */ + struct dns_header query; + /** Name buffer */ + char name[DNS_MAX_NAME_LEN]; + /** Space for question */ + struct dns_question padding; + } __attribute__ (( packed )) buf; + /** Current query name */ + struct dns_name name; + /** Question within current query */ + struct dns_question *question; + /** Length of current query */ + size_t len; + /** Offset of search suffix within current query */ + size_t offset; + /** Search list */ + struct dns_name search; /** Recursion counter */ unsigned int recursion; }; @@ -138,214 +508,76 @@ } /** - * Compare DNS reply name against the query name from the original request - * - * @v dns DNS request - * @v reply DNS reply - * @v rname Reply name - * @ret zero Names match - * @ret non-zero Names do not match - */ -static int dns_name_cmp ( struct dns_request *dns, - const struct dns_header *reply, - const char *rname ) { - const char *qname = dns->query.payload; - int i; - - while ( 1 ) { - /* Obtain next section of rname */ - while ( ( *rname ) & 0xc0 ) { - rname = ( ( ( char * ) reply ) + - ( ntohs( *((uint16_t *)rname) ) & ~0xc000 )); - } - /* Check that lengths match */ - if ( *rname != *qname ) - return -1; - /* If length is zero, we have reached the end */ - if ( ! *qname ) - return 0; - /* Check that data matches */ - for ( i = *qname + 1; i > 0 ; i-- ) { - if ( *(rname++) != *(qname++) ) - return -1; - } - } -} - -/** - * Skip over a (possibly compressed) DNS name - * - * @v name DNS name - * @ret name Next DNS name - */ -static const char * dns_skip_name ( const char *name ) { - while ( 1 ) { - if ( ! *name ) { - /* End of name */ - return ( name + 1); - } - if ( *name & 0xc0 ) { - /* Start of a compressed name */ - return ( name + 2 ); - } - /* Uncompressed name portion */ - name += *name + 1; - } -} - -/** - * Find an RR in a reply packet corresponding to our query + * Construct DNS question * * @v dns DNS request - * @v reply DNS reply - * @ret rr DNS RR, or NULL if not found + * @ret rc Return status code */ -static union dns_rr_info * dns_find_rr ( struct dns_request *dns, - const struct dns_header *reply ) { - int i, cmp; - const char *p = ( ( char * ) reply ) + sizeof ( struct dns_header ); - union dns_rr_info *rr_info; +static int dns_question ( struct dns_request *dns ) { + static struct dns_name search_root = { + .data = "", + .len = 1, + }; + struct dns_name *search = &dns->search; + int len; + size_t offset; + + /* Use root suffix if search list is empty */ + if ( search->offset == search->len ) + search = &search_root; + + /* Overwrite current suffix */ + dns->name.offset = dns->offset; + len = dns_copy ( search, &dns->name ); + if ( len < 0 ) + return len; - /* Skip over the questions section */ - for ( i = ntohs ( reply->qdcount ) ; i > 0 ; i-- ) { - p = dns_skip_name ( p ) + sizeof ( struct dns_query_info ); + /* Sanity check */ + offset = ( dns->name.offset + len ); + if ( offset > dns->name.len ) { + DBGC ( dns, "DNS %p name is too long\n", dns ); + return -EINVAL; } - /* Process the answers section */ - for ( i = ntohs ( reply->ancount ) ; i > 0 ; i-- ) { - cmp = dns_name_cmp ( dns, reply, p ); - p = dns_skip_name ( p ); - rr_info = ( ( union dns_rr_info * ) p ); - if ( cmp == 0 ) - return rr_info; - p += ( sizeof ( rr_info->common ) + - ntohs ( rr_info->common.rdlength ) ); - } + /* Construct question */ + dns->question = ( ( ( void * ) &dns->buf ) + offset ); + dns->question->qtype = dns->qtype; + dns->question->qclass = htons ( DNS_CLASS_IN ); - return NULL; -} + /* Store length */ + dns->len = ( offset + sizeof ( *(dns->question) ) ); -/** - * Append DHCP domain name if available and name is not fully qualified - * - * @v string Name as a NUL-terminated string - * @ret fqdn Fully-qualified domain name, malloc'd copy - * - * The caller must free fqdn which is allocated even if the name is already - * fully qualified. - */ -static char * dns_qualify_name ( const char *string ) { - char *fqdn; - - /* Leave unchanged if already fully-qualified or no local domain */ - if ( ( ! localdomain ) || ( strchr ( string, '.' ) != NULL ) ) - return strdup ( string ); - - /* Append local domain to name */ - asprintf ( &fqdn, "%s.%s", string, localdomain ); - return fqdn; -} - -/** - * Convert a standard NUL-terminated string to a DNS name - * - * @v string Name as a NUL-terminated string - * @v buf Buffer in which to place DNS name - * @ret next Byte following constructed DNS name - * - * DNS names consist of "<length>element" pairs. - */ -static char * dns_make_name ( const char *string, char *buf ) { - char *length_byte; - char c; - - length_byte = buf++; - *length_byte = 0; - do { - c = *(string++); - if ( ( c == '.' ) || ( c == '\0' ) ) { - if ( *length_byte ) { - length_byte = buf++; - *length_byte = 0; - } - } else { - *(buf++) = c; - (*length_byte)++; - } - } while ( c ); - - return buf; -} + /* Restore name */ + dns->name.offset = offsetof ( typeof ( dns->buf ), name ); -/** - * Convert an uncompressed DNS name to a NUL-terminated string - * - * @v name DNS name - * @ret string NUL-terminated string - * - * Produce a printable version of a DNS name. Used only for debugging. - */ -static inline char * dns_unmake_name ( char *name ) { - char *p; - unsigned int len; - - p = name; - while ( ( len = *p ) ) { - *(p++) = '.'; - p += len; - } - - return name + 1; -} - -/** - * Decompress a DNS name - * - * @v reply DNS replay - * @v name DNS name - * @v buf Buffer into which to decompress DNS name - * @ret next Byte following decompressed DNS name - */ -static char * dns_decompress_name ( const struct dns_header *reply, - const char *name, char *buf ) { - int i, len; + DBGC2 ( dns, "DNS %p question is %s type %s\n", dns, + dns_name ( &dns->name ), dns_type ( dns->question->qtype ) ); - do { - /* Obtain next section of name */ - while ( ( *name ) & 0xc0 ) { - name = ( ( char * ) reply + - ( ntohs ( *((uint16_t *)name) ) & ~0xc000 ) ); - } - /* Copy data */ - len = *name; - for ( i = len + 1 ; i > 0 ; i-- ) { - *(buf++) = *(name++); - } - } while ( len ); - return buf; + return 0; } /** - * Send next packet in DNS request + * Send DNS query * * @v dns DNS request + * @ret rc Return status code */ static int dns_send_packet ( struct dns_request *dns ) { - static unsigned int qid = 0; - size_t qlen; - - /* Increment query ID */ - dns->query.dns.id = htons ( ++qid ); - - DBGC ( dns, "DNS %p sending query ID %d\n", dns, qid ); + struct dns_header *query = &dns->buf.query; /* Start retransmission timer */ start_timer ( &dns->timer ); + /* Generate query identifier */ + query->id = random(); + + /* Send query */ + DBGC ( dns, "DNS %p sending query ID %#04x for %s type %s\n", dns, + ntohs ( query->id ), dns_name ( &dns->name ), + dns_type ( dns->question->qtype ) ); + /* Send the data */ - qlen = ( ( ( void * ) dns->qinfo ) - ( ( void * ) &dns->query ) - + sizeof ( dns->qinfo ) ); - return xfer_deliver_raw ( &dns->socket, &dns->query, qlen ); + return xfer_deliver_raw ( &dns->socket, query, dns->len ); } /** @@ -376,51 +608,115 @@ static int dns_xfer_deliver ( struct dns_request *dns, struct io_buffer *iobuf, struct xfer_metadata *meta __unused ) { - const struct dns_header *reply = iobuf->data; - union dns_rr_info *rr_info; - unsigned int qtype = dns->qinfo->qtype; + struct dns_header *response = iobuf->data; + struct dns_header *query = &dns->buf.query; + unsigned int qtype = dns->question->qtype; + struct dns_name buf; + union dns_rr *rr; + int offset; + size_t answer_offset; + size_t next_offset; + size_t rdlength; + size_t name_len; int rc; /* Sanity check */ - if ( iob_len ( iobuf ) < sizeof ( *reply ) ) { + if ( iob_len ( iobuf ) < sizeof ( *response ) ) { DBGC ( dns, "DNS %p received underlength packet length %zd\n", dns, iob_len ( iobuf ) ); rc = -EINVAL; goto done; } - /* Check reply ID matches query ID */ - if ( reply->id != dns->query.dns.id ) { - DBGC ( dns, "DNS %p received unexpected reply ID %d " - "(wanted %d)\n", dns, ntohs ( reply->id ), - ntohs ( dns->query.dns.id ) ); + /* Check response ID matches query ID */ + if ( response->id != query->id ) { + DBGC ( dns, "DNS %p received unexpected response ID %#04x " + "(wanted %d)\n", dns, ntohs ( response->id ), + ntohs ( query->id ) ); rc = -EINVAL; goto done; } + DBGC ( dns, "DNS %p received response ID %#04x\n", + dns, ntohs ( response->id ) ); - DBGC ( dns, "DNS %p received reply ID %d\n", dns, ntohs ( reply->id )); + /* Check that we have exactly one question */ + if ( response->qdcount != htons ( 1 ) ) { + DBGC ( dns, "DNS %p received response with %d questions\n", + dns, ntohs ( response->qdcount ) ); + rc = -EINVAL; + goto done; + } - /* Stop the retry timer. After this point, each code path - * must either restart the timer by calling dns_send_packet(), - * or mark the DNS operation as complete by calling - * dns_done() - */ - stop_timer ( &dns->timer ); + /* Skip question section */ + buf.data = iobuf->data; + buf.offset = sizeof ( *response ); + buf.len = iob_len ( iobuf ); + offset = dns_skip ( &buf ); + if ( offset < 0 ) { + rc = offset; + DBGC ( dns, "DNS %p received response with malformed " + "question: %s\n", dns, strerror ( rc ) ); + goto done; + } + answer_offset = ( offset + sizeof ( struct dns_question ) ); /* Search through response for useful answers. Do this * multiple times, to take advantage of useful nameservers * which send us e.g. the CNAME *and* the A record for the * pointed-to name. */ - while ( ( rr_info = dns_find_rr ( dns, reply ) ) ) { - switch ( rr_info->common.type ) { + for ( buf.offset = answer_offset ; buf.offset != buf.len ; + buf.offset = next_offset ) { + + /* Check for valid name */ + offset = dns_skip ( &buf ); + if ( offset < 0 ) { + rc = offset; + DBGC ( dns, "DNS %p received response with malformed " + "answer: %s\n", dns, strerror ( rc ) ); + goto done; + } + + /* Check for sufficient space for resource record */ + rr = ( buf.data + offset ); + if ( ( offset + sizeof ( rr->common ) ) > buf.len ) { + DBGC ( dns, "DNS %p received response with underlength " + "RR\n", dns ); + rc = -EINVAL; + goto done; + } + rdlength = ntohs ( rr->common.rdlength ); + next_offset = ( offset + sizeof ( rr->common ) + rdlength ); + if ( next_offset > buf.len ) { + DBGC ( dns, "DNS %p received response with underlength " + "RR\n", dns ); + rc = -EINVAL; + goto done; + } + + /* Skip non-matching names */ + if ( dns_compare ( &buf, &dns->name ) != 0 ) { + DBGC2 ( dns, "DNS %p ignoring response for %s type " + "%s\n", dns, dns_name ( &buf ), + dns_type ( rr->common.type ) ); + continue; + } + + /* Handle answer */ + switch ( rr->common.type ) { case htons ( DNS_TYPE_AAAA ): /* Found the target AAAA record */ + if ( rdlength < sizeof ( dns->address.sin6.sin6_addr )){ + DBGC ( dns, "DNS %p received response with " + "underlength AAAA\n", dns ); + rc = -EINVAL; + goto done; + } dns->address.sin6.sin6_family = AF_INET6; memcpy ( &dns->address.sin6.sin6_addr, - &rr_info->aaaa.in6_addr, + &rr->aaaa.in6_addr, sizeof ( dns->address.sin6.sin6_addr ) ); dns_resolved ( dns ); rc = 0; @@ -429,39 +725,58 @@ case htons ( DNS_TYPE_A ): /* Found the target A record */ + if ( rdlength < sizeof ( dns->address.sin.sin_addr ) ) { + DBGC ( dns, "DNS %p received response with " + "underlength A\n", dns ); + rc = -EINVAL; + goto done; + } dns->address.sin.sin_family = AF_INET; - dns->address.sin.sin_addr = rr_info->a.in_addr; + dns->address.sin.sin_addr = rr->a.in_addr; dns_resolved ( dns ); rc = 0; goto done; case htons ( DNS_TYPE_CNAME ): - /* Found a CNAME record; update query and recurse */ - DBGC ( dns, "DNS %p found CNAME\n", dns ); - dns->qinfo = ( void * ) dns_decompress_name ( reply, - rr_info->cname.cname, - dns->query.payload ); - dns->qinfo->qtype = dns->qtype; - dns->qinfo->qclass = htons ( DNS_CLASS_IN ); - /* Terminate the operation if we recurse too far */ if ( ++dns->recursion > DNS_MAX_CNAME_RECURSION ) { DBGC ( dns, "DNS %p recursion exceeded\n", dns ); - dns_done ( dns, -ELOOP ); - rc = 0; + rc = -ELOOP; + dns_done ( dns, rc ); goto done; } + + /* Found a CNAME record; update query and recurse */ + buf.offset = ( offset + sizeof ( rr->cname ) ); + DBGC ( dns, "DNS %p found CNAME %s\n", + dns, dns_name ( &buf ) ); + dns->search.offset = dns->search.len; + name_len = dns_copy ( &buf, &dns->name ); + dns->offset = ( offsetof ( typeof ( dns->buf ), name ) + + name_len - 1 /* Strip root label */ ); + if ( ( rc = dns_question ( dns ) ) != 0 ) { + dns_done ( dns, rc ); + goto done; + } + next_offset = answer_offset; break; default: DBGC ( dns, "DNS %p got unknown record type %d\n", - dns, ntohs ( rr_info->common.type ) ); + dns, ntohs ( rr->common.type ) ); break; } } - + + /* Stop the retry timer. After this point, each code path + * must either restart the timer by calling dns_send_packet(), + * or mark the DNS operation as complete by calling + * dns_done() + */ + stop_timer ( &dns->timer ); + /* Determine what to do next based on the type of query we * issued and the response we received */ @@ -472,7 +787,7 @@ * the A. */ DBGC ( dns, "DNS %p found no AAAA record; trying A\n", dns ); - dns->qinfo->qtype = htons ( DNS_TYPE_A ); + dns->question->qtype = htons ( DNS_TYPE_A ); dns_send_packet ( dns ); rc = 0; goto done; @@ -482,31 +797,49 @@ * try the CNAME. */ DBGC ( dns, "DNS %p found no A record; trying CNAME\n", dns ); - dns->qinfo->qtype = htons ( DNS_TYPE_CNAME ); + dns->question->qtype = htons ( DNS_TYPE_CNAME ); dns_send_packet ( dns ); rc = 0; goto done; case htons ( DNS_TYPE_CNAME ): /* We asked for a CNAME record. If we got a response - * (i.e. if the next A query is already set up), then - * issue it, otherwise abort. + * (i.e. if the next AAAA/A query is already set up), + * then issue it. */ - if ( dns->qinfo->qtype == dns->qtype ) { + if ( qtype == dns->qtype ) { dns_send_packet ( dns ); rc = 0; goto done; - } else { + } + + /* If we have already reached the end of the search list, + * then terminate lookup. + */ + if ( dns->search.offset == dns->search.len ) { DBGC ( dns, "DNS %p found no CNAME record\n", dns ); - dns_done ( dns, -ENXIO_NO_RECORD ); - rc = 0; + rc = -ENXIO_NO_RECORD; + dns_done ( dns, rc ); goto done; } + /* Move to next entry in search list. This can never fail, + * since we have already used this entry. + */ + DBGC ( dns, "DNS %p found no CNAME record; trying next " + "suffix\n", dns ); + dns->search.offset = dns_skip_search ( &dns->search ); + if ( ( rc = dns_question ( dns ) ) != 0 ) { + dns_done ( dns, rc ); + goto done; + } + dns_send_packet ( dns ); + goto done; + default: assert ( 0 ); - dns_done ( dns, -EINVAL ); rc = -EINVAL; + dns_done ( dns, rc ); goto done; } @@ -560,7 +893,9 @@ static int dns_resolv ( struct interface *resolv, const char *name, struct sockaddr *sa ) { struct dns_request *dns; - char *fqdn; + struct dns_header *query; + size_t search_len; + int name_len; int rc; /* Fail immediately if no DNS servers */ @@ -571,15 +906,11 @@ goto err_no_nameserver; } - /* Ensure fully-qualified domain name if DHCP option was given */ - fqdn = dns_qualify_name ( name ); - if ( ! fqdn ) { - rc = -ENOMEM; - goto err_qualify_name; - } + /* Determine whether or not to use search list */ + search_len = ( strchr ( name, '.' ) ? 0 : dns_search.len ); /* Allocate DNS structure */ - dns = zalloc ( sizeof ( *dns ) ); + dns = zalloc ( sizeof ( *dns ) + search_len ); if ( ! dns ) { rc = -ENOMEM; goto err_alloc_dns; @@ -589,6 +920,9 @@ intf_init ( &dns->socket, &dns_socket_desc, &dns->refcnt ); timer_init ( &dns->timer, dns_timer_expired, &dns->refcnt ); memcpy ( &dns->address.sa, sa, sizeof ( dns->address.sa ) ); + dns->search.data = ( ( ( void * ) dns ) + sizeof ( *dns ) ); + dns->search.len = search_len; + memcpy ( dns->search.data, dns_search.data, search_len ); /* Determine initial query type */ switch ( nameserver.sa.sa_family ) { @@ -600,16 +934,25 @@ break; default: rc = -ENOTSUP; - goto err_qtype; + goto err_type; } - /* Create query */ - dns->query.dns.flags = htons ( DNS_FLAG_QUERY | DNS_FLAG_OPCODE_QUERY | - DNS_FLAG_RD ); - dns->query.dns.qdcount = htons ( 1 ); - dns->qinfo = ( void * ) dns_make_name ( fqdn, dns->query.payload ); - dns->qinfo->qtype = dns->qtype; - dns->qinfo->qclass = htons ( DNS_CLASS_IN ); + /* Construct query */ + query = &dns->buf.query; + query->flags = htons ( DNS_FLAG_RD ); + query->qdcount = htons ( 1 ); + dns->name.data = &dns->buf; + dns->name.offset = offsetof ( typeof ( dns->buf ), name ); + dns->name.len = offsetof ( typeof ( dns->buf ), padding ); + name_len = dns_encode ( name, &dns->name ); + if ( name_len < 0 ) { + rc = name_len; + goto err_encode; + } + dns->offset = ( offsetof ( typeof ( dns->buf ), name ) + + name_len - 1 /* Strip root label */ ); + if ( ( rc = dns_question ( dns ) ) != 0 ) + goto err_question; /* Open UDP connection */ if ( ( rc = xfer_open_socket ( &dns->socket, SOCK_DGRAM, @@ -619,21 +962,20 @@ goto err_open_socket; } - /* Send first DNS packet */ - dns_send_packet ( dns ); + /* Start timer to trigger first packet */ + start_timer_nodelay ( &dns->timer ); /* Attach parent interface, mortalise self, and return */ intf_plug_plug ( &dns->resolv, resolv ); ref_put ( &dns->refcnt ); - free ( fqdn ); return 0; err_open_socket: - err_qtype: + err_question: + err_encode: + err_type: ref_put ( &dns->refcnt ); err_alloc_dns: - free ( fqdn ); - err_qualify_name: err_no_nameserver: return rc; } @@ -651,6 +993,56 @@ ****************************************************************************** */ +/** + * Format DNS search list setting + * + * @v type Setting type + * @v raw Raw setting value + * @v raw_len Length of raw setting value + * @v buf Buffer to contain formatted value + * @v len Length of buffer + * @ret len Length of formatted value, or negative error + */ +static int format_dnssl_setting ( const struct setting_type *type __unused, + const void *raw, size_t raw_len, + char *buf, size_t len ) { + struct dns_name name = { + .data = ( ( void * ) raw ), + .len = raw_len, + }; + size_t remaining = len; + size_t total = 0; + int name_len; + + while ( name.offset < raw_len ) { + + /* Decode name */ + remaining = ( ( total < len ) ? ( len - total ) : 0 ); + name_len = dns_decode ( &name, ( buf + total ), remaining ); + if ( name_len < 0 ) + return name_len; + total += name_len; + + /* Move to next name */ + name.offset = dns_skip_search ( &name ); + + /* Add separator if applicable */ + if ( name.offset != raw_len ) { + if ( total < len ) + buf[total] = ' '; + total++; + } + } + + return total; +} + +/** A DNS search list setting type */ +const struct setting_type setting_type_dnssl __setting_type = { + .name = "dnssl", + .format = format_dnssl_setting, +}; + /** IPv4 DNS server setting */ const struct setting dns_setting __setting ( SETTING_IP_EXTRA, dns ) = { .name = "dns", @@ -668,6 +1060,50 @@ .scope = &ipv6_scope, }; +/** DNS search list */ +const struct setting dnssl_setting __setting ( SETTING_IP_EXTRA, dnssl ) = { + .name = "dnssl", + .description = "DNS search list", + .tag = DHCP_DOMAIN_SEARCH, + .type = &setting_type_dnssl, +}; + +/** + * Apply DNS search list + * + */ +static void apply_dns_search ( void ) { + char *localdomain; + int len; + + /* Free existing search list */ + free ( dns_search.data ); + memset ( &dns_search, 0, sizeof ( dns_search ) ); + + /* Fetch DNS search list */ + len = fetch_setting_copy ( NULL, &dnssl_setting, NULL, NULL, + &dns_search.data ); + if ( len >= 0 ) { + dns_search.len = len; + return; + } + + /* If no DNS search list exists, try to fetch the local domain */ + fetch_string_setting_copy ( NULL, &domain_setting, &localdomain ); + if ( localdomain ) { + len = dns_encode ( localdomain, &dns_search ); + if ( len >= 0 ) { + dns_search.data = malloc ( len ); + if ( dns_search.data ) { + dns_search.len = len; + dns_encode ( localdomain, &dns_search ); + } + } + free ( localdomain ); + return; + } +} + /** * Apply DNS settings * @@ -689,11 +1125,23 @@ sock_ntoa ( &nameserver.sa ) ); } - /* Get local domain DHCP option */ - free ( localdomain ); - fetch_string_setting_copy ( NULL, &domain_setting, &localdomain ); - if ( localdomain ) - DBG ( "DNS local domain %s\n", localdomain ); + /* Fetch DNS search list */ + apply_dns_search(); + if ( DBG_LOG && ( dns_search.len != 0 ) ) { + struct dns_name name; + int offset; + + DBG ( "DNS search list:" ); + memcpy ( &name, &dns_search, sizeof ( name ) ); + while ( name.offset != name.len ) { + DBG ( " %s", dns_name ( &name ) ); + offset = dns_skip_search ( &name ); + if ( offset < 0 ) + break; + name.offset = offset; + } + DBG ( "\n" ); + } return 0; } | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/udp/slam.c ^ |
@@ -723,7 +723,7 @@ /* Open multicast socket */ memcpy ( &multicast, &default_multicast, sizeof ( multicast ) ); - if ( uri->path && + if ( uri->path && ( ( rc = slam_parse_multicast_address ( slam, uri->path, &multicast ) ) != 0 ) ) { goto err; | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/udp/tftp.c ^ |
@@ -323,24 +323,12 @@ * @ret rc Return status code */ static int tftp_send_rrq ( struct tftp_request *tftp ) { + const char *path = tftp->uri->path; struct tftp_rrq *rrq; - const char *path; size_t len; struct io_buffer *iobuf; size_t blksize; - /* Strip initial '/' if present. If we were opened via the - * URI interface, then there will be an initial '/', since a - * full tftp:// URI provides no way to specify a non-absolute - * path. However, many TFTP servers (particularly Windows - * TFTP servers) complain about having an initial '/', and it - * violates user expectations to have a '/' silently added to - * the DHCP-specified filename. - */ - path = tftp->uri->path; - if ( *path == '/' ) - path++; - DBGC ( tftp, "TFTP %p requesting \"%s\"\n", tftp, path ); /* Allocate buffer */ | ||
[-] [+] | Added | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/deflate_test.c ^ |
@@ -0,0 +1,246 @@ +/* + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * DEFLATE tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <ipxe/deflate.h> +#include <ipxe/test.h> + +/** A DEFLATE test */ +struct deflate_test { + /** Compression format */ + enum deflate_format format; + /** Compressed data */ + const void *compressed; + /** Length of compressed data */ + size_t compressed_len; + /** Expected uncompressed data */ + const void *expected; + /** Length of expected uncompressed data */ + size_t expected_len; +}; + +/** A DEFLATE fragment list */ +struct deflate_test_fragments { + /** Fragment lengths */ + size_t len[8]; +}; + +/** Define inline data */ +#define DATA(...) { __VA_ARGS__ } + +/** Define a DEFLATE test */ +#define DEFLATE( name, FORMAT, COMPRESSED, EXPECTED ) \ + static const uint8_t name ## _compressed[] = COMPRESSED; \ + static const uint8_t name ## _expected[] = EXPECTED; \ + static struct deflate_test name = { \ + .format = FORMAT, \ + .compressed = name ## _compressed, \ + .compressed_len = sizeof ( name ## _compressed ), \ + .expected = name ## _expected, \ + .expected_len = sizeof ( name ## _expected ), \ + }; + +/* Empty file, no compression */ +DEFLATE ( empty_literal, DEFLATE_RAW, + DATA ( 0x01, 0x00, 0x00, 0xff, 0xff ), DATA() ); + +/* "iPXE" string, no compression */ +DEFLATE ( literal, DEFLATE_RAW, + DATA ( 0x01, 0x04, 0x00, 0xfb, 0xff, 0x69, 0x50, 0x58, 0x45 ), + DATA ( 0x69, 0x50, 0x58, 0x45 ) ); + +/* "iPXE" string, no compression, split into two literals */ +DEFLATE ( split_literal, DEFLATE_RAW, + DATA ( 0x00, 0x02, 0x00, 0xfd, 0xff, 0x69, 0x50, 0x01, 0x02, 0x00, + 0xfd, 0xff, 0x58, 0x45 ), + DATA ( 0x69, 0x50, 0x58, 0x45 ) ); + +/* Empty file */ +DEFLATE ( empty, DEFLATE_RAW, DATA ( 0x03, 0x00 ), DATA() ); + +/* "Hello world" */ +DEFLATE ( hello_world, DEFLATE_RAW, + DATA ( 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, + 0x49, 0x01, 0x00 ), + DATA ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, + 0x64 ) ); + +/* "Hello hello world" */ +DEFLATE ( hello_hello_world, DEFLATE_RAW, + DATA ( 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57, 0xc8, 0x00, 0x93, 0xe5, + 0xf9, 0x45, 0x39, 0x29, 0x00 ), + DATA ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x68, 0x65, 0x6c, 0x6c, + 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64 ) ); + +/* "This specification defines a lossless compressed data format" */ +DEFLATE ( rfc_sentence, DEFLATE_RAW, + DATA ( 0x0d, 0xc6, 0xdb, 0x09, 0x00, 0x21, 0x0c, 0x04, 0xc0, 0x56, + 0xb6, 0x28, 0x1b, 0x08, 0x79, 0x70, 0x01, 0x35, 0xe2, 0xa6, + 0x7f, 0xce, 0xf9, 0x9a, 0xf1, 0x25, 0xc1, 0xe3, 0x9a, 0x91, + 0x2a, 0x9d, 0xb5, 0x61, 0x1e, 0xb9, 0x9d, 0x10, 0xcc, 0x22, + 0xa7, 0x93, 0xd0, 0x5a, 0xe7, 0xbe, 0xb8, 0xc1, 0xa4, 0x05, + 0x51, 0x77, 0x49, 0xff ), + DATA ( 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, + 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x61, 0x20, 0x6c, + 0x6f, 0x73, 0x73, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x63, 0x6f, + 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x64, + 0x61, 0x74, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74 ) ); + +/* "ZLIB Compressed Data Format Specification" */ +DEFLATE ( zlib, DEFLATE_ZLIB, + DATA ( 0x78, 0x01, 0x8b, 0xf2, 0xf1, 0x74, 0x52, 0x70, 0xce, 0xcf, + 0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e, 0x4d, 0x51, 0x70, 0x49, + 0x2c, 0x49, 0x54, 0x70, 0xcb, 0x2f, 0xca, 0x4d, 0x2c, 0x51, + 0x08, 0x2e, 0x48, 0x4d, 0xce, 0x4c, 0xcb, 0x4c, 0x4e, 0x2c, + 0xc9, 0xcc, 0xcf, 0x03, 0x00, 0x2c, 0x0e, 0x0e, 0xeb ), + DATA ( 0x5a, 0x4c, 0x49, 0x42, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x72, + 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x44, 0x61, 0x74, 0x61, + 0x20, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x53, 0x70, + 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e ) ); + +/* "ZLIB Compressed Data Format Specification" fragment list */ +static struct deflate_test_fragments zlib_fragments[] = { + { { -1UL, } }, + { { 0, 1, 5, -1UL, } }, + { { 0, 0, 1, 0, 0, 1, -1UL } }, + { { 10, 8, 4, 7, 11, -1UL } }, + { { 45, -1UL } }, + { { 48, -1UL } }, +}; + +/** + * Report DEFLATE test result + * + * @v deflate Decompressor + * @v test Deflate test + * @v frags Fragment list, or NULL + * @v file Test code file + * @v line Test code line + */ +static void deflate_okx ( struct deflate *deflate, + struct deflate_test *test, + struct deflate_test_fragments *frags, + const char *file, unsigned int line ) { + uint8_t data[ test->expected_len ]; + struct deflate_chunk in; + struct deflate_chunk out; + size_t frag_len = -1UL; + size_t offset = 0; + size_t remaining = test->compressed_len; + unsigned int i; + + /* Initialise decompressor */ + deflate_init ( deflate, test->format ); + + /* Initialise output chunk */ + deflate_chunk_init ( &out, virt_to_user ( data ), 0, sizeof ( data ) ); + + /* Process input (in fragments, if applicable) */ + for ( i = 0 ; i < ( sizeof ( frags->len ) / + sizeof ( frags->len[0] ) ) ; i++ ) { + + /* Initialise input chunk */ + if ( frags ) + frag_len = frags->len[i]; + if ( frag_len > remaining ) + frag_len = remaining; + deflate_chunk_init ( &in, virt_to_user ( test->compressed ), + offset, ( offset + frag_len ) ); + + /* Decompress this fragment */ + okx ( deflate_inflate ( deflate, &in, &out ) == 0, file, line ); + okx ( in.len == ( offset + frag_len ), file, line ); + okx ( in.offset == in.len, file, line ); + + /* Move to next fragment */ + offset = in.offset; + remaining -= frag_len; + if ( ! remaining ) + break; + + /* Check that decompression has not terminated early */ + okx ( ! deflate_finished ( deflate ), file, line ); + } + + /* Check decompression has terminated as expected */ + okx ( deflate_finished ( deflate ), file, line ); + okx ( offset == test->compressed_len, file, line ); + okx ( out.offset == test->expected_len, file, line ); + okx ( memcmp ( data, test->expected, test->expected_len ) == 0, + file, line ); +} +#define deflate_ok( deflate, test, frags ) \ + deflate_okx ( deflate, test, frags, __FILE__, __LINE__ ) + +/** + * Perform DEFLATE self-test + * + */ +static void deflate_test_exec ( void ) { + struct deflate *deflate; + unsigned int i; + + /* Allocate shared structure */ + deflate = malloc ( sizeof ( *deflate ) ); + ok ( deflate != NULL ); + + /* Perform self-tests */ + if ( deflate ) { + + /* Test as a single pass */ + deflate_ok ( deflate, &empty_literal, NULL ); + deflate_ok ( deflate, &literal, NULL ); + deflate_ok ( deflate, &split_literal, NULL ); + deflate_ok ( deflate, &empty, NULL ); + deflate_ok ( deflate, &hello_world, NULL ); + deflate_ok ( deflate, &hello_hello_world, NULL ); + deflate_ok ( deflate, &rfc_sentence, NULL ); + deflate_ok ( deflate, &zlib, NULL ); + + /* Test fragmentation */ + for ( i = 0 ; i < ( sizeof ( zlib_fragments ) / + sizeof ( zlib_fragments[0] ) ) ; i++ ) { + deflate_ok ( deflate, &zlib, &zlib_fragments[i] ); + } + } + + /* Free shared structure */ + free ( deflate ); +} + +/** DEFLATE self-test */ +struct self_test deflate_test __self_test = { + .name = "deflate", + .exec = deflate_test_exec, +}; | ||
[-] [+] | Added | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/dns_test.c ^ |
@@ -0,0 +1,605 @@ +/* + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * DNS self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <string.h> +#include <assert.h> +#include <ipxe/dns.h> +#include <ipxe/test.h> + +/** Define inline data */ +#define DATA(...) { __VA_ARGS__ } + +/** A DNS encoding test */ +struct dns_encode_test { + /** String */ + const char *string; + /** Encoded string */ + const void *data; + /** Length of encoded string */ + int len; +}; + +/** + * Define a DNS encoding test + * + * @v _name Test name + * @v _string Test string + * @v _data Expected encoded data + * @ret test DNS encoding test + */ +#define DNS_ENCODE( _name, _string, _data ) \ + static const uint8_t _name ## __data[] = _data; \ + static struct dns_encode_test _name = { \ + .string = _string, \ + .data = _name ## __data, \ + .len = sizeof ( _name ## __data ), \ + } + +/** + * Report DNS encoding test result + * + * @v test DNS encoding test + * @v file Test code file + * @v line Test code line + */ +static void dns_encode_okx ( struct dns_encode_test *test, const char *file, + unsigned int line ) { + uint8_t data[ test->len ]; + struct dns_name name; + int len; + + /* Check ability to determine length with no buffer */ + memset ( &name, 0, sizeof ( name ) ); + len = dns_encode ( test->string, &name ); + okx ( len >= 0, file, line ); + okx ( len == test->len, file, line ); + + /* Check encoded name */ + name.data = data; + name.len = sizeof ( data ); + len = dns_encode ( test->string, &name ); + okx ( len >= 0, file, line ); + if ( len >= 0 ) { + okx ( len == test->len, file, line ); + okx ( memcmp ( data, test->data, test->len ) == 0, file, line ); + DBGC ( test, "DNS encoded \"%s\" to:\n", test->string ); + DBGC_HDA ( test, 0, data, len ); + } +} +#define dns_encode_ok( test ) dns_encode_okx ( test, __FILE__, __LINE__ ) + +/** + * Report DNS encoding failure test result + * + * @v test DNS encoding test + * @v file Test code file + * @v line Test code line + */ +static void dns_encode_fail_okx ( struct dns_encode_test *test, + const char *file, unsigned int line ) { + struct dns_name name = { .data = NULL, .len = 0 }; + int len; + + len = dns_encode ( test->string, &name ); + okx ( len < 0, file, line ); +} +#define dns_encode_fail_ok( test ) \ + dns_encode_fail_okx ( test, __FILE__, __LINE__ ) + +/** A DNS decoding test */ +struct dns_decode_test { + /** Name */ + struct dns_name name; + /** Expected string */ + const char *string; +}; + +/** + * Define a DNS decoding test + * + * @v _name Test name + * @v _data RFC1035-encoded data + * @v _offset Starting offset within encoded data + * @v _string Expected decoded string + * @ret test DNS decoding test + */ +#define DNS_DECODE( _name, _data, _offset, _string ) \ + static uint8_t _name ## __data[] = _data; \ + static struct dns_decode_test _name = { \ + .name = { \ + .data = _name ## __data, \ + .offset = _offset, \ + .len = sizeof ( _name ## __data ), \ + }, \ + .string = _string, \ + } + +/** + * Report DNS decoding test result + * + * @v test DNS decoding test + * @v file Test code file + * @v line Test code line + */ +static void dns_decode_okx ( struct dns_decode_test *test, const char *file, + unsigned int line ) { + char string[ strlen ( test->string ) + 1 /* NUL */ ]; + int len; + + /* Check ability to determine length with no buffer */ + len = dns_decode ( &test->name, NULL, 0 ); + okx ( len >= 0, file, line ); + okx ( len == ( ( int ) strlen ( test->string ) ), file, line ); + + /* Check decoded string */ + len = dns_decode ( &test->name, string, sizeof ( string ) ); + okx ( len >= 0, file, line ); + if ( len >= 0 ) { + okx ( strcmp ( string, test->string ) == 0, file, line ); + DBGC ( test, "DNS decoded \"%s\" from offset %#zx in:\n", + string, test->name.offset ); + DBGC_HDA ( test, 0, test->name.data, test->name.len ); + } +} +#define dns_decode_ok( test ) dns_decode_okx ( test, __FILE__, __LINE__ ) + +/** + * Report DNS decoding failure test result + * + * @v test DNS decoding test + * @v file Test code file + * @v line Test code line + */ +static void dns_decode_fail_okx ( struct dns_decode_test *test, + const char *file, unsigned int line ) { + int len; + + len = dns_decode ( &test->name, NULL, 0 ); + okx ( len < 0, file, line ); +} +#define dns_decode_fail_ok( test ) \ + dns_decode_fail_okx ( test, __FILE__, __LINE__ ) + +/** A DNS comparison test */ +struct dns_compare_test { + /** First name */ + struct dns_name first; + /** Second name */ + struct dns_name second; +}; + +/** + * Define a DNS comparison test + * + * @v _name Test name + * @v _first_data First RFC1035-encoded data + * @v _first_offset Starting offset within first encoded data + * @v _second_data Second RFC1035-encoded data + * @v _second_offset Starting offset within second encoded data + * @ret test DNS comparison test + */ +#define DNS_COMPARE( _name, _first_data, _first_offset, _second_data, \ + _second_offset ) \ + static uint8_t _name ## __first_data[] = _first_data; \ + static uint8_t _name ## __second_data[] = _second_data; \ + static struct dns_compare_test _name = { \ + .first = { \ + .data = _name ## __first_data, \ + .offset = _first_offset, \ + .len = sizeof ( _name ## __first_data ), \ + }, \ + .second = { \ + .data = _name ## __second_data, \ + .offset = _second_offset, \ + .len = sizeof ( _name ## __second_data ), \ + }, \ + } + +/** + * Report DNS comparison test result + * + * @v test DNS comparison test + * @v file Test code file + * @v line Test code line + */ +static void dns_compare_okx ( struct dns_compare_test *test, const char *file, + unsigned int line ) { + + okx ( dns_compare ( &test->first, &test->second ) == 0, file, line ); +} +#define dns_compare_ok( test ) dns_compare_okx ( test, __FILE__, __LINE__ ) + +/** + * Report DNS comparison test failure result + * + * @v test DNS comparison test + * @v file Test code file + * @v line Test code line + */ +static void dns_compare_fail_okx ( struct dns_compare_test *test, + const char *file, unsigned int line ) { + + okx ( dns_compare ( &test->first, &test->second ) != 0, file, line ); +} +#define dns_compare_fail_ok( test ) \ + dns_compare_fail_okx ( test, __FILE__, __LINE__ ) + +/** A DNS copying test */ +struct dns_copy_test { + /** Source name */ + struct dns_name src; + /** Expected copied name */ + struct dns_name dst; +}; + +/** + * Define a DNS copying test + * + * @v _name Test name + * @v _src_data Source RFC1035-encoded data + * @v _src_offset Starting offset within source encoded data + * @v _dst_data Expected copied RFC1035-encoded data + * @v _dst_offset Starting offset withint copied encoded data + * @ret test DNS copying test + */ +#define DNS_COPY( _name, _src_data, _src_offset, _dst_data, \ + _dst_offset ) \ + static uint8_t _name ## __src_data[] = _src_data; \ + static uint8_t _name ## __dst_data[] = _dst_data; \ + static struct dns_copy_test _name = { \ + .src = { \ + .data = _name ## __src_data, \ + .offset = _src_offset, \ + .len = sizeof ( _name ## __src_data ), \ + }, \ + .dst = { \ + .data = _name ## __dst_data, \ + .offset = _dst_offset, \ + .len = sizeof ( _name ## __dst_data ), \ + }, \ + } + +/** + * Report a DNS copying test result + * + * @v test DNS copying test + * @v file Test code file + * @v line Test code line + */ +static void dns_copy_okx ( struct dns_copy_test *test, + const char *file, unsigned int line ) { + uint8_t data[ test->dst.len ]; + struct dns_name dst; + int len; + + /* Check ability to determine length with no buffer */ + memset ( &dst, 0, sizeof ( dst ) ); + len = dns_copy ( &test->src, &dst ); + okx ( len >= 0, file, line ); + okx ( len == ( ( int ) ( test->dst.len - test->dst.offset ) ), + file, line ); + + /* Check copied name */ + dst.data = data; + dst.offset = test->dst.offset; + dst.len = sizeof ( data ); + memcpy ( dst.data, test->dst.data, test->dst.offset ); + len = dns_copy ( &test->src, &dst ); + okx ( len >= 0, file, line ); + okx ( len == ( ( int ) ( test->dst.len - test->dst.offset ) ), + file, line ); + okx ( memcmp ( data, test->dst.data, sizeof ( data ) ) == 0, + file, line ); + DBGC ( test, "DNS copied:\n" ); + DBGC_HDA ( test, 0, test->src.data, test->src.len ); + DBGC_HDA ( test, 0, data, ( test->dst.offset + len ) ); +} +#define dns_copy_ok( test ) dns_copy_okx ( test, __FILE__, __LINE__ ) + +/** + * Report a DNS copying failure test result + * + * @v test DNS copying test + * @v file Test code file + * @v line Test code line + */ +static void dns_copy_fail_okx ( struct dns_copy_test *test, + const char *file, unsigned int line ) { + struct dns_name dst; + int len; + + memset ( &dst, 0, sizeof ( dst ) ); + len = dns_copy ( &test->src, &dst ); + okx ( len < 0, file, line ); +} +#define dns_copy_fail_ok( test ) dns_copy_fail_okx ( test, __FILE__, __LINE__ ) + +/** A DNS search list test */ +struct dns_list_test { + /** Search list */ + struct dns_name list; + /** Expected decoded search list */ + const char **strings; + /** Number of expected decoded string */ + unsigned int count; +}; + +/** + * Define a DNS search list test + * + * @v _name Test name + * @v _list RFC1035-encoded data + * @v _strings Expected decoded strings + * @ret test DNS search list test + */ +#define DNS_LIST( _name, _list, _strings ) \ + static uint8_t _name ## __list[] = _list; \ + static const char * _name ## __strings[] = _strings; \ + static struct dns_list_test _name = { \ + .list = { \ + .data = _name ## __list, \ + .offset = 0, \ + .len = sizeof ( _name ## __list ), \ + }, \ + .strings = _name ## __strings, \ + .count = ( sizeof ( _name ## __strings ) / \ + sizeof ( _name ## __strings[0] ) ), \ + } + +/** + * Report DNS search list test result + * + * @v test DNS search list test + * @v file Test code file + * @v line Test code line + */ +static void dns_list_okx ( struct dns_list_test *test, const char *file, + unsigned int line ) { + struct dns_name name; + unsigned int i; + + DBGC ( test, "DNS search list:\n" ); + DBGC_HDA ( test, 0, test->list.data, test->list.len ); + memcpy ( &name, &test->list, sizeof ( name ) ); + for ( i = 0 ; i < test->count ; i++ ) { + char buf[ strlen ( test->strings[i] ) + 1 /* NUL */ ]; + int len; + int offset; + + /* Decode this name */ + len = dns_decode ( &name, buf, sizeof ( buf ) ); + okx ( len >= 0, file, line ); + if ( len >= 0 ) { + okx ( len == ( ( int ) strlen ( test->strings[i] ) ), + file, line ); + okx ( strcmp ( buf, test->strings[i] ) == 0, + file, line ); + DBGC ( test, "DNS search list found \"%s\" at offset " + "%#zx\n", buf, name.offset ); + } + + /* Skip to next name */ + offset = dns_skip ( &name ); + okx ( offset >= 0, file, line ); + name.offset = offset; + } + + /* Check that we have consumed the whole search list */ + okx ( name.offset == name.len, file, line ); +} +#define dns_list_ok( test ) dns_list_okx ( test, __FILE__, __LINE__ ) + +/* Simple encoding test */ +DNS_ENCODE ( encode_simple, "ipxe.org", + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ) ); + +/* Single-word encoding test */ +DNS_ENCODE ( encode_single, "foo", DATA ( 3, 'f', 'o', 'o', 0 ) ); + +/* Absolute encoding test */ +DNS_ENCODE ( encode_absolute, "git.ipxe.org.", + DATA ( 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', + 0 ) ); + +/* Empty string encoding test */ +DNS_ENCODE ( encode_empty, "", DATA ( 0 ) ); + +/* Root domain encoding test */ +DNS_ENCODE ( encode_root, ".", DATA ( 0 ) ); + +/* Invalid initial dot encoding test */ +DNS_ENCODE ( encode_initial_dot, ".foo", DATA() ); + +/* Invalid double dot encoding test */ +DNS_ENCODE ( encode_double_dot, "ipxe..org", DATA() ); + +/* Invalid solo double dot encoding test */ +DNS_ENCODE ( encode_solo_double_dot, "..", DATA() ); + +/* Invalid trailing double dot encoding test */ +DNS_ENCODE ( encode_trailing_double_dot, "ipxe.org..", DATA() ); + +/* Invalid overlength label encoding test */ +DNS_ENCODE ( encode_overlength, + "this-label-is-maliciously-long-in-an-attempt-to-overflow-the-" + "length-field-and-generate-a-length-which-looks-like-a-" + "compression-pointer", DATA() ); + +/* Simple decoding test */ +DNS_DECODE ( decode_simple, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + "ipxe.org" ); + +/* Compression pointer decoding test */ +DNS_DECODE ( decode_ptr, + DATA ( 3, 'o', 'r', 'g', 0, 3, 'g', 'i', 't', 4, 'i', 'p', 'x', + 'e', 0xc0, 0x00 ), 5, + "git.ipxe.org" ); + +/* Root decoding test */ +DNS_DECODE ( decode_root, + DATA ( 0 ), 0, "" ); + +/* Incomplete name decoding test */ +DNS_DECODE ( decode_incomplete_name, + DATA ( 4, 'i', 'p', 'x', 'e' ), 0, NULL ); + +/* Incomplete label decoding test */ +DNS_DECODE ( decode_incomplete_label, + DATA ( 4, 'i', 'p', 'x' ), 0, NULL ); + +/* Incomplete compression pointer decoding test */ +DNS_DECODE ( decode_incomplete_ptr, + DATA ( 3, 'o', 'r', 'g', 0, 4, 'i', 'p', 'x', 'e', 0xc0 ), 5, + NULL ); + +/* Forward reference decoding test */ +DNS_DECODE ( decode_forward, + DATA ( 0xc0, 0x02, 3, 'f', 'o', 'o', 0 ), 0, NULL ); + +/* Infinite loop decoding test */ +DNS_DECODE ( decode_infinite, + DATA ( 4, 'i', 'p', 'x', 'e', 0xc0, 0x00 ), 0, NULL ); + +/* Empty decoding test */ +DNS_DECODE ( decode_empty, + DATA (), 0, NULL ); + +/* Simple comparison test */ +DNS_COMPARE ( compare_simple, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 ); + +/* Compression pointer comparison test */ +DNS_COMPARE ( compare_ptr, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + DATA ( 3, 'o', 'r', 'g', 0, 4, 'i', 'p', 'x', 'e', + 0xc0, 0x00 ), 5 ); + +/* Case insensitive comparison test */ +DNS_COMPARE ( compare_case, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'O', 'R', 'G', 0 ), 0 ); + +/* Mismatch comparison test */ +DNS_COMPARE ( compare_mismatch, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + DATA ( 4, 'g', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 ); + +/* Infinite loop comparison test */ +DNS_COMPARE ( compare_infinite, + DATA ( 3, 'f', 'o', 'o', 0xc0, 0x00 ), 0, + DATA ( 3, 'f', 'o', 'o', 0xc0, 0x00 ), 0 ); + +/* Simple copying test */ +DNS_COPY ( copy_simple, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0 ); + +/* Simple copying test with offset */ +DNS_COPY ( copy_offset, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0 ), 0, + DATA ( 'f', 'o', 'o', 0, 4, 'i', 'p', 'x', 'e', + 3, 'o', 'r', 'g', 0 ), 4 ); + +/* Compression pointer copying test */ +DNS_COPY ( copy_ptr, + DATA ( 3, 'o', 'r', 'g', 0, 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', + 0xc0, 0x00 ), 5, + DATA ( 3, 'g', 'i', 't', 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', + 0 ), 0 ); + +/* Infinite loop copying test */ +DNS_COPY ( copy_infinite, + DATA ( 4, 'l', 'o', 'o', 'p', 7, 'f', 'o', 'r', 'e', 'v', 'e', 'r', + 0xc0, 0x05 ), 0, + DATA (), 0 ); + +/* DNS search list test */ +DNS_LIST ( search, + DATA ( 4, 'i', 'p', 'x', 'e', 3, 'o', 'r', 'g', 0, + 4, 'b', 'o', 'o', 't', 0xc0, 0x00, + 3, 'd', 'e', 'v', 0xc0, 0x0a, + 11, 'n', 'e', 't', 'w', 'o', 'r', 'k', 'b', 'o', 'o', 't', + 0xc0, 0x05 ), + DATA ( "ipxe.org", "boot.ipxe.org", "dev.boot.ipxe.org", + "networkboot.org" ) ); + +/** + * Perform DNS self-test + * + */ +static void dns_test_exec ( void ) { + + /* Encoding tests */ + dns_encode_ok ( &encode_simple ); + dns_encode_ok ( &encode_single ); + dns_encode_ok ( &encode_absolute ); + dns_encode_ok ( &encode_empty ); + dns_encode_ok ( &encode_root ); + dns_encode_fail_ok ( &encode_initial_dot ); + dns_encode_fail_ok ( &encode_double_dot ); + dns_encode_fail_ok ( &encode_solo_double_dot ); + dns_encode_fail_ok ( &encode_trailing_double_dot ); + dns_encode_fail_ok ( &encode_overlength ); + + /* Decoding tests */ + dns_decode_ok ( &decode_simple ); + dns_decode_ok ( &decode_ptr ); + dns_decode_ok ( &decode_root ); + dns_decode_fail_ok ( &decode_incomplete_name ); + dns_decode_fail_ok ( &decode_incomplete_label ); + dns_decode_fail_ok ( &decode_incomplete_ptr ); + dns_decode_fail_ok ( &decode_forward ); + dns_decode_fail_ok ( &decode_infinite ); + dns_decode_fail_ok ( &decode_empty ); + + /* Comparison tests */ + dns_compare_ok ( &compare_simple ); + dns_compare_ok ( &compare_ptr ); + dns_compare_ok ( &compare_case ); + dns_compare_fail_ok ( &compare_mismatch ); + dns_compare_fail_ok ( &compare_infinite ); + + /* Copying tests */ + dns_copy_ok ( ©_simple ); + dns_copy_ok ( ©_offset ); + dns_copy_ok ( ©_ptr ); + dns_copy_fail_ok ( ©_infinite ); + + /* Search list tets */ + dns_list_ok ( &search ); +} + +/** DNS self-test */ +struct self_test dns_test __self_test = { + .name = "dns", + .exec = dns_test_exec, +}; | ||
[-] [+] | Added | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/pixbuf_test.c ^ |
@@ -0,0 +1,76 @@ +/* + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Pixel buffer self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <assert.h> +#include <ipxe/image.h> +#include <ipxe/pixbuf.h> +#include <ipxe/test.h> +#include "pixbuf_test.h" + +/** + * Report pixel buffer test result + * + * @v test Pixel buffer test + * @v file Test code file + * @v line Test code line + */ +void pixbuf_okx ( struct pixel_buffer_test *test, const char *file, + unsigned int line ) { + struct pixel_buffer *pixbuf; + int rc; + + /* Sanity check */ + assert ( ( test->width * test->height * sizeof ( test->data[0] ) ) + == test->len ); + + /* Correct image data pointer */ + test->image->data = virt_to_user ( ( void * ) test->image->data ); + + /* Check that image is detected as PNM */ + okx ( image_probe ( test->image ) == 0, file, line ); + okx ( test->image->type == test->type, file, line ); + + /* Check that a pixel buffer can be created from the image */ + okx ( ( rc = image_pixbuf ( test->image, &pixbuf ) ) == 0, file, line ); + if ( rc == 0 ) { + + /* Check pixel buffer dimensions */ + okx ( pixbuf->width == test->width, file, line ); + okx ( pixbuf->height == test->height, file, line ); + + /* Check pixel buffer data */ + okx ( pixbuf->len == test->len, file, line ); + okx ( memcmp_user ( pixbuf->data, 0, + virt_to_user ( test->data ), 0, + test->len ) == 0, file, line ); + + pixbuf_put ( pixbuf ); + } +} | ||
[-] [+] | Added | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/pixbuf_test.h ^ |
@@ -0,0 +1,66 @@ +#ifndef _PIXBUF_TEST_H +#define _PIXBUF_TEST_H + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <ipxe/refcnt.h> +#include <ipxe/image.h> +#include <ipxe/test.h> + +/** A pixel buffer test */ +struct pixel_buffer_test { + /** Image type */ + struct image_type *type; + /** Source image */ + struct image *image; + /** Pixel data */ + const uint32_t *data; + /** Length of pixel data */ + size_t len; + /** Width */ + unsigned int width; + /** Height */ + unsigned int height; +}; + +/** + * Define a pixel buffer test + * + * @v _name Test name + * @v _type Test image file type + * @v _file Test image file data + * @v _width Expected pixel buffer width + * @v _height Expected pixel buffer height + * @v _data Expected pixel buffer data + * @ret test Pixel buffer test + */ +#define PIX( _name, _type, _file, _width, _height, _data ) \ + static const char _name ## __file[] = _file; \ + static const uint32_t _name ## __data[] = _data; \ + static struct image _name ## __image = { \ + .refcnt = REF_INIT ( ref_no_free ), \ + .name = #_name, \ + .data = ( userptr_t ) ( _name ## __file ), \ + .len = sizeof ( _name ## __file ), \ + }; \ + static struct pixel_buffer_test _name = { \ + .type = _type, \ + .image = & _name ## __image, \ + .data = _name ## __data, \ + .len = sizeof ( _name ## __data ), \ + .width = _width, \ + .height = _height, \ + }; + +extern void pixbuf_okx ( struct pixel_buffer_test *test, const char *file, + unsigned int line ); + +/** + * Report pixel buffer test result + * + * @v test Pixel buffer test + */ +#define pixbuf_ok( test ) pixbuf_okx ( test, __FILE__, __LINE__ ) + +#endif /* _PIXBUF_TEST_H */ | ||
[-] [+] | Added | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/png_test.c ^ |
@@ -0,0 +1,1993 @@ +/* + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * PNG self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <string.h> +#include <assert.h> +#include <ipxe/pixbuf.h> +#include <ipxe/png.h> +#include <ipxe/test.h> +#include "pixbuf_test.h" + +/** Define inline pixel data */ +#define DATA(...) { __VA_ARGS__ } + +/* Non-opaque alpha channel */ +PIX ( alpha, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x06, 0x00, 0x00, 0x00, 0xf3, 0x1b, 0xaf, 0xbc, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x06, + 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, + 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, + 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, + 0x9c, 0x18, 0x00, 0x00, 0x01, 0x25, 0x49, 0x44, 0x41, 0x54, 0x18, + 0xd3, 0x05, 0xc1, 0xcb, 0x2e, 0x03, 0x51, 0x00, 0x80, 0xe1, 0x7f, + 0x6e, 0xa9, 0xe9, 0x65, 0x32, 0x53, 0x6d, 0xa5, 0x42, 0xd3, 0x34, + 0x12, 0x0b, 0x0b, 0x1b, 0x04, 0x3b, 0x3b, 0x3b, 0x8f, 0xe1, 0x35, + 0xbc, 0x81, 0x67, 0xf1, 0x10, 0x22, 0x11, 0x0b, 0x42, 0x68, 0x17, + 0x5a, 0x42, 0x94, 0xd0, 0x9e, 0xe9, 0xf4, 0x4c, 0x67, 0x3a, 0x39, + 0x33, 0xc7, 0xf7, 0x19, 0x97, 0xd7, 0xc5, 0x45, 0x7b, 0x3c, 0xc0, + 0xd2, 0x8a, 0xa8, 0xea, 0xa3, 0x6d, 0x87, 0xc2, 0x6f, 0xe2, 0xa9, + 0x39, 0x58, 0x0e, 0x69, 0x6e, 0xa0, 0x55, 0x42, 0xb8, 0xb0, 0x70, + 0xa5, 0x60, 0xa5, 0xa4, 0x31, 0xea, 0x75, 0xec, 0x2c, 0xd7, 0x28, + 0x95, 0x51, 0xff, 0x19, 0xd2, 0x7b, 0xba, 0x25, 0x2b, 0xb9, 0x8c, + 0x8e, 0xcf, 0xf0, 0xc2, 0x2f, 0x6a, 0x71, 0x88, 0xca, 0x73, 0x22, + 0xbf, 0xc9, 0x9a, 0x08, 0xf1, 0x3e, 0x5f, 0x49, 0x82, 0x26, 0x62, + 0x77, 0x1f, 0x33, 0x13, 0x92, 0xd5, 0xc1, 0x3d, 0xe6, 0xf4, 0x8f, + 0x49, 0x63, 0x93, 0xd8, 0xa9, 0xa0, 0xbf, 0xc7, 0xf4, 0xbb, 0x07, + 0xd4, 0x06, 0x0f, 0x68, 0x39, 0xa7, 0xdf, 0xdd, 0xc3, 0x1b, 0x8f, + 0x58, 0x3a, 0x65, 0x26, 0xc1, 0x06, 0x1f, 0xc1, 0x16, 0x26, 0xe1, + 0x0c, 0x33, 0x92, 0x58, 0x51, 0x4c, 0x25, 0x9a, 0x32, 0xa9, 0xae, + 0xf3, 0xdc, 0x39, 0x22, 0xff, 0x15, 0x68, 0x29, 0x11, 0x6e, 0x83, + 0x74, 0xa9, 0x58, 0xa6, 0x19, 0x9f, 0xe5, 0x16, 0x33, 0xa3, 0x44, + 0x94, 0x80, 0x1d, 0xfc, 0xbd, 0x93, 0x2a, 0x13, 0x65, 0x3a, 0xdc, + 0x9c, 0x9c, 0x23, 0xdc, 0x06, 0x85, 0x08, 0xd9, 0xb9, 0xb9, 0xe2, + 0x76, 0xfb, 0x94, 0xe6, 0xd7, 0x90, 0xb6, 0x75, 0x87, 0x23, 0xe7, + 0xa4, 0x75, 0x93, 0xb0, 0x1c, 0x10, 0xe3, 0x60, 0x0b, 0xd7, 0x27, + 0xe9, 0xee, 0xa1, 0x0d, 0x93, 0xa9, 0xe3, 0x43, 0x01, 0x5e, 0x26, + 0x19, 0x74, 0xf6, 0x79, 0xe9, 0x1d, 0xd2, 0x7a, 0x7b, 0xc4, 0x4d, + 0x26, 0x58, 0x9d, 0x1d, 0x72, 0x39, 0x63, 0x11, 0x67, 0x14, 0x96, + 0xcd, 0x3f, 0x0a, 0xd4, 0x8b, 0x0b, 0x4d, 0xd7, 0xb9, 0xb6, 0x00, + 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, + 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, + 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, + 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, + 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, + 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, + 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, + 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, + 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, + 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x48637f, 0x54566c, 0x56566a, 0x4f5c72, 0x4e5e74, 0x4d667f, + 0x546478, 0x54657b, 0x50647b, 0x506277, 0x485d78, 0x4c5770, + 0x505a6f, 0x516378, 0x45617f, 0x525469, 0x5d4958, 0x67333d, + 0x643641, 0x535369, 0x5b4b5c, 0x624654, 0x604452, 0x594c5d, + 0x5b4455, 0x623643, 0x5e3e4e, 0x555668, 0x425979, 0x5c4151, + 0x5e404e, 0x5d3d4b, 0x5e3947, 0x53475c, 0x475b77, 0x68323c, + 0x5f3e4c, 0x455c77, 0x623744, 0x5f3848, 0x54475c, 0x475e7a, + 0x425171, 0x5d3a4b, 0x603948, 0x633642, 0x553f54, 0x3e5679, + 0x46516e, 0x682c36, 0x574356, 0x415975, 0x5f3341, 0x513d53, + 0x4d475f, 0x405a7a, 0x4a4762, 0x59384c, 0x5b394b, 0x435676, + 0x3b5b80, 0x3a5278, 0x5b3447, 0x4d405a, 0x573649, 0x4d445b, + 0x612d3b, 0x4d3c54, 0x454c68, 0x3a5a7d, 0x424b6a, 0x464866, + 0x454867, 0x3a597e, 0x3a5a80, 0x414f72, 0x484361, 0x33547d, + 0x3e4467, 0x43405d, 0x4f3c50, 0x4b364d, 0x404765, 0x395b7f ) ); + +/* Colour type 0, bit depth 1 */ +PIX ( ctype_0_1, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x60, 0x92, 0x11, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x01, 0x86, + 0xa0, 0x31, 0xe8, 0x96, 0x5f, 0x00, 0x00, 0x00, 0x02, 0x62, 0x4b, + 0x47, 0x44, 0x00, 0x01, 0xdd, 0x8a, 0x13, 0xa4, 0x00, 0x00, 0x00, + 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, + 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x0e, + 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0xff, 0x87, 0x01, + 0x15, 0x01, 0x00, 0x6b, 0x0d, 0x0b, 0xe3, 0xeb, 0x45, 0x62, 0x80, + 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, + 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, + 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, + 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, + 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, + 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, + 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, + 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, + 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff ) ); + +/* Colour type 0, bit depth 16 */ +PIX ( ctype_0_16, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x10, 0x00, 0x00, 0x00, 0x00, 0x86, 0xe0, 0x2c, 0x23, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x01, 0x86, + 0xa0, 0x31, 0xe8, 0x96, 0x5f, 0x00, 0x00, 0x00, 0x02, 0x62, 0x4b, + 0x47, 0x44, 0xff, 0xff, 0x14, 0xab, 0x31, 0xcd, 0x00, 0x00, 0x00, + 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, + 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x85, + 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x1d, 0x8e, 0xc9, 0x0a, 0xc2, + 0x50, 0x0c, 0x45, 0xdf, 0x5f, 0xb9, 0x52, 0xea, 0xac, 0x88, 0xad, + 0x58, 0x41, 0x70, 0x5e, 0x89, 0xb3, 0x82, 0x82, 0xa0, 0x9b, 0xb3, + 0xe9, 0x42, 0x44, 0xc4, 0x3f, 0xf6, 0xb4, 0x84, 0x0c, 0x37, 0xb9, + 0x37, 0x49, 0xc8, 0x38, 0x6b, 0x77, 0x9e, 0x7c, 0xf9, 0xf0, 0xe3, + 0x4d, 0x26, 0x3a, 0x70, 0xe3, 0x45, 0x80, 0x2d, 0x33, 0xda, 0x74, + 0xcc, 0x4b, 0xa6, 0x8c, 0x8d, 0xa9, 0xb8, 0xcf, 0x89, 0x70, 0x24, + 0xd1, 0x7a, 0xc2, 0x94, 0xab, 0x94, 0xb8, 0x88, 0x39, 0x7a, 0x10, + 0xe6, 0x85, 0x2a, 0xf7, 0x35, 0x0b, 0x6a, 0x12, 0x77, 0x54, 0xa9, + 0x33, 0xc8, 0x95, 0xb1, 0x8d, 0x06, 0x1b, 0x2e, 0x8e, 0x22, 0x9a, + 0x54, 0xdc, 0x52, 0xb6, 0x1a, 0x79, 0x37, 0x0c, 0x5d, 0x94, 0xb0, + 0x97, 0x37, 0x51, 0xbd, 0xa2, 0xe5, 0x20, 0xa2, 0x44, 0xd7, 0x37, + 0xff, 0x4c, 0xf2, 0x48, 0x0d, 0x2c, 0x7a, 0x80, 0xe2, 0x00, 0x00, + 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, + 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, + 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, + 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, + 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, + 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, + 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, + 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x858585, 0x6f6f6f, 0x6f6f6f, 0x777777, 0x7b7b7b, 0x8f8f8f, + 0x8d8d8d, 0x919191, 0x8b8b8b, 0x858585, 0x777777, 0x6c6c6c, + 0x747474, 0x898989, 0x808080, 0x696969, 0x5c5c5c, 0x474747, + 0x484848, 0x696969, 0x5f5f5f, 0x5b5b5b, 0x575757, 0x5f5f5f, + 0x535353, 0x474747, 0x4d4d4d, 0x6e6e6e, 0x6d6d6d, 0x4f4f4f, + 0x4f4f4f, 0x4b4b4b, 0x474747, 0x535353, 0x737373, 0x484848, + 0x4e4e4e, 0x737373, 0x484848, 0x474747, 0x535353, 0x7a7a7a, + 0x5d5d5d, 0x474747, 0x484848, 0x474747, 0x484848, 0x666666, + 0x5e5e5e, 0x424242, 0x4f4f4f, 0x6a6a6a, 0x414141, 0x434343, + 0x505050, 0x6e6e6e, 0x4e4e4e, 0x424242, 0x444444, 0x686868, + 0x707070, 0x5e5e5e, 0x404040, 0x454545, 0x3e3e3e, 0x4b4b4b, + 0x3d3d3d, 0x404040, 0x545454, 0x6c6c6c, 0x525252, 0x4e4e4e, + 0x4f4f4f, 0x6b6b6b, 0x6e6e6e, 0x5a5a5a, 0x484848, 0x606060, + 0x464646, 0x404040, 0x404040, 0x373737, 0x494949, 0x6f6f6f ) ); + +/* Colour type 0, bit depth 2 */ +PIX ( ctype_0_2, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xc0, 0xe8, 0xc1, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x01, 0x86, + 0xa0, 0x31, 0xe8, 0x96, 0x5f, 0x00, 0x00, 0x00, 0x02, 0x62, 0x4b, + 0x47, 0x44, 0x00, 0x03, 0x33, 0x84, 0x72, 0x88, 0x00, 0x00, 0x00, + 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, + 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x24, + 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x08, 0x0d, 0x0d, 0x0d, + 0x60, 0x08, 0x11, 0x0d, 0x11, 0x60, 0x08, 0x10, 0x11, 0x08, 0x60, + 0x70, 0x10, 0x09, 0x08, 0x60, 0x70, 0x0c, 0x00, 0xb2, 0x42, 0x43, + 0x1d, 0x02, 0x00, 0x59, 0xc5, 0x06, 0x00, 0x68, 0xee, 0x01, 0x07, + 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, + 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, + 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, + 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, + 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, + 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, + 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, + 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, + 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x555555, 0x555555, 0x555555, 0x555555, 0x555555, 0x555555, + 0x555555, 0x555555, 0x555555, 0x555555, 0x555555, 0x555555, + 0x555555, 0x555555, 0x555555, 0x555555, 0x555555, 0x000000, + 0x000000, 0x555555, 0x555555, 0x555555, 0x555555, 0x555555, + 0x555555, 0x000000, 0x000000, 0x555555, 0x555555, 0x555555, + 0x000000, 0x000000, 0x000000, 0x555555, 0x555555, 0x000000, + 0x000000, 0x555555, 0x000000, 0x000000, 0x555555, 0x555555, + 0x555555, 0x000000, 0x000000, 0x000000, 0x000000, 0x555555, + 0x555555, 0x000000, 0x555555, 0x555555, 0x000000, 0x000000, + 0x555555, 0x555555, 0x555555, 0x000000, 0x000000, 0x555555, + 0x555555, 0x555555, 0x000000, 0x000000, 0x000000, 0x555555, + 0x000000, 0x000000, 0x555555, 0x555555, 0x555555, 0x555555, + 0x555555, 0x555555, 0x555555, 0x555555, 0x555555, 0x555555, + 0x555555, 0x000000, 0x000000, 0x000000, 0x555555, 0x555555 ) ); + +/* Colour type 0, bit depth 4 */ +PIX ( ctype_0_4, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x80, 0x1d, 0x61, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x01, 0x86, + 0xa0, 0x31, 0xe8, 0x96, 0x5f, 0x00, 0x00, 0x00, 0x02, 0x62, 0x4b, + 0x47, 0x44, 0x00, 0x0f, 0x3a, 0x32, 0x3e, 0xa3, 0x00, 0x00, 0x00, + 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, + 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x37, + 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x68, 0x4f, 0xaf, 0x9c, + 0xd9, 0x5e, 0x56, 0xc1, 0x50, 0x96, 0xe2, 0x96, 0x1a, 0x1a, 0xe2, + 0xc6, 0x90, 0xea, 0xe2, 0x5a, 0xe2, 0xee, 0x12, 0xce, 0x10, 0xe2, + 0xe2, 0x16, 0xec, 0xe6, 0xe2, 0xce, 0xe0, 0xe2, 0x56, 0xe6, 0x62, + 0x62, 0x02, 0xe4, 0xbb, 0x95, 0xba, 0x39, 0x1b, 0xbb, 0x03, 0x00, + 0x7a, 0x4c, 0x0e, 0x45, 0x5a, 0x3c, 0xd1, 0xca, 0x00, 0x00, 0x00, + 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, + 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, + 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, + 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, + 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, + 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, + 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, + 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x888888, 0x777777, 0x666666, 0x777777, 0x777777, 0x999999, + 0x999999, 0x999999, 0x888888, 0x777777, 0x777777, 0x666666, + 0x777777, 0x888888, 0x777777, 0x666666, 0x666666, 0x444444, + 0x444444, 0x666666, 0x666666, 0x555555, 0x555555, 0x555555, + 0x555555, 0x444444, 0x444444, 0x666666, 0x666666, 0x555555, + 0x444444, 0x444444, 0x444444, 0x555555, 0x777777, 0x444444, + 0x444444, 0x777777, 0x444444, 0x444444, 0x555555, 0x777777, + 0x555555, 0x444444, 0x444444, 0x444444, 0x444444, 0x666666, + 0x555555, 0x333333, 0x444444, 0x666666, 0x444444, 0x444444, + 0x444444, 0x777777, 0x444444, 0x444444, 0x444444, 0x666666, + 0x777777, 0x666666, 0x444444, 0x444444, 0x333333, 0x444444, + 0x333333, 0x444444, 0x555555, 0x777777, 0x555555, 0x444444, + 0x444444, 0x666666, 0x777777, 0x555555, 0x444444, 0x666666, + 0x444444, 0x333333, 0x333333, 0x333333, 0x444444, 0x777777 ) ); + +/* Colour type 0, bit depth 8 */ +PIX ( ctype_0_8, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x70, 0xf0, 0x60, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x01, 0x86, + 0xa0, 0x31, 0xe8, 0x96, 0x5f, 0x00, 0x00, 0x00, 0x02, 0x62, 0x4b, + 0x47, 0x44, 0x00, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x00, 0x00, 0x00, + 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, + 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x62, + 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x68, 0xcd, 0xcf, 0x2f, + 0xaf, 0xee, 0xef, 0x9d, 0xd8, 0xdd, 0x5a, 0x9e, 0x53, 0xd2, 0xc9, + 0xd0, 0x90, 0x19, 0xe3, 0xe1, 0x91, 0x19, 0x1f, 0x1d, 0x1e, 0x1f, + 0xec, 0xee, 0x97, 0xc7, 0x90, 0xeb, 0x1f, 0xe0, 0xed, 0x1e, 0x5c, + 0xec, 0xe9, 0x57, 0xec, 0xe9, 0x1e, 0x52, 0xc5, 0x10, 0xeb, 0xee, + 0xe9, 0xee, 0x91, 0x16, 0xe7, 0xec, 0x9f, 0xe5, 0xe8, 0x1c, 0x90, + 0xc7, 0xe0, 0xe7, 0xe4, 0x9a, 0x51, 0x10, 0xe7, 0xe0, 0x6a, 0xef, + 0x6d, 0xe7, 0x10, 0x92, 0xc3, 0x10, 0xe4, 0xe7, 0x9f, 0x9d, 0x17, + 0xe5, 0x91, 0xe8, 0xe6, 0xe0, 0x60, 0xee, 0x99, 0x0f, 0x00, 0xb8, + 0xaa, 0x1e, 0x19, 0xe8, 0x28, 0x25, 0xa0, 0x00, 0x00, 0x00, 0x25, + 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, + 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, + 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, + 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, + 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, + 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, + 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, + 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x858585, 0x6f6f6f, 0x6f6f6f, 0x777777, 0x7b7b7b, 0x8f8f8f, + 0x8d8d8d, 0x919191, 0x8b8b8b, 0x858585, 0x777777, 0x6c6c6c, + 0x747474, 0x898989, 0x808080, 0x696969, 0x5c5c5c, 0x484848, + 0x484848, 0x696969, 0x5f5f5f, 0x5b5b5b, 0x575757, 0x5f5f5f, + 0x535353, 0x474747, 0x4e4e4e, 0x6e6e6e, 0x6d6d6d, 0x4f4f4f, + 0x505050, 0x4b4b4b, 0x474747, 0x535353, 0x737373, 0x494949, + 0x4e4e4e, 0x737373, 0x494949, 0x474747, 0x545454, 0x7a7a7a, + 0x5d5d5d, 0x474747, 0x494949, 0x474747, 0x484848, 0x666666, + 0x5e5e5e, 0x434343, 0x4f4f4f, 0x6a6a6a, 0x414141, 0x434343, + 0x505050, 0x6e6e6e, 0x4e4e4e, 0x424242, 0x454545, 0x686868, + 0x707070, 0x5e5e5e, 0x404040, 0x454545, 0x3f3f3f, 0x4b4b4b, + 0x3e3e3e, 0x404040, 0x545454, 0x6c6c6c, 0x525252, 0x4e4e4e, + 0x4f4f4f, 0x6b6b6b, 0x6e6e6e, 0x5a5a5a, 0x484848, 0x616161, + 0x464646, 0x404040, 0x404040, 0x373737, 0x494949, 0x6f6f6f ) ); + +/* Colour type 2, bit depth 16 */ +PIX ( ctype_2_16, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x10, 0x02, 0x00, 0x00, 0x00, 0x2c, 0xe9, 0xe4, 0xa8, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x06, + 0x62, 0x4b, 0x47, 0x44, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x09, + 0x58, 0xf7, 0xdc, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, + 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, + 0x9c, 0x18, 0x00, 0x00, 0x01, 0x45, 0x49, 0x44, 0x41, 0x54, 0x18, + 0xd3, 0x2d, 0xcb, 0xc1, 0x6e, 0xd2, 0x00, 0x00, 0x00, 0xd0, 0x47, + 0x4b, 0x83, 0xb0, 0x8d, 0x00, 0x8e, 0x99, 0x19, 0x25, 0x64, 0x31, + 0xf1, 0xb0, 0x83, 0x97, 0xcd, 0xa8, 0x37, 0x6f, 0xde, 0xfc, 0x0c, + 0x7f, 0x83, 0x3f, 0xf0, 0x5b, 0xfc, 0x08, 0xb3, 0x64, 0xf1, 0xa0, + 0xd1, 0xe8, 0x38, 0xb8, 0x69, 0x5c, 0x86, 0xc6, 0x41, 0x4b, 0x29, + 0x83, 0x35, 0x2d, 0xf5, 0xe2, 0xbb, 0xbf, 0xda, 0xdb, 0xd1, 0xfb, + 0xd1, 0x66, 0xb4, 0x6f, 0x62, 0x2c, 0x54, 0x29, 0xa4, 0xb6, 0x75, + 0x54, 0xea, 0x22, 0x1b, 0x1d, 0x7d, 0x6d, 0x85, 0x05, 0x42, 0x91, + 0xb5, 0x52, 0x4d, 0xa5, 0xb0, 0x92, 0xb8, 0x11, 0x6a, 0xca, 0xc4, + 0xee, 0x68, 0xa8, 0xd4, 0xf4, 0xf4, 0xd4, 0x73, 0xa5, 0x4a, 0xa1, + 0x90, 0xeb, 0xf9, 0xe3, 0xdc, 0x81, 0x2f, 0x4e, 0xe5, 0x1a, 0x9a, + 0x2e, 0xbc, 0xf0, 0x5a, 0x5b, 0xe2, 0xca, 0x8e, 0xa5, 0x44, 0xa1, + 0x54, 0x4a, 0x75, 0xf4, 0xdd, 0x13, 0x4b, 0xb4, 0x5d, 0xfa, 0x6e, + 0xa5, 0xab, 0x2f, 0xf6, 0xc4, 0xb1, 0x20, 0x17, 0xcb, 0xdc, 0x35, + 0xf6, 0x51, 0x60, 0xe6, 0xda, 0xd4, 0xae, 0x87, 0x96, 0x22, 0x5b, + 0x2a, 0xbf, 0x4d, 0x9c, 0x19, 0x7a, 0x6a, 0xc7, 0xd8, 0x27, 0x95, + 0xcc, 0xc2, 0x99, 0xa1, 0x23, 0x6d, 0x13, 0x17, 0x6e, 0x45, 0x5a, + 0xa6, 0xba, 0x1e, 0xf8, 0xa5, 0xeb, 0x91, 0x80, 0xc4, 0x5c, 0x20, + 0x95, 0x09, 0xa5, 0x96, 0xb6, 0xa4, 0x66, 0xa6, 0xb6, 0xdd, 0xf7, + 0xd5, 0xc0, 0x73, 0xa5, 0xbf, 0x62, 0x95, 0x4c, 0x26, 0xd6, 0xb4, + 0x6b, 0xed, 0x56, 0xe1, 0xd6, 0x5a, 0xee, 0x52, 0xcb, 0x9e, 0xb9, + 0x9a, 0x86, 0xd4, 0x0a, 0xf5, 0xae, 0x6b, 0x3f, 0xad, 0x15, 0x02, + 0x85, 0x40, 0xe4, 0xc4, 0x4b, 0x6f, 0xfe, 0xe7, 0x8d, 0x58, 0xe2, + 0xd0, 0x89, 0x77, 0x4e, 0x3d, 0xf6, 0x4a, 0xdf, 0x95, 0x73, 0xfb, + 0x42, 0x1f, 0x44, 0x32, 0x0b, 0x6b, 0x3d, 0x81, 0x44, 0x4b, 0xd7, + 0x12, 0x91, 0x7a, 0xac, 0xa9, 0x63, 0x65, 0xe8, 0x48, 0xa5, 0x26, + 0x30, 0x13, 0xe9, 0x60, 0x83, 0xb6, 0x5c, 0x66, 0x6c, 0xe0, 0xd8, + 0x37, 0x07, 0x9e, 0xd9, 0xf3, 0xc3, 0x67, 0x4d, 0x2b, 0x53, 0xa1, + 0x81, 0x43, 0xa5, 0xcc, 0xdc, 0x8d, 0xa5, 0xdc, 0x46, 0xa8, 0xee, + 0x1f, 0x17, 0x48, 0x8c, 0x0b, 0x6d, 0x83, 0xc4, 0x70, 0x00, 0x00, + 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, + 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, + 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, + 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, + 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, + 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, + 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, + 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x8fc5fe, 0xa8acd7, 0xababd3, 0x9db7e3, 0x9cbbe8, 0x9acbfd, + 0xa8c7f0, 0xa8caf5, 0xa0c7f6, 0x9fc3ed, 0x8fb9f0, 0x98addf, + 0xa0b4de, 0xa1c6f0, 0x89c2fd, 0xa4a8d1, 0xba91af, 0xcd6579, + 0xc76c82, 0xa6a6d1, 0xb696b7, 0xc38ba7, 0xbf88a4, 0xb198b9, + 0xb687a9, 0xc46b86, 0xbb7c9b, 0xaaabd0, 0x83b1f1, 0xb781a1, + 0xbc7f9b, 0xba7996, 0xbc718d, 0xa58eb8, 0x8eb6ed, 0xd06478, + 0xbe7c97, 0x89b8ed, 0xc46e88, 0xbd7090, 0xa88db7, 0x8dbcf4, + 0x83a1e2, 0xb97395, 0xbf7190, 0xc56b84, 0xa97da7, 0x7bacf1, + 0x8ba1dc, 0xcf586c, 0xad85ab, 0x81b1e9, 0xbd6682, 0xa17aa6, + 0x998ebe, 0x7fb3f4, 0x948dc3, 0xb16f97, 0xb57195, 0x86aceb, + 0x75b5ff, 0x73a4ef, 0xb6688d, 0x997fb4, 0xae6b92, 0x9a88b5, + 0xc25a75, 0x9978a8, 0x8998cf, 0x74b3f9, 0x8396d3, 0x8b8fcb, + 0x8a90cd, 0x74b1fb, 0x74b3ff, 0x819ee3, 0x8f86c2, 0x66a8fa, + 0x7c88cd, 0x857fba, 0x9d78a0, 0x966c99, 0x7f8dc9, 0x72b6fd ) ); + +/* Colour type 2, bit depth 8 */ +PIX ( ctype_2_8, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x02, 0x00, 0x00, 0x00, 0x7c, 0x79, 0x38, 0xeb, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x06, + 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, + 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, + 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, + 0x9c, 0x18, 0x00, 0x00, 0x01, 0x04, 0x49, 0x44, 0x41, 0x54, 0x18, + 0xd3, 0x05, 0xc1, 0xc1, 0x4e, 0x83, 0x30, 0x00, 0x00, 0x50, 0x68, + 0x69, 0xb0, 0x6c, 0x23, 0x80, 0x30, 0x33, 0xa3, 0x84, 0x2c, 0x26, + 0x1e, 0x76, 0xf0, 0xb2, 0x19, 0xf5, 0xe6, 0xcd, 0x9b, 0x9f, 0xe1, + 0xe7, 0xf8, 0x2d, 0x7e, 0x84, 0x59, 0xb2, 0x78, 0xd0, 0x68, 0x74, + 0x1c, 0xdc, 0x34, 0x2e, 0x63, 0xc6, 0x41, 0x0b, 0x94, 0x01, 0x4d, + 0xa1, 0xbe, 0xa7, 0xde, 0x3f, 0xb6, 0x83, 0x28, 0x84, 0x52, 0x64, + 0x5d, 0x4b, 0x6a, 0xa8, 0xb5, 0x3c, 0x53, 0xe4, 0x0a, 0x44, 0x55, + 0xa3, 0x4a, 0x51, 0xd2, 0x1d, 0xc4, 0x8c, 0xec, 0xe9, 0x52, 0x75, + 0x1c, 0x8d, 0x37, 0x52, 0x08, 0xee, 0xfc, 0x2e, 0x86, 0x6f, 0x33, + 0xae, 0xe3, 0xe5, 0xd5, 0xad, 0x49, 0xd7, 0xbd, 0x82, 0x8a, 0xa6, + 0xc9, 0x2c, 0xef, 0x80, 0x50, 0x73, 0xf5, 0x59, 0xda, 0x1e, 0x39, + 0x9b, 0x00, 0x4e, 0xd8, 0x7e, 0xf8, 0x0c, 0x92, 0x6d, 0xec, 0x1e, + 0x17, 0xa8, 0x23, 0x37, 0xd1, 0x3c, 0x38, 0xef, 0x85, 0x2f, 0x92, + 0xe5, 0xf3, 0x60, 0x6c, 0x46, 0xcb, 0x1a, 0x19, 0xb1, 0x7d, 0xf4, + 0x63, 0x9f, 0x00, 0x85, 0xa6, 0x20, 0x63, 0x30, 0x2b, 0x3a, 0x59, + 0x12, 0x77, 0x0f, 0xdf, 0xfd, 0xcb, 0xe6, 0x8f, 0x48, 0xc6, 0x08, + 0x76, 0xab, 0x5a, 0xd4, 0x15, 0x5f, 0x19, 0xfd, 0x54, 0xd5, 0xb3, + 0x52, 0xd1, 0xec, 0xed, 0x77, 0x25, 0x80, 0x00, 0x68, 0x7a, 0x7d, + 0x47, 0xb0, 0xdb, 0x12, 0x3a, 0x9a, 0x3e, 0xcc, 0x4e, 0x6f, 0xbc, + 0xf5, 0x62, 0x00, 0x9f, 0x10, 0xcb, 0x2b, 0x07, 0x50, 0xc3, 0x2e, + 0x14, 0xa4, 0x11, 0x6c, 0x95, 0xc1, 0x58, 0xaa, 0x20, 0x41, 0x96, + 0xd2, 0x2a, 0x26, 0x67, 0xa1, 0x3f, 0xf9, 0x18, 0x5e, 0xf4, 0xbf, + 0x5e, 0x71, 0x19, 0x43, 0x7f, 0xd4, 0xb0, 0x74, 0x57, 0xf0, 0x16, + 0x6a, 0xff, 0xc1, 0x85, 0x8a, 0x8b, 0x87, 0xa4, 0x8a, 0x0e, 0x00, + 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, + 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, + 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, + 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, + 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, + 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, + 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, + 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, + 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, + 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x8fc5fe, 0xa8acd7, 0xababd3, 0x9db7e3, 0x9cbbe8, 0x9acbfd, + 0xa8c7f0, 0xa8caf5, 0xa0c7f6, 0x9fc3ed, 0x8fb9f0, 0x98addf, + 0xa0b4de, 0xa1c6f0, 0x89c2fd, 0xa4a8d1, 0xba91af, 0xcd6579, + 0xc76c82, 0xa6a6d1, 0xb696b7, 0xc38ba7, 0xbf88a4, 0xb198b9, + 0xb687a9, 0xc46b86, 0xbb7c9b, 0xaaabd0, 0x83b1f1, 0xb781a1, + 0xbc7f9b, 0xba7996, 0xbc718d, 0xa58eb8, 0x8eb6ed, 0xd06478, + 0xbe7c97, 0x89b8ed, 0xc46e88, 0xbd7090, 0xa88db7, 0x8dbcf4, + 0x83a1e2, 0xb97395, 0xbf7190, 0xc56b84, 0xa97da7, 0x7bacf1, + 0x8ba1dc, 0xcf586c, 0xad85ab, 0x81b1e9, 0xbd6682, 0xa17aa6, + 0x998ebe, 0x7fb3f4, 0x948dc3, 0xb16f97, 0xb57195, 0x86aceb, + 0x75b5ff, 0x73a4ef, 0xb6688d, 0x997fb4, 0xae6b92, 0x9a88b5, + 0xc25a75, 0x9978a8, 0x8998cf, 0x74b3f9, 0x8396d3, 0x8b8fcb, + 0x8a90cd, 0x74b1fb, 0x74b3ff, 0x819ee3, 0x8f86c2, 0x66a8fa, + 0x7c88cd, 0x857fba, 0x9d78a0, 0x966c99, 0x7f8dc9, 0x72b6fd ) ); + +/* Colour type 3, bit depth 1 */ +PIX ( ctype_3_1, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0x00, 0x8e, 0x75, 0x47, 0x2f, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x0c, + 0x50, 0x4c, 0x54, 0x45, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0x00, 0xff, 0xff, 0x35, 0x24, 0xb1, 0xc4, 0x00, 0x00, + 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x00, 0x88, 0x05, 0x1d, 0x48, + 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, + 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, + 0x00, 0x00, 0x24, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x60, + 0x00, 0x01, 0xc6, 0x06, 0xa6, 0x06, 0x06, 0xae, 0xc6, 0x2e, 0x06, + 0x06, 0xad, 0x8d, 0x5c, 0x06, 0x0c, 0x1a, 0xbf, 0xda, 0x0c, 0x18, + 0x98, 0x0f, 0xbf, 0xfa, 0x00, 0x00, 0x4a, 0x48, 0x07, 0xa6, 0x66, + 0x5c, 0x57, 0x79, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, + 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, + 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, + 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, + 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, + 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, + 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, + 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, + 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, + 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xff0000, + 0xff00ff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xff00ff, 0xff00ff, 0xffffff, 0xffffff, 0xffffff, + 0xff00ff, 0xff00ff, 0xff00ff, 0xffffff, 0xffffff, 0xff0000, + 0xff00ff, 0xffffff, 0xff00ff, 0xff00ff, 0xffffff, 0xffffff, + 0xffffff, 0xff00ff, 0xff00ff, 0xff00ff, 0xff00ff, 0x00ffff, + 0xffffff, 0xff0000, 0xffffff, 0xffffff, 0xff00ff, 0xff00ff, + 0xffffff, 0x00ffff, 0xffffff, 0xff00ff, 0xff00ff, 0xffffff, + 0x00ffff, 0x00ffff, 0xff00ff, 0xff00ff, 0xff00ff, 0xffffff, + 0xff0000, 0xff00ff, 0xffffff, 0x00ffff, 0xffffff, 0xffffff, + 0xffffff, 0x00ffff, 0x00ffff, 0xffffff, 0xffffff, 0x00ffff, + 0x00ffff, 0xff00ff, 0xff00ff, 0xff00ff, 0x00ffff, 0x00ffff ) ); + +/* Colour type 3, bit depth 2 */ +PIX ( ctype_3_2, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x04, 0x03, 0x00, 0x00, 0x00, 0x01, 0x35, 0xb2, 0x8f, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x15, + 0x50, 0x4c, 0x54, 0x45, 0xaa, 0xaa, 0xff, 0xaa, 0xaa, 0xaa, 0xaa, + 0x55, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0xff, 0x55, 0xaa, 0xaa, + 0xff, 0xff, 0xff, 0xef, 0x1e, 0x2f, 0x5e, 0x00, 0x00, 0x00, 0x01, + 0x62, 0x4b, 0x47, 0x44, 0x06, 0x61, 0x66, 0xb8, 0x7d, 0x00, 0x00, + 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, + 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, + 0x34, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x60, 0x10, 0x60, + 0x00, 0x03, 0x46, 0x21, 0x43, 0x41, 0x41, 0x61, 0x43, 0x06, 0x46, + 0x63, 0x43, 0x26, 0x03, 0x63, 0x01, 0x06, 0x66, 0x63, 0x13, 0x26, + 0x01, 0x63, 0x11, 0x06, 0x61, 0x03, 0x17, 0x63, 0x43, 0x65, 0x11, + 0x06, 0x41, 0x11, 0x07, 0x91, 0x60, 0xe3, 0x10, 0x00, 0x53, 0x53, + 0x04, 0xcd, 0x45, 0xaa, 0x11, 0x71, 0x00, 0x00, 0x00, 0x25, 0x74, + 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, + 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, + 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, + 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, + 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, + 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, + 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, + 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, + 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0xaaaaff, 0xaaaaff, 0xaaaaaa, 0xaaaaff, 0xaaaaff, 0xaaaaff, + 0xaaaaff, 0xaaaaff, 0xaaaaff, 0xaaaaff, 0xaaaaff, 0xaaaaff, + 0xaaaaff, 0xaaaaff, 0xaaaaff, 0xaaaaaa, 0xaaaaaa, 0xaa5555, + 0xaa55aa, 0xaaaaaa, 0xaaaaaa, 0xaaaaaa, 0xaaaaaa, 0xaaaaaa, + 0xaaaaaa, 0xaa55aa, 0xaa55aa, 0xaaaaaa, 0xaaaaff, 0xaaaaaa, + 0xaa55aa, 0xaa55aa, 0xaa55aa, 0xaaaaaa, 0xaaaaff, 0xaa5555, + 0xaa55aa, 0xaaaaff, 0xaa55aa, 0xaa55aa, 0xaaaaaa, 0xaaaaff, + 0xaaaaff, 0xaa55aa, 0xaa55aa, 0xaa55aa, 0xaa55aa, 0x55aaff, + 0xaaaaff, 0xaa5555, 0xaaaaaa, 0xaaaaff, 0xaa55aa, 0xaa55aa, + 0xaaaaaa, 0x55aaff, 0xaaaaaa, 0xaa55aa, 0xaa55aa, 0xaaaaff, + 0x55aaff, 0x55aaff, 0xaa55aa, 0xaa55aa, 0xaa55aa, 0xaaaaaa, + 0xaa5555, 0xaa55aa, 0xaaaaaa, 0x55aaff, 0xaaaaaa, 0xaaaaaa, + 0xaaaaaa, 0x55aaff, 0x55aaff, 0xaaaaff, 0xaaaaaa, 0x55aaff, + 0x55aaaa, 0xaa55aa, 0xaa55aa, 0xaa55aa, 0x55aaaa, 0x55aaff ) ); + +/* Colour type 3, bit depth 4 */ +PIX ( ctype_3_4, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x03, 0x00, 0x00, 0x00, 0xc4, 0xc5, 0x5f, 0x8e, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x8a, + 0x50, 0x4c, 0x54, 0x45, 0x88, 0xcc, 0xff, 0xaa, 0xaa, 0xdd, 0xaa, + 0xaa, 0xcc, 0x99, 0xbb, 0xdd, 0x99, 0xbb, 0xee, 0x99, 0xcc, 0xff, + 0xaa, 0xcc, 0xee, 0x99, 0xcc, 0xee, 0x88, 0xbb, 0xee, 0x99, 0xaa, + 0xdd, 0x88, 0xbb, 0xff, 0xbb, 0x99, 0xaa, 0xcc, 0x66, 0x77, 0xcc, + 0x66, 0x88, 0xbb, 0x99, 0xbb, 0xbb, 0x88, 0xaa, 0xaa, 0x99, 0xbb, + 0xbb, 0x77, 0x99, 0x88, 0xaa, 0xee, 0xbb, 0x88, 0x99, 0xbb, 0x77, + 0x88, 0xaa, 0x88, 0xbb, 0x88, 0x99, 0xdd, 0xaa, 0x77, 0xaa, 0x77, + 0xaa, 0xee, 0xcc, 0x55, 0x66, 0xaa, 0x88, 0xaa, 0xbb, 0x66, 0x88, + 0x99, 0x77, 0xaa, 0x99, 0x88, 0xbb, 0x77, 0xbb, 0xee, 0xaa, 0x77, + 0x99, 0x77, 0xbb, 0xff, 0x99, 0x77, 0xbb, 0xaa, 0x66, 0x99, 0xbb, + 0x55, 0x77, 0x88, 0x99, 0xcc, 0x88, 0x88, 0xcc, 0x77, 0xaa, 0xff, + 0x88, 0x88, 0xbb, 0x66, 0xaa, 0xff, 0x77, 0x88, 0xcc, 0x88, 0x77, + 0xbb, 0x99, 0x77, 0x99, 0x99, 0x66, 0x99, 0xff, 0xff, 0xff, 0xac, + 0x68, 0xae, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, + 0x2d, 0xcd, 0xda, 0x41, 0x3d, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, + 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, + 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x59, 0x49, 0x44, 0x41, + 0x54, 0x08, 0xd7, 0x0d, 0xc5, 0xd9, 0x02, 0x40, 0x20, 0x10, 0x00, + 0xc0, 0x95, 0x2b, 0x47, 0xb2, 0x49, 0xce, 0x08, 0xe5, 0xfe, 0xff, + 0xef, 0x63, 0x5e, 0x06, 0xc0, 0x23, 0x7e, 0x10, 0x46, 0x51, 0x1c, + 0xd0, 0xc4, 0x8f, 0x21, 0x25, 0x59, 0xce, 0x48, 0xc1, 0x79, 0xc9, + 0x19, 0x12, 0x10, 0x15, 0xa2, 0xac, 0x69, 0x8e, 0x94, 0xfd, 0x81, + 0x42, 0xc9, 0x9a, 0x56, 0x75, 0xbd, 0x18, 0x46, 0x3d, 0x81, 0x9e, + 0x51, 0x98, 0x76, 0x58, 0x56, 0xbd, 0x8d, 0xd6, 0x80, 0x75, 0x6e, + 0x37, 0xea, 0x38, 0xaf, 0xfb, 0x79, 0x2f, 0xf3, 0x01, 0xcb, 0xd6, + 0x06, 0x9f, 0x93, 0x26, 0xe0, 0xd0, 0x00, 0x00, 0x00, 0x25, 0x74, + 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, + 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, + 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, + 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, + 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, + 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, + 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, + 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, + 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x88ccff, 0xaaaadd, 0xaaaacc, 0x99bbdd, 0x99bbee, 0x99ccff, + 0xaaccee, 0xaaccee, 0x99ccee, 0x99bbee, 0x88bbee, 0x99aadd, + 0x99bbdd, 0x99ccee, 0x88bbff, 0xaaaacc, 0xbb99aa, 0xcc6677, + 0xcc6688, 0xaaaacc, 0xbb99bb, 0xbb88aa, 0xbb88aa, 0xaa99bb, + 0xbb88aa, 0xcc6688, 0xbb7799, 0xaaaacc, 0x88aaee, 0xbb8899, + 0xbb7799, 0xbb7799, 0xbb7788, 0xaa88bb, 0x88bbee, 0xcc6677, + 0xbb7799, 0x88bbee, 0xcc6688, 0xbb7788, 0xaa88bb, 0x88bbee, + 0x8899dd, 0xbb7799, 0xbb7788, 0xcc6688, 0xaa77aa, 0x77aaee, + 0x8899dd, 0xcc5566, 0xaa88aa, 0x88aaee, 0xbb6688, 0x9977aa, + 0x9988bb, 0x77bbee, 0x9988bb, 0xaa7799, 0xbb7799, 0x88aaee, + 0x77bbff, 0x77aaee, 0xbb6688, 0x9977bb, 0xaa6699, 0x9988bb, + 0xbb5577, 0x9977aa, 0x8899cc, 0x77bbff, 0x8899cc, 0x8888cc, + 0x8888cc, 0x77aaff, 0x77bbff, 0x8899dd, 0x8888bb, 0x66aaff, + 0x7788cc, 0x8877bb, 0x997799, 0x996699, 0x7788cc, 0x77bbff ) ); + +/* Colour type 3, bit depth 8 */ +PIX ( ctype_3_8, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x03, 0x00, 0x00, 0x00, 0xc4, 0xc5, 0x5f, 0x8e, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0xff, + 0x50, 0x4c, 0x54, 0x45, 0x8f, 0xc5, 0xfe, 0xa8, 0xac, 0xd7, 0xab, + 0xab, 0xd3, 0x9d, 0xb7, 0xe3, 0x9c, 0xbb, 0xe8, 0x9a, 0xcb, 0xfd, + 0xa8, 0xc7, 0xf0, 0xa8, 0xca, 0xf5, 0xa0, 0xc7, 0xf6, 0x9f, 0xc3, + 0xed, 0x8f, 0xb9, 0xf0, 0x98, 0xad, 0xdf, 0xa0, 0xb4, 0xde, 0xa1, + 0xc6, 0xf0, 0x89, 0xc2, 0xfd, 0xa4, 0xa8, 0xd1, 0xba, 0x91, 0xaf, + 0xcd, 0x65, 0x79, 0xc7, 0x6c, 0x82, 0xa6, 0xa6, 0xd1, 0xb6, 0x96, + 0xb7, 0xc3, 0x8b, 0xa7, 0xbf, 0x88, 0xa4, 0xb1, 0x98, 0xb9, 0xb6, + 0x87, 0xa9, 0xc4, 0x6b, 0x86, 0xbb, 0x7c, 0x9b, 0xaa, 0xab, 0xd0, + 0x83, 0xb1, 0xf1, 0xb7, 0x81, 0xa1, 0xbc, 0x7f, 0x9b, 0xba, 0x79, + 0x96, 0xbc, 0x71, 0x8d, 0xa5, 0x8e, 0xb8, 0x8e, 0xb6, 0xed, 0xd0, + 0x64, 0x78, 0xbe, 0x7c, 0x97, 0x89, 0xb8, 0xed, 0xc4, 0x6e, 0x88, + 0xbd, 0x70, 0x90, 0xa8, 0x8d, 0xb7, 0x8d, 0xbc, 0xf4, 0x83, 0xa1, + 0xe2, 0xb9, 0x73, 0x95, 0xbf, 0x71, 0x90, 0xc5, 0x6b, 0x84, 0xa9, + 0x7d, 0xa7, 0x7b, 0xac, 0xf1, 0x8b, 0xa1, 0xdc, 0xcf, 0x58, 0x6c, + 0xad, 0x85, 0xab, 0x81, 0xb1, 0xe9, 0xbd, 0x66, 0x82, 0xa1, 0x7a, + 0xa6, 0x99, 0x8e, 0xbe, 0x7f, 0xb3, 0xf4, 0x94, 0x8d, 0xc3, 0xb1, + 0x6f, 0x97, 0xb5, 0x71, 0x95, 0x86, 0xac, 0xeb, 0x75, 0xb5, 0xff, + 0x73, 0xa4, 0xef, 0xb6, 0x68, 0x8d, 0x99, 0x7f, 0xb4, 0xae, 0x6b, + 0x92, 0x9a, 0x88, 0xb5, 0xc2, 0x5a, 0x75, 0x99, 0x78, 0xa8, 0x89, + 0x98, 0xcf, 0x74, 0xb3, 0xf9, 0x83, 0x96, 0xd3, 0x8b, 0x8f, 0xcb, + 0x8a, 0x90, 0xcd, 0x74, 0xb1, 0xfb, 0x74, 0xb3, 0xff, 0x81, 0x9e, + 0xe3, 0x8f, 0x86, 0xc2, 0x66, 0xa8, 0xfa, 0x7c, 0x88, 0xcd, 0x85, + 0x7f, 0xba, 0x9d, 0x78, 0xa0, 0x96, 0x6c, 0x99, 0x7f, 0x8d, 0xc9, + 0x72, 0xb6, 0xfd, 0xff, 0xff, 0xff, 0xdb, 0x2a, 0x9f, 0xad, 0x00, + 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x54, 0xe4, 0x03, 0x88, + 0xa5, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, + 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, + 0x00, 0x00, 0x00, 0x62, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, + 0x60, 0x60, 0x64, 0x62, 0x66, 0x61, 0x65, 0x63, 0xe7, 0xe0, 0xe4, + 0xe2, 0xe6, 0xe1, 0x65, 0xe0, 0xe3, 0x17, 0x10, 0x14, 0x12, 0x16, + 0x11, 0x15, 0x13, 0x97, 0x90, 0x94, 0x92, 0x66, 0x90, 0x91, 0x95, + 0x93, 0x57, 0x50, 0x54, 0x52, 0x56, 0x51, 0x55, 0x53, 0xd7, 0xd0, + 0x64, 0xd0, 0xd2, 0xd6, 0xd1, 0xd5, 0xd3, 0x37, 0x30, 0x34, 0x32, + 0x36, 0x31, 0x35, 0x33, 0x67, 0xb0, 0xb0, 0xb4, 0xb2, 0xb6, 0xb1, + 0xb5, 0xb3, 0x77, 0x70, 0x74, 0x72, 0x76, 0x71, 0x65, 0x70, 0x73, + 0xf7, 0xf0, 0xf4, 0xf2, 0xf6, 0xf1, 0xf5, 0xf3, 0x0f, 0x08, 0x0c, + 0x0a, 0x06, 0x00, 0x96, 0xe0, 0x0d, 0x9f, 0x37, 0x73, 0x30, 0xa4, + 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, + 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, + 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, + 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, + 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, + 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, + 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, + 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, + 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x8fc5fe, 0xa8acd7, 0xababd3, 0x9db7e3, 0x9cbbe8, 0x9acbfd, + 0xa8c7f0, 0xa8caf5, 0xa0c7f6, 0x9fc3ed, 0x8fb9f0, 0x98addf, + 0xa0b4de, 0xa1c6f0, 0x89c2fd, 0xa4a8d1, 0xba91af, 0xcd6579, + 0xc76c82, 0xa6a6d1, 0xb696b7, 0xc38ba7, 0xbf88a4, 0xb198b9, + 0xb687a9, 0xc46b86, 0xbb7c9b, 0xaaabd0, 0x83b1f1, 0xb781a1, + 0xbc7f9b, 0xba7996, 0xbc718d, 0xa58eb8, 0x8eb6ed, 0xd06478, + 0xbe7c97, 0x89b8ed, 0xc46e88, 0xbd7090, 0xa88db7, 0x8dbcf4, + 0x83a1e2, 0xb97395, 0xbf7190, 0xc56b84, 0xa97da7, 0x7bacf1, + 0x8ba1dc, 0xcf586c, 0xad85ab, 0x81b1e9, 0xbd6682, 0xa17aa6, + 0x998ebe, 0x7fb3f4, 0x948dc3, 0xb16f97, 0xb57195, 0x86aceb, + 0x75b5ff, 0x73a4ef, 0xb6688d, 0x997fb4, 0xae6b92, 0x9a88b5, + 0xc25a75, 0x9978a8, 0x8998cf, 0x74b3f9, 0x8396d3, 0x8b8fcb, + 0x8a90cd, 0x74b1fb, 0x74b3ff, 0x819ee3, 0x8f86c2, 0x66a8fa, + 0x7c88cd, 0x857fba, 0x9d78a0, 0x966c99, 0x7f8dc9, 0x72b6fd ) ); + +/* Colour type 4, bit depth 16 */ +PIX ( ctype_4_16, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x10, 0x04, 0x00, 0x00, 0x00, 0x09, 0x82, 0xbb, 0x74, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x01, 0x86, + 0xa0, 0x31, 0xe8, 0x96, 0x5f, 0x00, 0x00, 0x00, 0x02, 0x62, 0x4b, + 0x47, 0x44, 0xff, 0xff, 0x14, 0xab, 0x31, 0xcd, 0x00, 0x00, 0x00, + 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, + 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x93, + 0x49, 0x44, 0x41, 0x54, 0x18, 0xd3, 0x4d, 0xcf, 0xc1, 0x4e, 0xc2, + 0x60, 0x10, 0x04, 0xe0, 0x8f, 0xf2, 0x0b, 0x24, 0x72, 0x13, 0x4f, + 0x9e, 0x48, 0x78, 0xd0, 0x5e, 0x78, 0x51, 0x0f, 0x1e, 0x4a, 0xaa, + 0x80, 0x96, 0x22, 0x68, 0xeb, 0xc1, 0x39, 0x74, 0x93, 0xc9, 0x4e, + 0x76, 0x76, 0x33, 0xb3, 0xb3, 0x7d, 0x3d, 0xd6, 0x8d, 0xff, 0x5a, + 0xa1, 0x60, 0x83, 0x21, 0xfc, 0x16, 0x9c, 0xd1, 0x65, 0xe7, 0x19, + 0xe5, 0x1e, 0xe1, 0x13, 0x07, 0xcc, 0xb0, 0xc5, 0x05, 0x3f, 0xc1, + 0x0a, 0x5f, 0xc1, 0x22, 0xfb, 0x55, 0x8b, 0xb7, 0x1c, 0x16, 0x8c, + 0x68, 0xe2, 0xda, 0xa2, 0x0f, 0xef, 0x92, 0x6a, 0x81, 0x35, 0xca, + 0x11, 0xd7, 0x38, 0x8d, 0xe9, 0x4f, 0x71, 0xbf, 0x61, 0x99, 0xe3, + 0x6f, 0x54, 0xf8, 0x8d, 0x73, 0x39, 0xe1, 0x9e, 0xe1, 0x2e, 0xb1, + 0xde, 0xf1, 0x8a, 0x07, 0x7c, 0x4c, 0x22, 0xcf, 0x93, 0x6a, 0x40, + 0x55, 0x62, 0xfd, 0x18, 0x61, 0x98, 0xfc, 0xf5, 0x92, 0xde, 0x45, + 0xeb, 0x27, 0xfc, 0x0f, 0x08, 0x4c, 0x30, 0x03, 0xe4, 0x95, 0x23, + 0xfb, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, + 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, + 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, + 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, + 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, + 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, + 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, + 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, + 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, + 0x82 ), + 14, 6, + DATA ( 0x858585, 0x6f6f6f, 0x6f6f6f, 0x777777, 0x7b7b7b, 0x8f8f8f, + 0x8d8d8d, 0x919191, 0x8b8b8b, 0x858585, 0x777777, 0x6c6c6c, + 0x747474, 0x898989, 0x808080, 0x696969, 0x5c5c5c, 0x474747, + 0x484848, 0x696969, 0x5f5f5f, 0x5b5b5b, 0x575757, 0x5f5f5f, + 0x535353, 0x474747, 0x4d4d4d, 0x6e6e6e, 0x6d6d6d, 0x4f4f4f, + 0x4f4f4f, 0x4b4b4b, 0x474747, 0x535353, 0x737373, 0x484848, + 0x4e4e4e, 0x737373, 0x484848, 0x474747, 0x535353, 0x7a7a7a, + 0x5d5d5d, 0x474747, 0x484848, 0x474747, 0x484848, 0x666666, + 0x5e5e5e, 0x424242, 0x4f4f4f, 0x6a6a6a, 0x414141, 0x434343, + 0x505050, 0x6e6e6e, 0x4e4e4e, 0x424242, 0x444444, 0x686868, + 0x707070, 0x5e5e5e, 0x404040, 0x454545, 0x3e3e3e, 0x4b4b4b, + 0x3d3d3d, 0x404040, 0x545454, 0x6c6c6c, 0x525252, 0x4e4e4e, + 0x4f4f4f, 0x6b6b6b, 0x6e6e6e, 0x5a5a5a, 0x484848, 0x606060, + 0x464646, 0x404040, 0x404040, 0x373737, 0x494949, 0x6f6f6f ) ); + +/* Colour type 4, bit depth 8 */ +PIX ( ctype_4_8, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x04, 0x00, 0x00, 0x00, 0x59, 0x12, 0x67, 0x37, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x01, 0x86, + 0xa0, 0x31, 0xe8, 0x96, 0x5f, 0x00, 0x00, 0x00, 0x02, 0x62, 0x4b, + 0x47, 0x44, 0x00, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x00, 0x00, 0x00, + 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, + 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x72, + 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x05, 0xc1, 0xbb, 0x0e, 0x82, + 0x30, 0x00, 0x00, 0xc0, 0xa3, 0x54, 0x6d, 0x0c, 0x9b, 0xb8, 0xb9, + 0x18, 0xbf, 0xd5, 0x1f, 0x75, 0x70, 0xf0, 0x15, 0x1f, 0x20, 0xa6, + 0x56, 0xf0, 0xae, 0xda, 0x4f, 0x27, 0x24, 0x51, 0x6b, 0x14, 0x65, + 0xd9, 0x53, 0x2f, 0x59, 0x8b, 0x5f, 0xd9, 0xcb, 0x05, 0x5b, 0x6f, + 0x45, 0x91, 0x74, 0x3a, 0x0b, 0x59, 0xb8, 0x3a, 0xea, 0xd4, 0x26, + 0x27, 0xad, 0x9b, 0x41, 0xeb, 0x8d, 0xb9, 0x46, 0xbc, 0xfb, 0x08, + 0x46, 0x95, 0x95, 0xb3, 0x6c, 0x6e, 0xf0, 0x11, 0x14, 0x9d, 0xf8, + 0xf0, 0x55, 0xdb, 0x49, 0x6e, 0x0e, 0x66, 0xee, 0x8a, 0x9f, 0x49, + 0x34, 0x0a, 0x51, 0x63, 0xa9, 0x36, 0x2a, 0x92, 0x8d, 0x85, 0x5e, + 0x30, 0xe8, 0xd5, 0xfe, 0x3c, 0xbb, 0x2f, 0xff, 0xe5, 0xd1, 0x65, + 0x25, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, + 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, + 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, + 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, + 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, + 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, + 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, + 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, + 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, + 0x82 ), + 14, 6, + DATA ( 0x858585, 0x6f6f6f, 0x6f6f6f, 0x777777, 0x7b7b7b, 0x8f8f8f, + 0x8d8d8d, 0x919191, 0x8b8b8b, 0x858585, 0x777777, 0x6c6c6c, + 0x747474, 0x898989, 0x808080, 0x696969, 0x5c5c5c, 0x484848, + 0x484848, 0x696969, 0x5f5f5f, 0x5b5b5b, 0x575757, 0x5f5f5f, + 0x535353, 0x474747, 0x4e4e4e, 0x6e6e6e, 0x6d6d6d, 0x4f4f4f, + 0x505050, 0x4b4b4b, 0x474747, 0x535353, 0x737373, 0x494949, + 0x4e4e4e, 0x737373, 0x494949, 0x474747, 0x545454, 0x7a7a7a, + 0x5d5d5d, 0x474747, 0x494949, 0x474747, 0x484848, 0x666666, + 0x5e5e5e, 0x434343, 0x4f4f4f, 0x6a6a6a, 0x414141, 0x434343, + 0x505050, 0x6e6e6e, 0x4e4e4e, 0x424242, 0x454545, 0x686868, + 0x707070, 0x5e5e5e, 0x404040, 0x454545, 0x3f3f3f, 0x4b4b4b, + 0x3e3e3e, 0x404040, 0x545454, 0x6c6c6c, 0x525252, 0x4e4e4e, + 0x4f4f4f, 0x6b6b6b, 0x6e6e6e, 0x5a5a5a, 0x484848, 0x616161, + 0x464646, 0x404040, 0x404040, 0x373737, 0x494949, 0x6f6f6f ) ); + +/* Colour type 6, bit depth 16 */ +PIX ( ctype_6_16, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x10, 0x06, 0x00, 0x00, 0x00, 0xa3, 0x8b, 0x73, 0xff, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x06, + 0x62, 0x4b, 0x47, 0x44, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x09, + 0x58, 0xf7, 0xdc, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, + 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, + 0x9c, 0x18, 0x00, 0x00, 0x01, 0x5f, 0x49, 0x44, 0x41, 0x54, 0x28, + 0xcf, 0x4d, 0xd0, 0x31, 0x6e, 0xd3, 0x00, 0x00, 0x85, 0xe1, 0x2f, + 0x76, 0xac, 0x90, 0xb4, 0x8d, 0x92, 0xd0, 0x14, 0x15, 0x41, 0x84, + 0x2a, 0x24, 0x86, 0x0e, 0x2c, 0x14, 0x01, 0x1b, 0x1b, 0x1b, 0xc7, + 0xe0, 0x1a, 0xb9, 0x01, 0x67, 0xe1, 0x10, 0xa8, 0x52, 0xc5, 0x00, + 0x02, 0x01, 0x19, 0x68, 0x41, 0xad, 0x1a, 0x10, 0x4d, 0xec, 0xb8, + 0x4e, 0x93, 0x58, 0x4e, 0xcc, 0xe2, 0x81, 0xf5, 0x0d, 0xef, 0xfd, + 0xef, 0xaf, 0xbd, 0x1d, 0xbe, 0x1f, 0x6e, 0x86, 0xe5, 0x70, 0xdf, + 0xd8, 0x08, 0xa1, 0x52, 0x81, 0xd4, 0xb6, 0x0e, 0x4a, 0x75, 0x11, + 0x36, 0x3a, 0xfa, 0x68, 0x2b, 0x5c, 0x83, 0x50, 0x84, 0xa5, 0xb5, + 0x1a, 0x4a, 0x85, 0x05, 0x12, 0x37, 0x42, 0x34, 0x65, 0x62, 0xdc, + 0xd2, 0x50, 0xa2, 0xa6, 0xa7, 0x87, 0x7a, 0x6e, 0xad, 0x44, 0xa1, + 0x90, 0xa3, 0xe7, 0x8f, 0x53, 0x1c, 0xf8, 0xe2, 0x04, 0xb9, 0x86, + 0x26, 0xce, 0xbc, 0xf0, 0x1a, 0x6d, 0x89, 0x4b, 0xec, 0x98, 0x4b, + 0x50, 0x58, 0x5b, 0x23, 0xad, 0x80, 0xee, 0x88, 0x25, 0x68, 0xbb, + 0xf0, 0x03, 0x0b, 0x5d, 0x7d, 0xc4, 0x1e, 0x3b, 0x42, 0x90, 0x8b, + 0x65, 0xb8, 0x6d, 0xe4, 0x23, 0x02, 0x53, 0x57, 0x98, 0xd8, 0x75, + 0x1f, 0x73, 0x91, 0x2d, 0x94, 0x7e, 0x1b, 0xe3, 0xbb, 0x07, 0x9e, + 0x62, 0xc7, 0xc8, 0x27, 0x94, 0x32, 0xd7, 0x55, 0xfe, 0x04, 0x6d, + 0x63, 0x67, 0x58, 0x89, 0xb4, 0x30, 0xd1, 0x75, 0x0f, 0xe7, 0xba, + 0x1e, 0x22, 0x20, 0x31, 0x43, 0x20, 0x95, 0x21, 0x94, 0x9a, 0x63, + 0x4b, 0x6a, 0x8a, 0x89, 0x6d, 0x77, 0xf1, 0xd5, 0xc0, 0x73, 0xac, + 0xfd, 0x15, 0x57, 0x43, 0x19, 0x62, 0x4d, 0xbb, 0x58, 0x5a, 0x29, + 0xb0, 0xb2, 0x94, 0xe3, 0x42, 0xcb, 0x1e, 0x66, 0x6a, 0x1a, 0x48, + 0x2d, 0x40, 0xbd, 0xeb, 0xca, 0x2f, 0x2c, 0x15, 0x02, 0x14, 0x02, + 0x11, 0x8e, 0xbd, 0xf4, 0xe6, 0xbf, 0xc2, 0x4d, 0xa5, 0xea, 0xd0, + 0xb1, 0x77, 0x38, 0xf1, 0xc8, 0x2b, 0xf4, 0x5d, 0x3a, 0xc5, 0xbe, + 0xd0, 0x07, 0x44, 0xd5, 0xe3, 0xa5, 0x9e, 0x00, 0x89, 0x96, 0x2e, + 0xe6, 0x88, 0x50, 0x8f, 0x35, 0x75, 0xb0, 0xa8, 0x94, 0x94, 0x6a, + 0x02, 0x4c, 0x45, 0x3a, 0x60, 0x03, 0xda, 0x72, 0x19, 0x46, 0x06, + 0x8e, 0xf0, 0xcd, 0x81, 0x67, 0xd8, 0xf3, 0xd3, 0x67, 0x34, 0x2d, + 0x4c, 0x10, 0x1a, 0x38, 0xc4, 0x5a, 0x66, 0x86, 0x1b, 0x73, 0x39, + 0x36, 0x42, 0x75, 0xfc, 0x03, 0x3f, 0x65, 0x8d, 0x8a, 0xc6, 0x64, + 0x55, 0xda, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, + 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, + 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, + 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, + 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, + 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, + 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, + 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, + 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, + 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, + 0x60, 0x82 ), + 14, 6, + DATA ( 0x8fc5fe, 0xa8acd7, 0xababd3, 0x9db7e3, 0x9cbbe8, 0x9acbfd, + 0xa8c7f0, 0xa8caf5, 0xa0c7f6, 0x9fc3ed, 0x8fb9f0, 0x98addf, + 0xa0b4de, 0xa1c6f0, 0x89c2fd, 0xa4a8d1, 0xba91af, 0xcd6579, + 0xc76c82, 0xa6a6d1, 0xb696b7, 0xc38ba7, 0xbf88a4, 0xb198b9, + 0xb687a9, 0xc46b86, 0xbb7c9b, 0xaaabd0, 0x83b1f1, 0xb781a1, + 0xbc7f9b, 0xba7996, 0xbc718d, 0xa58eb8, 0x8eb6ed, 0xd06478, + 0xbe7c97, 0x89b8ed, 0xc46e88, 0xbd7090, 0xa88db7, 0x8dbcf4, + 0x83a1e2, 0xb97395, 0xbf7190, 0xc56b84, 0xa97da7, 0x7bacf1, + 0x8ba1dc, 0xcf586c, 0xad85ab, 0x81b1e9, 0xbd6682, 0xa17aa6, + 0x998ebe, 0x7fb3f4, 0x948dc3, 0xb16f97, 0xb57195, 0x86aceb, + 0x75b5ff, 0x73a4ef, 0xb6688d, 0x997fb4, 0xae6b92, 0x9a88b5, + 0xc25a75, 0x9978a8, 0x8998cf, 0x74b3f9, 0x8396d3, 0x8b8fcb, + 0x8a90cd, 0x74b1fb, 0x74b3ff, 0x819ee3, 0x8f86c2, 0x66a8fa, + 0x7c88cd, 0x857fba, 0x9d78a0, 0x966c99, 0x7f8dc9, 0x72b6fd ) ); + +/* Colour type 6, bit depth 8 */ +PIX ( ctype_6_8, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x06, 0x00, 0x00, 0x00, 0xf3, 0x1b, 0xaf, 0xbc, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x06, + 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, + 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, + 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, + 0x9c, 0x18, 0x00, 0x00, 0x01, 0x23, 0x49, 0x44, 0x41, 0x54, 0x18, + 0xd3, 0x05, 0xc1, 0x4d, 0x4e, 0xc2, 0x40, 0x00, 0x80, 0xd1, 0xaf, + 0x7f, 0xc1, 0x22, 0x36, 0x2d, 0x02, 0x06, 0xa3, 0x84, 0x10, 0x13, + 0x17, 0x2e, 0xdc, 0x80, 0x51, 0x77, 0xee, 0xdc, 0x79, 0x0c, 0x8f, + 0xe3, 0x59, 0x3c, 0x84, 0x31, 0x21, 0x2e, 0x34, 0x1a, 0x95, 0x85, + 0xa8, 0x91, 0x88, 0x46, 0x60, 0x4a, 0x99, 0xd2, 0xd2, 0x4c, 0x3b, + 0xbe, 0x67, 0x5c, 0xdd, 0x14, 0xba, 0x39, 0x1e, 0x60, 0x69, 0x45, + 0x54, 0xf1, 0xd1, 0xb6, 0x43, 0xe1, 0xd7, 0xf1, 0xd4, 0x02, 0x2c, + 0x87, 0x34, 0x37, 0xd0, 0x2a, 0x21, 0x5c, 0x5a, 0xb8, 0x52, 0xb0, + 0x56, 0xd2, 0x18, 0xd5, 0x2a, 0x76, 0x96, 0x6b, 0x94, 0xca, 0xa8, + 0xfe, 0x0e, 0xe9, 0x3c, 0xf5, 0xc9, 0x4a, 0x2e, 0xef, 0xa7, 0x17, + 0x78, 0xe1, 0x37, 0x1b, 0x71, 0x88, 0xca, 0x73, 0x22, 0xbf, 0xce, + 0x96, 0x08, 0xf1, 0x46, 0x6f, 0x24, 0x41, 0x1d, 0x71, 0xd8, 0xc3, + 0xcc, 0x84, 0x64, 0x73, 0x70, 0x8f, 0x39, 0x9b, 0x30, 0xad, 0xed, + 0x12, 0x3b, 0xeb, 0xe8, 0x9f, 0x31, 0xaf, 0xed, 0x23, 0x36, 0x06, + 0x0f, 0x68, 0xb9, 0xe0, 0xb5, 0xdd, 0xc5, 0x1b, 0xbf, 0xb3, 0x72, + 0xca, 0x4c, 0x83, 0x1d, 0xbe, 0x82, 0x3d, 0x4c, 0xc2, 0x39, 0x66, + 0x24, 0xb1, 0xa2, 0x98, 0xf5, 0x68, 0xc6, 0xb4, 0xb2, 0xcd, 0x73, + 0xeb, 0x84, 0xfc, 0x4f, 0xa0, 0xa5, 0x44, 0xb8, 0x35, 0xd2, 0x95, + 0x62, 0x95, 0x66, 0x8c, 0xca, 0x0d, 0xe6, 0x46, 0x89, 0x28, 0x01, + 0x3b, 0x98, 0x7c, 0x92, 0x2a, 0x13, 0x65, 0x3a, 0xdc, 0x9e, 0x5d, + 0x22, 0xdc, 0x1a, 0x85, 0x08, 0x39, 0xb8, 0xbd, 0xa6, 0xbf, 0x7f, + 0x4e, 0xfd, 0x7b, 0x48, 0xd3, 0xba, 0xc3, 0x91, 0x0b, 0xd2, 0xaa, + 0x49, 0x58, 0x0e, 0x88, 0x71, 0xb0, 0x85, 0xeb, 0x93, 0xb4, 0xbb, + 0x68, 0xc3, 0x64, 0xe6, 0xf8, 0x50, 0x80, 0x97, 0x49, 0x06, 0xad, + 0x1e, 0x2f, 0x9d, 0x63, 0x1a, 0x1f, 0x8f, 0xb8, 0xc9, 0x14, 0xab, + 0x75, 0x40, 0x2e, 0xe7, 0x2c, 0xe3, 0x8c, 0xc2, 0xb2, 0xf9, 0x07, + 0xb2, 0x82, 0x8b, 0x8a, 0x51, 0x8a, 0xfe, 0x2f, 0x00, 0x00, 0x00, + 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, + 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, + 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, + 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, + 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, + 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, + 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, + 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x8fc5fe, 0xa8acd7, 0xababd3, 0x9db7e3, 0x9cbbe8, 0x9acbfd, + 0xa8c7f0, 0xa8caf5, 0xa0c7f6, 0x9fc3ed, 0x8fb9f0, 0x98addf, + 0xa0b4de, 0xa1c6f0, 0x89c2fd, 0xa4a8d1, 0xba91af, 0xcd6579, + 0xc76c82, 0xa6a6d1, 0xb696b7, 0xc38ba7, 0xbf88a4, 0xb198b9, + 0xb687a9, 0xc46b86, 0xbb7c9b, 0xaaabd0, 0x83b1f1, 0xb781a1, + 0xbc7f9b, 0xba7996, 0xbc718d, 0xa58eb8, 0x8eb6ed, 0xd06478, + 0xbe7c97, 0x89b8ed, 0xc46e88, 0xbd7090, 0xa88db7, 0x8dbcf4, + 0x83a1e2, 0xb97395, 0xbf7190, 0xc56b84, 0xa97da7, 0x7bacf1, + 0x8ba1dc, 0xcf586c, 0xad85ab, 0x81b1e9, 0xbd6682, 0xa17aa6, + 0x998ebe, 0x7fb3f4, 0x948dc3, 0xb16f97, 0xb57195, 0x86aceb, + 0x75b5ff, 0x73a4ef, 0xb6688d, 0x997fb4, 0xae6b92, 0x9a88b5, + 0xc25a75, 0x9978a8, 0x8998cf, 0x74b3f9, 0x8396d3, 0x8b8fcb, + 0x8a90cd, 0x74b1fb, 0x74b3ff, 0x819ee3, 0x8f86c2, 0x66a8fa, + 0x7c88cd, 0x857fba, 0x9d78a0, 0x966c99, 0x7f8dc9, 0x72b6fd ) ); + +/* Filter method 0 */ +PIX ( filter_0, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x03, 0x00, 0x00, 0x00, 0xc4, 0xc5, 0x5f, 0x8e, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0xff, + 0x50, 0x4c, 0x54, 0x45, 0x8f, 0xc5, 0xfe, 0xa8, 0xac, 0xd7, 0xab, + 0xab, 0xd3, 0x9d, 0xb7, 0xe3, 0x9c, 0xbb, 0xe8, 0x9a, 0xcb, 0xfd, + 0xa8, 0xc7, 0xf0, 0xa8, 0xca, 0xf5, 0xa0, 0xc7, 0xf6, 0x9f, 0xc3, + 0xed, 0x8f, 0xb9, 0xf0, 0x98, 0xad, 0xdf, 0xa0, 0xb4, 0xde, 0xa1, + 0xc6, 0xf0, 0x89, 0xc2, 0xfd, 0xa4, 0xa8, 0xd1, 0xba, 0x91, 0xaf, + 0xcd, 0x65, 0x79, 0xc7, 0x6c, 0x82, 0xa6, 0xa6, 0xd1, 0xb6, 0x96, + 0xb7, 0xc3, 0x8b, 0xa7, 0xbf, 0x88, 0xa4, 0xb1, 0x98, 0xb9, 0xb6, + 0x87, 0xa9, 0xc4, 0x6b, 0x86, 0xbb, 0x7c, 0x9b, 0xaa, 0xab, 0xd0, + 0x83, 0xb1, 0xf1, 0xb7, 0x81, 0xa1, 0xbc, 0x7f, 0x9b, 0xba, 0x79, + 0x96, 0xbc, 0x71, 0x8d, 0xa5, 0x8e, 0xb8, 0x8e, 0xb6, 0xed, 0xd0, + 0x64, 0x78, 0xbe, 0x7c, 0x97, 0x89, 0xb8, 0xed, 0xc4, 0x6e, 0x88, + 0xbd, 0x70, 0x90, 0xa8, 0x8d, 0xb7, 0x8d, 0xbc, 0xf4, 0x83, 0xa1, + 0xe2, 0xb9, 0x73, 0x95, 0xbf, 0x71, 0x90, 0xc5, 0x6b, 0x84, 0xa9, + 0x7d, 0xa7, 0x7b, 0xac, 0xf1, 0x8b, 0xa1, 0xdc, 0xcf, 0x58, 0x6c, + 0xad, 0x85, 0xab, 0x81, 0xb1, 0xe9, 0xbd, 0x66, 0x82, 0xa1, 0x7a, + 0xa6, 0x99, 0x8e, 0xbe, 0x7f, 0xb3, 0xf4, 0x94, 0x8d, 0xc3, 0xb1, + 0x6f, 0x97, 0xb5, 0x71, 0x95, 0x86, 0xac, 0xeb, 0x75, 0xb5, 0xff, + 0x73, 0xa4, 0xef, 0xb6, 0x68, 0x8d, 0x99, 0x7f, 0xb4, 0xae, 0x6b, + 0x92, 0x9a, 0x88, 0xb5, 0xc2, 0x5a, 0x75, 0x99, 0x78, 0xa8, 0x89, + 0x98, 0xcf, 0x74, 0xb3, 0xf9, 0x83, 0x96, 0xd3, 0x8b, 0x8f, 0xcb, + 0x8a, 0x90, 0xcd, 0x74, 0xb1, 0xfb, 0x74, 0xb3, 0xff, 0x81, 0x9e, + 0xe3, 0x8f, 0x86, 0xc2, 0x66, 0xa8, 0xfa, 0x7c, 0x88, 0xcd, 0x85, + 0x7f, 0xba, 0x9d, 0x78, 0xa0, 0x96, 0x6c, 0x99, 0x7f, 0x8d, 0xc9, + 0x72, 0xb6, 0xfd, 0xff, 0xff, 0xff, 0xdb, 0x2a, 0x9f, 0xad, 0x00, + 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x54, 0xe4, 0x03, 0x88, + 0xa5, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, + 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, + 0x00, 0x00, 0x00, 0x62, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, + 0x60, 0x60, 0x64, 0x62, 0x66, 0x61, 0x65, 0x63, 0xe7, 0xe0, 0xe4, + 0xe2, 0xe6, 0xe1, 0x65, 0xe0, 0xe3, 0x17, 0x10, 0x14, 0x12, 0x16, + 0x11, 0x15, 0x13, 0x97, 0x90, 0x94, 0x92, 0x66, 0x90, 0x91, 0x95, + 0x93, 0x57, 0x50, 0x54, 0x52, 0x56, 0x51, 0x55, 0x53, 0xd7, 0xd0, + 0x64, 0xd0, 0xd2, 0xd6, 0xd1, 0xd5, 0xd3, 0x37, 0x30, 0x34, 0x32, + 0x36, 0x31, 0x35, 0x33, 0x67, 0xb0, 0xb0, 0xb4, 0xb2, 0xb6, 0xb1, + 0xb5, 0xb3, 0x77, 0x70, 0x74, 0x72, 0x76, 0x71, 0x65, 0x70, 0x73, + 0xf7, 0xf0, 0xf4, 0xf2, 0xf6, 0xf1, 0xf5, 0xf3, 0x0f, 0x08, 0x0c, + 0x0a, 0x06, 0x00, 0x96, 0xe0, 0x0d, 0x9f, 0x37, 0x73, 0x30, 0xa4, + 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, + 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, + 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, + 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, + 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, + 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, + 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, + 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, + 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x8fc5fe, 0xa8acd7, 0xababd3, 0x9db7e3, 0x9cbbe8, 0x9acbfd, + 0xa8c7f0, 0xa8caf5, 0xa0c7f6, 0x9fc3ed, 0x8fb9f0, 0x98addf, + 0xa0b4de, 0xa1c6f0, 0x89c2fd, 0xa4a8d1, 0xba91af, 0xcd6579, + 0xc76c82, 0xa6a6d1, 0xb696b7, 0xc38ba7, 0xbf88a4, 0xb198b9, + 0xb687a9, 0xc46b86, 0xbb7c9b, 0xaaabd0, 0x83b1f1, 0xb781a1, + 0xbc7f9b, 0xba7996, 0xbc718d, 0xa58eb8, 0x8eb6ed, 0xd06478, + 0xbe7c97, 0x89b8ed, 0xc46e88, 0xbd7090, 0xa88db7, 0x8dbcf4, + 0x83a1e2, 0xb97395, 0xbf7190, 0xc56b84, 0xa97da7, 0x7bacf1, + 0x8ba1dc, 0xcf586c, 0xad85ab, 0x81b1e9, 0xbd6682, 0xa17aa6, + 0x998ebe, 0x7fb3f4, 0x948dc3, 0xb16f97, 0xb57195, 0x86aceb, + 0x75b5ff, 0x73a4ef, 0xb6688d, 0x997fb4, 0xae6b92, 0x9a88b5, + 0xc25a75, 0x9978a8, 0x8998cf, 0x74b3f9, 0x8396d3, 0x8b8fcb, + 0x8a90cd, 0x74b1fb, 0x74b3ff, 0x819ee3, 0x8f86c2, 0x66a8fa, + 0x7c88cd, 0x857fba, 0x9d78a0, 0x966c99, 0x7f8dc9, 0x72b6fd ) ); + +/* Filter method 1 */ +PIX ( filter_1, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x03, 0x00, 0x00, 0x00, 0xc4, 0xc5, 0x5f, 0x8e, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0xff, + 0x50, 0x4c, 0x54, 0x45, 0x8f, 0xc5, 0xfe, 0xa8, 0xac, 0xd7, 0xab, + 0xab, 0xd3, 0x9d, 0xb7, 0xe3, 0x9c, 0xbb, 0xe8, 0x9a, 0xcb, 0xfd, + 0xa8, 0xc7, 0xf0, 0xa8, 0xca, 0xf5, 0xa0, 0xc7, 0xf6, 0x9f, 0xc3, + 0xed, 0x8f, 0xb9, 0xf0, 0x98, 0xad, 0xdf, 0xa0, 0xb4, 0xde, 0xa1, + 0xc6, 0xf0, 0x89, 0xc2, 0xfd, 0xa4, 0xa8, 0xd1, 0xba, 0x91, 0xaf, + 0xcd, 0x65, 0x79, 0xc7, 0x6c, 0x82, 0xa6, 0xa6, 0xd1, 0xb6, 0x96, + 0xb7, 0xc3, 0x8b, 0xa7, 0xbf, 0x88, 0xa4, 0xb1, 0x98, 0xb9, 0xb6, + 0x87, 0xa9, 0xc4, 0x6b, 0x86, 0xbb, 0x7c, 0x9b, 0xaa, 0xab, 0xd0, + 0x83, 0xb1, 0xf1, 0xb7, 0x81, 0xa1, 0xbc, 0x7f, 0x9b, 0xba, 0x79, + 0x96, 0xbc, 0x71, 0x8d, 0xa5, 0x8e, 0xb8, 0x8e, 0xb6, 0xed, 0xd0, + 0x64, 0x78, 0xbe, 0x7c, 0x97, 0x89, 0xb8, 0xed, 0xc4, 0x6e, 0x88, + 0xbd, 0x70, 0x90, 0xa8, 0x8d, 0xb7, 0x8d, 0xbc, 0xf4, 0x83, 0xa1, + 0xe2, 0xb9, 0x73, 0x95, 0xbf, 0x71, 0x90, 0xc5, 0x6b, 0x84, 0xa9, + 0x7d, 0xa7, 0x7b, 0xac, 0xf1, 0x8b, 0xa1, 0xdc, 0xcf, 0x58, 0x6c, + 0xad, 0x85, 0xab, 0x81, 0xb1, 0xe9, 0xbd, 0x66, 0x82, 0xa1, 0x7a, + 0xa6, 0x99, 0x8e, 0xbe, 0x7f, 0xb3, 0xf4, 0x94, 0x8d, 0xc3, 0xb1, + 0x6f, 0x97, 0xb5, 0x71, 0x95, 0x86, 0xac, 0xeb, 0x75, 0xb5, 0xff, + 0x73, 0xa4, 0xef, 0xb6, 0x68, 0x8d, 0x99, 0x7f, 0xb4, 0xae, 0x6b, + 0x92, 0x9a, 0x88, 0xb5, 0xc2, 0x5a, 0x75, 0x99, 0x78, 0xa8, 0x89, + 0x98, 0xcf, 0x74, 0xb3, 0xf9, 0x83, 0x96, 0xd3, 0x8b, 0x8f, 0xcb, + 0x8a, 0x90, 0xcd, 0x74, 0xb1, 0xfb, 0x74, 0xb3, 0xff, 0x81, 0x9e, + 0xe3, 0x8f, 0x86, 0xc2, 0x66, 0xa8, 0xfa, 0x7c, 0x88, 0xcd, 0x85, + 0x7f, 0xba, 0x9d, 0x78, 0xa0, 0x96, 0x6c, 0x99, 0x7f, 0x8d, 0xc9, + 0x72, 0xb6, 0xfd, 0xff, 0xff, 0xff, 0xdb, 0x2a, 0x9f, 0xad, 0x00, + 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x54, 0xe4, 0x03, 0x88, + 0xa5, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, + 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, + 0x00, 0x00, 0x00, 0x1b, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, + 0x64, 0x60, 0x44, 0x01, 0x7c, 0xa8, 0x5c, 0x19, 0x54, 0xae, 0x16, + 0x2a, 0xd7, 0x02, 0x95, 0xeb, 0x86, 0xc2, 0x03, 0x00, 0x2b, 0x08, + 0x01, 0x27, 0x21, 0x1c, 0x62, 0x0d, 0x00, 0x00, 0x00, 0x25, 0x74, + 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, + 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, + 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, + 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, + 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, + 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, + 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, + 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, + 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x8fc5fe, 0xa8acd7, 0xababd3, 0x9db7e3, 0x9cbbe8, 0x9acbfd, + 0xa8c7f0, 0xa8caf5, 0xa0c7f6, 0x9fc3ed, 0x8fb9f0, 0x98addf, + 0xa0b4de, 0xa1c6f0, 0x89c2fd, 0xa4a8d1, 0xba91af, 0xcd6579, + 0xc76c82, 0xa6a6d1, 0xb696b7, 0xc38ba7, 0xbf88a4, 0xb198b9, + 0xb687a9, 0xc46b86, 0xbb7c9b, 0xaaabd0, 0x83b1f1, 0xb781a1, + 0xbc7f9b, 0xba7996, 0xbc718d, 0xa58eb8, 0x8eb6ed, 0xd06478, + 0xbe7c97, 0x89b8ed, 0xc46e88, 0xbd7090, 0xa88db7, 0x8dbcf4, + 0x83a1e2, 0xb97395, 0xbf7190, 0xc56b84, 0xa97da7, 0x7bacf1, + 0x8ba1dc, 0xcf586c, 0xad85ab, 0x81b1e9, 0xbd6682, 0xa17aa6, + 0x998ebe, 0x7fb3f4, 0x948dc3, 0xb16f97, 0xb57195, 0x86aceb, + 0x75b5ff, 0x73a4ef, 0xb6688d, 0x997fb4, 0xae6b92, 0x9a88b5, + 0xc25a75, 0x9978a8, 0x8998cf, 0x74b3f9, 0x8396d3, 0x8b8fcb, + 0x8a90cd, 0x74b1fb, 0x74b3ff, 0x819ee3, 0x8f86c2, 0x66a8fa, + 0x7c88cd, 0x857fba, 0x9d78a0, 0x966c99, 0x7f8dc9, 0x72b6fd ) ); + +/* Filter method 2 */ +PIX ( filter_2, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x03, 0x00, 0x00, 0x00, 0xc4, 0xc5, 0x5f, 0x8e, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0xff, + 0x50, 0x4c, 0x54, 0x45, 0x8f, 0xc5, 0xfe, 0xa8, 0xac, 0xd7, 0xab, + 0xab, 0xd3, 0x9d, 0xb7, 0xe3, 0x9c, 0xbb, 0xe8, 0x9a, 0xcb, 0xfd, + 0xa8, 0xc7, 0xf0, 0xa8, 0xca, 0xf5, 0xa0, 0xc7, 0xf6, 0x9f, 0xc3, + 0xed, 0x8f, 0xb9, 0xf0, 0x98, 0xad, 0xdf, 0xa0, 0xb4, 0xde, 0xa1, + 0xc6, 0xf0, 0x89, 0xc2, 0xfd, 0xa4, 0xa8, 0xd1, 0xba, 0x91, 0xaf, + 0xcd, 0x65, 0x79, 0xc7, 0x6c, 0x82, 0xa6, 0xa6, 0xd1, 0xb6, 0x96, + 0xb7, 0xc3, 0x8b, 0xa7, 0xbf, 0x88, 0xa4, 0xb1, 0x98, 0xb9, 0xb6, + 0x87, 0xa9, 0xc4, 0x6b, 0x86, 0xbb, 0x7c, 0x9b, 0xaa, 0xab, 0xd0, + 0x83, 0xb1, 0xf1, 0xb7, 0x81, 0xa1, 0xbc, 0x7f, 0x9b, 0xba, 0x79, + 0x96, 0xbc, 0x71, 0x8d, 0xa5, 0x8e, 0xb8, 0x8e, 0xb6, 0xed, 0xd0, + 0x64, 0x78, 0xbe, 0x7c, 0x97, 0x89, 0xb8, 0xed, 0xc4, 0x6e, 0x88, + 0xbd, 0x70, 0x90, 0xa8, 0x8d, 0xb7, 0x8d, 0xbc, 0xf4, 0x83, 0xa1, + 0xe2, 0xb9, 0x73, 0x95, 0xbf, 0x71, 0x90, 0xc5, 0x6b, 0x84, 0xa9, + 0x7d, 0xa7, 0x7b, 0xac, 0xf1, 0x8b, 0xa1, 0xdc, 0xcf, 0x58, 0x6c, + 0xad, 0x85, 0xab, 0x81, 0xb1, 0xe9, 0xbd, 0x66, 0x82, 0xa1, 0x7a, + 0xa6, 0x99, 0x8e, 0xbe, 0x7f, 0xb3, 0xf4, 0x94, 0x8d, 0xc3, 0xb1, + 0x6f, 0x97, 0xb5, 0x71, 0x95, 0x86, 0xac, 0xeb, 0x75, 0xb5, 0xff, + 0x73, 0xa4, 0xef, 0xb6, 0x68, 0x8d, 0x99, 0x7f, 0xb4, 0xae, 0x6b, + 0x92, 0x9a, 0x88, 0xb5, 0xc2, 0x5a, 0x75, 0x99, 0x78, 0xa8, 0x89, + 0x98, 0xcf, 0x74, 0xb3, 0xf9, 0x83, 0x96, 0xd3, 0x8b, 0x8f, 0xcb, + 0x8a, 0x90, 0xcd, 0x74, 0xb1, 0xfb, 0x74, 0xb3, 0xff, 0x81, 0x9e, + 0xe3, 0x8f, 0x86, 0xc2, 0x66, 0xa8, 0xfa, 0x7c, 0x88, 0xcd, 0x85, + 0x7f, 0xba, 0x9d, 0x78, 0xa0, 0x96, 0x6c, 0x99, 0x7f, 0x8d, 0xc9, + 0x72, 0xb6, 0xfd, 0xff, 0xff, 0xff, 0xdb, 0x2a, 0x9f, 0xad, 0x00, + 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x54, 0xe4, 0x03, 0x88, + 0xa5, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, + 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, + 0x00, 0x00, 0x00, 0x1c, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, + 0x62, 0x60, 0x64, 0x62, 0x66, 0x61, 0x65, 0x63, 0xe7, 0xe0, 0xe4, + 0xe2, 0xe6, 0xe1, 0x65, 0xe2, 0x43, 0x01, 0x94, 0x70, 0x01, 0xae, + 0xce, 0x04, 0x3c, 0x32, 0x9e, 0x82, 0x4f, 0x00, 0x00, 0x00, 0x25, + 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, + 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, + 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, + 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, + 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, + 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, + 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, + 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x8fc5fe, 0xa8acd7, 0xababd3, 0x9db7e3, 0x9cbbe8, 0x9acbfd, + 0xa8c7f0, 0xa8caf5, 0xa0c7f6, 0x9fc3ed, 0x8fb9f0, 0x98addf, + 0xa0b4de, 0xa1c6f0, 0x89c2fd, 0xa4a8d1, 0xba91af, 0xcd6579, + 0xc76c82, 0xa6a6d1, 0xb696b7, 0xc38ba7, 0xbf88a4, 0xb198b9, + 0xb687a9, 0xc46b86, 0xbb7c9b, 0xaaabd0, 0x83b1f1, 0xb781a1, + 0xbc7f9b, 0xba7996, 0xbc718d, 0xa58eb8, 0x8eb6ed, 0xd06478, + 0xbe7c97, 0x89b8ed, 0xc46e88, 0xbd7090, 0xa88db7, 0x8dbcf4, + 0x83a1e2, 0xb97395, 0xbf7190, 0xc56b84, 0xa97da7, 0x7bacf1, + 0x8ba1dc, 0xcf586c, 0xad85ab, 0x81b1e9, 0xbd6682, 0xa17aa6, + 0x998ebe, 0x7fb3f4, 0x948dc3, 0xb16f97, 0xb57195, 0x86aceb, + 0x75b5ff, 0x73a4ef, 0xb6688d, 0x997fb4, 0xae6b92, 0x9a88b5, + 0xc25a75, 0x9978a8, 0x8998cf, 0x74b3f9, 0x8396d3, 0x8b8fcb, + 0x8a90cd, 0x74b1fb, 0x74b3ff, 0x819ee3, 0x8f86c2, 0x66a8fa, + 0x7c88cd, 0x857fba, 0x9d78a0, 0x966c99, 0x7f8dc9, 0x72b6fd ) ); + +/* Filter method 3 */ +PIX ( filter_3, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x03, 0x00, 0x00, 0x00, 0xc4, 0xc5, 0x5f, 0x8e, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0xff, + 0x50, 0x4c, 0x54, 0x45, 0x8f, 0xc5, 0xfe, 0xa8, 0xac, 0xd7, 0xab, + 0xab, 0xd3, 0x9d, 0xb7, 0xe3, 0x9c, 0xbb, 0xe8, 0x9a, 0xcb, 0xfd, + 0xa8, 0xc7, 0xf0, 0xa8, 0xca, 0xf5, 0xa0, 0xc7, 0xf6, 0x9f, 0xc3, + 0xed, 0x8f, 0xb9, 0xf0, 0x98, 0xad, 0xdf, 0xa0, 0xb4, 0xde, 0xa1, + 0xc6, 0xf0, 0x89, 0xc2, 0xfd, 0xa4, 0xa8, 0xd1, 0xba, 0x91, 0xaf, + 0xcd, 0x65, 0x79, 0xc7, 0x6c, 0x82, 0xa6, 0xa6, 0xd1, 0xb6, 0x96, + 0xb7, 0xc3, 0x8b, 0xa7, 0xbf, 0x88, 0xa4, 0xb1, 0x98, 0xb9, 0xb6, + 0x87, 0xa9, 0xc4, 0x6b, 0x86, 0xbb, 0x7c, 0x9b, 0xaa, 0xab, 0xd0, + 0x83, 0xb1, 0xf1, 0xb7, 0x81, 0xa1, 0xbc, 0x7f, 0x9b, 0xba, 0x79, + 0x96, 0xbc, 0x71, 0x8d, 0xa5, 0x8e, 0xb8, 0x8e, 0xb6, 0xed, 0xd0, + 0x64, 0x78, 0xbe, 0x7c, 0x97, 0x89, 0xb8, 0xed, 0xc4, 0x6e, 0x88, + 0xbd, 0x70, 0x90, 0xa8, 0x8d, 0xb7, 0x8d, 0xbc, 0xf4, 0x83, 0xa1, + 0xe2, 0xb9, 0x73, 0x95, 0xbf, 0x71, 0x90, 0xc5, 0x6b, 0x84, 0xa9, + 0x7d, 0xa7, 0x7b, 0xac, 0xf1, 0x8b, 0xa1, 0xdc, 0xcf, 0x58, 0x6c, + 0xad, 0x85, 0xab, 0x81, 0xb1, 0xe9, 0xbd, 0x66, 0x82, 0xa1, 0x7a, + 0xa6, 0x99, 0x8e, 0xbe, 0x7f, 0xb3, 0xf4, 0x94, 0x8d, 0xc3, 0xb1, + 0x6f, 0x97, 0xb5, 0x71, 0x95, 0x86, 0xac, 0xeb, 0x75, 0xb5, 0xff, + 0x73, 0xa4, 0xef, 0xb6, 0x68, 0x8d, 0x99, 0x7f, 0xb4, 0xae, 0x6b, + 0x92, 0x9a, 0x88, 0xb5, 0xc2, 0x5a, 0x75, 0x99, 0x78, 0xa8, 0x89, + 0x98, 0xcf, 0x74, 0xb3, 0xf9, 0x83, 0x96, 0xd3, 0x8b, 0x8f, 0xcb, + 0x8a, 0x90, 0xcd, 0x74, 0xb1, 0xfb, 0x74, 0xb3, 0xff, 0x81, 0x9e, + 0xe3, 0x8f, 0x86, 0xc2, 0x66, 0xa8, 0xfa, 0x7c, 0x88, 0xcd, 0x85, + 0x7f, 0xba, 0x9d, 0x78, 0xa0, 0x96, 0x6c, 0x99, 0x7f, 0x8d, 0xc9, + 0x72, 0xb6, 0xfd, 0xff, 0xff, 0xff, 0xdb, 0x2a, 0x9f, 0xad, 0x00, + 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x54, 0xe4, 0x03, 0x88, + 0xa5, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, + 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, + 0x00, 0x00, 0x00, 0x28, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, + 0x66, 0x60, 0x64, 0x62, 0x62, 0x66, 0x66, 0x61, 0x61, 0x65, 0x65, + 0x63, 0x63, 0x67, 0x67, 0xe6, 0xe3, 0x40, 0x06, 0xcc, 0xa2, 0xa8, + 0x5c, 0x19, 0x54, 0xae, 0x32, 0x2a, 0x57, 0x0b, 0x85, 0x0b, 0x00, + 0x74, 0x6c, 0x02, 0xde, 0x3a, 0xf5, 0xbf, 0x99, 0x00, 0x00, 0x00, + 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, + 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, + 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, + 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, + 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, + 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, + 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, + 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x8fc5fe, 0xa8acd7, 0xababd3, 0x9db7e3, 0x9cbbe8, 0x9acbfd, + 0xa8c7f0, 0xa8caf5, 0xa0c7f6, 0x9fc3ed, 0x8fb9f0, 0x98addf, + 0xa0b4de, 0xa1c6f0, 0x89c2fd, 0xa4a8d1, 0xba91af, 0xcd6579, + 0xc76c82, 0xa6a6d1, 0xb696b7, 0xc38ba7, 0xbf88a4, 0xb198b9, + 0xb687a9, 0xc46b86, 0xbb7c9b, 0xaaabd0, 0x83b1f1, 0xb781a1, + 0xbc7f9b, 0xba7996, 0xbc718d, 0xa58eb8, 0x8eb6ed, 0xd06478, + 0xbe7c97, 0x89b8ed, 0xc46e88, 0xbd7090, 0xa88db7, 0x8dbcf4, + 0x83a1e2, 0xb97395, 0xbf7190, 0xc56b84, 0xa97da7, 0x7bacf1, + 0x8ba1dc, 0xcf586c, 0xad85ab, 0x81b1e9, 0xbd6682, 0xa17aa6, + 0x998ebe, 0x7fb3f4, 0x948dc3, 0xb16f97, 0xb57195, 0x86aceb, + 0x75b5ff, 0x73a4ef, 0xb6688d, 0x997fb4, 0xae6b92, 0x9a88b5, + 0xc25a75, 0x9978a8, 0x8998cf, 0x74b3f9, 0x8396d3, 0x8b8fcb, + 0x8a90cd, 0x74b1fb, 0x74b3ff, 0x819ee3, 0x8f86c2, 0x66a8fa, + 0x7c88cd, 0x857fba, 0x9d78a0, 0x966c99, 0x7f8dc9, 0x72b6fd ) ); + +/* Filter method 4 */ +PIX ( filter_4, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x03, 0x00, 0x00, 0x00, 0xc4, 0xc5, 0x5f, 0x8e, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0xff, + 0x50, 0x4c, 0x54, 0x45, 0x8f, 0xc5, 0xfe, 0xa8, 0xac, 0xd7, 0xab, + 0xab, 0xd3, 0x9d, 0xb7, 0xe3, 0x9c, 0xbb, 0xe8, 0x9a, 0xcb, 0xfd, + 0xa8, 0xc7, 0xf0, 0xa8, 0xca, 0xf5, 0xa0, 0xc7, 0xf6, 0x9f, 0xc3, + 0xed, 0x8f, 0xb9, 0xf0, 0x98, 0xad, 0xdf, 0xa0, 0xb4, 0xde, 0xa1, + 0xc6, 0xf0, 0x89, 0xc2, 0xfd, 0xa4, 0xa8, 0xd1, 0xba, 0x91, 0xaf, + 0xcd, 0x65, 0x79, 0xc7, 0x6c, 0x82, 0xa6, 0xa6, 0xd1, 0xb6, 0x96, + 0xb7, 0xc3, 0x8b, 0xa7, 0xbf, 0x88, 0xa4, 0xb1, 0x98, 0xb9, 0xb6, + 0x87, 0xa9, 0xc4, 0x6b, 0x86, 0xbb, 0x7c, 0x9b, 0xaa, 0xab, 0xd0, + 0x83, 0xb1, 0xf1, 0xb7, 0x81, 0xa1, 0xbc, 0x7f, 0x9b, 0xba, 0x79, + 0x96, 0xbc, 0x71, 0x8d, 0xa5, 0x8e, 0xb8, 0x8e, 0xb6, 0xed, 0xd0, + 0x64, 0x78, 0xbe, 0x7c, 0x97, 0x89, 0xb8, 0xed, 0xc4, 0x6e, 0x88, + 0xbd, 0x70, 0x90, 0xa8, 0x8d, 0xb7, 0x8d, 0xbc, 0xf4, 0x83, 0xa1, + 0xe2, 0xb9, 0x73, 0x95, 0xbf, 0x71, 0x90, 0xc5, 0x6b, 0x84, 0xa9, + 0x7d, 0xa7, 0x7b, 0xac, 0xf1, 0x8b, 0xa1, 0xdc, 0xcf, 0x58, 0x6c, + 0xad, 0x85, 0xab, 0x81, 0xb1, 0xe9, 0xbd, 0x66, 0x82, 0xa1, 0x7a, + 0xa6, 0x99, 0x8e, 0xbe, 0x7f, 0xb3, 0xf4, 0x94, 0x8d, 0xc3, 0xb1, + 0x6f, 0x97, 0xb5, 0x71, 0x95, 0x86, 0xac, 0xeb, 0x75, 0xb5, 0xff, + 0x73, 0xa4, 0xef, 0xb6, 0x68, 0x8d, 0x99, 0x7f, 0xb4, 0xae, 0x6b, + 0x92, 0x9a, 0x88, 0xb5, 0xc2, 0x5a, 0x75, 0x99, 0x78, 0xa8, 0x89, + 0x98, 0xcf, 0x74, 0xb3, 0xf9, 0x83, 0x96, 0xd3, 0x8b, 0x8f, 0xcb, + 0x8a, 0x90, 0xcd, 0x74, 0xb1, 0xfb, 0x74, 0xb3, 0xff, 0x81, 0x9e, + 0xe3, 0x8f, 0x86, 0xc2, 0x66, 0xa8, 0xfa, 0x7c, 0x88, 0xcd, 0x85, + 0x7f, 0xba, 0x9d, 0x78, 0xa0, 0x96, 0x6c, 0x99, 0x7f, 0x8d, 0xc9, + 0x72, 0xb6, 0xfd, 0xff, 0xff, 0xff, 0xdb, 0x2a, 0x9f, 0xad, 0x00, + 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x54, 0xe4, 0x03, 0x88, + 0xa5, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, + 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, + 0x00, 0x00, 0x00, 0x11, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, + 0x61, 0x60, 0x44, 0x06, 0x2c, 0x7c, 0x54, 0xe3, 0x02, 0x00, 0x1e, + 0xdd, 0x00, 0xad, 0x19, 0xa1, 0xfb, 0x47, 0x00, 0x00, 0x00, 0x25, + 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, + 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, + 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, + 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, + 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, + 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, + 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, + 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x8fc5fe, 0xa8acd7, 0xababd3, 0x9db7e3, 0x9cbbe8, 0x9acbfd, + 0xa8c7f0, 0xa8caf5, 0xa0c7f6, 0x9fc3ed, 0x8fb9f0, 0x98addf, + 0xa0b4de, 0xa1c6f0, 0x89c2fd, 0xa4a8d1, 0xba91af, 0xcd6579, + 0xc76c82, 0xa6a6d1, 0xb696b7, 0xc38ba7, 0xbf88a4, 0xb198b9, + 0xb687a9, 0xc46b86, 0xbb7c9b, 0xaaabd0, 0x83b1f1, 0xb781a1, + 0xbc7f9b, 0xba7996, 0xbc718d, 0xa58eb8, 0x8eb6ed, 0xd06478, + 0xbe7c97, 0x89b8ed, 0xc46e88, 0xbd7090, 0xa88db7, 0x8dbcf4, + 0x83a1e2, 0xb97395, 0xbf7190, 0xc56b84, 0xa97da7, 0x7bacf1, + 0x8ba1dc, 0xcf586c, 0xad85ab, 0x81b1e9, 0xbd6682, 0xa17aa6, + 0x998ebe, 0x7fb3f4, 0x948dc3, 0xb16f97, 0xb57195, 0x86aceb, + 0x75b5ff, 0x73a4ef, 0xb6688d, 0x997fb4, 0xae6b92, 0x9a88b5, + 0xc25a75, 0x9978a8, 0x8998cf, 0x74b3f9, 0x8396d3, 0x8b8fcb, + 0x8a90cd, 0x74b1fb, 0x74b3ff, 0x819ee3, 0x8f86c2, 0x66a8fa, + 0x7c88cd, 0x857fba, 0x9d78a0, 0x966c99, 0x7f8dc9, 0x72b6fd ) ); + +/* Interlaced */ +PIX ( interlaced, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x03, 0x00, 0x00, 0x01, 0xb3, 0xc2, 0x6f, 0x18, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0xff, + 0x50, 0x4c, 0x54, 0x45, 0x8f, 0xc5, 0xfe, 0xa8, 0xac, 0xd7, 0xab, + 0xab, 0xd3, 0x9d, 0xb7, 0xe3, 0x9c, 0xbb, 0xe8, 0x9a, 0xcb, 0xfd, + 0xa8, 0xc7, 0xf0, 0xa8, 0xca, 0xf5, 0xa0, 0xc7, 0xf6, 0x9f, 0xc3, + 0xed, 0x8f, 0xb9, 0xf0, 0x98, 0xad, 0xdf, 0xa0, 0xb4, 0xde, 0xa1, + 0xc6, 0xf0, 0x89, 0xc2, 0xfd, 0xa4, 0xa8, 0xd1, 0xba, 0x91, 0xaf, + 0xcd, 0x65, 0x79, 0xc7, 0x6c, 0x82, 0xa6, 0xa6, 0xd1, 0xb6, 0x96, + 0xb7, 0xc3, 0x8b, 0xa7, 0xbf, 0x88, 0xa4, 0xb1, 0x98, 0xb9, 0xb6, + 0x87, 0xa9, 0xc4, 0x6b, 0x86, 0xbb, 0x7c, 0x9b, 0xaa, 0xab, 0xd0, + 0x83, 0xb1, 0xf1, 0xb7, 0x81, 0xa1, 0xbc, 0x7f, 0x9b, 0xba, 0x79, + 0x96, 0xbc, 0x71, 0x8d, 0xa5, 0x8e, 0xb8, 0x8e, 0xb6, 0xed, 0xd0, + 0x64, 0x78, 0xbe, 0x7c, 0x97, 0x89, 0xb8, 0xed, 0xc4, 0x6e, 0x88, + 0xbd, 0x70, 0x90, 0xa8, 0x8d, 0xb7, 0x8d, 0xbc, 0xf4, 0x83, 0xa1, + 0xe2, 0xb9, 0x73, 0x95, 0xbf, 0x71, 0x90, 0xc5, 0x6b, 0x84, 0xa9, + 0x7d, 0xa7, 0x7b, 0xac, 0xf1, 0x8b, 0xa1, 0xdc, 0xcf, 0x58, 0x6c, + 0xad, 0x85, 0xab, 0x81, 0xb1, 0xe9, 0xbd, 0x66, 0x82, 0xa1, 0x7a, + 0xa6, 0x99, 0x8e, 0xbe, 0x7f, 0xb3, 0xf4, 0x94, 0x8d, 0xc3, 0xb1, + 0x6f, 0x97, 0xb5, 0x71, 0x95, 0x86, 0xac, 0xeb, 0x75, 0xb5, 0xff, + 0x73, 0xa4, 0xef, 0xb6, 0x68, 0x8d, 0x99, 0x7f, 0xb4, 0xae, 0x6b, + 0x92, 0x9a, 0x88, 0xb5, 0xc2, 0x5a, 0x75, 0x99, 0x78, 0xa8, 0x89, + 0x98, 0xcf, 0x74, 0xb3, 0xf9, 0x83, 0x96, 0xd3, 0x8b, 0x8f, 0xcb, + 0x8a, 0x90, 0xcd, 0x74, 0xb1, 0xfb, 0x74, 0xb3, 0xff, 0x81, 0x9e, + 0xe3, 0x8f, 0x86, 0xc2, 0x66, 0xa8, 0xfa, 0x7c, 0x88, 0xcd, 0x85, + 0x7f, 0xba, 0x9d, 0x78, 0xa0, 0x96, 0x6c, 0x99, 0x7f, 0x8d, 0xc9, + 0x72, 0xb6, 0xfd, 0xff, 0xff, 0xff, 0xdb, 0x2a, 0x9f, 0xad, 0x00, + 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x54, 0xe4, 0x03, 0x88, + 0xa5, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, + 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, + 0x00, 0x00, 0x00, 0x68, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, + 0x60, 0xe0, 0x60, 0x60, 0xe1, 0x61, 0xb0, 0xb0, 0x71, 0x70, 0x61, + 0x60, 0x62, 0xe3, 0x62, 0xb0, 0xb2, 0x73, 0x62, 0x90, 0x91, 0x53, + 0x50, 0x52, 0x51, 0xd3, 0x60, 0x60, 0x64, 0x66, 0x65, 0xe7, 0xe4, + 0xe6, 0x65, 0x90, 0x95, 0x57, 0x54, 0x56, 0x55, 0xd7, 0x64, 0xb0, + 0xb4, 0xb6, 0xb5, 0x77, 0x74, 0x76, 0x65, 0xe0, 0xe3, 0x17, 0x10, + 0x14, 0x12, 0x16, 0x11, 0x15, 0x13, 0x97, 0x90, 0x94, 0x92, 0x66, + 0xd0, 0xd2, 0xd6, 0xd1, 0xd5, 0xd3, 0x37, 0x30, 0x34, 0x32, 0x36, + 0x31, 0x35, 0x33, 0x67, 0x70, 0x73, 0xf7, 0xf0, 0xf4, 0xf2, 0xf6, + 0xf1, 0xf5, 0xf3, 0x0f, 0x08, 0x0c, 0x0a, 0x06, 0x00, 0xf9, 0xc2, + 0x0d, 0x9f, 0x36, 0xdc, 0x4b, 0x87, 0x00, 0x00, 0x00, 0x25, 0x74, + 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, + 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, + 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, + 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, + 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, + 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, + 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, + 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, + 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x8fc5fe, 0xa8acd7, 0xababd3, 0x9db7e3, 0x9cbbe8, 0x9acbfd, + 0xa8c7f0, 0xa8caf5, 0xa0c7f6, 0x9fc3ed, 0x8fb9f0, 0x98addf, + 0xa0b4de, 0xa1c6f0, 0x89c2fd, 0xa4a8d1, 0xba91af, 0xcd6579, + 0xc76c82, 0xa6a6d1, 0xb696b7, 0xc38ba7, 0xbf88a4, 0xb198b9, + 0xb687a9, 0xc46b86, 0xbb7c9b, 0xaaabd0, 0x83b1f1, 0xb781a1, + 0xbc7f9b, 0xba7996, 0xbc718d, 0xa58eb8, 0x8eb6ed, 0xd06478, + 0xbe7c97, 0x89b8ed, 0xc46e88, 0xbd7090, 0xa88db7, 0x8dbcf4, + 0x83a1e2, 0xb97395, 0xbf7190, 0xc56b84, 0xa97da7, 0x7bacf1, + 0x8ba1dc, 0xcf586c, 0xad85ab, 0x81b1e9, 0xbd6682, 0xa17aa6, + 0x998ebe, 0x7fb3f4, 0x948dc3, 0xb16f97, 0xb57195, 0x86aceb, + 0x75b5ff, 0x73a4ef, 0xb6688d, 0x997fb4, 0xae6b92, 0x9a88b5, + 0xc25a75, 0x9978a8, 0x8998cf, 0x74b3f9, 0x8396d3, 0x8b8fcb, + 0x8a90cd, 0x74b1fb, 0x74b3ff, 0x819ee3, 0x8f86c2, 0x66a8fa, + 0x7c88cd, 0x857fba, 0x9d78a0, 0x966c99, 0x7f8dc9, 0x72b6fd ) ); + +/* Interlaced (height 1) */ +PIX ( interlaced_h1, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x01, 0x04, 0x03, 0x00, 0x00, 0x01, 0x66, 0x29, 0xc2, 0xe6, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x1b, + 0x50, 0x4c, 0x54, 0x45, 0x9a, 0x9a, 0xcd, 0xae, 0x88, 0xae, 0x9f, + 0x94, 0xc3, 0x9a, 0x9d, 0xcf, 0xab, 0x8a, 0xb3, 0xa2, 0x91, 0xbb, + 0xa9, 0x7f, 0xa6, 0x93, 0xa4, 0xd7, 0xff, 0xff, 0xff, 0x01, 0x68, + 0x32, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x08, + 0x86, 0xde, 0x95, 0x7a, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, + 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, + 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x11, 0x49, 0x44, 0x41, 0x54, + 0x08, 0xd7, 0x63, 0x60, 0x60, 0x70, 0x60, 0x50, 0x63, 0x10, 0x0e, + 0x07, 0x00, 0x02, 0x9e, 0x00, 0xd1, 0x1a, 0x21, 0xdf, 0x5d, 0x00, + 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, + 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, + 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, + 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, + 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, + 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, + 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, + 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, + 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, + 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 8, 1, + DATA ( 0x9a9acd, 0xae88ae, 0x9f94c3, 0x9a9dcf, 0xab8ab3, 0xa291bb, + 0xa97fa6, 0x93a4d7, ) ); + +/* Interlaced (height 2) */ +PIX ( interlaced_h2, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x02, 0x08, 0x03, 0x00, 0x00, 0x01, 0x25, 0x4d, 0x5d, 0x49, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x33, + 0x50, 0x4c, 0x54, 0x45, 0x9b, 0xa9, 0xda, 0xb7, 0x8b, 0xab, 0xb1, + 0x8b, 0xae, 0xa4, 0xa6, 0xd2, 0xb7, 0x94, 0xb5, 0xa7, 0x9e, 0xc5, + 0xb0, 0x86, 0xab, 0xa2, 0xa5, 0xd0, 0x99, 0x8b, 0xbe, 0xa7, 0x82, + 0xae, 0x8e, 0x9b, 0xd5, 0x90, 0x92, 0xcb, 0xa0, 0x7e, 0xad, 0x9e, + 0x82, 0xae, 0xa4, 0x76, 0x9f, 0x85, 0xa2, 0xde, 0xff, 0xff, 0xff, + 0xf3, 0x35, 0x13, 0x79, 0x00, 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, + 0x44, 0x10, 0x95, 0xb2, 0x0d, 0x2c, 0x00, 0x00, 0x00, 0x09, 0x70, + 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, + 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x1d, 0x49, 0x44, + 0x41, 0x54, 0x08, 0xd7, 0x63, 0x60, 0x60, 0x60, 0x61, 0x60, 0x62, + 0x63, 0x60, 0x64, 0x66, 0x65, 0x67, 0xe0, 0xe0, 0xe4, 0xe2, 0xe6, + 0xe1, 0xe5, 0xe3, 0x07, 0x00, 0x02, 0xf9, 0x00, 0x79, 0x11, 0xe8, + 0xb8, 0x97, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, + 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, + 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, + 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, + 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, + 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, + 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, + 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, + 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, + 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, + 0x60, 0x82 ), + 8, 2, + DATA ( 0x9ba9da, 0xb78bab, 0xb18bae, 0xa4a6d2, 0xb794b5, 0xa79ec5, + 0xb086ab, 0xa2a5d0, 0x998bbe, 0xa782ae, 0x8e9bd5, 0x9092cb, + 0xa07ead, 0x9e82ae, 0xa4769f, 0x85a2de, ) ); + +/* Interlaced (height 3) */ +PIX ( interlaced_h3, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x03, 0x08, 0x03, 0x00, 0x00, 0x01, 0xee, 0x11, 0x8e, 0xec, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x4b, + 0x50, 0x4c, 0x54, 0x45, 0x99, 0xb4, 0xe6, 0xb3, 0x97, 0xb9, 0xb1, + 0x95, 0xb7, 0xa9, 0xaf, 0xd7, 0xb4, 0xa4, 0xc7, 0xa8, 0xa6, 0xce, + 0xad, 0x90, 0xb7, 0xa8, 0xa8, 0xcf, 0x9d, 0x94, 0xc5, 0xbc, 0x78, + 0x97, 0xac, 0x81, 0xa8, 0x9a, 0x98, 0xca, 0xb9, 0x79, 0x99, 0xa5, + 0x8f, 0xb6, 0xb1, 0x76, 0x9a, 0x94, 0xa1, 0xd4, 0x96, 0x87, 0xbc, + 0x9a, 0x8a, 0xbe, 0x7d, 0xaa, 0xef, 0x8c, 0x8f, 0xcc, 0x91, 0x83, + 0xbc, 0x9b, 0x7c, 0xaa, 0x9c, 0x76, 0xa2, 0x7d, 0xa3, 0xe2, 0xff, + 0xff, 0xff, 0x53, 0xa1, 0xdb, 0xb9, 0x00, 0x00, 0x00, 0x01, 0x62, + 0x4b, 0x47, 0x44, 0x18, 0x9b, 0x69, 0x85, 0x1e, 0x00, 0x00, 0x00, + 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, + 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x26, + 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x05, 0xc1, 0x85, 0x01, 0x00, + 0x20, 0x00, 0xc0, 0xa0, 0xd9, 0xdd, 0xf5, 0xff, 0xa7, 0x02, 0xa0, + 0x91, 0x96, 0x3e, 0xf7, 0x45, 0x28, 0xe3, 0x18, 0xeb, 0x3c, 0x7c, + 0x88, 0x29, 0x97, 0xda, 0x3e, 0x0d, 0xb1, 0x01, 0x15, 0x29, 0x54, + 0xbc, 0x10, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, + 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, + 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, + 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, + 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, 0x25, + 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, + 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, + 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, + 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, 0xde, + 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, + 0x60, 0x82 ), + 8, 3, + DATA ( 0x99b4e6, 0xb397b9, 0xb195b7, 0xa9afd7, 0xb4a4c7, 0xa8a6ce, + 0xad90b7, 0xa8a8cf, 0x9d94c5, 0xbc7897, 0xac81a8, 0x9a98ca, + 0xb97999, 0xa58fb6, 0xb1769a, 0x94a1d4, 0x9687bc, 0x9a8abe, + 0x7daaef, 0x8c8fcc, 0x9183bc, 0x9b7caa, 0x9c76a2, 0x7da3e2 ) ); + +/* Interlaced (height 4) */ +PIX ( interlaced_h4, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x04, 0x08, 0x03, 0x00, 0x00, 0x01, 0xf3, 0x14, 0xbe, 0x54, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x63, + 0x50, 0x4c, 0x54, 0x45, 0x99, 0xb8, 0xea, 0xaf, 0xa0, 0xc4, 0xab, + 0xa1, 0xc7, 0xa8, 0xb7, 0xe0, 0xaf, 0xb1, 0xd7, 0xa5, 0xae, 0xd7, + 0xa6, 0x9b, 0xc5, 0xa8, 0xad, 0xd3, 0x9a, 0xa3, 0xd4, 0xbd, 0x7e, + 0x9b, 0xbb, 0x77, 0x94, 0xa4, 0x9b, 0xc6, 0xbe, 0x80, 0x9d, 0xaa, + 0x93, 0xb9, 0xba, 0x76, 0x96, 0xa2, 0x9e, 0xca, 0x9f, 0x87, 0xb7, + 0xb7, 0x76, 0x99, 0x99, 0x91, 0xc5, 0x91, 0x94, 0xcc, 0xb1, 0x76, + 0x9a, 0xa2, 0x88, 0xb1, 0xa7, 0x77, 0x9f, 0x87, 0xa3, 0xde, 0x92, + 0x8a, 0xc1, 0x91, 0x91, 0xca, 0x77, 0xb0, 0xf8, 0x8a, 0x8f, 0xce, + 0x87, 0x89, 0xc8, 0x97, 0x7a, 0xaa, 0x99, 0x76, 0xa3, 0x7b, 0xa2, + 0xe3, 0xff, 0xff, 0xff, 0xfa, 0x09, 0xb4, 0x8e, 0x00, 0x00, 0x00, + 0x01, 0x62, 0x4b, 0x47, 0x44, 0x20, 0xb3, 0x6b, 0x3d, 0x80, 0x00, + 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, + 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x60, 0x60, + 0x60, 0x61, 0x60, 0x62, 0x63, 0x10, 0x10, 0x12, 0x11, 0x63, 0x60, + 0x64, 0x66, 0x65, 0x67, 0x10, 0x14, 0x16, 0x15, 0x67, 0xe0, 0xe0, + 0xe4, 0xe2, 0xe6, 0xe1, 0xe5, 0xe3, 0x67, 0x90, 0x90, 0x94, 0x92, + 0x96, 0x91, 0x95, 0x93, 0x07, 0x00, 0x1b, 0x22, 0x01, 0xf1, 0x69, + 0x98, 0xfa, 0x95, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, + 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, + 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, + 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, 0x00, + 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, + 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, + 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, + 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, 0xe9, + 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, + 0x42, 0x60, 0x82 ), + 8, 4, + DATA ( 0x99b8ea, 0xafa0c4, 0xaba1c7, 0xa8b7e0, 0xafb1d7, 0xa5aed7, + 0xa69bc5, 0xa8add3, 0x9aa3d4, 0xbd7e9b, 0xbb7794, 0xa49bc6, + 0xbe809d, 0xaa93b9, 0xba7696, 0xa29eca, 0x9f87b7, 0xb77699, + 0x9991c5, 0x9194cc, 0xb1769a, 0xa288b1, 0xa7779f, 0x87a3de, + 0x928ac1, 0x9191ca, 0x77b0f8, 0x8a8fce, 0x8789c8, 0x977aaa, + 0x9976a3, 0x7ba2e3, ) ); + +/* Interlaced (width 1) */ +PIX ( interlaced_w1, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x08, 0x04, 0x03, 0x00, 0x00, 0x01, 0xbd, 0x33, 0xb8, 0xe4, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x1b, + 0x50, 0x4c, 0x54, 0x45, 0x9f, 0xbd, 0xeb, 0xae, 0xa0, 0xc5, 0xb4, + 0x8a, 0xac, 0xac, 0x8a, 0xb0, 0xa5, 0x87, 0xb2, 0x9d, 0x86, 0xb6, + 0x90, 0x8c, 0xc3, 0x82, 0x93, 0xd3, 0xff, 0xff, 0xff, 0xac, 0xaf, + 0x93, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x08, + 0x86, 0xde, 0x95, 0x7a, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, + 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, + 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x18, 0x49, 0x44, 0x41, 0x54, + 0x08, 0xd7, 0x63, 0x60, 0x60, 0x70, 0x60, 0x50, 0x60, 0x48, 0x60, + 0x10, 0x60, 0x30, 0x60, 0x08, 0x60, 0x28, 0x00, 0x00, 0x0a, 0xd0, + 0x01, 0xc1, 0x05, 0xa2, 0x99, 0xc6, 0x00, 0x00, 0x00, 0x25, 0x74, + 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, + 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, + 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, + 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, + 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, + 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, + 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, + 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, + 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 1, 8, + DATA ( 0x9fbdeb, 0xaea0c5, 0xb48aac, 0xac8ab0, 0xa587b2, 0x9d86b6, + 0x908cc3, 0x8293d3, ) ); + +/* Interlaced (width 2) */ +PIX ( interlaced_w2, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x01, 0x93, 0xf4, 0xee, 0xe6, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x33, + 0x50, 0x4c, 0x54, 0x45, 0xa0, 0xbc, 0xe9, 0x9e, 0xbe, 0xec, 0xad, + 0xa1, 0xc7, 0xaf, 0x9e, 0xc2, 0xb4, 0x8b, 0xad, 0xb6, 0x88, 0xa9, + 0xae, 0x87, 0xac, 0xac, 0x8b, 0xb1, 0xa9, 0x83, 0xad, 0xa1, 0x8a, + 0xb6, 0x9e, 0x87, 0xb8, 0x9d, 0x84, 0xb3, 0x8e, 0x92, 0xcc, 0x92, + 0x85, 0xba, 0x80, 0x9b, 0xde, 0x84, 0x8b, 0xc7, 0xff, 0xff, 0xff, + 0xa3, 0x2a, 0xf5, 0x35, 0x00, 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, + 0x44, 0x10, 0x95, 0xb2, 0x0d, 0x2c, 0x00, 0x00, 0x00, 0x09, 0x70, + 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, + 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x20, 0x49, 0x44, + 0x41, 0x54, 0x08, 0xd7, 0x05, 0xc1, 0x05, 0x01, 0x00, 0x20, 0x00, + 0x00, 0x20, 0xec, 0xd6, 0xff, 0x6f, 0x05, 0x74, 0xd9, 0x16, 0x14, + 0xc3, 0x11, 0x93, 0xda, 0xcc, 0xe5, 0xbe, 0x0f, 0x04, 0xf2, 0x00, + 0x79, 0x83, 0x54, 0x1a, 0x1e, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, + 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, + 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, + 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, + 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, + 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, + 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, + 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, + 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, + 0x44, 0xae, 0x42, 0x60, 0x82 ), + 2, 8, + DATA ( 0xa0bce9, 0x9ebeec, 0xada1c7, 0xaf9ec2, 0xb48bad, 0xb688a9, + 0xae87ac, 0xac8bb1, 0xa983ad, 0xa18ab6, 0x9e87b8, 0x9d84b3, + 0x8e92cc, 0x9285ba, 0x809bde, 0x848bc7, ) ); + +/* Interlaced (width 3) */ +PIX ( interlaced_w3, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x01, 0x7c, 0x36, 0x85, 0xd8, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x4b, + 0x50, 0x4c, 0x54, 0x45, 0xa0, 0xb7, 0xe4, 0xa1, 0xc4, 0xf1, 0x9c, + 0xba, 0xe9, 0xab, 0xa0, 0xc7, 0xb1, 0xa1, 0xc5, 0xae, 0x9b, 0xc0, + 0xb1, 0x8d, 0xb0, 0xb8, 0x88, 0xa8, 0xb5, 0x87, 0xa9, 0xae, 0x86, + 0xab, 0xae, 0x88, 0xad, 0xaa, 0x8c, 0xb4, 0xac, 0x80, 0xa9, 0xa5, + 0x88, 0xb2, 0x9f, 0x8b, 0xb7, 0xa0, 0x88, 0xb8, 0x9e, 0x84, 0xb5, + 0x9c, 0x85, 0xb4, 0x8f, 0x94, 0xce, 0x8f, 0x8a, 0xc4, 0x93, 0x84, + 0xb6, 0x81, 0x9d, 0xdf, 0x7e, 0x95, 0xd8, 0x88, 0x86, 0xbe, 0xff, + 0xff, 0xff, 0xef, 0xfb, 0x85, 0x9c, 0x00, 0x00, 0x00, 0x01, 0x62, + 0x4b, 0x47, 0x44, 0x18, 0x9b, 0x69, 0x85, 0x1e, 0x00, 0x00, 0x00, + 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, + 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x28, + 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x05, 0xc1, 0x85, 0x01, 0x00, + 0x20, 0x00, 0xc0, 0xa0, 0xd9, 0xdd, 0xf5, 0xff, 0xa7, 0x02, 0x90, + 0x91, 0x54, 0xac, 0x67, 0x6e, 0x04, 0x8e, 0xc2, 0x42, 0x69, 0x43, + 0x88, 0x89, 0xd6, 0x07, 0xe7, 0xbe, 0x0f, 0x0f, 0x68, 0x01, 0x15, + 0x06, 0x65, 0x37, 0x5a, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, + 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, + 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, + 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, 0x28, 0x00, 0x00, + 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, + 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, 0x31, 0x34, + 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, + 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xd3, + 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, + 0xae, 0x42, 0x60, 0x82 ), + 3, 8, + DATA ( 0xa0b7e4, 0xa1c4f1, 0x9cbae9, 0xaba0c7, 0xb1a1c5, 0xae9bc0, + 0xb18db0, 0xb888a8, 0xb587a9, 0xae86ab, 0xae88ad, 0xaa8cb4, + 0xac80a9, 0xa588b2, 0x9f8bb7, 0xa088b8, 0x9e84b5, 0x9c85b4, + 0x8f94ce, 0x8f8ac4, 0x9384b6, 0x819ddf, 0x7e95d8, 0x8886be ) ); + +/* Interlaced (width 4) */ +PIX ( interlaced_w4, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x01, 0x9e, 0xea, 0x9e, 0xa1, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0x63, + 0x50, 0x4c, 0x54, 0x45, 0xa0, 0xb4, 0xe1, 0xa1, 0xc1, 0xee, 0x9f, + 0xc3, 0xf1, 0x9b, 0xb8, 0xe6, 0xa8, 0xa3, 0xcc, 0xb2, 0x9d, 0xc1, + 0xb0, 0xa2, 0xc6, 0xad, 0x99, 0xbe, 0xae, 0x92, 0xb7, 0xb9, 0x84, + 0xa4, 0xb8, 0x89, 0xa9, 0xb4, 0x87, 0xa9, 0xae, 0x87, 0xac, 0xae, + 0x86, 0xab, 0xaf, 0x88, 0xac, 0xa8, 0x8d, 0xb7, 0xaf, 0x7e, 0xa5, + 0xa4, 0x88, 0xb5, 0xa8, 0x85, 0xad, 0x9c, 0x8d, 0xbc, 0xa6, 0x81, + 0xae, 0x94, 0x90, 0xc7, 0xa8, 0x79, 0xa2, 0x96, 0x8b, 0xbd, 0x94, + 0x8e, 0xc4, 0x85, 0x9b, 0xdb, 0x99, 0x7b, 0xac, 0x8f, 0x89, 0xbe, + 0x84, 0x99, 0xd9, 0x7c, 0xa1, 0xe8, 0x83, 0x87, 0xc5, 0x88, 0x89, + 0xbf, 0xff, 0xff, 0xff, 0xec, 0xf4, 0xb8, 0xe8, 0x00, 0x00, 0x00, + 0x01, 0x62, 0x4b, 0x47, 0x44, 0x20, 0xb3, 0x6b, 0x3d, 0x80, 0x00, + 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, + 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, + 0x00, 0x34, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x05, 0xc1, 0x09, + 0x02, 0x80, 0x10, 0x00, 0x00, 0xc1, 0x4d, 0x85, 0x0e, 0x8a, 0xa2, + 0xc3, 0xf5, 0xff, 0x5f, 0x9a, 0x01, 0x4e, 0x04, 0x1e, 0xbd, 0xf2, + 0xfe, 0x0c, 0x23, 0xcb, 0x86, 0xbb, 0xf8, 0x12, 0xd3, 0x2c, 0x15, + 0xbb, 0xb1, 0x07, 0x77, 0x88, 0x0f, 0xb9, 0xd4, 0xd6, 0x01, 0x21, + 0x30, 0x01, 0xf1, 0x50, 0x46, 0x7a, 0xbf, 0x00, 0x00, 0x00, 0x25, + 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, + 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, 0x32, 0x3a, 0x34, 0x33, 0x3a, + 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0xa2, 0xb4, 0x66, + 0x28, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, + 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, + 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x2d, 0x31, 0x32, 0x54, 0x32, + 0x32, 0x3a, 0x34, 0x33, 0x3a, 0x30, 0x33, 0x2b, 0x30, 0x31, 0x3a, + 0x30, 0x30, 0xd3, 0xe9, 0xde, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 4, 8, + DATA ( 0xa0b4e1, 0xa1c1ee, 0x9fc3f1, 0x9bb8e6, 0xa8a3cc, 0xb29dc1, + 0xb0a2c6, 0xad99be, 0xae92b7, 0xb984a4, 0xb889a9, 0xb487a9, + 0xae87ac, 0xae86ab, 0xaf88ac, 0xa88db7, 0xaf7ea5, 0xa488b5, + 0xa885ad, 0x9c8dbc, 0xa681ae, 0x9490c7, 0xa879a2, 0x968bbd, + 0x948ec4, 0x859bdb, 0x997bac, 0x8f89be, 0x8499d9, 0x7ca1e8, + 0x8387c5, 0x8889bf, ) ); + +/* Multiple IDAT sections */ +PIX ( multi_idat, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x03, 0x00, 0x00, 0x00, 0xc4, 0xc5, 0x5f, 0x8e, + 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, + 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, + 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x20, + 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x26, 0x00, 0x00, 0x80, + 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80, 0xe8, 0x00, 0x00, + 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a, 0x98, 0x00, + 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00, 0xff, + 0x50, 0x4c, 0x54, 0x45, 0x8f, 0xc5, 0xfe, 0xa8, 0xac, 0xd7, 0xab, + 0xab, 0xd3, 0x9d, 0xb7, 0xe3, 0x9c, 0xbb, 0xe8, 0x9a, 0xcb, 0xfd, + 0xa8, 0xc7, 0xf0, 0xa8, 0xca, 0xf5, 0xa0, 0xc7, 0xf6, 0x9f, 0xc3, + 0xed, 0x8f, 0xb9, 0xf0, 0x98, 0xad, 0xdf, 0xa0, 0xb4, 0xde, 0xa1, + 0xc6, 0xf0, 0x89, 0xc2, 0xfd, 0xa4, 0xa8, 0xd1, 0xba, 0x91, 0xaf, + 0xcd, 0x65, 0x79, 0xc7, 0x6c, 0x82, 0xa6, 0xa6, 0xd1, 0xb6, 0x96, + 0xb7, 0xc3, 0x8b, 0xa7, 0xbf, 0x88, 0xa4, 0xb1, 0x98, 0xb9, 0xb6, + 0x87, 0xa9, 0xc4, 0x6b, 0x86, 0xbb, 0x7c, 0x9b, 0xaa, 0xab, 0xd0, + 0x83, 0xb1, 0xf1, 0xb7, 0x81, 0xa1, 0xbc, 0x7f, 0x9b, 0xba, 0x79, + 0x96, 0xbc, 0x71, 0x8d, 0xa5, 0x8e, 0xb8, 0x8e, 0xb6, 0xed, 0xd0, + 0x64, 0x78, 0xbe, 0x7c, 0x97, 0x89, 0xb8, 0xed, 0xc4, 0x6e, 0x88, + 0xbd, 0x70, 0x90, 0xa8, 0x8d, 0xb7, 0x8d, 0xbc, 0xf4, 0x83, 0xa1, + 0xe2, 0xb9, 0x73, 0x95, 0xbf, 0x71, 0x90, 0xc5, 0x6b, 0x84, 0xa9, + 0x7d, 0xa7, 0x7b, 0xac, 0xf1, 0x8b, 0xa1, 0xdc, 0xcf, 0x58, 0x6c, + 0xad, 0x85, 0xab, 0x81, 0xb1, 0xe9, 0xbd, 0x66, 0x82, 0xa1, 0x7a, + 0xa6, 0x99, 0x8e, 0xbe, 0x7f, 0xb3, 0xf4, 0x94, 0x8d, 0xc3, 0xb1, + 0x6f, 0x97, 0xb5, 0x71, 0x95, 0x86, 0xac, 0xeb, 0x75, 0xb5, 0xff, + 0x73, 0xa4, 0xef, 0xb6, 0x68, 0x8d, 0x99, 0x7f, 0xb4, 0xae, 0x6b, + 0x92, 0x9a, 0x88, 0xb5, 0xc2, 0x5a, 0x75, 0x99, 0x78, 0xa8, 0x89, + 0x98, 0xcf, 0x74, 0xb3, 0xf9, 0x83, 0x96, 0xd3, 0x8b, 0x8f, 0xcb, + 0x8a, 0x90, 0xcd, 0x74, 0xb1, 0xfb, 0x74, 0xb3, 0xff, 0x81, 0x9e, + 0xe3, 0x8f, 0x86, 0xc2, 0x66, 0xa8, 0xfa, 0x7c, 0x88, 0xcd, 0x85, + 0x7f, 0xba, 0x9d, 0x78, 0xa0, 0x96, 0x6c, 0x99, 0x7f, 0x8d, 0xc9, + 0x72, 0xb6, 0xfd, 0xff, 0xff, 0xff, 0xdb, 0x2a, 0x9f, 0xad, 0x00, + 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x54, 0xe4, 0x03, 0x88, + 0xa5, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, + 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, + 0x00, 0x00, 0x00, 0x07, 0x49, 0x44, 0x41, 0x54, 0x08, 0x5b, 0x63, + 0x64, 0x60, 0x44, 0x01, 0xdd, 0xe3, 0x71, 0x09, 0x00, 0x00, 0x00, + 0x07, 0x49, 0x44, 0x41, 0x54, 0x7c, 0x28, 0x3c, 0x16, 0x0a, 0xb8, + 0x00, 0xb9, 0x49, 0x1a, 0x82, 0x00, 0x00, 0x00, 0x04, 0x49, 0x44, + 0x41, 0x54, 0x1c, 0xee, 0x00, 0xa7, 0x1b, 0x22, 0xc4, 0xc1, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 ), + 14, 6, + DATA ( 0x8fc5fe, 0xa8acd7, 0xababd3, 0x9db7e3, 0x9cbbe8, 0x9acbfd, + 0xa8c7f0, 0xa8caf5, 0xa0c7f6, 0x9fc3ed, 0x8fb9f0, 0x98addf, + 0xa0b4de, 0xa1c6f0, 0x89c2fd, 0xa4a8d1, 0xba91af, 0xcd6579, + 0xc76c82, 0xa6a6d1, 0xb696b7, 0xc38ba7, 0xbf88a4, 0xb198b9, + 0xb687a9, 0xc46b86, 0xbb7c9b, 0xaaabd0, 0x83b1f1, 0xb781a1, + 0xbc7f9b, 0xba7996, 0xbc718d, 0xa58eb8, 0x8eb6ed, 0xd06478, + 0xbe7c97, 0x89b8ed, 0xc46e88, 0xbd7090, 0xa88db7, 0x8dbcf4, + 0x83a1e2, 0xb97395, 0xbf7190, 0xc56b84, 0xa97da7, 0x7bacf1, + 0x8ba1dc, 0xcf586c, 0xad85ab, 0x81b1e9, 0xbd6682, 0xa17aa6, + 0x998ebe, 0x7fb3f4, 0x948dc3, 0xb16f97, 0xb57195, 0x86aceb, + 0x75b5ff, 0x73a4ef, 0xb6688d, 0x997fb4, 0xae6b92, 0x9a88b5, + 0xc25a75, 0x9978a8, 0x8998cf, 0x74b3f9, 0x8396d3, 0x8b8fcb, + 0x8a90cd, 0x74b1fb, 0x74b3ff, 0x819ee3, 0x8f86c2, 0x66a8fa, + 0x7c88cd, 0x857fba, 0x9d78a0, 0x966c99, 0x7f8dc9, 0x72b6fd ) ); + +/* Original large image */ +PIX ( original, &png_image_type, + DATA ( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, + 0x00, 0x0c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x71, 0xdb, 0xdd, 0x0f, + 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, + 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, + 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, + 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, + 0x49, 0x4d, 0x45, 0x07, 0xde, 0x01, 0x06, 0x10, 0x37, 0x03, 0xe9, + 0xc3, 0xf3, 0x6d, 0x00, 0x00, 0x00, 0x1d, 0x69, 0x54, 0x58, 0x74, + 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x64, 0x2e, 0x65, 0x07, + 0x00, 0x00, 0x04, 0x14, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0x35, + 0xcd, 0x5d, 0x4c, 0x56, 0x65, 0x00, 0xc0, 0xf1, 0xff, 0xf3, 0x9c, + 0x6f, 0x10, 0x04, 0x14, 0x14, 0x03, 0x11, 0xc9, 0x8f, 0x54, 0x96, + 0x42, 0x5a, 0x2d, 0x5d, 0x19, 0xa6, 0x76, 0xd1, 0xec, 0xc6, 0x34, + 0x6b, 0xf3, 0xa3, 0x39, 0xb3, 0x69, 0x6b, 0x6b, 0xb3, 0xac, 0x95, + 0x5b, 0x8b, 0x5a, 0xb9, 0xd2, 0x0b, 0xaf, 0x32, 0xbd, 0xc0, 0xa5, + 0xd5, 0x85, 0xce, 0x69, 0xf8, 0xb1, 0x35, 0x96, 0x92, 0x3a, 0x33, + 0xdd, 0x50, 0xd4, 0xa5, 0x94, 0x86, 0x06, 0xa8, 0x7c, 0xc8, 0xfb, + 0xf2, 0xbe, 0xe7, 0x9c, 0xe7, 0x9c, 0xe7, 0xe9, 0xa2, 0x75, 0xf5, + 0xbb, 0xfc, 0x89, 0x9d, 0xed, 0xda, 0x08, 0x93, 0xe2, 0x49, 0x70, + 0x03, 0x9b, 0x54, 0x43, 0x12, 0x2b, 0x54, 0xa2, 0x71, 0x3d, 0x17, + 0x23, 0x04, 0x49, 0xa2, 0x29, 0xf0, 0x25, 0xd2, 0x80, 0x30, 0x9a, + 0x02, 0x5f, 0x20, 0xb5, 0x60, 0x24, 0x34, 0x24, 0x06, 0x6c, 0x0f, + 0x84, 0x05, 0xc3, 0x23, 0x8a, 0x5c, 0x5e, 0xa3, 0x8d, 0x8b, 0x6b, + 0x49, 0xd2, 0x44, 0x61, 0xd9, 0x8a, 0xb2, 0xb2, 0x00, 0x93, 0x6a, + 0xa2, 0x48, 0x62, 0x1b, 0x21, 0xd0, 0xa9, 0x26, 0xb2, 0x2c, 0xe6, + 0xef, 0xfe, 0x08, 0x30, 0xb4, 0xbf, 0xf1, 0x29, 0x39, 0x17, 0x42, + 0x09, 0xb6, 0x0b, 0x26, 0x94, 0x48, 0xa5, 0x09, 0x3c, 0x89, 0x52, + 0x20, 0x02, 0x81, 0x0f, 0x10, 0x19, 0x4c, 0xaa, 0xc9, 0x69, 0x0b, + 0xab, 0x48, 0x60, 0xa5, 0x2e, 0x22, 0x1f, 0x93, 0xb3, 0x24, 0x89, + 0x07, 0x56, 0xe0, 0x90, 0x0d, 0x1d, 0x1c, 0x0b, 0x02, 0xdf, 0x42, + 0x2a, 0x83, 0x1d, 0x27, 0x06, 0xd7, 0x76, 0xd0, 0x02, 0x12, 0xad, + 0xb1, 0x2c, 0x0b, 0x27, 0x97, 0xe5, 0xbd, 0x55, 0x93, 0xd1, 0x5e, + 0x80, 0xb2, 0x5c, 0x6e, 0x3d, 0xf1, 0x02, 0x27, 0xd7, 0x7c, 0x46, + 0x54, 0x5a, 0x42, 0xd1, 0x40, 0x1f, 0xcb, 0xd6, 0x2d, 0xa6, 0x67, + 0xde, 0x62, 0xce, 0x6e, 0xfa, 0x8a, 0x54, 0x6b, 0x1a, 0x5a, 0x3e, + 0x67, 0x76, 0xeb, 0x5e, 0x8e, 0x6e, 0x3b, 0x40, 0xb6, 0x6a, 0x0e, + 0x1b, 0xb7, 0x2d, 0xa5, 0xe2, 0xee, 0x75, 0xd0, 0x1a, 0x21, 0x04, + 0x26, 0xd5, 0x74, 0x37, 0x2c, 0xe4, 0xc4, 0xb6, 0x16, 0xec, 0x30, + 0x52, 0xb8, 0xae, 0x83, 0x46, 0x70, 0xf4, 0xcd, 0x66, 0xc6, 0x4a, + 0xa8, 0x6b, 0x3b, 0xc4, 0x50, 0x65, 0x1d, 0x47, 0x56, 0x37, 0xe3, + 0xa1, 0x59, 0xb2, 0xef, 0x63, 0x9e, 0xfc, 0x71, 0x3b, 0xa7, 0xd6, + 0x35, 0x23, 0xca, 0x2b, 0xe9, 0x7c, 0x7e, 0x15, 0xd3, 0xcf, 0x1d, + 0xc1, 0x7e, 0x38, 0xc0, 0x84, 0xae, 0x2b, 0xcc, 0x3e, 0xb6, 0x97, + 0xd6, 0xcd, 0x3b, 0xe8, 0x9d, 0x3e, 0x97, 0xc2, 0xbe, 0x07, 0xb8, + 0xe1, 0x08, 0x3f, 0x2f, 0xdb, 0xca, 0xed, 0x99, 0xcf, 0x62, 0x5b, + 0x9a, 0x34, 0xce, 0x23, 0xc6, 0x8f, 0xc5, 0x06, 0x64, 0x2e, 0x4c, + 0xc8, 0x8c, 0xc0, 0xb4, 0x4b, 0xc7, 0xd8, 0xb2, 0xa2, 0x8e, 0xfe, + 0x14, 0x26, 0x74, 0xb4, 0x33, 0x52, 0x36, 0x8e, 0xee, 0xba, 0x46, + 0x3a, 0xa6, 0xcc, 0x67, 0xa0, 0xbc, 0x86, 0xd1, 0xfd, 0x77, 0xc8, + 0x86, 0x29, 0x99, 0x1c, 0x9c, 0x5e, 0xbe, 0x15, 0x19, 0x87, 0x4c, + 0x39, 0xde, 0xc2, 0xc2, 0x1d, 0x6f, 0xd1, 0xfe, 0xda, 0x07, 0x5c, + 0x9d, 0xbb, 0x94, 0xa1, 0x4c, 0x44, 0x41, 0x38, 0xc8, 0xa8, 0xe1, + 0xfb, 0x9c, 0x99, 0xb7, 0x92, 0x9e, 0xda, 0xe9, 0xdc, 0xad, 0x99, + 0x41, 0xf7, 0xc4, 0xc7, 0xe9, 0x0d, 0xca, 0xc9, 0x47, 0x06, 0xdb, + 0x71, 0x7d, 0x32, 0x89, 0xa0, 0xec, 0xf2, 0x05, 0x6e, 0x34, 0x2e, + 0xc5, 0x0c, 0x19, 0x4a, 0xfe, 0xbe, 0x41, 0xcf, 0xd4, 0x46, 0xa2, + 0xb2, 0xd1, 0x54, 0x5d, 0x3c, 0xc7, 0x98, 0x9e, 0x2e, 0xce, 0x2f, + 0x5a, 0x4b, 0xa4, 0xc0, 0xa8, 0x98, 0xa2, 0xd1, 0x2e, 0xc7, 0x57, + 0x7f, 0xc1, 0x4b, 0xdf, 0xbc, 0xcd, 0xd5, 0x05, 0xcb, 0xb9, 0xd4, + 0xb4, 0x86, 0x28, 0x93, 0x25, 0x36, 0x1e, 0xc5, 0x37, 0xaf, 0xa0, + 0x2d, 0x8b, 0x95, 0x2d, 0x9b, 0xb1, 0x45, 0x8a, 0x30, 0x86, 0x7b, + 0x15, 0xb5, 0xb4, 0xbe, 0xde, 0x4c, 0x41, 0x62, 0xb0, 0xb5, 0x11, + 0x64, 0x14, 0x54, 0x5f, 0x3b, 0x4b, 0xe7, 0xc2, 0x95, 0xf8, 0x0f, + 0x07, 0x71, 0xf2, 0x19, 0xea, 0xdb, 0xf6, 0x33, 0xe7, 0xc4, 0x1e, + 0xa2, 0x82, 0x62, 0xfe, 0xaa, 0xaa, 0xa7, 0x6d, 0xc9, 0x46, 0x44, + 0xa8, 0xc9, 0xc5, 0x20, 0x0b, 0xc0, 0xef, 0xef, 0x45, 0x0a, 0xe8, + 0x2f, 0x7d, 0x84, 0x10, 0x09, 0x32, 0x20, 0x13, 0x0b, 0x2a, 0x2f, + 0xb4, 0x31, 0x5c, 0x52, 0x09, 0x46, 0x13, 0xa7, 0x06, 0xcf, 0x86, + 0xfe, 0xa2, 0x0a, 0x54, 0xac, 0xc9, 0x03, 0x76, 0x9c, 0x08, 0xac, + 0x38, 0xa5, 0xb2, 0xf7, 0x0f, 0x5a, 0xab, 0xe7, 0x50, 0x38, 0xf2, + 0x80, 0x92, 0xfe, 0x6e, 0x5a, 0xb6, 0x1c, 0x02, 0xd7, 0x62, 0xd8, + 0x04, 0xfc, 0x69, 0x8f, 0xc5, 0x1e, 0xd6, 0xf8, 0xae, 0x44, 0x49, + 0x97, 0xaa, 0xd3, 0x27, 0x59, 0x74, 0x78, 0x3b, 0x17, 0x67, 0xbd, + 0x48, 0x43, 0xdb, 0x3e, 0xce, 0xcc, 0x5d, 0x8e, 0xa8, 0x28, 0xc5, + 0xb8, 0x82, 0xfa, 0x6b, 0x6d, 0x1c, 0x58, 0xbb, 0x93, 0x8b, 0x33, + 0x9a, 0x78, 0xf8, 0x20, 0xa6, 0xba, 0xca, 0x25, 0x8d, 0xc0, 0x89, + 0x14, 0xd9, 0x44, 0x21, 0x35, 0x30, 0xb5, 0xaf, 0x83, 0x9c, 0x5f, + 0x4c, 0x0f, 0xe5, 0x4c, 0xe8, 0xfa, 0x9d, 0xc1, 0xb2, 0x89, 0xdc, + 0x9c, 0x54, 0xcf, 0x3f, 0xe3, 0x1f, 0x63, 0xb0, 0xa2, 0x16, 0xdb, + 0x2f, 0x24, 0x0c, 0x15, 0xd9, 0x9c, 0xa6, 0x78, 0xb0, 0x8f, 0x97, + 0x0f, 0x7f, 0xc2, 0x8d, 0xba, 0xa7, 0xd8, 0xb3, 0xe2, 0x6b, 0xac, + 0x24, 0x66, 0xda, 0xaf, 0x07, 0x19, 0x88, 0x04, 0x95, 0x77, 0x6e, + 0x63, 0xe9, 0x94, 0x2b, 0xfe, 0x14, 0xa2, 0x08, 0x62, 0x63, 0xb8, + 0xdb, 0x17, 0xe2, 0xf9, 0x90, 0x1a, 0x8b, 0x30, 0x9f, 0x60, 0x47, + 0x06, 0x26, 0x75, 0x9d, 0x27, 0x5b, 0x58, 0x46, 0x7f, 0x30, 0x86, + 0x49, 0x1d, 0xbf, 0x70, 0x7d, 0xc6, 0x73, 0xc4, 0x31, 0x48, 0x23, + 0x40, 0x18, 0x3c, 0x4b, 0xa2, 0x8c, 0x21, 0x8b, 0x64, 0xd3, 0x81, + 0x77, 0xc0, 0x18, 0xbe, 0x7d, 0x65, 0x17, 0x8e, 0x80, 0xef, 0x9a, + 0x3e, 0x64, 0xfd, 0x4f, 0xef, 0xd3, 0xd6, 0xb0, 0x82, 0xc9, 0xd7, + 0x4f, 0xa1, 0x2d, 0x9b, 0x0d, 0x07, 0xdf, 0xc5, 0x38, 0x1e, 0xda, + 0x68, 0x4c, 0x9a, 0x72, 0x74, 0xc3, 0x97, 0x0c, 0x16, 0x56, 0xa3, + 0x22, 0x89, 0x0c, 0x55, 0x8c, 0x9f, 0x19, 0xe0, 0x56, 0x6d, 0x23, + 0x19, 0xcf, 0xc1, 0xc9, 0x0c, 0x71, 0x69, 0xe6, 0x12, 0x12, 0x05, + 0xa1, 0x02, 0xa5, 0x04, 0xc2, 0x18, 0x1c, 0xd7, 0xa5, 0xe9, 0xb7, + 0xef, 0xb1, 0x13, 0xc5, 0xae, 0x57, 0x77, 0x13, 0x5a, 0x2e, 0x69, + 0x62, 0xb8, 0xfc, 0xe8, 0x02, 0x3a, 0x6a, 0x9e, 0xe6, 0x99, 0xd3, + 0x2d, 0x04, 0xf7, 0xfb, 0xe8, 0xae, 0x99, 0x85, 0xb2, 0x1d, 0x42, + 0xa5, 0x10, 0x52, 0x10, 0xd9, 0x3e, 0xf7, 0x43, 0x17, 0x3b, 0x90, + 0xd8, 0x9e, 0x8f, 0x58, 0xff, 0x43, 0xc6, 0x38, 0xc1, 0x28, 0x3c, + 0x0f, 0xa2, 0x61, 0x43, 0x2e, 0x85, 0xc2, 0x40, 0xe0, 0x59, 0x06, + 0xc1, 0x7f, 0xd9, 0xff, 0x46, 0x5a, 0x90, 0x4f, 0xc1, 0x28, 0x83, + 0x11, 0x60, 0x10, 0x24, 0x1a, 0x06, 0x43, 0x43, 0x3e, 0x9f, 0xa3, + 0xa0, 0xb4, 0x90, 0x31, 0xe3, 0x20, 0x1f, 0x43, 0x67, 0xe7, 0x3d, + 0x6a, 0x6b, 0x2b, 0x50, 0x0a, 0xc8, 0x85, 0xd4, 0x57, 0xf9, 0x88, + 0xc4, 0xf0, 0x2f, 0xb4, 0x16, 0xf4, 0xd5, 0x82, 0x00, 0xa9, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, + 0x82 ), + 28, 12, + DATA ( 0x90c4fe, 0x91c3fb, 0x98c5fb, 0x9eceff, 0x9bccff, 0x97c6fa, + 0x92c2f8, 0x98c9fe, 0x97caff, 0x93c6fd, 0x9dceff, 0x9fcdff, + 0xa0ccfd, 0xaad4fe, 0xacd2ff, 0xa1cafe, 0x9dc9fe, 0xa1d0fe, + 0xa2d3fe, 0x94c8f9, 0x8abff7, 0x88befd, 0x8ec1ff, 0x8bbdfa, + 0x8ec1f5, 0xa0d3fe, 0x9fd0fc, 0x98c9fe, 0x8fc5ff, 0x8ec1f9, + 0x91c6fc, 0xd4697c, 0xd4697b, 0x98ccff, 0x88ccff, 0x8aceff, + 0x8ed4ff, 0x8dccff, 0x95c9fd, 0x9ed0ff, 0x9acbfd, 0xa1ddff, + 0xa9ddff, 0xa1cbfd, 0x9cc7fb, 0x97cefe, 0x9addff, 0x97d0ff, + 0x8bbff9, 0x7ec1ff, 0x84c8ff, 0x87caff, 0x7fc2ff, 0x93d6ff, + 0x9cdbff, 0x9acbfe, 0x89c1fe, 0x8fc5fe, 0x8fc7fe, 0xd0677a, + 0xd36a7d, 0x9dc2f3, 0xff1c15, 0xfd231e, 0xf82624, 0xd85a69, + 0x92baef, 0x97cbff, 0xa4b9e6, 0xf32d2c, 0xda6372, 0xa1cfff, + 0x99c9fb, 0xc97085, 0xf92623, 0xada5ca, 0x8bc1fb, 0xe74047, + 0xfd251f, 0xfd231d, 0xfe241e, 0xfd211c, 0xe0535d, 0x99d2ff, + 0x81baf9, 0x8fc7fe, 0x8dc7ff, 0x84cfff, 0x98d1ff, 0xbb90ae, + 0xef3538, 0xa294bd, 0xa994bb, 0xf03739, 0xc9647a, 0x8bc6ff, + 0x98ceff, 0xc86f86, 0xf03739, 0xa5c0ed, 0xb39dc1, 0xf92723, + 0xaf93b2, 0x95cdff, 0x96b6eb, 0xed383c, 0xba7498, 0x9b9fd7, + 0x9fa2d5, 0x9c9ccc, 0x9db4e0, 0x9dd2ff, 0x77b2f5, 0x82bcfe, + 0xb496b6, 0xfa2622, 0x85ceff, 0xd56272, 0xe4474f, 0x85b7f0, + 0x7bb9f7, 0xde4c58, 0xd8515e, 0x7fbefc, 0x8bc4ff, 0x8bc4ff, + 0xf23131, 0xca788f, 0xf42c2b, 0xbd829d, 0x85c8fa, 0x85c0f8, + 0xa0aeda, 0xf92a27, 0x80aaf0, 0x82c0ff, 0x84c1ff, 0x7fbafb, + 0x85bdf5, 0x94cbfe, 0x7cb8fd, 0x75b8ff, 0xc66982, 0xd5596a, + 0x84befe, 0xe5444d, 0xcc6a80, 0x7ec9ff, 0x9797c7, 0xf13335, + 0xbb7796, 0x78b9fc, 0x7eb9f9, 0x8bc8ff, 0xaa90ba, 0xf72a28, + 0xcd677d, 0x8cc5fd, 0x7ebbf1, 0x78baf8, 0xae8aae, 0xf72d2a, + 0xd84c5d, 0xdc4d5a, 0xdd4c59, 0xc7627a, 0x7dbeff, 0x8fc7fe, + 0x7ab7fe, 0x68b2ff, 0xe34049, 0xb881a1, 0x8cafed, 0xea3b40, + 0xf92926, 0xfd231d, 0xf62d2b, 0xd54958, 0x7abeff, 0x79b6fd, + 0x74b0f9, 0x80c3ff, 0xb27da2, 0xf92b28, 0xba7898, 0x84c5ff, + 0x7ebdfa, 0x6bb7fb, 0xc7566d, 0xe93d43, 0xd84b5b, 0xd64959, + 0xdd4d59, 0xb46f90, 0x78b8fd, 0x86befd, 0x74b3ff, 0x6bacfc, + 0xfc2823, 0x999ed2, 0x97a4d9, 0xfa2823, 0x9c9ed2, 0x9ca4d5, + 0x8ea3de, 0x6ca7f2, 0x70b0fd, 0x78b6ff, 0x6fb2ff, 0x9c86b9, + 0xf62e2d, 0xc75771, 0xec373b, 0x80aded, 0x7fc3fe, 0x6ac3ff, + 0xf42d2c, 0x9b8ebc, 0x69b8ff, 0x5aa4f9, 0x77c0ff, 0x74b9ff, + 0x79b2fa, 0x7ab4f5, 0x72b3ff, 0x9195ce, 0xf23031, 0x809ee7, + 0xb181a6, 0xe93a41, 0x78beff, 0x82bcfe, 0x7db9ff, 0x70affd, + 0x68a8f8, 0x6cacfd, 0x7da1e8, 0xec373b, 0xd15165, 0x64aeff, + 0xef3335, 0xa7729b, 0x6dbcff, 0x83a7e0, 0xf72b29, 0x6f96e1, + 0x62b1ff, 0x54a3f8, 0x5ca9f7, 0x7bc1ff, 0x76b1fd, 0x72abf1, + 0x6bb2ff, 0xb17298, 0xe63b43, 0x6da7fa, 0xd15367, 0xc16481, + 0x72b8ff, 0x7ab7ff, 0x7ab8fe, 0x77b2ff, 0x6ba7f7, 0x60acff, + 0xd84858, 0xec363a, 0x6da7f9, 0x69afff, 0x9476b0, 0xf92b28, + 0x66a4f2, 0xa57ca2, 0xf52e2d, 0xd64454, 0xd5495b, 0xd34859, + 0xd24556, 0x86ace0, 0x75b7fd, 0x6daaf3, 0x63adf9, 0xb96586, + 0xc65c76, 0x60aeff, 0xd64657, 0x908fc8, 0x6eb3ff, 0x72b2ff, + 0x75b3ff, 0x78b1fe, 0x70adfd, 0xa377a7, 0xdc4453, 0x808fd5, + 0x65aaff, 0x66abfe, 0x679aed, 0xcb4a61, 0xa16794, 0xae678b, + 0xd84d59, 0xd14859, 0xcd4456, 0xd44a5a, 0xcb495e, 0x71a4e6, + 0x79c0ff, 0x71b1fb, 0x65a9f3, 0x6ab2ff, 0x71b9ff, 0x6aabfe, + 0x60a8fe, 0x6bb1ff, 0x72b4fe, 0x73b4ff, 0x74b3fe, 0x75b3ff, + 0x76b2fe, 0x6fb0ff, 0x66adff, 0x65a8fe, 0x64a9fe, 0x63a9ff, + 0x5fa7ff, 0x4e9ffe, 0x4596f4, 0x4fa7ff, 0x62beff, 0x59b8ff, + 0x2e8de9, 0x4faeff, 0x4aa9ff, 0x4a9ff7, 0x77bbff, 0x78b7fe ) ); + +/** + * Perform PNG self-test + * + */ +static void png_test_exec ( void ) { + + /* Original image */ + pixbuf_ok ( &original ); + + /* All allowed colour type and bit depth combinations */ + pixbuf_ok ( &ctype_0_1 ); + pixbuf_ok ( &ctype_0_2 ); + pixbuf_ok ( &ctype_0_4 ); + pixbuf_ok ( &ctype_0_8 ); + pixbuf_ok ( &ctype_0_16 ); + pixbuf_ok ( &ctype_2_8 ); + pixbuf_ok ( &ctype_2_16 ); + pixbuf_ok ( &ctype_3_1 ); + pixbuf_ok ( &ctype_3_2 ); + pixbuf_ok ( &ctype_3_4 ); + pixbuf_ok ( &ctype_3_8 ); + pixbuf_ok ( &ctype_4_8 ); + pixbuf_ok ( &ctype_4_16 ); + pixbuf_ok ( &ctype_6_8 ); + pixbuf_ok ( &ctype_6_16 ); + + /* All basic filter types */ + pixbuf_ok ( &filter_0 ); + pixbuf_ok ( &filter_1 ); + pixbuf_ok ( &filter_2 ); + pixbuf_ok ( &filter_3 ); + pixbuf_ok ( &filter_4 ); + + /* Multiple IDAT sections */ + pixbuf_ok ( &multi_idat ); + + /* Interlaced */ + pixbuf_ok ( &interlaced ); + pixbuf_ok ( &interlaced_w1 ); + pixbuf_ok ( &interlaced_w2 ); + pixbuf_ok ( &interlaced_w3 ); + pixbuf_ok ( &interlaced_w4 ); + pixbuf_ok ( &interlaced_h1 ); + pixbuf_ok ( &interlaced_h2 ); + pixbuf_ok ( &interlaced_h3 ); + pixbuf_ok ( &interlaced_h4 ); + + /* Alpha channel */ + pixbuf_ok ( &alpha ); +} + +/** PNG self-test */ +struct self_test png_test __self_test = { + .name = "png", + .exec = png_test_exec, +}; | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/pnm_test.c ^ |
@@ -33,44 +33,13 @@ #include <ipxe/pixbuf.h> #include <ipxe/pnm.h> #include <ipxe/test.h> +#include "pixbuf_test.h" /** Define inline pixel data */ #define DATA(...) { __VA_ARGS__ } -/** A PNM test */ -struct pnm_test { - /** Source image */ - struct image *image; - /** Pixel data */ - const uint32_t *data; - /** Length of pixel data */ - size_t len; - /** Width */ - unsigned int width; - /** Height */ - unsigned int height; -}; - -/** Define a PNM test */ -#define PNM( NAME, FILE, WIDTH, HEIGHT, DATA ) \ - static const char NAME ## _file[] = FILE; \ - static const uint32_t NAME ## _data[] = DATA; \ - static struct image NAME ## _image = { \ - .refcnt = REF_INIT ( ref_no_free ), \ - .name = #NAME, \ - .data = ( userptr_t ) ( NAME ## _file ), \ - .len = sizeof ( NAME ## _file ), \ - }; \ - static struct pnm_test NAME = { \ - .image = & NAME ## _image, \ - .data = NAME ## _data, \ - .len = sizeof ( NAME ## _data ), \ - .width = WIDTH, \ - .height = HEIGHT, \ - }; - /** PBM ASCII example (from Wikipedia) */ -PNM ( pbm_ascii, +PIX ( pbm_ascii, &pnm_image_type, "P1\n" "# This is an example bitmap of the letter \"J\"\n" "6 10\n" @@ -97,7 +66,7 @@ 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff ) ); /** PGM ASCII example (from Wikipedia) */ -PNM ( pgm_ascii, +PIX ( pgm_ascii, &pnm_image_type, "P2\n" "# Shows the word \"FEEP\" (example from Netpbm man page on PGM)\n" "24 7\n" @@ -140,7 +109,7 @@ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000 ) ); /** PPM ASCII example (from Wikipedia) */ -PNM ( ppm_ascii, +PIX ( ppm_ascii, &pnm_image_type, "P3\n" "# The P3 means colors are in ASCII, then 3 columns and 2 rows,\n" "# then 255 for max color, then RGB triplets\n" @@ -152,7 +121,7 @@ DATA ( 0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xffffff, 0x000000 ) ); /** PBM ASCII with no space between pixel values */ -PNM ( pbm_ascii_no_space, +PIX ( pbm_ascii_no_space, &pnm_image_type, "P1\n" "3 3\n" "001\n" @@ -163,7 +132,7 @@ 0x000000, 0x000000, 0x000000 ) ); /** PBM binary example (converted from Wikipedia) */ -PNM ( pbm_binary, +PIX ( pbm_binary, &pnm_image_type, DATA ( 0x50, 0x34, 0x0a, 0x23, 0x20, 0x43, 0x52, 0x45, 0x41, 0x54, 0x4f, 0x52, 0x3a, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x20, 0x50, 0x4e, 0x4d, 0x20, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x56, 0x65, 0x72, @@ -183,7 +152,7 @@ 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff ) ); /** PGM binary example (converted from Wikipedia) */ -PNM ( pgm_binary, +PIX ( pgm_binary, &pnm_image_type, DATA ( 0x50, 0x35, 0x0a, 0x32, 0x34, 0x20, 0x37, 0x0a, 0x31, 0x35, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -232,7 +201,7 @@ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000 ) ); /** PPM binary example (converted from Wikipedia) */ -PNM ( ppm_binary, +PIX ( ppm_binary, &pnm_image_type, DATA ( 0x50, 0x36, 0x0a, 0x33, 0x20, 0x32, 0x0a, 0x32, 0x35, 0x35, 0x0a, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00 ), @@ -240,53 +209,18 @@ DATA ( 0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xffffff, 0x000000 ) ); /** - * Report PNM test result - * - * @v test PNM test - */ -#define pnm_ok( test ) do { \ - struct pixel_buffer *pixbuf; \ - uint8_t data[ (test)->len ]; \ - int rc; \ - \ - /* Sanity check */ \ - assert ( ( (test)->width * (test)->height * \ - sizeof ( (test)->data[0] ) ) == (test)->len ); \ - \ - /* Correct image data pointer */ \ - (test)->image->data = \ - virt_to_user ( ( void * ) (test)->image->data ); \ - \ - /* Perform tests */ \ - ok ( image_probe ( (test)->image ) == 0 ); \ - ok ( (test)->image->type == &pnm_image_type ); \ - ok ( ( rc = image_pixbuf ( (test)->image, &pixbuf ) ) == 0 ); \ - if ( rc == 0 ) { \ - ok ( pixbuf->width == (test)->width ); \ - ok ( pixbuf->height == (test)->height ); \ - ok ( pixbuf->len == (test)->len ); \ - copy_from_user ( data, pixbuf->data, 0, \ - sizeof ( data ) ); \ - ok ( memcmp ( data, (test)->data, \ - sizeof ( data ) ) == 0 ); \ - DBGC_HDA ( (test)->image, 0, data, sizeof ( data ) ); \ - pixbuf_put ( pixbuf ); \ - } \ - } while ( 0 ) - -/** * Perform PNM self-test * */ static void pnm_test_exec ( void ) { - pnm_ok ( &pbm_ascii ); - pnm_ok ( &pgm_ascii ); - pnm_ok ( &ppm_ascii ); - pnm_ok ( &pbm_ascii_no_space ); - pnm_ok ( &pbm_binary ); - pnm_ok ( &pgm_binary ); - pnm_ok ( &ppm_binary ); + pixbuf_ok ( &pbm_ascii ); + pixbuf_ok ( &pgm_ascii ); + pixbuf_ok ( &ppm_ascii ); + pixbuf_ok ( &pbm_ascii_no_space ); + pixbuf_ok ( &pbm_binary ); + pixbuf_ok ( &pgm_binary ); + pixbuf_ok ( &ppm_binary ); } /** PNM self-test */ | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/settings_test.c ^ |
@@ -162,12 +162,6 @@ .type = &setting_type_string, }; -/** Test URI-encoded string setting */ -static struct setting test_uristring_setting = { - .name = "test_uristring", - .type = &setting_type_uristring, -}; - /** Test IPv4 address setting type */ static struct setting test_ipv4_setting = { .name = "test_ipv4", @@ -261,13 +255,6 @@ fetchf_ok ( &test_settings, &test_string_setting, RAW ( 'w', 'o', 'r', 'l', 'd' ), "world" ); - /* "uristring" setting type */ - storef_ok ( &test_settings, &test_uristring_setting, "hello%20world", - RAW ( 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', - 'd' ) ); - fetchf_ok ( &test_settings, &test_uristring_setting, - RAW ( 1, 2, 3, 4, 5 ), "%01%02%03%04%05" ); - /* "ipv4" setting type */ storef_ok ( &test_settings, &test_ipv4_setting, "192.168.0.1", RAW ( 192, 168, 0, 1 ) ); | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/tests.c ^ |
@@ -50,3 +50,7 @@ REQUIRE_OBJECT ( ocsp_test ); REQUIRE_OBJECT ( cms_test ); REQUIRE_OBJECT ( pnm_test ); +REQUIRE_OBJECT ( deflate_test ); +REQUIRE_OBJECT ( png_test ); +REQUIRE_OBJECT ( dns_test ); +REQUIRE_OBJECT ( uri_test ); | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/uri_test.c ^ |
@@ -1,146 +1,858 @@ -#include <stdint.h> -#include <stddef.h> -#include <stdio.h> +/* + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * URI self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + #include <string.h> -#include <errno.h> +#include <byteswap.h> #include <ipxe/uri.h> +#include <ipxe/params.h> +#include <ipxe/test.h> -#define URI_MAX_LEN 1024 - +/** A URI parsing/formatting test */ struct uri_test { - const char *base_uri_string; - const char *relative_uri_string; - const char *resolved_uri_string; -}; - -static struct uri_test uri_tests[] = { - { "http://www.fensystems.co.uk", "", - "http://www.fensystems.co.uk/" }, - { "http://ipxe.org/wiki/page1", "page2", - "http://ipxe.org/wiki/page2" }, - { "http://ipxe.org/wiki/page1", "../page3", - "http://ipxe.org/page3" }, - { "tftp://192.168.0.1/", "/tftpboot/vmlinuz", - "tftp://192.168.0.1/tftpboot/vmlinuz" }, - { "ftp://the%41nswer%3d:%34ty%32wo@ether%62oot.org:8080/p%41th/foo", - "to?%41=b#%43d", - "ftp://theAnswer%3d:4ty2wo@ipxe.org:8080/path/to?a=b#cd" }, -#if 0 - "http://www.ipxe.org/wiki", - "mailto:bob@nowhere.com", - "ftp://joe:secret@insecure.org:8081/hidden/path/to?what=is#this", -#endif -}; - -static int test_parse_unparse ( const char *uri_string ) { - char buf[URI_MAX_LEN]; - struct uri *uri = NULL; - int rc; - - /* Parse and unparse URI */ - uri = parse_uri ( uri_string ); - if ( ! uri ) { - rc = -ENOMEM; - goto done; - } - unparse_uri ( buf, sizeof ( buf ), uri, URI_ALL ); - - /* Compare result */ - if ( strcmp ( buf, uri_string ) != 0 ) { - printf ( "Unparse of \"%s\" produced \"%s\"\n", - uri_string, buf ); - rc = -EINVAL; - goto done; + /** URI string */ + const char *string; + /** URI */ + struct uri uri; +}; + +/** A URI port number test */ +struct uri_port_test { + /** URI string */ + const char *string; + /** Default port number */ + unsigned int default_port; + /** Expected port number */ + unsigned int port; +}; + +/** A URI or path resolution test */ +struct uri_resolve_test { + /** Base path or URI */ + const char *base; + /** Relative path or URI */ + const char *relative; + /** Expected resolved path or URI */ + const char *resolved; +}; + +/** A TFTP URI test */ +struct uri_tftp_test { + /** Next-server address */ + struct in_addr next_server; + /** Filename */ + const char *filename; + /** URI */ + struct uri uri; + /** URI string (for display only; cannot be reparsed) */ + const char *string; +}; + +/** A current working URI test */ +struct uri_churi_test { + /** Relative URI */ + const char *relative; + /** Expected new working URI */ + const char *expected; +}; + +/** A form parameter URI test list */ +struct uri_params_test_list { + /** Key */ + const char *key; + /** Value */ + const char *value; +}; + +/** A form parameter URI test */ +struct uri_params_test { + /** URI string */ + const char *string; + /** URI */ + struct uri uri; + /** Parameter list name */ + const char *name; + /** Parameter list */ + struct uri_params_test_list *list; +}; + +/** + * Compare two URI component strings + * + * @v first First string, or NULL + * @v second Second string, or NULL + * @v difference Difference + */ +static int uristrcmp ( const char *first, const char *second ) { + + /* Compare strings, allowing for either to be NULL */ + if ( first == second ) { + return 0; + } else if ( ( first == NULL ) || ( second == NULL ) ) { + return -1; + } else { + return strcmp ( first, second ); } +} - rc = 0; +/** + * Report URI equality test result + * + * @v uri URI + * @v expected Expected URI + * @v file Test code file + * @v line Test code line + */ +static void uri_okx ( struct uri *uri, struct uri *expected, const char *file, + unsigned int line ) { + + okx ( uristrcmp ( uri->scheme, expected->scheme ) == 0, file, line ); + okx ( uristrcmp ( uri->opaque, expected->opaque ) == 0, file, line ); + okx ( uristrcmp ( uri->user, expected->user ) == 0, file, line ); + okx ( uristrcmp ( uri->password, expected->password ) == 0, file, line); + okx ( uristrcmp ( uri->host, expected->host ) == 0, file, line ); + okx ( uristrcmp ( uri->port, expected->port ) == 0, file, line ); + okx ( uristrcmp ( uri->path, expected->path ) == 0, file, line ); + okx ( uristrcmp ( uri->query, expected->query ) == 0, file, line ); + okx ( uristrcmp ( uri->fragment, expected->fragment ) == 0, file, line); + okx ( uri->params == expected->params, file, line ); +} +#define uri_ok( uri, expected ) uri_okx ( uri, expected, __FILE__, __LINE__ ) - done: +/** + * Report URI parsing test result + * + * @v test URI test + * @v file Test code file + * @v line Test code line + */ +static void uri_parse_okx ( struct uri_test *test, const char *file, + unsigned int line ) { + struct uri *uri; + + /* Parse URI */ + uri = parse_uri ( test->string ); + okx ( uri != NULL, file, line ); + if ( uri ) + uri_okx ( uri, &test->uri, file, line ); uri_put ( uri ); - if ( rc ) { - printf ( "URI parse-unparse of \"%s\" failed: %s\n", - uri_string, strerror ( rc ) ); - } - return rc; } +#define uri_parse_ok( test ) uri_parse_okx ( test, __FILE__, __LINE__ ) -static int test_resolve ( const char *base_uri_string, - const char *relative_uri_string, - const char *resolved_uri_string ) { - struct uri *base_uri = NULL; - struct uri *relative_uri = NULL; - struct uri *resolved_uri = NULL; - char buf[URI_MAX_LEN]; - int rc; +/** + * Report URI formatting test result + * + * @v test URI test + * @v file Test code file + * @v line Test code line + */ +static void uri_format_okx ( struct uri_test *test, const char *file, + unsigned int line ) { + char buf[ strlen ( test->string ) + 1 /* NUL */ ]; + char *tmp; + size_t len; + + /* Format into fixed-size buffer */ + len = format_uri ( &test->uri, buf, sizeof ( buf ) ); + okx ( len == ( sizeof ( buf ) - 1 /* NUL */ ), file, line ); + okx ( strcmp ( buf, test->string ) == 0, file, line ); + + /* Format into temporarily allocated buffer */ + tmp = format_uri_alloc ( &test->uri ); + okx ( tmp != NULL, file, line ); + if ( tmp ) + okx ( strcmp ( tmp, test->string ) == 0, file, line ); + free ( tmp ); +} +#define uri_format_ok( test ) uri_format_okx ( test, __FILE__, __LINE__ ) + +/** + * Report URI duplication test result + * + * @v test URI + * @v file Test code file + * @v line Test code line + */ +static void uri_dup_okx ( struct uri *uri, const char *file, + unsigned int line ) { + struct uri *dup; + + dup = uri_dup ( uri ); + okx ( dup != NULL, file, line ); + if ( dup ) + uri_okx ( dup, uri, file, line ); + uri_put ( dup ); +} +#define uri_dup_ok( test ) uri_dup_okx ( test, __FILE__, __LINE__ ) + +/** + * Report URI combined parsing and formatting test result + * + * @v test URI test + * @v file Test code file + * @v line Test code line + */ +static void uri_parse_format_dup_okx ( struct uri_test *test, const char *file, + unsigned int line ) { + + uri_parse_okx ( test, file, line ); + uri_format_okx ( test, file, line ); + uri_dup_okx ( &test->uri, file, line ); +} +#define uri_parse_format_dup_ok( test ) \ + uri_parse_format_dup_okx ( test, __FILE__, __LINE__ ) + +/** + * Report URI port number test result + * + * @v test URI port number test + * @v file Test code file + * @v line Test code line + */ +static void uri_port_okx ( struct uri_port_test *test, const char *file, + unsigned int line ) { + struct uri *uri; + unsigned int port; + + /* Parse URI */ + uri = parse_uri ( test->string ); + okx ( uri != NULL, file, line ); + if ( uri ) { + port = uri_port ( uri, test->default_port ); + okx ( port == test->port, file, line ); + } + uri_put ( uri ); +} +#define uri_port_ok( test ) uri_port_okx ( test, __FILE__, __LINE__ ) + +/** + * Report URI resolution test result + * + * @v test Path resolution test + * @v file Test code file + * @v line Test code line + */ +static void uri_resolve_okx ( struct uri_resolve_test *test, + const char *file, unsigned int line ) { + struct uri *base; + struct uri *relative; + struct uri *resolved = NULL; + char *formatted; /* Parse URIs */ - base_uri = parse_uri ( base_uri_string ); - if ( ! base_uri ) { - rc = -ENOMEM; - goto done; - } - relative_uri = parse_uri ( relative_uri_string ); - if ( ! relative_uri ) { - rc = -ENOMEM; - goto done; - } - - /* Resolve URI */ - resolved_uri = resolve_uri ( base_uri, relative_uri ); - if ( ! resolved_uri ) { - rc = -ENOMEM; - goto done; - } - - /* Compare result */ - unparse_uri ( buf, sizeof ( buf ), resolved_uri, URI_ALL ); - if ( strcmp ( buf, resolved_uri_string ) != 0 ) { - printf ( "Resolution of \"%s\"+\"%s\" produced \"%s\"\n", - base_uri_string, relative_uri_string, buf ); - rc = -EINVAL; - goto done; - } - - rc = 0; - - done: - uri_put ( base_uri ); - uri_put ( relative_uri ); - uri_put ( resolved_uri ); - if ( rc ) { - printf ( "URI resolution of \"%s\"+\"%s\" failed: %s\n", - base_uri_string, relative_uri_string, - strerror ( rc ) ); - } - return rc; -} - -int uri_test ( void ) { - unsigned int i; - struct uri_test *uri_test; - int rc; - int overall_rc = 0; - - for ( i = 0 ; i < ( sizeof ( uri_tests ) / - sizeof ( uri_tests[0] ) ) ; i++ ) { - uri_test = &uri_tests[i]; - rc = test_parse_unparse ( uri_test->base_uri_string ); - if ( rc != 0 ) - overall_rc = rc; - rc = test_parse_unparse ( uri_test->relative_uri_string ); - if ( rc != 0 ) - overall_rc = rc; - rc = test_parse_unparse ( uri_test->resolved_uri_string ); - if ( rc != 0 ) - overall_rc = rc; - rc = test_resolve ( uri_test->base_uri_string, - uri_test->relative_uri_string, - uri_test->resolved_uri_string ); - if ( rc != 0 ) - overall_rc = rc; - } - - if ( overall_rc ) - printf ( "URI tests failed: %s\n", strerror ( overall_rc ) ); - return overall_rc; + base = parse_uri ( test->base ); + okx ( base != NULL, file, line ); + relative = parse_uri ( test->relative ); + okx ( relative != NULL, file, line ); + + /* Resolve URI */ + if ( base && relative ) { + resolved = resolve_uri ( base, relative ); + okx ( resolved != NULL, file, line ); + } + + /* Format resolved URI */ + formatted = format_uri_alloc ( resolved ); + okx ( formatted != NULL, file, line ); + + /* Check resolved URI */ + if ( formatted ) + okx ( strcmp ( formatted, test->resolved ) == 0, file, line ); + + free ( formatted ); + uri_put ( resolved ); + uri_put ( relative ); + uri_put ( base ); +} +#define uri_resolve_ok( test ) uri_resolve_okx ( test, __FILE__, __LINE__ ) + +/** + * Report path resolution test result + * + * @v test Path resolution test + * @v file Test code file + * @v line Test code line + */ +static void uri_resolve_path_okx ( struct uri_resolve_test *test, + const char *file, unsigned int line ) { + char *resolved; + + /* Resolve paths using resolve_path() directly */ + resolved = resolve_path ( test->base, test->relative ); + okx ( resolved != NULL, file, line ); + if ( resolved ) + okx ( strcmp ( resolved, test->resolved ) == 0, file, line ); + free ( resolved ); + + /* Resolve paths as URIs (since all paths are valid URIs) */ + uri_resolve_okx ( test, file, line ); +} +#define uri_resolve_path_ok( test ) \ + uri_resolve_path_okx ( test, __FILE__, __LINE__ ) + +/** + * Report URI TFTP test result + * + * @v test URI TFTP test + * @v file Test code file + * @v line Test code line + */ +static void uri_tftp_okx ( struct uri_tftp_test *test, const char *file, + unsigned int line ) { + char buf[ strlen ( test->string ) + 1 /* NUL */ ]; + struct uri *uri; + size_t len; + + /* Construct URI */ + uri = tftp_uri ( test->next_server, test->filename ); + okx ( uri != NULL, file, line ); + if ( uri ) { + uri_okx ( uri, &test->uri, file, line ); + len = format_uri ( uri, buf, sizeof ( buf ) ); + okx ( len == ( sizeof ( buf ) - 1 /* NUL */ ), file, line ); + okx ( strcmp ( buf, test->string ) == 0, file, line ); + } + uri_put ( uri ); +} +#define uri_tftp_ok( test ) uri_tftp_okx ( test, __FILE__, __LINE__ ) + +/** + * Report current working URI test result + * + * @v tests List of current working URI tests + * @v file Test code file + * @v line Test code line + */ +static void uri_churi_okx ( struct uri_churi_test *test, const char *file, + unsigned int line ) { + struct uri *old_cwuri; + struct uri *uri; + char *formatted; + + /* Preserve original current working URI */ + old_cwuri = uri_get ( cwuri ); + + /* Perform sequence of current working URI changes */ + do { + /* Parse relative URI */ + uri = parse_uri ( test->relative ); + okx ( uri != NULL, file, line ); + + /* Move to this URI */ + churi ( uri ); + + /* Format new current working URI */ + formatted = format_uri_alloc ( cwuri ); + okx ( formatted != NULL, file, line ); + if ( formatted ) { + okx ( strcmp ( formatted, test->expected ) == 0, + file, line ); + } + + /* Free temporary storage */ + free ( formatted ); + uri_put ( uri ); + + /* Move to next current working URI test */ + test++; + + } while ( test->relative != NULL ); + + /* Restore original current working URI */ + churi ( old_cwuri ); + uri_put ( old_cwuri ); +} +#define uri_churi_ok( test ) uri_churi_okx ( test, __FILE__, __LINE__ ) + +/** + * Report form parameter URI test list result + * + * @v test Form parameter URI test + * @v uri URI + * @v file Test code file + * @v line Test code line + */ +static void uri_params_list_okx ( struct uri_params_test *test, + struct uri *uri, const char *file, + unsigned int line ) { + struct uri_params_test_list *list; + struct parameter *param; + + /* Check URI */ + uri_okx ( uri, &test->uri, file, line ); + + /* Check URI parameters */ + okx ( uri->params != NULL, file, line ); + if ( uri->params ) { + list = test->list; + for_each_param ( param, uri->params ) { + okx ( strcmp ( param->key, list->key ) == 0, + file, line ); + okx ( strcmp ( param->value, list->value ) == 0, + file, line ); + list++; + } + okx ( list->key == NULL, file, line ); + } +} +#define uri_params_list_ok( test ) \ + uri_params_list_okx ( test, __FILE__, __LINE__ ) + +/** + * Report form parameter URI test result + * + * @v test Form parameter URI test + * @v file Test code file + * @v line Test code line + */ +static void uri_params_okx ( struct uri_params_test *test, const char *file, + unsigned int line ) { + struct uri_params_test_list *list; + struct parameters *params; + struct parameter *param; + struct uri *uri; + struct uri *dup; + + /* Create parameter list */ + params = create_parameters ( test->name ); + okx ( params != NULL, file, line ); + if ( params ) { + for ( list = test->list ; list->key ; list++ ) { + param = add_parameter ( params, list->key, list->value); + okx ( param != NULL, file, line ); + } + } + + /* Record parameter list as part of expected URI */ + test->uri.params = params; + + /* Parse URI */ + uri = parse_uri ( test->string ); + okx ( uri != NULL, file, line ); + if ( uri ) + uri_params_list_okx ( test, uri, file, line ); + + /* Duplicate URI */ + dup = uri_dup ( uri ); + okx ( dup != NULL, file, line ); + if ( dup ) + uri_params_list_okx ( test, dup, file, line ); + + /* Clear parameter list in expected URI */ + test->uri.params = NULL; + + uri_put ( uri ); + uri_put ( dup ); +} +#define uri_params_ok( test ) uri_params_okx ( test, __FILE__, __LINE__ ) + +/** Empty URI */ +static struct uri_test uri_empty = { + .string = "", +}; + +/** Basic HTTP URI */ +static struct uri_test uri_boot_ipxe_org = { + "http://boot.ipxe.org/demo/boot.php", + { .scheme = "http", .host = "boot.ipxe.org", .path = "/demo/boot.php" } +}; + +/** Basic opaque URI */ +static struct uri_test uri_mailto = { + "mailto:ipxe-devel@lists.ipxe.org", + { .scheme = "mailto", .opaque = "ipxe-devel@lists.ipxe.org" } +}; + +/** HTTP URI with all the trimmings */ +static struct uri_test uri_http_all = { + "http://anon:password@example.com:3001/~foo/cgi-bin/foo.pl?a=b&c=d#bit", + { + .scheme = "http", + .user = "anon", + .password = "password", + .host = "example.com", + .port = "3001", + .path = "/~foo/cgi-bin/foo.pl", + .query = "a=b&c=d", + .fragment = "bit", + }, +}; + +/** HTTP URI with escaped characters */ +static struct uri_test uri_http_escaped = { + "https://test.ipxe.org/wtf%3F%0A?kind%23of/uri%20is#this%3F", + { + .scheme = "https", + .host = "test.ipxe.org", + .path = "/wtf?\n", + .query = "kind#of/uri is", + .fragment = "this?", + }, +}; + +/** HTTP URI with improperly escaped characters */ +static struct uri_test uri_http_escaped_improper = { + /* We accept for parsing improperly escaped characters. + * (Formatting the parsed URI would produce the properly + * encoded form, and so would not exactly match the original + * URI string.) + */ + "https://test%2eipxe.org/wt%66%3f\n?kind%23of/uri is#this?", + { + .scheme = "https", + .host = "test.ipxe.org", + .path = "/wtf?\n", + .query = "kind#of/uri is", + .fragment = "this?", + }, +}; + +/** IPv6 URI */ +static struct uri_test uri_ipv6 = { + "http://[2001:ba8:0:1d4::6950:5845]/", + { + .scheme = "http", + .host = "[2001:ba8:0:1d4::6950:5845]", + .path = "/", + }, +}; + +/** IPv6 URI with port */ +static struct uri_test uri_ipv6_port = { + "http://[2001:ba8:0:1d4::6950:5845]:8001/boot", + { + .scheme = "http", + .host = "[2001:ba8:0:1d4::6950:5845]", + .port = "8001", + .path = "/boot", + }, +}; + +/** IPv6 URI with link-local address */ +static struct uri_test uri_ipv6_local = { + "http://[fe80::69ff:fe50:5845%25net0]/ipxe", + { + .scheme = "http", + .host = "[fe80::69ff:fe50:5845%net0]", + .path = "/ipxe", + }, +}; + +/** IPv6 URI with link-local address not conforming to RFC 6874 */ +static struct uri_test uri_ipv6_local_non_conforming = { + /* We accept for parsing a single "%" in "%net0" (rather than + * the properly encoded form "%25net0"). (Formatting the + * parsed URI would produce the properly encoded form, and so + * would not exactly match the original URI string.) + */ + "http://[fe80::69ff:fe50:5845%net0]/ipxe", + { + .scheme = "http", + .host = "[fe80::69ff:fe50:5845%net0]", + .path = "/ipxe", + }, +}; + +/** iSCSI URI */ +static struct uri_test uri_iscsi = { + "iscsi:10.253.253.1::::iqn.2010-04.org.ipxe:rabbit", + { + .scheme = "iscsi", + .opaque = "10.253.253.1::::iqn.2010-04.org.ipxe:rabbit", + }, +}; + +/** URI with port number */ +static struct uri_port_test uri_explicit_port = { + "http://192.168.0.1:8080/boot.php", + 80, + 8080, +}; + +/** URI without port number */ +static struct uri_port_test uri_default_port = { + "http://192.168.0.1/boot.php", + 80, + 80, +}; + +/** Simple path resolution test */ +static struct uri_resolve_test uri_simple_path = { + "/etc/passwd", + "group", + "/etc/group", +}; + +/** Path resolution test with "." and ".." elements */ +static struct uri_resolve_test uri_relative_path = { + "/var/lib/tftpboot/pxe/pxelinux.0", + "./../ipxe/undionly.kpxe", + "/var/lib/tftpboot/ipxe/undionly.kpxe", +}; + +/** Path resolution test terminating with directory */ +static struct uri_resolve_test uri_directory_path = { + "/test/cgi-bin.pl/boot.ipxe", + "..", + "/test/", +}; + +/** Path resolution test with excessive ".." elements */ +static struct uri_resolve_test uri_excessive_path = { + "/var/lib/tftpboot/ipxe.pxe", + "../../../../../../../foo", + "/foo", +}; + +/** Path resolution test with absolute path */ +static struct uri_resolve_test uri_absolute_path = { + "/var/lib/tftpboot", + "/etc/hostname", + "/etc/hostname", +}; + +/** Relative URI resolution test */ +static struct uri_resolve_test uri_relative = { + "http://boot.ipxe.org/demo/boot.php?vendor=10ec&device=8139", + "initrd.img", + "http://boot.ipxe.org/demo/initrd.img", +}; + +/** Absolute URI resolution test */ +static struct uri_resolve_test uri_absolute = { + "http://boot.ipxe.org/demo/boot.php", + "ftp://192.168.0.1/boot.ipxe", + "ftp://192.168.0.1/boot.ipxe", +}; + +/** Absolute path URI resolution test */ +static struct uri_resolve_test uri_absolute_uri_path = { + "http://boot.ipxe.org/demo/boot.php#test", + "/demo/vmlinuz", + "http://boot.ipxe.org/demo/vmlinuz", +}; + +/** Query URI resolution test */ +static struct uri_resolve_test uri_query = { + "http://10.253.253.1/test.pl?mac=02-00-69-50-58-45", + "?mac=00-1f-16-bc-fe-2f", + "http://10.253.253.1/test.pl?mac=00-1f-16-bc-fe-2f", +}; + +/** Fragment URI resolution test */ +static struct uri_resolve_test uri_fragment = { + "http://192.168.0.254/test#foo", + "#bar", + "http://192.168.0.254/test#bar", +}; + +/** TFTP URI with absolute path */ +static struct uri_tftp_test uri_tftp_absolute = { + { .s_addr = htonl ( 0xc0a80002 ) /* 192.168.0.2 */ }, + "/absolute/path", + { + .scheme = "tftp", + .host = "192.168.0.2", + .path = "/absolute/path", + }, + "tftp://192.168.0.2/absolute/path", +}; + +/** TFTP URI with relative path */ +static struct uri_tftp_test uri_tftp_relative = { + { .s_addr = htonl ( 0xc0a80003 ) /* 192.168.0.3 */ }, + "relative/path", + { + .scheme = "tftp", + .host = "192.168.0.3", + .path = "relative/path", + }, + "tftp://192.168.0.3/relative/path", +}; + +/** TFTP URI with path containing special characters */ +static struct uri_tftp_test uri_tftp_icky = { + { .s_addr = htonl ( 0x0a000006 ) /* 10.0.0.6 */ }, + "C:\\tftpboot\\icky#path", + { + .scheme = "tftp", + .host = "10.0.0.6", + .path = "C:\\tftpboot\\icky#path", + }, + "tftp://10.0.0.6/C%3A\\tftpboot\\icky%23path", +}; + +/** Current working URI test */ +static struct uri_churi_test uri_churi[] = { + { + "http://boot.ipxe.org/demo/boot.php", + "http://boot.ipxe.org/demo/boot.php", + }, + { + "?vendor=10ec&device=8139", + "http://boot.ipxe.org/demo/boot.php?vendor=10ec&device=8139", + }, + { + "fedora/fedora.ipxe", + "http://boot.ipxe.org/demo/fedora/fedora.ipxe", + }, + { + "vmlinuz", + "http://boot.ipxe.org/demo/fedora/vmlinuz", + }, + { + "http://local/boot/initrd.img", + "http://local/boot/initrd.img", + }, + { + "modules/8139too.ko", + "http://local/boot/modules/8139too.ko", + }, + { + NULL, + NULL, + } +}; + +/** Form parameter URI test list */ +static struct uri_params_test_list uri_params_list[] = { + { + "vendor", + "10ec", + }, + { + "device", + "8139", + }, + { + "uuid", + "f59fac00-758f-498f-9fe5-87d790045d94", + }, + { + NULL, + NULL, + } +}; + +/** Form parameter URI test */ +static struct uri_params_test uri_params = { + "http://boot.ipxe.org/demo/boot.php##params", + { + .scheme = "http", + .host = "boot.ipxe.org", + .path = "/demo/boot.php", + }, + NULL, + uri_params_list, +}; + +/** Named form parameter URI test list */ +static struct uri_params_test_list uri_named_params_list[] = { + { + "mac", + "00:1e:65:80:d3:b6", + }, + { + "serial", + "LXTQ20Z1139322762F2000", + }, + { + NULL, + NULL, + } +}; + +/** Named form parameter URI test */ +static struct uri_params_test uri_named_params = { + "http://192.168.100.4:3001/register##params=foo", + { + .scheme = "http", + .host = "192.168.100.4", + .port = "3001", + .path = "/register", + }, + "foo", + uri_named_params_list, +}; + +/** + * Perform URI self-test + * + */ +static void uri_test_exec ( void ) { + + /* URI parsing, formatting, and duplication tests */ + uri_parse_format_dup_ok ( &uri_empty ); + uri_parse_format_dup_ok ( &uri_boot_ipxe_org ); + uri_parse_format_dup_ok ( &uri_mailto ); + uri_parse_format_dup_ok ( &uri_http_all ); + uri_parse_format_dup_ok ( &uri_http_escaped ); + uri_parse_ok ( &uri_http_escaped_improper ); /* Parse only */ + uri_parse_format_dup_ok ( &uri_ipv6 ); + uri_parse_format_dup_ok ( &uri_ipv6_port ); + uri_parse_format_dup_ok ( &uri_ipv6_local ); + uri_parse_ok ( &uri_ipv6_local_non_conforming ); /* Parse only */ + uri_parse_format_dup_ok ( &uri_iscsi ); + + /** URI port number tests */ + uri_port_ok ( &uri_explicit_port ); + uri_port_ok ( &uri_default_port ); + + /** Path resolution tests */ + uri_resolve_path_ok ( &uri_simple_path ); + uri_resolve_path_ok ( &uri_relative_path ); + uri_resolve_path_ok ( &uri_directory_path ); + uri_resolve_path_ok ( &uri_excessive_path ); + uri_resolve_path_ok ( &uri_absolute_path ); + + /** URI resolution tests */ + uri_resolve_ok ( &uri_relative ); + uri_resolve_ok ( &uri_absolute ); + uri_resolve_ok ( &uri_absolute_uri_path ); + uri_resolve_ok ( &uri_query ); + uri_resolve_ok ( &uri_fragment ); + + /* TFTP URI construction tests */ + uri_tftp_ok ( &uri_tftp_absolute ); + uri_tftp_ok ( &uri_tftp_relative ); + uri_tftp_ok ( &uri_tftp_icky ); + + /* Current working URI tests */ + uri_churi_ok ( uri_churi ); + + /* Form parameter URI tests */ + uri_params_ok ( &uri_params ); + uri_params_ok ( &uri_named_params ); } + +/** URI self-test */ +struct self_test uri_test __self_test = { + .name = "uri", + .exec = uri_test_exec, +}; | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/usr/autoboot.c ^ |
@@ -91,8 +91,6 @@ */ static struct uri * parse_next_server_and_filename ( struct in_addr next_server, const char *filename ) { - char buf[ 23 /* "tftp://xxx.xxx.xxx.xxx/" */ + strlen ( filename ) - + 1 /* NUL */ ]; struct uri *uri; /* Parse filename */ @@ -100,17 +98,10 @@ if ( ! uri ) return NULL; - /* Construct a tftp:// URI for the filename, if applicable. - * We can't just rely on the current working URI, because the - * relative URI resolution will remove the distinction between - * filenames with and without initial slashes, which is - * significant for TFTP. - */ + /* Construct a TFTP URI for the filename, if applicable */ if ( next_server.s_addr && filename[0] && ! uri_is_absolute ( uri ) ) { uri_put ( uri ); - snprintf ( buf, sizeof ( buf ), "tftp://%s/%s", - inet_ntoa ( next_server ), filename ); - uri = parse_uri ( buf ); + uri = tftp_uri ( next_server, filename ); if ( ! uri ) return NULL; } | ||
[-] [+] | Changed | _service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/usr/imgmgmt.c ^ |
@@ -44,11 +44,28 @@ * @ret rc Return status code */ int imgdownload ( struct uri *uri, struct image **image ) { - size_t len = ( unparse_uri ( NULL, 0, uri, URI_ALL ) + 1 ); - char uri_string_redacted[len]; const char *password; + char *uri_string_redacted; int rc; + /* Construct redacted URI */ + password = uri->password; + if ( password ) + uri->password = "***"; + uri_string_redacted = format_uri_alloc ( uri ); + uri->password = password; + if ( ! uri_string_redacted ) { + rc = -ENOMEM; + goto err_uri_string; + } + + /* Resolve URI */ + uri = resolve_uri ( cwuri, uri ); + if ( ! uri ) { + rc = -ENOMEM; + goto err_resolve_uri; + } + /* Allocate image */ *image = alloc_image ( uri ); if ( ! *image ) { @@ -56,17 +73,8 @@ goto err_alloc_image; } - /* Redact password portion of URI, if necessary */ - password = uri->password; - if ( password ) - uri->password = "***"; - unparse_uri ( uri_string_redacted, sizeof ( uri_string_redacted ), - uri, URI_ALL ); - uri->password = password; - /* Create downloader */ - if ( ( rc = create_downloader ( &monojob, *image, LOCATION_URI, - uri ) ) != 0 ) { + if ( ( rc = create_downloader ( &monojob, *image ) ) != 0 ) { printf ( "Could not start download: %s\n", strerror ( rc ) ); goto err_create_downloader; } @@ -81,18 +89,15 @@ goto err_register_image; } - /* Drop local reference to image. Image is guaranteed to - * remain in scope since it is registered. - */ - image_put ( *image ); - - return 0; - err_register_image: err_monojob_wait: err_create_downloader: image_put ( *image ); err_alloc_image: + uri_put ( uri ); + err_resolve_uri: + free ( uri_string_redacted ); + err_uri_string: return rc; } |