From de4f31cdcad7c4734c68da828351eeb7afd0360e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 6 May 2021 13:09:30 +0100 Subject: [image] Provide image_set_len() utility function Signed-off-by: Michael Brown --- src/core/image.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src/core') diff --git a/src/core/image.c b/src/core/image.c index 9fe77c54c..ce8cf868b 100644 --- a/src/core/image.c +++ b/src/core/image.c @@ -176,14 +176,13 @@ int image_set_cmdline ( struct image *image, const char *cmdline ) { } /** - * Set image data + * Set image length * * @v image Image - * @v data Image data * @v len Length of image data * @ret rc Return status code */ -int image_set_data ( struct image *image, userptr_t data, size_t len ) { +int image_set_len ( struct image *image, size_t len ) { userptr_t new; /* (Re)allocate image data */ @@ -191,10 +190,28 @@ int image_set_data ( struct image *image, userptr_t data, size_t len ) { if ( ! new ) return -ENOMEM; image->data = new; + image->len = len; + + return 0; +} + +/** + * Set image data + * + * @v image Image + * @v data Image data + * @v len Length of image data + * @ret rc Return status code + */ +int image_set_data ( struct image *image, userptr_t data, size_t len ) { + int rc; + + /* Set image length */ + if ( ( rc = image_set_len ( image, len ) ) != 0 ) + return rc; /* Copy in new image data */ memcpy_user ( image->data, 0, data, 0, len ); - image->len = len; return 0; } -- cgit v1.2.3-55-g7522 From 5c9c8d2b9b78cf4e1f256fe6874855c1aee458f2 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 6 May 2021 13:11:31 +0100 Subject: [image] Add "imgextract" command for extracting archive images Add the concept of extracting an image from an archive (which could be a single-file archive such as a gzip-compressed file), along with an "imgextract" command to expose this functionality to scripts. Signed-off-by: Michael Brown --- src/config/config.c | 3 + src/config/config_archive.c | 32 +++++++++++ src/config/general.h | 1 + src/core/archive.c | 104 ++++++++++++++++++++++++++++++++++ src/hci/commands/image_archive_cmd.c | 105 +++++++++++++++++++++++++++++++++++ src/include/ipxe/errfile.h | 1 + src/include/ipxe/image.h | 10 ++++ src/include/usr/imgarchive.h | 16 ++++++ src/usr/imgarchive.c | 54 ++++++++++++++++++ 9 files changed, 326 insertions(+) create mode 100644 src/config/config_archive.c create mode 100644 src/core/archive.c create mode 100644 src/hci/commands/image_archive_cmd.c create mode 100644 src/include/usr/imgarchive.h create mode 100644 src/usr/imgarchive.c (limited to 'src/core') diff --git a/src/config/config.c b/src/config/config.c index 5e7a3ecfd..dd1fceb92 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -284,6 +284,9 @@ REQUIRE_OBJECT ( cert_cmd ); #ifdef IMAGE_MEM_CMD REQUIRE_OBJECT ( image_mem_cmd ); #endif +#ifdef IMAGE_ARCHIVE_CMD +REQUIRE_OBJECT ( image_archive_cmd ); +#endif /* * Drag in miscellaneous objects diff --git a/src/config/config_archive.c b/src/config/config_archive.c new file mode 100644 index 000000000..3644b5de8 --- /dev/null +++ b/src/config/config_archive.c @@ -0,0 +1,32 @@ +/* + * 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 (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include + +/** @file + * + * Archive image configuration + * + */ + +PROVIDE_REQUIRING_SYMBOL(); diff --git a/src/config/general.h b/src/config/general.h index 9b21f1271..fd317be96 100644 --- a/src/config/general.h +++ b/src/config/general.h @@ -156,6 +156,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); //#define NTP_CMD /* NTP commands */ //#define CERT_CMD /* Certificate management commands */ //#define IMAGE_MEM_CMD /* Read memory command */ +//#define IMAGE_ARCHIVE_CMD /* Archive image management commands */ /* * ROM-specific options diff --git a/src/core/archive.c b/src/core/archive.c new file mode 100644 index 000000000..cd024bde3 --- /dev/null +++ b/src/core/archive.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2021 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include +#include +#include + +/** @file + * + * Archive images + * + */ + +/** + * Extract archive image + * + * @v image Image + * @v name Extracted image name + * @v extracted Extracted image to fill in + * @ret rc Return status code + */ +int image_extract ( struct image *image, const char *name, + struct image **extracted ) { + char *dot; + int rc; + + /* Check that this image can be used to extract an archive image */ + if ( ! ( image->type && image->type->extract ) ) { + rc = -ENOTSUP; + goto err_unsupported; + } + + /* Allocate new image */ + *extracted = alloc_image ( image->uri ); + if ( ! *extracted ) { + rc = -ENOMEM; + goto err_alloc; + } + + /* Set image name */ + if ( ( rc = image_set_name ( *extracted, + ( name ? name : image->name ) ) ) != 0 ) { + goto err_set_name; + } + + /* Strip any archive or compression suffix from implicit name */ + if ( ( ! name ) && ( (*extracted)->name ) && + ( ( dot = strrchr ( (*extracted)->name, '.' ) ) != NULL ) ) { + *dot = '\0'; + } + + /* Try extracting archive image */ + if ( ( rc = image->type->extract ( image, *extracted ) ) != 0 ) { + DBGC ( image, "IMAGE %s could not extract image: %s\n", + image->name, strerror ( rc ) ); + goto err_extract; + } + + /* Register image */ + if ( ( rc = register_image ( *extracted ) ) != 0 ) + goto err_register; + + /* Drop local reference to image */ + image_put ( *extracted ); + + return 0; + + unregister_image ( *extracted ); + err_register: + err_extract: + err_set_name: + image_put ( *extracted ); + err_alloc: + err_unsupported: + return rc; +} + +/* Drag in objects via image_extract() */ +REQUIRING_SYMBOL ( image_extract ); + +/* Drag in archive image formats */ +REQUIRE_OBJECT ( config_archive ); diff --git a/src/hci/commands/image_archive_cmd.c b/src/hci/commands/image_archive_cmd.c new file mode 100644 index 000000000..a2212aecf --- /dev/null +++ b/src/hci/commands/image_archive_cmd.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2021 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include +#include +#include +#include +#include + +/** @file + * + * Archive image commands + * + */ + +/** "imgextract" options */ +struct imgextract_options { + /** Image name */ + char *name; + /** Keep original image */ + int keep; + /** Download timeout */ + unsigned long timeout; +}; + +/** "imgextract" option list */ +static struct option_descriptor imgextract_opts[] = { + OPTION_DESC ( "name", 'n', required_argument, + struct imgextract_options, name, parse_string ), + OPTION_DESC ( "keep", 'k', no_argument, + struct imgextract_options, keep, parse_flag ), + OPTION_DESC ( "timeout", 't', required_argument, + struct imgextract_options, timeout, parse_timeout ), +}; + +/** "imgextract" command descriptor */ +static struct command_descriptor imgextract_cmd = + COMMAND_DESC ( struct imgextract_options, imgextract_opts, 1, 1, NULL ); + +/** + * The "imgextract" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Return status code + */ +static int imgextract_exec ( int argc, char **argv ) { + struct imgextract_options opts; + struct image *image; + int rc; + + /* Parse options */ + if ( ( rc = parse_options ( argc, argv, &imgextract_cmd, + &opts ) ) != 0 ) + goto err_parse; + + /* Acquire image */ + if ( ( rc = imgacquire ( argv[optind], opts.timeout, &image ) ) != 0 ) + goto err_acquire; + + /* Extract archive image */ + if ( ( rc = imgextract ( image, opts.name ) ) != 0 ) + goto err_extract; + + /* Success */ + rc = 0; + + err_extract: + /* Discard original image unless --keep was specified */ + if ( ! opts.keep ) + unregister_image ( image ); + err_acquire: + err_parse: + return rc; +} + +/** Archive image commands */ +struct command image_archive_commands[] __command = { + { + .name = "imgextract", + .exec = imgextract_exec, + }, +}; diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index e3bf9f565..162e6b7b0 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -301,6 +301,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define ERRFILE_png ( ERRFILE_IMAGE | 0x00070000 ) #define ERRFILE_der ( ERRFILE_IMAGE | 0x00080000 ) #define ERRFILE_pem ( ERRFILE_IMAGE | 0x00090000 ) +#define ERRFILE_archive ( ERRFILE_IMAGE | 0x000a0000 ) #define ERRFILE_asn1 ( ERRFILE_OTHER | 0x00000000 ) #define ERRFILE_chap ( ERRFILE_OTHER | 0x00010000 ) diff --git a/src/include/ipxe/image.h b/src/include/ipxe/image.h index 046edf9a5..c6e723dc6 100644 --- a/src/include/ipxe/image.h +++ b/src/include/ipxe/image.h @@ -113,6 +113,14 @@ struct image_type { */ int ( * asn1 ) ( struct image *image, size_t offset, struct asn1_cursor **cursor ); + /** + * Extract archive image + * + * @v image Image + * @v extracted Extracted image + * @ret rc Return status code + */ + int ( * extract ) ( struct image *image, struct image *extracted ); }; /** @@ -190,6 +198,8 @@ extern struct image * image_memory ( const char *name, userptr_t data, extern int image_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ); extern int image_asn1 ( struct image *image, size_t offset, struct asn1_cursor **cursor ); +extern int image_extract ( struct image *image, const char *name, + struct image **extracted ); /** * Increment reference count on an image diff --git a/src/include/usr/imgarchive.h b/src/include/usr/imgarchive.h new file mode 100644 index 000000000..bf0c18f55 --- /dev/null +++ b/src/include/usr/imgarchive.h @@ -0,0 +1,16 @@ +#ifndef _USR_IMGARCHIVE_H +#define _USR_IMGARCHIVE_H + +/** @file + * + * Archive image management + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include + +extern int imgextract ( struct image *image, const char *name ); + +#endif /* _USR_IMGARCHIVE_H */ diff --git a/src/usr/imgarchive.c b/src/usr/imgarchive.c new file mode 100644 index 000000000..6849dd510 --- /dev/null +++ b/src/usr/imgarchive.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include +#include +#include + +/** @file + * + * Archive image management + * + */ + +/** + * Extract archive image + * + * @v image Image + * @v name Extracted image name (or NULL to use default) + * @ret rc Return status code + */ +int imgextract ( struct image *image, const char *name ) { + struct image *extracted; + int rc; + + /* Extract archive image */ + if ( ( rc = image_extract ( image, name, &extracted ) ) != 0 ) { + printf ( "Could not extract image: %s\n", strerror ( rc ) ); + return rc; + } + + return 0; +} -- cgit v1.2.3-55-g7522 From 191f8825cbd17a6819545e5633287e3d934039b6 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 12 May 2021 13:54:59 +0100 Subject: [image] Allow single-member archive images to be executed transparently Provide image_extract_exec() as a helper method to allow single-member archive images (such as gzip compressed images) to be executed without an explicit "imgextract" step. Signed-off-by: Michael Brown --- src/core/archive.c | 30 ++++++++++++++++++++++++++++++ src/image/gzip.c | 1 + src/image/zlib.c | 1 + src/include/ipxe/image.h | 1 + 4 files changed, 33 insertions(+) (limited to 'src/core') diff --git a/src/core/archive.c b/src/core/archive.c index cd024bde3..7ef86bd9a 100644 --- a/src/core/archive.c +++ b/src/core/archive.c @@ -97,6 +97,36 @@ int image_extract ( struct image *image, const char *name, return rc; } +/** + * Extract and execute image + * + * @v image Image + * @ret rc Return status code + */ +int image_extract_exec ( struct image *image ) { + struct image *extracted; + int rc; + + /* Extract image */ + if ( ( rc = image_extract ( image, NULL, &extracted ) ) != 0 ) + goto err_extract; + + /* Set image command line */ + if ( ( rc = image_set_cmdline ( extracted, image->cmdline ) ) != 0 ) + goto err_set_cmdline; + + /* Set auto-unregister flag */ + extracted->flags |= IMAGE_AUTO_UNREGISTER; + + /* Tail-recurse into extracted image */ + return image_exec ( extracted ); + + err_set_cmdline: + unregister_image ( extracted ); + err_extract: + return rc; +} + /* Drag in objects via image_extract() */ REQUIRING_SYMBOL ( image_extract ); diff --git a/src/image/gzip.c b/src/image/gzip.c index 40728138b..98376e113 100644 --- a/src/image/gzip.c +++ b/src/image/gzip.c @@ -163,4 +163,5 @@ struct image_type gzip_image_type __image_type ( PROBE_NORMAL ) = { .name = "gzip", .probe = gzip_probe, .extract = gzip_extract, + .exec = image_extract_exec, }; diff --git a/src/image/zlib.c b/src/image/zlib.c index bc27142d7..a42c47e1b 100644 --- a/src/image/zlib.c +++ b/src/image/zlib.c @@ -159,4 +159,5 @@ struct image_type zlib_image_type __image_type ( PROBE_NORMAL ) = { .name = "zlib", .probe = zlib_probe, .extract = zlib_extract, + .exec = image_extract_exec, }; diff --git a/src/include/ipxe/image.h b/src/include/ipxe/image.h index c6e723dc6..0a5a26034 100644 --- a/src/include/ipxe/image.h +++ b/src/include/ipxe/image.h @@ -200,6 +200,7 @@ extern int image_asn1 ( struct image *image, size_t offset, struct asn1_cursor **cursor ); extern int image_extract ( struct image *image, const char *name, struct image **extracted ); +extern int image_extract_exec ( struct image *image ); /** * Increment reference count on an image -- cgit v1.2.3-55-g7522 From 62f732207e7cbd226a11b85581c2c33e1e6be409 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 12 May 2021 14:13:01 +0100 Subject: [image] Propagate trust flag to extracted archive images An extracted image is wholly derived from the original archive image. If the original archive image has been verified and marked as trusted, then this trust logically extends to any image extracted from it. Signed-off-by: Michael Brown --- src/core/archive.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/core') diff --git a/src/core/archive.c b/src/core/archive.c index 7ef86bd9a..bb62c7e47 100644 --- a/src/core/archive.c +++ b/src/core/archive.c @@ -82,6 +82,10 @@ int image_extract ( struct image *image, const char *name, if ( ( rc = register_image ( *extracted ) ) != 0 ) goto err_register; + /* Propagate trust flag */ + if ( image->flags & IMAGE_TRUSTED ) + image_trust ( *extracted ); + /* Drop local reference to image */ image_put ( *extracted ); -- cgit v1.2.3-55-g7522 From 661093054bcfae16d79404304d6f8318baf1231e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 18 May 2021 11:45:24 +0100 Subject: [libc] Add strncasecmp() Signed-off-by: Michael Brown --- src/core/string.c | 17 ++++++++++++++++- src/include/strings.h | 2 ++ src/tests/string_test.c | 8 ++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/string.c b/src/core/string.c index 188fe0864..9a1b9b72a 100644 --- a/src/core/string.c +++ b/src/core/string.c @@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include #include /** @file @@ -205,11 +206,24 @@ int strncmp ( const char *first, const char *second, size_t max ) { * @ret diff Difference */ int strcasecmp ( const char *first, const char *second ) { + + return strncasecmp ( first, second, ~( ( size_t ) 0 ) ); +} + +/** + * Compare case-insensitive strings + * + * @v first First string + * @v second Second string + * @v max Maximum length to compare + * @ret diff Difference + */ +int strncasecmp ( const char *first, const char *second, size_t max ) { const uint8_t *first_bytes = ( ( const uint8_t * ) first ); const uint8_t *second_bytes = ( ( const uint8_t * ) second ); int diff; - for ( ; ; first_bytes++, second_bytes++ ) { + for ( ; max-- ; first_bytes++, second_bytes++ ) { diff = ( toupper ( *first_bytes ) - toupper ( *second_bytes ) ); if ( diff ) @@ -217,6 +231,7 @@ int strcasecmp ( const char *first, const char *second ) { if ( ! *first_bytes ) return 0; } + return 0; } /** diff --git a/src/include/strings.h b/src/include/strings.h index fab26dc28..d7e9d6971 100644 --- a/src/include/strings.h +++ b/src/include/strings.h @@ -189,5 +189,7 @@ bzero ( void *dest, size_t len ) { } int __pure strcasecmp ( const char *first, const char *second ) __nonnull; +int __pure strncasecmp ( const char *first, const char *second, + size_t max ) __nonnull; #endif /* _STRINGS_H */ diff --git a/src/tests/string_test.c b/src/tests/string_test.c index 88a730aec..3afb8deb2 100644 --- a/src/tests/string_test.c +++ b/src/tests/string_test.c @@ -105,6 +105,14 @@ static void string_test_exec ( void ) { ok ( strcasecmp ( "Uncle", "Uncle Jack" ) != 0 ); ok ( strcasecmp ( "not", "equal" ) != 0 ); + /* Test strncasecmp() */ + ok ( strncasecmp ( "", "", 0 ) == 0 ); + ok ( strncasecmp ( "", "", 73 ) == 0 ); + ok ( strncasecmp ( "Uncle Jack", "Uncle jack", 47 ) == 0 ); + ok ( strncasecmp ( "Uncle Jack", "Uncle jake", 47 ) != 0 ); + ok ( strncasecmp ( "Uncle Jack", "Uncle jake", 9 ) != 0 ); + ok ( strncasecmp ( "Uncle Jack", "Uncle jake", 8 ) == 0 ); + /* Test memcmp() */ ok ( memcmp ( "", "", 0 ) == 0 ); ok ( memcmp ( "Foo", "Foo", 3 ) == 0 ); -- cgit v1.2.3-55-g7522 From bfca3db41e9af78e56e7a9b7f30121df83b6af0a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 17 May 2021 14:57:48 +0100 Subject: [cpio] Split out bzImage initrd CPIO header construction iPXE will construct CPIO headers for images that have a non-empty command line, thereby allowing raw images (without CPIO headers) to be injected into a dynamically constructed initrd. This feature is currently implemented within the BIOS-only bzImage format support. Split out the CPIO header construction logic to allow for reuse in other contexts such as in a UEFI build. Signed-off-by: Michael Brown --- src/arch/x86/image/bzimage.c | 52 ++------------------------ src/arch/x86/image/initrd.c | 1 + src/arch/x86/include/initrd.h | 7 ---- src/core/cpio.c | 85 +++++++++++++++++++++++++++++++++++++++++++ src/include/ipxe/cpio.h | 21 +++++++++++ 5 files changed, 110 insertions(+), 56 deletions(-) (limited to 'src/core') diff --git a/src/arch/x86/image/bzimage.c b/src/arch/x86/image/bzimage.c index 51498bf95..a782127a1 100644 --- a/src/arch/x86/image/bzimage.c +++ b/src/arch/x86/image/bzimage.c @@ -326,32 +326,6 @@ static void bzimage_set_cmdline ( struct image *image, DBGC ( image, "bzImage %p command line \"%s\"\n", image, cmdline ); } -/** - * Parse standalone image command line for cpio parameters - * - * @v image bzImage file - * @v cpio CPIO header - * @v cmdline Command line - */ -static void bzimage_parse_cpio_cmdline ( struct image *image, - struct cpio_header *cpio, - const char *cmdline ) { - char *arg; - char *end; - unsigned int mode; - - /* Look for "mode=" */ - if ( ( arg = strstr ( cmdline, "mode=" ) ) ) { - arg += 5; - mode = strtoul ( arg, &end, 8 /* Octal for file mode */ ); - if ( *end && ( *end != ' ' ) ) { - DBGC ( image, "bzImage %p strange \"mode=\"" - "terminator '%c'\n", image, *end ); - } - cpio_set_field ( cpio->c_mode, ( 0100000 | mode ) ); - } -} - /** * Align initrd length * @@ -374,11 +348,9 @@ static inline size_t bzimage_align ( size_t len ) { static size_t bzimage_load_initrd ( struct image *image, struct image *initrd, userptr_t address ) { - char *filename = initrd->cmdline; - char *cmdline; + const char *filename = cpio_name ( initrd ); struct cpio_header cpio; size_t offset; - size_t name_len; size_t pad_len; /* Do not include kernel image itself as an initrd */ @@ -386,25 +358,7 @@ static size_t bzimage_load_initrd ( struct image *image, return 0; /* Create cpio header for non-prebuilt images */ - if ( filename && filename[0] ) { - cmdline = strchr ( filename, ' ' ); - name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) ) - : strlen ( filename ) ) + 1 /* NUL */ ); - memset ( &cpio, '0', sizeof ( cpio ) ); - memcpy ( cpio.c_magic, CPIO_MAGIC, sizeof ( cpio.c_magic ) ); - cpio_set_field ( cpio.c_mode, 0100644 ); - cpio_set_field ( cpio.c_nlink, 1 ); - cpio_set_field ( cpio.c_filesize, initrd->len ); - cpio_set_field ( cpio.c_namesize, name_len ); - if ( cmdline ) { - bzimage_parse_cpio_cmdline ( image, &cpio, - ( cmdline + 1 /* ' ' */ )); - } - offset = ( ( sizeof ( cpio ) + name_len + 0x03 ) & ~0x03 ); - } else { - offset = 0; - name_len = 0; - } + offset = cpio_header ( initrd, &cpio ); /* Copy in initrd image body (and cpio header if applicable) */ if ( address ) { @@ -413,7 +367,7 @@ static size_t bzimage_load_initrd ( struct image *image, memset_user ( address, 0, 0, offset ); copy_to_user ( address, 0, &cpio, sizeof ( cpio ) ); copy_to_user ( address, sizeof ( cpio ), filename, - ( name_len - 1 /* NUL (or space) */ ) ); + cpio_name_len ( initrd ) ); } DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)" "%s%s\n", image, initrd, user_to_phys ( address, 0 ), diff --git a/src/arch/x86/image/initrd.c b/src/arch/x86/image/initrd.c index 49b959a91..d7b1f5773 100644 --- a/src/arch/x86/image/initrd.c +++ b/src/arch/x86/image/initrd.c @@ -29,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include /** @file * diff --git a/src/arch/x86/include/initrd.h b/src/arch/x86/include/initrd.h index ddb3e5a45..2fb9d3d3a 100644 --- a/src/arch/x86/include/initrd.h +++ b/src/arch/x86/include/initrd.h @@ -11,13 +11,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include -/** Minimum alignment for initrds - * - * Some versions of Linux complain about initrds that are not - * page-aligned. - */ -#define INITRD_ALIGN 4096 - /** Minimum free space required to reshuffle initrds * * Chosen to avoid absurdly long reshuffling times diff --git a/src/core/cpio.c b/src/core/cpio.c index 080c72daf..27aee7581 100644 --- a/src/core/cpio.c +++ b/src/core/cpio.c @@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); */ #include +#include #include #include @@ -45,3 +46,87 @@ void cpio_set_field ( char *field, unsigned long value ) { snprintf ( buf, sizeof ( buf ), "%08lx", value ); memcpy ( field, buf, 8 ); } + +/** + * Get CPIO image filename + * + * @v image Image + * @ret len CPIO filename length (0 for no filename) + */ +size_t cpio_name_len ( struct image *image ) { + const char *name = cpio_name ( image ); + char *sep; + size_t len; + + /* Check for existence of CPIO filename */ + if ( ! name ) + return 0; + + /* Locate separator (if any) */ + sep = strchr ( name, ' ' ); + len = ( sep ? ( ( size_t ) ( sep - name ) ) : strlen ( name ) ); + + return len; +} + +/** + * Parse CPIO image parameters + * + * @v image Image + * @v cpio CPIO header to fill in + */ +static void cpio_parse_cmdline ( struct image *image, + struct cpio_header *cpio ) { + const char *cmdline; + char *arg; + char *end; + unsigned int mode; + + /* Skip image filename */ + cmdline = ( cpio_name ( image ) + cpio_name_len ( image ) ); + + /* Look for "mode=" */ + if ( ( arg = strstr ( cmdline, "mode=" ) ) ) { + arg += 5; + mode = strtoul ( arg, &end, 8 /* Octal for file mode */ ); + if ( *end && ( *end != ' ' ) ) { + DBGC ( image, "CPIO %p strange \"mode=\" " + "terminator '%c'\n", image, *end ); + } + cpio_set_field ( cpio->c_mode, ( 0100000 | mode ) ); + } +} + +/** + * Construct CPIO header for image, if applicable + * + * @v image Image + * @v cpio CPIO header to fill in + * @ret len Length of magic CPIO header (including filename) + */ +size_t cpio_header ( struct image *image, struct cpio_header *cpio ) { + size_t name_len; + size_t len; + + /* Get filename length */ + name_len = cpio_name_len ( image ); + + /* Images with no filename are assumed to already be CPIO archives */ + if ( ! name_len ) + return 0; + + /* Construct CPIO header */ + memset ( cpio, '0', sizeof ( *cpio ) ); + memcpy ( cpio->c_magic, CPIO_MAGIC, sizeof ( cpio->c_magic ) ); + cpio_set_field ( cpio->c_mode, 0100644 ); + cpio_set_field ( cpio->c_nlink, 1 ); + cpio_set_field ( cpio->c_filesize, image->len ); + cpio_set_field ( cpio->c_namesize, ( name_len + 1 /* NUL */ ) ); + cpio_parse_cmdline ( image, cpio ); + + /* Calculate total length */ + len = ( ( sizeof ( *cpio ) + name_len + 1 /* NUL */ + CPIO_ALIGN - 1 ) + & ~( CPIO_ALIGN - 1 ) ); + + return len; +} diff --git a/src/include/ipxe/cpio.h b/src/include/ipxe/cpio.h index 0637c531d..9c5e22d5a 100644 --- a/src/include/ipxe/cpio.h +++ b/src/include/ipxe/cpio.h @@ -9,6 +9,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); +#include + /** A CPIO archive header * * All field are hexadecimal ASCII numbers padded with '0' on the @@ -48,6 +50,25 @@ struct cpio_header { /** CPIO magic */ #define CPIO_MAGIC "070701" +/** CPIO header length alignment */ +#define CPIO_ALIGN 4 + +/** Alignment for CPIO archives within an initrd */ +#define INITRD_ALIGN 4096 + +/** + * Get CPIO image name + * + * @v image Image + * @ret name Image name (not NUL terminated) + */ +static inline __attribute__ (( always_inline )) const char * +cpio_name ( struct image *image ) { + return image->cmdline; +} + extern void cpio_set_field ( char *field, unsigned long value ); +extern size_t cpio_name_len ( struct image *image ); +extern size_t cpio_header ( struct image *image, struct cpio_header *cpio ); #endif /* _IPXE_CPIO_H */ -- cgit v1.2.3-55-g7522 From 52300ccf98f94d48dbde84626097c7c22cfdf867 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 7 Jun 2021 13:18:19 +0100 Subject: [base64] Include terminating NUL within base64 character array Reported-by: Bernhard M. Wiedemann Signed-off-by: Michael Brown --- src/core/base64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/base64.c b/src/core/base64.c index e452f7d41..ec11be261 100644 --- a/src/core/base64.c +++ b/src/core/base64.c @@ -36,7 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * */ -static const char base64[64] = +static const char base64[ 64 + 1 /* NUL */ ] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** -- cgit v1.2.3-55-g7522 From 3dd1989ac0c0b699adcfe5c1c0efa2b229fd1e86 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 7 Jun 2021 13:26:01 +0100 Subject: [libc] Match standard prototype for putchar() Reported-by: Bernhard M. Wiedemann Signed-off-by: Michael Brown --- src/core/console.c | 5 ++++- src/include/stdio.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/console.c b/src/core/console.c index 7fd00036f..2b90809bf 100644 --- a/src/core/console.c +++ b/src/core/console.c @@ -20,11 +20,12 @@ unsigned int console_height = CONSOLE_DEFAULT_HEIGHT; * Write a single character to each console device * * @v character Character to be written + * @ret character Character written * * The character is written out to all enabled console devices, using * each device's console_driver::putchar() method. */ -void putchar ( int character ) { +int putchar ( int character ) { struct console_driver *console; /* Automatic LF -> CR,LF translation */ @@ -37,6 +38,8 @@ void putchar ( int character ) { console->putchar ) console->putchar ( character ); } + + return character; } /** diff --git a/src/include/stdio.h b/src/include/stdio.h index a618482ce..ac17da83d 100644 --- a/src/include/stdio.h +++ b/src/include/stdio.h @@ -6,7 +6,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include -extern void putchar ( int character ); +extern int putchar ( int character ); extern int getchar ( void ); -- cgit v1.2.3-55-g7522 From 2690f730961e335875cac5fd9cf870a94eaef11a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 1 Jul 2021 16:32:46 +0100 Subject: [uri] Make URI schemes case-insensitive RFC 3986 section 3.1 defines URI schemes as case-insensitive (though the canonical form is always lowercase). Use strcasecmp() rather than strcmp() to allow for case insensitivity in URI schemes. Requested-by: Andreas Hammarskjöld Signed-off-by: Michael Brown --- src/core/open.c | 3 ++- src/net/tcp/httpconn.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/open.c b/src/core/open.c index c27d8a021..f9198c9d9 100644 --- a/src/core/open.c +++ b/src/core/open.c @@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include +#include #include #include #include @@ -47,7 +48,7 @@ struct uri_opener * xfer_uri_opener ( const char *scheme ) { struct uri_opener *opener; for_each_table_entry ( opener, URI_OPENERS ) { - if ( strcmp ( scheme, opener->scheme ) == 0 ) + if ( strcasecmp ( scheme, opener->scheme ) == 0 ) return opener; } return NULL; diff --git a/src/net/tcp/httpconn.c b/src/net/tcp/httpconn.c index f9221b27e..538c4dcf6 100644 --- a/src/net/tcp/httpconn.c +++ b/src/net/tcp/httpconn.c @@ -32,6 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include +#include #include #include #include @@ -63,7 +64,7 @@ static struct http_scheme * http_scheme ( struct uri *uri ) { /* Identify scheme */ for_each_table_entry ( scheme, HTTP_SCHEMES ) { - if ( strcmp ( uri->scheme, scheme->name ) == 0 ) + if ( strcasecmp ( uri->scheme, scheme->name ) == 0 ) return scheme; } -- cgit v1.2.3-55-g7522