From 437fd90c0250dee670290f9b714253671a990160 Mon Sep 17 00:00:00 2001 From: José Pekkarinen Date: Wed, 18 May 2016 13:18:31 +0300 Subject: These changes are the raw update to qemu-2.6. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collission happened in the following patches: migration: do cleanup operation after completion(738df5b9) Bug fix.(1750c932f86) kvmclock: add a new function to update env->tsc.(b52baab2) The code provided by the patches was already in the upstreamed version. Change-Id: I3cc11841a6a76ae20887b2e245710199e1ea7f9a Signed-off-by: José Pekkarinen --- qemu/roms/ipxe/src/core/acpi.c | 6 +- qemu/roms/ipxe/src/core/ansicol.c | 6 +- qemu/roms/ipxe/src/core/ansicoldef.c | 6 +- qemu/roms/ipxe/src/core/ansiesc.c | 6 +- qemu/roms/ipxe/src/core/asprintf.c | 2 +- qemu/roms/ipxe/src/core/assert.c | 6 +- qemu/roms/ipxe/src/core/base16.c | 96 ++--- qemu/roms/ipxe/src/core/base64.c | 106 +++-- qemu/roms/ipxe/src/core/basename.c | 6 +- qemu/roms/ipxe/src/core/bitmap.c | 6 +- qemu/roms/ipxe/src/core/blockdev.c | 6 +- qemu/roms/ipxe/src/core/blocktrans.c | 261 ++++++++++++ qemu/roms/ipxe/src/core/console.c | 2 +- qemu/roms/ipxe/src/core/cpio.c | 6 +- qemu/roms/ipxe/src/core/ctype.c | 13 +- qemu/roms/ipxe/src/core/cwuri.c | 6 +- qemu/roms/ipxe/src/core/debug.c | 6 +- qemu/roms/ipxe/src/core/debug_md5.c | 6 +- qemu/roms/ipxe/src/core/device.c | 6 +- qemu/roms/ipxe/src/core/downloader.c | 112 ++---- qemu/roms/ipxe/src/core/edd.c | 6 +- qemu/roms/ipxe/src/core/errno.c | 2 +- qemu/roms/ipxe/src/core/exec.c | 6 +- qemu/roms/ipxe/src/core/fault.c | 82 ++++ qemu/roms/ipxe/src/core/fbcon.c | 6 +- qemu/roms/ipxe/src/core/fnrec.c | 6 +- qemu/roms/ipxe/src/core/gdbserial.c | 80 +++- qemu/roms/ipxe/src/core/gdbstub.c | 6 +- qemu/roms/ipxe/src/core/gdbudp.c | 6 +- qemu/roms/ipxe/src/core/getkey.c | 6 +- qemu/roms/ipxe/src/core/getopt.c | 6 +- qemu/roms/ipxe/src/core/image.c | 89 ++-- qemu/roms/ipxe/src/core/init.c | 6 +- qemu/roms/ipxe/src/core/interface.c | 31 +- qemu/roms/ipxe/src/core/iobuf.c | 36 +- qemu/roms/ipxe/src/core/isqrt.c | 6 +- qemu/roms/ipxe/src/core/job.c | 6 +- qemu/roms/ipxe/src/core/linebuf.c | 59 ++- qemu/roms/ipxe/src/core/lineconsole.c | 6 +- qemu/roms/ipxe/src/core/list.c | 6 +- qemu/roms/ipxe/src/core/log.c | 6 +- qemu/roms/ipxe/src/core/main.c | 11 +- qemu/roms/ipxe/src/core/malloc.c | 63 ++- qemu/roms/ipxe/src/core/memblock.c | 6 +- qemu/roms/ipxe/src/core/memmap_settings.c | 6 +- qemu/roms/ipxe/src/core/menu.c | 6 +- qemu/roms/ipxe/src/core/misc.c | 85 ---- qemu/roms/ipxe/src/core/monojob.c | 6 +- qemu/roms/ipxe/src/core/null_reboot.c | 6 +- qemu/roms/ipxe/src/core/null_sanboot.c | 6 +- qemu/roms/ipxe/src/core/null_time.c | 6 +- qemu/roms/ipxe/src/core/nvo.c | 6 +- qemu/roms/ipxe/src/core/open.c | 6 +- qemu/roms/ipxe/src/core/params.c | 6 +- qemu/roms/ipxe/src/core/parseopt.c | 9 +- qemu/roms/ipxe/src/core/pending.c | 6 +- qemu/roms/ipxe/src/core/pinger.c | 6 +- qemu/roms/ipxe/src/core/pixbuf.c | 6 +- qemu/roms/ipxe/src/core/pool.c | 114 ++++++ qemu/roms/ipxe/src/core/posix_io.c | 6 +- qemu/roms/ipxe/src/core/process.c | 6 +- qemu/roms/ipxe/src/core/profile.c | 6 +- qemu/roms/ipxe/src/core/random.c | 2 +- qemu/roms/ipxe/src/core/refcnt.c | 6 +- qemu/roms/ipxe/src/core/resolv.c | 6 +- qemu/roms/ipxe/src/core/serial.c | 349 +++++++--------- qemu/roms/ipxe/src/core/serial_console.c | 42 -- qemu/roms/ipxe/src/core/settings.c | 102 +++-- qemu/roms/ipxe/src/core/string.c | 648 ++++++++++++++++++------------ qemu/roms/ipxe/src/core/stringextra.c | 188 --------- qemu/roms/ipxe/src/core/strtoull.c | 60 --- qemu/roms/ipxe/src/core/time.c | 6 +- qemu/roms/ipxe/src/core/timer.c | 6 +- qemu/roms/ipxe/src/core/uart.c | 153 +++++++ qemu/roms/ipxe/src/core/uri.c | 15 +- qemu/roms/ipxe/src/core/uuid.c | 6 +- qemu/roms/ipxe/src/core/version.c | 7 +- qemu/roms/ipxe/src/core/vsprintf.c | 6 +- qemu/roms/ipxe/src/core/wchar.c | 6 +- qemu/roms/ipxe/src/core/xfer.c | 49 ++- qemu/roms/ipxe/src/core/xferbuf.c | 262 ++++++++++-- 81 files changed, 2174 insertions(+), 1256 deletions(-) create mode 100644 qemu/roms/ipxe/src/core/blocktrans.c create mode 100644 qemu/roms/ipxe/src/core/fault.c delete mode 100644 qemu/roms/ipxe/src/core/misc.c create mode 100644 qemu/roms/ipxe/src/core/pool.c delete mode 100644 qemu/roms/ipxe/src/core/serial_console.c delete mode 100644 qemu/roms/ipxe/src/core/strtoull.c create mode 100644 qemu/roms/ipxe/src/core/uart.c (limited to 'qemu/roms/ipxe/src/core') diff --git a/qemu/roms/ipxe/src/core/acpi.c b/qemu/roms/ipxe/src/core/acpi.c index 330f50631..b0ccfa78d 100644 --- a/qemu/roms/ipxe/src/core/acpi.c +++ b/qemu/roms/ipxe/src/core/acpi.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/ansicol.c b/qemu/roms/ipxe/src/core/ansicol.c index 142a00f8d..ddf9ba77c 100644 --- a/qemu/roms/ipxe/src/core/ansicol.c +++ b/qemu/roms/ipxe/src/core/ansicol.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/ansicoldef.c b/qemu/roms/ipxe/src/core/ansicoldef.c index dd89f3b70..6d8598e11 100644 --- a/qemu/roms/ipxe/src/core/ansicoldef.c +++ b/qemu/roms/ipxe/src/core/ansicoldef.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/ansiesc.c b/qemu/roms/ipxe/src/core/ansiesc.c index ca9a73ce0..7f545db0e 100644 --- a/qemu/roms/ipxe/src/core/ansiesc.c +++ b/qemu/roms/ipxe/src/core/ansiesc.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/asprintf.c b/qemu/roms/ipxe/src/core/asprintf.c index 03cf45cfc..00edf8e11 100644 --- a/qemu/roms/ipxe/src/core/asprintf.c +++ b/qemu/roms/ipxe/src/core/asprintf.c @@ -4,7 +4,7 @@ #include #include -FILE_LICENCE ( GPL2_OR_LATER ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** * Write a formatted string to newly allocated memory. diff --git a/qemu/roms/ipxe/src/core/assert.c b/qemu/roms/ipxe/src/core/assert.c index 0791ea7b9..294e766be 100644 --- a/qemu/roms/ipxe/src/core/assert.c +++ b/qemu/roms/ipxe/src/core/assert.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/base16.c b/qemu/roms/ipxe/src/core/base16.c index bf9cc21bb..f9e0f3364 100644 --- a/qemu/roms/ipxe/src/core/base16.c +++ b/qemu/roms/ipxe/src/core/base16.c @@ -15,14 +15,20 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include -#include #include #include +#include +#include +#include #include /** @file @@ -32,48 +38,42 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ /** - * Base16-encode data + * Encode hexadecimal string (with optional byte separator character) * + * @v separator Byte separator character, or 0 for no separator * @v raw Raw data - * @v len Length of raw data - * @v encoded Buffer for encoded string - * - * The buffer must be the correct length for the encoded string. Use - * something like - * - * char buf[ base16_encoded_len ( len ) + 1 ]; - * - * (the +1 is for the terminating NUL) to provide a buffer of the - * correct size. + * @v raw_len Length of raw data + * @v data Buffer + * @v len Length of buffer + * @ret len Encoded length */ -void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) { - const uint8_t *raw_bytes = raw; - char *encoded_bytes = encoded; - size_t remaining = len; - - /* Encode each byte */ - for ( ; remaining-- ; encoded_bytes += 2 ) { - sprintf ( encoded_bytes, "%02x", *(raw_bytes++) ); +size_t hex_encode ( char separator, const void *raw, size_t raw_len, + char *data, size_t len ) { + const uint8_t *bytes = raw; + const char delimiter[2] = { separator, '\0' }; + size_t used = 0; + unsigned int i; + + if ( len ) + data[0] = 0; /* Ensure that a terminating NUL exists */ + for ( i = 0 ; i < raw_len ; i++ ) { + used += ssnprintf ( ( data + used ), ( len - used ), + "%s%02x", ( used ? delimiter : "" ), + bytes[i] ); } - - /* Ensure terminating NUL exists even if length was zero */ - *encoded_bytes = '\0'; - - DBG ( "Base16-encoded to \"%s\":\n", encoded ); - DBG_HDA ( 0, raw, len ); - assert ( strlen ( encoded ) == base16_encoded_len ( len ) ); + return used; } /** - * Decode hexadecimal string + * Decode hexadecimal string (with optional byte separator character) * - * @v encoded Encoded string * @v separator Byte separator character, or 0 for no separator + * @v encoded Encoded string * @v data Buffer * @v len Length of buffer * @ret len Length of data, or negative error */ -int hex_decode ( const char *encoded, char separator, void *data, size_t len ) { +int hex_decode ( char separator, const char *encoded, void *data, size_t len ) { uint8_t *out = data; unsigned int count = 0; unsigned int sixteens; @@ -87,13 +87,13 @@ int hex_decode ( const char *encoded, char separator, void *data, size_t len ) { /* Extract digits. Note that either digit may be NUL, * which would be interpreted as an invalid value by - * strtoul_charval(); there is therefore no need for an + * digit_value(); there is therefore no need for an * explicit end-of-string check. */ - sixteens = strtoul_charval ( *(encoded++) ); + sixteens = digit_value ( *(encoded++) ); if ( sixteens >= 16 ) return -EINVAL; - units = strtoul_charval ( *(encoded++) ); + units = digit_value ( *(encoded++) ); if ( units >= 16 ) return -EINVAL; @@ -105,31 +105,3 @@ int hex_decode ( const char *encoded, char separator, void *data, size_t len ) { } return count; } - -/** - * Base16-decode data - * - * @v encoded Encoded string - * @v raw Raw data - * @ret len Length of raw data, or negative error - * - * The buffer must be large enough to contain the decoded data. Use - * something like - * - * char buf[ base16_decoded_max_len ( encoded ) ]; - * - * to provide a buffer of the correct size. - */ -int base16_decode ( const char *encoded, uint8_t *raw ) { - int len; - - len = hex_decode ( encoded, 0, raw, -1UL ); - if ( len < 0 ) - return len; - - DBG ( "Base16-decoded \"%s\" to:\n", encoded ); - DBG_HDA ( 0, raw, len ); - assert ( len <= ( int ) base16_decoded_max_len ( encoded ) ); - - return len; -} diff --git a/qemu/roms/ipxe/src/core/base64.c b/qemu/roms/ipxe/src/core/base64.c index bdaf70957..e452f7d41 100644 --- a/qemu/roms/ipxe/src/core/base64.c +++ b/qemu/roms/ipxe/src/core/base64.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include @@ -39,80 +43,73 @@ static const char base64[64] = * Base64-encode data * * @v raw Raw data - * @v len Length of raw data - * @v encoded Buffer for encoded string - * - * The buffer must be the correct length for the encoded string. Use - * something like - * - * char buf[ base64_encoded_len ( len ) + 1 ]; - * - * (the +1 is for the terminating NUL) to provide a buffer of the - * correct size. + * @v raw_len Length of raw data + * @v data Buffer + * @v len Length of buffer + * @ret len Encoded length */ -void base64_encode ( const uint8_t *raw, size_t len, char *encoded ) { +size_t base64_encode ( const void *raw, size_t raw_len, char *data, + size_t len ) { const uint8_t *raw_bytes = ( ( const uint8_t * ) raw ); - uint8_t *encoded_bytes = ( ( uint8_t * ) encoded ); - size_t raw_bit_len = ( 8 * len ); + size_t raw_bit_len = ( 8 * raw_len ); + size_t used = 0; unsigned int bit; unsigned int byte; unsigned int shift; unsigned int tmp; - for ( bit = 0 ; bit < raw_bit_len ; bit += 6 ) { + for ( bit = 0 ; bit < raw_bit_len ; bit += 6, used++ ) { byte = ( bit / 8 ); shift = ( bit % 8 ); tmp = ( raw_bytes[byte] << shift ); - if ( ( byte + 1 ) < len ) + if ( ( byte + 1 ) < raw_len ) tmp |= ( raw_bytes[ byte + 1 ] >> ( 8 - shift ) ); tmp = ( ( tmp >> 2 ) & 0x3f ); - *(encoded_bytes++) = base64[tmp]; + if ( used < len ) + data[used] = base64[tmp]; + } + for ( ; ( bit % 8 ) != 0 ; bit += 6, used++ ) { + if ( used < len ) + data[used] = '='; } - for ( ; ( bit % 8 ) != 0 ; bit += 6 ) - *(encoded_bytes++) = '='; - *(encoded_bytes++) = '\0'; + if ( used < len ) + data[used] = '\0'; + if ( len ) + data[ len - 1 ] = '\0'; /* Ensure terminator exists */ - DBG ( "Base64-encoded to \"%s\":\n", encoded ); - DBG_HDA ( 0, raw, len ); - assert ( strlen ( encoded ) == base64_encoded_len ( len ) ); + return used; } /** * Base64-decode string * * @v encoded Encoded string - * @v raw Raw data - * @ret len Length of raw data, or negative error - * - * The buffer must be large enough to contain the decoded data. Use - * something like - * - * char buf[ base64_decoded_max_len ( encoded ) ]; - * - * to provide a buffer of the correct size. + * @v data Buffer + * @v len Length of buffer + * @ret len Length of data, or negative error */ -int base64_decode ( const char *encoded, uint8_t *raw ) { - const uint8_t *encoded_bytes = ( ( const uint8_t * ) encoded ); - uint8_t *raw_bytes = ( ( uint8_t * ) raw ); - uint8_t encoded_byte; +int base64_decode ( const char *encoded, void *data, size_t len ) { + const char *in = encoded; + uint8_t *out = data; + uint8_t in_char; char *match; - int decoded; + int in_bits; unsigned int bit = 0; unsigned int pad_count = 0; - size_t len; + size_t offset; - /* Zero the raw data */ - memset ( raw, 0, base64_decoded_max_len ( encoded ) ); + /* Zero the output buffer */ + memset ( data, 0, len ); /* Decode string */ - while ( ( encoded_byte = *(encoded_bytes++) ) ) { + while ( ( in_char = *(in++) ) ) { /* Ignore whitespace characters */ - if ( isspace ( encoded_byte ) ) + if ( isspace ( in_char ) ) continue; /* Process pad characters */ - if ( encoded_byte == '=' ) { + if ( in_char == '=' ) { if ( pad_count >= 2 ) { DBG ( "Base64-encoded string \"%s\" has too " "many pad characters\n", encoded ); @@ -129,18 +126,22 @@ int base64_decode ( const char *encoded, uint8_t *raw ) { } /* Process normal characters */ - match = strchr ( base64, encoded_byte ); + match = strchr ( base64, in_char ); if ( ! match ) { DBG ( "Base64-encoded string \"%s\" contains invalid " - "character '%c'\n", encoded, encoded_byte ); + "character '%c'\n", encoded, in_char ); return -EINVAL; } - decoded = ( match - base64 ); + in_bits = ( match - base64 ); /* Add to raw data */ - decoded <<= 2; - raw_bytes[ bit / 8 ] |= ( decoded >> ( bit % 8 ) ); - raw_bytes[ bit / 8 + 1 ] |= ( decoded << ( 8 - ( bit % 8 ) ) ); + in_bits <<= 2; + offset = ( bit / 8 ); + if ( offset < len ) + out[offset] |= ( in_bits >> ( bit % 8 ) ); + offset++; + if ( offset < len ) + out[offset] |= ( in_bits << ( 8 - ( bit % 8 ) ) ); bit += 6; } @@ -150,12 +151,7 @@ int base64_decode ( const char *encoded, uint8_t *raw ) { "%d\n", encoded, bit ); return -EINVAL; } - len = ( bit / 8 ); - - DBG ( "Base64-decoded \"%s\" to:\n", encoded ); - DBG_HDA ( 0, raw, len ); - assert ( len <= base64_decoded_max_len ( encoded ) ); /* Return length in bytes */ - return ( len ); + return ( bit / 8 ); } diff --git a/qemu/roms/ipxe/src/core/basename.c b/qemu/roms/ipxe/src/core/basename.c index b534a7886..f4f929517 100644 --- a/qemu/roms/ipxe/src/core/basename.c +++ b/qemu/roms/ipxe/src/core/basename.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** * @file diff --git a/qemu/roms/ipxe/src/core/bitmap.c b/qemu/roms/ipxe/src/core/bitmap.c index 0d1152327..2aac33870 100644 --- a/qemu/roms/ipxe/src/core/bitmap.c +++ b/qemu/roms/ipxe/src/core/bitmap.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/blockdev.c b/qemu/roms/ipxe/src/core/blockdev.c index 9d118cb2f..c219d9673 100644 --- a/qemu/roms/ipxe/src/core/blockdev.c +++ b/qemu/roms/ipxe/src/core/blockdev.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/blocktrans.c b/qemu/roms/ipxe/src/core/blocktrans.c new file mode 100644 index 000000000..3f32f9cf8 --- /dev/null +++ b/qemu/roms/ipxe/src/core/blocktrans.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2015 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 ); + +/** + * @file + * + * Block device translator + * + */ + +#include +#include +#include +#include +#include +#include +#include + +/** + * Reallocate block device translator data buffer + * + * @v xferbuf Data transfer buffer + * @v len New length (or zero to free buffer) + * @ret rc Return status code + */ +static int blktrans_xferbuf_realloc ( struct xfer_buffer *xferbuf, + size_t len ) { + struct block_translator *blktrans = + container_of ( xferbuf, struct block_translator, xferbuf ); + + /* Record length, if applicable */ + if ( blktrans->buffer ) { + + /* We have a (non-reallocatable) data buffer */ + return -ENOTSUP; + + } else { + + /* Record length (for block device capacity) */ + xferbuf->len = len; + return 0; + } +} + +/** + * Write data to block device translator data buffer + * + * @v xferbuf Data transfer buffer + * @v offset Starting offset + * @v data Data to copy + * @v len Length of data + */ +static void blktrans_xferbuf_write ( struct xfer_buffer *xferbuf, size_t offset, + const void *data, size_t len ) { + struct block_translator *blktrans = + container_of ( xferbuf, struct block_translator, xferbuf ); + + /* Write data to buffer, if applicable */ + if ( blktrans->buffer ) { + + /* Write data to buffer */ + copy_to_user ( blktrans->buffer, offset, data, len ); + + } else { + + /* Sanity check */ + assert ( len == 0 ); + } +} + +/** + * Read data from block device translator data buffer + * + * @v xferbuf Data transfer buffer + * @v offset Starting offset + * @v data Data to read + * @v len Length of data + */ +static void blktrans_xferbuf_read ( struct xfer_buffer *xferbuf, size_t offset, + void *data, size_t len ) { + struct block_translator *blktrans = + container_of ( xferbuf, struct block_translator, xferbuf ); + + /* Read data from buffer, if applicable */ + if ( blktrans->buffer ) { + + /* Read data from buffer */ + copy_from_user ( data, blktrans->buffer, offset, len ); + + } else { + + /* Sanity check */ + assert ( len == 0 ); + } +} + +/** Block device translator data transfer buffer operations */ +static struct xfer_buffer_operations blktrans_xferbuf_operations = { + .realloc = blktrans_xferbuf_realloc, + .write = blktrans_xferbuf_write, + .read = blktrans_xferbuf_read, +}; + +/** + * Close block device translator + * + * @v blktrans Block device translator + * @v rc Reason for close + */ +static void blktrans_close ( struct block_translator *blktrans, int rc ) { + struct block_device_capacity capacity; + + /* Report block device capacity, if applicable */ + if ( ( rc == 0 ) && ( blktrans->blksize ) ) { + + /* Construct block device capacity */ + capacity.blocks = + ( blktrans->xferbuf.len / blktrans->blksize ); + capacity.blksize = blktrans->blksize; + capacity.max_count = -1U; + + /* Report block device capacity */ + block_capacity ( &blktrans->block, &capacity ); + } + + /* Shut down interfaces */ + intf_shutdown ( &blktrans->xfer, rc ); + intf_shutdown ( &blktrans->block, rc ); +} + +/** + * Deliver data + * + * @v blktrans Block device translator + * @v iobuf I/O buffer + * @v meta Data transfer metadata + * @ret rc Return status code + */ +static int blktrans_deliver ( struct block_translator *blktrans, + struct io_buffer *iobuf, + struct xfer_metadata *meta ) { + int rc; + + /* Deliver to buffer */ + if ( ( rc = xferbuf_deliver ( &blktrans->xferbuf, iob_disown ( iobuf ), + meta ) ) != 0 ) { + DBGC ( blktrans, "BLKTRANS %p could not deliver: %s\n", + blktrans, strerror ( rc ) ); + goto err; + } + + return 0; + + err: + blktrans_close ( blktrans, rc ); + return rc; +} + +/** + * Get underlying data transfer buffer + * + * @v blktrans Block device translator + * @ret xferbuf Data transfer buffer + */ +static struct xfer_buffer * +blktrans_buffer ( struct block_translator *blktrans ) { + + return &blktrans->xferbuf; +} + +/** Block device translator block device interface operations */ +static struct interface_operation blktrans_block_operations[] = { + INTF_OP ( intf_close, struct block_translator *, blktrans_close ), +}; + +/** Block device translator block device interface descriptor */ +static struct interface_descriptor blktrans_block_desc = + INTF_DESC_PASSTHRU ( struct block_translator, block, + blktrans_block_operations, xfer ); + +/** Block device translator data transfer interface operations */ +static struct interface_operation blktrans_xfer_operations[] = { + INTF_OP ( xfer_deliver, struct block_translator *, blktrans_deliver ), + INTF_OP ( xfer_buffer, struct block_translator *, blktrans_buffer ), + INTF_OP ( intf_close, struct block_translator *, blktrans_close ), +}; + +/** Block device translator data transfer interface descriptor */ +static struct interface_descriptor blktrans_xfer_desc = + INTF_DESC_PASSTHRU ( struct block_translator, xfer, + blktrans_xfer_operations, block ); + +/** + * Insert block device translator + * + * @v block Block device interface + * @v buffer Data buffer (or UNULL) + * @v size Length of data buffer, or block size + * @ret rc Return status code + */ +int block_translate ( struct interface *block, userptr_t buffer, size_t size ) { + struct block_translator *blktrans; + int rc; + + /* Allocate and initialise structure */ + blktrans = zalloc ( sizeof ( *blktrans ) ); + if ( ! blktrans ) { + rc = -ENOMEM; + goto err_alloc; + } + ref_init ( &blktrans->refcnt, NULL ); + intf_init ( &blktrans->block, &blktrans_block_desc, &blktrans->refcnt ); + intf_init ( &blktrans->xfer, &blktrans_xfer_desc, &blktrans->refcnt ); + blktrans->xferbuf.op = &blktrans_xferbuf_operations; + blktrans->buffer = buffer; + if ( buffer ) { + blktrans->xferbuf.len = size; + } else { + blktrans->blksize = size; + } + + /* Attach to interfaces, mortalise self, and return */ + assert ( block->dest != &null_intf ); + intf_plug_plug ( &blktrans->xfer, block->dest ); + intf_plug_plug ( &blktrans->block, block ); + ref_put ( &blktrans->refcnt ); + + DBGC2 ( blktrans, "BLKTRANS %p created", blktrans ); + if ( buffer ) { + DBGC2 ( blktrans, " for %#lx+%#zx", + user_to_phys ( buffer, 0 ), size ); + } + DBGC2 ( blktrans, "\n" ); + return 0; + + ref_put ( &blktrans->refcnt ); + err_alloc: + return rc; +} diff --git a/qemu/roms/ipxe/src/core/console.c b/qemu/roms/ipxe/src/core/console.c index 141d8f0f0..7fd00036f 100644 --- a/qemu/roms/ipxe/src/core/console.c +++ b/qemu/roms/ipxe/src/core/console.c @@ -5,7 +5,7 @@ /** @file */ -FILE_LICENCE ( GPL2_OR_LATER ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** Current console usage */ int console_usage = CONSOLE_USAGE_STDOUT; diff --git a/qemu/roms/ipxe/src/core/cpio.c b/qemu/roms/ipxe/src/core/cpio.c index 3a5f4d2b6..080c72daf 100644 --- a/qemu/roms/ipxe/src/core/cpio.c +++ b/qemu/roms/ipxe/src/core/cpio.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/ctype.c b/qemu/roms/ipxe/src/core/ctype.c index c812346a0..891af71ea 100644 --- a/qemu/roms/ipxe/src/core/ctype.c +++ b/qemu/roms/ipxe/src/core/ctype.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** * @file @@ -31,11 +35,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** * Check to see if character is a space * - * @v c Character + * @v character Character * @ret isspace Character is a space */ -int isspace ( int c ) { - switch ( c ) { +int isspace ( int character ) { + + switch ( character ) { case ' ' : case '\f' : case '\n' : diff --git a/qemu/roms/ipxe/src/core/cwuri.c b/qemu/roms/ipxe/src/core/cwuri.c index 5865552a0..612f0b179 100644 --- a/qemu/roms/ipxe/src/core/cwuri.c +++ b/qemu/roms/ipxe/src/core/cwuri.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/debug.c b/qemu/roms/ipxe/src/core/debug.c index 7ded47089..def5d8b09 100644 --- a/qemu/roms/ipxe/src/core/debug.c +++ b/qemu/roms/ipxe/src/core/debug.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/debug_md5.c b/qemu/roms/ipxe/src/core/debug_md5.c index f049ac757..d0dbad9ed 100644 --- a/qemu/roms/ipxe/src/core/debug_md5.c +++ b/qemu/roms/ipxe/src/core/debug_md5.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/device.c b/qemu/roms/ipxe/src/core/device.c index 330f95c5a..77d7b719b 100644 --- a/qemu/roms/ipxe/src/core/device.c +++ b/qemu/roms/ipxe/src/core/device.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/downloader.c b/qemu/roms/ipxe/src/core/downloader.c index ec69db6b1..d745f3617 100644 --- a/qemu/roms/ipxe/src/core/downloader.c +++ b/qemu/roms/ipxe/src/core/downloader.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include @@ -29,7 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include +#include #include /** @file @@ -38,14 +42,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ -/** Receive profiler */ -static struct profiler downloader_rx_profiler __profiler = - { .name = "downloader.rx" }; - -/** Data copy profiler */ -static struct profiler downloader_copy_profiler __profiler = - { .name = "downloader.copy" }; - /** A downloader */ struct downloader { /** Reference count for this object */ @@ -58,8 +54,8 @@ struct downloader { /** Image to contain downloaded file */ struct image *image; - /** Current position within image buffer */ - size_t pos; + /** Data transfer buffer */ + struct xfer_buffer buffer; }; /** @@ -92,42 +88,14 @@ static void downloader_finished ( struct downloader *downloader, int rc ) { downloader->image->name, strerror ( rc ) ); } + /* Update image length */ + downloader->image->len = downloader->buffer.len; + /* Shut down interfaces */ intf_shutdown ( &downloader->xfer, rc ); intf_shutdown ( &downloader->job, rc ); } -/** - * Ensure that download buffer is large enough for the specified size - * - * @v downloader Downloader - * @v len Required minimum size - * @ret rc Return status code - */ -static int downloader_ensure_size ( struct downloader *downloader, - size_t len ) { - userptr_t new_buffer; - - /* If buffer is already large enough, do nothing */ - if ( len <= downloader->image->len ) - return 0; - - DBGC ( downloader, "Downloader %p extending to %zd bytes\n", - downloader, len ); - - /* Extend buffer */ - new_buffer = urealloc ( downloader->image->data, len ); - if ( ! new_buffer ) { - DBGC ( downloader, "Downloader %p could not extend buffer to " - "%zd bytes\n", downloader, len ); - return -ENOSPC; - } - downloader->image->data = new_buffer; - downloader->image->len = len; - - return 0; -} - /**************************************************************************** * * Job control interface @@ -148,8 +116,8 @@ static int downloader_progress ( struct downloader *downloader, * arrive out of order (e.g. with multicast protocols), but * it's a reasonable first approximation. */ - progress->completed = downloader->pos; - progress->total = downloader->image->len; + progress->completed = downloader->buffer.pos; + progress->total = downloader->buffer.len; return 0; } @@ -171,44 +139,37 @@ static int downloader_progress ( struct downloader *downloader, static int downloader_xfer_deliver ( struct downloader *downloader, struct io_buffer *iobuf, struct xfer_metadata *meta ) { - size_t len; - size_t max; int rc; - /* Start profiling */ - profile_start ( &downloader_rx_profiler ); - - /* Calculate new buffer position */ - if ( meta->flags & XFER_FL_ABS_OFFSET ) - downloader->pos = 0; - downloader->pos += meta->offset; - - /* Ensure that we have enough buffer space for this data */ - len = iob_len ( iobuf ); - max = ( downloader->pos + len ); - if ( ( rc = downloader_ensure_size ( downloader, max ) ) != 0 ) - goto done; - - /* Copy data to buffer */ - profile_start ( &downloader_copy_profiler ); - copy_to_user ( downloader->image->data, downloader->pos, - iobuf->data, len ); - profile_stop ( &downloader_copy_profiler ); - - /* Update current buffer position */ - downloader->pos += len; - - done: - free_iob ( iobuf ); - if ( rc != 0 ) - downloader_finished ( downloader, rc ); - profile_stop ( &downloader_rx_profiler ); + /* Add data to buffer */ + if ( ( rc = xferbuf_deliver ( &downloader->buffer, iob_disown ( iobuf ), + meta ) ) != 0 ) + goto err_deliver; + + return 0; + + err_deliver: + downloader_finished ( downloader, rc ); return rc; } +/** + * Get underlying data transfer buffer + * + * @v downloader Downloader + * @ret xferbuf Data transfer buffer, or NULL on error + */ +static struct xfer_buffer * +downloader_xfer_buffer ( struct downloader *downloader ) { + + /* Provide direct access to underlying data transfer buffer */ + return &downloader->buffer; +} + /** Downloader data transfer interface operations */ static struct interface_operation downloader_xfer_operations[] = { INTF_OP ( xfer_deliver, struct downloader *, downloader_xfer_deliver ), + INTF_OP ( xfer_buffer, struct downloader *, downloader_xfer_buffer ), INTF_OP ( intf_close, struct downloader *, downloader_finished ), }; @@ -262,6 +223,7 @@ int create_downloader ( struct interface *job, struct image *image ) { intf_init ( &downloader->xfer, &downloader_xfer_desc, &downloader->refcnt ); downloader->image = image_get ( image ); + xferbuf_umalloc_init ( &downloader->buffer, &image->data ); /* Instantiate child objects and attach to our interfaces */ if ( ( rc = xfer_open_uri ( &downloader->xfer, image->uri ) ) != 0 ) diff --git a/qemu/roms/ipxe/src/core/edd.c b/qemu/roms/ipxe/src/core/edd.c index d574ea6c0..a50b74ab1 100644 --- a/qemu/roms/ipxe/src/core/edd.c +++ b/qemu/roms/ipxe/src/core/edd.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/errno.c b/qemu/roms/ipxe/src/core/errno.c index 06905561f..5de15bb92 100644 --- a/qemu/roms/ipxe/src/core/errno.c +++ b/qemu/roms/ipxe/src/core/errno.c @@ -1,6 +1,6 @@ #include -FILE_LICENCE ( GPL2_OR_LATER ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/exec.c b/qemu/roms/ipxe/src/core/exec.c index 1c85705ae..2c2ade0a5 100644 --- a/qemu/roms/ipxe/src/core/exec.c +++ b/qemu/roms/ipxe/src/core/exec.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/fault.c b/qemu/roms/ipxe/src/core/fault.c new file mode 100644 index 000000000..63d3ccacf --- /dev/null +++ b/qemu/roms/ipxe/src/core/fault.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2015 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 (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 +#include +#include + +/** @file + * + * Fault injection + * + */ + +/** + * Inject fault with a specified probability + * + * @v rate Reciprocal of fault probability (must be non-zero) + * @ret rc Return status code + */ +int inject_fault_nonzero ( unsigned int rate ) { + + /* Do nothing unless we want to inject a fault now */ + if ( ( random() % rate ) != 0 ) + return 0; + + /* Generate error number here so that faults can be injected + * into files that don't themselves have error file + * identifiers (via errfile.h). + */ + return -EFAULT; +} + +/** + * Corrupt data with a specified probability + * + * @v rate Reciprocal of fault probability (must be non-zero) + * @v data Data + * @v len Length of data + * @ret rc Return status code + */ +void inject_corruption_nonzero ( unsigned int rate, const void *data, + size_t len ) { + uint8_t *writable; + size_t offset; + + /* Do nothing if we have no data to corrupt */ + if ( ! len ) + return; + + /* Do nothing unless we want to inject a fault now */ + if ( ! inject_fault_nonzero ( rate ) ) + return; + + /* Get a writable pointer to the nominally read-only data */ + writable = ( ( uint8_t * ) data ); + + /* Pick a random victim byte and zap it */ + offset = ( random() % len ); + writable[offset] ^= random(); +} diff --git a/qemu/roms/ipxe/src/core/fbcon.c b/qemu/roms/ipxe/src/core/fbcon.c index 72d6a6789..6d8b0086d 100644 --- a/qemu/roms/ipxe/src/core/fbcon.c +++ b/qemu/roms/ipxe/src/core/fbcon.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/fnrec.c b/qemu/roms/ipxe/src/core/fnrec.c index 3453c8b6a..0430817f8 100644 --- a/qemu/roms/ipxe/src/core/fnrec.c +++ b/qemu/roms/ipxe/src/core/fnrec.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/gdbserial.c b/qemu/roms/ipxe/src/core/gdbserial.c index 6f78c88bf..0983f2557 100644 --- a/qemu/roms/ipxe/src/core/gdbserial.c +++ b/qemu/roms/ipxe/src/core/gdbserial.c @@ -15,35 +15,105 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); +#include +#include +#include #include -#include +#include #include #include +#include + +/* UART port number */ +#ifdef COMCONSOLE +#define GDBSERIAL_PORT COMCONSOLE +#else +#define GDBSERIAL_PORT 0 +#endif + +/* UART baud rate */ +#ifdef COMPRESERVE +#define GDBSERIAL_BAUD 0 +#else +#define GDBSERIAL_BAUD COMSPEED +#endif + +/* UART line control register value */ +#ifdef COMPRESERVE +#define GDBSERIAL_LCR 0 +#else +#define GDBSERIAL_LCR UART_LCR_WPS ( COMDATA, COMPARITY, COMSTOP ) +#endif + +/** GDB serial UART */ +static struct uart gdbserial_uart; struct gdb_transport serial_gdb_transport __gdb_transport; static size_t gdbserial_recv ( char *buf, size_t len ) { + assert ( len > 0 ); - buf [ 0 ] = serial_getc(); + while ( ! uart_data_ready ( &gdbserial_uart ) ) {} + buf[0] = uart_receive ( &gdbserial_uart ); return 1; } static void gdbserial_send ( const char *buf, size_t len ) { + while ( len-- > 0 ) { - serial_putc ( *buf++ ); + uart_transmit ( &gdbserial_uart, *buf++ ); } } +static int gdbserial_init ( int argc, char **argv ) { + unsigned int port; + char *endp; + + if ( argc == 0 ) { + port = GDBSERIAL_PORT; + } else if ( argc == 1 ) { + port = strtoul ( argv[0], &endp, 10 ); + if ( *endp ) { + printf ( "serial: invalid port\n" ); + return 1; + } + } else { + printf ( "serial: syntax \n" ); + return 1; + } + + if ( ! gdbserial_configure ( port, GDBSERIAL_BAUD, GDBSERIAL_LCR ) ) { + printf ( "serial: unable to configure\n" ); + return 1; + } + + return 0; +} + struct gdb_transport serial_gdb_transport __gdb_transport = { .name = "serial", + .init = gdbserial_init, .recv = gdbserial_recv, .send = gdbserial_send, }; -struct gdb_transport *gdbserial_configure ( void ) { +struct gdb_transport * gdbserial_configure ( unsigned int port, + unsigned int baud, uint8_t lcr ) { + int rc; + + if ( ( rc = uart_select ( &gdbserial_uart, port ) ) != 0 ) + return NULL; + + if ( ( rc = uart_init ( &gdbserial_uart, baud, lcr ) ) != 0 ) + return NULL; + return &serial_gdb_transport; } diff --git a/qemu/roms/ipxe/src/core/gdbstub.c b/qemu/roms/ipxe/src/core/gdbstub.c index af06118b2..6ad52d1a6 100644 --- a/qemu/roms/ipxe/src/core/gdbstub.c +++ b/qemu/roms/ipxe/src/core/gdbstub.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** * @file diff --git a/qemu/roms/ipxe/src/core/gdbudp.c b/qemu/roms/ipxe/src/core/gdbudp.c index 5977547c8..e4613d137 100644 --- a/qemu/roms/ipxe/src/core/gdbudp.c +++ b/qemu/roms/ipxe/src/core/gdbudp.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/getkey.c b/qemu/roms/ipxe/src/core/getkey.c index d69cfb44b..0f0f8b7c3 100644 --- a/qemu/roms/ipxe/src/core/getkey.c +++ b/qemu/roms/ipxe/src/core/getkey.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/getopt.c b/qemu/roms/ipxe/src/core/getopt.c index abc1edd6c..e6c3948d1 100644 --- a/qemu/roms/ipxe/src/core/getopt.c +++ b/qemu/roms/ipxe/src/core/getopt.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/image.c b/qemu/roms/ipxe/src/core/image.c index ec4480238..529e3d72c 100644 --- a/qemu/roms/ipxe/src/core/image.c +++ b/qemu/roms/ipxe/src/core/image.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include @@ -153,6 +157,32 @@ int image_set_cmdline ( struct image *image, const char *cmdline ) { return 0; } +/** + * Determine image type + * + * @v image Executable image + * @ret rc Return status code + */ +static int image_probe ( struct image *image ) { + struct image_type *type; + int rc; + + /* Try each type in turn */ + for_each_table_entry ( type, IMAGE_TYPES ) { + if ( ( rc = type->probe ( image ) ) == 0 ) { + image->type = type; + DBGC ( image, "IMAGE %s is %s\n", + image->name, type->name ); + break; + } + DBGC ( image, "IMAGE %s is not %s: %s\n", image->name, + type->name, strerror ( rc ) ); + } + + DBGC ( image, "IMAGE %s format not recognised\n", image->name ); + return -ENOTSUP; +} + /** * Register executable image * @@ -185,6 +215,14 @@ int register_image ( struct image *image ) { image->name, user_to_phys ( image->data, 0 ), user_to_phys ( image->data, image->len ) ); + /* Try to detect image type, if applicable. Ignore failures, + * since we expect to handle some unrecognised images + * (e.g. kernel initrds, multiboot modules, random files + * provided via our EFI virtual filesystem, etc). + */ + if ( ! image->type ) + image_probe ( image ); + return 0; } @@ -222,36 +260,6 @@ struct image * find_image ( const char *name ) { return NULL; } -/** - * Determine image type - * - * @v image Executable image - * @ret rc Return status code - */ -int image_probe ( struct image *image ) { - struct image_type *type; - int rc; - - /* Succeed if we already have a type */ - if ( image->type ) - return 0; - - /* Try each type in turn */ - for_each_table_entry ( type, IMAGE_TYPES ) { - if ( ( rc = type->probe ( image ) ) == 0 ) { - image->type = type; - DBGC ( image, "IMAGE %s is %s\n", - image->name, type->name ); - return 0; - } - DBGC ( image, "IMAGE %s is not %s: %s\n", image->name, - type->name, strerror ( rc ) ); - } - - DBGC ( image, "IMAGE %s format not recognised\n", image->name ); - return -ENOEXEC; -} - /** * Execute image * @@ -284,9 +292,11 @@ int image_exec ( struct image *image ) { */ current_image = image_get ( image ); - /* Check that this image can be selected for execution */ - if ( ( rc = image_select ( image ) ) != 0 ) + /* Check that this image can be executed */ + if ( ! ( image->type && image->type->exec ) ) { + rc = -ENOEXEC; goto err; + } /* Check that image is trusted (if applicable) */ if ( require_trusted_images && ! ( image->flags & IMAGE_TRUSTED ) ) { @@ -378,8 +388,8 @@ int image_replace ( struct image *replacement ) { } /* Check that the replacement image can be executed */ - if ( ( rc = image_probe ( replacement ) ) != 0 ) - return rc; + if ( ! ( replacement->type && replacement->type->exec ) ) + return -ENOEXEC; /* Clear any existing replacement */ image_put ( image->replacement ); @@ -400,16 +410,13 @@ int image_replace ( struct image *replacement ) { */ int image_select ( struct image *image ) { struct image *tmp; - int rc; /* Unselect all other images */ for_each_image ( tmp ) tmp->flags &= ~IMAGE_SELECTED; /* Check that this image can be executed */ - if ( ( rc = image_probe ( image ) ) != 0 ) - return rc; - if ( ! image->type->exec ) + if ( ! ( image->type && image->type->exec ) ) return -ENOEXEC; /* Mark image as selected */ @@ -468,9 +475,7 @@ int image_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) { int rc; /* Check that this image can be used to create a pixel buffer */ - if ( ( rc = image_probe ( image ) ) != 0 ) - return rc; - if ( ! image->type->pixbuf ) + if ( ! ( image->type && image->type->pixbuf ) ) return -ENOTSUP; /* Try creating pixel buffer */ diff --git a/qemu/roms/ipxe/src/core/init.c b/qemu/roms/ipxe/src/core/init.c index 7ea0730fa..d91e44669 100644 --- a/qemu/roms/ipxe/src/core/init.c +++ b/qemu/roms/ipxe/src/core/init.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/interface.c b/qemu/roms/ipxe/src/core/interface.c index 62f4621db..ba148c13d 100644 --- a/qemu/roms/ipxe/src/core/interface.c +++ b/qemu/roms/ipxe/src/core/interface.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include @@ -307,3 +311,28 @@ void intf_restart ( struct interface *intf, int rc ) { */ intf->desc = desc; } + +/** + * Poke an object interface + * + * @v intf Object interface + * @v type Operation type + * + * This is a helper function to implement methods which take no + * parameters and return nothing. + */ +void intf_poke ( struct interface *intf, + void ( type ) ( struct interface *intf ) ) { + struct interface *dest; + intf_poke_TYPE ( void * ) *op = + intf_get_dest_op_untyped ( intf, type, &dest ); + void *object = intf_object ( dest ); + + if ( op ) { + op ( object ); + } else { + /* Default is to do nothing */ + } + + intf_put ( dest ); +} diff --git a/qemu/roms/ipxe/src/core/iobuf.c b/qemu/roms/ipxe/src/core/iobuf.c index afc91d150..3e52ada4f 100644 --- a/qemu/roms/ipxe/src/core/iobuf.c +++ b/qemu/roms/ipxe/src/core/iobuf.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include @@ -200,3 +204,33 @@ struct io_buffer * iob_concatenate ( struct list_head *list ) { return concatenated; } + +/** + * Split I/O buffer + * + * @v iobuf I/O buffer + * @v len Length to split into a new I/O buffer + * @ret split New I/O buffer, or NULL on allocation failure + * + * Split the first @c len bytes of the existing I/O buffer into a + * separate I/O buffer. The resulting buffers are likely to have no + * headroom or tailroom. + * + * If this call fails, then the original buffer will be unmodified. + */ +struct io_buffer * iob_split ( struct io_buffer *iobuf, size_t len ) { + struct io_buffer *split; + + /* Sanity checks */ + assert ( len <= iob_len ( iobuf ) ); + + /* Allocate new I/O buffer */ + split = alloc_iob ( len ); + if ( ! split ) + return NULL; + + /* Copy in data */ + memcpy ( iob_put ( split, len ), iobuf->data, len ); + iob_pull ( iobuf, len ); + return split; +} diff --git a/qemu/roms/ipxe/src/core/isqrt.c b/qemu/roms/ipxe/src/core/isqrt.c index 35c918d19..c4d0571e7 100644 --- a/qemu/roms/ipxe/src/core/isqrt.c +++ b/qemu/roms/ipxe/src/core/isqrt.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/job.c b/qemu/roms/ipxe/src/core/job.c index 674bec8b5..65df80056 100644 --- a/qemu/roms/ipxe/src/core/job.c +++ b/qemu/roms/ipxe/src/core/job.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/linebuf.c b/qemu/roms/ipxe/src/core/linebuf.c index 8fb2f86a7..c197e383c 100644 --- a/qemu/roms/ipxe/src/core/linebuf.c +++ b/qemu/roms/ipxe/src/core/linebuf.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** * @file @@ -39,7 +43,18 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @ret line Buffered line, or NULL if no line ready to read */ char * buffered_line ( struct line_buffer *linebuf ) { - return ( linebuf->ready ? linebuf->data : NULL ); + char *line = &linebuf->data[ linebuf->len ]; + + /* Fail unless we have a newly completed line to retrieve */ + if ( ( linebuf->len == 0 ) || ( linebuf->consumed == 0 ) || + ( *(--line) != '\0' ) ) + return NULL; + + /* Identify start of line */ + while ( ( line > linebuf->data ) && ( line[-1] != '\0' ) ) + line--; + + return line; } /** @@ -48,10 +63,11 @@ char * buffered_line ( struct line_buffer *linebuf ) { * @v linebuf Line buffer */ void empty_line_buffer ( struct line_buffer *linebuf ) { + free ( linebuf->data ); linebuf->data = NULL; linebuf->len = 0; - linebuf->ready = 0; + linebuf->consumed = 0; } /** @@ -72,16 +88,13 @@ void empty_line_buffer ( struct line_buffer *linebuf ) { * should call empty_line_buffer() before freeing a @c struct @c * line_buffer. */ -ssize_t line_buffer ( struct line_buffer *linebuf, - const char *data, size_t len ) { +int line_buffer ( struct line_buffer *linebuf, const char *data, size_t len ) { const char *eol; size_t consume; size_t new_len; char *new_data; - - /* Free any completed line from previous iteration */ - if ( linebuf->ready ) - empty_line_buffer ( linebuf ); + char *lf; + char *cr; /* Search for line terminator */ if ( ( eol = memchr ( data, '\n', len ) ) ) { @@ -90,6 +103,10 @@ ssize_t line_buffer ( struct line_buffer *linebuf, consume = len; } + /* Reject any embedded NULs within the data to be consumed */ + if ( memchr ( data, '\0', consume ) ) + return -EINVAL; + /* Reallocate data buffer and copy in new data */ new_len = ( linebuf->len + consume ); new_data = realloc ( linebuf->data, ( new_len + 1 ) ); @@ -100,13 +117,27 @@ ssize_t line_buffer ( struct line_buffer *linebuf, linebuf->data = new_data; linebuf->len = new_len; - /* If we have reached end of line, trim the line and mark as ready */ + /* If we have reached end of line, terminate the line */ if ( eol ) { - linebuf->data[--linebuf->len] = '\0'; /* trim NL */ - if ( linebuf->data[linebuf->len - 1] == '\r' ) - linebuf->data[--linebuf->len] = '\0'; /* trim CR */ - linebuf->ready = 1; + + /* Overwrite trailing LF (which must exist at this point) */ + assert ( linebuf->len > 0 ); + lf = &linebuf->data[ linebuf->len - 1 ]; + assert ( *lf == '\n' ); + *lf = '\0'; + + /* Trim (and overwrite) trailing CR, if present */ + if ( linebuf->len > 1 ) { + cr = ( lf - 1 ); + if ( *cr == '\r' ) { + linebuf->len--; + *cr = '\0'; + } + } } + /* Record consumed length */ + linebuf->consumed = consume; + return consume; } diff --git a/qemu/roms/ipxe/src/core/lineconsole.c b/qemu/roms/ipxe/src/core/lineconsole.c index 1b6791cf3..bb3bfafc9 100644 --- a/qemu/roms/ipxe/src/core/lineconsole.c +++ b/qemu/roms/ipxe/src/core/lineconsole.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/list.c b/qemu/roms/ipxe/src/core/list.c index 77579d69a..5175c84ec 100644 --- a/qemu/roms/ipxe/src/core/list.c +++ b/qemu/roms/ipxe/src/core/list.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/log.c b/qemu/roms/ipxe/src/core/log.c index f160b4fc8..c08e4bb9b 100644 --- a/qemu/roms/ipxe/src/core/log.c +++ b/qemu/roms/ipxe/src/core/log.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/main.c b/qemu/roms/ipxe/src/core/main.c index db09e4c39..638dea9cf 100644 --- a/qemu/roms/ipxe/src/core/main.c +++ b/qemu/roms/ipxe/src/core/main.c @@ -12,7 +12,7 @@ Literature dealing with the network protocols: **************************************************************************/ -FILE_LICENCE ( GPL2_OR_LATER ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include @@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @ret rc Return status code */ __asmcall int main ( void ) { + int rc; /* Perform one-time-only initialisation (e.g. heap) */ initialise(); @@ -35,9 +36,11 @@ __asmcall int main ( void ) { startup(); printf ( "ok\n" ); - ipxe ( NULL ); + /* Attempt to boot */ + if ( ( rc = ipxe ( NULL ) ) != 0 ) + goto err_ipxe; + err_ipxe: shutdown_exit(); - - return 0; + return rc; } diff --git a/qemu/roms/ipxe/src/core/malloc.c b/qemu/roms/ipxe/src/core/malloc.c index d9c07495d..b120c0325 100644 --- a/qemu/roms/ipxe/src/core/malloc.c +++ b/qemu/roms/ipxe/src/core/malloc.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include @@ -106,6 +110,7 @@ static char heap[HEAP_SIZE] __attribute__ (( aligned ( __alignof__(void *) ))); static inline void valgrind_make_blocks_defined ( void ) { struct memory_block *block; + /* Do nothing unless running under Valgrind */ if ( RUNNING_ON_VALGRIND <= 0 ) return; @@ -147,6 +152,7 @@ static inline void valgrind_make_blocks_noaccess ( void ) { struct memory_block *block; struct memory_block *prev = NULL; + /* Do nothing unless running under Valgrind */ if ( RUNNING_ON_VALGRIND <= 0 ) return; @@ -267,24 +273,25 @@ static void discard_all_cache ( void ) { void * alloc_memblock ( size_t size, size_t align, size_t offset ) { struct memory_block *block; size_t align_mask; + size_t actual_size; size_t pre_size; ssize_t post_size; struct memory_block *pre; struct memory_block *post; - struct memory_block *ptr; + void *ptr; /* Sanity checks */ assert ( size != 0 ); assert ( ( align == 0 ) || ( ( align & ( align - 1 ) ) == 0 ) ); - valgrind_make_blocks_defined(); check_blocks(); /* Round up size to multiple of MIN_MEMBLOCK_SIZE and * calculate alignment mask. */ - size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 ); - align_mask = ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 ); + actual_size = ( ( size + MIN_MEMBLOCK_SIZE - 1 ) & + ~( MIN_MEMBLOCK_SIZE - 1 ) ); + align_mask = ( ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 ) ); DBGC2 ( &heap, "Allocating %#zx (aligned %#zx+%zx)\n", size, align, offset ); @@ -293,7 +300,7 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) { list_for_each_entry ( block, &free_blocks, list ) { pre_size = ( ( offset - virt_to_phys ( block ) ) & align_mask ); - post_size = ( block->size - pre_size - size ); + post_size = ( block->size - pre_size - actual_size ); if ( post_size >= 0 ) { /* Split block into pre-block, block, and * post-block. After this split, the "pre" @@ -302,7 +309,7 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) { */ pre = block; block = ( ( ( void * ) pre ) + pre_size ); - post = ( ( ( void * ) block ) + size ); + post = ( ( ( void * ) block ) + actual_size ); DBGC2 ( &heap, "[%p,%p) -> [%p,%p) + [%p,%p)\n", pre, ( ( ( void * ) pre ) + pre->size ), pre, block, post, @@ -313,8 +320,8 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) { * the heap). */ if ( (size_t) post_size >= MIN_MEMBLOCK_SIZE ) { - VALGRIND_MAKE_MEM_DEFINED ( post, - sizeof ( *post ) ); + VALGRIND_MAKE_MEM_UNDEFINED + ( post, sizeof ( *post ) ); post->size = post_size; list_add ( &post->list, &pre->list ); } @@ -328,14 +335,18 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) { * it is too small, which can happen only at * the very start of the heap. */ - if ( pre_size < MIN_MEMBLOCK_SIZE ) + if ( pre_size < MIN_MEMBLOCK_SIZE ) { list_del ( &pre->list ); + VALGRIND_MAKE_MEM_NOACCESS + ( pre, sizeof ( *pre ) ); + } /* Update total free memory */ - freemem -= size; + freemem -= actual_size; /* Return allocated block */ DBGC2 ( &heap, "Allocated [%p,%p)\n", block, ( ( ( void * ) block ) + size ) ); ptr = block; + VALGRIND_MAKE_MEM_UNDEFINED ( ptr, size ); goto done; } } @@ -368,13 +379,16 @@ void free_memblock ( void *ptr, size_t size ) { struct memory_block *freeing; struct memory_block *block; struct memory_block *tmp; + size_t actual_size; ssize_t gap_before; ssize_t gap_after = -1; /* Allow for ptr==NULL */ if ( ! ptr ) return; + VALGRIND_MAKE_MEM_NOACCESS ( ptr, size ); + /* Sanity checks */ valgrind_make_blocks_defined(); check_blocks(); @@ -382,9 +396,10 @@ void free_memblock ( void *ptr, size_t size ) { * would have used. */ assert ( size != 0 ); - size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 ); + actual_size = ( ( size + MIN_MEMBLOCK_SIZE - 1 ) & + ~( MIN_MEMBLOCK_SIZE - 1 ) ); freeing = ptr; - VALGRIND_MAKE_MEM_DEFINED ( freeing, sizeof ( *freeing ) ); + VALGRIND_MAKE_MEM_UNDEFINED ( freeing, sizeof ( *freeing ) ); DBGC2 ( &heap, "Freeing [%p,%p)\n", freeing, ( ( ( void * ) freeing ) + size ) ); @@ -392,7 +407,7 @@ void free_memblock ( void *ptr, size_t size ) { if ( ASSERTING ) { list_for_each_entry ( block, &free_blocks, list ) { if ( ( ( ( void * ) block ) < - ( ( void * ) freeing + size ) ) && + ( ( void * ) freeing + actual_size ) ) && ( ( void * ) freeing < ( ( void * ) block + block->size ) ) ) { assert ( 0 ); @@ -407,7 +422,7 @@ void free_memblock ( void *ptr, size_t size ) { } /* Insert/merge into free list */ - freeing->size = size; + freeing->size = actual_size; list_for_each_entry_safe ( block, tmp, &free_blocks, list ) { /* Calculate gaps before and after the "freeing" block */ gap_before = ( ( ( void * ) freeing ) - @@ -421,8 +436,10 @@ void free_memblock ( void *ptr, size_t size ) { ( ( ( void * ) freeing ) + freeing->size ), block, ( ( ( void * ) freeing ) + freeing->size ) ); - block->size += size; + block->size += actual_size; list_del ( &block->list ); + VALGRIND_MAKE_MEM_NOACCESS ( freeing, + sizeof ( *freeing ) ); freeing = block; } /* Stop processing as soon as we reach a following block */ @@ -444,10 +461,11 @@ void free_memblock ( void *ptr, size_t size ) { ( ( ( void * ) block ) + block->size ) ); freeing->size += block->size; list_del ( &block->list ); + VALGRIND_MAKE_MEM_NOACCESS ( block, sizeof ( *block ) ); } /* Update free memory counter */ - freemem += size; + freemem += actual_size; check_blocks(); valgrind_make_blocks_noaccess(); @@ -490,9 +508,9 @@ void * realloc ( void *old_ptr, size_t new_size ) { new_block = alloc_memblock ( new_total_size, 1, 0 ); if ( ! new_block ) return NULL; - VALGRIND_MAKE_MEM_UNDEFINED ( new_block, offsetof ( struct autosized_block, data ) ); new_block->size = new_total_size; - VALGRIND_MAKE_MEM_NOACCESS ( new_block, offsetof ( struct autosized_block, data ) ); + VALGRIND_MAKE_MEM_NOACCESS ( &new_block->size, + sizeof ( new_block->size ) ); new_ptr = &new_block->data; VALGRIND_MALLOCLIKE_BLOCK ( new_ptr, new_size, 0, 0 ); } @@ -505,16 +523,16 @@ void * realloc ( void *old_ptr, size_t new_size ) { if ( old_ptr && ( old_ptr != NOWHERE ) ) { old_block = container_of ( old_ptr, struct autosized_block, data ); - VALGRIND_MAKE_MEM_DEFINED ( old_block, offsetof ( struct autosized_block, data ) ); + VALGRIND_MAKE_MEM_DEFINED ( &old_block->size, + sizeof ( old_block->size ) ); old_total_size = old_block->size; assert ( old_total_size != 0 ); old_size = ( old_total_size - offsetof ( struct autosized_block, data ) ); memcpy ( new_ptr, old_ptr, ( ( old_size < new_size ) ? old_size : new_size ) ); - free_memblock ( old_block, old_total_size ); - VALGRIND_MAKE_MEM_NOACCESS ( old_block, offsetof ( struct autosized_block, data ) ); VALGRIND_FREELIKE_BLOCK ( old_ptr, 0 ); + free_memblock ( old_block, old_total_size ); } if ( ASSERTED ) { @@ -611,6 +629,7 @@ void mpopulate ( void *start, size_t len ) { */ static void init_heap ( void ) { VALGRIND_MAKE_MEM_NOACCESS ( heap, sizeof ( heap ) ); + VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks, sizeof ( free_blocks ) ); mpopulate ( heap, sizeof ( heap ) ); } diff --git a/qemu/roms/ipxe/src/core/memblock.c b/qemu/roms/ipxe/src/core/memblock.c index 1fd89b871..aecddc22c 100644 --- a/qemu/roms/ipxe/src/core/memblock.c +++ b/qemu/roms/ipxe/src/core/memblock.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/memmap_settings.c b/qemu/roms/ipxe/src/core/memmap_settings.c index 0f6d0abf5..fab3e5f3a 100644 --- a/qemu/roms/ipxe/src/core/memmap_settings.c +++ b/qemu/roms/ipxe/src/core/memmap_settings.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/menu.c b/qemu/roms/ipxe/src/core/menu.c index 8d42e1f83..ab5b0c7f5 100644 --- a/qemu/roms/ipxe/src/core/menu.c +++ b/qemu/roms/ipxe/src/core/menu.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/misc.c b/qemu/roms/ipxe/src/core/misc.c deleted file mode 100644 index eaceddfea..000000000 --- a/qemu/roms/ipxe/src/core/misc.c +++ /dev/null @@ -1,85 +0,0 @@ -/************************************************************************** -MISC Support Routines -**************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include -#include -#include -#include -#include - -/************************************************************************** -INET_ATON - Convert an ascii x.x.x.x to binary form -**************************************************************************/ -int inet_aton ( const char *cp, struct in_addr *inp ) { - const char *p = cp; - const char *digits_start; - unsigned long ip = 0; - unsigned long val; - int j; - for(j = 0; j <= 3; j++) { - digits_start = p; - val = strtoul(p, ( char ** ) &p, 10); - if ((p == digits_start) || (val > 255)) return 0; - if ( ( j < 3 ) && ( *(p++) != '.' ) ) return 0; - ip = (ip << 8) | val; - } - if ( *p == '\0' ) { - inp->s_addr = htonl(ip); - return 1; - } - return 0; -} - -unsigned int strtoul_charval ( unsigned int charval ) { - - if ( charval >= 'a' ) { - charval = ( charval - 'a' + 10 ); - } else if ( charval >= 'A' ) { - charval = ( charval - 'A' + 10 ); - } else if ( charval <= '9' ) { - charval = ( charval - '0' ); - } - - return charval; -} - -unsigned long strtoul ( const char *p, char **endp, int base ) { - unsigned long ret = 0; - int negative = 0; - unsigned int charval; - - while ( isspace ( *p ) ) - p++; - - if ( *p == '-' ) { - negative = 1; - p++; - } - - base = strtoul_base ( &p, base ); - - while ( 1 ) { - charval = strtoul_charval ( *p ); - if ( charval >= ( unsigned int ) base ) - break; - ret = ( ( ret * base ) + charval ); - p++; - } - - if ( negative ) - ret = -ret; - - if ( endp ) - *endp = ( char * ) p; - - return ( ret ); -} - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/qemu/roms/ipxe/src/core/monojob.c b/qemu/roms/ipxe/src/core/monojob.c index 820fa31dc..817f21b2c 100644 --- a/qemu/roms/ipxe/src/core/monojob.c +++ b/qemu/roms/ipxe/src/core/monojob.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/null_reboot.c b/qemu/roms/ipxe/src/core/null_reboot.c index a3d5b2ef8..7be5612a3 100644 --- a/qemu/roms/ipxe/src/core/null_reboot.c +++ b/qemu/roms/ipxe/src/core/null_reboot.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** * @file diff --git a/qemu/roms/ipxe/src/core/null_sanboot.c b/qemu/roms/ipxe/src/core/null_sanboot.c index 18c0dea84..2f7522c6c 100644 --- a/qemu/roms/ipxe/src/core/null_sanboot.c +++ b/qemu/roms/ipxe/src/core/null_sanboot.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/null_time.c b/qemu/roms/ipxe/src/core/null_time.c index 506c70b52..90041a456 100644 --- a/qemu/roms/ipxe/src/core/null_time.c +++ b/qemu/roms/ipxe/src/core/null_time.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/nvo.c b/qemu/roms/ipxe/src/core/nvo.c index e135d2b41..d2c9b5e73 100644 --- a/qemu/roms/ipxe/src/core/nvo.c +++ b/qemu/roms/ipxe/src/core/nvo.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/open.c b/qemu/roms/ipxe/src/core/open.c index b479c2975..9d665ffda 100644 --- a/qemu/roms/ipxe/src/core/open.c +++ b/qemu/roms/ipxe/src/core/open.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/params.c b/qemu/roms/ipxe/src/core/params.c index 93b834419..e1f66acca 100644 --- a/qemu/roms/ipxe/src/core/params.c +++ b/qemu/roms/ipxe/src/core/params.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/parseopt.c b/qemu/roms/ipxe/src/core/parseopt.c index d268c0594..66f60158c 100644 --- a/qemu/roms/ipxe/src/core/parseopt.c +++ b/qemu/roms/ipxe/src/core/parseopt.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include @@ -32,6 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** @file * @@ -343,7 +348,7 @@ void print_usage ( struct command_descriptor *cmd, char **argv ) { } if ( cmd->usage ) printf ( " %s", cmd->usage ); - printf ( "\n\nSee http://ipxe.org/cmd/%s for further information\n", + printf ( "\n\nSee " PRODUCT_COMMAND_URI " for further information\n", argv[0] ); } diff --git a/qemu/roms/ipxe/src/core/pending.c b/qemu/roms/ipxe/src/core/pending.c index 7bb0c2e00..96d0cf197 100644 --- a/qemu/roms/ipxe/src/core/pending.c +++ b/qemu/roms/ipxe/src/core/pending.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/pinger.c b/qemu/roms/ipxe/src/core/pinger.c index 31ea2ce1c..0ff7bb9f2 100644 --- a/qemu/roms/ipxe/src/core/pinger.c +++ b/qemu/roms/ipxe/src/core/pinger.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/pixbuf.c b/qemu/roms/ipxe/src/core/pixbuf.c index 48f8e9f9a..41e18f8dc 100644 --- a/qemu/roms/ipxe/src/core/pixbuf.c +++ b/qemu/roms/ipxe/src/core/pixbuf.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * diff --git a/qemu/roms/ipxe/src/core/pool.c b/qemu/roms/ipxe/src/core/pool.c new file mode 100644 index 000000000..0163405f7 --- /dev/null +++ b/qemu/roms/ipxe/src/core/pool.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2015 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 ); + +/** + * @file + * + * Pooled connections + * + */ + +#include +#include + +/** + * Recycle this connection after closing + * + * @v intf Data transfer interface + */ +void pool_recycle ( struct interface *intf ) { + + intf_poke ( intf, pool_recycle ); +} + +/** + * Reopen a defunct connection + * + * @v intf Data transfer interface + */ +void pool_reopen ( struct interface *intf ) { + + intf_poke ( intf, pool_reopen ); +} + +/** + * Add connection to pool + * + * @v pool Pooled connection + * @v list List of pooled connections + * @v expiry Expiry time + */ +void pool_add ( struct pooled_connection *pool, struct list_head *list, + unsigned long expiry ) { + + /* Sanity check */ + assert ( list_empty ( &pool->list ) ); + assert ( ! timer_running ( &pool->timer ) ); + + /* Add to list of pooled connections */ + list_add_tail ( &pool->list, list ); + + /* Start expiry timer */ + start_timer_fixed ( &pool->timer, expiry ); +} + +/** + * Remove connection from pool + * + * @v pool Pooled connection + */ +void pool_del ( struct pooled_connection *pool ) { + + /* Remove from list of pooled connections */ + list_del ( &pool->list ); + INIT_LIST_HEAD ( &pool->list ); + + /* Stop expiry timer */ + stop_timer ( &pool->timer ); + + /* Mark as a freshly recycled connection */ + pool->flags = POOL_RECYCLED; +} + +/** + * Close expired pooled connection + * + * @v timer Expiry timer + * @v over Failure indicator + */ +void pool_expired ( struct retry_timer *timer, int over __unused ) { + struct pooled_connection *pool = + container_of ( timer, struct pooled_connection, timer ); + + /* Sanity check */ + assert ( ! list_empty ( &pool->list ) ); + + /* Remove from connection pool */ + list_del ( &pool->list ); + INIT_LIST_HEAD ( &pool->list ); + + /* Close expired connection */ + pool->expired ( pool ); +} diff --git a/qemu/roms/ipxe/src/core/posix_io.c b/qemu/roms/ipxe/src/core/posix_io.c index 8460d0f51..35b52beeb 100644 --- a/qemu/roms/ipxe/src/core/posix_io.c +++ b/qemu/roms/ipxe/src/core/posix_io.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/process.c b/qemu/roms/ipxe/src/core/process.c index d341a2c37..69852c416 100644 --- a/qemu/roms/ipxe/src/core/process.c +++ b/qemu/roms/ipxe/src/core/process.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/profile.c b/qemu/roms/ipxe/src/core/profile.c index 150e6b273..1075047b9 100644 --- a/qemu/roms/ipxe/src/core/profile.c +++ b/qemu/roms/ipxe/src/core/profile.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/random.c b/qemu/roms/ipxe/src/core/random.c index 8824dca3a..a74175a79 100644 --- a/qemu/roms/ipxe/src/core/random.c +++ b/qemu/roms/ipxe/src/core/random.c @@ -4,7 +4,7 @@ * */ -FILE_LICENCE ( GPL2_OR_LATER ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/refcnt.c b/qemu/roms/ipxe/src/core/refcnt.c index 68a86120e..47c975a0b 100644 --- a/qemu/roms/ipxe/src/core/refcnt.c +++ b/qemu/roms/ipxe/src/core/refcnt.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/resolv.c b/qemu/roms/ipxe/src/core/resolv.c index d59a8c0ad..1e3182b0b 100644 --- a/qemu/roms/ipxe/src/core/resolv.c +++ b/qemu/roms/ipxe/src/core/resolv.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/serial.c b/qemu/roms/ipxe/src/core/serial.c index 7e4460ab9..4ce025519 100644 --- a/qemu/roms/ipxe/src/core/serial.c +++ b/qemu/roms/ipxe/src/core/serial.c @@ -1,259 +1,184 @@ /* - * The serial port interface routines implement a simple polled i/o - * interface to a standard serial port. Due to the space restrictions - * for the boot blocks, no BIOS support is used (since BIOS requires - * expensive real/protected mode switches), instead the rudimentary - * BIOS support is duplicated here. + * Copyright (C) 2014 Michael Brown . * - * The base address and speed for the i/o port are passed from the - * Makefile in the COMCONSOLE and CONSPEED preprocessor macros. The - * line control parameters are currently hard-coded to 8 bits, no - * parity, 1 stop bit (8N1). This can be changed in init_serial(). + * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +/** @file + * + * Serial console + * + */ -#include "stddef.h" +#include #include -#include -#include +#include +#include #include -#include "config/serial.h" - -/* Set default values if none specified */ +#include +#include -#ifndef COMCONSOLE -#define COMCONSOLE 0x3f8 +/* Set default console usage if applicable */ +#if ! ( defined ( CONSOLE_SERIAL ) && CONSOLE_EXPLICIT ( CONSOLE_SERIAL ) ) +#undef CONSOLE_SERIAL +#define CONSOLE_SERIAL ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG ) #endif -#ifndef COMSPEED -#define COMSPEED 9600 -#endif - -#ifndef COMDATA -#define COMDATA 8 +/* UART port number */ +#ifdef COMCONSOLE +#define CONSOLE_PORT COMCONSOLE +#else +#define CONSOLE_PORT 0 #endif -#ifndef COMPARITY -#define COMPARITY 0 +/* UART baud rate */ +#ifdef COMPRESERVE +#define CONSOLE_BAUD 0 +#else +#define CONSOLE_BAUD COMSPEED #endif -#ifndef COMSTOP -#define COMSTOP 1 +/* UART line control register value */ +#ifdef COMPRESERVE +#define CONSOLE_LCR 0 +#else +#define CONSOLE_LCR UART_LCR_WPS ( COMDATA, COMPARITY, COMSTOP ) #endif -#undef UART_BASE -#define UART_BASE ( COMCONSOLE ) - -#undef UART_BAUD -#define UART_BAUD ( COMSPEED ) +/** Serial console UART */ +struct uart serial_console; -#if ((115200%UART_BAUD) != 0) -#error Bad ttys0 baud rate -#endif - -#define COMBRD (115200/UART_BAUD) +/** + * Print a character to serial console + * + * @v character Character to be printed + */ +static void serial_putchar ( int character ) { -/* Line Control Settings */ -#define UART_LCS ( ( ( (COMDATA) - 5 ) << 0 ) | \ - ( ( (COMPARITY) ) << 3 ) | \ - ( ( (COMSTOP) - 1 ) << 2 ) ) + /* Do nothing if we have no UART */ + if ( ! serial_console.base ) + return; -/* Data */ -#define UART_RBR 0x00 -#define UART_TBR 0x00 + /* Transmit character */ + uart_transmit ( &serial_console, character ); +} -/* Control */ -#define UART_IER 0x01 -#define UART_IIR 0x02 -#define UART_FCR 0x02 -#define UART_LCR 0x03 -#define UART_MCR 0x04 -#define UART_DLL 0x00 -#define UART_DLM 0x01 +/** + * Get character from serial console + * + * @ret character Character read from console + */ +static int serial_getchar ( void ) { + uint8_t data; -/* Status */ -#define UART_LSR 0x05 -#define UART_LSR_TEMPT 0x40 /* Transmitter empty */ -#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ -#define UART_LSR_BI 0x10 /* Break interrupt indicator */ -#define UART_LSR_FE 0x08 /* Frame error indicator */ -#define UART_LSR_PE 0x04 /* Parity error indicator */ -#define UART_LSR_OE 0x02 /* Overrun error indicator */ -#define UART_LSR_DR 0x01 /* Receiver data ready */ + /* Do nothing if we have no UART */ + if ( ! serial_console.base ) + return 0; -#define UART_MSR 0x06 -#define UART_SCR 0x07 + /* Wait for data to be ready */ + while ( ! uart_data_ready ( &serial_console ) ) {} -#if defined(UART_MEM) -#define uart_readb(addr) readb((addr)) -#define uart_writeb(val,addr) writeb((val),(addr)) -#else -#define uart_readb(addr) inb((addr)) -#define uart_writeb(val,addr) outb((val),(addr)) -#endif + /* Receive data */ + data = uart_receive ( &serial_console ); -/* Boolean for the state of serial driver initialization */ -int serial_initialized = 0; + /* Strip any high bit and convert DEL to backspace */ + data &= 0x7f; + if ( data == 0x7f ) + data = 0x08; -/* - * void serial_putc(int ch); - * Write character `ch' to port UART_BASE. - */ -void serial_putc ( int ch ) { - int i; - int status; - i = 1000; /* timeout */ - while(--i > 0) { - status = uart_readb(UART_BASE + UART_LSR); - if (status & UART_LSR_THRE) { - /* TX buffer emtpy */ - uart_writeb(ch, UART_BASE + UART_TBR); - break; - } - mdelay(2); - } + return data; } -/* - * int serial_getc(void); - * Read a character from port UART_BASE. - */ -int serial_getc ( void ) { - int status; - int ch; - do { - status = uart_readb(UART_BASE + UART_LSR); - } while((status & 1) == 0); - ch = uart_readb(UART_BASE + UART_RBR); /* fetch (first) character */ - ch &= 0x7f; /* remove any parity bits we get */ - if (ch == 0x7f) { /* Make DEL... look like BS */ - ch = 0x08; - } - return ch; -} - -/* - * int serial_ischar(void); - * If there is a character in the input buffer of port UART_BASE, - * return nonzero; otherwise return 0. +/** + * Check for character ready to read from serial console + * + * @ret True Character available to read + * @ret False No character available to read */ -int serial_ischar ( void ) { - int status; - status = uart_readb(UART_BASE + UART_LSR); /* line status reg; */ - return status & 1; /* rx char available */ -} +static int serial_iskey ( void ) { -/* - * int serial_init(void); - * Initialize port UART_BASE to speed COMSPEED, line settings 8N1. - */ -static void serial_init ( void ) { - int status; - int divisor, lcs; + /* Do nothing if we have no UART */ + if ( ! serial_console.base ) + return 0; - DBG ( "Serial port %#x initialising\n", UART_BASE ); + /* Check UART */ + return uart_data_ready ( &serial_console ); +} - divisor = COMBRD; - lcs = UART_LCS; +/** Serial console */ +struct console_driver serial_console_driver __console_driver = { + .putchar = serial_putchar, + .getchar = serial_getchar, + .iskey = serial_iskey, + .usage = CONSOLE_SERIAL, +}; +/** Initialise serial console */ +static void serial_init ( void ) { + int rc; -#ifdef COMPRESERVE - lcs = uart_readb(UART_BASE + UART_LCR) & 0x7f; - uart_writeb(0x80 | lcs, UART_BASE + UART_LCR); - divisor = (uart_readb(UART_BASE + UART_DLM) << 8) | uart_readb(UART_BASE + UART_DLL); - uart_writeb(lcs, UART_BASE + UART_LCR); -#endif + /* Do nothing if we have no default port */ + if ( ! CONSOLE_PORT ) + return; - /* Set Baud Rate Divisor to COMSPEED, and test to see if the - * serial port appears to be present. - */ - uart_writeb(0x80 | lcs, UART_BASE + UART_LCR); - uart_writeb(0xaa, UART_BASE + UART_DLL); - if (uart_readb(UART_BASE + UART_DLL) != 0xaa) { - DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE ); - goto out; - } - uart_writeb(0x55, UART_BASE + UART_DLL); - if (uart_readb(UART_BASE + UART_DLL) != 0x55) { - DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE ); - goto out; + /* Select UART */ + if ( ( rc = uart_select ( &serial_console, CONSOLE_PORT ) ) != 0 ) { + DBG ( "Could not select UART %d: %s\n", + CONSOLE_PORT, strerror ( rc ) ); + return; } - uart_writeb(divisor & 0xff, UART_BASE + UART_DLL); - if (uart_readb(UART_BASE + UART_DLL) != (divisor & 0xff)) { - DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE ); - goto out; - } - uart_writeb(0xaa, UART_BASE + UART_DLM); - if (uart_readb(UART_BASE + UART_DLM) != 0xaa) { - DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE ); - goto out; - } - uart_writeb(0x55, UART_BASE + UART_DLM); - if (uart_readb(UART_BASE + UART_DLM) != 0x55) { - DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE ); - goto out; - } - uart_writeb((divisor >> 8) & 0xff, UART_BASE + UART_DLM); - if (uart_readb(UART_BASE + UART_DLM) != ((divisor >> 8) & 0xff)) { - DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE ); - goto out; - } - uart_writeb(lcs, UART_BASE + UART_LCR); - - /* disable interrupts */ - uart_writeb(0x0, UART_BASE + UART_IER); - /* enable fifos */ - uart_writeb(0x01, UART_BASE + UART_FCR); + /* Initialise UART */ + if ( ( rc = uart_init ( &serial_console, CONSOLE_BAUD, + CONSOLE_LCR ) ) != 0 ) { + DBG ( "Could not initialise UART %d baud %d LCR %#02x: %s\n", + CONSOLE_PORT, CONSOLE_BAUD, CONSOLE_LCR, strerror ( rc )); + return; + } +} - /* Set clear to send, so flow control works... */ - uart_writeb((1<<1), UART_BASE + UART_MCR); +/** + * Shut down serial console + * + * @v flags Shutdown flags + */ +static void serial_shutdown ( int flags __unused ) { - /* Flush the input buffer. */ - do { - /* rx buffer reg - * throw away (unconditionally the first time) - */ - (void) uart_readb(UART_BASE + UART_RBR); - /* line status reg */ - status = uart_readb(UART_BASE + UART_LSR); - } while(status & UART_LSR_DR); + /* Do nothing if we have no UART */ + if ( ! serial_console.base ) + return; - /* Note that serial support has been initialized */ - serial_initialized = 1; - out: - return; -} + /* Flush any pending output */ + uart_flush ( &serial_console ); -/* - * void serial_fini(void); - * Cleanup our use of the serial port, in particular flush the - * output buffer so we don't accidentially lose characters. - */ -static void serial_fini ( int flags __unused ) { - int i, status; - /* Flush the output buffer to avoid dropping characters, - * if we are reinitializing the serial port. - */ - i = 10000; /* timeout */ - do { - status = uart_readb(UART_BASE + UART_LSR); - } while((--i > 0) && !(status & UART_LSR_TEMPT)); - /* Don't mark it as disabled; it's still usable */ + /* Leave console enabled; it's still usable */ } -/** - * Serial driver initialisation function - * - * Initialise serial port early on so that it is available to capture - * early debug messages. - */ -struct init_fn serial_init_fn __init_fn ( INIT_SERIAL ) = { +/** Serial console initialisation function */ +struct init_fn serial_console_init_fn __init_fn ( INIT_CONSOLE ) = { .initialise = serial_init, }; -/** Serial driver startup function */ +/** Serial console startup function */ struct startup_fn serial_startup_fn __startup_fn ( STARTUP_EARLY ) = { - .shutdown = serial_fini, + .shutdown = serial_shutdown, }; diff --git a/qemu/roms/ipxe/src/core/serial_console.c b/qemu/roms/ipxe/src/core/serial_console.c deleted file mode 100644 index de9b84ca7..000000000 --- a/qemu/roms/ipxe/src/core/serial_console.c +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include -#include - -/** @file - * - * Serial console - * - */ - -/* Set default console usage if applicable */ -#if ! ( defined ( CONSOLE_SERIAL ) && CONSOLE_EXPLICIT ( CONSOLE_SERIAL ) ) -#undef CONSOLE_SERIAL -#define CONSOLE_SERIAL ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG ) -#endif - -struct console_driver serial_console __console_driver; - -static void serial_console_init ( void ) { - /* - * Check if serial driver initialization is done. - * If so, it's time to enable the serial console. - */ - if ( serial_initialized ) - serial_console.disabled = 0; -} - -struct console_driver serial_console __console_driver = { - .putchar = serial_putc, - .getchar = serial_getc, - .iskey = serial_ischar, - .disabled = CONSOLE_DISABLED, - .usage = CONSOLE_SERIAL, -}; - -/** - * Serial console initialisation function - */ -struct init_fn serial_console_init_fn __init_fn ( INIT_CONSOLE ) = { - .initialise = serial_console_init, -}; diff --git a/qemu/roms/ipxe/src/core/settings.c b/qemu/roms/ipxe/src/core/settings.c index 5e16b27d0..12e6c7d61 100644 --- a/qemu/roms/ipxe/src/core/settings.c +++ b/qemu/roms/ipxe/src/core/settings.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include @@ -35,6 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -337,17 +342,20 @@ struct settings * autovivify_child_settings ( struct settings *parent, */ const char * settings_name ( struct settings *settings ) { static char buf[16]; - char tmp[ sizeof ( buf ) ]; + char tmp[ 1 /* '.' */ + sizeof ( buf ) ]; /* Find target settings block */ settings = settings_target ( settings ); /* Construct name */ - for ( buf[2] = buf[0] = 0 ; settings ; settings = settings->parent ) { - memcpy ( tmp, buf, sizeof ( tmp ) ); - snprintf ( buf, sizeof ( buf ), ".%s%s", settings->name, tmp ); + buf[0] = '\0'; + tmp[0] = '\0'; + for ( ; settings->parent ; settings = settings->parent ) { + memcpy ( ( tmp + 1 ), buf, ( sizeof ( tmp ) - 1 ) ); + snprintf ( buf, sizeof ( buf ), "%s%s", settings->name, tmp ); + tmp[0] = '.'; } - return ( buf + 2 ); + return buf; } /** @@ -499,10 +507,10 @@ int register_settings ( struct settings *settings, struct settings *parent, */ void unregister_settings ( struct settings *settings ) { struct settings *child; - struct settings *tmp; /* Unregister child settings */ - list_for_each_entry_safe ( child, tmp, &settings->children, siblings ) { + while ( ( child = list_first_entry ( &settings->children, + struct settings, siblings ) ) ) { unregister_settings ( child ); } @@ -1998,32 +2006,6 @@ const struct setting_type setting_type_uint16 __setting_type = const struct setting_type setting_type_uint32 __setting_type = SETTING_TYPE_UINT ( SETTING_TYPE_INT32 ); -/** - * Format hex string setting value - * - * @v delimiter Byte delimiter - * @v raw Raw setting value - * @v raw_len Length of raw setting value - * @v buf Buffer to contain formatted value - * @v len Length of buffer - * @ret len Length of formatted value, or negative error - */ -static int format_hex_setting ( const char *delimiter, const void *raw, - size_t raw_len, char *buf, size_t len ) { - const uint8_t *bytes = raw; - int used = 0; - unsigned int i; - - if ( len ) - buf[0] = 0; /* Ensure that a terminating NUL exists */ - for ( i = 0 ; i < raw_len ; i++ ) { - used += ssnprintf ( ( buf + used ), ( len - used ), - "%s%02x", ( used ? delimiter : "" ), - bytes[i] ); - } - return used; -} - /** * Parse hex string setting value (using colon delimiter) * @@ -2036,7 +2018,7 @@ static int format_hex_setting ( const char *delimiter, const void *raw, */ static int parse_hex_setting ( const struct setting_type *type __unused, const char *value, void *buf, size_t len ) { - return hex_decode ( value, ':', buf, len ); + return hex_decode ( ':', value, buf, len ); } /** @@ -2052,7 +2034,7 @@ static int parse_hex_setting ( const struct setting_type *type __unused, static int format_hex_colon_setting ( const struct setting_type *type __unused, const void *raw, size_t raw_len, char *buf, size_t len ) { - return format_hex_setting ( ":", raw, raw_len, buf, len ); + return hex_encode ( ':', raw, raw_len, buf, len ); } /** @@ -2068,7 +2050,7 @@ static int format_hex_colon_setting ( const struct setting_type *type __unused, static int parse_hex_hyphen_setting ( const struct setting_type *type __unused, const char *value, void *buf, size_t len ) { - return hex_decode ( value, '-', buf, len ); + return hex_decode ( '-', value, buf, len ); } /** @@ -2084,7 +2066,7 @@ static int parse_hex_hyphen_setting ( const struct setting_type *type __unused, static int format_hex_hyphen_setting ( const struct setting_type *type __unused, const void *raw, size_t raw_len, char *buf, size_t len ) { - return format_hex_setting ( "-", raw, raw_len, buf, len ); + return hex_encode ( '-', raw, raw_len, buf, len ); } /** @@ -2099,7 +2081,7 @@ static int format_hex_hyphen_setting ( const struct setting_type *type __unused, */ static int parse_hex_raw_setting ( const struct setting_type *type __unused, const char *value, void *buf, size_t len ) { - return hex_decode ( value, 0, buf, len ); + return hex_decode ( 0, value, buf, len ); } /** @@ -2115,7 +2097,7 @@ static int parse_hex_raw_setting ( const struct setting_type *type __unused, static int format_hex_raw_setting ( const struct setting_type *type __unused, const void *raw, size_t raw_len, char *buf, size_t len ) { - return format_hex_setting ( "", raw, raw_len, buf, len ); + return hex_encode ( 0, raw, raw_len, buf, len ); } /** A hex-string setting (colon-delimited) */ @@ -2139,6 +2121,46 @@ const struct setting_type setting_type_hexraw __setting_type = { .format = format_hex_raw_setting, }; +/** + * Parse Base64-encoded setting value + * + * @v type Setting type + * @v value Formatted setting value + * @v buf Buffer to contain raw value + * @v len Length of buffer + * @v size Integer size, in bytes + * @ret len Length of raw value, or negative error + */ +static int parse_base64_setting ( const struct setting_type *type __unused, + const char *value, void *buf, size_t len ) { + + return base64_decode ( value, buf, len ); +} + +/** + * Format Base64-encoded setting value + * + * @v type Setting type + * @v raw Raw setting value + * @v raw_len Length of raw setting value + * @v buf Buffer to contain formatted value + * @v len Length of buffer + * @ret len Length of formatted value, or negative error + */ +static int format_base64_setting ( const struct setting_type *type __unused, + const void *raw, size_t raw_len, + char *buf, size_t len ) { + + return base64_encode ( raw, raw_len, buf, len ); +} + +/** A Base64-encoded setting */ +const struct setting_type setting_type_base64 __setting_type = { + .name = "base64", + .parse = parse_base64_setting, + .format = format_base64_setting, +}; + /** * Format UUID setting value * diff --git a/qemu/roms/ipxe/src/core/string.c b/qemu/roms/ipxe/src/core/string.c index e53c283c2..3e658e54e 100644 --- a/qemu/roms/ipxe/src/core/string.c +++ b/qemu/roms/ipxe/src/core/string.c @@ -1,353 +1,501 @@ /* - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 2004 Tobias Lorenz + * Copyright (C) 2015 Michael Brown . * - * string handling functions - * based on linux/lib/string.c + * 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 free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -FILE_LICENCE ( GPL2_ONLY ); - -/* - * stupid library routines.. The optimized versions should generally be found - * as inline code in + * 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. * - * These are buggy as well.. + * 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. * - * * Fri Jun 25 1999, Ingo Oeser - * - Added strsep() which will replace strtok() soon (because strsep() is - * reentrant and should be faster). Use only strsep() in new code, please. + * 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 -/* *** FROM string.c *** */ +/** @file + * + * String functions + * + */ -#ifndef __HAVE_ARCH_STRCPY /** - * strcpy - Copy a %NUL terminated string - * @dest: Where to copy the string to - * @src: Where to copy the string from + * Fill memory region + * + * @v dest Destination region + * @v character Fill character + * @v len Length + * @ret dest Destination region */ -char * strcpy(char * dest,const char *src) -{ - char *tmp = dest; +void * generic_memset ( void *dest, int character, size_t len ) { + uint8_t *dest_bytes = dest; - while ((*dest++ = *src++) != '\0') - /* nothing */; - return tmp; + while ( len-- ) + *(dest_bytes++) = character; + return dest; } -#endif -#ifndef __HAVE_ARCH_STRNCPY /** - * strncpy - Copy a length-limited, %NUL-terminated string - * @dest: Where to copy the string to - * @src: Where to copy the string from - * @count: The maximum number of bytes to copy + * Copy memory region * - * Note that unlike userspace strncpy, this does not %NUL-pad the buffer. - * However, the result is not %NUL-terminated if the source exceeds - * @count bytes. + * @v dest Destination region + * @v src Source region + * @v len Length + * @ret dest Destination region */ -char * strncpy(char * dest,const char *src,size_t count) -{ - char *tmp = dest; - - while (count-- && (*dest++ = *src++) != '\0') - /* nothing */; +void * generic_memcpy ( void *dest, const void *src, size_t len ) { + const uint8_t *src_bytes = src; + uint8_t *dest_bytes = dest; - return tmp; + while ( len-- ) + *(dest_bytes++) = *(src_bytes++); + return dest; } -#endif -#ifndef __HAVE_ARCH_STRCAT /** - * strcat - Append one %NUL-terminated string to another - * @dest: The string to be appended to - * @src: The string to append to it + * Copy (possibly overlapping) memory region + * + * @v dest Destination region + * @v src Source region + * @v len Length + * @ret dest Destination region */ -char * strcat(char * dest, const char * src) -{ - char *tmp = dest; - - while (*dest) - dest++; - while ((*dest++ = *src++) != '\0') - ; +void * generic_memmove ( void *dest, const void *src, size_t len ) { + const uint8_t *src_bytes = ( src + len ); + uint8_t *dest_bytes = ( dest + len ); + + if ( dest < src ) + return memcpy ( dest, src, len ); + while ( len-- ) + *(--dest_bytes) = *(--src_bytes); + return dest; +} - return tmp; +/** + * Compare memory regions + * + * @v first First region + * @v second Second region + * @v len Length + * @ret diff Difference + */ +int memcmp ( const void *first, const void *second, size_t len ) { + const uint8_t *first_bytes = first; + const uint8_t *second_bytes = second; + int diff; + + while ( len-- ) { + diff = ( *(second_bytes++) - *(first_bytes++) ); + if ( diff ) + return diff; + } + return 0; } -#endif -#ifndef __HAVE_ARCH_STRCMP /** - * strcmp - Compare two strings - * @cs: One string - * @ct: Another string + * Find character within a memory region + * + * @v src Source region + * @v character Character to find + * @v len Length + * @ret found Found character, or NULL if not found */ -int strcmp(const char * cs,const char * ct) -{ - register signed char __res; +void * memchr ( const void *src, int character, size_t len ) { + const uint8_t *src_bytes = src; - while (1) { - if ((__res = *cs - *ct++) != 0 || !*cs++) - break; + for ( ; len-- ; src_bytes++ ) { + if ( *src_bytes == character ) + return ( ( void * ) src_bytes ); } - - return __res; + return NULL; } -#endif -#ifndef __HAVE_ARCH_STRNCMP /** - * strncmp - Compare two length-limited strings - * @cs: One string - * @ct: Another string - * @count: The maximum number of bytes to compare + * Swap memory regions + * + * @v first First region + * @v second Second region + * @v len Length + * @ret first First region */ -int strncmp(const char * cs,const char * ct,size_t count) -{ - register signed char __res = 0; - - while (count) { - if ((__res = *cs - *ct++) != 0 || !*cs++) - break; - count--; +void * memswap ( void *first, void *second, size_t len ) { + uint8_t *first_bytes = first; + uint8_t *second_bytes = second; + uint8_t temp; + + for ( ; len-- ; first_bytes++, second_bytes++ ) { + temp = *first_bytes; + *first_bytes = *second_bytes; + *second_bytes = temp; } + return first; +} + +/** + * Compare strings + * + * @v first First string + * @v second Second string + * @ret diff Difference + */ +int strcmp ( const char *first, const char *second ) { - return __res; + return strncmp ( first, second, ~( ( size_t ) 0 ) ); } -#endif -#ifndef __HAVE_ARCH_STRCASECMP -int strcasecmp(const char *a, const char *b) -{ - while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; } - return((*a & ~0x20) - (*b & ~0x20)); +/** + * Compare strings + * + * @v first First string + * @v second Second string + * @v max Maximum length to compare + * @ret diff Difference + */ +int strncmp ( 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 ( ; max-- ; first_bytes++, second_bytes++ ) { + diff = ( *second_bytes - *first_bytes ); + if ( diff ) + return diff; + if ( ! *first_bytes ) + return 0; + } + return 0; } -#endif -#ifndef __HAVE_ARCH_STRCHR /** - * strchr - Find the first occurrence of a character in a string - * @s: The string to be searched - * @c: The character to search for + * Compare case-insensitive strings + * + * @v first First string + * @v second Second string + * @ret diff Difference */ -char * strchr(const char * s, int c) -{ - for(; *s != (char) c; ++s) - if (*s == '\0') - return NULL; - return (char *) s; +int strcasecmp ( const char *first, const char *second ) { + 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++ ) { + diff = ( toupper ( *second_bytes ) - + toupper ( *first_bytes ) ); + if ( diff ) + return diff; + if ( ! *first_bytes ) + return 0; + } } -#endif -#ifndef __HAVE_ARCH_STRRCHR /** - * strrchr - Find the last occurrence of a character in a string - * @s: The string to be searched - * @c: The character to search for + * Get length of string + * + * @v src String + * @ret len Length */ -char * strrchr(const char * s, int c) -{ - const char *p = s + strlen(s); - do { - if (*p == (char)c) - return (char *)p; - } while (--p >= s); - return NULL; +size_t strlen ( const char *src ) { + + return strnlen ( src, ~( ( size_t ) 0 ) ); } -#endif -#ifndef __HAVE_ARCH_STRLEN /** - * strlen - Find the length of a string - * @s: The string to be sized + * Get length of string + * + * @v src String + * @v max Maximum length + * @ret len Length */ -size_t strlen(const char * s) -{ - const char *sc; +size_t strnlen ( const char *src, size_t max ) { + const uint8_t *src_bytes = ( ( const uint8_t * ) src ); + size_t len = 0; - for (sc = s; *sc != '\0'; ++sc) - /* nothing */; - return sc - s; + while ( max-- && *(src_bytes++) ) + len++; + return len; } -#endif -#ifndef __HAVE_ARCH_STRNLEN /** - * strnlen - Find the length of a length-limited string - * @s: The string to be sized - * @count: The maximum number of bytes to search + * Find character within a string + * + * @v src String + * @v character Character to find + * @ret found Found character, or NULL if not found */ -size_t strnlen(const char * s, size_t count) -{ - const char *sc; +char * strchr ( const char *src, int character ) { + const uint8_t *src_bytes = ( ( const uint8_t * ) src ); - for (sc = s; count-- && *sc != '\0'; ++sc) - /* nothing */; - return sc - s; + for ( ; ; src_bytes++ ) { + if ( *src_bytes == character ) + return ( ( char * ) src_bytes ); + if ( ! *src_bytes ) + return NULL; + } } -#endif -#ifndef __HAVE_ARCH_MEMSET /** - * memset - Fill a region of memory with the given value - * @s: Pointer to the start of the area. - * @c: The byte to fill the area with - * @count: The size of the area. + * Find rightmost character within a string * - * Do not use memset() to access IO space, use memset_io() instead. + * @v src String + * @v character Character to find + * @ret found Found character, or NULL if not found */ -void * memset(void * s,int c,size_t count) -{ - char *xs = (char *) s; +char * strrchr ( const char *src, int character ) { + const uint8_t *src_bytes = ( ( const uint8_t * ) src ); + const uint8_t *start = src_bytes; + + while ( *src_bytes ) + src_bytes++; + for ( src_bytes-- ; src_bytes >= start ; src_bytes-- ) { + if ( *src_bytes == character ) + return ( ( char * ) src_bytes ); + } + return NULL; +} - while (count--) - *xs++ = c; +/** + * Find substring + * + * @v haystack String + * @v needle Substring + * @ret found Found substring, or NULL if not found + */ +char * strstr ( const char *haystack, const char *needle ) { + size_t len = strlen ( needle ); - return s; + for ( ; *haystack ; haystack++ ) { + if ( memcmp ( haystack, needle, len ) == 0 ) + return ( ( char * ) haystack ); + } + return NULL; } -#endif -#ifndef __HAVE_ARCH_MEMCPY /** - * memcpy - Copy one area of memory to another - * @dest: Where to copy to - * @src: Where to copy from - * @count: The size of the area. + * Copy string * - * You should not use this function to access IO space, use memcpy_toio() - * or memcpy_fromio() instead. + * @v dest Destination string + * @v src Source string + * @ret dest Destination string */ -void * memcpy(void * dest,const void *src,size_t count) -{ - char *tmp = (char *) dest, *s = (char *) src; +char * strcpy ( char *dest, const char *src ) { + const uint8_t *src_bytes = ( ( const uint8_t * ) src ); + uint8_t *dest_bytes = ( ( uint8_t * ) dest ); + + /* We cannot use strncpy(), since that would pad the destination */ + for ( ; ; src_bytes++, dest_bytes++ ) { + *dest_bytes = *src_bytes; + if ( ! *dest_bytes ) + break; + } + return dest; +} - while (count--) - *tmp++ = *s++; +/** + * Copy string + * + * @v dest Destination string + * @v src Source string + * @v max Maximum length + * @ret dest Destination string + */ +char * strncpy ( char *dest, const char *src, size_t max ) { + const uint8_t *src_bytes = ( ( const uint8_t * ) src ); + uint8_t *dest_bytes = ( ( uint8_t * ) dest ); + for ( ; max ; max--, src_bytes++, dest_bytes++ ) { + *dest_bytes = *src_bytes; + if ( ! *dest_bytes ) + break; + } + while ( max-- ) + *(dest_bytes++) = '\0'; return dest; } -#endif -#ifndef __HAVE_ARCH_MEMMOVE /** - * memmove - Copy one area of memory to another - * @dest: Where to copy to - * @src: Where to copy from - * @count: The size of the area. + * Concatenate string * - * Unlike memcpy(), memmove() copes with overlapping areas. + * @v dest Destination string + * @v src Source string + * @ret dest Destination string */ -void * memmove(void * dest,const void *src,size_t count) -{ - char *tmp, *s; - - if (dest <= src) { - tmp = (char *) dest; - s = (char *) src; - while (count--) - *tmp++ = *s++; - } - else { - tmp = (char *) dest + count; - s = (char *) src + count; - while (count--) - *--tmp = *--s; - } +char * strcat ( char *dest, const char *src ) { + strcpy ( ( dest + strlen ( dest ) ), src ); return dest; } -#endif -#ifndef __HAVE_ARCH_MEMCMP /** - * memcmp - Compare two areas of memory - * @cs: One area of memory - * @ct: Another area of memory - * @count: The size of the area. + * Duplicate string + * + * @v src Source string + * @ret dup Duplicated string, or NULL if allocation failed */ -int memcmp(const void * cs,const void * ct,size_t count) -{ - const unsigned char *su1, *su2; - int res = 0; +char * strdup ( const char *src ) { - for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) - if ((res = *su1 - *su2) != 0) - break; - return res; + return strndup ( src, ~( ( size_t ) 0 ) ); } -#endif -#ifndef __HAVE_ARCH_STRSTR /** - * strstr - Find the first substring in a %NUL terminated string - * @s1: The string to be searched - * @s2: The string to search for + * Duplicate string + * + * @v src Source string + * @v max Maximum length + * @ret dup Duplicated string, or NULL if allocation failed */ -char * strstr(const char * s1,const char * s2) -{ - int l1, l2; - - l2 = strlen(s2); - if (!l2) - return (char *) s1; - l1 = strlen(s1); - while (l1 >= l2) { - l1--; - if (!memcmp(s1,s2,l2)) - return (char *) s1; - s1++; - } - return NULL; +char * strndup ( const char *src, size_t max ) { + size_t len = strnlen ( src, max ); + char *dup; + + dup = malloc ( len + 1 /* NUL */ ); + if ( dup ) { + memcpy ( dup, src, len ); + dup[len] = '\0'; + } + return dup; +} + +/** + * Calculate digit value + * + * @v character Digit character + * @ret digit Digit value + * + * Invalid digits will be returned as a value greater than or equal to + * the numeric base. + */ +unsigned int digit_value ( unsigned int character ) { + + if ( character >= 'a' ) + return ( character - ( 'a' - 10 ) ); + if ( character >= 'A' ) + return ( character - ( 'A' - 10 ) ); + if ( character <= '9' ) + return ( character - '0' ); + return character; } -#endif -#ifndef __HAVE_ARCH_MEMCHR /** - * memchr - Find a character in an area of memory. - * @s: The memory area - * @c: The byte to search for - * @n: The size of the area. + * Preprocess string for strtoul() or strtoull() * - * returns the address of the first occurrence of @c, or %NULL - * if @c is not found + * @v string String + * @v negate Final value should be negated + * @v base Numeric base + * @ret string Remaining string */ -void * memchr(const void *s, int c, size_t n) -{ - const unsigned char *p = s; - while (n-- != 0) { - if ((unsigned char)c == *p++) { - return (void *)(p-1); +static const char * strtoul_pre ( const char *string, int *negate, int *base ) { + + /* Skip any leading whitespace */ + while ( isspace ( *string ) ) + string++; + + /* Process arithmetic sign, if present */ + *negate = 0; + if ( *string == '-' ) { + string++; + *negate = 1; + } else if ( *string == '+' ) { + string++; + } + + /* Process base, if present */ + if ( *base == 0 ) { + *base = 10; + if ( *string == '0' ) { + string++; + *base = 8; + if ( ( *string & ~0x20 ) == 'X' ) { + string++; + *base = 16; + } } } - return NULL; + + return string; } -#endif +/** + * Convert string to numeric value + * + * @v string String + * @v endp End pointer (or NULL) + * @v base Numeric base (or zero to autodetect) + * @ret value Numeric value + */ +unsigned long strtoul ( const char *string, char **endp, int base ) { + unsigned long value = 0; + unsigned int digit; + int negate; + + /* Preprocess string */ + string = strtoul_pre ( string, &negate, &base ); + + /* Process digits */ + for ( ; ; string++ ) { + digit = digit_value ( *string ); + if ( digit >= ( unsigned int ) base ) + break; + value = ( ( value * base ) + digit ); + } + + /* Negate value if, applicable */ + if ( negate ) + value = -value; -char * strndup(const char *s, size_t n) -{ - size_t len = strnlen(s,n); - char *new; + /* Fill in end pointer, if applicable */ + if ( endp ) + *endp = ( ( char * ) string ); - new = malloc(len+1); - if (new) { - new[len] = '\0'; - memcpy(new,s,len); - } - return new; + return value; } -char * strdup(const char *s) { - return strndup(s, ~((size_t)0)); +/** + * Convert string to numeric value + * + * @v string String + * @v endp End pointer (or NULL) + * @v base Numeric base (or zero to autodetect) + * @ret value Numeric value + */ +unsigned long long strtoull ( const char *string, char **endp, int base ) { + unsigned long long value = 0; + unsigned int digit; + int negate; + + /* Preprocess string */ + string = strtoul_pre ( string, &negate, &base ); + + /* Process digits */ + for ( ; ; string++ ) { + digit = digit_value ( *string ); + if ( digit >= ( unsigned int ) base ) + break; + value = ( ( value * base ) + digit ); + } + + /* Negate value if, applicable */ + if ( negate ) + value = -value; + + /* Fill in end pointer, if applicable */ + if ( endp ) + *endp = ( ( char * ) string ); + + return value; } diff --git a/qemu/roms/ipxe/src/core/stringextra.c b/qemu/roms/ipxe/src/core/stringextra.c index 0a509852e..18ffc6301 100644 --- a/qemu/roms/ipxe/src/core/stringextra.c +++ b/qemu/roms/ipxe/src/core/stringextra.c @@ -38,122 +38,6 @@ FILE_LICENCE ( GPL2_ONLY ); /* *** FROM string.c *** */ -#ifndef __HAVE_ARCH_STRNICMP -/** - * strnicmp - Case insensitive, length-limited string comparison - * @s1: One string - * @s2: The other string - * @len: the maximum number of characters to compare - */ -int strnicmp(const char *s1, const char *s2, size_t len) -{ - /* Yes, Virginia, it had better be unsigned */ - unsigned char c1, c2; - - c1 = 0; c2 = 0; - if (len) { - do { - c1 = *s1; c2 = *s2; - s1++; s2++; - if (!c1) - break; - if (!c2) - break; - if (c1 == c2) - continue; - c1 = tolower(c1); - c2 = tolower(c2); - if (c1 != c2) - break; - } while (--len); - } - return (int)c1 - (int)c2; -} -#endif - -char * ___strtok; - -#ifndef __HAVE_ARCH_STRNCAT -/** - * strncat - Append a length-limited, %NUL-terminated string to another - * @dest: The string to be appended to - * @src: The string to append to it - * @count: The maximum numbers of bytes to copy - * - * Note that in contrast to strncpy, strncat ensures the result is - * terminated. - */ -char * strncat(char *dest, const char *src, size_t count) -{ - char *tmp = dest; - - if (count) { - while (*dest) - dest++; - while ((*dest++ = *src++)) { - if (--count == 0) { - *dest = '\0'; - break; - } - } - } - - return tmp; -} -#endif - -#ifndef __HAVE_ARCH_STRSPN -/** - * strspn - Calculate the length of the initial substring of @s which only - * contain letters in @accept - * @s: The string to be searched - * @accept: The string to search for - */ -size_t strspn(const char *s, const char *accept) -{ - const char *p; - const char *a; - size_t count = 0; - - for (p = s; *p != '\0'; ++p) { - for (a = accept; *a != '\0'; ++a) { - if (*p == *a) - break; - } - if (*a == '\0') - return count; - ++count; - } - - return count; -} -#endif - -#ifndef __HAVE_ARCH_STRCSPN -/** - * strcspn - Calculate the length of the initial substring of @s which only - * contain letters not in @reject - * @s: The string to be searched - * @accept: The string to search for - */ -size_t strcspn(const char *s, const char *reject) -{ - const char *p; - const char *r; - size_t count = 0; - - for (p = s; *p != '\0'; ++p) { - for (r = reject; *r != '\0'; ++r) { - if (*p == *r) - return count; - } - ++count; - } - - return count; -} -#endif - #ifndef __HAVE_ARCH_STRPBRK /** * strpbrk - Find the first occurrence of a set of characters @@ -174,35 +58,6 @@ char * strpbrk(const char * cs,const char * ct) } #endif -#ifndef __HAVE_ARCH_STRTOK -/** - * strtok - Split a string into tokens - * @s: The string to be searched - * @ct: The characters to search for - * - * WARNING: strtok is deprecated, use strsep instead. - */ -char * strtok(char * s,const char * ct) -{ - char *sbegin, *send; - - sbegin = s ? s : ___strtok; - if (!sbegin) { - return NULL; - } - sbegin += strspn(sbegin,ct); - if (*sbegin == '\0') { - ___strtok = NULL; - return( NULL ); - } - send = strpbrk( sbegin, ct); - if (send && *send != '\0') - *send++ = '\0'; - ___strtok = send; - return (sbegin); -} -#endif - #ifndef __HAVE_ARCH_STRSEP /** * strsep - Split a string into tokens @@ -230,46 +85,3 @@ char * strsep(char **s, const char *ct) return sbegin; } #endif - -#ifndef __HAVE_ARCH_BCOPY -/** - * bcopy - Copy one area of memory to another - * @src: Where to copy from - * @dest: Where to copy to - * @count: The size of the area. - * - * Note that this is the same as memcpy(), with the arguments reversed. - * memcpy() is the standard, bcopy() is a legacy BSD function. - * - * You should not use this function to access IO space, use memcpy_toio() - * or memcpy_fromio() instead. - */ -char * bcopy(const char * src, char * dest, int count) -{ - return memmove(dest,src,count); -} -#endif - -#ifndef __HAVE_ARCH_MEMSCAN -/** - * memscan - Find a character in an area of memory. - * @addr: The memory area - * @c: The byte to search for - * @size: The size of the area. - * - * returns the address of the first occurrence of @c, or 1 byte past - * the area if @c is not found - */ -void * memscan(const void * addr, int c, size_t size) -{ - unsigned char * p = (unsigned char *) addr; - - while (size) { - if (*p == c) - return (void *) p; - p++; - size--; - } - return (void *) p; -} -#endif diff --git a/qemu/roms/ipxe/src/core/strtoull.c b/qemu/roms/ipxe/src/core/strtoull.c deleted file mode 100644 index 00986eef0..000000000 --- a/qemu/roms/ipxe/src/core/strtoull.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown - * Copyright (C) 2010 Piotr Jaroszyński - * - * 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 St, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include -#include - -/* - * Despite being exactly the same as strtoul() except the long long instead of - * long it ends up being much bigger so provide a separate implementation in a - * separate object so that it won't be linked in if not used. - */ -unsigned long long strtoull ( const char *p, char **endp, int base ) { - unsigned long long ret = 0; - int negative = 0; - unsigned int charval; - - while ( isspace ( *p ) ) - p++; - - if ( *p == '-' ) { - negative = 1; - p++; - } - - base = strtoul_base ( &p, base ); - - while ( 1 ) { - charval = strtoul_charval ( *p ); - if ( charval >= ( unsigned int ) base ) - break; - ret = ( ( ret * base ) + charval ); - p++; - } - - if ( negative ) - ret = -ret; - - if ( endp ) - *endp = ( char * ) p; - - return ( ret ); -} diff --git a/qemu/roms/ipxe/src/core/time.c b/qemu/roms/ipxe/src/core/time.c index f70e1981d..29a924ebe 100644 --- a/qemu/roms/ipxe/src/core/time.c +++ b/qemu/roms/ipxe/src/core/time.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include diff --git a/qemu/roms/ipxe/src/core/timer.c b/qemu/roms/ipxe/src/core/timer.c index 18c2b2849..dbd89f12b 100644 --- a/qemu/roms/ipxe/src/core/timer.c +++ b/qemu/roms/ipxe/src/core/timer.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include diff --git a/qemu/roms/ipxe/src/core/uart.c b/qemu/roms/ipxe/src/core/uart.c new file mode 100644 index 000000000..b85fe0767 --- /dev/null +++ b/qemu/roms/ipxe/src/core/uart.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2014 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 ); + +/** @file + * + * 16550-compatible UART + * + */ + +#include +#include +#include + +/** Timeout for transmit holding register to become empty */ +#define UART_THRE_TIMEOUT_MS 100 + +/** Timeout for transmitter to become empty */ +#define UART_TEMT_TIMEOUT_MS 1000 + +/** + * Transmit data + * + * @v uart UART + * @v data Data + */ +void uart_transmit ( struct uart *uart, uint8_t data ) { + unsigned int i; + uint8_t lsr; + + /* Wait for transmitter holding register to become empty */ + for ( i = 0 ; i < UART_THRE_TIMEOUT_MS ; i++ ) { + lsr = uart_read ( uart, UART_LSR ); + if ( lsr & UART_LSR_THRE ) + break; + mdelay ( 1 ); + } + + /* Transmit data (even if we timed out) */ + uart_write ( uart, UART_THR, data ); +} + +/** + * Flush data + * + * @v uart UART + */ +void uart_flush ( struct uart *uart ) { + unsigned int i; + uint8_t lsr; + + /* Wait for transmitter and receiver to become empty */ + for ( i = 0 ; i < UART_TEMT_TIMEOUT_MS ; i++ ) { + uart_read ( uart, UART_RBR ); + lsr = uart_read ( uart, UART_LSR ); + if ( ( lsr & UART_LSR_TEMT ) && ! ( lsr & UART_LSR_DR ) ) + break; + } +} + +/** + * Check for existence of UART + * + * @v uart UART + * @ret rc Return status code + */ +int uart_exists ( struct uart *uart ) { + + /* Fail if no UART port is defined */ + if ( ! uart->base ) + return -ENODEV; + + /* Fail if UART scratch register seems not to be present */ + uart_write ( uart, UART_SCR, 0x18 ); + if ( uart_read ( uart, UART_SCR ) != 0x18 ) + return -ENODEV; + uart_write ( uart, UART_SCR, 0xae ); + if ( uart_read ( uart, UART_SCR ) != 0xae ) + return -ENODEV; + + return 0; +} + +/** + * Initialise UART + * + * @v uart UART + * @v baud Baud rate, or zero to leave unchanged + * @v lcr Line control register value, or zero to leave unchanged + * @ret rc Return status code + */ +int uart_init ( struct uart *uart, unsigned int baud, uint8_t lcr ) { + uint8_t dlm; + uint8_t dll; + int rc; + + /* Check for existence of UART */ + if ( ( rc = uart_exists ( uart ) ) != 0 ) + return rc; + + /* Configure divisor and line control register, if applicable */ + if ( ! lcr ) + lcr = uart_read ( uart, UART_LCR ); + uart->lcr = lcr; + uart_write ( uart, UART_LCR, ( lcr | UART_LCR_DLAB ) ); + if ( baud ) { + uart->divisor = ( UART_MAX_BAUD / baud ); + dlm = ( ( uart->divisor >> 8 ) & 0xff ); + dll = ( ( uart->divisor >> 0 ) & 0xff ); + uart_write ( uart, UART_DLM, dlm ); + uart_write ( uart, UART_DLL, dll ); + } else { + dlm = uart_read ( uart, UART_DLM ); + dll = uart_read ( uart, UART_DLL ); + uart->divisor = ( ( dlm << 8 ) | dll ); + } + uart_write ( uart, UART_LCR, ( lcr & ~UART_LCR_DLAB ) ); + + /* Disable interrupts */ + uart_write ( uart, UART_IER, 0 ); + + /* Enable FIFOs */ + uart_write ( uart, UART_FCR, UART_FCR_FE ); + + /* Assert DTR and RTS */ + uart_write ( uart, UART_MCR, ( UART_MCR_DTR | UART_MCR_RTS ) ); + + /* Flush any stale data */ + uart_flush ( uart ); + + return 0; +} diff --git a/qemu/roms/ipxe/src/core/uri.c b/qemu/roms/ipxe/src/core/uri.c index 9ec21cee4..3b5f270fe 100644 --- a/qemu/roms/ipxe/src/core/uri.c +++ b/qemu/roms/ipxe/src/core/uri.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * @@ -661,6 +665,7 @@ struct uri * resolve_uri ( const struct uri *base_uri, * Construct TFTP URI from next-server and filename * * @v next_server Next-server address + * @v port Port number, or zero to use the default port * @v filename Filename * @ret uri URI, or NULL on failure * @@ -669,12 +674,18 @@ struct uri * resolve_uri ( const struct uri *base_uri, * generic URI parser. We provide a mechanism for directly * constructing a TFTP URI from the next-server and filename. */ -struct uri * tftp_uri ( struct in_addr next_server, const char *filename ) { +struct uri * tftp_uri ( struct in_addr next_server, unsigned int port, + const char *filename ) { + char buf[ 6 /* "65535" + NUL */ ]; struct uri uri; memset ( &uri, 0, sizeof ( uri ) ); uri.scheme = "tftp"; uri.host = inet_ntoa ( next_server ); + if ( port ) { + snprintf ( buf, sizeof ( buf ), "%d", port ); + uri.port = buf; + } uri.path = filename; return uri_dup ( &uri ); } diff --git a/qemu/roms/ipxe/src/core/uuid.c b/qemu/roms/ipxe/src/core/uuid.c index 27a249da8..b8d21de17 100644 --- a/qemu/roms/ipxe/src/core/uuid.c +++ b/qemu/roms/ipxe/src/core/uuid.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/version.c b/qemu/roms/ipxe/src/core/version.c index 1e1e9daca..c984335c2 100644 --- a/qemu/roms/ipxe/src/core/version.c +++ b/qemu/roms/ipxe/src/core/version.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * @@ -29,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** * Create wide-character version of string diff --git a/qemu/roms/ipxe/src/core/vsprintf.c b/qemu/roms/ipxe/src/core/vsprintf.c index 54811b11b..cb3bec5dd 100644 --- a/qemu/roms/ipxe/src/core/vsprintf.c +++ b/qemu/roms/ipxe/src/core/vsprintf.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include diff --git a/qemu/roms/ipxe/src/core/wchar.c b/qemu/roms/ipxe/src/core/wchar.c index 7fabca470..860322820 100644 --- a/qemu/roms/ipxe/src/core/wchar.c +++ b/qemu/roms/ipxe/src/core/wchar.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** * @file diff --git a/qemu/roms/ipxe/src/core/xfer.c b/qemu/roms/ipxe/src/core/xfer.c index 8d4bc9f53..112fee1bf 100644 --- a/qemu/roms/ipxe/src/core/xfer.c +++ b/qemu/roms/ipxe/src/core/xfer.c @@ -15,9 +15,13 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include @@ -134,18 +138,8 @@ size_t xfer_window ( struct interface *intf ) { * generating an xfer_window_changed() message. */ void xfer_window_changed ( struct interface *intf ) { - struct interface *dest; - xfer_window_changed_TYPE ( void * ) *op = - intf_get_dest_op ( intf, xfer_window_changed, &dest ); - void *object = intf_object ( dest ); - if ( op ) { - op ( object ); - } else { - /* Default is to do nothing */ - } - - intf_put ( dest ); + intf_poke ( intf, xfer_window_changed ); } /** @@ -365,3 +359,34 @@ int xfer_seek ( struct interface *intf, off_t offset ) { return xfer_deliver ( intf, iobuf, &meta ); } + +/** + * Check that data is delivered strictly in order + * + * @v meta Data transfer metadata + * @v pos Current position + * @v len Length of data + * @ret rc Return status code + */ +int xfer_check_order ( struct xfer_metadata *meta, size_t *pos, size_t len ) { + size_t new_pos; + + /* Allow out-of-order zero-length packets (as used by xfer_seek()) */ + if ( len == 0 ) + return 0; + + /* Calculate position of this delivery */ + new_pos = *pos; + if ( meta->flags & XFER_FL_ABS_OFFSET ) + new_pos = 0; + new_pos += meta->offset; + + /* Fail if delivery position is not equal to current position */ + if ( new_pos != *pos ) + return -EPROTO; + + /* Update current position */ + *pos += len; + + return 0; +} diff --git a/qemu/roms/ipxe/src/core/xferbuf.c b/qemu/roms/ipxe/src/core/xferbuf.c index a0457feee..240118557 100644 --- a/qemu/roms/ipxe/src/core/xferbuf.c +++ b/qemu/roms/ipxe/src/core/xferbuf.c @@ -15,15 +15,21 @@ * 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 ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include #include #include +#include +#include #include /** @file @@ -32,14 +38,26 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/** Data delivery profiler */ +static struct profiler xferbuf_deliver_profiler __profiler = + { .name = "xferbuf.deliver" }; + +/** Data write profiler */ +static struct profiler xferbuf_write_profiler __profiler = + { .name = "xferbuf.write" }; + +/** Data read profiler */ +static struct profiler xferbuf_read_profiler __profiler = + { .name = "xferbuf.read" }; + /** - * Finish using data transfer buffer + * Free data transfer buffer * * @v xferbuf Data transfer buffer */ -void xferbuf_done ( struct xfer_buffer *xferbuf ) { - free ( xferbuf->data ); - xferbuf->data = NULL; +void xferbuf_free ( struct xfer_buffer *xferbuf ) { + + xferbuf->op->realloc ( xferbuf, 0 ); xferbuf->len = 0; xferbuf->pos = 0; } @@ -52,25 +70,77 @@ void xferbuf_done ( struct xfer_buffer *xferbuf ) { * @ret rc Return status code */ static int xferbuf_ensure_size ( struct xfer_buffer *xferbuf, size_t len ) { - void *new_data; + int rc; /* If buffer is already large enough, do nothing */ if ( len <= xferbuf->len ) return 0; /* Extend buffer */ - new_data = realloc ( xferbuf->data, len ); - if ( ! new_data ) { + if ( ( rc = xferbuf->op->realloc ( xferbuf, len ) ) != 0 ) { DBGC ( xferbuf, "XFERBUF %p could not extend buffer to " - "%zd bytes\n", xferbuf, len ); - return -ENOSPC; + "%zd bytes: %s\n", xferbuf, len, strerror ( rc ) ); + return rc; } - xferbuf->data = new_data; xferbuf->len = len; return 0; } +/** + * Write to data transfer buffer + * + * @v xferbuf Data transfer buffer + * @v offset Starting offset + * @v data Data to write + * @v len Length of data + */ +int xferbuf_write ( struct xfer_buffer *xferbuf, size_t offset, + const void *data, size_t len ) { + size_t max_len; + int rc; + + /* Check for overflow */ + max_len = ( offset + len ); + if ( max_len < offset ) + return -EOVERFLOW; + + /* Ensure buffer is large enough to contain this write */ + if ( ( rc = xferbuf_ensure_size ( xferbuf, max_len ) ) != 0 ) + return rc; + + /* Copy data to buffer */ + profile_start ( &xferbuf_write_profiler ); + xferbuf->op->write ( xferbuf, offset, data, len ); + profile_stop ( &xferbuf_write_profiler ); + + return 0; +} + +/** + * Read from data transfer buffer + * + * @v xferbuf Data transfer buffer + * @v offset Starting offset + * @v data Data to write + * @v len Length of data + */ +int xferbuf_read ( struct xfer_buffer *xferbuf, size_t offset, + void *data, size_t len ) { + + /* Check that read is within buffer range */ + if ( ( offset > xferbuf->len ) || + ( len > ( xferbuf->len - offset ) ) ) + return -ENOENT; + + /* Copy data from buffer */ + profile_start ( &xferbuf_read_profiler ); + xferbuf->op->read ( xferbuf, offset, data, len ); + profile_stop ( &xferbuf_read_profiler ); + + return 0; +} + /** * Add received data to data transfer buffer * @@ -81,28 +151,174 @@ static int xferbuf_ensure_size ( struct xfer_buffer *xferbuf, size_t len ) { */ int xferbuf_deliver ( struct xfer_buffer *xferbuf, struct io_buffer *iobuf, struct xfer_metadata *meta ) { - size_t len; - size_t max; + size_t len = iob_len ( iobuf ); + size_t pos; int rc; + /* Start profiling */ + profile_start ( &xferbuf_deliver_profiler ); + /* Calculate new buffer position */ + pos = xferbuf->pos; if ( meta->flags & XFER_FL_ABS_OFFSET ) - xferbuf->pos = 0; - xferbuf->pos += meta->offset; + pos = 0; + pos += meta->offset; - /* Ensure that we have enough buffer space for this data */ - len = iob_len ( iobuf ); - max = ( xferbuf->pos + len ); - if ( ( rc = xferbuf_ensure_size ( xferbuf, max ) ) != 0 ) + /* Write data to buffer */ + if ( ( rc = xferbuf_write ( xferbuf, pos, iobuf->data, len ) ) != 0 ) goto done; - /* Copy data to buffer */ - memcpy ( ( xferbuf->data + xferbuf->pos ), iobuf->data, len ); - /* Update current buffer position */ - xferbuf->pos += len; + xferbuf->pos = ( pos + len ); done: free_iob ( iobuf ); + profile_stop ( &xferbuf_deliver_profiler ); return rc; } + +/** + * Reallocate malloc()-based data buffer + * + * @v xferbuf Data transfer buffer + * @v len New length (or zero to free buffer) + * @ret rc Return status code + */ +static int xferbuf_malloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) { + void *new_data; + + new_data = realloc ( xferbuf->data, len ); + if ( ! new_data ) + return -ENOSPC; + xferbuf->data = new_data; + return 0; +} + +/** + * Write data to malloc()-based data buffer + * + * @v xferbuf Data transfer buffer + * @v offset Starting offset + * @v data Data to copy + * @v len Length of data + */ +static void xferbuf_malloc_write ( struct xfer_buffer *xferbuf, size_t offset, + const void *data, size_t len ) { + + memcpy ( ( xferbuf->data + offset ), data, len ); +} + +/** + * Read data from malloc()-based data buffer + * + * @v xferbuf Data transfer buffer + * @v offset Starting offset + * @v data Data to read + * @v len Length of data + */ +static void xferbuf_malloc_read ( struct xfer_buffer *xferbuf, size_t offset, + void *data, size_t len ) { + + memcpy ( data, ( xferbuf->data + offset ), len ); +} + +/** malloc()-based data buffer operations */ +struct xfer_buffer_operations xferbuf_malloc_operations = { + .realloc = xferbuf_malloc_realloc, + .write = xferbuf_malloc_write, + .read = xferbuf_malloc_read, +}; + +/** + * Reallocate umalloc()-based data buffer + * + * @v xferbuf Data transfer buffer + * @v len New length (or zero to free buffer) + * @ret rc Return status code + */ +static int xferbuf_umalloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) { + userptr_t *udata = xferbuf->data; + userptr_t new_udata; + + new_udata = urealloc ( *udata, len ); + if ( ! new_udata ) + return -ENOSPC; + *udata = new_udata; + return 0; +} + +/** + * Write data to umalloc()-based data buffer + * + * @v xferbuf Data transfer buffer + * @v offset Starting offset + * @v data Data to copy + * @v len Length of data + */ +static void xferbuf_umalloc_write ( struct xfer_buffer *xferbuf, size_t offset, + const void *data, size_t len ) { + userptr_t *udata = xferbuf->data; + + copy_to_user ( *udata, offset, data, len ); +} + +/** + * Read data from umalloc()-based data buffer + * + * @v xferbuf Data transfer buffer + * @v offset Starting offset + * @v data Data to read + * @v len Length of data + */ +static void xferbuf_umalloc_read ( struct xfer_buffer *xferbuf, size_t offset, + void *data, size_t len ) { + userptr_t *udata = xferbuf->data; + + copy_from_user ( data, *udata, offset, len ); +} + +/** umalloc()-based data buffer operations */ +struct xfer_buffer_operations xferbuf_umalloc_operations = { + .realloc = xferbuf_umalloc_realloc, + .write = xferbuf_umalloc_write, + .read = xferbuf_umalloc_read, +}; + +/** + * Get underlying data transfer buffer + * + * @v interface Data transfer interface + * @ret xferbuf Data transfer buffer, or NULL on error + * + * This call will check that the xfer_buffer() handler belongs to the + * destination interface which also provides xfer_deliver() for this + * interface. + * + * This is done to prevent accidental accesses to a data transfer + * buffer which may be located behind a non-transparent datapath via a + * series of pass-through interfaces. + */ +struct xfer_buffer * xfer_buffer ( struct interface *intf ) { + struct interface *dest; + xfer_buffer_TYPE ( void * ) *op = + intf_get_dest_op ( intf, xfer_buffer, &dest ); + void *object = intf_object ( dest ); + struct interface *xfer_deliver_dest; + struct xfer_buffer *xferbuf; + + /* Check that this operation is provided by the same interface + * which handles xfer_deliver(). + */ + ( void ) intf_get_dest_op ( intf, xfer_deliver, &xfer_deliver_dest ); + + if ( op && ( dest == xfer_deliver_dest ) ) { + xferbuf = op ( object ); + } else { + /* Default is to not have a data transfer buffer */ + xferbuf = NULL; + } + + intf_put ( xfer_deliver_dest ); + intf_put ( dest ); + return xferbuf; +} -- cgit 1.2.3-korg