mirror of
https://github.com/ipxe/ipxe
synced 2026-05-09 18:00:12 +03:00
301b1ecf2b
Some older distributions (such as RHEL 8) provide their AArch64 kernels as gzip-compressed EFI binaries (with no self-decompressing EFI stub present). We therefore enable support for gzip images by default for arm64 EFI builds. Review the files used to implement the gzip (and zlib) formats and mark these as permitted for UEFI Secure Boot. Signed-off-by: Michael Brown <mcb30@ipxe.org>
161 lines
3.9 KiB
C
161 lines
3.9 KiB
C
/*
|
|
* Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301, USA.
|
|
*
|
|
* You can also choose to distribute this program under the terms of
|
|
* the Unmodified Binary Distribution Licence (as given in the file
|
|
* COPYING.UBDL), provided that you have satisfied its requirements.
|
|
*/
|
|
|
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|
FILE_SECBOOT ( PERMITTED );
|
|
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <assert.h>
|
|
#include <ipxe/deflate.h>
|
|
#include <ipxe/image.h>
|
|
#include <ipxe/zlib.h>
|
|
|
|
/** @file
|
|
*
|
|
* zlib compressed images
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* Extract compressed data to image
|
|
*
|
|
* @v format Compression format code
|
|
* @v data Compressed input data
|
|
* @v len Length of compressed input data
|
|
* @v extracted Extracted image
|
|
* @ret rc Return status code
|
|
*/
|
|
int zlib_deflate ( enum deflate_format format, const void *data, size_t len,
|
|
struct image *extracted ) {
|
|
struct deflate *deflate;
|
|
struct deflate_chunk out;
|
|
int rc;
|
|
|
|
/* Allocate and initialise decompressor */
|
|
deflate = zalloc ( sizeof ( *deflate ) );
|
|
if ( ! deflate ) {
|
|
rc = -ENOMEM;
|
|
goto err_alloc;
|
|
}
|
|
|
|
/* Decompress data, (re)allocating if necessary */
|
|
while ( 1 ) {
|
|
|
|
/* (Re)initialise decompressor */
|
|
deflate_init ( deflate, format );
|
|
|
|
/* Initialise output chunk */
|
|
deflate_chunk_init ( &out, extracted->rwdata, 0,
|
|
extracted->len );
|
|
|
|
/* Decompress data */
|
|
if ( ( rc = deflate_inflate ( deflate, data, len,
|
|
&out ) ) != 0 ) {
|
|
DBGC ( extracted, "ZLIB %s could not decompress: %s\n",
|
|
extracted->name, strerror ( rc ) );
|
|
goto err_inflate;
|
|
}
|
|
|
|
/* Check that decompression is valid */
|
|
if ( ! deflate_finished ( deflate ) ) {
|
|
DBGC ( extracted, "ZLIB %s decompression incomplete\n",
|
|
extracted->name );
|
|
rc = -EINVAL;
|
|
goto err_unfinished;
|
|
}
|
|
|
|
/* Finish if output image size was correct */
|
|
if ( out.offset == extracted->len )
|
|
break;
|
|
|
|
/* Otherwise, resize output image and retry */
|
|
if ( ( rc = image_set_len ( extracted, out.offset ) ) != 0 ) {
|
|
DBGC ( extracted, "ZLIB %s could not resize: %s\n",
|
|
extracted->name, strerror ( rc ) );
|
|
goto err_set_size;
|
|
}
|
|
}
|
|
|
|
/* Success */
|
|
rc = 0;
|
|
|
|
err_set_size:
|
|
err_unfinished:
|
|
err_inflate:
|
|
free ( deflate );
|
|
err_alloc:
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Extract zlib image
|
|
*
|
|
* @v image Image
|
|
* @v extracted Extracted image
|
|
* @ret rc Return status code
|
|
*/
|
|
static int zlib_extract ( struct image *image, struct image *extracted ) {
|
|
int rc;
|
|
|
|
/* Decompress image */
|
|
if ( ( rc = zlib_deflate ( DEFLATE_ZLIB, image->data, image->len,
|
|
extracted ) ) != 0 )
|
|
return rc;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Probe zlib image
|
|
*
|
|
* @v image zlib image
|
|
* @ret rc Return status code
|
|
*/
|
|
static int zlib_probe ( struct image *image ) {
|
|
const union zlib_magic *magic;
|
|
|
|
/* Sanity check */
|
|
if ( image->len < sizeof ( *magic ) ) {
|
|
DBGC ( image, "ZLIB %s image too short\n", image->name );
|
|
return -ENOEXEC;
|
|
}
|
|
magic = image->data;
|
|
|
|
/* Check magic header */
|
|
if ( ! zlib_magic_is_valid ( magic ) ) {
|
|
DBGC ( image, "ZLIB %s invalid magic data\n", image->name );
|
|
return -ENOEXEC;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/** zlib image type */
|
|
struct image_type zlib_image_type __image_type ( PROBE_NORMAL ) = {
|
|
.name = "zlib",
|
|
.probe = zlib_probe,
|
|
.extract = zlib_extract,
|
|
.exec = image_extract_exec,
|
|
};
|