iPXE
png.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <stdint.h>
28#include <stdlib.h>
29#include <string.h>
30#include <errno.h>
31#include <byteswap.h>
32#include <ipxe/umalloc.h>
33#include <ipxe/pixbuf.h>
34#include <ipxe/deflate.h>
35#include <ipxe/png.h>
36
37/** @file
38 *
39 * Portable Network Graphics (PNG) format
40 *
41 * The PNG format is defined in RFC 2083.
42 */
43
44/** PNG context */
46 /** Offset within image */
47 size_t offset;
48
49 /** Pixel buffer */
51
52 /** Bit depth */
53 unsigned int depth;
54 /** Colour type */
55 unsigned int colour_type;
56 /** Number of channels */
57 unsigned int channels;
58 /** Number of interlace passes */
59 unsigned int passes;
60 /** Palette, in iPXE's pixel buffer format */
62
63 /** Decompression buffer for raw PNG data */
65 /** Decompressor */
67};
68
69/** A PNG interlace pass */
71 /** Pass number */
72 unsigned int pass;
73 /** X starting indent */
74 unsigned int x_indent;
75 /** Y starting indent */
76 unsigned int y_indent;
77 /** X stride */
78 unsigned int x_stride;
79 /** Y stride */
80 unsigned int y_stride;
81 /** Width */
82 unsigned int width;
83 /** Height */
84 unsigned int height;
85};
86
87/** PNG file signature */
89
90/** Number of interlacing passes */
95
96/**
97 * Transcribe PNG chunk type name (for debugging)
98 *
99 * @v type Chunk type
100 * @ret name Chunk type name
101 */
102static const char * png_type_name ( uint32_t type ) {
103 static union {
105 char name[ sizeof ( uint32_t ) + 1 /* NUL */ ];
106 } u;
107
108 u.type = type;
109 return u.name;
110}
111
112/**
113 * Calculate PNG interlace pass parameters
114 *
115 * @v png PNG context
116 * @v pass Pass number (0=first pass)
117 * @v interlace Interlace pass to fill in
118 */
119static void png_interlace ( struct png_context *png, unsigned int pass,
120 struct png_interlace *interlace ) {
121 unsigned int grid_width_log2;
122 unsigned int grid_height_log2;
123 unsigned int x_indent;
124 unsigned int y_indent;
125 unsigned int x_stride_log2;
126 unsigned int y_stride_log2;
127 unsigned int x_stride;
128 unsigned int y_stride;
129 unsigned int width;
130 unsigned int height;
131
132 /* Sanity check */
133 assert ( png->passes > 0 );
134
135 /* Store pass number */
136 interlace->pass = pass;
137
138 /* Calculate interlace grid dimensions */
139 grid_width_log2 = ( png->passes / 2 );
140 grid_height_log2 = ( ( png->passes - 1 ) / 2 );
141
142 /* Calculate starting indents */
143 interlace->x_indent = x_indent =
144 ( ( pass & 1 ) ?
145 ( 1 << ( grid_width_log2 - ( pass / 2 ) - 1 ) ) : 0 );
146 interlace->y_indent = y_indent =
147 ( ( pass && ! ( pass & 1 ) ) ?
148 ( 1 << ( grid_height_log2 - ( ( pass - 1 ) / 2 ) - 1 ) ) : 0);
149
150 /* Calculate strides */
151 x_stride_log2 = ( grid_width_log2 - ( pass / 2 ) );
152 y_stride_log2 =
153 ( grid_height_log2 - ( pass ? ( ( pass - 1 ) / 2 ) : 0 ) );
154 interlace->x_stride = x_stride = ( 1 << x_stride_log2 );
155 interlace->y_stride = y_stride = ( 1 << y_stride_log2 );
156
157 /* Calculate pass dimensions */
158 width = png->pixbuf->width;
159 height = png->pixbuf->height;
160 interlace->width =
161 ( ( width - x_indent + x_stride - 1 ) >> x_stride_log2 );
162 interlace->height =
163 ( ( height - y_indent + y_stride - 1 ) >> y_stride_log2 );
164}
165
166/**
167 * Calculate PNG pixel length
168 *
169 * @v png PNG context
170 * @ret pixel_len Pixel length
171 */
172static unsigned int png_pixel_len ( struct png_context *png ) {
173
174 return ( ( ( png->channels * png->depth ) + 7 ) / 8 );
175}
176
177/**
178 * Calculate PNG scanline length
179 *
180 * @v png PNG context
181 * @v interlace Interlace pass
182 * @ret scanline_len Scanline length (including filter byte), or 0 on error
183 */
184static size_t png_scanline_len ( struct png_context *png,
185 struct png_interlace *interlace ) {
186 size_t bits;
187
188 /* Calculate bit count and check for overflow */
189 bits = ( interlace->width * png->channels * png->depth );
190 assert ( png->channels != 0 );
191 assert ( png->depth != 0 );
192 if ( ( ( bits / png->channels ) / png->depth ) != interlace->width )
193 return 0;
194
195 /* Calculate byte length (cannot overflow) */
196 return ( 1 /* Filter byte */ + ( bits / 8 ) + ( !! ( bits & 7 ) ) );
197}
198
199/**
200 * Handle PNG image header chunk
201 *
202 * @v image PNG image
203 * @v png PNG context
204 * @v len Chunk length
205 * @ret rc Return status code
206 */
207static int png_image_header ( struct image *image, struct png_context *png,
208 size_t len ) {
209 const struct png_image_header *ihdr;
210 struct png_interlace interlace;
211 size_t scanline_len;
212 size_t pass_len;
213 unsigned int pass;
214
215 /* Sanity check */
216 if ( len != sizeof ( *ihdr ) ) {
217 DBGC ( image, "PNG %s invalid IHDR length %zd\n",
218 image->name, len );
219 return -EINVAL;
220 }
221 if ( png->pixbuf ) {
222 DBGC ( image, "PNG %s duplicate IHDR\n", image->name );
223 return -EINVAL;
224 }
225
226 /* Extract image header */
227 ihdr = ( image->data + png->offset );
228 DBGC ( image, "PNG %s %dx%d depth %d type %d compression %d filter %d "
229 "interlace %d\n", image->name, ntohl ( ihdr->width ),
230 ntohl ( ihdr->height ), ihdr->depth, ihdr->colour_type,
231 ihdr->compression, ihdr->filter, ihdr->interlace );
232
233 /* Sanity checks */
234 if ( ihdr->compression >= PNG_COMPRESSION_UNKNOWN ) {
235 DBGC ( image, "PNG %s unknown compression method %d\n",
236 image->name, ihdr->compression );
237 return -ENOTSUP;
238 }
239 if ( ihdr->filter >= PNG_FILTER_UNKNOWN ) {
240 DBGC ( image, "PNG %s unknown filter method %d\n",
241 image->name, ihdr->filter );
242 return -ENOTSUP;
243 }
244 if ( ihdr->interlace >= PNG_INTERLACE_UNKNOWN ) {
245 DBGC ( image, "PNG %s unknown interlace method %d\n",
246 image->name, ihdr->interlace );
247 return -ENOTSUP;
248 }
249
250 /* Allocate pixel buffer */
251 png->pixbuf = alloc_pixbuf ( ntohl ( ihdr->width ),
252 ntohl ( ihdr->height ) );
253 if ( ! png->pixbuf ) {
254 DBGC ( image, "PNG %s could not allocate pixel buffer\n",
255 image->name );
256 return -ENOMEM;
257 }
258
259 /* Extract bit depth */
260 png->depth = ihdr->depth;
261 if ( ( png->depth == 0 ) ||
262 ( ( png->depth & ( png->depth - 1 ) ) != 0 ) ) {
263 DBGC ( image, "PNG %s invalid depth %d\n",
264 image->name, png->depth );
265 return -EINVAL;
266 }
267
268 /* Calculate number of channels */
269 png->colour_type = ihdr->colour_type;
270 png->channels = 1;
271 if ( ! ( ihdr->colour_type & PNG_COLOUR_TYPE_PALETTE ) ) {
272 if ( ihdr->colour_type & PNG_COLOUR_TYPE_RGB )
273 png->channels += 2;
275 png->channels += 1;
276 }
277
278 /* Calculate number of interlace passes */
280
281 /* Calculate length of raw data buffer */
282 for ( pass = 0 ; pass < png->passes ; pass++ ) {
283 png_interlace ( png, pass, &interlace );
284 if ( interlace.width == 0 )
285 continue;
286 scanline_len = png_scanline_len ( png, &interlace );
287 if ( ! scanline_len )
288 return -ERANGE;
289 pass_len = ( interlace.height * scanline_len );
290 if ( ( pass_len / scanline_len ) != interlace.height )
291 return -ERANGE;
292 png->raw.len += pass_len;
293 if ( png->raw.len < pass_len )
294 return -ERANGE;
295 }
296
297 /* Allocate raw data buffer */
298 png->raw.data = umalloc ( png->raw.len );
299 if ( ! png->raw.data ) {
300 DBGC ( image, "PNG %s could not allocate data buffer\n",
301 image->name );
302 return -ENOMEM;
303 }
304
305 return 0;
306}
307
308/**
309 * Handle PNG palette chunk
310 *
311 * @v image PNG image
312 * @v png PNG context
313 * @v len Chunk length
314 * @ret rc Return status code
315 */
316static int png_palette ( struct image *image, struct png_context *png,
317 size_t len ) {
318 const struct png_palette_entry *palette;
319 unsigned int i;
320
321 /* Populate palette */
322 palette = ( image->data + png->offset );
323 for ( i = 0 ; i < ( sizeof ( png->palette ) /
324 sizeof ( png->palette[0] ) ) ; i++ ) {
325
326 /* Stop when we run out of palette data */
327 if ( len < sizeof ( *palette ) )
328 break;
329
330 /* Extract palette entry */
331 png->palette[i] = ( ( palette->red << 16 ) |
332 ( palette->green << 8 ) |
333 ( palette->blue << 0 ) );
334 DBGC2 ( image, "PNG %s palette entry %d is %#06x\n",
335 image->name, i, png->palette[i] );
336
337 /* Move to next entry */
338 palette++;
339 len -= sizeof ( *palette );
340 }
341
342 return 0;
343}
344
345/**
346 * Handle PNG image data chunk
347 *
348 * @v image PNG image
349 * @v png PNG context
350 * @v len Chunk length
351 * @ret rc Return status code
352 */
353static int png_image_data ( struct image *image, struct png_context *png,
354 size_t len ) {
355 int rc;
356
357 /* Deflate this chunk */
358 if ( ( rc = deflate_inflate ( &png->deflate,
359 ( image->data + png->offset ),
360 len, &png->raw ) ) != 0 ) {
361 DBGC ( image, "PNG %s could not decompress: %s\n",
362 image->name, strerror ( rc ) );
363 return rc;
364 }
365
366 return 0;
367}
368
369/**
370 * Unfilter byte using the "None" filter
371 *
372 * @v current Filtered current byte
373 * @v left Unfiltered left byte
374 * @v above Unfiltered above byte
375 * @v above_left Unfiltered above-left byte
376 * @ret current Unfiltered current byte
377 */
378static unsigned int png_unfilter_none ( unsigned int current,
379 unsigned int left __unused,
380 unsigned int above __unused,
381 unsigned int above_left __unused ) {
382
383 return current;
384}
385
386/**
387 * Unfilter byte using the "Sub" filter
388 *
389 * @v current Filtered current byte
390 * @v left Unfiltered left byte
391 * @v above Unfiltered above byte
392 * @v above_left Unfiltered above-left byte
393 * @ret current Unfiltered current byte
394 */
395static unsigned int png_unfilter_sub ( unsigned int current,
396 unsigned int left,
397 unsigned int above __unused,
398 unsigned int above_left __unused ) {
399
400 return ( current + left );
401}
402
403/**
404 * Unfilter byte using the "Up" filter
405 *
406 * @v current Filtered current byte
407 * @v left Unfiltered left byte
408 * @v above Unfiltered above byte
409 * @v above_left Unfiltered above-left byte
410 * @ret current Unfiltered current byte
411 */
412static unsigned int png_unfilter_up ( unsigned int current,
413 unsigned int left __unused,
414 unsigned int above,
415 unsigned int above_left __unused ) {
416
417 return ( current + above );
418}
419
420/**
421 * Unfilter byte using the "Average" filter
422 *
423 * @v current Filtered current byte
424 * @v left Unfiltered left byte
425 * @v above Unfiltered above byte
426 * @v above_left Unfiltered above-left byte
427 * @ret current Unfiltered current byte
428 */
429static unsigned int png_unfilter_average ( unsigned int current,
430 unsigned int left,
431 unsigned int above,
432 unsigned int above_left __unused ) {
433
434 return ( current + ( ( above + left ) >> 1 ) );
435}
436
437/**
438 * Paeth predictor function (defined in RFC 2083)
439 *
440 * @v a Pixel A
441 * @v b Pixel B
442 * @v c Pixel C
443 * @ret predictor Predictor pixel
444 */
445static unsigned int png_paeth_predictor ( unsigned int a, unsigned int b,
446 unsigned int c ) {
447 unsigned int p;
448 unsigned int pa;
449 unsigned int pb;
450 unsigned int pc;
451
452 /* Algorithm as defined in RFC 2083 section 6.6 */
453 p = ( a + b - c );
454 pa = abs ( p - a );
455 pb = abs ( p - b );
456 pc = abs ( p - c );
457 if ( ( pa <= pb ) && ( pa <= pc ) ) {
458 return a;
459 } else if ( pb <= pc ) {
460 return b;
461 } else {
462 return c;
463 }
464}
465
466/**
467 * Unfilter byte using the "Paeth" filter
468 *
469 * @v current Filtered current byte
470 * @v above_left Unfiltered above-left byte
471 * @v above Unfiltered above byte
472 * @v left Unfiltered left byte
473 * @ret current Unfiltered current byte
474 */
475static unsigned int png_unfilter_paeth ( unsigned int current,
476 unsigned int left,
477 unsigned int above,
478 unsigned int above_left ) {
479
480 return ( current + png_paeth_predictor ( left, above, above_left ) );
481}
482
483/** A PNG filter */
485 /**
486 * Unfilter byte
487 *
488 * @v current Filtered current byte
489 * @v left Unfiltered left byte
490 * @v above Unfiltered above byte
491 * @v above_left Unfiltered above-left byte
492 * @ret current Unfiltered current byte
493 */
494 unsigned int ( * unfilter ) ( unsigned int current,
495 unsigned int left,
496 unsigned int above,
497 unsigned int above_left );
498};
499
500/** PNG filter types */
508
509/**
510 * Unfilter one interlace pass of PNG raw data
511 *
512 * @v image PNG image
513 * @v png PNG context
514 * @v interlace Interlace pass
515 * @ret rc Return status code
516 *
517 * This routine may assume that it is impossible to overrun the raw
518 * data buffer, since the size is determined by the image dimensions.
519 */
520static int png_unfilter_pass ( struct image *image, struct png_context *png,
521 struct png_interlace *interlace ) {
522 size_t pixel_len = png_pixel_len ( png );
523 size_t scanline_len = png_scanline_len ( png, interlace );
524 uint8_t *data = ( png->raw.data + png->raw.offset );
525 struct png_filter *filter;
526 unsigned int scanline;
527 unsigned int byte;
528 unsigned int filter_type;
529 unsigned int left;
530 unsigned int above;
531 unsigned int above_left;
532
533 /* On the first scanline of a pass, above bytes are assumed to
534 * be zero.
535 */
536 above = 0;
537
538 /* Iterate over each scanline in turn */
539 for ( scanline = 0 ; scanline < interlace->height ; scanline++ ) {
540
541 /* Extract filter byte and determine filter type */
542 filter_type = *(data++);
543 if ( filter_type >= ( sizeof ( png_filters ) /
544 sizeof ( png_filters[0] ) ) ) {
545 DBGC ( image, "PNG %s unknown filter type %d\n",
546 image->name, filter_type );
547 return -ENOTSUP;
548 }
549 filter = &png_filters[filter_type];
550 assert ( filter->unfilter != NULL );
551 DBGC2 ( image, "PNG %s pass %d scanline %d filter type %d\n",
552 image->name, interlace->pass, scanline, filter_type );
553
554 /* At the start of a line, both above-left and left
555 * bytes are taken to be zero.
556 */
557 left = 0;
558 above_left = 0;
559
560 /* Iterate over each byte (not pixel) in turn */
561 for ( byte = 0 ; byte < ( scanline_len - 1 ) ; byte++ ) {
562
563 /* Extract predictor bytes, if applicable */
564 if ( byte >= pixel_len )
565 left = *( data - pixel_len );
566 if ( scanline > 0 )
567 above = *( data - scanline_len );
568 if ( ( scanline > 0 ) && ( byte >= pixel_len ) ) {
569 above_left = *( data - scanline_len -
570 pixel_len );
571 }
572
573 /* Unfilter current byte */
574 *data = filter->unfilter ( *data, left, above,
575 above_left );
576 data++;
577 }
578 }
579
580 /* Update offset */
581 png->raw.offset = ( ( ( void * ) data ) - png->raw.data );
582
583 return 0;
584}
585
586/**
587 * Unfilter PNG raw data
588 *
589 * @v image PNG image
590 * @v png PNG context
591 * @ret rc Return status code
592 *
593 * This routine may assume that it is impossible to overrun the raw
594 * data buffer, since the size is determined by the image dimensions.
595 */
596static int png_unfilter ( struct image *image, struct png_context *png ) {
597 struct png_interlace interlace;
598 unsigned int pass;
599 int rc;
600
601 /* Process each interlace pass */
602 png->raw.offset = 0;
603 for ( pass = 0 ; pass < png->passes ; pass++ ) {
604
605 /* Calculate interlace pass parameters */
606 png_interlace ( png, pass, &interlace );
607
608 /* Skip zero-width rows (which have no filter bytes) */
609 if ( interlace.width == 0 )
610 continue;
611
612 /* Unfilter this pass */
613 if ( ( rc = png_unfilter_pass ( image, png,
614 &interlace ) ) != 0 )
615 return rc;
616 }
617 assert ( png->raw.offset == png->raw.len );
618
619 return 0;
620}
621
622/**
623 * Calculate PNG pixel component value
624 *
625 * @v raw Raw component value
626 * @v alpha Alpha value
627 * @v max Maximum raw/alpha value
628 * @ret value Component value in range 0-255
629 */
630static inline unsigned int png_pixel ( unsigned int raw, unsigned int alpha,
631 unsigned int max ) {
632
633 /* The basic calculation is 255*(raw/max)*(value/max). We use
634 * fixed-point arithmetic (scaling up to the maximum range for
635 * a 32-bit integer), in order to get the same results for
636 * alpha blending as the test cases (produced using
637 * ImageMagick).
638 */
639 return ( ( ( ( ( 0xff00 * raw * alpha ) / max ) / max ) + 0x80 ) >> 8 );
640}
641
642/**
643 * Fill one interlace pass of PNG pixels
644 *
645 * @v image PNG image
646 * @v png PNG context
647 * @v interlace Interlace pass
648 *
649 * This routine may assume that it is impossible to overrun either the
650 * raw data buffer or the pixel buffer, since the sizes of both are
651 * determined by the image dimensions.
652 */
653static void png_pixels_pass ( struct image *image,
654 struct png_context *png,
655 struct png_interlace *interlace ) {
657 int is_indexed = ( png->colour_type & PNG_COLOUR_TYPE_PALETTE );
658 int is_rgb = ( png->colour_type & PNG_COLOUR_TYPE_RGB );
659 int has_alpha = ( png->colour_type & PNG_COLOUR_TYPE_ALPHA );
660 const uint8_t *data = ( png->raw.data + png->raw.offset );
661 size_t data_stride;
662 unsigned int pixbuf_y_index;
663 unsigned int pixbuf_index;
664 unsigned int pixbuf_x_stride;
665 unsigned int pixbuf_y_stride;
666 unsigned int y;
667 unsigned int x;
668 unsigned int c;
669 unsigned int bits;
670 unsigned int depth;
671 unsigned int max;
672 unsigned int alpha;
673 unsigned int raw;
674 unsigned int value;
675 uint8_t current = 0;
676 uint32_t pixel;
677
678 /* We only ever use the top byte of 16-bit pixels. Model this
679 * as a bit depth of 8 with a stride of more than one.
680 */
681 depth = png->depth;
682 data_stride = ( ( depth + 7 ) / 8 );
683 if ( depth > 8 )
684 depth = 8;
685 max = ( ( 1 << depth ) - 1 );
686
687 /* Calculate pixel buffer offset and strides */
688 pixbuf_y_index = ( ( ( interlace->y_indent * png->pixbuf->width ) +
689 interlace->x_indent ) );
690 pixbuf_x_stride = interlace->x_stride;
691 pixbuf_y_stride = ( interlace->y_stride * png->pixbuf->width );
692 DBGC2 ( image, "PNG %s pass %d %dx%d at (%d,%d) stride (%d,%d)\n",
693 image->name, interlace->pass, interlace->width,
694 interlace->height, interlace->x_indent, interlace->y_indent,
695 interlace->x_stride, interlace->y_stride );
696
697 /* Iterate over each scanline in turn */
698 for ( y = 0 ; y < interlace->height ; y++ ) {
699
700 /* Skip filter byte */
701 data++;
702
703 /* Iterate over each pixel in turn */
704 bits = depth;
705 pixbuf_index = pixbuf_y_index;
706 for ( x = 0 ; x < interlace->width ; x++ ) {
707
708 /* Extract sample value */
709 for ( c = 0 ; c < png->channels ; c++ ) {
710
711 /* Get sample value into high bits of current */
712 current <<= depth;
713 bits -= depth;
714 if ( ! bits ) {
715 current = *data;
716 data += data_stride;
717 bits = 8;
718 }
719
720 /* Extract sample value */
721 channel[c] = ( current >> ( 8 - depth ) );
722 }
723
724 /* Convert to native pixel format */
725 if ( is_indexed ) {
726
727 /* Indexed */
728 pixel = png->palette[channel[0]];
729
730 } else {
731
732 /* Determine alpha value */
733 alpha = ( has_alpha ?
734 channel[ png->channels - 1 ] : max );
735
736 /* Convert to RGB value */
737 pixel = 0;
738 for ( c = 0 ; c < 3 ; c++ ) {
739 raw = channel[ is_rgb ? c : 0 ];
740 value = png_pixel ( raw, alpha, max );
741 assert ( value <= 255 );
742 pixel = ( ( pixel << 8 ) | value );
743 }
744 }
745
746 /* Store pixel */
747 png->pixbuf->data[pixbuf_index] = pixel;
748 pixbuf_index += pixbuf_x_stride;
749 }
750
751 /* Move to next output row */
752 pixbuf_y_index += pixbuf_y_stride;
753 }
754
755 /* Update offset */
756 png->raw.offset = ( ( ( const void * ) data ) - png->raw.data );
757}
758
759/**
760 * Fill PNG pixels
761 *
762 * @v image PNG image
763 * @v png PNG context
764 *
765 * This routine may assume that it is impossible to overrun either the
766 * raw data buffer or the pixel buffer, since the sizes of both are
767 * determined by the image dimensions.
768 */
769static void png_pixels ( struct image *image, struct png_context *png ) {
770 struct png_interlace interlace;
771 unsigned int pass;
772
773 /* Process each interlace pass */
774 png->raw.offset = 0;
775 for ( pass = 0 ; pass < png->passes ; pass++ ) {
776
777 /* Calculate interlace pass parameters */
778 png_interlace ( png, pass, &interlace );
779
780 /* Skip zero-width rows (which have no filter bytes) */
781 if ( interlace.width == 0 )
782 continue;
783
784 /* Unfilter this pass */
785 png_pixels_pass ( image, png, &interlace );
786 }
787 assert ( png->raw.offset == png->raw.len );
788}
789
790/**
791 * Handle PNG image end chunk
792 *
793 * @v image PNG image
794 * @v png PNG context
795 * @v len Chunk length
796 * @ret rc Return status code
797 */
798static int png_image_end ( struct image *image, struct png_context *png,
799 size_t len ) {
800 int rc;
801
802 /* Sanity checks */
803 if ( len != 0 ) {
804 DBGC ( image, "PNG %s invalid IEND length %zd\n",
805 image->name, len );
806 return -EINVAL;
807 }
808 if ( ! png->pixbuf ) {
809 DBGC ( image, "PNG %s missing pixel buffer (no IHDR?)\n",
810 image->name );
811 return -EINVAL;
812 }
813 if ( ! deflate_finished ( &png->deflate ) ) {
814 DBGC ( image, "PNG %s decompression not complete\n",
815 image->name );
816 return -EINVAL;
817 }
818 if ( png->raw.offset != png->raw.len ) {
819 DBGC ( image, "PNG %s incorrect decompressed length (expected "
820 "%zd, got %zd)\n", image->name, png->raw.len,
821 png->raw.offset );
822 return -EINVAL;
823 }
824
825 /* Unfilter raw data */
826 if ( ( rc = png_unfilter ( image, png ) ) != 0 )
827 return rc;
828
829 /* Fill pixel buffer */
830 png_pixels ( image, png );
831
832 return 0;
833}
834
835/** A PNG chunk handler */
837 /** Chunk type */
839 /**
840 * Handle chunk
841 *
842 * @v image PNG image
843 * @v png PNG context
844 * @v len Chunk length
845 * @ret rc Return status code
846 */
847 int ( * handle ) ( struct image *image, struct png_context *png,
848 size_t len );
849};
850
851/** PNG chunk handlers */
858
859/**
860 * Handle PNG chunk
861 *
862 * @v image PNG image
863 * @v png PNG context
864 * @v type Chunk type
865 * @v len Chunk length
866 * @ret rc Return status code
867 */
868static int png_chunk ( struct image *image, struct png_context *png,
869 uint32_t type, size_t len ) {
870 struct png_chunk_handler *handler;
871 unsigned int i;
872
873 DBGC ( image, "PNG %s chunk type %s offset %zd length %zd\n",
874 image->name, png_type_name ( type ), png->offset, len );
875
876 /* Handle according to chunk type */
877 for ( i = 0 ; i < ( sizeof ( png_chunk_handlers ) /
878 sizeof ( png_chunk_handlers[0] ) ) ; i++ ) {
879 handler = &png_chunk_handlers[i];
880 if ( handler->type == type )
881 return handler->handle ( image, png, len );
882 }
883
884 /* Fail if unknown chunk type is critical */
885 if ( ! ( type & htonl ( PNG_CHUNK_ANCILLARY ) ) ) {
886 DBGC ( image, "PNG %s unknown critical chunk type %s\n",
888 return -ENOTSUP;
889 }
890
891 /* Ignore non-critical unknown chunk types */
892 return 0;
893}
894
895/**
896 * Convert PNG image to pixel buffer
897 *
898 * @v image PNG image
899 * @v pixbuf Pixel buffer to fill in
900 * @ret rc Return status code
901 */
902static int png_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) {
903 struct png_context *png;
904 const struct png_chunk_header *header;
905 const struct png_chunk_footer *footer;
906 size_t remaining;
907 size_t chunk_len;
908 int rc;
909
910 /* Allocate and initialise context */
911 png = zalloc ( sizeof ( *png ) );
912 if ( ! png ) {
913 rc = -ENOMEM;
914 goto err_alloc;
915 }
916 png->offset = sizeof ( struct png_signature );
918
919 /* Process chunks */
920 do {
921
922 /* Extract chunk header */
923 remaining = ( image->len - png->offset );
924 if ( remaining < ( sizeof ( *header ) + sizeof ( *footer ) ) ){
925 DBGC ( image, "PNG %s truncated chunk header/footer "
926 "at offset %zd\n", image->name, png->offset );
927 rc = -EINVAL;
928 goto err_truncated;
929 }
930 header = ( image->data + png->offset );
931 png->offset += sizeof ( *header );
932
933 /* Validate chunk length */
934 chunk_len = ntohl ( header->len );
935 if ( chunk_len > ( remaining - sizeof ( *header ) -
936 sizeof ( *footer ) ) ) {
937 DBGC ( image, "PNG %s truncated chunk data at offset "
938 "%zd\n", image->name, png->offset );
939 rc = -EINVAL;
940 goto err_truncated;
941 }
942
943 /* Handle chunk */
944 if ( ( rc = png_chunk ( image, png, header->type,
945 chunk_len ) ) != 0 )
946 goto err_chunk;
947
948 /* Move to next chunk */
949 png->offset += ( chunk_len + sizeof ( *footer ) );
950
951 } while ( png->offset < image->len );
952
953 /* Check that we finished with an IEND chunk */
954 if ( header->type != htonl ( PNG_TYPE_IEND ) ) {
955 DBGC ( image, "PNG %s did not finish with IEND\n",
956 image->name );
957 rc = -EINVAL;
958 goto err_iend;
959 }
960
961 /* Return pixel buffer */
962 *pixbuf = pixbuf_get ( png->pixbuf );
963
964 /* Success */
965 rc = 0;
966
967 err_iend:
968 err_chunk:
969 err_truncated:
970 pixbuf_put ( png->pixbuf );
971 ufree ( png->raw.data );
972 free ( png );
973 err_alloc:
974 return rc;
975}
976
977/**
978 * Probe PNG image
979 *
980 * @v image PNG image
981 * @ret rc Return status code
982 */
983static int png_probe ( struct image *image ) {
984 const struct png_signature *signature;
985
986 /* Sanity check */
987 if ( image->len < sizeof ( *signature ) ) {
988 DBGC ( image, "PNG %s is too short\n", image->name );
989 return -ENOEXEC;
990 }
991
992 /* Check signature */
994 if ( memcmp ( signature, &png_signature, sizeof ( *signature ) ) != 0 ){
995 DBGC ( image, "PNG %s has invalid signature\n", image->name );
996 return -ENOEXEC;
997 }
998
999 return 0;
1000}
1001
1002/** PNG image type */
1003struct image_type png_image_type __image_type ( PROBE_NORMAL ) = {
1004 .name = "PNG",
1005 .probe = png_probe,
1006 .pixbuf = png_pixbuf,
1007};
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
__be32 raw[7]
Definition CIB_PRM.h:0
u8 signature
CPU signature.
Definition CIB_PRM.h:7
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
pseudo_bit_t value[0x00020]
Definition arbel.h:2
unsigned int uint32_t
Definition stdint.h:12
unsigned char uint8_t
Definition stdint.h:10
static volatile void * bits
Definition bitops.h:28
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
const char * name
Definition ath9k_hw.c:1986
#define abs(x)
Definition ath.h:46
#define max(x, y)
Definition ath.h:41
void deflate_init(struct deflate *deflate, enum deflate_format format)
Initialise decompressor.
Definition deflate.c:992
int deflate_inflate(struct deflate *deflate, const void *data, size_t len, struct deflate_chunk *out)
Inflate compressed data.
Definition deflate.c:484
DEFLATE decompression algorithm.
static int deflate_finished(struct deflate *deflate)
Check if decompression has finished.
Definition deflate.h:278
@ DEFLATE_ZLIB
ZLIB header and footer.
Definition deflate.h:21
union @104331263140136355135267063077374276003064103115 u
ring len
Length.
Definition dwmac.h:226
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
struct ena_llq_option header
Header locations.
Definition ena.h:5
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define DBGC2(...)
Definition compiler.h:547
#define DBGC(...)
Definition compiler.h:530
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define EINVAL
Invalid argument.
Definition errno.h:472
#define ENOEXEC
Exec format error.
Definition errno.h:563
#define ENOMEM
Not enough space.
Definition errno.h:578
#define ENOTSUP
Operation not supported.
Definition errno.h:633
#define ERANGE
Result too large.
Definition errno.h:683
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:951
#define PROBE_NORMAL
Normal image probe priority.
Definition image.h:163
#define __image_type(probe_order)
An executable image type.
Definition image.h:177
#define ntohl(value)
Definition byteswap.h:135
#define htonl(value)
Definition byteswap.h:134
User memory allocation.
static __always_inline void * umalloc(size_t size)
Allocate external memory.
Definition umalloc.h:57
static __always_inline void ufree(void *ptr)
Free external memory.
Definition umalloc.h:68
String functions.
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
uint32_t channel
RNDIS channel.
Definition netvsc.h:3
struct pixel_buffer * alloc_pixbuf(unsigned int width, unsigned int height)
Allocate pixel buffer.
Definition pixbuf.c:60
Pixel buffer.
static unsigned int unsigned int y
Definition pixbuf.h:63
static unsigned int x
Definition pixbuf.h:63
static int png_unfilter_pass(struct image *image, struct png_context *png, struct png_interlace *interlace)
Unfilter one interlace pass of PNG raw data.
Definition png.c:520
static int png_pixbuf(struct image *image, struct pixel_buffer **pixbuf)
Convert PNG image to pixel buffer.
Definition png.c:902
static unsigned int png_unfilter_average(unsigned int current, unsigned int left, unsigned int above, unsigned int above_left __unused)
Unfilter byte using the "Average" filter.
Definition png.c:429
static unsigned int png_pixel(unsigned int raw, unsigned int alpha, unsigned int max)
Calculate PNG pixel component value.
Definition png.c:630
static int png_unfilter(struct image *image, struct png_context *png)
Unfilter PNG raw data.
Definition png.c:596
static void png_pixels_pass(struct image *image, struct png_context *png, struct png_interlace *interlace)
Fill one interlace pass of PNG pixels.
Definition png.c:653
static int png_image_data(struct image *image, struct png_context *png, size_t len)
Handle PNG image data chunk.
Definition png.c:353
static uint8_t png_interlace_passes[]
Number of interlacing passes.
Definition png.c:91
static int png_palette(struct image *image, struct png_context *png, size_t len)
Handle PNG palette chunk.
Definition png.c:316
static unsigned int png_pixel_len(struct png_context *png)
Calculate PNG pixel length.
Definition png.c:172
static unsigned int png_unfilter_none(unsigned int current, unsigned int left __unused, unsigned int above __unused, unsigned int above_left __unused)
Unfilter byte using the "None" filter.
Definition png.c:378
static int png_probe(struct image *image)
Probe PNG image.
Definition png.c:983
static int png_image_header(struct image *image, struct png_context *png, size_t len)
Handle PNG image header chunk.
Definition png.c:207
static struct png_chunk_handler png_chunk_handlers[]
PNG chunk handlers.
Definition png.c:852
static unsigned int png_unfilter_sub(unsigned int current, unsigned int left, unsigned int above __unused, unsigned int above_left __unused)
Unfilter byte using the "Sub" filter.
Definition png.c:395
static size_t png_scanline_len(struct png_context *png, struct png_interlace *interlace)
Calculate PNG scanline length.
Definition png.c:184
static int png_chunk(struct image *image, struct png_context *png, uint32_t type, size_t len)
Handle PNG chunk.
Definition png.c:868
static unsigned int png_paeth_predictor(unsigned int a, unsigned int b, unsigned int c)
Paeth predictor function (defined in RFC 2083).
Definition png.c:445
static void png_pixels(struct image *image, struct png_context *png)
Fill PNG pixels.
Definition png.c:769
static void png_interlace(struct png_context *png, unsigned int pass, struct png_interlace *interlace)
Calculate PNG interlace pass parameters.
Definition png.c:119
static int png_image_end(struct image *image, struct png_context *png, size_t len)
Handle PNG image end chunk.
Definition png.c:798
static unsigned int png_unfilter_up(unsigned int current, unsigned int left __unused, unsigned int above, unsigned int above_left __unused)
Unfilter byte using the "Up" filter.
Definition png.c:412
static const char * png_type_name(uint32_t type)
Transcribe PNG chunk type name (for debugging).
Definition png.c:102
static unsigned int png_unfilter_paeth(unsigned int current, unsigned int left, unsigned int above, unsigned int above_left)
Unfilter byte using the "Paeth" filter.
Definition png.c:475
static struct png_filter png_filters[]
PNG filter types.
Definition png.c:501
Portable Network Graphics (PNG) format.
#define PNG_TYPE_IDAT
PNG image data chunk type.
Definition png.h:159
@ PNG_CHUNK_ANCILLARY
Chunk is ancillary.
Definition png.h:43
#define PNG_SIGNATURE
PNG file signature.
Definition png.h:24
@ PNG_FILTER_UNKNOWN
First unknown filter method.
Definition png.h:123
@ PNG_INTERLACE_NONE
No interlacing.
Definition png.h:129
@ PNG_INTERLACE_UNKNOWN
First unknown interlace method.
Definition png.h:133
@ PNG_INTERLACE_ADAM7
Adam7 interlacing.
Definition png.h:131
#define PNG_TYPE_IHDR
PNG image header chunk type.
Definition png.h:77
#define PNG_TYPE_IEND
PNG image end chunk type.
Definition png.h:176
@ PNG_FILTER_BASIC_SUB
Left byte used as predictor.
Definition png.h:166
@ PNG_FILTER_BASIC_UP
Above byte used as predictor.
Definition png.h:168
@ PNG_FILTER_BASIC_PAETH
Paeth filter.
Definition png.h:172
@ PNG_FILTER_BASIC_AVERAGE
Above and left bytes used as predictors.
Definition png.h:170
@ PNG_FILTER_BASIC_NONE
No filtering.
Definition png.h:164
#define PNG_TYPE_PLTE
PNG palette chunk type.
Definition png.h:137
#define PNG_PALETTE_COUNT
Maximum number of PNG palette entries.
Definition png.h:156
@ PNG_COLOUR_TYPE_ALPHA
Alpha channel is used.
Definition png.h:104
@ PNG_COLOUR_TYPE_PALETTE
Palette is used.
Definition png.h:100
@ PNG_COLOUR_TYPE_RGB
RGB colour is used.
Definition png.h:102
@ PNG_COMPRESSION_UNKNOWN
First unknown compression method.
Definition png.h:115
UINT8_t filter
Receive packet filter.
Definition pxe_api.h:11
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
unsigned char byte
Definition smc9000.h:38
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
A chunk of data.
Definition deflate.h:246
size_t offset
Current offset.
Definition deflate.h:250
void * data
Data.
Definition deflate.h:248
size_t len
Length of data.
Definition deflate.h:252
An executable image type.
Definition image.h:102
An executable image.
Definition image.h:24
const void * data
Read-only data.
Definition image.h:51
char * name
Name.
Definition image.h:38
size_t len
Length of raw file image.
Definition image.h:63
A pixel buffer.
Definition pixbuf.h:17
unsigned int height
Height.
Definition pixbuf.h:23
unsigned int width
Width.
Definition pixbuf.h:21
uint32_t * data
32-bit (8:8:8:8) xRGB pixel data, in host-endian order
Definition pixbuf.h:25
A PNG chunk handler.
Definition png.c:836
uint32_t type
Chunk type.
Definition png.c:838
int(* handle)(struct image *image, struct png_context *png, size_t len)
Handle chunk.
Definition png.c:847
A PNG chunk header.
Definition png.h:27
PNG context.
Definition png.c:45
size_t offset
Offset within image.
Definition png.c:47
struct deflate_chunk raw
Decompression buffer for raw PNG data.
Definition png.c:64
struct pixel_buffer * pixbuf
Pixel buffer.
Definition png.c:50
struct deflate deflate
Decompressor.
Definition png.c:66
unsigned int channels
Number of channels.
Definition png.c:57
unsigned int colour_type
Colour type.
Definition png.c:55
unsigned int passes
Number of interlace passes.
Definition png.c:59
unsigned int depth
Bit depth.
Definition png.c:53
uint32_t palette[PNG_PALETTE_COUNT]
Palette, in iPXE's pixel buffer format.
Definition png.c:61
A PNG filter.
Definition png.c:484
unsigned int(* unfilter)(unsigned int current, unsigned int left, unsigned int above, unsigned int above_left)
Unfilter byte.
Definition png.c:494
A PNG image header.
Definition png.h:80
uint8_t filter
Filter method.
Definition png.h:92
uint8_t colour_type
Colour type.
Definition png.h:88
uint8_t depth
Bit depth.
Definition png.h:86
uint8_t compression
Compression method.
Definition png.h:90
uint32_t height
Height.
Definition png.h:84
uint32_t width
Width.
Definition png.h:82
uint8_t interlace
Interlace method.
Definition png.h:94
A PNG interlace pass.
Definition png.c:70
unsigned int x_stride
X stride.
Definition png.c:78
unsigned int height
Height.
Definition png.c:84
unsigned int width
Width.
Definition png.c:82
unsigned int y_stride
Y stride.
Definition png.c:80
unsigned int y_indent
Y starting indent.
Definition png.c:76
unsigned int x_indent
X starting indent.
Definition png.c:74
unsigned int pass
Pass number.
Definition png.c:72
A PNG palette entry.
Definition png.h:140
uint8_t red
Red.
Definition png.h:142
uint8_t green
Green.
Definition png.h:144
uint8_t blue
Blue.
Definition png.h:146
A PNG palette chunk.
Definition png.h:150
A PNG file signature.
Definition png.h:18