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)
183 */
184static size_t png_scanline_len ( struct png_context *png,
185 struct png_interlace *interlace ) {
186
187 return ( 1 /* Filter byte */ +
188 ( ( interlace->width * png->channels * png->depth ) + 7 ) / 8);
189}
190
191/**
192 * Handle PNG image header chunk
193 *
194 * @v image PNG image
195 * @v png PNG context
196 * @v len Chunk length
197 * @ret rc Return status code
198 */
199static int png_image_header ( struct image *image, struct png_context *png,
200 size_t len ) {
201 const struct png_image_header *ihdr;
202 struct png_interlace interlace;
203 unsigned int pass;
204
205 /* Sanity check */
206 if ( len != sizeof ( *ihdr ) ) {
207 DBGC ( image, "PNG %s invalid IHDR length %zd\n",
208 image->name, len );
209 return -EINVAL;
210 }
211 if ( png->pixbuf ) {
212 DBGC ( image, "PNG %s duplicate IHDR\n", image->name );
213 return -EINVAL;
214 }
215
216 /* Extract image header */
217 ihdr = ( image->data + png->offset );
218 DBGC ( image, "PNG %s %dx%d depth %d type %d compression %d filter %d "
219 "interlace %d\n", image->name, ntohl ( ihdr->width ),
220 ntohl ( ihdr->height ), ihdr->depth, ihdr->colour_type,
221 ihdr->compression, ihdr->filter, ihdr->interlace );
222
223 /* Sanity checks */
224 if ( ihdr->compression >= PNG_COMPRESSION_UNKNOWN ) {
225 DBGC ( image, "PNG %s unknown compression method %d\n",
226 image->name, ihdr->compression );
227 return -ENOTSUP;
228 }
229 if ( ihdr->filter >= PNG_FILTER_UNKNOWN ) {
230 DBGC ( image, "PNG %s unknown filter method %d\n",
231 image->name, ihdr->filter );
232 return -ENOTSUP;
233 }
234 if ( ihdr->interlace >= PNG_INTERLACE_UNKNOWN ) {
235 DBGC ( image, "PNG %s unknown interlace method %d\n",
236 image->name, ihdr->interlace );
237 return -ENOTSUP;
238 }
239
240 /* Allocate pixel buffer */
241 png->pixbuf = alloc_pixbuf ( ntohl ( ihdr->width ),
242 ntohl ( ihdr->height ) );
243 if ( ! png->pixbuf ) {
244 DBGC ( image, "PNG %s could not allocate pixel buffer\n",
245 image->name );
246 return -ENOMEM;
247 }
248
249 /* Extract bit depth */
250 png->depth = ihdr->depth;
251 if ( ( png->depth == 0 ) ||
252 ( ( png->depth & ( png->depth - 1 ) ) != 0 ) ) {
253 DBGC ( image, "PNG %s invalid depth %d\n",
254 image->name, png->depth );
255 return -EINVAL;
256 }
257
258 /* Calculate number of channels */
259 png->colour_type = ihdr->colour_type;
260 png->channels = 1;
261 if ( ! ( ihdr->colour_type & PNG_COLOUR_TYPE_PALETTE ) ) {
262 if ( ihdr->colour_type & PNG_COLOUR_TYPE_RGB )
263 png->channels += 2;
265 png->channels += 1;
266 }
267
268 /* Calculate number of interlace passes */
270
271 /* Calculate length of raw data buffer */
272 for ( pass = 0 ; pass < png->passes ; pass++ ) {
273 png_interlace ( png, pass, &interlace );
274 if ( interlace.width == 0 )
275 continue;
276 png->raw.len += ( interlace.height *
277 png_scanline_len ( png, &interlace ) );
278 }
279
280 /* Allocate raw data buffer */
281 png->raw.data = umalloc ( png->raw.len );
282 if ( ! png->raw.data ) {
283 DBGC ( image, "PNG %s could not allocate data buffer\n",
284 image->name );
285 return -ENOMEM;
286 }
287
288 return 0;
289}
290
291/**
292 * Handle PNG palette chunk
293 *
294 * @v image PNG image
295 * @v png PNG context
296 * @v len Chunk length
297 * @ret rc Return status code
298 */
299static int png_palette ( struct image *image, struct png_context *png,
300 size_t len ) {
301 const struct png_palette_entry *palette;
302 unsigned int i;
303
304 /* Populate palette */
305 palette = ( image->data + png->offset );
306 for ( i = 0 ; i < ( sizeof ( png->palette ) /
307 sizeof ( png->palette[0] ) ) ; i++ ) {
308
309 /* Stop when we run out of palette data */
310 if ( len < sizeof ( *palette ) )
311 break;
312
313 /* Extract palette entry */
314 png->palette[i] = ( ( palette->red << 16 ) |
315 ( palette->green << 8 ) |
316 ( palette->blue << 0 ) );
317 DBGC2 ( image, "PNG %s palette entry %d is %#06x\n",
318 image->name, i, png->palette[i] );
319
320 /* Move to next entry */
321 palette++;
322 len -= sizeof ( *palette );
323 }
324
325 return 0;
326}
327
328/**
329 * Handle PNG image data chunk
330 *
331 * @v image PNG image
332 * @v png PNG context
333 * @v len Chunk length
334 * @ret rc Return status code
335 */
336static int png_image_data ( struct image *image, struct png_context *png,
337 size_t len ) {
338 int rc;
339
340 /* Deflate this chunk */
341 if ( ( rc = deflate_inflate ( &png->deflate,
342 ( image->data + png->offset ),
343 len, &png->raw ) ) != 0 ) {
344 DBGC ( image, "PNG %s could not decompress: %s\n",
345 image->name, strerror ( rc ) );
346 return rc;
347 }
348
349 return 0;
350}
351
352/**
353 * Unfilter byte using the "None" filter
354 *
355 * @v current Filtered current byte
356 * @v left Unfiltered left byte
357 * @v above Unfiltered above byte
358 * @v above_left Unfiltered above-left byte
359 * @ret current Unfiltered current byte
360 */
361static unsigned int png_unfilter_none ( unsigned int current,
362 unsigned int left __unused,
363 unsigned int above __unused,
364 unsigned int above_left __unused ) {
365
366 return current;
367}
368
369/**
370 * Unfilter byte using the "Sub" 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_sub ( unsigned int current,
379 unsigned int left,
380 unsigned int above __unused,
381 unsigned int above_left __unused ) {
382
383 return ( current + left );
384}
385
386/**
387 * Unfilter byte using the "Up" 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_up ( unsigned int current,
396 unsigned int left __unused,
397 unsigned int above,
398 unsigned int above_left __unused ) {
399
400 return ( current + above );
401}
402
403/**
404 * Unfilter byte using the "Average" 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_average ( unsigned int current,
413 unsigned int left,
414 unsigned int above,
415 unsigned int above_left __unused ) {
416
417 return ( current + ( ( above + left ) >> 1 ) );
418}
419
420/**
421 * Paeth predictor function (defined in RFC 2083)
422 *
423 * @v a Pixel A
424 * @v b Pixel B
425 * @v c Pixel C
426 * @ret predictor Predictor pixel
427 */
428static unsigned int png_paeth_predictor ( unsigned int a, unsigned int b,
429 unsigned int c ) {
430 unsigned int p;
431 unsigned int pa;
432 unsigned int pb;
433 unsigned int pc;
434
435 /* Algorithm as defined in RFC 2083 section 6.6 */
436 p = ( a + b - c );
437 pa = abs ( p - a );
438 pb = abs ( p - b );
439 pc = abs ( p - c );
440 if ( ( pa <= pb ) && ( pa <= pc ) ) {
441 return a;
442 } else if ( pb <= pc ) {
443 return b;
444 } else {
445 return c;
446 }
447}
448
449/**
450 * Unfilter byte using the "Paeth" filter
451 *
452 * @v current Filtered current byte
453 * @v above_left Unfiltered above-left byte
454 * @v above Unfiltered above byte
455 * @v left Unfiltered left byte
456 * @ret current Unfiltered current byte
457 */
458static unsigned int png_unfilter_paeth ( unsigned int current,
459 unsigned int left,
460 unsigned int above,
461 unsigned int above_left ) {
462
463 return ( current + png_paeth_predictor ( left, above, above_left ) );
464}
465
466/** A PNG filter */
468 /**
469 * Unfilter byte
470 *
471 * @v current Filtered current byte
472 * @v left Unfiltered left byte
473 * @v above Unfiltered above byte
474 * @v above_left Unfiltered above-left byte
475 * @ret current Unfiltered current byte
476 */
477 unsigned int ( * unfilter ) ( unsigned int current,
478 unsigned int left,
479 unsigned int above,
480 unsigned int above_left );
481};
482
483/** PNG filter types */
491
492/**
493 * Unfilter one interlace pass of PNG raw data
494 *
495 * @v image PNG image
496 * @v png PNG context
497 * @v interlace Interlace pass
498 * @ret rc Return status code
499 *
500 * This routine may assume that it is impossible to overrun the raw
501 * data buffer, since the size is determined by the image dimensions.
502 */
503static int png_unfilter_pass ( struct image *image, struct png_context *png,
504 struct png_interlace *interlace ) {
505 size_t pixel_len = png_pixel_len ( png );
506 size_t scanline_len = png_scanline_len ( png, interlace );
507 uint8_t *data = ( png->raw.data + png->raw.offset );
508 struct png_filter *filter;
509 unsigned int scanline;
510 unsigned int byte;
511 unsigned int filter_type;
512 unsigned int left;
513 unsigned int above;
514 unsigned int above_left;
515
516 /* On the first scanline of a pass, above bytes are assumed to
517 * be zero.
518 */
519 above = 0;
520
521 /* Iterate over each scanline in turn */
522 for ( scanline = 0 ; scanline < interlace->height ; scanline++ ) {
523
524 /* Extract filter byte and determine filter type */
525 filter_type = *(data++);
526 if ( filter_type >= ( sizeof ( png_filters ) /
527 sizeof ( png_filters[0] ) ) ) {
528 DBGC ( image, "PNG %s unknown filter type %d\n",
529 image->name, filter_type );
530 return -ENOTSUP;
531 }
532 filter = &png_filters[filter_type];
533 assert ( filter->unfilter != NULL );
534 DBGC2 ( image, "PNG %s pass %d scanline %d filter type %d\n",
535 image->name, interlace->pass, scanline, filter_type );
536
537 /* At the start of a line, both above-left and left
538 * bytes are taken to be zero.
539 */
540 left = 0;
541 above_left = 0;
542
543 /* Iterate over each byte (not pixel) in turn */
544 for ( byte = 0 ; byte < ( scanline_len - 1 ) ; byte++ ) {
545
546 /* Extract predictor bytes, if applicable */
547 if ( byte >= pixel_len )
548 left = *( data - pixel_len );
549 if ( scanline > 0 )
550 above = *( data - scanline_len );
551 if ( ( scanline > 0 ) && ( byte >= pixel_len ) ) {
552 above_left = *( data - scanline_len -
553 pixel_len );
554 }
555
556 /* Unfilter current byte */
557 *data = filter->unfilter ( *data, left, above,
558 above_left );
559 data++;
560 }
561 }
562
563 /* Update offset */
564 png->raw.offset = ( ( ( void * ) data ) - png->raw.data );
565
566 return 0;
567}
568
569/**
570 * Unfilter PNG raw data
571 *
572 * @v image PNG image
573 * @v png PNG context
574 * @ret rc Return status code
575 *
576 * This routine may assume that it is impossible to overrun the raw
577 * data buffer, since the size is determined by the image dimensions.
578 */
579static int png_unfilter ( struct image *image, struct png_context *png ) {
580 struct png_interlace interlace;
581 unsigned int pass;
582 int rc;
583
584 /* Process each interlace pass */
585 png->raw.offset = 0;
586 for ( pass = 0 ; pass < png->passes ; pass++ ) {
587
588 /* Calculate interlace pass parameters */
589 png_interlace ( png, pass, &interlace );
590
591 /* Skip zero-width rows (which have no filter bytes) */
592 if ( interlace.width == 0 )
593 continue;
594
595 /* Unfilter this pass */
596 if ( ( rc = png_unfilter_pass ( image, png,
597 &interlace ) ) != 0 )
598 return rc;
599 }
600 assert ( png->raw.offset == png->raw.len );
601
602 return 0;
603}
604
605/**
606 * Calculate PNG pixel component value
607 *
608 * @v raw Raw component value
609 * @v alpha Alpha value
610 * @v max Maximum raw/alpha value
611 * @ret value Component value in range 0-255
612 */
613static inline unsigned int png_pixel ( unsigned int raw, unsigned int alpha,
614 unsigned int max ) {
615
616 /* The basic calculation is 255*(raw/max)*(value/max). We use
617 * fixed-point arithmetic (scaling up to the maximum range for
618 * a 32-bit integer), in order to get the same results for
619 * alpha blending as the test cases (produced using
620 * ImageMagick).
621 */
622 return ( ( ( ( ( 0xff00 * raw * alpha ) / max ) / max ) + 0x80 ) >> 8 );
623}
624
625/**
626 * Fill one interlace pass of PNG pixels
627 *
628 * @v image PNG image
629 * @v png PNG context
630 * @v interlace Interlace pass
631 *
632 * This routine may assume that it is impossible to overrun either the
633 * raw data buffer or the pixel buffer, since the sizes of both are
634 * determined by the image dimensions.
635 */
636static void png_pixels_pass ( struct image *image,
637 struct png_context *png,
638 struct png_interlace *interlace ) {
640 int is_indexed = ( png->colour_type & PNG_COLOUR_TYPE_PALETTE );
641 int is_rgb = ( png->colour_type & PNG_COLOUR_TYPE_RGB );
642 int has_alpha = ( png->colour_type & PNG_COLOUR_TYPE_ALPHA );
643 const uint8_t *data = ( png->raw.data + png->raw.offset );
644 size_t data_stride;
645 unsigned int pixbuf_y_index;
646 unsigned int pixbuf_index;
647 unsigned int pixbuf_x_stride;
648 unsigned int pixbuf_y_stride;
649 unsigned int y;
650 unsigned int x;
651 unsigned int c;
652 unsigned int bits;
653 unsigned int depth;
654 unsigned int max;
655 unsigned int alpha;
656 unsigned int raw;
657 unsigned int value;
658 uint8_t current = 0;
659 uint32_t pixel;
660
661 /* We only ever use the top byte of 16-bit pixels. Model this
662 * as a bit depth of 8 with a stride of more than one.
663 */
664 depth = png->depth;
665 data_stride = ( ( depth + 7 ) / 8 );
666 if ( depth > 8 )
667 depth = 8;
668 max = ( ( 1 << depth ) - 1 );
669
670 /* Calculate pixel buffer offset and strides */
671 pixbuf_y_index = ( ( ( interlace->y_indent * png->pixbuf->width ) +
672 interlace->x_indent ) );
673 pixbuf_x_stride = interlace->x_stride;
674 pixbuf_y_stride = ( interlace->y_stride * png->pixbuf->width );
675 DBGC2 ( image, "PNG %s pass %d %dx%d at (%d,%d) stride (%d,%d)\n",
676 image->name, interlace->pass, interlace->width,
677 interlace->height, interlace->x_indent, interlace->y_indent,
678 interlace->x_stride, interlace->y_stride );
679
680 /* Iterate over each scanline in turn */
681 for ( y = 0 ; y < interlace->height ; y++ ) {
682
683 /* Skip filter byte */
684 data++;
685
686 /* Iterate over each pixel in turn */
687 bits = depth;
688 pixbuf_index = pixbuf_y_index;
689 for ( x = 0 ; x < interlace->width ; x++ ) {
690
691 /* Extract sample value */
692 for ( c = 0 ; c < png->channels ; c++ ) {
693
694 /* Get sample value into high bits of current */
695 current <<= depth;
696 bits -= depth;
697 if ( ! bits ) {
698 current = *data;
699 data += data_stride;
700 bits = 8;
701 }
702
703 /* Extract sample value */
704 channel[c] = ( current >> ( 8 - depth ) );
705 }
706
707 /* Convert to native pixel format */
708 if ( is_indexed ) {
709
710 /* Indexed */
711 pixel = png->palette[channel[0]];
712
713 } else {
714
715 /* Determine alpha value */
716 alpha = ( has_alpha ?
717 channel[ png->channels - 1 ] : max );
718
719 /* Convert to RGB value */
720 pixel = 0;
721 for ( c = 0 ; c < 3 ; c++ ) {
722 raw = channel[ is_rgb ? c : 0 ];
723 value = png_pixel ( raw, alpha, max );
724 assert ( value <= 255 );
725 pixel = ( ( pixel << 8 ) | value );
726 }
727 }
728
729 /* Store pixel */
730 png->pixbuf->data[pixbuf_index] = pixel;
731 pixbuf_index += pixbuf_x_stride;
732 }
733
734 /* Move to next output row */
735 pixbuf_y_index += pixbuf_y_stride;
736 }
737
738 /* Update offset */
739 png->raw.offset = ( ( ( const void * ) data ) - png->raw.data );
740}
741
742/**
743 * Fill PNG pixels
744 *
745 * @v image PNG image
746 * @v png PNG context
747 *
748 * This routine may assume that it is impossible to overrun either the
749 * raw data buffer or the pixel buffer, since the sizes of both are
750 * determined by the image dimensions.
751 */
752static void png_pixels ( struct image *image, struct png_context *png ) {
753 struct png_interlace interlace;
754 unsigned int pass;
755
756 /* Process each interlace pass */
757 png->raw.offset = 0;
758 for ( pass = 0 ; pass < png->passes ; pass++ ) {
759
760 /* Calculate interlace pass parameters */
761 png_interlace ( png, pass, &interlace );
762
763 /* Skip zero-width rows (which have no filter bytes) */
764 if ( interlace.width == 0 )
765 continue;
766
767 /* Unfilter this pass */
768 png_pixels_pass ( image, png, &interlace );
769 }
770 assert ( png->raw.offset == png->raw.len );
771}
772
773/**
774 * Handle PNG image end chunk
775 *
776 * @v image PNG image
777 * @v png PNG context
778 * @v len Chunk length
779 * @ret rc Return status code
780 */
781static int png_image_end ( struct image *image, struct png_context *png,
782 size_t len ) {
783 int rc;
784
785 /* Sanity checks */
786 if ( len != 0 ) {
787 DBGC ( image, "PNG %s invalid IEND length %zd\n",
788 image->name, len );
789 return -EINVAL;
790 }
791 if ( ! png->pixbuf ) {
792 DBGC ( image, "PNG %s missing pixel buffer (no IHDR?)\n",
793 image->name );
794 return -EINVAL;
795 }
796 if ( ! deflate_finished ( &png->deflate ) ) {
797 DBGC ( image, "PNG %s decompression not complete\n",
798 image->name );
799 return -EINVAL;
800 }
801 if ( png->raw.offset != png->raw.len ) {
802 DBGC ( image, "PNG %s incorrect decompressed length (expected "
803 "%zd, got %zd)\n", image->name, png->raw.len,
804 png->raw.offset );
805 return -EINVAL;
806 }
807
808 /* Unfilter raw data */
809 if ( ( rc = png_unfilter ( image, png ) ) != 0 )
810 return rc;
811
812 /* Fill pixel buffer */
813 png_pixels ( image, png );
814
815 return 0;
816}
817
818/** A PNG chunk handler */
820 /** Chunk type */
822 /**
823 * Handle chunk
824 *
825 * @v image PNG image
826 * @v png PNG context
827 * @v len Chunk length
828 * @ret rc Return status code
829 */
830 int ( * handle ) ( struct image *image, struct png_context *png,
831 size_t len );
832};
833
834/** PNG chunk handlers */
841
842/**
843 * Handle PNG chunk
844 *
845 * @v image PNG image
846 * @v png PNG context
847 * @v type Chunk type
848 * @v len Chunk length
849 * @ret rc Return status code
850 */
851static int png_chunk ( struct image *image, struct png_context *png,
852 uint32_t type, size_t len ) {
853 struct png_chunk_handler *handler;
854 unsigned int i;
855
856 DBGC ( image, "PNG %s chunk type %s offset %zd length %zd\n",
857 image->name, png_type_name ( type ), png->offset, len );
858
859 /* Handle according to chunk type */
860 for ( i = 0 ; i < ( sizeof ( png_chunk_handlers ) /
861 sizeof ( png_chunk_handlers[0] ) ) ; i++ ) {
862 handler = &png_chunk_handlers[i];
863 if ( handler->type == type )
864 return handler->handle ( image, png, len );
865 }
866
867 /* Fail if unknown chunk type is critical */
868 if ( ! ( type & htonl ( PNG_CHUNK_ANCILLARY ) ) ) {
869 DBGC ( image, "PNG %s unknown critical chunk type %s\n",
871 return -ENOTSUP;
872 }
873
874 /* Ignore non-critical unknown chunk types */
875 return 0;
876}
877
878/**
879 * Convert PNG image to pixel buffer
880 *
881 * @v image PNG image
882 * @v pixbuf Pixel buffer to fill in
883 * @ret rc Return status code
884 */
885static int png_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) {
886 struct png_context *png;
887 const struct png_chunk_header *header;
888 const struct png_chunk_footer *footer;
889 size_t remaining;
890 size_t chunk_len;
891 int rc;
892
893 /* Allocate and initialise context */
894 png = zalloc ( sizeof ( *png ) );
895 if ( ! png ) {
896 rc = -ENOMEM;
897 goto err_alloc;
898 }
899 png->offset = sizeof ( struct png_signature );
901
902 /* Process chunks */
903 do {
904
905 /* Extract chunk header */
906 remaining = ( image->len - png->offset );
907 if ( remaining < ( sizeof ( *header ) + sizeof ( *footer ) ) ){
908 DBGC ( image, "PNG %s truncated chunk header/footer "
909 "at offset %zd\n", image->name, png->offset );
910 rc = -EINVAL;
911 goto err_truncated;
912 }
913 header = ( image->data + png->offset );
914 png->offset += sizeof ( *header );
915
916 /* Validate chunk length */
917 chunk_len = ntohl ( header->len );
918 if ( chunk_len > ( remaining - sizeof ( *header ) -
919 sizeof ( *footer ) ) ) {
920 DBGC ( image, "PNG %s truncated chunk data at offset "
921 "%zd\n", image->name, png->offset );
922 rc = -EINVAL;
923 goto err_truncated;
924 }
925
926 /* Handle chunk */
927 if ( ( rc = png_chunk ( image, png, header->type,
928 chunk_len ) ) != 0 )
929 goto err_chunk;
930
931 /* Move to next chunk */
932 png->offset += ( chunk_len + sizeof ( *footer ) );
933
934 } while ( png->offset < image->len );
935
936 /* Check that we finished with an IEND chunk */
937 if ( header->type != htonl ( PNG_TYPE_IEND ) ) {
938 DBGC ( image, "PNG %s did not finish with IEND\n",
939 image->name );
940 rc = -EINVAL;
941 goto err_iend;
942 }
943
944 /* Return pixel buffer */
945 *pixbuf = pixbuf_get ( png->pixbuf );
946
947 /* Success */
948 rc = 0;
949
950 err_iend:
951 err_chunk:
952 err_truncated:
953 pixbuf_put ( png->pixbuf );
954 ufree ( png->raw.data );
955 free ( png );
956 err_alloc:
957 return rc;
958}
959
960/**
961 * Probe PNG image
962 *
963 * @v image PNG image
964 * @ret rc Return status code
965 */
966static int png_probe ( struct image *image ) {
967 const struct png_signature *signature;
968
969 /* Sanity check */
970 if ( image->len < sizeof ( *signature ) ) {
971 DBGC ( image, "PNG %s is too short\n", image->name );
972 return -ENOEXEC;
973 }
974
975 /* Check signature */
977 if ( memcmp ( signature, &png_signature, sizeof ( *signature ) ) != 0 ){
978 DBGC ( image, "PNG %s has invalid signature\n", image->name );
979 return -ENOEXEC;
980 }
981
982 return 0;
983}
984
985/** PNG image type */
986struct image_type png_image_type __image_type ( PROBE_NORMAL ) = {
987 .name = "PNG",
988 .probe = png_probe,
989 .pixbuf = png_pixbuf,
990};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
__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:50
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:573
#define DBGC2(...)
Definition compiler.h:522
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOEXEC
Exec format error.
Definition errno.h:520
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define PROBE_NORMAL
Normal image probe priority.
Definition image.h:156
#define __image_type(probe_order)
An executable image type.
Definition image.h:170
#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:662
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:503
static int png_pixbuf(struct image *image, struct pixel_buffer **pixbuf)
Convert PNG image to pixel buffer.
Definition png.c:885
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:412
static unsigned int png_pixel(unsigned int raw, unsigned int alpha, unsigned int max)
Calculate PNG pixel component value.
Definition png.c:613
static int png_unfilter(struct image *image, struct png_context *png)
Unfilter PNG raw data.
Definition png.c:579
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:636
static int png_image_data(struct image *image, struct png_context *png, size_t len)
Handle PNG image data chunk.
Definition png.c:336
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:299
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:361
static int png_probe(struct image *image)
Probe PNG image.
Definition png.c:966
static int png_image_header(struct image *image, struct png_context *png, size_t len)
Handle PNG image header chunk.
Definition png.c:199
static struct png_chunk_handler png_chunk_handlers[]
PNG chunk handlers.
Definition png.c:835
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:378
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:851
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:428
static void png_pixels(struct image *image, struct png_context *png)
Fill PNG pixels.
Definition png.c:752
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:781
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:395
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:458
static struct png_filter png_filters[]
PNG filter types.
Definition png.c:484
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:95
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:56
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:819
uint32_t type
Chunk type.
Definition png.c:821
int(* handle)(struct image *image, struct png_context *png, size_t len)
Handle chunk.
Definition png.c:830
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:467
unsigned int(* unfilter)(unsigned int current, unsigned int left, unsigned int above, unsigned int above_left)
Unfilter byte.
Definition png.c:477
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