[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/contrib/vm/bochsrc.txt
|
@@ -341,7 +341,7 @@
#optromimage2: file=optionalrom.bin, address=0xd1000
#optromimage3: file=optionalrom.bin, address=0xd2000
#optromimage4: file=optionalrom.bin, address=0xd3000
-optromimage1: file=../../src/bin/intel.rom, address=0xd0000
+optromimage1: file=../../src/bin/intel.rom, address=0xcb000
#optramimage1: file=/path/file1.img, address=0x0010000
#optramimage2: file=/path/file2.img, address=0x0020000
@@ -1066,7 +1066,7 @@
# Example:
# port_e9_hack: enabled=1
#=======================================================================
-#port_e9_hack: enabled=1
+port_e9_hack: enabled=1
#=======================================================================
# DEBUG_SYMBOLS:
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/Makefile.housekeeping
^
|
@@ -663,7 +663,7 @@
define deps_template
@$(ECHO) " [DEPS] $(1)"
@$(MKDIR) -p $(BIN)/deps/$(dir $(1))
- @$(CPP) $(CFLAGS) $(CFLAGS_$(2)) $(CFLAGS_$(3)) -DOBJECT=$(3) \
+ $(Q)$(CPP) $(CFLAGS) $(CFLAGS_$(2)) $(CFLAGS_$(3)) -DOBJECT=$(3) \
-Wno-error -M $(1) -MG -MP | \
sed 's/\.o\s*:/_DEPS +=/' > $(BIN)/deps/$(1).d
endef
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/image/bootsector.c
^
|
@@ -80,9 +80,22 @@
"movw %%ss, %%ax\n\t"
"movw %%ax, %%cs:saved_ss\n\t"
"movw %%sp, %%cs:saved_sp\n\t"
- /* Jump to boot sector */
+ /* Prepare jump to boot sector */
"pushw %%bx\n\t"
"pushw %%di\n\t"
+ /* Clear all registers */
+ "xorl %%eax, %%eax\n\t"
+ "xorl %%ebx, %%ebx\n\t"
+ "xorl %%ecx, %%ecx\n\t"
+ /* %edx contains drive number */
+ "xorl %%esi, %%esi\n\t"
+ "xorl %%edi, %%edi\n\t"
+ "xorl %%ebp, %%ebp\n\t"
+ "movw %%ax, %%ds\n\t"
+ "movw %%ax, %%es\n\t"
+ "movw %%ax, %%fs\n\t"
+ "movw %%ax, %%gs\n\t"
+ /* Jump to boot sector */
"sti\n\t"
"lret\n\t"
/* Preserved variables */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/image/bzimage.c
^
|
@@ -323,6 +323,32 @@
}
/**
+ * Parse standalone image command line for cpio parameters
+ *
+ * @v image bzImage file
+ * @v cpio CPIO header
+ * @v cmdline Command line
+ */
+static void bzimage_parse_cpio_cmdline ( struct image *image,
+ struct cpio_header *cpio,
+ const char *cmdline ) {
+ char *arg;
+ char *end;
+ unsigned int mode;
+
+ /* Look for "mode=" */
+ if ( ( arg = strstr ( cmdline, "mode=" ) ) ) {
+ arg += 5;
+ mode = strtoul ( arg, &end, 8 /* Octal for file mode */ );
+ if ( *end && ( *end != ' ' ) ) {
+ DBGC ( image, "bzImage %p strange \"mode=\""
+ "terminator '%c'\n", image, *end );
+ }
+ cpio_set_field ( cpio->c_mode, ( 0100000 | mode ) );
+ }
+}
+
+/**
* Load initrd
*
* @v image bzImage image
@@ -334,8 +360,10 @@
struct image *initrd,
userptr_t address ) {
char *filename = initrd->cmdline;
+ char *cmdline;
struct cpio_header cpio;
size_t offset = 0;
+ size_t name_len;
/* Do not include kernel image itself as an initrd */
if ( initrd == image )
@@ -343,24 +371,30 @@
/* Create cpio header before non-prebuilt images */
if ( filename && filename[0] ) {
- size_t name_len = ( strlen ( filename ) + 1 );
-
DBGC ( image, "bzImage %p inserting initrd %p as %s\n",
image, initrd, filename );
+ cmdline = strchr ( filename, ' ' );
+ name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) )
+ : strlen ( filename ) ) + 1 /* NUL */ );
memset ( &cpio, '0', sizeof ( cpio ) );
memcpy ( cpio.c_magic, CPIO_MAGIC, sizeof ( cpio.c_magic ) );
cpio_set_field ( cpio.c_mode, 0100644 );
cpio_set_field ( cpio.c_nlink, 1 );
cpio_set_field ( cpio.c_filesize, initrd->len );
cpio_set_field ( cpio.c_namesize, name_len );
+ if ( cmdline ) {
+ bzimage_parse_cpio_cmdline ( image, &cpio,
+ ( cmdline + 1 /* ' ' */ ));
+ }
if ( address ) {
copy_to_user ( address, offset, &cpio,
sizeof ( cpio ) );
}
offset += sizeof ( cpio );
if ( address ) {
+ memset_user ( address, offset, 0, name_len );
copy_to_user ( address, offset, filename,
- name_len );
+ ( name_len - 1 /* NUL (or space) */ ) );
}
offset += name_len;
offset = ( ( offset + 0x03 ) & ~0x03 );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/image/comboot.c
^
|
@@ -229,7 +229,7 @@
++ext;
- if ( strcasecmp( ext, "com" ) && strcasecmp( ext, "cbt" ) ) {
+ if ( strcasecmp( ext, "cbt" ) ) {
DBGC ( image, "COMBOOT %p: unrecognized extension %s\n",
image, ext );
return -ENOEXEC;
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/image/sdi.c
^
|
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (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.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <realmode.h>
+#include <sdi.h>
+#include <ipxe/image.h>
+#include <ipxe/features.h>
+
+/** @file
+ *
+ * System Deployment Image (SDI)
+ *
+ * Based on the MSDN article "RAM boot using SDI in Windows XP
+ * Embedded with Service Pack 1", available at the time of writing
+ * from:
+ *
+ * http://msdn.microsoft.com/en-us/library/ms838543.aspx
+ */
+
+FEATURE ( FEATURE_IMAGE, "SDI", DHCP_EB_FEATURE_SDI, 1 );
+
+/**
+ * Parse SDI image header
+ *
+ * @v image SDI file
+ * @v sdi SDI header to fill in
+ * @ret rc Return status code
+ */
+static int sdi_parse_header ( struct image *image, struct sdi_header *sdi ) {
+
+ /* Sanity check */
+ if ( image->len < sizeof ( *sdi ) ) {
+ DBGC ( image, "SDI %p too short for SDI header\n", image );
+ return -ENOEXEC;
+ }
+
+ /* Read in header */
+ copy_from_user ( sdi, image->data, 0, sizeof ( *sdi ) );
+
+ /* Check signature */
+ if ( sdi->magic != SDI_MAGIC ) {
+ DBGC ( image, "SDI %p is not an SDI image\n", image );
+ return -ENOEXEC;
+ }
+
+ return 0;
+}
+
+/**
+ * Execute SDI image
+ *
+ * @v image SDI file
+ * @ret rc Return status code
+ */
+static int sdi_exec ( struct image *image ) {
+ struct sdi_header sdi;
+ uint32_t sdiptr;
+ int rc;
+
+ /* Parse image header */
+ if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 )
+ return rc;
+
+ /* Check that image is bootable */
+ if ( sdi.boot_size == 0 ) {
+ DBGC ( image, "SDI %p is not bootable\n", image );
+ return -ENOTTY;
+ }
+ DBGC ( image, "SDI %p image at %08lx+%08zx\n",
+ image, user_to_phys ( image->data, 0 ), image->len );
+ DBGC ( image, "SDI %p boot code at %08lx+%llx\n", image,
+ user_to_phys ( image->data, sdi.boot_offset ), sdi.boot_size );
+
+ /* Copy boot code */
+ memcpy_user ( real_to_user ( SDI_BOOT_SEG, SDI_BOOT_OFF ), 0,
+ image->data, sdi.boot_offset, sdi.boot_size );
+
+ /* Jump to boot code */
+ sdiptr = ( user_to_phys ( image->data, 0 ) | SDI_WTF );
+ __asm__ __volatile__ ( REAL_CODE ( "ljmp %0, %1\n\t" )
+ : : "i" ( SDI_BOOT_SEG ),
+ "i" ( SDI_BOOT_OFF ),
+ "d" ( sdiptr ) );
+
+ /* There is no way for the image to return, since we provide
+ * no return address.
+ */
+ assert ( 0 );
+
+ return -ECANCELED; /* -EIMPOSSIBLE */
+}
+
+/**
+ * Probe SDI image
+ *
+ * @v image SDI file
+ * @ret rc Return status code
+ */
+static int sdi_probe ( struct image *image ) {
+ struct sdi_header sdi;
+ int rc;
+
+ /* Parse image */
+ if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/** SDI image type */
+struct image_type sdi_image_type __image_type ( PROBE_NORMAL ) = {
+ .name = "SDI",
+ .probe = sdi_probe,
+ .exec = sdi_exec,
+};
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/include/sdi.h
^
|
@@ -0,0 +1,39 @@
+#ifndef _SDI_H
+#define _SDI_H
+
+/** @file
+ *
+ * System Deployment Image (SDI)
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** SDI image header */
+struct sdi_header {
+ /** Signature */
+ uint32_t magic;
+ /** Version (as an ASCII string) */
+ uint32_t version;
+ /** Reserved */
+ uint8_t reserved[8];
+ /** Boot code offset */
+ uint64_t boot_offset;
+ /** Boot code size */
+ uint64_t boot_size;
+} __attribute__ (( packed ));
+
+/** SDI image signature */
+#define SDI_MAGIC \
+ ( ( '$' << 0 ) | ( 'S' << 8 ) | ( 'D' << 16 ) | ( 'I' << 24 ) )
+
+/** SDI boot segment */
+#define SDI_BOOT_SEG 0x0000
+
+/** SDI boot offset */
+#define SDI_BOOT_OFF 0x7c00
+
+/** Constant to binary-OR with physical address of SDI image */
+#define SDI_WTF 0x41
+
+#endif /* _SDI_H */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/interface/pcbios/int13.c
^
|
@@ -627,7 +627,7 @@
static int int13_guess_geometry_fdd ( struct int13_drive *int13,
unsigned int *heads,
unsigned int *sectors ) {
- unsigned int blocks = int13_blksize ( int13 );
+ unsigned int blocks = int13_capacity ( int13 );
const struct int13_fdd_geometry *geometry;
unsigned int cylinders;
unsigned int i;
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/interface/pxe/pxe_undi.c
^
|
@@ -358,7 +358,8 @@
}
/* Allocate and fill I/O buffer */
- iobuf = alloc_iob ( MAX_LL_HEADER_LEN + len );
+ iobuf = alloc_iob ( MAX_LL_HEADER_LEN +
+ ( ( len > IOB_ZLEN ) ? len : IOB_ZLEN ) );
if ( ! iobuf ) {
DBGC2 ( &pxe_netdev, " could not allocate iobuf\n" );
undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES;
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/x86/core/debugcon.c
^
|
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (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.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Debug port console
+ *
+ * The debug port is supported by bochs (via the "port_e9_hack"
+ * configuration file directive) and by qemu (via the "-debugcon"
+ * command-line option).
+ */
+
+#include <stdint.h>
+#include <ipxe/io.h>
+#include <ipxe/console.h>
+#include <ipxe/init.h>
+#include <config/console.h>
+
+/** Debug port */
+#define DEBUG_PORT 0xe9
+
+/** Debug port installation check magic value */
+#define DEBUG_PORT_CHECK 0xe9
+
+/* Set default console usage if applicable */
+#if ! ( defined ( CONSOLE_DEBUGCON ) && CONSOLE_EXPLICIT ( CONSOLE_DEBUGCON ) )
+#undef CONSOLE_DEBUGCON
+#define CONSOLE_DEBUGCON ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_TUI )
+#endif
+
+/**
+ * Print a character to debug port console
+ *
+ * @v character Character to be printed
+ */
+static void debugcon_putchar ( int character ) {
+
+ /* Write character to debug port */
+ outb ( character, DEBUG_PORT );
+}
+
+/** Debug port console driver */
+struct console_driver debugcon_console __console_driver = {
+ .putchar = debugcon_putchar,
+ .usage = CONSOLE_DEBUGCON,
+};
+
+/**
+ * Initialise debug port console
+ *
+ */
+static void debugcon_init ( void ) {
+ uint8_t check;
+
+ /* Check if console is present */
+ check = inb ( DEBUG_PORT );
+ if ( check != DEBUG_PORT_CHECK ) {
+ DBG ( "Debug port not present; disabling console\n" );
+ debugcon_console.disabled = 1;
+ }
+}
+
+/**
+ * Debug port console initialisation function
+ */
+struct init_fn debugcon_init_fn __init_fn ( INIT_EARLY ) = {
+ .initialise = debugcon_init,
+};
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/x86/include/bits/errfile.h
^
|
@@ -31,6 +31,7 @@
#define ERRFILE_com32 ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00080000 )
#define ERRFILE_comboot_resolv ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00090000 )
#define ERRFILE_comboot_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000a0000 )
+#define ERRFILE_sdi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000b0000 )
#define ERRFILE_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 )
#define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 )
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/config/config.c
^
|
@@ -89,6 +89,9 @@
#ifdef CONSOLE_VMWARE
REQUIRE_OBJECT ( vmconsole );
#endif
+#ifdef CONSOLE_DEBUGCON
+REQUIRE_OBJECT ( debugcon );
+#endif
/*
* Drag in all requested network protocols
@@ -181,6 +184,9 @@
#ifdef IMAGE_EFI
REQUIRE_OBJECT ( efi_image );
#endif
+#ifdef IMAGE_SDI
+REQUIRE_OBJECT ( sdi );
+#endif
/*
* Drag in all requested commands
@@ -244,6 +250,9 @@
#ifdef SYNC_CMD
REQUIRE_OBJECT ( sync_cmd );
#endif
+#ifdef NSLOOKUP_CMD
+REQUIRE_OBJECT ( nslookup_cmd );
+#endif
/*
* Drag in miscellaneous objects
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/config/console.h
^
|
@@ -21,6 +21,7 @@
//#define CONSOLE_SYSLOG /* Syslog console */
//#define CONSOLE_SYSLOGS /* Encrypted syslog console */
//#define CONSOLE_VMWARE /* VMware logfile console */
+//#define CONSOLE_DEBUGCON /* Debug port console */
#define KEYBOARD_MAP us
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/config/general.h
^
|
@@ -100,6 +100,7 @@
//#define IMAGE_BZIMAGE /* Linux bzImage image support */
//#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */
//#define IMAGE_EFI /* EFI image support */
+//#define IMAGE_SDI /* SDI image support */
/*
* Command-line commands to include
@@ -118,6 +119,7 @@
#define MENU_CMD /* Menu commands */
#define LOGIN_CMD /* Login command */
#define SYNC_CMD /* Sync command */
+//#define NSLOOKUP_CMD /* DNS resolving command */
//#define TIME_CMD /* Time commands */
//#define DIGEST_CMD /* Image crypto digest commands */
//#define LOTEST_CMD /* Loopback testing commands */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/config/sideband.h
^
|
@@ -12,4 +12,6 @@
//#define CONFIG_BOFM /* IBM's BladeCenter Open Fabric Manager */
//#define VMWARE_SETTINGS /* VMware GuestInfo settings */
+#include <config/local/sideband.h>
+
#endif /* CONFIG_SIDEBAND_H */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/iobuf.c
^
|
@@ -32,31 +32,25 @@
*/
/**
- * Allocate I/O buffer
+ * Allocate I/O buffer with specified alignment and offset
*
* @v len Required length of buffer
+ * @v align Physical alignment
+ * @v offset Offset from physical alignment
* @ret iobuf I/O buffer, or NULL if none available
*
- * The I/O buffer will be physically aligned to a multiple of
- * @c IOBUF_SIZE.
+ * @c align will be rounded up to the nearest power of two.
*/
-struct io_buffer * alloc_iob ( size_t len ) {
+struct io_buffer * alloc_iob_raw ( size_t len, size_t align, size_t offset ) {
struct io_buffer *iobuf;
- size_t align;
void *data;
- /* Pad to minimum length */
- if ( len < IOB_ZLEN )
- len = IOB_ZLEN;
-
/* Align buffer length to ensure that struct io_buffer is aligned */
len = ( len + __alignof__ ( *iobuf ) - 1 ) &
~( __alignof__ ( *iobuf ) - 1 );
- /* Align buffer on its own size to avoid potential problems
- * with boundary-crossing DMA.
- */
- align = ( 1 << fls ( len - 1 ) );
+ /* Round up alignment to the nearest power of two */
+ align = ( 1 << fls ( align - 1 ) );
/* Allocate buffer plus descriptor as a single unit, unless
* doing so will push the total size over the alignment
@@ -65,7 +59,8 @@
if ( ( len + sizeof ( *iobuf ) ) <= align ) {
/* Allocate memory for buffer plus descriptor */
- data = malloc_dma ( len + sizeof ( *iobuf ), align );
+ data = malloc_dma_offset ( len + sizeof ( *iobuf ), align,
+ offset );
if ( ! data )
return NULL;
iobuf = ( data + len );
@@ -73,7 +68,7 @@
} else {
/* Allocate memory for buffer */
- data = malloc_dma ( len, align );
+ data = malloc_dma_offset ( len, align, offset );
if ( ! data )
return NULL;
@@ -92,6 +87,26 @@
return iobuf;
}
+/**
+ * Allocate I/O buffer
+ *
+ * @v len Required length of buffer
+ * @ret iobuf I/O buffer, or NULL if none available
+ *
+ * The I/O buffer will be physically aligned on its own size (rounded
+ * up to the nearest power of two).
+ */
+struct io_buffer * alloc_iob ( size_t len ) {
+
+ /* Pad to minimum length */
+ if ( len < IOB_ZLEN )
+ len = IOB_ZLEN;
+
+ /* Align buffer on its own size to avoid potential problems
+ * with boundary-crossing DMA.
+ */
+ return alloc_iob_raw ( len, len, 0 );
+}
/**
* Free I/O buffer
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/main.c
^
|
@@ -48,7 +48,9 @@
if ( BANNER_TIMEOUT <= 0 )
return 0;
- return ( prompt ( "\nPress Ctrl-B for the iPXE command line...",
+ /* Prompt user */
+ printf ( "\n" );
+ return ( prompt ( "Press Ctrl-B for the iPXE command line...",
( BANNER_TIMEOUT * 100 ), CTRL_B ) == 0 );
}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/malloc.c
^
|
@@ -220,6 +220,7 @@
*
* @v size Requested size
* @v align Physical alignment
+ * @v offset Offset from physical alignment
* @ret ptr Memory block, or NULL
*
* Allocates a memory block @b physically aligned as requested. No
@@ -227,7 +228,7 @@
*
* @c align must be a power of two. @c size may not be zero.
*/
-void * alloc_memblock ( size_t size, size_t align ) {
+void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
struct memory_block *block;
size_t align_mask;
size_t pre_size;
@@ -244,12 +245,13 @@
size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 );
align_mask = ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 );
- DBG ( "Allocating %#zx (aligned %#zx)\n", size, align );
+ DBG ( "Allocating %#zx (aligned %#zx+%zx)\n", size, align, offset );
while ( 1 ) {
/* Search through blocks for the first one with enough space */
list_for_each_entry ( block, &free_blocks, list ) {
- pre_size = ( - virt_to_phys ( block ) ) & align_mask;
- post_size = block->size - pre_size - size;
+ pre_size = ( ( offset - virt_to_phys ( block ) )
+ & align_mask );
+ post_size = ( block->size - pre_size - size );
if ( post_size >= 0 ) {
/* Split block into pre-block, block, and
* post-block. After this split, the "pre"
@@ -418,7 +420,7 @@
if ( new_size ) {
new_total_size = ( new_size +
offsetof ( struct autosized_block, data ) );
- new_block = alloc_memblock ( new_total_size, 1 );
+ 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 ) );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/nvo.c
^
|
@@ -192,8 +192,8 @@
* @v setting Setting
* @ret applies Setting applies within this settings block
*/
-static int nvo_applies ( struct settings *settings __unused,
- struct setting *setting ) {
+int nvo_applies ( struct settings *settings __unused,
+ struct setting *setting ) {
return dhcpopt_applies ( setting->tag );
}
@@ -296,7 +296,8 @@
goto err_load;
/* Register settings */
- if ( ( rc = register_settings ( &nvo->settings, parent, "nvo" ) ) != 0 )
+ if ( ( rc = register_settings ( &nvo->settings, parent,
+ NVO_SETTINGS_NAME ) ) != 0 )
goto err_register;
DBGC ( nvo, "NVO %p registered\n", nvo );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/serial.c
^
|
@@ -93,6 +93,9 @@
#define uart_writeb(val,addr) outb((val),(addr))
#endif
+/* Boolean for the state of serial driver initialization */
+int serial_initialized = 0;
+
/*
* void serial_putc(int ch);
* Write character `ch' to port UART_BASE.
@@ -207,7 +210,6 @@
/* Set clear to send, so flow control works... */
uart_writeb((1<<1), UART_BASE + UART_MCR);
-
/* Flush the input buffer. */
do {
/* rx buffer reg
@@ -217,6 +219,9 @@
/* line status reg */
status = uart_readb(UART_BASE + UART_LSR);
} while(status & UART_LSR_DR);
+
+ /* Note that serial support has been initialized */
+ serial_initialized = 1;
out:
return;
}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/serial_console.c
^
|
@@ -18,9 +18,12 @@
struct console_driver serial_console __console_driver;
static void serial_console_init ( void ) {
- /* Serial driver initialization should already be done,
- * time to enable the serial console. */
- serial_console.disabled = 0;
+ /*
+ * 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 = {
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/settings.c
^
|
@@ -180,6 +180,11 @@
if ( len > generic->data_len )
len = generic->data_len;
memcpy ( data, generic_setting_data ( generic ), len );
+
+ /* Set setting type, if not yet specified */
+ if ( ! setting->type )
+ setting->type = generic->setting.type;
+
return generic->data_len;
}
@@ -260,8 +265,8 @@
* @v name Name within this parent
* @ret settings Settings block, or NULL
*/
-static struct settings * find_child_settings ( struct settings *parent,
- const char *name ) {
+struct settings * find_child_settings ( struct settings *parent,
+ const char *name ) {
struct settings *settings;
/* Treat empty name as meaning "this block" */
@@ -614,8 +619,12 @@
if ( setting_applies ( settings, setting ) &&
( ( ret = settings->op->fetch ( settings, setting,
data, len ) ) >= 0 ) ) {
+ /* Record origin, if applicable */
if ( origin )
*origin = settings;
+ /* Default to string setting type, if not yet specified */
+ if ( ! setting->type )
+ setting->type = &setting_type_string;
return ret;
}
@@ -1043,8 +1052,8 @@
int check_len;
int rc;
- /* NULL value implies deletion */
- if ( ! value )
+ /* NULL value or empty string implies deletion */
+ if ( ( ! value ) || ( ! value[0] ) )
return delete_setting ( settings, setting );
/* Parse formatted value */
@@ -1132,6 +1141,7 @@
* @v get_child Function to find or create child settings block
* @v settings Settings block to fill in
* @v setting Setting to fill in
+ * @v default_type Default type to use, if none specified
* @v tmp_name Buffer for copy of setting name
* @ret rc Return status code
*
@@ -1147,6 +1157,7 @@
struct settings * ( * get_child ) ( struct settings *,
const char * ),
struct settings **settings, struct setting *setting,
+ struct setting_type *default_type,
char *tmp_name ) {
char *settings_name;
char *setting_name;
@@ -1157,7 +1168,7 @@
*settings = &settings_root;
memset ( setting, 0, sizeof ( *setting ) );
setting->name = "";
- setting->type = &setting_type_string;
+ setting->type = default_type;
/* Split name into "[settings_name/]setting_name[:type_name]" */
strcpy ( tmp_name, name );
@@ -1227,13 +1238,44 @@
}
/**
+ * Store value of named setting
+ *
+ * @v name Name of setting
+ * @v default_type Default type to use, if none specified
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
+ */
+int store_named_setting ( const char *name, struct setting_type *default_type,
+ const void *data, size_t len ) {
+ struct settings *settings;
+ struct setting setting;
+ char tmp_name[ strlen ( name ) + 1 ];
+ int rc;
+
+ /* Parse setting name */
+ if ( ( rc = parse_setting_name ( name, autovivify_child_settings,
+ &settings, &setting, default_type,
+ tmp_name ) ) != 0 )
+ return rc;
+
+ /* Store setting */
+ if ( ( rc = store_setting ( settings, &setting, data, len ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/**
* Parse and store value of named setting
*
* @v name Name of setting
+ * @v default_type Default type to use, if none specified
* @v value Formatted setting data, or NULL
* @ret rc Return status code
*/
-int storef_named_setting ( const char *name, const char *value ) {
+int storef_named_setting ( const char *name, struct setting_type *default_type,
+ const char *value ) {
struct settings *settings;
struct setting setting;
char tmp_name[ strlen ( name ) + 1 ];
@@ -1241,7 +1283,8 @@
/* Parse setting name */
if ( ( rc = parse_setting_name ( name, autovivify_child_settings,
- &settings, &setting, tmp_name )) != 0)
+ &settings, &setting, default_type,
+ tmp_name ) ) != 0 )
return rc;
/* Store setting */
@@ -1272,8 +1315,8 @@
int rc;
/* Parse setting name */
- if ( ( rc = parse_setting_name ( name, find_child_settings,
- &settings, &setting, tmp_name )) != 0)
+ if ( ( rc = parse_setting_name ( name, find_child_settings, &settings,
+ &setting, NULL, tmp_name ) ) != 0 )
return rc;
/* Fetch setting */
@@ -1289,6 +1332,45 @@
return len;
}
+/**
+ * Fetch and format copy of value of named setting
+ *
+ * @v name Name of setting
+ * @v data Buffer to allocate and fill with formatted value
+ * @ret len Length of formatted value, or negative error
+ *
+ * The caller is responsible for eventually freeing the allocated
+ * buffer.
+ *
+ * To allow the caller to distinguish between a non-existent setting
+ * and an error in allocating memory for the copy, this function will
+ * return success (and a NULL buffer pointer) for a non-existent
+ * setting.
+ */
+int fetchf_named_setting_copy ( const char *name, char **data ) {
+ int len;
+ int check_len;
+
+ /* Avoid returning uninitialised data on error */
+ *data = NULL;
+
+ /* Fetch formatted value length, and return success if non-existent */
+ len = fetchf_named_setting ( name, NULL, 0, NULL, 0 );
+ if ( len < 0 )
+ return 0;
+
+ /* Allocate buffer */
+ *data = malloc ( len + 1 /* NUL */ );
+ if ( ! *data )
+ return -ENOMEM;
+
+ /* Fetch formatted value */
+ check_len = fetchf_named_setting ( name, NULL, 0, *data,
+ ( len + 1 /* NUL */ ) );
+ assert ( check_len == len );
+ return len;
+}
+
/******************************************************************************
*
* Setting types
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/wchar.c
^
|
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Wide-character strings
+ *
+ */
+
+#include <wchar.h>
+
+/**
+ * Calculate length of wide-character string
+ *
+ * @v string String
+ * @ret len Length (excluding terminating NUL)
+ */
+size_t wcslen ( const wchar_t *string ) {
+ size_t len = 0;
+
+ while ( *(string++) )
+ len++;
+ return len;
+}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/crypto/cbc.c
^
|
@@ -88,13 +88,15 @@
void cbc_decrypt ( void *ctx, const void *src, void *dst, size_t len,
struct cipher_algorithm *raw_cipher, void *cbc_ctx ) {
size_t blocksize = raw_cipher->blocksize;
+ uint8_t next_cbc_ctx[blocksize];
assert ( ( len % blocksize ) == 0 );
while ( len ) {
+ memcpy ( next_cbc_ctx, src, blocksize );
cipher_decrypt ( raw_cipher, ctx, src, dst, blocksize );
cbc_xor ( cbc_ctx, dst, blocksize );
- memcpy ( cbc_ctx, src, blocksize );
+ memcpy ( cbc_ctx, next_cbc_ctx, blocksize );
dst += blocksize;
src += blocksize;
len -= blocksize;
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/bitbash/i2c_bit.c
^
|
@@ -239,6 +239,7 @@
* pull SDA low while SCL is high (which creates a start
* condition).
*/
+ open_bit ( basher );
setscl ( basher, 0 );
setsda ( basher, 1 );
for ( i = 0 ; i < I2C_RESET_MAX_CYCLES ; i++ ) {
@@ -251,6 +252,7 @@
i2c_stop ( basher );
DBGC ( basher, "I2CBIT %p reset after %d attempts\n",
basher, ( i + 1 ) );
+ close_bit ( basher );
return 0;
}
setscl ( basher, 0 );
@@ -258,6 +260,7 @@
DBGC ( basher, "I2CBIT %p could not reset after %d attempts\n",
basher, i );
+ close_bit ( basher );
return -ETIMEDOUT;
}
@@ -285,6 +288,8 @@
DBGC ( basher, "I2CBIT %p reading from device %x: ",
basher, i2cdev->dev_addr );
+ open_bit ( basher );
+
for ( ; ; data++, offset++ ) {
/* Select device for writing */
@@ -312,6 +317,7 @@
DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) );
i2c_stop ( basher );
+ close_bit ( basher );
return rc;
}
@@ -339,6 +345,8 @@
DBGC ( basher, "I2CBIT %p writing to device %x: ",
basher, i2cdev->dev_addr );
+ open_bit ( basher );
+
for ( ; ; data++, offset++ ) {
/* Select device for writing */
@@ -359,9 +367,10 @@
if ( ( rc = i2c_send_byte ( basher, *data ) ) != 0 )
break;
}
-
+
DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) );
i2c_stop ( basher );
+ close_bit ( basher );
return rc;
}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/bitbash/spi_bit.c
^
|
@@ -163,6 +163,9 @@
uint32_t tmp_address;
uint32_t tmp_address_detect;
+ /* Open bit-bashing interface */
+ open_bit ( &spibit->basher );
+
/* Deassert chip select to reset specified slave */
spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE );
@@ -214,6 +217,9 @@
/* Deassert chip select on specified slave */
spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE );
+ /* Close bit-bashing interface */
+ close_bit ( &spibit->basher );
+
return 0;
}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/infiniband/arbel.c
^
|
@@ -1250,14 +1250,14 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @v wqe Send work queue entry
* @ret nds Work queue entry size
*/
static size_t arbel_fill_ud_send_wqe ( struct ib_device *ibdev,
struct ib_queue_pair *qp __unused,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf,
union arbel_send_wqe *wqe ) {
struct arbel *arbel = ib_get_drvdata ( ibdev );
@@ -1269,16 +1269,16 @@
ud_address_vector.pd, ARBEL_GLOBAL_PD,
ud_address_vector.port_number, ibdev->port );
MLX_FILL_2 ( &wqe->ud.ud, 1,
- ud_address_vector.rlid, av->lid,
- ud_address_vector.g, av->gid_present );
+ ud_address_vector.rlid, dest->lid,
+ ud_address_vector.g, dest->gid_present );
MLX_FILL_2 ( &wqe->ud.ud, 2,
- ud_address_vector.max_stat_rate, arbel_rate ( av ),
+ ud_address_vector.max_stat_rate, arbel_rate ( dest ),
ud_address_vector.msg, 3 );
- MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, av->sl );
- gid = ( av->gid_present ? &av->gid : &arbel_no_gid );
+ MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, dest->sl );
+ gid = ( dest->gid_present ? &dest->gid : &arbel_no_gid );
memcpy ( &wqe->ud.ud.u.dwords[4], gid, sizeof ( *gid ) );
- MLX_FILL_1 ( &wqe->ud.ud, 8, destination_qp, av->qpn );
- MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, av->qkey );
+ MLX_FILL_1 ( &wqe->ud.ud, 8, destination_qp, dest->qpn );
+ MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, dest->qkey );
MLX_FILL_1 ( &wqe->ud.data[0], 0, byte_count, iob_len ( iobuf ) );
MLX_FILL_1 ( &wqe->ud.data[0], 1, l_key, arbel->lkey );
MLX_FILL_H ( &wqe->ud.data[0], 2,
@@ -1294,15 +1294,14 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @v wqe Send work queue entry
- * @v next Previous work queue entry's "next" field
* @ret nds Work queue entry size
*/
static size_t arbel_fill_mlx_send_wqe ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf,
union arbel_send_wqe *wqe ) {
struct arbel *arbel = ib_get_drvdata ( ibdev );
@@ -1312,16 +1311,16 @@
iob_populate ( &headers, &wqe->mlx.headers, 0,
sizeof ( wqe->mlx.headers ) );
iob_reserve ( &headers, sizeof ( wqe->mlx.headers ) );
- ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av );
+ ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest );
/* Construct this work queue entry */
MLX_FILL_5 ( &wqe->mlx.ctrl, 0,
c, 1 /* generate completion */,
icrc, 0 /* generate ICRC */,
- max_statrate, arbel_rate ( av ),
+ max_statrate, arbel_rate ( dest ),
slr, 0,
v15, ( ( qp->ext_qpn == IB_QPN_SMI ) ? 1 : 0 ) );
- MLX_FILL_1 ( &wqe->mlx.ctrl, 1, rlid, av->lid );
+ MLX_FILL_1 ( &wqe->mlx.ctrl, 1, rlid, dest->lid );
MLX_FILL_1 ( &wqe->mlx.data[0], 0,
byte_count, iob_len ( &headers ) );
MLX_FILL_1 ( &wqe->mlx.data[0], 1, l_key, arbel->lkey );
@@ -1345,15 +1344,14 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @v wqe Send work queue entry
- * @v next Previous work queue entry's "next" field
* @ret nds Work queue entry size
*/
static size_t arbel_fill_rc_send_wqe ( struct ib_device *ibdev,
struct ib_queue_pair *qp __unused,
- struct ib_address_vector *av __unused,
+ struct ib_address_vector *dest __unused,
struct io_buffer *iobuf,
union arbel_send_wqe *wqe ) {
struct arbel *arbel = ib_get_drvdata ( ibdev );
@@ -1374,7 +1372,7 @@
static size_t
( * arbel_fill_send_wqe[] ) ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf,
union arbel_send_wqe *wqe ) = {
[IB_QPT_SMI] = arbel_fill_mlx_send_wqe,
@@ -1388,13 +1386,13 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @ret rc Return status code
*/
static int arbel_post_send ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf ) {
struct arbel *arbel = ib_get_drvdata ( ibdev );
struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp );
@@ -1424,7 +1422,7 @@
assert ( qp->type < ( sizeof ( arbel_fill_send_wqe ) /
sizeof ( arbel_fill_send_wqe[0] ) ) );
assert ( arbel_fill_send_wqe[qp->type] != NULL );
- nds = arbel_fill_send_wqe[qp->type] ( ibdev, qp, av, iobuf, wqe );
+ nds = arbel_fill_send_wqe[qp->type] ( ibdev, qp, dest, iobuf, wqe );
DBGCP ( arbel, "Arbel %p QPN %#lx posting send WQE %#lx:\n",
arbel, qp->qpn, ( wq->next_idx & wqe_idx_mask ) );
DBGCP_HDA ( arbel, virt_to_phys ( wqe ), wqe, sizeof ( *wqe ) );
@@ -1527,9 +1525,10 @@
struct arbel_recv_work_queue *arbel_recv_wq;
struct arbelprm_recv_wqe *recv_wqe;
struct io_buffer *iobuf;
- struct ib_address_vector recv_av;
+ struct ib_address_vector recv_dest;
+ struct ib_address_vector recv_source;
struct ib_global_route_header *grh;
- struct ib_address_vector *av;
+ struct ib_address_vector *source;
unsigned int opcode;
unsigned long qpn;
int is_send;
@@ -1610,6 +1609,8 @@
l_key, ARBEL_INVALID_LKEY );
assert ( len <= iob_tailroom ( iobuf ) );
iob_put ( iobuf, len );
+ memset ( &recv_dest, 0, sizeof ( recv_dest ) );
+ recv_dest.qpn = qpn;
switch ( qp->type ) {
case IB_QPT_SMI:
case IB_QPT_GSI:
@@ -1618,23 +1619,27 @@
grh = iobuf->data;
iob_pull ( iobuf, sizeof ( *grh ) );
/* Construct address vector */
- av = &recv_av;
- memset ( av, 0, sizeof ( *av ) );
- av->qpn = MLX_GET ( &cqe->normal, rqpn );
- av->lid = MLX_GET ( &cqe->normal, rlid );
- av->sl = MLX_GET ( &cqe->normal, sl );
- av->gid_present = MLX_GET ( &cqe->normal, g );
- memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) );
+ source = &recv_source;
+ memset ( source, 0, sizeof ( *source ) );
+ source->qpn = MLX_GET ( &cqe->normal, rqpn );
+ source->lid = MLX_GET ( &cqe->normal, rlid );
+ source->sl = MLX_GET ( &cqe->normal, sl );
+ recv_dest.gid_present = source->gid_present =
+ MLX_GET ( &cqe->normal, g );
+ memcpy ( &recv_dest.gid, &grh->dgid,
+ sizeof ( recv_dest.gid ) );
+ memcpy ( &source->gid, &grh->sgid,
+ sizeof ( source->gid ) );
break;
case IB_QPT_RC:
- av = &qp->av;
+ source = &qp->av;
break;
default:
assert ( 0 );
return -EINVAL;
}
/* Hand off to completion handler */
- ib_complete_recv ( ibdev, qp, av, iobuf, rc );
+ ib_complete_recv ( ibdev, qp, &recv_dest, source, iobuf, rc );
}
return rc;
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/infiniband/hermon.c
^
|
@@ -42,6 +42,8 @@
#include <ipxe/fcoe.h>
#include <ipxe/vlan.h>
#include <ipxe/bofm.h>
+#include <ipxe/nvsvpd.h>
+#include <ipxe/nvo.h>
#include "hermon.h"
/**
@@ -1364,7 +1366,7 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @v wqe Send work queue entry
* @ret opcode Control opcode
@@ -1372,7 +1374,7 @@
static __attribute__ (( unused )) unsigned int
hermon_fill_nop_send_wqe ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp __unused,
- struct ib_address_vector *av __unused,
+ struct ib_address_vector *dest __unused,
struct io_buffer *iobuf __unused,
union hermon_send_wqe *wqe ) {
@@ -1386,7 +1388,7 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @v wqe Send work queue entry
* @ret opcode Control opcode
@@ -1394,7 +1396,7 @@
static unsigned int
hermon_fill_ud_send_wqe ( struct ib_device *ibdev,
struct ib_queue_pair *qp __unused,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf,
union hermon_send_wqe *wqe ) {
struct hermon *hermon = ib_get_drvdata ( ibdev );
@@ -1406,14 +1408,14 @@
ud_address_vector.pd, HERMON_GLOBAL_PD,
ud_address_vector.port_number, ibdev->port );
MLX_FILL_2 ( &wqe->ud.ud, 1,
- ud_address_vector.rlid, av->lid,
- ud_address_vector.g, av->gid_present );
+ ud_address_vector.rlid, dest->lid,
+ ud_address_vector.g, dest->gid_present );
MLX_FILL_1 ( &wqe->ud.ud, 2,
- ud_address_vector.max_stat_rate, hermon_rate ( av ) );
- MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, av->sl );
- memcpy ( &wqe->ud.ud.u.dwords[4], &av->gid, sizeof ( av->gid ) );
- MLX_FILL_1 ( &wqe->ud.ud, 8, destination_qp, av->qpn );
- MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, av->qkey );
+ ud_address_vector.max_stat_rate, hermon_rate ( dest ) );
+ MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, dest->sl );
+ memcpy ( &wqe->ud.ud.u.dwords[4], &dest->gid, sizeof ( dest->gid ) );
+ MLX_FILL_1 ( &wqe->ud.ud, 8, destination_qp, dest->qpn );
+ MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, dest->qkey );
MLX_FILL_1 ( &wqe->ud.data[0], 0, byte_count, iob_len ( iobuf ) );
MLX_FILL_1 ( &wqe->ud.data[0], 1, l_key, hermon->lkey );
MLX_FILL_H ( &wqe->ud.data[0], 2,
@@ -1428,7 +1430,7 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @v wqe Send work queue entry
* @ret opcode Control opcode
@@ -1436,7 +1438,7 @@
static unsigned int
hermon_fill_mlx_send_wqe ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf,
union hermon_send_wqe *wqe ) {
struct hermon *hermon = ib_get_drvdata ( ibdev );
@@ -1446,7 +1448,7 @@
iob_populate ( &headers, &wqe->mlx.headers, 0,
sizeof ( wqe->mlx.headers ) );
iob_reserve ( &headers, sizeof ( wqe->mlx.headers ) );
- ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av );
+ ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest );
/* Fill work queue entry */
MLX_FILL_1 ( &wqe->mlx.ctrl, 1, ds,
@@ -1454,10 +1456,10 @@
MLX_FILL_5 ( &wqe->mlx.ctrl, 2,
c, 0x03 /* generate completion */,
icrc, 0 /* generate ICRC */,
- max_statrate, hermon_rate ( av ),
+ max_statrate, hermon_rate ( dest ),
slr, 0,
v15, ( ( qp->ext_qpn == IB_QPN_SMI ) ? 1 : 0 ) );
- MLX_FILL_1 ( &wqe->mlx.ctrl, 3, rlid, av->lid );
+ MLX_FILL_1 ( &wqe->mlx.ctrl, 3, rlid, dest->lid );
MLX_FILL_1 ( &wqe->mlx.data[0], 0,
byte_count, iob_len ( &headers ) );
MLX_FILL_1 ( &wqe->mlx.data[0], 1, l_key, hermon->lkey );
@@ -1480,7 +1482,7 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @v wqe Send work queue entry
* @ret opcode Control opcode
@@ -1488,7 +1490,7 @@
static unsigned int
hermon_fill_rc_send_wqe ( struct ib_device *ibdev,
struct ib_queue_pair *qp __unused,
- struct ib_address_vector *av __unused,
+ struct ib_address_vector *dest __unused,
struct io_buffer *iobuf,
union hermon_send_wqe *wqe ) {
struct hermon *hermon = ib_get_drvdata ( ibdev );
@@ -1510,7 +1512,7 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @v wqe Send work queue entry
* @ret opcode Control opcode
@@ -1518,7 +1520,7 @@
static unsigned int
hermon_fill_eth_send_wqe ( struct ib_device *ibdev,
struct ib_queue_pair *qp __unused,
- struct ib_address_vector *av __unused,
+ struct ib_address_vector *dest __unused,
struct io_buffer *iobuf,
union hermon_send_wqe *wqe ) {
struct hermon *hermon = ib_get_drvdata ( ibdev );
@@ -1543,7 +1545,7 @@
static unsigned int
( * hermon_fill_send_wqe[] ) ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf,
union hermon_send_wqe *wqe ) = {
[IB_QPT_SMI] = hermon_fill_mlx_send_wqe,
@@ -1558,13 +1560,13 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @ret rc Return status code
*/
static int hermon_post_send ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf ) {
struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp );
@@ -1595,7 +1597,7 @@
assert ( qp->type < ( sizeof ( hermon_fill_send_wqe ) /
sizeof ( hermon_fill_send_wqe[0] ) ) );
assert ( hermon_fill_send_wqe[qp->type] != NULL );
- opcode = hermon_fill_send_wqe[qp->type] ( ibdev, qp, av, iobuf, wqe );
+ opcode = hermon_fill_send_wqe[qp->type] ( ibdev, qp, dest, iobuf, wqe );
barrier();
MLX_FILL_2 ( &wqe->ctrl, 0,
opcode, opcode,
@@ -1677,9 +1679,10 @@
struct ib_work_queue *wq;
struct ib_queue_pair *qp;
struct io_buffer *iobuf;
- struct ib_address_vector recv_av;
+ struct ib_address_vector recv_dest;
+ struct ib_address_vector recv_source;
struct ib_global_route_header *grh;
- struct ib_address_vector *av;
+ struct ib_address_vector *source;
unsigned int opcode;
unsigned long qpn;
int is_send;
@@ -1737,7 +1740,9 @@
len = MLX_GET ( &cqe->normal, byte_cnt );
assert ( len <= iob_tailroom ( iobuf ) );
iob_put ( iobuf, len );
- memset ( &recv_av, 0, sizeof ( recv_av ) );
+ memset ( &recv_dest, 0, sizeof ( recv_dest ) );
+ recv_dest.qpn = qpn;
+ memset ( &recv_source, 0, sizeof ( recv_source ) );
switch ( qp->type ) {
case IB_QPT_SMI:
case IB_QPT_GSI:
@@ -1746,28 +1751,32 @@
grh = iobuf->data;
iob_pull ( iobuf, sizeof ( *grh ) );
/* Construct address vector */
- av = &recv_av;
- av->qpn = MLX_GET ( &cqe->normal, srq_rqpn );
- av->lid = MLX_GET ( &cqe->normal, slid_smac47_32 );
- av->sl = MLX_GET ( &cqe->normal, sl );
- av->gid_present = MLX_GET ( &cqe->normal, g );
- memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) );
+ source = &recv_source;
+ source->qpn = MLX_GET ( &cqe->normal, srq_rqpn );
+ source->lid = MLX_GET ( &cqe->normal, slid_smac47_32 );
+ source->sl = MLX_GET ( &cqe->normal, sl );
+ recv_dest.gid_present = source->gid_present =
+ MLX_GET ( &cqe->normal, g );
+ memcpy ( &recv_dest.gid, &grh->dgid,
+ sizeof ( recv_dest.gid ) );
+ memcpy ( &source->gid, &grh->sgid,
+ sizeof ( source->gid ) );
break;
case IB_QPT_RC:
- av = &qp->av;
+ source = &qp->av;
break;
case IB_QPT_ETH:
/* Construct address vector */
- av = &recv_av;
- av->vlan_present = MLX_GET ( &cqe->normal, vlan );
- av->vlan = MLX_GET ( &cqe->normal, vid );
+ source = &recv_source;
+ source->vlan_present = MLX_GET ( &cqe->normal, vlan );
+ source->vlan = MLX_GET ( &cqe->normal, vid );
break;
default:
assert ( 0 );
return -EINVAL;
}
/* Hand off to completion handler */
- ib_complete_recv ( ibdev, qp, av, iobuf, rc );
+ ib_complete_recv ( ibdev, qp, &recv_dest, source, iobuf, rc );
}
return rc;
@@ -3128,6 +3137,11 @@
return 0;
}
+/** Hermon Ethernet queue pair operations */
+static struct ib_queue_pair_operations hermon_eth_qp_op = {
+ .alloc_iob = alloc_iob,
+};
+
/**
* Handle Hermon Ethernet device send completion
*
@@ -3149,20 +3163,22 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector, or NULL
+ * @v dest Destination address vector, or NULL
+ * @v source Source address vector, or NULL
* @v iobuf I/O buffer
* @v rc Completion status code
*/
static void hermon_eth_complete_recv ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest __unused,
+ struct ib_address_vector *source,
struct io_buffer *iobuf, int rc ) {
struct net_device *netdev = ib_qp_get_ownerdata ( qp );
struct net_device *vlan;
/* Find VLAN device, if applicable */
- if ( av->vlan_present ) {
- if ( ( vlan = vlan_find ( netdev, av->vlan ) ) != NULL ) {
+ if ( source->vlan_present ) {
+ if ( ( vlan = vlan_find ( netdev, source->vlan ) ) != NULL ) {
netdev = vlan;
} else if ( rc == 0 ) {
rc = -ENODEV;
@@ -3225,7 +3241,8 @@
/* Allocate queue pair */
port->eth_qp = ib_create_qp ( ibdev, IB_QPT_ETH,
HERMON_ETH_NUM_SEND_WQES, port->eth_cq,
- HERMON_ETH_NUM_RECV_WQES, port->eth_cq );
+ HERMON_ETH_NUM_RECV_WQES, port->eth_cq,
+ &hermon_eth_qp_op );
if ( ! port->eth_qp ) {
DBGC ( hermon, "Hermon %p port %d could not create queue "
"pair\n", hermon, ibdev->port );
@@ -3368,7 +3385,7 @@
&query_port ) ) != 0 ) {
DBGC ( hermon, "Hermon %p port %d could not query port: %s\n",
hermon, ibdev->port, strerror ( rc ) );
- return rc;
+ goto err_query_port;
}
mac.dwords[0] = htonl ( MLX_GET ( &query_port, mac_47_32 ) );
mac.dwords[1] = htonl ( MLX_GET ( &query_port, mac_31_0 ) );
@@ -3379,10 +3396,26 @@
if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
DBGC ( hermon, "Hermon %p port %d could not register network "
"device: %s\n", hermon, ibdev->port, strerror ( rc ) );
- return rc;
+ goto err_register_netdev;
+ }
+
+ /* Register non-volatile options */
+ if ( ( rc = register_nvo ( &port->nvo,
+ netdev_settings ( netdev ) ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p port %d could not register non-"
+ "volatile options: %s\n",
+ hermon, ibdev->port, strerror ( rc ) );
+ goto err_register_nvo;
}
return 0;
+
+ unregister_nvo ( &port->nvo );
+ err_register_nvo:
+ unregister_netdev ( netdev );
+ err_register_netdev:
+ err_query_port:
+ return rc;
}
/**
@@ -3414,6 +3447,7 @@
struct hermon_port *port ) {
struct net_device *netdev = port->netdev;
+ unregister_nvo ( &port->nvo );
unregister_netdev ( netdev );
}
@@ -3807,6 +3841,15 @@
goto err_set_port_type;
}
+ /* Initialise non-volatile storage */
+ nvs_vpd_init ( &hermon->nvsvpd, pci );
+ for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
+ port = &hermon->port[i];
+ nvs_vpd_nvo_init ( &hermon->nvsvpd,
+ HERMON_VPD_FIELD ( port->ibdev->port ),
+ &port->nvo, NULL );
+ }
+
/* Register devices */
for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
port = &hermon->port[i];
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/infiniband/hermon.h
^
|
@@ -13,6 +13,8 @@
#include <ipxe/uaccess.h>
#include <ipxe/ib_packet.h>
#include <ipxe/bofm.h>
+#include <ipxe/nvsvpd.h>
+#include <ipxe/nvo.h>
#include "mlx_bitops.h"
#include "MT25408_PRM.h"
@@ -135,6 +137,9 @@
#define HERMON_MOD_STAT_CFG_SET 0x01
#define HERMON_MOD_STAT_CFG_QUERY 0x03
+#define HERMON_VPD_FIELD( port ) \
+ PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'V', ( '5' + (port) - 1 ) )
+
/*
* Datatypes that seem to be missing from the autogenerated documentation
*
@@ -825,6 +830,8 @@
struct ib_queue_pair *eth_qp;
/** Port type */
struct hermon_port_type *type;
+ /** Non-volatile option storage */
+ struct nvo_block nvo;
};
/** A Hermon device */
@@ -891,6 +898,9 @@
/** QPN base */
unsigned long qpn_base;
+ /** Non-volatile storage in PCI VPD */
+ struct nvs_vpd_device nvsvpd;
+
/** Ports */
struct hermon_port port[HERMON_MAX_PORTS];
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/infiniband/linda.c
^
|
@@ -936,13 +936,13 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @ret rc Return status code
*/
static int linda_post_send ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf ) {
struct linda *linda = ib_get_drvdata ( ibdev );
struct ib_work_queue *wq = &qp->send;
@@ -969,7 +969,7 @@
/* Construct headers */
iob_populate ( &headers, header_buf, 0, sizeof ( header_buf ) );
iob_reserve ( &headers, sizeof ( header_buf ) );
- ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av );
+ ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest );
/* Calculate packet length */
len = ( ( sizeof ( sendpbc ) + iob_len ( &headers ) +
@@ -1170,7 +1170,8 @@
struct io_buffer headers;
struct io_buffer *iobuf;
struct ib_queue_pair *intended_qp;
- struct ib_address_vector av;
+ struct ib_address_vector dest;
+ struct ib_address_vector source;
unsigned int rcvtype;
unsigned int pktlen;
unsigned int egrindex;
@@ -1238,7 +1239,7 @@
qp0 = ( qp->qpn == 0 );
intended_qp = NULL;
if ( ( rc = ib_pull ( ibdev, &headers, ( qp0 ? &intended_qp : NULL ),
- &payload_len, &av ) ) != 0 ) {
+ &payload_len, &dest, &source ) ) != 0 ) {
DBGC ( linda, "Linda %p could not parse headers: %s\n",
linda, strerror ( rc ) );
err = 1;
@@ -1295,10 +1296,12 @@
qp->recv.fill--;
intended_qp->recv.fill++;
}
- ib_complete_recv ( ibdev, intended_qp, &av, iobuf, rc);
+ ib_complete_recv ( ibdev, intended_qp, &dest, &source,
+ iobuf, rc);
} else {
/* Completing on a skipped-over eager buffer */
- ib_complete_recv ( ibdev, qp, &av, iobuf, -ECANCELED );
+ ib_complete_recv ( ibdev, qp, &dest, &source, iobuf,
+ -ECANCELED );
}
/* Clear eager buffer */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/infiniband/qib7322.c
^
|
@@ -1173,13 +1173,13 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @ret rc Return status code
*/
static int qib7322_post_send ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf ) {
struct qib7322 *qib7322 = ib_get_drvdata ( ibdev );
struct ib_work_queue *wq = &qp->send;
@@ -1211,7 +1211,7 @@
/* Construct headers */
iob_populate ( &headers, header_buf, 0, sizeof ( header_buf ) );
iob_reserve ( &headers, sizeof ( header_buf ) );
- ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av );
+ ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest );
/* Calculate packet length */
len = ( ( sizeof ( sendpbc ) + iob_len ( &headers ) +
@@ -1413,7 +1413,8 @@
struct io_buffer headers;
struct io_buffer *iobuf;
struct ib_queue_pair *intended_qp;
- struct ib_address_vector av;
+ struct ib_address_vector dest;
+ struct ib_address_vector source;
unsigned int rcvtype;
unsigned int pktlen;
unsigned int egrindex;
@@ -1474,7 +1475,7 @@
qp0 = ( qp->qpn == 0 );
intended_qp = NULL;
if ( ( rc = ib_pull ( ibdev, &headers, ( qp0 ? &intended_qp : NULL ),
- &payload_len, &av ) ) != 0 ) {
+ &payload_len, &dest, &source ) ) != 0 ) {
DBGC ( qib7322, "QIB7322 %p could not parse headers: %s\n",
qib7322, strerror ( rc ) );
err = 1;
@@ -1531,10 +1532,12 @@
qp->recv.fill--;
intended_qp->recv.fill++;
}
- ib_complete_recv ( ibdev, intended_qp, &av, iobuf, rc);
+ ib_complete_recv ( ibdev, intended_qp, &dest, &source,
+ iobuf, rc);
} else {
/* Completing on a skipped-over eager buffer */
- ib_complete_recv ( ibdev, qp, &av, iobuf, -ECANCELED );
+ ib_complete_recv ( ibdev, qp, &dest, &source, iobuf,
+ -ECANCELED );
}
/* Clear eager buffer */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/net/forcedeth.h
^
|
@@ -55,7 +55,7 @@
#define DESC_VER_3 3
#define RX_RING_SIZE 16
-#define TX_RING_SIZE 16
+#define TX_RING_SIZE 32
#define RXTX_RING_SIZE ( ( RX_RING_SIZE ) + ( TX_RING_SIZE ) )
#define RX_RING_MIN 128
#define TX_RING_MIN 64
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/net/intel.c
^
|
@@ -699,10 +699,14 @@
if ( icr & INTEL_IRQ_TXDW )
intel_poll_tx ( netdev );
- /* Poll for RX completionsm, if applicable */
- if ( icr & INTEL_IRQ_RXT0 )
+ /* Poll for RX completions, if applicable */
+ if ( icr & ( INTEL_IRQ_RXT0 | INTEL_IRQ_RXO ) )
intel_poll_rx ( netdev );
+ /* Report receive overruns */
+ if ( icr & INTEL_IRQ_RXO )
+ netdev_rx_err ( netdev, NULL, -ENOBUFS );
+
/* Check link state, if applicable */
if ( icr & INTEL_IRQ_LSC )
intel_check_link ( netdev );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/net/intel.h
^
|
@@ -93,6 +93,7 @@
#define INTEL_IRQ_TXDW 0x00000001UL /**< Transmit descriptor done */
#define INTEL_IRQ_LSC 0x00000004UL /**< Link status change */
#define INTEL_IRQ_RXT0 0x00000080UL /**< Receive timer */
+#define INTEL_IRQ_RXO 0x00000400UL /**< Receive overrun */
/** Interrupt Mask Set/Read Register */
#define INTEL_IMS 0x000d0UL
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/net/ipoib.c
^
|
@@ -20,18 +20,23 @@
FILE_LICENCE ( GPL2_OR_LATER );
#include <stdint.h>
+#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <byteswap.h>
#include <errno.h>
#include <ipxe/errortab.h>
+#include <ipxe/malloc.h>
#include <ipxe/if_arp.h>
+#include <ipxe/if_ether.h>
+#include <ipxe/ethernet.h>
#include <ipxe/iobuf.h>
#include <ipxe/netdevice.h>
#include <ipxe/infiniband.h>
#include <ipxe/ib_pathrec.h>
#include <ipxe/ib_mcast.h>
+#include <ipxe/retry.h>
#include <ipxe/ipoib.h>
/** @file
@@ -58,6 +63,8 @@
struct ib_completion_queue *cq;
/** Queue pair */
struct ib_queue_pair *qp;
+ /** Local MAC */
+ struct ipoib_mac mac;
/** Broadcast MAC */
struct ipoib_mac broadcast;
/** Joined to IPv4 broadcast multicast group
@@ -68,6 +75,8 @@
int broadcast_joined;
/** IPv4 broadcast multicast group membership */
struct ib_mc_membership broadcast_membership;
+ /** REMAC cache */
+ struct list_head peers;
};
/** Broadcast IPoIB address */
@@ -89,184 +98,140 @@
/****************************************************************************
*
- * IPoIB peer cache
+ * IPoIB REMAC cache
*
****************************************************************************
*/
-/**
- * IPoIB peer address
- *
- * The IPoIB link-layer header is only four bytes long and so does not
- * have sufficient room to store IPoIB MAC address(es). We therefore
- * maintain a cache of MAC addresses identified by a single-byte key,
- * and abuse the spare two bytes within the link-layer header to
- * communicate these MAC addresses between the link-layer code and the
- * netdevice driver.
- */
+/** An IPoIB REMAC cache entry */
struct ipoib_peer {
- /** Key */
- uint8_t key;
+ /** List of REMAC cache entries */
+ struct list_head list;
+ /** Remote Ethermet MAC */
+ struct ipoib_remac remac;
/** MAC address */
struct ipoib_mac mac;
};
-/** Number of IPoIB peer cache entries
- *
- * Must be a power of two.
- */
-#define IPOIB_NUM_CACHED_PEERS 4
-
-/** IPoIB peer address cache */
-static struct ipoib_peer ipoib_peer_cache[IPOIB_NUM_CACHED_PEERS];
-
-/** Oldest IPoIB peer cache entry index */
-static unsigned int ipoib_peer_cache_idx = 0;
-
-/** IPoIB peer cache entry validity flag */
-#define IPOIB_PEER_KEY_VALID 0x80
-
/**
- * Look up cached peer by key
+ * Find IPoIB MAC from REMAC
*
- * @v key Peer cache key
- * @ret peer Peer cache entry, or NULL
+ * @v ipoib IPoIB device
+ * @v remac Remote Ethernet MAC
+ * @ret mac IPoIB MAC (or NULL if not found)
*/
-static struct ipoib_peer * ipoib_lookup_peer_by_key ( unsigned int key ) {
+static struct ipoib_mac * ipoib_find_remac ( struct ipoib_device *ipoib,
+ const struct ipoib_remac *remac ) {
struct ipoib_peer *peer;
- unsigned int i;
-
- if ( ! key )
- return NULL;
- for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) {
- peer = &ipoib_peer_cache[i];
- if ( peer->key == key )
- return peer;
+ /* Check for broadcast REMAC */
+ if ( is_broadcast_ether_addr ( remac ) )
+ return &ipoib->broadcast;
+
+ /* Try to find via REMAC cache */
+ list_for_each_entry ( peer, &ipoib->peers, list ) {
+ if ( memcmp ( remac, &peer->remac,
+ sizeof ( peer->remac ) ) == 0 ) {
+ /* Move peer to start of list */
+ list_del ( &peer->list );
+ list_add ( &peer->list, &ipoib->peers );
+ return &peer->mac;
+ }
}
- DBG ( "IPoIB warning: peer cache lost track of key %x while still in "
- "use\n", key );
+ DBGC ( ipoib, "IPoIB %p unknown REMAC %s\n",
+ ipoib, eth_ntoa ( remac ) );
return NULL;
}
/**
- * Store GID and QPN in peer cache
+ * Add IPoIB MAC to REMAC cache
*
- * @v mac Peer MAC address
- * @ret peer Peer cache entry
+ * @v ipoib IPoIB device
+ * @v remac Remote Ethernet MAC
+ * @v mac IPoIB MAC
+ * @ret rc Return status code
*/
-static struct ipoib_peer * ipoib_cache_peer ( const struct ipoib_mac *mac ) {
+static int ipoib_map_remac ( struct ipoib_device *ipoib,
+ const struct ipoib_remac *remac,
+ const struct ipoib_mac *mac ) {
struct ipoib_peer *peer;
- uint8_t key;
- unsigned int i;
- /* Look for existing cache entry */
- for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) {
- peer = &ipoib_peer_cache[i];
- if ( memcmp ( &peer->mac, mac, sizeof ( peer->mac ) ) == 0 )
- return peer;
+ /* Check for existing entry in REMAC cache */
+ list_for_each_entry ( peer, &ipoib->peers, list ) {
+ if ( memcmp ( remac, &peer->remac,
+ sizeof ( peer->remac ) ) == 0 ) {
+ /* Move peer to start of list */
+ list_del ( &peer->list );
+ list_add ( &peer->list, &ipoib->peers );
+ /* Update MAC */
+ memcpy ( &peer->mac, mac, sizeof ( peer->mac ) );
+ return 0;
+ }
}
- /* No entry found: create a new one */
- key = ( ipoib_peer_cache_idx++ | IPOIB_PEER_KEY_VALID );
- peer = &ipoib_peer_cache[ key % IPOIB_NUM_CACHED_PEERS ];
- if ( peer->key )
- DBG ( "IPoIB peer %x evicted from cache\n", peer->key );
-
- memset ( peer, 0, sizeof ( *peer ) );
- peer->key = key;
+ /* Create new entry */
+ peer = malloc ( sizeof ( *peer ) );
+ if ( ! peer )
+ return -ENOMEM;
+ memcpy ( &peer->remac, remac, sizeof ( peer->remac ) );
memcpy ( &peer->mac, mac, sizeof ( peer->mac ) );
- DBG ( "IPoIB peer %x has MAC %s\n",
- peer->key, ipoib_ntoa ( &peer->mac ) );
- return peer;
-}
+ list_add ( &peer->list, &ipoib->peers );
-/****************************************************************************
- *
- * IPoIB link layer
- *
- ****************************************************************************
- */
+ return 0;
+}
/**
- * Add IPoIB link-layer header
+ * Flush REMAC cache
*
- * @v netdev Network device
- * @v iobuf I/O buffer
- * @v ll_dest Link-layer destination address
- * @v ll_source Source link-layer address
- * @v net_proto Network-layer protocol, in network-byte order
- * @ret rc Return status code
+ * @v ipoib IPoIB device
*/
-static int ipoib_push ( struct net_device *netdev __unused,
- struct io_buffer *iobuf, const void *ll_dest,
- const void *ll_source __unused, uint16_t net_proto ) {
- struct ipoib_hdr *ipoib_hdr =
- iob_push ( iobuf, sizeof ( *ipoib_hdr ) );
- const struct ipoib_mac *dest_mac = ll_dest;
- const struct ipoib_mac *src_mac = ll_source;
- struct ipoib_peer *dest;
- struct ipoib_peer *src;
-
- /* Add link-layer addresses to cache */
- dest = ipoib_cache_peer ( dest_mac );
- src = ipoib_cache_peer ( src_mac );
-
- /* Build IPoIB header */
- ipoib_hdr->proto = net_proto;
- ipoib_hdr->u.peer.dest = dest->key;
- ipoib_hdr->u.peer.src = src->key;
+static void ipoib_flush_remac ( struct ipoib_device *ipoib ) {
+ struct ipoib_peer *peer;
+ struct ipoib_peer *tmp;
- return 0;
+ list_for_each_entry_safe ( peer, tmp, &ipoib->peers, list ) {
+ list_del ( &peer->list );
+ free ( peer );
+ }
}
/**
- * Remove IPoIB link-layer header
+ * Discard some entries from the REMAC cache
*
- * @v netdev Network device
- * @v iobuf I/O buffer
- * @ret ll_dest Link-layer destination address
- * @ret ll_source Source link-layer address
- * @ret net_proto Network-layer protocol, in network-byte order
- * @ret flags Packet flags
- * @ret rc Return status code
+ * @ret discarded Number of cached items discarded
*/
-static int ipoib_pull ( struct net_device *netdev,
- struct io_buffer *iobuf, const void **ll_dest,
- const void **ll_source, uint16_t *net_proto,
- unsigned int *flags ) {
- struct ipoib_device *ipoib = netdev->priv;
- struct ipoib_hdr *ipoib_hdr = iobuf->data;
- struct ipoib_peer *dest;
- struct ipoib_peer *source;
+static unsigned int ipoib_discard_remac ( void ) {
+ struct ib_device *ibdev;
+ struct ipoib_device *ipoib;
+ struct ipoib_peer *peer;
+ unsigned int discarded = 0;
- /* Sanity check */
- if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
- DBG ( "IPoIB packet too short for link-layer header\n" );
- DBG_HD ( iobuf->data, iob_len ( iobuf ) );
- return -EINVAL;
+ /* Try to discard one cache entry for each IPoIB device */
+ for_each_ibdev ( ibdev ) {
+ ipoib = ib_get_ownerdata ( ibdev );
+ list_for_each_entry_reverse ( peer, &ipoib->peers, list ) {
+ list_del ( &peer->list );
+ free ( peer );
+ discarded++;
+ break;
+ }
}
- /* Strip off IPoIB header */
- iob_pull ( iobuf, sizeof ( *ipoib_hdr ) );
+ return discarded;
+}
- /* Identify source and destination addresses, and clear
- * reserved word in IPoIB header
- */
- dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest );
- source = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.src );
- ipoib_hdr->u.reserved = 0;
-
- /* Fill in required fields */
- *ll_dest = ( dest ? &dest->mac : &ipoib->broadcast );
- *ll_source = ( source ? &source->mac : &ipoib->broadcast );
- *net_proto = ipoib_hdr->proto;
- *flags = ( ( *ll_dest == &ipoib->broadcast ) ?
- ( LL_MULTICAST | LL_BROADCAST ) : 0 );
+/** IPoIB cache discarder */
+struct cache_discarder ipoib_discarder __cache_discarder ( CACHE_NORMAL ) = {
+ .discard = ipoib_discard_remac,
+};
- return 0;
-}
+/****************************************************************************
+ *
+ * IPoIB link layer
+ *
+ ****************************************************************************
+ */
/**
* Initialise IPoIB link-layer address
@@ -275,133 +240,205 @@
* @v ll_addr Link-layer address
*/
static void ipoib_init_addr ( const void *hw_addr, void *ll_addr ) {
- const union ib_guid *guid = hw_addr;
- struct ipoib_mac *mac = ll_addr;
+ const uint8_t *guid = hw_addr;
+ uint8_t *eth_addr = ll_addr;
+ uint8_t guid_mask = IPOIB_GUID_MASK;
+ unsigned int i;
- memset ( mac, 0, sizeof ( *mac ) );
- memcpy ( &mac->gid.s.guid, guid, sizeof ( mac->gid.s.guid ) );
+ /* Extract bytes from GUID according to mask */
+ for ( i = 0 ; i < 8 ; i++, guid++, guid_mask <<= 1 ) {
+ if ( guid_mask & 0x80 )
+ *(eth_addr++) = *guid;
+ }
}
+/** IPoIB protocol */
+struct ll_protocol ipoib_protocol __ll_protocol = {
+ .name = "IPoIB",
+ .ll_proto = htons ( ARPHRD_ETHER ),
+ .hw_addr_len = sizeof ( union ib_guid ),
+ .ll_addr_len = ETH_ALEN,
+ .ll_header_len = ETH_HLEN,
+ .push = eth_push,
+ .pull = eth_pull,
+ .init_addr = ipoib_init_addr,
+ .ntoa = eth_ntoa,
+ .mc_hash = eth_mc_hash,
+ .eth_addr = eth_eth_addr,
+ .flags = LL_NAME_ONLY,
+};
+
/**
- * Transcribe IPoIB link-layer address
+ * Allocate IPoIB device
*
- * @v ll_addr Link-layer address
- * @ret string Link-layer address in human-readable format
+ * @v priv_size Size of driver private data
+ * @ret netdev Network device, or NULL
*/
-const char * ipoib_ntoa ( const void *ll_addr ) {
- static char buf[45];
- const struct ipoib_mac *mac = ll_addr;
+struct net_device * alloc_ipoibdev ( size_t priv_size ) {
+ struct net_device *netdev;
- snprintf ( buf, sizeof ( buf ), "%08x:%08x:%08x:%08x:%08x",
- htonl ( mac->flags__qpn ), htonl ( mac->gid.dwords[0] ),
- htonl ( mac->gid.dwords[1] ),
- htonl ( mac->gid.dwords[2] ),
- htonl ( mac->gid.dwords[3] ) );
- return buf;
+ netdev = alloc_netdev ( priv_size );
+ if ( netdev ) {
+ netdev->ll_protocol = &ipoib_protocol;
+ netdev->ll_broadcast = eth_broadcast;
+ netdev->max_pkt_len = IB_MAX_PAYLOAD_SIZE;
+ }
+ return netdev;
}
+/****************************************************************************
+ *
+ * IPoIB translation layer
+ *
+ ****************************************************************************
+ */
+
/**
- * Hash multicast address
+ * Translate transmitted ARP packet
*
- * @v af Address family
- * @v net_addr Network-layer address
- * @v ll_addr Link-layer address to fill in
+ * @v netdev Network device
+ * @v iobuf Packet to be transmitted (with no link-layer headers)
* @ret rc Return status code
*/
-static int ipoib_mc_hash ( unsigned int af __unused,
- const void *net_addr __unused,
- void *ll_addr __unused ) {
+static int ipoib_translate_tx_arp ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct ipoib_device *ipoib = netdev->priv;
+ struct arphdr *arphdr = iobuf->data;
+ struct ipoib_mac *target_ha = NULL;
+ void *sender_pa;
+ void *target_pa;
+
+ /* Do nothing unless ARP contains eIPoIB link-layer addresses */
+ if ( arphdr->ar_hln != ETH_ALEN )
+ return 0;
+
+ /* Fail unless we have room to expand packet */
+ if ( iob_tailroom ( iobuf ) < ( 2 * ( sizeof ( ipoib->mac ) -
+ ETH_ALEN ) ) ) {
+ DBGC ( ipoib, "IPoIB %p insufficient space in TX ARP\n",
+ ipoib );
+ return -ENOBUFS;
+ }
+
+ /* Look up REMAC, if applicable */
+ if ( arphdr->ar_op == ARPOP_REPLY ) {
+ target_ha = ipoib_find_remac ( ipoib, arp_target_pa ( arphdr ));
+ if ( ! target_ha )
+ return -ENXIO;
+ }
+
+ /* Construct new packet */
+ iob_put ( iobuf, ( 2 * ( sizeof ( ipoib->mac ) - ETH_ALEN ) ) );
+ sender_pa = arp_sender_pa ( arphdr );
+ target_pa = arp_target_pa ( arphdr );
+ arphdr->ar_hrd = htons ( ARPHRD_INFINIBAND );
+ arphdr->ar_hln = sizeof ( ipoib->mac );
+ memcpy ( arp_target_pa ( arphdr ), target_pa, arphdr->ar_pln );
+ memcpy ( arp_sender_pa ( arphdr ), sender_pa, arphdr->ar_pln );
+ memcpy ( arp_sender_ha ( arphdr ), &ipoib->mac, sizeof ( ipoib->mac ) );
+ memset ( arp_target_ha ( arphdr ), 0, sizeof ( ipoib->mac ) );
+ if ( target_ha ) {
+ memcpy ( arp_target_ha ( arphdr ), target_ha,
+ sizeof ( *target_ha ) );
+ }
- return -ENOTSUP;
+ return 0;
}
/**
- * Generate Mellanox Ethernet-compatible compressed link-layer address
+ * Translate transmitted packet
*
- * @v ll_addr Link-layer address
- * @v eth_addr Ethernet-compatible address to fill in
+ * @v netdev Network device
+ * @v iobuf Packet to be transmitted (with no link-layer headers)
+ * @v net_proto Network-layer protocol (in network byte order)
+ * @ret rc Return status code
*/
-static int ipoib_mlx_eth_addr ( const union ib_guid *guid,
- uint8_t *eth_addr ) {
- eth_addr[0] = ( ( guid->bytes[3] == 2 ) ? 0x00 : 0x02 );
- eth_addr[1] = guid->bytes[1];
- eth_addr[2] = guid->bytes[2];
- eth_addr[3] = guid->bytes[5];
- eth_addr[4] = guid->bytes[6];
- eth_addr[5] = guid->bytes[7];
- return 0;
-}
-
-/** An IPoIB Ethernet-compatible compressed link-layer address generator */
-struct ipoib_eth_addr_handler {
- /** GUID byte 1 */
- uint8_t byte1;
- /** GUID byte 2 */
- uint8_t byte2;
- /** Handler */
- int ( * eth_addr ) ( const union ib_guid *guid,
- uint8_t *eth_addr );
-};
+static int ipoib_translate_tx ( struct net_device *netdev,
+ struct io_buffer *iobuf, uint16_t net_proto ) {
-/** IPoIB Ethernet-compatible compressed link-layer address generators */
-static struct ipoib_eth_addr_handler ipoib_eth_addr_handlers[] = {
- { 0x02, 0xc9, ipoib_mlx_eth_addr },
-};
+ switch ( net_proto ) {
+ case htons ( ETH_P_ARP ) :
+ return ipoib_translate_tx_arp ( netdev, iobuf );
+ case htons ( ETH_P_IP ) :
+ /* No translation needed */
+ return 0;
+ default:
+ /* Cannot handle other traffic via eIPoIB */
+ return -ENOTSUP;
+ }
+}
/**
- * Generate Ethernet-compatible compressed link-layer address
+ * Translate received ARP packet
*
- * @v ll_addr Link-layer address
- * @v eth_addr Ethernet-compatible address to fill in
+ * @v netdev Network device
+ * @v iobuf Received packet (with no link-layer headers)
+ * @v remac Constructed Remote Ethernet MAC
+ * @ret rc Return status code
*/
-static int ipoib_eth_addr ( const void *ll_addr, void *eth_addr ) {
- const struct ipoib_mac *ipoib_addr = ll_addr;
- const union ib_guid *guid = &ipoib_addr->gid.s.guid;
- struct ipoib_eth_addr_handler *handler;
- unsigned int i;
+static int ipoib_translate_rx_arp ( struct net_device *netdev,
+ struct io_buffer *iobuf,
+ struct ipoib_remac *remac ) {
+ struct ipoib_device *ipoib = netdev->priv;
+ struct arphdr *arphdr = iobuf->data;
+ void *sender_pa;
+ void *target_pa;
+ int rc;
- for ( i = 0 ; i < ( sizeof ( ipoib_eth_addr_handlers ) /
- sizeof ( ipoib_eth_addr_handlers[0] ) ) ; i++ ) {
- handler = &ipoib_eth_addr_handlers[i];
- if ( ( handler->byte1 == guid->bytes[1] ) &&
- ( handler->byte2 == guid->bytes[2] ) ) {
- return handler->eth_addr ( guid, eth_addr );
- }
+ /* Do nothing unless ARP contains IPoIB link-layer addresses */
+ if ( arphdr->ar_hln != sizeof ( ipoib->mac ) )
+ return 0;
+
+ /* Create REMAC cache entry */
+ if ( ( rc = ipoib_map_remac ( ipoib, remac,
+ arp_sender_ha ( arphdr ) ) ) != 0 ) {
+ DBGC ( ipoib, "IPoIB %p could not map REMAC: %s\n",
+ ipoib, strerror ( rc ) );
+ return rc;
}
- return -ENOTSUP;
-}
-/** IPoIB protocol */
-struct ll_protocol ipoib_protocol __ll_protocol = {
- .name = "IPoIB",
- .ll_proto = htons ( ARPHRD_INFINIBAND ),
- .hw_addr_len = sizeof ( union ib_guid ),
- .ll_addr_len = IPOIB_ALEN,
- .ll_header_len = IPOIB_HLEN,
- .push = ipoib_push,
- .pull = ipoib_pull,
- .init_addr = ipoib_init_addr,
- .ntoa = ipoib_ntoa,
- .mc_hash = ipoib_mc_hash,
- .eth_addr = ipoib_eth_addr,
-};
+ /* Construct new packet */
+ sender_pa = arp_sender_pa ( arphdr );
+ target_pa = arp_target_pa ( arphdr );
+ arphdr->ar_hrd = htons ( ARPHRD_ETHER );
+ arphdr->ar_hln = ETH_ALEN;
+ memcpy ( arp_sender_pa ( arphdr ), sender_pa, arphdr->ar_pln );
+ memcpy ( arp_target_pa ( arphdr ), target_pa, arphdr->ar_pln );
+ memcpy ( arp_sender_ha ( arphdr ), remac, ETH_ALEN );
+ memset ( arp_target_ha ( arphdr ), 0, ETH_ALEN );
+ if ( arphdr->ar_op == ARPOP_REPLY ) {
+ /* Assume received replies were directed to us */
+ memcpy ( arp_target_ha ( arphdr ), netdev->ll_addr, ETH_ALEN );
+ }
+ iob_unput ( iobuf, ( 2 * ( sizeof ( ipoib->mac ) - ETH_ALEN ) ) );
+
+ return 0;
+}
/**
- * Allocate IPoIB device
+ * Translate received packet
*
- * @v priv_size Size of driver private data
- * @ret netdev Network device, or NULL
+ * @v netdev Network device
+ * @v iobuf Received packet (with no link-layer headers)
+ * @v remac Constructed Remote Ethernet MAC
+ * @v net_proto Network-layer protocol (in network byte order)
+ * @ret rc Return status code
*/
-struct net_device * alloc_ipoibdev ( size_t priv_size ) {
- struct net_device *netdev;
-
- netdev = alloc_netdev ( priv_size );
- if ( netdev ) {
- netdev->ll_protocol = &ipoib_protocol;
- netdev->ll_broadcast = ( uint8_t * ) &ipoib_broadcast;
- netdev->max_pkt_len = IB_MAX_PAYLOAD_SIZE;
+static int ipoib_translate_rx ( struct net_device *netdev,
+ struct io_buffer *iobuf,
+ struct ipoib_remac *remac,
+ uint16_t net_proto ) {
+
+ switch ( net_proto ) {
+ case htons ( ETH_P_ARP ) :
+ return ipoib_translate_rx_arp ( netdev, iobuf, remac );
+ case htons ( ETH_P_IP ) :
+ /* No translation needed */
+ return 0;
+ default:
+ /* Cannot handle other traffic via eIPoIB */
+ return -ENOTSUP;
}
- return netdev;
}
/****************************************************************************
@@ -422,17 +459,18 @@
struct io_buffer *iobuf ) {
struct ipoib_device *ipoib = netdev->priv;
struct ib_device *ibdev = ipoib->ibdev;
+ struct ethhdr *ethhdr;
struct ipoib_hdr *ipoib_hdr;
- struct ipoib_peer *dest;
- struct ib_address_vector av;
+ struct ipoib_mac *mac;
+ struct ib_address_vector dest;
+ uint16_t net_proto;
int rc;
/* Sanity check */
- if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
+ if ( iob_len ( iobuf ) < sizeof ( *ethhdr ) ) {
DBGC ( ipoib, "IPoIB %p buffer too short\n", ipoib );
return -EINVAL;
}
- ipoib_hdr = iobuf->data;
/* Attempting transmission while link is down will put the
* queue pair into an error state, so don't try it.
@@ -440,23 +478,36 @@
if ( ! ib_link_ok ( ibdev ) )
return -ENETUNREACH;
+ /* Strip eIPoIB header */
+ ethhdr = iobuf->data;
+ net_proto = ethhdr->h_protocol;
+ iob_pull ( iobuf, sizeof ( *ethhdr ) );
+
/* Identify destination address */
- dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest );
- if ( ! dest )
+ mac = ipoib_find_remac ( ipoib, ( ( void *) ethhdr->h_dest ) );
+ if ( ! mac )
return -ENXIO;
- ipoib_hdr->u.reserved = 0;
+
+ /* Translate packet if applicable */
+ if ( ( rc = ipoib_translate_tx ( netdev, iobuf, net_proto ) ) != 0 )
+ return rc;
+
+ /* Prepend real IPoIB header */
+ ipoib_hdr = iob_push ( iobuf, sizeof ( *ipoib_hdr ) );
+ ipoib_hdr->proto = net_proto;
+ ipoib_hdr->reserved = 0;
/* Construct address vector */
- memset ( &av, 0, sizeof ( av ) );
- av.qpn = ( ntohl ( dest->mac.flags__qpn ) & IB_QPN_MASK );
- av.gid_present = 1;
- memcpy ( &av.gid, &dest->mac.gid, sizeof ( av.gid ) );
- if ( ( rc = ib_resolve_path ( ibdev, &av ) ) != 0 ) {
+ memset ( &dest, 0, sizeof ( dest ) );
+ dest.qpn = ( ntohl ( mac->flags__qpn ) & IB_QPN_MASK );
+ dest.gid_present = 1;
+ memcpy ( &dest.gid, &mac->gid, sizeof ( dest.gid ) );
+ if ( ( rc = ib_resolve_path ( ibdev, &dest ) ) != 0 ) {
/* Path not resolved yet */
return rc;
}
- return ib_post_send ( ibdev, ipoib->qp, &av, iobuf );
+ return ib_post_send ( ibdev, ipoib->qp, &dest, iobuf );
}
/**
@@ -480,19 +531,22 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector, or NULL
+ * @v dest Destination address vector, or NULL
+ * @v source Source address vector, or NULL
* @v iobuf I/O buffer
* @v rc Completion status code
*/
static void ipoib_complete_recv ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
+ struct ib_address_vector *source,
struct io_buffer *iobuf, int rc ) {
struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp );
struct net_device *netdev = ipoib->netdev;
struct ipoib_hdr *ipoib_hdr;
- struct ipoib_mac ll_src;
- struct ipoib_peer *src;
+ struct ethhdr *ethhdr;
+ struct ipoib_remac remac;
+ uint16_t net_proto;
/* Record errors */
if ( rc != 0 ) {
@@ -508,20 +562,44 @@
netdev_rx_err ( netdev, iobuf, -EIO );
return;
}
- ipoib_hdr = iobuf->data;
- if ( ! av ) {
+ if ( ! source ) {
DBGC ( ipoib, "IPoIB %p received packet without address "
"vector\n", ipoib );
netdev_rx_err ( netdev, iobuf, -ENOTTY );
return;
}
- /* Parse source address */
- if ( av->gid_present ) {
- ll_src.flags__qpn = htonl ( av->qpn );
- memcpy ( &ll_src.gid, &av->gid, sizeof ( ll_src.gid ) );
- src = ipoib_cache_peer ( &ll_src );
- ipoib_hdr->u.peer.src = src->key;
+ /* Strip real IPoIB header */
+ ipoib_hdr = iobuf->data;
+ net_proto = ipoib_hdr->proto;
+ iob_pull ( iobuf, sizeof ( *ipoib_hdr ) );
+
+ /* Construct source address from remote QPN and LID */
+ remac.qpn = htonl ( source->qpn | EIPOIB_QPN_LA );
+ remac.lid = htons ( source->lid );
+
+ /* Translate packet if applicable */
+ if ( ( rc = ipoib_translate_rx ( netdev, iobuf, &remac,
+ net_proto ) ) != 0 ) {
+ netdev_rx_err ( netdev, iobuf, rc );
+ return;
+ }
+
+ /* Prepend eIPoIB header */
+ ethhdr = iob_push ( iobuf, sizeof ( *ethhdr ) );
+ memcpy ( ðhdr->h_source, &remac, sizeof ( ethhdr->h_source ) );
+ ethhdr->h_protocol = net_proto;
+
+ /* Construct destination address */
+ if ( dest->gid_present && ( memcmp ( &dest->gid, &ipoib->broadcast.gid,
+ sizeof ( dest->gid ) ) == 0 ) ) {
+ /* Broadcast GID; use the Ethernet broadcast address */
+ memcpy ( ðhdr->h_dest, eth_broadcast,
+ sizeof ( ethhdr->h_dest ) );
+ } else {
+ /* Assume destination address is local Ethernet MAC */
+ memcpy ( ðhdr->h_dest, netdev->ll_addr,
+ sizeof ( ethhdr->h_dest ) );
}
/* Hand off to network layer */
@@ -535,6 +613,42 @@
};
/**
+ * Allocate IPoIB receive I/O buffer
+ *
+ * @v len Length of buffer
+ * @ret iobuf I/O buffer, or NULL
+ *
+ * Some Infiniband hardware requires 2kB alignment of receive buffers
+ * and provides no way to disable header separation. The result is
+ * that there are only four bytes of link-layer header (the real IPoIB
+ * header) before the payload. This is not sufficient space to insert
+ * an eIPoIB link-layer pseudo-header.
+ *
+ * We therefore allocate I/O buffers offset to start slightly before
+ * the natural alignment boundary, in order to allow sufficient space.
+ */
+static struct io_buffer * ipoib_alloc_iob ( size_t len ) {
+ struct io_buffer *iobuf;
+ size_t reserve_len;
+
+ /* Calculate additional length required at start of buffer */
+ reserve_len = ( sizeof ( struct ethhdr ) -
+ sizeof ( struct ipoib_hdr ) );
+
+ /* Allocate buffer */
+ iobuf = alloc_iob_raw ( ( len + reserve_len ), len, -reserve_len );
+ if ( iobuf ) {
+ iob_reserve ( iobuf, reserve_len );
+ }
+ return iobuf;
+}
+
+/** IPoIB queue pair operations */
+static struct ib_queue_pair_operations ipoib_qp_op = {
+ .alloc_iob = ipoib_alloc_iob,
+};
+
+/**
* Poll IPoIB network device
*
* @v netdev Network device
@@ -543,7 +657,11 @@
struct ipoib_device *ipoib = netdev->priv;
struct ib_device *ibdev = ipoib->ibdev;
+ /* Poll Infiniband device */
ib_poll_eq ( ibdev );
+
+ /* Poll the retry timers (required for IPoIB multicast join) */
+ retry_poll();
}
/**
@@ -610,15 +728,14 @@
static void ipoib_link_state_changed ( struct ib_device *ibdev ) {
struct net_device *netdev = ib_get_ownerdata ( ibdev );
struct ipoib_device *ipoib = netdev->priv;
- struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
int rc;
/* Leave existing broadcast group */
ipoib_leave_broadcast_group ( ipoib );
/* Update MAC address based on potentially-new GID prefix */
- memcpy ( &mac->gid.s.prefix, &ibdev->gid.s.prefix,
- sizeof ( mac->gid.s.prefix ) );
+ memcpy ( &ipoib->mac.gid.s.prefix, &ibdev->gid.s.prefix,
+ sizeof ( ipoib->mac.gid.s.prefix ) );
/* Update broadcast GID based on potentially-new partition key */
ipoib->broadcast.gid.words[2] =
@@ -647,7 +764,6 @@
static int ipoib_open ( struct net_device *netdev ) {
struct ipoib_device *ipoib = netdev->priv;
struct ib_device *ibdev = ipoib->ibdev;
- struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
int rc;
/* Open IB device */
@@ -667,9 +783,9 @@
}
/* Allocate queue pair */
- ipoib->qp = ib_create_qp ( ibdev, IB_QPT_UD,
- IPOIB_NUM_SEND_WQES, ipoib->cq,
- IPOIB_NUM_RECV_WQES, ipoib->cq );
+ ipoib->qp = ib_create_qp ( ibdev, IB_QPT_UD, IPOIB_NUM_SEND_WQES,
+ ipoib->cq, IPOIB_NUM_RECV_WQES, ipoib->cq,
+ &ipoib_qp_op );
if ( ! ipoib->qp ) {
DBGC ( ipoib, "IPoIB %p could not allocate queue pair\n",
ipoib );
@@ -679,7 +795,7 @@
ib_qp_set_ownerdata ( ipoib->qp, ipoib );
/* Update MAC address with QPN */
- mac->flags__qpn = htonl ( ipoib->qp->qpn );
+ ipoib->mac.flags__qpn = htonl ( ipoib->qp->qpn );
/* Fill receive rings */
ib_refill_recv ( ibdev, ipoib->qp );
@@ -706,13 +822,15 @@
static void ipoib_close ( struct net_device *netdev ) {
struct ipoib_device *ipoib = netdev->priv;
struct ib_device *ibdev = ipoib->ibdev;
- struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
+
+ /* Flush REMAC cache */
+ ipoib_flush_remac ( ipoib );
/* Leave broadcast group */
ipoib_leave_broadcast_group ( ipoib );
/* Remove QPN from MAC address */
- mac->flags__qpn = 0;
+ ipoib->mac.flags__qpn = 0;
/* Tear down the queues */
ib_destroy_qp ( ibdev, ipoib->qp );
@@ -752,15 +870,19 @@
memset ( ipoib, 0, sizeof ( *ipoib ) );
ipoib->netdev = netdev;
ipoib->ibdev = ibdev;
+ INIT_LIST_HEAD ( &ipoib->peers );
/* Extract hardware address */
memcpy ( netdev->hw_addr, &ibdev->gid.s.guid,
sizeof ( ibdev->gid.s.guid ) );
- /* Set default broadcast address */
+ /* Set local MAC address */
+ memcpy ( &ipoib->mac.gid.s.guid, &ibdev->gid.s.guid,
+ sizeof ( ipoib->mac.gid.s.guid ) );
+
+ /* Set default broadcast MAC address */
memcpy ( &ipoib->broadcast, &ipoib_broadcast,
sizeof ( ipoib->broadcast ) );
- netdev->ll_broadcast = ( ( uint8_t * ) &ipoib->broadcast );
/* Register network device */
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/net/mii.c
^
|
@@ -31,6 +31,37 @@
*/
/**
+ * Restart autonegotiation
+ *
+ * @v mii MII interface
+ * @ret rc Return status code
+ */
+int mii_restart ( struct mii_interface *mii ) {
+ int bmcr;
+ int rc;
+
+ /* Read BMCR */
+ bmcr = mii_read ( mii, MII_BMCR );
+ if ( bmcr < 0 ) {
+ rc = bmcr;
+ DBGC ( mii, "MII %p could not read BMCR: %s\n",
+ mii, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Enable and restart autonegotiation */
+ bmcr |= ( BMCR_ANENABLE | BMCR_ANRESTART );
+ if ( ( rc = mii_write ( mii, MII_BMCR, bmcr ) ) != 0 ) {
+ DBGC ( mii, "MII %p could not write BMCR: %s\n",
+ mii, strerror ( rc ) );
+ return rc;
+ }
+
+ DBGC ( mii, "MII %p restarted autonegotiation\n", mii );
+ return 0;
+}
+
+/**
* Reset MII interface
*
* @v mii MII interface
@@ -70,11 +101,8 @@
/* Force autonegotation on again, in case it was
* cleared by the reset.
*/
- if ( ( rc = mii_write ( mii, MII_BMCR, BMCR_ANENABLE ) ) != 0 ){
- DBGC ( mii, "MII %p could not write BMCR: %s\n",
- mii, strerror ( rc ) );
+ if ( ( rc = mii_restart ( mii ) ) != 0 )
return rc;
- }
DBGC ( mii, "MII %p reset after %dms\n", mii, i );
return 0;
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/net/realtek.c
^
|
@@ -60,10 +60,36 @@
[SPI_BIT_SCLK] = RTL_9346CR_EESK,
[SPI_BIT_MOSI] = RTL_9346CR_EEDI,
[SPI_BIT_MISO] = RTL_9346CR_EEDO,
- [SPI_BIT_SS(0)] = ( RTL_9346CR_EECS | RTL_9346CR_EEM1 ),
+ [SPI_BIT_SS(0)] = RTL_9346CR_EECS,
};
/**
+ * Open bit-bashing interface
+ *
+ * @v basher Bit-bashing interface
+ */
+static void realtek_spi_open_bit ( struct bit_basher *basher ) {
+ struct realtek_nic *rtl = container_of ( basher, struct realtek_nic,
+ spibit.basher );
+
+ /* Enable EEPROM access */
+ writeb ( RTL_9346CR_EEM_EEPROM, rtl->regs + RTL_9346CR );
+}
+
+/**
+ * Close bit-bashing interface
+ *
+ * @v basher Bit-bashing interface
+ */
+static void realtek_spi_close_bit ( struct bit_basher *basher ) {
+ struct realtek_nic *rtl = container_of ( basher, struct realtek_nic,
+ spibit.basher );
+
+ /* Disable EEPROM access */
+ writeb ( RTL_9346CR_EEM_NORMAL, rtl->regs + RTL_9346CR );
+}
+
+/**
* Read input bit
*
* @v basher Bit-bashing interface
@@ -108,6 +134,8 @@
/** SPI bit-bashing interface */
static struct bit_basher_operations realtek_basher_ops = {
+ .open = realtek_spi_open_bit,
+ .close = realtek_spi_close_bit,
.read = realtek_spi_read_bit,
.write = realtek_spi_write_bit,
};
@@ -272,6 +300,75 @@
return -ETIMEDOUT;
}
+/**
+ * Configure PHY for Gigabit operation
+ *
+ * @v rtl Realtek device
+ * @ret rc Return status code
+ */
+static int realtek_phy_speed ( struct realtek_nic *rtl ) {
+ int ctrl1000;
+ int rc;
+
+ /* Read CTRL1000 register */
+ ctrl1000 = mii_read ( &rtl->mii, MII_CTRL1000 );
+ if ( ctrl1000 < 0 ) {
+ rc = ctrl1000;
+ DBGC ( rtl, "REALTEK %p could not read CTRL1000: %s\n",
+ rtl, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Advertise 1000Mbps speeds */
+ ctrl1000 |= ( ADVERTISE_1000FULL | ADVERTISE_1000HALF );
+ if ( ( rc = mii_write ( &rtl->mii, MII_CTRL1000, ctrl1000 ) ) != 0 ) {
+ DBGC ( rtl, "REALTEK %p could not write CTRL1000: %s\n",
+ rtl, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Reset PHY
+ *
+ * @v rtl Realtek device
+ * @ret rc Return status code
+ */
+static int realtek_phy_reset ( struct realtek_nic *rtl ) {
+ int rc;
+
+ /* Do nothing if we have no separate PHY register access */
+ if ( ! rtl->have_phy_regs )
+ return 0;
+
+ /* Perform MII reset */
+ if ( ( rc = mii_reset ( &rtl->mii ) ) != 0 ) {
+ DBGC ( rtl, "REALTEK %p could not reset MII: %s\n",
+ rtl, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Some cards (e.g. RTL8169SC) do not advertise Gigabit by
+ * default. Try to enable advertisement of Gigabit speeds.
+ */
+ if ( ( rc = realtek_phy_speed ( rtl ) ) != 0 ) {
+ /* Ignore failures, since the register may not be
+ * present on non-Gigabit PHYs (e.g. RTL8101).
+ */
+ }
+
+ /* Restart autonegotiation */
+ if ( ( rc = mii_restart ( &rtl->mii ) ) != 0 ) {
+ DBGC ( rtl, "REALTEK %p could not restart MII: %s\n",
+ rtl, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
/******************************************************************************
*
* Link state
@@ -409,11 +506,9 @@
/* Program ring address */
address = virt_to_bus ( ring->desc );
+ writel ( ( ( ( uint64_t ) address ) >> 32 ),
+ rtl->regs + ring->reg + 4 );
writel ( ( address & 0xffffffffUL ), rtl->regs + ring->reg );
- if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {
- writel ( ( ( ( uint64_t ) address ) >> 32 ),
- rtl->regs + ring->reg + 4 );
- }
DBGC ( rtl, "REALTEK %p ring %02x is at [%08llx,%08llx)\n",
rtl, ring->reg, ( ( unsigned long long ) address ),
( ( unsigned long long ) address + ring->len ) );
@@ -502,6 +597,7 @@
*/
static int realtek_open ( struct net_device *netdev ) {
struct realtek_nic *rtl = netdev->priv;
+ uint32_t tcr;
uint32_t rcr;
int rc;
@@ -526,10 +622,18 @@
*/
writeb ( ( RTL_CR_TE | RTL_CR_RE ), rtl->regs + RTL_CR );
+ /* Configure transmitter */
+ tcr = readl ( rtl->regs + RTL_TCR );
+ tcr &= ~RTL_TCR_MXDMA_MASK;
+ tcr |= RTL_TCR_MXDMA_DEFAULT;
+ writel ( tcr, rtl->regs + RTL_TCR );
+
/* Configure receiver */
rcr = readl ( rtl->regs + RTL_RCR );
- rcr &= ~( RTL_RCR_RBLEN_MASK );
- rcr |= ( RTL_RCR_RBLEN_DEFAULT | RTL_RCR_WRAP | RTL_RCR_AB |
+ rcr &= ~( RTL_RCR_RXFTH_MASK | RTL_RCR_RBLEN_MASK |
+ RTL_RCR_MXDMA_MASK );
+ rcr |= ( RTL_RCR_RXFTH_DEFAULT | RTL_RCR_RBLEN_DEFAULT |
+ RTL_RCR_MXDMA_DEFAULT | RTL_RCR_WRAP | RTL_RCR_AB |
RTL_RCR_AM | RTL_RCR_APM | RTL_RCR_AAP );
writel ( rcr, rtl->regs + RTL_RCR );
@@ -871,9 +975,15 @@
/* The C+ Command register is present only on 8169 and 8139C+.
* Try to enable C+ mode and PCI Dual Address Cycle (for
* 64-bit systems), if supported.
+ *
+ * Note that enabling DAC seems to cause bizarre behaviour
+ * (lockups, garbage data on the wire) on some systems, even
+ * if only 32-bit addresses are used.
*/
- cpcr = ( RTL_CPCR_DAC | RTL_CPCR_MULRW | RTL_CPCR_CPRX |
- RTL_CPCR_CPTX );
+ cpcr = readw ( rtl->regs + RTL_CPCR );
+ cpcr |= ( RTL_CPCR_MULRW | RTL_CPCR_CPRX | RTL_CPCR_CPTX );
+ if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) )
+ cpcr |= RTL_CPCR_DAC;
writew ( cpcr, rtl->regs + RTL_CPCR );
check_cpcr = readw ( rtl->regs + RTL_CPCR );
@@ -883,7 +993,7 @@
rtl->have_phy_regs = 1;
rtl->tppoll = RTL_TPPOLL_8169;
} else {
- if ( check_cpcr == cpcr ) {
+ if ( ( check_cpcr == cpcr ) && ( cpcr != 0xffff ) ) {
DBGC ( rtl, "REALTEK %p appears to be an RTL8139C+\n",
rtl );
rtl->tppoll = RTL_TPPOLL_8139CP;
@@ -957,12 +1067,8 @@
/* Initialise and reset MII interface */
mii_init ( &rtl->mii, &realtek_mii_operations );
- if ( rtl->have_phy_regs &&
- ( ( rc = mii_reset ( &rtl->mii ) ) != 0 ) ) {
- DBGC ( rtl, "REALTEK %p could not reset MII: %s\n",
- rtl, strerror ( rc ) );
- goto err_mii_reset;
- }
+ if ( ( rc = realtek_phy_reset ( rtl ) ) != 0 )
+ goto err_phy_reset;
/* Register network device */
if ( ( rc = register_netdev ( netdev ) ) != 0 )
@@ -983,7 +1089,7 @@
err_register_nvo:
unregister_netdev ( netdev );
err_register_netdev:
- err_mii_reset:
+ err_phy_reset:
err_nvs_read:
realtek_reset ( rtl );
err_reset:
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/net/realtek.h
^
|
@@ -132,11 +132,23 @@
/** Interrupt Status Register (word) */
#define RTL_ISR 0x3e
+/** Transmit (Tx) Configuration Register (dword) */
+#define RTL_TCR 0x40
+#define RTL_TCR_MXDMA(x) ( (x) << 8 ) /**< Max DMA burst size */
+#define RTL_TCR_MXDMA_MASK RTL_TCR_MXDMA ( 0x7 )
+#define RTL_TCR_MXDMA_DEFAULT RTL_TCR_MXDMA ( 0x7 /* Unlimited */ )
+
/** Receive (Rx) Configuration Register (dword) */
#define RTL_RCR 0x44
+#define RTL_RCR_RXFTH(x) ( (x) << 13 ) /**< Receive FIFO threshold */
+#define RTL_RCR_RXFTH_MASK RTL_RCR_RXFTH ( 0x7 )
+#define RTL_RCR_RXFTH_DEFAULT RTL_RCR_RXFTH ( 0x7 /* Whole packet */ )
#define RTL_RCR_RBLEN(x) ( (x) << 11 ) /**< Receive buffer length */
#define RTL_RCR_RBLEN_MASK RTL_RCR_RBLEN ( 0x3 )
#define RTL_RCR_RBLEN_DEFAULT RTL_RCR_RBLEN ( 0 /* 8kB */ )
+#define RTL_RCR_MXDMA(x) ( (x) << 8 ) /**< Max DMA burst size */
+#define RTL_RCR_MXDMA_MASK RTL_RCR_MXDMA ( 0x7 )
+#define RTL_RCR_MXDMA_DEFAULT RTL_RCR_MXDMA ( 0x7 /* Unlimited */ )
#define RTL_RCR_WRAP 0x00000080UL /**< Overrun receive buffer */
#define RTL_RCR_9356SEL 0x00000040UL /**< EEPROM is a 93C56 */
#define RTL_RCR_AB 0x00000008UL /**< Accept broadcast packets */
@@ -146,8 +158,9 @@
/** 93C46 (93C56) Command Register (byte) */
#define RTL_9346CR 0x50
-#define RTL_9346CR_EEM1 0x80 /**< Mode select bit 1 */
-#define RTL_9346CR_EEM0 0x40 /**< Mode select bit 0 */
+#define RTL_9346CR_EEM(x) ( (x) << 6 ) /**< Mode select */
+#define RTL_9346CR_EEM_EEPROM RTL_9346CR_EEM ( 0x2 ) /**< EEPROM mode */
+#define RTL_9346CR_EEM_NORMAL RTL_9346CR_EEM ( 0x0 ) /**< Normal mode */
#define RTL_9346CR_EECS 0x08 /**< Chip select */
#define RTL_9346CR_EESK 0x04 /**< Clock */
#define RTL_9346CR_EEDI 0x02 /**< Data in */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/net/tg3/tg3.c
^
|
@@ -247,11 +247,12 @@
return err;
tpr->rx_std_iob_cnt = 0;
- tg3_refill_prod_ring(tp);
err = tg3_init_hw(tp, 1);
if (err != 0)
DBGC(tp->dev, "tg3_init_hw failed: %s\n", strerror(err));
+ else
+ tg3_refill_prod_ring(tp);
return err;
}
@@ -301,7 +302,6 @@
struct tg3 *tp = netdev_priv(dev);
u32 len, entry;
dma_addr_t mapping;
- u32 bmsr;
if (tg3_tx_avail(tp) < 1) {
DBGC(dev, "Transmit ring full\n");
@@ -323,14 +323,10 @@
/* Packets are ready, update Tx producer idx local and on card. */
tw32_tx_mbox(tp->prodmbox, entry);
- writel(entry, tp->regs + MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
-
tp->tx_prod = entry;
mb();
- tg3_readphy(tp, MII_BMSR, &bmsr);
-
return 0;
}
@@ -422,8 +418,10 @@
tpr->rx_std_iob_cnt++;
}
- tpr->rx_std_prod_idx = idx;
- tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, idx);
+ if ((u32)idx != tpr->rx_std_prod_idx) {
+ tpr->rx_std_prod_idx = idx;
+ tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, idx);
+ }
}
static void tg3_rx_complete(struct net_device *dev)
@@ -469,7 +467,10 @@
tpr->rx_std_iob_cnt--;
}
- tp->rx_rcb_ptr = sw_idx;
+ if (tp->rx_rcb_ptr != sw_idx) {
+ tw32_rx_mbox(tp->consmbox, sw_idx);
+ tp->rx_rcb_ptr = sw_idx;
+ }
tg3_refill_prod_ring(tp);
}
@@ -480,7 +481,9 @@
struct tg3 *tp = netdev_priv(dev);
/* ACK interrupts */
- tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00);
+ /*
+ *tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00);
+ */
tp->hw_status->status &= ~SD_STATUS_UPDATED;
tg3_poll_link(tp);
@@ -905,6 +908,7 @@
PCI_ROM(0x14e4, 0x1684, "14e4-1684", "14e4-1684", 0),
PCI_ROM(0x14e4, 0x165b, "14e4-165b", "14e4-165b", 0),
PCI_ROM(0x14e4, 0x1681, "14e4-1681", "14e4-1681", 0),
+ PCI_ROM(0x14e4, 0x1682, "14e4-1682", "14e4-1682", 0),
PCI_ROM(0x14e4, 0x1680, "14e4-1680", "14e4-1680", 0),
PCI_ROM(0x14e4, 0x1688, "14e4-1688", "14e4-1688", 0),
PCI_ROM(0x14e4, 0x1689, "14e4-1689", "14e4-1689", 0),
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/net/tg3/tg3.h
^
|
@@ -153,6 +153,7 @@
#define TG3_BDINFO_NIC_ADDR 0xcUL /* 32-bit */
#define TG3_BDINFO_SIZE 0x10UL
+#define RX_STD_MAX_SIZE 1536
#define TG3_RX_STD_MAX_SIZE_5700 512
#define TG3_RX_STD_MAX_SIZE_5717 2048
#define TG3_RX_JMB_MAX_SIZE_5700 256
@@ -182,6 +183,7 @@
#define TG3PCI_DEVICE_TIGON3_57781 0x16b1
#define TG3PCI_DEVICE_TIGON3_57785 0x16b5
#define TG3PCI_DEVICE_TIGON3_57761 0x16b0
+#define TG3PCI_DEVICE_TIGON3_57762 0x1682
#define TG3PCI_DEVICE_TIGON3_57765 0x16b4
#define TG3PCI_DEVICE_TIGON3_57791 0x16b2
#define TG3PCI_DEVICE_TIGON3_57795 0x16b6
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/net/tg3/tg3_hw.c
^
|
@@ -434,6 +434,7 @@
else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57762 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795)
@@ -2127,9 +2128,12 @@
val = TG3_RX_STD_MAX_SIZE_5700 << BDINFO_FLAGS_MAXLEN_SHIFT;
+ if (tg3_flag(tp, 57765_PLUS))
+ val |= (RX_STD_MAX_SIZE << 2);
+
tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val);
- tpr->rx_std_prod_idx = TG3_DEF_RX_RING_PENDING;
+ tpr->rx_std_prod_idx = 0;
/* std prod index is updated by tg3_refill_prod_ring() */
tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, 0);
@@ -2137,6 +2141,8 @@
tg3_rings_reset(tp);
+ __tg3_set_mac_addr(tp,0);
+
#define TG3_MAX_MTU 1522
/* MTU + ethernet header + FCS + optional VLAN tag */
tw32(MAC_RX_MTU_SIZE, TG3_MAX_MTU);
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/drivers/net/tg3/tg3_phy.c
^
|
@@ -1008,12 +1008,11 @@
void tg3_poll_link(struct tg3 *tp)
{ DBGP("%s\n", __func__);
- u32 mac_stat;
-
- mac_stat = tr32(MAC_STATUS);
-
- if (mac_stat & MAC_STATUS_LNKSTATE_CHANGED)
+ if (tp->hw_status->status & SD_STATUS_LINK_CHG) {
+ DBGC(tp->dev,"link_changed\n");
+ tp->hw_status->status &= ~SD_STATUS_LINK_CHG;
tg3_setup_phy(tp, 0);
+ }
}
static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
@@ -1506,9 +1505,8 @@
tw32_f(MAC_MODE, tp->mac_mode);
udelay(40);
- /* We always use the link change register */
- /* NOTE: this freezes for mdc? */
- tw32_f(MAC_EVENT, 0);
+ /* Enabled attention when the link has changed state. */
+ tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
udelay(40);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/hci/commands/menu_cmd.c
^
|
@@ -249,7 +249,8 @@
goto err_show_menu;
/* Store setting */
- if ( ( rc = storef_named_setting ( setting, item->label ) ) != 0 ) {
+ if ( ( rc = storef_named_setting ( setting, &setting_type_string,
+ item->label ) ) != 0 ) {
printf ( "Could not store \"%s\": %s\n",
setting, strerror ( rc ) );
goto err_store;
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/hci/commands/nslookup_cmd.c
^
|
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 Patrick Plenefisch <phplenefisch@wpi.edu>.
+ *
+ * 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.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <getopt.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <usr/nslookup.h>
+
+/** @file
+ *
+ * nslookup command
+ *
+ */
+
+/** "nslookup" options */
+struct nslookup_options {};
+
+/** "nslookup" option list */
+static struct option_descriptor nslookup_opts[] = {};
+
+/** "nslookup" command descriptor */
+static struct command_descriptor nslookup_cmd =
+ COMMAND_DESC ( struct nslookup_options, nslookup_opts, 2, 2,
+ "<setting> <name>" );
+
+/**
+ * The "nslookup" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int nslookup_exec ( int argc, char **argv ) {
+ struct nslookup_options opts;
+ const char *name;
+ const char *setting_name;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &nslookup_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse setting name */
+ setting_name = argv[optind];
+
+ /* Parse name to be resolved */
+ name = argv[ optind + 1 ];
+
+ /* Look up name */
+ if ( ( rc = nslookup ( name, setting_name ) ) != 0 )
+ return rc;
+
+ return 0;
+}
+
+/** The "nslookup" command */
+struct command nslookup_command __command = {
+ .name = "nslookup",
+ .exec = nslookup_exec,
+};
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/hci/commands/nvo_cmd.c
^
|
@@ -109,7 +109,8 @@
*/
static int set_core_exec ( int argc, char **argv,
struct command_descriptor *cmd,
- int ( * get_value ) ( char **args, char **value ) ) {
+ int ( * get_value ) ( const char *name,
+ char **args, char **value ) ) {
struct set_core_options opts;
const char *name;
char *value;
@@ -123,11 +124,12 @@
name = argv[optind];
/* Parse setting value */
- if ( ( rc = get_value ( &argv[ optind + 1 ], &value ) ) != 0 )
+ if ( ( rc = get_value ( name, &argv[ optind + 1 ], &value ) ) != 0 )
goto err_get_value;
/* Determine total length of command line */
- if ( ( rc = storef_named_setting ( name, value ) ) != 0 ) {
+ if ( ( rc = storef_named_setting ( name, &setting_type_string,
+ value ) ) != 0 ) {
printf ( "Could not %s \"%s\": %s\n",
argv[0], name, strerror ( rc ) );
goto err_store;
@@ -146,11 +148,12 @@
/**
* Get setting value for "set" command
*
+ * @v name Setting name
* @v args Remaining arguments
* @ret value Setting value
* @ret rc Return status code
*/
-static int set_value ( char **args, char **value ) {
+static int set_value ( const char *name __unused, char **args, char **value ) {
*value = concat_args ( args );
if ( ! *value )
@@ -173,11 +176,13 @@
/**
* Get setting value for "clear" command
*
+ * @v name Setting name
* @v args Remaining arguments
* @ret value Setting value
* @ret rc Return status code
*/
-static int clear_value ( char **args __unused, char **value ) {
+static int clear_value ( const char *name __unused, char **args __unused,
+ char **value ) {
*value = NULL;
return 0;
@@ -197,16 +202,30 @@
/**
* Get setting value for "read" command
*
+ * @v name Setting name
+ * @v args Remaining arguments
* @ret value Setting value
* @ret rc Return status code
*/
-static int read_value ( char **args __unused, char **value ) {
-
- *value = readline ( NULL );
- if ( ! *value )
- return -ENOMEM;
+static int read_value ( const char *name, char **args __unused, char **value ) {
+ char *existing;
+ int rc;
- return 0;
+ /* Read existing value */
+ if ( ( rc = fetchf_named_setting_copy ( name, &existing ) ) < 0 )
+ goto err_existing;
+
+ /* Read new value */
+ if ( ( rc = readline_history ( NULL, existing, NULL, value ) ) != 0 )
+ goto err_new;
+
+ /* Success */
+ rc = 0;
+
+ err_new:
+ free ( existing );
+ err_existing:
+ return rc;
}
/**
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/hci/readline.c
^
|
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <errno.h>
#include <ipxe/console.h>
#include <ipxe/keys.h>
#include <ipxe/editstring.h>
@@ -241,20 +242,25 @@
* Read line from console (with history)
*
* @v prompt Prompt string
+ * @v prefill Prefill string, or NULL for no prefill
* @v history History buffer, or NULL for no history
* @ret line Line read from console (excluding terminating newline)
+ * @ret rc Return status code
*
* The returned line is allocated with malloc(); the caller must
* eventually call free() to release the storage.
*/
-char * readline_history ( const char *prompt,
- struct readline_history *history ) {
+int readline_history ( const char *prompt, const char *prefill,
+ struct readline_history *history, char **line ) {
char buf[READLINE_MAX];
struct edit_string string;
int key;
int move_by;
const char *new_string;
- char *line;
+ int rc;
+
+ /* Avoid returning uninitialised data on error */
+ *line = NULL;
/* Display prompt, if applicable */
if ( prompt )
@@ -265,6 +271,12 @@
init_editstring ( &string, buf, sizeof ( buf ) );
buf[0] = '\0';
+ /* Prefill string, if applicable */
+ if ( prefill ) {
+ replace_string ( &string, prefill );
+ sync_console ( &string );
+ }
+
while ( 1 ) {
/* Handle keypress */
key = edit_string ( &string, getkey ( 0 ) );
@@ -273,12 +285,11 @@
switch ( key ) {
case CR:
case LF:
- line = strdup ( buf );
- if ( ! line )
- printf ( "\nOut of memory" );
+ *line = strdup ( buf );
+ rc = ( ( *line ) ? 0 : -ENOMEM );
goto done;
case CTRL_C:
- line = NULL;
+ rc = -ECANCELED;
goto done;
case KEY_UP:
move_by = 1;
@@ -304,11 +315,12 @@
done:
putchar ( '\n' );
if ( history ) {
- if ( line && line[0] )
- history_append ( history, line );
+ if ( *line && (*line)[0] )
+ history_append ( history, *line );
history_cleanup ( history );
}
- return line;
+ assert ( ( rc == 0 ) ^ ( *line == NULL ) );
+ return rc;
}
/**
@@ -321,5 +333,8 @@
* eventually call free() to release the storage.
*/
char * readline ( const char *prompt ) {
- return readline_history ( prompt, NULL );
+ char *line;
+
+ readline_history ( prompt, NULL, NULL, &line );
+ return line;
}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/hci/shell.c
^
|
@@ -86,7 +86,7 @@
/* Read and execute commands */
do {
- line = readline_history ( shell_prompt, &history );
+ readline_history ( shell_prompt, NULL, &history, &line );
if ( line ) {
rc = system ( line );
free ( line );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/bitbash.h
^
|
@@ -14,6 +14,18 @@
/** Bit-bashing operations */
struct bit_basher_operations {
/**
+ * Open bit-bashing interface (optional)
+ *
+ * @v basher Bit-bashing interface
+ */
+ void ( * open ) ( struct bit_basher *basher );
+ /**
+ * Close bit-bashing interface (optional)
+ *
+ * @v basher Bit-bashing interface
+ */
+ void ( * close ) ( struct bit_basher *basher );
+ /**
* Set/clear output bit
*
* @v basher Bit-bashing interface
@@ -45,6 +57,26 @@
struct bit_basher_operations *op;
};
+/**
+ * Open bit-bashing interface
+ *
+ * @v basher Bit-bashing interface
+ */
+static inline void open_bit ( struct bit_basher *basher ) {
+ if ( basher->op->open )
+ basher->op->open ( basher );
+}
+
+/**
+ * Close bit-bashing interface
+ *
+ * @v basher Bit-bashing interface
+ */
+static inline void close_bit ( struct bit_basher *basher ) {
+ if ( basher->op->close )
+ basher->op->close ( basher );
+}
+
extern void write_bit ( struct bit_basher *basher, unsigned int bit_id,
unsigned long data );
extern int read_bit ( struct bit_basher *basher, unsigned int bit_id );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/dhcp.h
^
|
@@ -651,8 +651,6 @@
#define PXEBS_SETTINGS_NAME "pxebs"
extern uint32_t dhcp_last_xid;
-extern unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr,
- uint16_t *flags );
extern int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
struct net_device *netdev, uint8_t msgtype,
uint32_t xid, const void *options,
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/efi/efi_hii.h
^
|
@@ -8,133 +8,89 @@
FILE_LICENCE ( GPL2_OR_LATER );
+#include <string.h>
#include <ipxe/efi/Uefi/UefiInternalFormRepresentation.h>
#include <ipxe/efi/Guid/MdeModuleHii.h>
-/**
- * Define an EFI IFR form set type
- *
- * @v num_class_guids Number of class GUIDs
- * @ret type Form set type
- */
-#define EFI_IFR_FORM_SET_TYPE( num_class_guids ) \
- struct { \
- EFI_IFR_FORM_SET FormSet; \
- EFI_GUID ClassGuid[num_class_guids]; \
- } __attribute__ (( packed ))
-
-/**
- * Define an EFI IFR form set
- *
- * @v guid GUID
- * @v title Title string
- * @v help Help string
- * @v type Form set type (as returned by EFI_IFR_FORM_SET_TYPE())
- * @ret ifr Form set
- *
- * This definition opens a new scope, which must be closed by an
- * EFI_IFR_END().
- */
-#define EFI_IFR_FORM_SET( guid, title, help, type, ... ) { \
- .FormSet = { \
- .Header = { \
- .OpCode = EFI_IFR_FORM_SET_OP, \
- .Length = sizeof ( type ), \
- .Scope = 1, \
- }, \
- .Guid = guid, \
- .FormSetTitle = title, \
- .Help = help, \
- .Flags = ( sizeof ( ( ( type * ) NULL )->ClassGuid ) / \
- sizeof ( ( ( type * ) NULL )->ClassGuid[0] ) ), \
- }, \
- .ClassGuid = { \
- __VA_ARGS__ \
- }, \
- }
-
-/**
- * Define an EFI IFR GUID class
- *
- * @v class Class
- * @ret ifr GUID class
- */
-#define EFI_IFR_GUID_CLASS( class ) { \
- .Header = { \
- .OpCode = EFI_IFR_GUID_OP, \
- .Length = sizeof ( EFI_IFR_GUID_CLASS ), \
- }, \
- .Guid = EFI_IFR_TIANO_GUID, \
- .ExtendOpCode = EFI_IFR_EXTEND_OP_CLASS, \
- .Class = class, \
- }
-
-/**
- * Define an EFI IFR GUID subclass
- *
- * @v subclass Subclass
- * @ret ifr GUID subclass
- */
-#define EFI_IFR_GUID_SUBCLASS( subclass ) { \
- .Header = { \
- .OpCode = EFI_IFR_GUID_OP, \
- .Length = sizeof ( EFI_IFR_GUID_SUBCLASS ), \
- }, \
- .Guid = EFI_IFR_TIANO_GUID, \
- .ExtendOpCode = EFI_IFR_EXTEND_OP_SUBCLASS, \
- .SubClass = subclass, \
- }
-
-/**
- * Define an EFI IFR form
- *
- * @v formid Form ID
- * @v title Title string
- * @ret ifr Form
- *
- * This definition opens a new scope, which must be closed by an
- * EFI_IFR_END().
- */
-#define EFI_IFR_FORM( formid, title ) { \
- .Header = { \
- .OpCode = EFI_IFR_FORM_OP, \
- .Length = sizeof ( EFI_IFR_FORM ), \
- .Scope = 1, \
- }, \
- .FormId = formid, \
- .FormTitle = title, \
- }
-
-/**
- * Define an EFI IFR text widget
- *
- * @v prompt Prompt string
- * @v help Help string
- * @v text Text string
- * @ret ifr Text widget
- */
-#define EFI_IFR_TEXT( prompt, help, text ) { \
- .Header = { \
- .OpCode = EFI_IFR_TEXT_OP, \
- .Length = sizeof ( EFI_IFR_TEXT ), \
- }, \
- .Statement = { \
- .Prompt = prompt, \
- .Help = help, \
- }, \
- .TextTwo = text, \
- }
-
-/**
- * Define an EFI IFR end marker
- *
- * @ret ifr End marker
- */
-#define EFI_IFR_END() { \
- .Header = { \
- .OpCode = EFI_IFR_END_OP, \
- .Length = sizeof ( EFI_IFR_END ), \
- }, \
- }
+/** GUID indicating formset compliance for IBM Unified Configuration Manager */
+#define EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID \
+ { 0x5c8e9746, 0xa5f7, 0x4593, \
+ { 0xaf, 0x1f, 0x66, 0xa8, 0x2a, 0xa1, 0x9c, 0xb1 } }
+
+/** An EFI IFR builder */
+struct efi_ifr_builder {
+ /** IFR opcodes */
+ EFI_IFR_OP_HEADER *ops;
+ /** Length of IFR opcodes */
+ size_t ops_len;
+ /** Strings */
+ EFI_HII_STRING_BLOCK *strings;
+ /** Length of strings */
+ size_t strings_len;
+ /** Current string identifier */
+ unsigned int string_id;
+ /** Current variable store identifier */
+ unsigned int varstore_id;
+ /** Current form identifier */
+ unsigned int form_id;
+ /** An allocation has failed */
+ int failed;
+};
+
+/**
+ * Initialise IFR builder
+ *
+ * @v ifr IFR builder
+ *
+ * The caller must eventually call efi_ifr_free() to free the dynamic
+ * storage associated with the IFR builder.
+ */
+static inline void efi_ifr_init ( struct efi_ifr_builder *ifr ) {
+ memset ( ifr, 0, sizeof ( *ifr ) );
+}
+
+extern unsigned int efi_ifr_string ( struct efi_ifr_builder *ifr,
+ const char *fmt, ... );
+extern void efi_ifr_end_op ( struct efi_ifr_builder *ifr );
+extern void efi_ifr_false_op ( struct efi_ifr_builder *ifr );
+extern unsigned int efi_ifr_form_op ( struct efi_ifr_builder *ifr,
+ unsigned int title_id );
+extern void efi_ifr_form_set_op ( struct efi_ifr_builder *ifr,
+ const EFI_GUID *guid,
+ unsigned int title_id, unsigned int help_id,
+ ... );
+void efi_ifr_get_op ( struct efi_ifr_builder *ifr, unsigned int varstore_id,
+ unsigned int varstore_info, unsigned int varstore_type );
+extern void efi_ifr_guid_class_op ( struct efi_ifr_builder *ifr,
+ unsigned int class );
+extern void efi_ifr_guid_subclass_op ( struct efi_ifr_builder *ifr,
+ unsigned int subclass );
+extern void efi_ifr_numeric_op ( struct efi_ifr_builder *ifr,
+ unsigned int prompt_id,
+ unsigned int help_id, unsigned int question_id,
+ unsigned int varstore_id,
+ unsigned int varstore_info,
+ unsigned int vflags, unsigned long min_value,
+ unsigned long max_value, unsigned int step,
+ unsigned int flags );
+extern void efi_ifr_string_op ( struct efi_ifr_builder *ifr,
+ unsigned int prompt_id, unsigned int help_id,
+ unsigned int question_id,
+ unsigned int varstore_id,
+ unsigned int varstore_info, unsigned int vflags,
+ unsigned int min_size, unsigned int max_size,
+ unsigned int flags );
+extern void efi_ifr_suppress_if_op ( struct efi_ifr_builder *ifr );
+extern void efi_ifr_text_op ( struct efi_ifr_builder *ifr,
+ unsigned int prompt_id, unsigned int help_id,
+ unsigned int text_id );
+extern void efi_ifr_true_op ( struct efi_ifr_builder *ifr );
+extern unsigned int
+efi_ifr_varstore_name_value_op ( struct efi_ifr_builder *ifr,
+ const EFI_GUID *guid );
+extern void efi_ifr_free ( struct efi_ifr_builder *ifr );
+extern EFI_HII_PACKAGE_LIST_HEADER *
+efi_ifr_package ( struct efi_ifr_builder *ifr, const EFI_GUID *guid,
+ const char *language, unsigned int language_id );
#endif /* _IPXE_EFI_HII_H */
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/efi/efi_snp.h
^
|
@@ -0,0 +1,75 @@
+#ifndef _IPXE_EFI_SNP_H
+#define _IPXE_EFI_SNP_H
+
+/** @file
+ *
+ * iPXE EFI SNP interface
+ *
+ */
+
+#include <ipxe/list.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/Protocol/SimpleNetwork.h>
+#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
+#include <ipxe/efi/Protocol/ComponentName2.h>
+#include <ipxe/efi/Protocol/DevicePath.h>
+#include <ipxe/efi/Protocol/HiiConfigAccess.h>
+#include <ipxe/efi/Protocol/HiiDatabase.h>
+
+/** An SNP device */
+struct efi_snp_device {
+ /** List of SNP devices */
+ struct list_head list;
+ /** The underlying iPXE network device */
+ struct net_device *netdev;
+ /** The underlying EFI PCI device */
+ struct efi_pci_device *efipci;
+ /** EFI device handle */
+ EFI_HANDLE handle;
+ /** The SNP structure itself */
+ EFI_SIMPLE_NETWORK_PROTOCOL snp;
+ /** The SNP "mode" (parameters) */
+ EFI_SIMPLE_NETWORK_MODE mode;
+ /** Outstanding TX packet count (via "interrupt status")
+ *
+ * Used in order to generate TX completions.
+ */
+ unsigned int tx_count_interrupts;
+ /** Outstanding TX packet count (via "recycled tx buffers")
+ *
+ * Used in order to generate TX completions.
+ */
+ unsigned int tx_count_txbufs;
+ /** Outstanding RX packet count (via "interrupt status") */
+ unsigned int rx_count_interrupts;
+ /** Outstanding RX packet count (via WaitForPacket event) */
+ unsigned int rx_count_events;
+ /** The network interface identifier */
+ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii;
+ /** Component name protocol */
+ EFI_COMPONENT_NAME2_PROTOCOL name2;
+ /** HII configuration access protocol */
+ EFI_HII_CONFIG_ACCESS_PROTOCOL hii;
+ /** HII package list */
+ EFI_HII_PACKAGE_LIST_HEADER *package_list;
+ /** HII handle */
+ EFI_HII_HANDLE hii_handle;
+ /** Device name */
+ wchar_t name[ sizeof ( ( ( struct net_device * ) NULL )->name ) ];
+ /** Driver name */
+ wchar_t driver_name[16];
+ /** Controller name */
+ wchar_t controller_name[32];
+ /** The device path
+ *
+ * This field is variable in size and must appear at the end
+ * of the structure.
+ */
+ EFI_DEVICE_PATH_PROTOCOL path;
+};
+
+extern int efi_snp_hii_install ( struct efi_snp_device *snpdev );
+extern void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev );
+
+#endif /* _IPXE_EFI_SNP_H */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/errfile.h
^
|
@@ -262,6 +262,9 @@
#define ERRFILE_menu_cmd ( ERRFILE_OTHER | 0x002d0000 )
#define ERRFILE_validator ( ERRFILE_OTHER | 0x002e0000 )
#define ERRFILE_ocsp ( ERRFILE_OTHER | 0x002f0000 )
+#define ERRFILE_nslookup ( ERRFILE_OTHER | 0x00300000 )
+#define ERRFILE_efi_snp_hii ( ERRFILE_OTHER | 0x00310000 )
+#define ERRFILE_readline ( ERRFILE_OTHER | 0x00320000 )
/** @} */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/ethernet.h
^
|
@@ -79,6 +79,7 @@
( ! is_zero_ether_addr ( addr ) ) );
}
+extern uint8_t eth_broadcast[];
extern int eth_push ( struct net_device *netdev, struct io_buffer *iobuf,
const void *ll_dest, const void *ll_source,
uint16_t net_proto );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/features.h
^
|
@@ -53,6 +53,7 @@
#define DHCP_EB_FEATURE_FCOE 0x25 /**< FCoE protocol */
#define DHCP_EB_FEATURE_VLAN 0x26 /**< VLAN support */
#define DHCP_EB_FEATURE_MENU 0x27 /**< Menu support */
+#define DHCP_EB_FEATURE_SDI 0x28 /**< SDI image support */
/** @} */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/ib_packet.h
^
|
@@ -152,9 +152,10 @@
extern int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf,
struct ib_queue_pair *qp, size_t payload_len,
- const struct ib_address_vector *av );
+ const struct ib_address_vector *dest );
extern int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf,
struct ib_queue_pair **qp, size_t *payload_len,
- struct ib_address_vector *av );
+ struct ib_address_vector *dest,
+ struct ib_address_vector *source );
#endif /* _IPXE_IB_PACKET_H */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/infiniband.h
^
|
@@ -142,6 +142,16 @@
IB_QPT_ETH,
};
+/** Infiniband queue pair operations */
+struct ib_queue_pair_operations {
+ /** Allocate receive I/O buffer
+ *
+ * @v len Maximum receive length
+ * @ret iobuf I/O buffer (or NULL if out of memory)
+ */
+ struct io_buffer * ( * alloc_iob ) ( size_t len );
+};
+
/** An Infiniband Queue Pair */
struct ib_queue_pair {
/** Containing Infiniband device */
@@ -169,6 +179,8 @@
struct list_head mgids;
/** Address vector */
struct ib_address_vector av;
+ /** Queue pair operations */
+ struct ib_queue_pair_operations *op;
/** Driver private data */
void *drv_priv;
/** Queue owner private data */
@@ -193,13 +205,15 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector, or NULL
+ * @v dest Destination address vector, or NULL
+ * @v source Source address vector, or NULL
* @v iobuf I/O buffer
* @v rc Completion status code
*/
void ( * complete_recv ) ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
+ struct ib_address_vector *source,
struct io_buffer *iobuf, int rc );
};
@@ -277,7 +291,7 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @ret rc Return status code
*
@@ -288,7 +302,7 @@
*/
int ( * post_send ) ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf );
/** Post receive work queue entry
*
@@ -478,8 +492,8 @@
extern struct ib_queue_pair *
ib_create_qp ( struct ib_device *ibdev, enum ib_queue_pair_type type,
unsigned int num_send_wqes, struct ib_completion_queue *send_cq,
- unsigned int num_recv_wqes,
- struct ib_completion_queue *recv_cq );
+ unsigned int num_recv_wqes, struct ib_completion_queue *recv_cq,
+ struct ib_queue_pair_operations *op );
extern int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp );
extern void ib_destroy_qp ( struct ib_device *ibdev,
struct ib_queue_pair *qp );
@@ -490,7 +504,7 @@
extern struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
unsigned long qpn, int is_send );
extern int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf );
extern int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
struct io_buffer *iobuf );
@@ -499,7 +513,8 @@
struct io_buffer *iobuf, int rc );
extern void ib_complete_recv ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
+ struct ib_address_vector *source,
struct io_buffer *iobuf, int rc );
extern void ib_refill_recv ( struct ib_device *ibdev,
struct ib_queue_pair *qp );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/iobuf.h
^
|
@@ -210,6 +210,8 @@
(iobuf) = NULL; \
__iobuf; } )
+extern struct io_buffer * __malloc alloc_iob_raw ( size_t len, size_t align,
+ size_t offset );
extern struct io_buffer * __malloc alloc_iob ( size_t len );
extern void free_iob ( struct io_buffer *iobuf );
extern void iob_pad ( struct io_buffer *iobuf, size_t min_len );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/ipoib.h
^
|
@@ -8,6 +8,7 @@
FILE_LICENCE ( GPL2_OR_LATER );
+#include <ipxe/if_arp.h>
#include <ipxe/infiniband.h>
/** IPoIB MAC address length */
@@ -33,25 +34,32 @@
/** Network-layer protocol */
uint16_t proto;
/** Reserved, must be zero */
- union {
- /** Reserved, must be zero */
- uint16_t reserved;
- /** Peer addresses
- *
- * We use these fields internally to represent the
- * peer addresses using a lookup key. There simply
- * isn't enough room in the IPoIB header to store
- * literal source or destination MAC addresses.
- */
- struct {
- /** Destination address key */
- uint8_t dest;
- /** Source address key */
- uint8_t src;
- } __attribute__ (( packed )) peer;
- } __attribute__ (( packed )) u;
+ uint16_t reserved;
} __attribute__ (( packed ));
+/** GUID mask used for constructing eIPoIB Local Ethernet MAC address (LEMAC) */
+#define IPOIB_GUID_MASK 0xe7
+
+/** eIPoIB Remote Ethernet MAC address
+ *
+ * An eIPoIB REMAC address is an Ethernet-like (6 byte) link-layer
+ * pseudo-address used to look up a full IPoIB link-layer address.
+ */
+struct ipoib_remac {
+ /** Remote QPN
+ *
+ * Must be ORed with EIPOIB_QPN_LA so that eIPoIB REMAC
+ * addresses are considered as locally-assigned Ethernet MAC
+ * addreses.
+ */
+ uint32_t qpn;
+ /** Remote LID */
+ uint16_t lid;
+} __attribute__ (( packed ));
+
+/** eIPoIB REMAC locally-assigned address indicator */
+#define EIPOIB_QPN_LA 0x02000000UL
+
extern const char * ipoib_ntoa ( const void *ll_addr );
extern struct net_device * alloc_ipoibdev ( size_t priv_size );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/malloc.h
^
|
@@ -23,7 +23,8 @@
extern size_t freemem;
-extern void * __malloc alloc_memblock ( size_t size, size_t align );
+extern void * __malloc alloc_memblock ( size_t size, size_t align,
+ size_t offset );
extern void free_memblock ( void *ptr, size_t size );
extern void mpopulate ( void *start, size_t len );
extern void mdumpfree ( void );
@@ -33,20 +34,38 @@
*
* @v size Requested size
* @v align Physical alignment
+ * @v offset Offset from physical alignment
* @ret ptr Memory, or NULL
*
* Allocates physically-aligned memory for DMA.
*
* @c align must be a power of two. @c size may not be zero.
*/
-static inline void * __malloc malloc_dma ( size_t size, size_t phys_align ) {
- void * ptr = alloc_memblock ( size, phys_align );
+static inline void * __malloc malloc_dma_offset ( size_t size,
+ size_t phys_align,
+ size_t offset ) {
+ void * ptr = alloc_memblock ( size, phys_align, offset );
if ( ptr && size )
VALGRIND_MALLOCLIKE_BLOCK ( ptr, size, 0, 0 );
return ptr;
}
/**
+ * Allocate memory for DMA
+ *
+ * @v size Requested size
+ * @v align Physical alignment
+ * @ret ptr Memory, or NULL
+ *
+ * Allocates physically-aligned memory for DMA.
+ *
+ * @c align must be a power of two. @c size may not be zero.
+ */
+static inline void * __malloc malloc_dma ( size_t size, size_t phys_align ) {
+ return malloc_dma_offset ( size, phys_align, 0 );
+}
+
+/**
* Free memory allocated with malloc_dma()
*
* @v ptr Memory allocated by malloc_dma(), or NULL
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/mii.h
^
|
@@ -81,6 +81,7 @@
/** Maximum time to wait for a reset, in milliseconds */
#define MII_RESET_MAX_WAIT_MS 500
+extern int mii_restart ( struct mii_interface *mii );
extern int mii_reset ( struct mii_interface *mii );
#endif /* _IPXE_MII_H */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/netdevice.h
^
|
@@ -188,8 +188,17 @@
uint8_t ll_addr_len;
/** Link-layer header length */
uint8_t ll_header_len;
+ /** Flags */
+ unsigned int flags;
};
+/** Local link-layer address functions only as a name
+ *
+ * This flag indicates that the local link-layer address cannot
+ * directly be used as a destination address by a remote node.
+ */
+#define LL_NAME_ONLY 0x0001
+
/** Network device operations */
struct net_device_operations {
/** Open network device
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/nvo.h
^
|
@@ -42,6 +42,10 @@
struct dhcp_options dhcpopts;
};
+/** Name of non-volatile options settings block */
+#define NVO_SETTINGS_NAME "nvo"
+
+extern int nvo_applies ( struct settings *settings, struct setting *setting );
extern void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
size_t address, size_t len,
int ( * resize ) ( struct nvo_block *nvo, size_t len ),
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/retry.h
^
|
@@ -85,6 +85,7 @@
extern void start_timer_fixed ( struct retry_timer *timer,
unsigned long timeout );
extern void stop_timer ( struct retry_timer *timer );
+extern void retry_poll ( void );
/**
* Start timer with no delay
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/serial.h
^
|
@@ -12,5 +12,6 @@
extern void serial_putc ( int ch );
extern int serial_getc ( void );
extern int serial_ischar ( void );
+extern int serial_initialized;
#endif /* _IPXE_SERIAL_H */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/settings.h
^
|
@@ -269,6 +269,8 @@
extern void clear_settings ( struct settings *settings );
extern int setting_cmp ( struct setting *a, struct setting *b );
+extern struct settings * find_child_settings ( struct settings *parent,
+ const char *name );
extern const char * settings_name ( struct settings *settings );
extern struct settings * find_settings ( const char *name );
extern struct setting * find_setting ( const char *name );
@@ -280,10 +282,16 @@
extern int storef_setting ( struct settings *settings,
struct setting *setting,
const char *value );
-extern int storef_named_setting ( const char *name, const char *value );
+extern int store_named_setting ( const char *name,
+ struct setting_type *default_type,
+ const void *data, size_t len );
+extern int storef_named_setting ( const char *name,
+ struct setting_type *default_type,
+ const char *value );
extern int fetchf_named_setting ( const char *name, char *name_buf,
size_t name_len, char *value_buf,
size_t value_len );
+extern int fetchf_named_setting_copy ( const char *name, char **data );
extern char * expand_settings ( const char *string );
extern struct setting_type setting_type_string __setting_type;
@@ -366,7 +374,7 @@
* @ret rc Return status code
*/
static inline int delete_named_setting ( const char *name ) {
- return storef_named_setting ( name, NULL );
+ return store_named_setting ( name, NULL, NULL, 0 );
}
/**
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/tls.h
^
|
@@ -19,6 +19,7 @@
#include <ipxe/sha256.h>
#include <ipxe/x509.h>
#include <ipxe/pending.h>
+#include <ipxe/iobuf.h>
/** A TLS header */
struct tls_header {
@@ -264,14 +265,35 @@
uint64_t rx_seq;
/** RX state */
enum tls_rx_state rx_state;
- /** Offset within current RX state */
- size_t rx_rcvd;
/** Current received record header */
struct tls_header rx_header;
- /** Current received raw data buffer */
- void *rx_data;
+ /** Current received record header (static I/O buffer) */
+ struct io_buffer rx_header_iobuf;
+ /** List of received data buffers */
+ struct list_head rx_data;
};
+/** RX I/O buffer size
+ *
+ * The maximum fragment length extension is optional, and many common
+ * implementations (including OpenSSL) do not support it. We must
+ * therefore be prepared to receive records of up to 16kB in length.
+ * The chance of an allocation of this size failing is non-negligible,
+ * so we must split received data into smaller allocations.
+ */
+#define TLS_RX_BUFSIZE 4096
+
+/** Minimum RX I/O buffer size
+ *
+ * To simplify manipulations, we ensure that no RX I/O buffer is
+ * smaller than this size. This allows us to assume that the MAC and
+ * padding are entirely contained within the final I/O buffer.
+ */
+#define TLS_RX_MIN_BUFSIZE 512
+
+/** RX I/O buffer alignment */
+#define TLS_RX_ALIGN 16
+
extern int add_tls ( struct interface *xfer, const char *name,
struct interface **next );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/readline/readline.h
^
|
@@ -50,8 +50,8 @@
};
extern void history_free ( struct readline_history *history );
-extern char * __malloc readline_history ( const char *prompt,
- struct readline_history *history );
+extern int readline_history ( const char *prompt, const char *prefill,
+ struct readline_history *history, char **line );
extern char * __malloc readline ( const char *prompt );
#endif /* _READLINE_H */
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/usr/nslookup.h
^
|
@@ -0,0 +1,14 @@
+#ifndef _USR_NSLOOKUP_H
+#define _USR_NSLOOKUP_H
+
+/** @file
+ *
+ * Standalone name resolution
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern int nslookup ( const char *name, const char *setting_name );
+
+#endif /* _USR_NSLOOKUP_H */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/wchar.h
^
|
@@ -24,4 +24,6 @@
return 1;
}
+extern size_t wcslen ( const wchar_t *string );
+
#endif /* WCHAR_H */
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/interface/efi/efi_hii.c
^
|
@@ -0,0 +1,577 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_strings.h>
+#include <ipxe/efi/efi_hii.h>
+
+/** Tiano GUID */
+static const EFI_GUID tiano_guid = EFI_IFR_TIANO_GUID;
+
+/**
+ * Add string to IFR builder
+ *
+ * @v ifr IFR builder
+ * @v fmt Format string
+ * @v ... Arguments
+ * @ret string_id String identifier, or zero on failure
+ */
+unsigned int efi_ifr_string ( struct efi_ifr_builder *ifr, const char *fmt,
+ ... ) {
+ EFI_HII_STRING_BLOCK *new_strings;
+ EFI_HII_SIBT_STRING_UCS2_BLOCK *ucs2;
+ size_t new_strings_len;
+ va_list args;
+ size_t len;
+ unsigned int string_id;
+
+ /* Do nothing if a previous allocation has failed */
+ if ( ifr->failed )
+ return 0;
+
+ /* Calculate string length */
+ va_start ( args, fmt );
+ len = ( efi_vsnprintf ( NULL, 0, fmt, args ) + 1 /* wNUL */ );
+ va_end ( args );
+
+ /* Reallocate strings */
+ new_strings_len = ( ifr->strings_len +
+ offsetof ( typeof ( *ucs2 ), StringText ) +
+ ( len * sizeof ( ucs2->StringText[0] ) ) );
+ new_strings = realloc ( ifr->strings, new_strings_len );
+ if ( ! new_strings ) {
+ ifr->failed = 1;
+ return 0;
+ }
+ ucs2 = ( ( ( void * ) new_strings ) + ifr->strings_len );
+ ifr->strings = new_strings;
+ ifr->strings_len = new_strings_len;
+
+ /* Fill in string */
+ ucs2->Header.BlockType = EFI_HII_SIBT_STRING_UCS2;
+ va_start ( args, fmt );
+ efi_vsnprintf ( ucs2->StringText, len, fmt, args );
+ va_end ( args );
+
+ /* Allocate string ID */
+ string_id = ++(ifr->string_id);
+
+ DBGC ( ifr, "IFR %p string %#04x is \"%ls\"\n",
+ ifr, string_id, ucs2->StringText );
+ return string_id;
+}
+
+/**
+ * Add IFR opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ * @v opcode Opcode
+ * @v len Opcode length
+ * @ret op Opcode, or NULL
+ */
+static void * efi_ifr_op ( struct efi_ifr_builder *ifr, unsigned int opcode,
+ size_t len ) {
+ EFI_IFR_OP_HEADER *new_ops;
+ EFI_IFR_OP_HEADER *op;
+ size_t new_ops_len;
+
+ /* Do nothing if a previous allocation has failed */
+ if ( ifr->failed )
+ return NULL;
+
+ /* Reallocate opcodes */
+ new_ops_len = ( ifr->ops_len + len );
+ new_ops = realloc ( ifr->ops, new_ops_len );
+ if ( ! new_ops ) {
+ ifr->failed = 1;
+ return NULL;
+ }
+ op = ( ( ( void * ) new_ops ) + ifr->ops_len );
+ ifr->ops = new_ops;
+ ifr->ops_len = new_ops_len;
+
+ /* Fill in opcode header */
+ op->OpCode = opcode;
+ op->Length = len;
+
+ return op;
+}
+
+/**
+ * Add end opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ */
+void efi_ifr_end_op ( struct efi_ifr_builder *ifr ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_END *end;
+
+ /* Add opcode */
+ end = efi_ifr_op ( ifr, EFI_IFR_END_OP, sizeof ( *end ) );
+
+ DBGC ( ifr, "IFR %p end\n", ifr );
+ DBGC2_HDA ( ifr, dispaddr, end, sizeof ( *end ) );
+}
+
+/**
+ * Add false opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ */
+void efi_ifr_false_op ( struct efi_ifr_builder *ifr ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_FALSE *false;
+
+ /* Add opcode */
+ false = efi_ifr_op ( ifr, EFI_IFR_FALSE_OP, sizeof ( *false ) );
+
+ DBGC ( ifr, "IFR %p false\n", ifr );
+ DBGC2_HDA ( ifr, dispaddr, false, sizeof ( *false ) );
+}
+
+/**
+ * Add form opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ * @v title_id Title string identifier
+ * @ret form_id Form identifier
+ */
+unsigned int efi_ifr_form_op ( struct efi_ifr_builder *ifr,
+ unsigned int title_id ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_FORM *form;
+
+ /* Add opcode */
+ form = efi_ifr_op ( ifr, EFI_IFR_FORM_OP, sizeof ( *form ) );
+ if ( ! form )
+ return 0;
+ form->Header.Scope = 1;
+ form->FormId = ++(ifr->form_id);
+ form->FormTitle = title_id;
+
+ DBGC ( ifr, "IFR %p name/value store %#04x title %#04x\n",
+ ifr, form->FormId, title_id );
+ DBGC2_HDA ( ifr, dispaddr, form, sizeof ( *form ) );
+ return form->FormId;
+}
+
+/**
+ * Add formset opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ * @v guid GUID
+ * @v title_id Title string identifier
+ * @v help_id Help string identifier
+ * @v ... Class GUIDs (terminated by NULL)
+ */
+void efi_ifr_form_set_op ( struct efi_ifr_builder *ifr, const EFI_GUID *guid,
+ unsigned int title_id, unsigned int help_id, ... ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_FORM_SET *formset;
+ EFI_GUID *class_guid;
+ unsigned int num_class_guids = 0;
+ size_t len;
+ va_list args;
+
+ /* Count number of class GUIDs */
+ va_start ( args, help_id );
+ while ( va_arg ( args, const EFI_GUID * ) != NULL )
+ num_class_guids++;
+ va_end ( args );
+
+ /* Add opcode */
+ len = ( sizeof ( *formset ) +
+ ( num_class_guids * sizeof ( *class_guid ) ) );
+ formset = efi_ifr_op ( ifr, EFI_IFR_FORM_SET_OP, len );
+ if ( ! formset )
+ return;
+ formset->Header.Scope = 1;
+ memcpy ( &formset->Guid, guid, sizeof ( formset->Guid ) );
+ formset->FormSetTitle = title_id;
+ formset->Help = help_id;
+ formset->Flags = num_class_guids;
+
+ /* Add class GUIDs */
+ class_guid = ( ( ( void * ) formset ) + sizeof ( *formset ) );
+ va_start ( args, help_id );
+ while ( num_class_guids-- ) {
+ memcpy ( class_guid++, va_arg ( args, const EFI_GUID * ),
+ sizeof ( *class_guid ) );
+ }
+ va_end ( args );
+
+ DBGC ( ifr, "IFR %p formset title %#04x help %#04x\n",
+ ifr, title_id, help_id );
+ DBGC2_HDA ( ifr, dispaddr, formset, len );
+}
+
+/**
+ * Add get opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ * @v varstore_id Variable store identifier
+ * @v varstore_info Variable string identifier or offset
+ * @v varstore_type Variable type
+ */
+void efi_ifr_get_op ( struct efi_ifr_builder *ifr, unsigned int varstore_id,
+ unsigned int varstore_info, unsigned int varstore_type ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_GET *get;
+
+ /* Add opcode */
+ get = efi_ifr_op ( ifr, EFI_IFR_GET_OP, sizeof ( *get ) );
+ get->VarStoreId = varstore_id;
+ get->VarStoreInfo.VarName = varstore_info;
+ get->VarStoreType = varstore_type;
+
+ DBGC ( ifr, "IFR %p get varstore %#04x:%#04x type %#02x\n",
+ ifr, varstore_id, varstore_info, varstore_type );
+ DBGC2_HDA ( ifr, dispaddr, get, sizeof ( *get ) );
+}
+
+/**
+ * Add GUID class opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ * @v class Class
+ */
+void efi_ifr_guid_class_op ( struct efi_ifr_builder *ifr, unsigned int class ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_GUID_CLASS *guid_class;
+
+ /* Add opcode */
+ guid_class = efi_ifr_op ( ifr, EFI_IFR_GUID_OP,
+ sizeof ( *guid_class ) );
+ if ( ! guid_class )
+ return;
+ memcpy ( &guid_class->Guid, &tiano_guid, sizeof ( guid_class->Guid ) );
+ guid_class->ExtendOpCode = EFI_IFR_EXTEND_OP_CLASS;
+ guid_class->Class = class;
+
+ DBGC ( ifr, "IFR %p GUID class %#02x\n", ifr, class );
+ DBGC2_HDA ( ifr, dispaddr, guid_class, sizeof ( *guid_class ) );
+}
+
+/**
+ * Add GUID subclass opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ * @v subclass Subclass
+ */
+void efi_ifr_guid_subclass_op ( struct efi_ifr_builder *ifr,
+ unsigned int subclass ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_GUID_SUBCLASS *guid_subclass;
+
+ /* Add opcode */
+ guid_subclass = efi_ifr_op ( ifr, EFI_IFR_GUID_OP,
+ sizeof ( *guid_subclass ) );
+ if ( ! guid_subclass )
+ return;
+ memcpy ( &guid_subclass->Guid, &tiano_guid,
+ sizeof ( guid_subclass->Guid ) );
+ guid_subclass->ExtendOpCode = EFI_IFR_EXTEND_OP_SUBCLASS;
+ guid_subclass->SubClass = subclass;
+
+ DBGC ( ifr, "IFR %p GUID subclass %#02x\n", ifr, subclass );
+ DBGC2_HDA ( ifr, dispaddr, guid_subclass, sizeof ( *guid_subclass ) );
+}
+
+/**
+ * Add numeric opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ * @v prompt_id Prompt string identifier
+ * @v help_id Help string identifier
+ * @v question_id Question identifier
+ * @v varstore_id Variable store identifier
+ * @v varstore_info Variable string identifier or offset
+ * @v vflags Variable flags
+ * @v min_value Minimum value
+ * @v max_value Maximum value
+ * @v step Step
+ * @v flags Flags
+ */
+void efi_ifr_numeric_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id,
+ unsigned int help_id, unsigned int question_id,
+ unsigned int varstore_id, unsigned int varstore_info,
+ unsigned int vflags, unsigned long min_value,
+ unsigned long max_value, unsigned int step,
+ unsigned int flags ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_NUMERIC *numeric;
+ unsigned int size;
+
+ /* Add opcode */
+ numeric = efi_ifr_op ( ifr, EFI_IFR_NUMERIC_OP, sizeof ( *numeric ) );
+ if ( ! numeric )
+ return;
+ numeric->Question.Header.Prompt = prompt_id;
+ numeric->Question.Header.Help = help_id;
+ numeric->Question.QuestionId = question_id;
+ numeric->Question.VarStoreId = varstore_id;
+ numeric->Question.VarStoreInfo.VarName = varstore_info;
+ numeric->Question.Flags = vflags;
+ size = ( flags & EFI_IFR_NUMERIC_SIZE );
+ switch ( size ) {
+ case EFI_IFR_NUMERIC_SIZE_1 :
+ numeric->data.u8.MinValue = min_value;
+ numeric->data.u8.MaxValue = max_value;
+ numeric->data.u8.Step = step;
+ break;
+ case EFI_IFR_NUMERIC_SIZE_2 :
+ numeric->data.u16.MinValue = min_value;
+ numeric->data.u16.MaxValue = max_value;
+ numeric->data.u16.Step = step;
+ break;
+ case EFI_IFR_NUMERIC_SIZE_4 :
+ numeric->data.u32.MinValue = min_value;
+ numeric->data.u32.MaxValue = max_value;
+ numeric->data.u32.Step = step;
+ break;
+ case EFI_IFR_NUMERIC_SIZE_8 :
+ numeric->data.u64.MinValue = min_value;
+ numeric->data.u64.MaxValue = max_value;
+ numeric->data.u64.Step = step;
+ break;
+ }
+
+ DBGC ( ifr, "IFR %p numeric prompt %#04x help %#04x question %#04x "
+ "varstore %#04x:%#04x\n", ifr, prompt_id, help_id, question_id,
+ varstore_id, varstore_info );
+ DBGC2_HDA ( ifr, dispaddr, numeric, sizeof ( *numeric ) );
+}
+
+/**
+ * Add string opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ * @v prompt_id Prompt string identifier
+ * @v help_id Help string identifier
+ * @v question_id Question identifier
+ * @v varstore_id Variable store identifier
+ * @v varstore_info Variable string identifier or offset
+ * @v vflags Variable flags
+ * @v min_size Minimum size
+ * @v max_size Maximum size
+ * @v flags Flags
+ */
+void efi_ifr_string_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id,
+ unsigned int help_id, unsigned int question_id,
+ unsigned int varstore_id, unsigned int varstore_info,
+ unsigned int vflags, unsigned int min_size,
+ unsigned int max_size, unsigned int flags ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_STRING *string;
+
+ /* Add opcode */
+ string = efi_ifr_op ( ifr, EFI_IFR_STRING_OP, sizeof ( *string ) );
+ if ( ! string )
+ return;
+ string->Question.Header.Prompt = prompt_id;
+ string->Question.Header.Help = help_id;
+ string->Question.QuestionId = question_id;
+ string->Question.VarStoreId = varstore_id;
+ string->Question.VarStoreInfo.VarName = varstore_info;
+ string->Question.Flags = vflags;
+ string->MinSize = min_size;
+ string->MaxSize = max_size;
+ string->Flags = flags;
+
+ DBGC ( ifr, "IFR %p string prompt %#04x help %#04x question %#04x "
+ "varstore %#04x:%#04x\n", ifr, prompt_id, help_id, question_id,
+ varstore_id, varstore_info );
+ DBGC2_HDA ( ifr, dispaddr, string, sizeof ( *string ) );
+}
+
+/**
+ * Add suppress-if opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ */
+void efi_ifr_suppress_if_op ( struct efi_ifr_builder *ifr ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_SUPPRESS_IF *suppress_if;
+
+ /* Add opcode */
+ suppress_if = efi_ifr_op ( ifr, EFI_IFR_SUPPRESS_IF_OP,
+ sizeof ( *suppress_if ) );
+ suppress_if->Header.Scope = 1;
+
+ DBGC ( ifr, "IFR %p suppress-if\n", ifr );
+ DBGC2_HDA ( ifr, dispaddr, suppress_if, sizeof ( *suppress_if ) );
+}
+
+/**
+ * Add text opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ * @v prompt_id Prompt string identifier
+ * @v help_id Help string identifier
+ * @v text_id Text string identifier
+ */
+void efi_ifr_text_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id,
+ unsigned int help_id, unsigned int text_id ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_TEXT *text;
+
+ /* Add opcode */
+ text = efi_ifr_op ( ifr, EFI_IFR_TEXT_OP, sizeof ( *text ) );
+ if ( ! text )
+ return;
+ text->Statement.Prompt = prompt_id;
+ text->Statement.Help = help_id;
+ text->TextTwo = text_id;
+
+ DBGC ( ifr, "IFR %p text prompt %#04x help %#04x text %#04x\n",
+ ifr, prompt_id, help_id, text_id );
+ DBGC2_HDA ( ifr, dispaddr, text, sizeof ( *text ) );
+}
+
+/**
+ * Add true opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ */
+void efi_ifr_true_op ( struct efi_ifr_builder *ifr ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_TRUE *true;
+
+ /* Add opcode */
+ true = efi_ifr_op ( ifr, EFI_IFR_TRUE_OP, sizeof ( *true ) );
+
+ DBGC ( ifr, "IFR %p true\n", ifr );
+ DBGC2_HDA ( ifr, dispaddr, true, sizeof ( *true ) );
+}
+
+/**
+ * Add name/value store opcode to IFR builder
+ *
+ * @v ifr IFR builder
+ * @v guid GUID
+ * @ret varstore_id Variable store identifier, or 0 on failure
+ */
+unsigned int efi_ifr_varstore_name_value_op ( struct efi_ifr_builder *ifr,
+ const EFI_GUID *guid ) {
+ size_t dispaddr = ifr->ops_len;
+ EFI_IFR_VARSTORE_NAME_VALUE *varstore;
+
+ /* Add opcode */
+ varstore = efi_ifr_op ( ifr, EFI_IFR_VARSTORE_NAME_VALUE_OP,
+ sizeof ( *varstore ) );
+ if ( ! varstore )
+ return 0;
+ varstore->VarStoreId = ++(ifr->varstore_id);
+ memcpy ( &varstore->Guid, guid, sizeof ( varstore->Guid ) );
+
+ DBGC ( ifr, "IFR %p name/value store %#04x\n",
+ ifr, varstore->VarStoreId );
+ DBGC2_HDA ( ifr, dispaddr, varstore, sizeof ( *varstore ) );
+ return varstore->VarStoreId;
+}
+
+/**
+ * Free memory used by IFR builder
+ *
+ * @v ifr IFR builder
+ */
+void efi_ifr_free ( struct efi_ifr_builder *ifr ) {
+
+ free ( ifr->ops );
+ free ( ifr->strings );
+ memset ( ifr, 0, sizeof ( *ifr ) );
+}
+
+/**
+ * Construct package list from IFR builder
+ *
+ * @v ifr IFR builder
+ * @v guid Package GUID
+ * @v language Language
+ * @v language_id Language string ID
+ * @ret package Package list, or NULL
+ *
+ * The package list is allocated using malloc(), and must eventually
+ * be freed by the caller. (The caller must also call efi_ifr_free()
+ * to free the temporary storage used during construction.)
+ */
+EFI_HII_PACKAGE_LIST_HEADER * efi_ifr_package ( struct efi_ifr_builder *ifr,
+ const EFI_GUID *guid,
+ const char *language,
+ unsigned int language_id ) {
+ struct {
+ EFI_HII_PACKAGE_LIST_HEADER header;
+ struct {
+ EFI_HII_PACKAGE_HEADER header;
+ uint8_t data[ifr->ops_len];
+ } __attribute__ (( packed )) ops;
+ struct {
+ union {
+ EFI_HII_STRING_PACKAGE_HDR header;
+ uint8_t pad[offsetof(EFI_HII_STRING_PACKAGE_HDR,
+ Language) +
+ strlen ( language ) + 1 /* NUL */ ];
+ } __attribute__ (( packed )) header;
+ uint8_t data[ifr->strings_len];
+ EFI_HII_STRING_BLOCK end;
+ } __attribute__ (( packed )) strings;
+ EFI_HII_PACKAGE_HEADER end;
+ } __attribute__ (( packed )) *package;
+
+ /* Fail if any previous allocation failed */
+ if ( ifr->failed )
+ return NULL;
+
+ /* Allocate package list */
+ package = zalloc ( sizeof ( *package ) );
+ if ( ! package )
+ return NULL;
+
+ /* Populate package list */
+ package->header.PackageLength = sizeof ( *package );
+ memcpy ( &package->header.PackageListGuid, guid,
+ sizeof ( package->header.PackageListGuid ) );
+ package->ops.header.Length = sizeof ( package->ops );
+ package->ops.header.Type = EFI_HII_PACKAGE_FORMS;
+ memcpy ( package->ops.data, ifr->ops, sizeof ( package->ops.data ) );
+ package->strings.header.header.Header.Length =
+ sizeof ( package->strings );
+ package->strings.header.header.Header.Type =
+ EFI_HII_PACKAGE_STRINGS;
+ package->strings.header.header.HdrSize =
+ sizeof ( package->strings.header );
+ package->strings.header.header.StringInfoOffset =
+ sizeof ( package->strings.header );
+ package->strings.header.header.LanguageName = language_id;
+ strcpy ( package->strings.header.header.Language, language );
+ memcpy ( package->strings.data, ifr->strings,
+ sizeof ( package->strings.data ) );
+ package->strings.end.BlockType = EFI_HII_SIBT_END;
+ package->end.Type = EFI_HII_PACKAGE_END;
+ package->end.Length = sizeof ( package->end );
+
+ return &package->header;
+}
+
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/interface/efi/efi_snp.c
^
|
@@ -32,65 +32,7 @@
#include <ipxe/efi/efi_pci.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_strings.h>
-#include <ipxe/efi/efi_hii.h>
-#include <ipxe/efi/Protocol/SimpleNetwork.h>
-#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
-#include <ipxe/efi/Protocol/DevicePath.h>
-#include <ipxe/efi/Protocol/HiiConfigAccess.h>
-#include <ipxe/efi/Protocol/HiiDatabase.h>
-#include <config/general.h>
-
-/** @file
- *
- * iPXE EFI SNP interface
- *
- */
-
-/** An SNP device */
-struct efi_snp_device {
- /** List of SNP devices */
- struct list_head list;
- /** The underlying iPXE network device */
- struct net_device *netdev;
- /** The underlying EFI PCI device */
- struct efi_pci_device *efipci;
- /** EFI device handle */
- EFI_HANDLE handle;
- /** The SNP structure itself */
- EFI_SIMPLE_NETWORK_PROTOCOL snp;
- /** The SNP "mode" (parameters) */
- EFI_SIMPLE_NETWORK_MODE mode;
- /** Outstanding TX packet count (via "interrupt status")
- *
- * Used in order to generate TX completions.
- */
- unsigned int tx_count_interrupts;
- /** Outstanding TX packet count (via "recycled tx buffers")
- *
- * Used in order to generate TX completions.
- */
- unsigned int tx_count_txbufs;
- /** Outstanding RX packet count (via "interrupt status") */
- unsigned int rx_count_interrupts;
- /** Outstanding RX packet count (via WaitForPacket event) */
- unsigned int rx_count_events;
- /** The network interface identifier */
- EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii;
- /** HII configuration access protocol */
- EFI_HII_CONFIG_ACCESS_PROTOCOL hii;
- /** HII package list */
- EFI_HII_PACKAGE_LIST_HEADER *package_list;
- /** HII handle */
- EFI_HII_HANDLE hii_handle;
- /** Device name */
- wchar_t name[ sizeof ( ( ( struct net_device * ) NULL )->name ) ];
- /** The device path
- *
- * This field is variable in size and must appear at the end
- * of the structure.
- */
- EFI_DEVICE_PATH_PROTOCOL path;
-};
+#include <ipxe/efi/efi_snp.h>
/** EFI simple network protocol GUID */
static EFI_GUID efi_simple_network_protocol_guid
@@ -114,6 +56,10 @@
{ 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 }
};
+/** EFI component name protocol */
+static EFI_GUID efi_component_name2_protocol_guid
+ = EFI_COMPONENT_NAME2_PROTOCOL_GUID;
+
/** List of SNP devices */
static LIST_HEAD ( efi_snp_devices );
@@ -536,7 +482,7 @@
container_of ( snp, struct efi_snp_device, snp );
struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
struct io_buffer *iobuf;
- size_t ll_headroom;
+ size_t payload_len;
int rc;
EFI_STATUS efirc;
@@ -589,20 +535,22 @@
}
/* Allocate buffer */
- ll_headroom = ( MAX_LL_HEADER_LEN - ll_header_len );
- iobuf = alloc_iob ( ll_headroom + len );
+ payload_len = ( len - ll_protocol->ll_header_len );
+ iobuf = alloc_iob ( MAX_LL_HEADER_LEN + ( ( payload_len > IOB_ZLEN ) ?
+ payload_len : IOB_ZLEN ) );
if ( ! iobuf ) {
DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte "
"buffer\n", snpdev, ( ( unsigned long ) len ) );
efirc = EFI_DEVICE_ERROR;
goto err_alloc_iob;
}
- iob_reserve ( iobuf, ll_headroom );
+ iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN -
+ ll_protocol->ll_header_len ) );
memcpy ( iob_put ( iobuf, len ), data, len );
/* Create link-layer header, if specified */
if ( ll_header_len ) {
- iob_pull ( iobuf, ll_header_len );
+ iob_pull ( iobuf, ll_protocol->ll_header_len );
if ( ( rc = ll_protocol->push ( snpdev->netdev,
iobuf, ll_dest, ll_src,
htons ( *net_proto ) )) != 0 ){
@@ -759,333 +707,52 @@
/******************************************************************************
*
- * Human Interface Infrastructure
+ * Component name protocol
*
******************************************************************************
*/
-/** EFI configuration access protocol GUID */
-static EFI_GUID efi_hii_config_access_protocol_guid
- = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID;
-
-/** EFI HII database protocol */
-static EFI_HII_DATABASE_PROTOCOL *efihii;
-EFI_REQUIRE_PROTOCOL ( EFI_HII_DATABASE_PROTOCOL, &efihii );
-
-/** Local base GUID used for our EFI SNP formset */
-#define EFI_SNP_FORMSET_GUID_BASE \
- { 0xc4f84019, 0x6dfd, 0x4a27, \
- { 0x9b, 0x94, 0xb7, 0x2e, 0x1f, 0xbc, 0xad, 0xca } }
-
-/** Form identifiers used for our EFI SNP HII */
-enum efi_snp_hii_form_id {
- EFI_SNP_FORM = 0x0001, /**< The only form */
-};
-
-/** String identifiers used for our EFI SNP HII */
-enum efi_snp_hii_string_id {
- /* Language name */
- EFI_SNP_LANGUAGE_NAME = 0x0001,
- /* Formset */
- EFI_SNP_FORMSET_TITLE, EFI_SNP_FORMSET_HELP,
- /* Product name */
- EFI_SNP_PRODUCT_PROMPT, EFI_SNP_PRODUCT_HELP, EFI_SNP_PRODUCT_TEXT,
- /* Version */
- EFI_SNP_VERSION_PROMPT, EFI_SNP_VERSION_HELP, EFI_SNP_VERSION_TEXT,
- /* Driver */
- EFI_SNP_DRIVER_PROMPT, EFI_SNP_DRIVER_HELP, EFI_SNP_DRIVER_TEXT,
- /* Device */
- EFI_SNP_DEVICE_PROMPT, EFI_SNP_DEVICE_HELP, EFI_SNP_DEVICE_TEXT,
- /* End of list */
- EFI_SNP_MAX_STRING_ID
-};
-
-/** EFI SNP formset */
-struct efi_snp_formset {
- EFI_HII_PACKAGE_HEADER Header;
- EFI_IFR_FORM_SET_TYPE(1) FormSet;
- EFI_IFR_GUID_CLASS Class;
- EFI_IFR_GUID_SUBCLASS SubClass;
- EFI_IFR_FORM Form;
- EFI_IFR_TEXT ProductText;
- EFI_IFR_TEXT VersionText;
- EFI_IFR_TEXT DriverText;
- EFI_IFR_TEXT DeviceText;
- EFI_IFR_END EndForm;
- EFI_IFR_END EndFormSet;
-} __attribute__ (( packed )) efi_snp_formset = {
- .Header = {
- .Length = sizeof ( efi_snp_formset ),
- .Type = EFI_HII_PACKAGE_FORMS,
- },
- .FormSet = EFI_IFR_FORM_SET ( EFI_SNP_FORMSET_GUID_BASE,
- EFI_SNP_FORMSET_TITLE,
- EFI_SNP_FORMSET_HELP,
- typeof ( efi_snp_formset.FormSet ),
- EFI_HII_PLATFORM_SETUP_FORMSET_GUID ),
- .Class = EFI_IFR_GUID_CLASS ( EFI_NETWORK_DEVICE_CLASS ),
- .SubClass = EFI_IFR_GUID_SUBCLASS ( 0x03 ),
- .Form = EFI_IFR_FORM ( EFI_SNP_FORM, EFI_SNP_FORMSET_TITLE ),
- .ProductText = EFI_IFR_TEXT ( EFI_SNP_PRODUCT_PROMPT,
- EFI_SNP_PRODUCT_HELP,
- EFI_SNP_PRODUCT_TEXT ),
- .VersionText = EFI_IFR_TEXT ( EFI_SNP_VERSION_PROMPT,
- EFI_SNP_VERSION_HELP,
- EFI_SNP_VERSION_TEXT ),
- .DriverText = EFI_IFR_TEXT ( EFI_SNP_DRIVER_PROMPT,
- EFI_SNP_DRIVER_HELP,
- EFI_SNP_DRIVER_TEXT ),
- .DeviceText = EFI_IFR_TEXT ( EFI_SNP_DEVICE_PROMPT,
- EFI_SNP_DEVICE_HELP,
- EFI_SNP_DEVICE_TEXT ),
- .EndForm = EFI_IFR_END(),
- .EndFormSet = EFI_IFR_END(),
-};
-
-/**
- * Generate EFI SNP string
- *
- * @v wbuf Buffer
- * @v swlen Size of buffer (in wide characters)
- * @v snpdev SNP device
- * @ret wlen Length of string (in wide characters)
- */
-static int efi_snp_string ( wchar_t *wbuf, ssize_t swlen,
- enum efi_snp_hii_string_id id,
- struct efi_snp_device *snpdev ) {
- struct net_device *netdev = snpdev->netdev;
- struct device *dev = netdev->dev;
-
- switch ( id ) {
- case EFI_SNP_LANGUAGE_NAME:
- return efi_ssnprintf ( wbuf, swlen, "English" );
- case EFI_SNP_FORMSET_TITLE:
- return efi_ssnprintf ( wbuf, swlen, "%s (%s)",
- ( PRODUCT_NAME[0] ?
- PRODUCT_NAME : PRODUCT_SHORT_NAME ),
- netdev_addr ( netdev ) );
- case EFI_SNP_FORMSET_HELP:
- return efi_ssnprintf ( wbuf, swlen,
- "Configure " PRODUCT_SHORT_NAME );
- case EFI_SNP_PRODUCT_PROMPT:
- return efi_ssnprintf ( wbuf, swlen, "Name" );
- case EFI_SNP_PRODUCT_HELP:
- return efi_ssnprintf ( wbuf, swlen, "Firmware product name" );
- case EFI_SNP_PRODUCT_TEXT:
- return efi_ssnprintf ( wbuf, swlen, "%s",
- ( PRODUCT_NAME[0] ?
- PRODUCT_NAME : PRODUCT_SHORT_NAME ) );
- case EFI_SNP_VERSION_PROMPT:
- return efi_ssnprintf ( wbuf, swlen, "Version" );
- case EFI_SNP_VERSION_HELP:
- return efi_ssnprintf ( wbuf, swlen, "Firmware version" );
- case EFI_SNP_VERSION_TEXT:
- return efi_ssnprintf ( wbuf, swlen, VERSION );
- case EFI_SNP_DRIVER_PROMPT:
- return efi_ssnprintf ( wbuf, swlen, "Driver" );
- case EFI_SNP_DRIVER_HELP:
- return efi_ssnprintf ( wbuf, swlen, "Firmware driver" );
- case EFI_SNP_DRIVER_TEXT:
- return efi_ssnprintf ( wbuf, swlen, "%s", dev->driver_name );
- case EFI_SNP_DEVICE_PROMPT:
- return efi_ssnprintf ( wbuf, swlen, "Device" );
- case EFI_SNP_DEVICE_HELP:
- return efi_ssnprintf ( wbuf, swlen, "Hardware device" );
- case EFI_SNP_DEVICE_TEXT:
- return efi_ssnprintf ( wbuf, swlen, "%s", dev->name );
- default:
- assert ( 0 );
- return 0;
- }
-}
-
/**
- * Generate EFI SNP string package
+ * Look up driver name
*
- * @v strings String package header buffer
- * @v max_len Buffer length
- * @v snpdev SNP device
- * @ret len Length of string package
- */
-static int efi_snp_strings ( EFI_HII_STRING_PACKAGE_HDR *strings,
- size_t max_len, struct efi_snp_device *snpdev ) {
- static const char language[] = "en-us";
- void *buf = strings;
- ssize_t remaining = max_len;
- size_t hdrsize;
- EFI_HII_SIBT_STRING_UCS2_BLOCK *string;
- ssize_t wremaining;
- size_t string_wlen;
- unsigned int id;
- EFI_HII_STRING_BLOCK *end;
- size_t len;
-
- /* Calculate header size */
- hdrsize = ( offsetof ( typeof ( *strings ), Language ) +
- sizeof ( language ) );
- buf += hdrsize;
- remaining -= hdrsize;
-
- /* Fill in strings */
- for ( id = 1 ; id < EFI_SNP_MAX_STRING_ID ; id++ ) {
- string = buf;
- if ( remaining >= ( ( ssize_t ) sizeof ( string->Header ) ) )
- string->Header.BlockType = EFI_HII_SIBT_STRING_UCS2;
- buf += offsetof ( typeof ( *string ), StringText );
- remaining -= offsetof ( typeof ( *string ), StringText );
- wremaining = ( remaining /
- ( ( ssize_t ) sizeof ( string->StringText[0] )));
- assert ( ! ( ( remaining <= 0 ) && ( wremaining > 0 ) ) );
- string_wlen = efi_snp_string ( string->StringText, wremaining,
- id, snpdev );
- buf += ( ( string_wlen + 1 /* wNUL */ ) *
- sizeof ( string->StringText[0] ) );
- remaining -= ( ( string_wlen + 1 /* wNUL */ ) *
- sizeof ( string->StringText[0] ) );
- }
-
- /* Fill in end marker */
- end = buf;
- if ( remaining >= ( ( ssize_t ) sizeof ( *end ) ) )
- end->BlockType = EFI_HII_SIBT_END;
- buf += sizeof ( *end );
- remaining -= sizeof ( *end );
-
- /* Calculate overall length */
- len = ( max_len - remaining );
-
- /* Fill in string package header */
- if ( strings ) {
- memset ( strings, 0, sizeof ( *strings ) );
- strings->Header.Length = len;
- strings->Header.Type = EFI_HII_PACKAGE_STRINGS;
- strings->HdrSize = hdrsize;
- strings->StringInfoOffset = hdrsize;
- strings->LanguageName = EFI_SNP_LANGUAGE_NAME;
- memcpy ( strings->Language, language, sizeof ( language ) );
- }
-
- return len;
-}
-
-/**
- * Generate EFI SNP package list
- *
- * @v snpdev SNP device
- * @ret package_list Package list, or NULL on error
- *
- * The package list is allocated using malloc(), and must eventually
- * be freed by the caller.
- */
-static EFI_HII_PACKAGE_LIST_HEADER *
-efi_snp_package_list ( struct efi_snp_device *snpdev ) {
- size_t strings_len = efi_snp_strings ( NULL, 0, snpdev );
- struct {
- EFI_HII_PACKAGE_LIST_HEADER header;
- struct efi_snp_formset formset;
- union {
- EFI_HII_STRING_PACKAGE_HDR strings;
- uint8_t pad[strings_len];
- } __attribute__ (( packed )) strings;
- EFI_HII_PACKAGE_HEADER end;
- } __attribute__ (( packed )) *package_list;
-
- /* Allocate package list */
- package_list = zalloc ( sizeof ( *package_list ) );
- if ( ! package_list )
- return NULL;
-
- /* Create a unique GUID for this package list and formset */
- efi_snp_formset.FormSet.FormSet.Guid.Data1++;
-
- /* Populate package list */
- memcpy ( &package_list->header.PackageListGuid,
- &efi_snp_formset.FormSet.FormSet.Guid,
- sizeof ( package_list->header.PackageListGuid ) );
- package_list->header.PackageLength = sizeof ( *package_list );
- memcpy ( &package_list->formset, &efi_snp_formset,
- sizeof ( package_list->formset ) );
- efi_snp_strings ( &package_list->strings.strings,
- sizeof ( package_list->strings ), snpdev );
- package_list->end.Length = sizeof ( package_list->end );
- package_list->end.Type = EFI_HII_PACKAGE_END;
-
- return &package_list->header;
-}
-
-/**
- * Fetch configuration
- *
- * @v hii HII configuration access protocol
- * @v request Configuration to fetch
- * @ret progress Progress made through configuration to fetch
- * @ret results Query results
+ * @v name2 Component name protocol
+ * @v language Language to use
+ * @v driver_name Driver name to fill in
* @ret efirc EFI status code
*/
static EFI_STATUS EFIAPI
-efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
- EFI_STRING request, EFI_STRING *progress,
- EFI_STRING *results __unused ) {
+efi_snp_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2,
+ CHAR8 *language __unused, CHAR16 **driver_name ) {
struct efi_snp_device *snpdev =
- container_of ( hii, struct efi_snp_device, hii );
-
- DBGC ( snpdev, "SNPDEV %p ExtractConfig\n", snpdev );
-
- *progress = request;
- return EFI_INVALID_PARAMETER;
-}
+ container_of ( name2, struct efi_snp_device, name2 );
-/**
- * Store configuration
- *
- * @v hii HII configuration access protocol
- * @v config Configuration to store
- * @ret progress Progress made through configuration to store
- * @ret efirc EFI status code
- */
-static EFI_STATUS EFIAPI
-efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
- EFI_STRING config, EFI_STRING *progress ) {
- struct efi_snp_device *snpdev =
- container_of ( hii, struct efi_snp_device, hii );
-
- DBGC ( snpdev, "SNPDEV %p RouteConfig\n", snpdev );
-
- *progress = config;
- return EFI_INVALID_PARAMETER;
+ *driver_name = snpdev->driver_name;
+ return 0;
}
/**
- * Handle form actions
+ * Look up controller name
*
- * @v hii HII configuration access protocol
- * @v action Form browser action
- * @v question_id Question ID
- * @v type Type of value
- * @v value Value
- * @ret action_request Action requested by driver
+ * @v name2 Component name protocol
+ * @v device Device
+ * @v child Child device, or NULL
+ * @v language Language to use
+ * @v driver_name Device name to fill in
* @ret efirc EFI status code
*/
static EFI_STATUS EFIAPI
-efi_snp_hii_callback ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
- EFI_BROWSER_ACTION action __unused,
- EFI_QUESTION_ID question_id __unused,
- UINT8 type __unused, EFI_IFR_TYPE_VALUE *value __unused,
- EFI_BROWSER_ACTION_REQUEST *action_request __unused ) {
+efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2,
+ EFI_HANDLE device __unused,
+ EFI_HANDLE child __unused,
+ CHAR8 *language __unused,
+ CHAR16 **controller_name ) {
struct efi_snp_device *snpdev =
- container_of ( hii, struct efi_snp_device, hii );
+ container_of ( name2, struct efi_snp_device, name2 );
- DBGC ( snpdev, "SNPDEV %p Callback\n", snpdev );
- return EFI_UNSUPPORTED;
+ *controller_name = snpdev->controller_name;
+ return 0;
}
-/** HII configuration access protocol */
-static EFI_HII_CONFIG_ACCESS_PROTOCOL efi_snp_device_hii = {
- .ExtractConfig = efi_snp_hii_extract_config,
- .RouteConfig = efi_snp_hii_route_config,
- .Callback = efi_snp_hii_callback,
-};
-
/******************************************************************************
*
* iPXE network driver
@@ -1179,8 +846,18 @@
strncpy ( snpdev->nii.StringId, "iPXE",
sizeof ( snpdev->nii.StringId ) );
- /* Populate the HII configuration access structure */
- memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) );
+ /* Populate the component name structure */
+ efi_snprintf ( snpdev->driver_name,
+ ( sizeof ( snpdev->driver_name ) /
+ sizeof ( snpdev->driver_name[0] ) ), "%s",
+ netdev->dev->driver_name );
+ efi_snprintf ( snpdev->controller_name,
+ ( sizeof ( snpdev->controller_name ) /
+ sizeof ( snpdev->controller_name[0] ) ), "%s (%s)",
+ netdev->name, netdev_addr ( netdev ) );
+ snpdev->name2.GetDriverName = efi_snp_get_driver_name;
+ snpdev->name2.GetControllerName = efi_snp_get_controller_name;
+ snpdev->name2.SupportedLanguages = "en";
/* Populate the device name */
efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) /
@@ -1210,7 +887,7 @@
&efi_device_path_protocol_guid, &snpdev->path,
&efi_nii_protocol_guid, &snpdev->nii,
&efi_nii31_protocol_guid, &snpdev->nii,
- &efi_hii_config_access_protocol_guid, &snpdev->hii,
+ &efi_component_name2_protocol_guid, &snpdev->name2,
NULL ) ) != 0 ) {
DBGC ( snpdev, "SNPDEV %p could not install protocols: "
"%s\n", snpdev, efi_strerror ( efirc ) );
@@ -1227,23 +904,11 @@
goto err_efipci_child_add;
}
- /* Create HII package list */
- snpdev->package_list = efi_snp_package_list ( snpdev );
- if ( ! snpdev->package_list ) {
- DBGC ( snpdev, "SNPDEV %p could not create HII package list\n",
- snpdev );
- rc = -ENOMEM;
- goto err_create_hii;
- }
-
- /* Add HII packages */
- if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list,
- snpdev->handle,
- &snpdev->hii_handle ) ) != 0 ) {
- DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n",
- snpdev, efi_strerror ( efirc ) );
- rc = EFIRC_TO_RC ( efirc );
- goto err_register_hii;
+ /* Install HII */
+ if ( ( rc = efi_snp_hii_install ( snpdev ) ) != 0 ) {
+ DBGC ( snpdev, "SNPDEV %p could not install HII: %s\n",
+ snpdev, strerror ( rc ) );
+ goto err_hii_install;
}
/* Add to list of SNP devices */
@@ -1253,10 +918,8 @@
snpdev, netdev->name, snpdev->handle );
return 0;
- efihii->RemovePackageList ( efihii, snpdev->hii_handle );
- err_register_hii:
- free ( snpdev->package_list );
- err_create_hii:
+ efi_snp_hii_uninstall ( snpdev );
+ err_hii_install:
efipci_child_del ( efipci, snpdev->handle );
err_efipci_child_add:
bs->UninstallMultipleProtocolInterfaces (
@@ -1265,7 +928,7 @@
&efi_device_path_protocol_guid, &snpdev->path,
&efi_nii_protocol_guid, &snpdev->nii,
&efi_nii31_protocol_guid, &snpdev->nii,
- &efi_hii_config_access_protocol_guid, &snpdev->hii,
+ &efi_component_name2_protocol_guid, &snpdev->name2,
NULL );
err_install_protocol_interface:
bs->CloseEvent ( snpdev->snp.WaitForPacket );
@@ -1317,8 +980,7 @@
}
/* Uninstall the SNP */
- efihii->RemovePackageList ( efihii, snpdev->hii_handle );
- free ( snpdev->package_list );
+ efi_snp_hii_uninstall ( snpdev );
efipci_child_del ( snpdev->efipci, snpdev->handle );
list_del ( &snpdev->list );
bs->UninstallMultipleProtocolInterfaces (
@@ -1327,7 +989,7 @@
&efi_device_path_protocol_guid, &snpdev->path,
&efi_nii_protocol_guid, &snpdev->nii,
&efi_nii31_protocol_guid, &snpdev->nii,
- &efi_hii_config_access_protocol_guid, &snpdev->hii,
+ &efi_component_name2_protocol_guid, &snpdev->name2,
NULL );
bs->CloseEvent ( snpdev->snp.WaitForPacket );
netdev_put ( snpdev->netdev );
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/interface/efi/efi_snp_hii.c
^
|
@@ -0,0 +1,706 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * EFI SNP HII protocol
+ *
+ * The HII protocols are some of the less-well designed parts of the
+ * entire EFI specification. This is a significant accomplishment.
+ *
+ * The face-slappingly ludicrous query string syntax seems to be
+ * motivated by the desire to allow a caller to query multiple drivers
+ * simultaneously via the single-instance HII_CONFIG_ROUTING_PROTOCOL,
+ * which is supposed to pass relevant subsets of the query string to
+ * the relevant drivers.
+ *
+ * Nobody uses the HII_CONFIG_ROUTING_PROTOCOL. Not even the EFI
+ * setup browser uses the HII_CONFIG_ROUTING_PROTOCOL. To the best of
+ * my knowledge, there has only ever been one implementation of the
+ * HII_CONFIG_ROUTING_PROTOCOL (as part of EDK2), and it just doesn't
+ * work. It's so badly broken that I can't even figure out what the
+ * code is _trying_ to do.
+ *
+ * Fundamentally, the problem seems to be that Javascript programmers
+ * should not be allowed to design APIs for C code.
+ */
+
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <errno.h>
+#include <ipxe/settings.h>
+#include <ipxe/nvo.h>
+#include <ipxe/device.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_hii.h>
+#include <ipxe/efi/efi_snp.h>
+#include <ipxe/efi/efi_strings.h>
+#include <config/general.h>
+
+/** EFI configuration access protocol GUID */
+static EFI_GUID efi_hii_config_access_protocol_guid
+ = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID;
+
+/** EFI platform setup formset GUID */
+static EFI_GUID efi_hii_platform_setup_formset_guid
+ = EFI_HII_PLATFORM_SETUP_FORMSET_GUID;
+
+/** EFI IBM UCM compliant formset GUID */
+static EFI_GUID efi_hii_ibm_ucm_compliant_formset_guid
+ = EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID;
+
+/** EFI HII database protocol */
+static EFI_HII_DATABASE_PROTOCOL *efihii;
+EFI_REQUIRE_PROTOCOL ( EFI_HII_DATABASE_PROTOCOL, &efihii );
+
+/**
+ * Identify settings to be exposed via HII
+ *
+ * @v snpdev SNP device
+ * @ret settings Settings, or NULL
+ */
+static struct settings * efi_snp_hii_settings ( struct efi_snp_device *snpdev ){
+
+ return find_child_settings ( netdev_settings ( snpdev->netdev ),
+ NVO_SETTINGS_NAME );
+}
+
+/**
+ * Check whether or not setting is applicable
+ *
+ * @v snpdev SNP device
+ * @v setting Setting
+ * @ret applies Setting applies
+ */
+static int efi_snp_hii_setting_applies ( struct efi_snp_device *snpdev,
+ struct setting *setting ) {
+
+ return nvo_applies ( efi_snp_hii_settings ( snpdev ), setting );
+}
+
+/**
+ * Generate a random GUID
+ *
+ * @v guid GUID to fill in
+ */
+static void efi_snp_hii_random_guid ( EFI_GUID *guid ) {
+ uint8_t *byte = ( ( uint8_t * ) guid );
+ unsigned int i;
+
+ for ( i = 0 ; i < sizeof ( *guid ) ; i++ )
+ *(byte++) = random();
+}
+
+/**
+ * Generate EFI SNP questions
+ *
+ * @v snpdev SNP device
+ * @v ifr IFR builder
+ * @v varstore_id Variable store identifier
+ */
+static void efi_snp_hii_questions ( struct efi_snp_device *snpdev,
+ struct efi_ifr_builder *ifr,
+ unsigned int varstore_id ) {
+ struct setting *setting;
+ unsigned int name_id;
+ unsigned int prompt_id;
+ unsigned int help_id;
+ unsigned int question_id;
+
+ /* Add all applicable settings */
+ for_each_table_entry ( setting, SETTINGS ) {
+ if ( ! efi_snp_hii_setting_applies ( snpdev, setting ) )
+ continue;
+ name_id = efi_ifr_string ( ifr, "%s", setting->name );
+ prompt_id = efi_ifr_string ( ifr, "%s", setting->description );
+ help_id = efi_ifr_string ( ifr, "http://ipxe.org/cfg/%s",
+ setting->name );
+ question_id = setting->tag;
+ efi_ifr_string_op ( ifr, prompt_id, help_id,
+ question_id, varstore_id, name_id,
+ 0, 0x00, 0xff, 0 );
+ }
+}
+
+/**
+ * Build HII package list for SNP device
+ *
+ * @v snpdev SNP device
+ * @ret package Package list, or NULL on error
+ */
+static EFI_HII_PACKAGE_LIST_HEADER *
+efi_snp_hii_package_list ( struct efi_snp_device *snpdev ) {
+ struct net_device *netdev = snpdev->netdev;
+ struct device *dev = netdev->dev;
+ struct efi_ifr_builder ifr;
+ EFI_HII_PACKAGE_LIST_HEADER *package;
+ const char *product_name;
+ EFI_GUID package_guid;
+ EFI_GUID formset_guid;
+ EFI_GUID varstore_guid;
+ unsigned int title_id;
+ unsigned int varstore_id;
+
+ /* Initialise IFR builder */
+ efi_ifr_init ( &ifr );
+
+ /* Determine product name */
+ product_name = ( PRODUCT_NAME[0] ? PRODUCT_NAME : PRODUCT_SHORT_NAME );
+
+ /* Generate GUIDs */
+ efi_snp_hii_random_guid ( &package_guid );
+ efi_snp_hii_random_guid ( &formset_guid );
+ efi_snp_hii_random_guid ( &varstore_guid );
+
+ /* Generate title string (used more than once) */
+ title_id = efi_ifr_string ( &ifr, "%s (%s)", product_name,
+ netdev_addr ( netdev ) );
+
+ /* Generate opcodes */
+ efi_ifr_form_set_op ( &ifr, &formset_guid, title_id,
+ efi_ifr_string ( &ifr,
+ "Configure " PRODUCT_SHORT_NAME),
+ &efi_hii_platform_setup_formset_guid,
+ &efi_hii_ibm_ucm_compliant_formset_guid, NULL );
+ efi_ifr_guid_class_op ( &ifr, EFI_NETWORK_DEVICE_CLASS );
+ efi_ifr_guid_subclass_op ( &ifr, 0x03 );
+ varstore_id = efi_ifr_varstore_name_value_op ( &ifr, &varstore_guid );
+ efi_ifr_form_op ( &ifr, title_id );
+ efi_ifr_text_op ( &ifr,
+ efi_ifr_string ( &ifr, "Name" ),
+ efi_ifr_string ( &ifr, "Firmware product name" ),
+ efi_ifr_string ( &ifr, "%s", product_name ) );
+ efi_ifr_text_op ( &ifr,
+ efi_ifr_string ( &ifr, "Version" ),
+ efi_ifr_string ( &ifr, "Firmware version" ),
+ efi_ifr_string ( &ifr, VERSION ) );
+ efi_ifr_text_op ( &ifr,
+ efi_ifr_string ( &ifr, "Driver" ),
+ efi_ifr_string ( &ifr, "Firmware driver" ),
+ efi_ifr_string ( &ifr, "%s", dev->driver_name ) );
+ efi_ifr_text_op ( &ifr,
+ efi_ifr_string ( &ifr, "Device" ),
+ efi_ifr_string ( &ifr, "Hardware device" ),
+ efi_ifr_string ( &ifr, "%s", dev->name ) );
+ efi_snp_hii_questions ( snpdev, &ifr, varstore_id );
+ efi_ifr_end_op ( &ifr );
+ efi_ifr_end_op ( &ifr );
+
+ /* Build package */
+ package = efi_ifr_package ( &ifr, &package_guid, "en-us",
+ efi_ifr_string ( &ifr, "English" ) );
+ if ( ! package ) {
+ DBGC ( snpdev, "SNPDEV %p could not build IFR package\n",
+ snpdev );
+ efi_ifr_free ( &ifr );
+ return NULL;
+ }
+
+ /* Free temporary storage */
+ efi_ifr_free ( &ifr );
+ return package;
+}
+
+/**
+ * Append response to result string
+ *
+ * @v snpdev SNP device
+ * @v key Key
+ * @v value Value
+ * @v results Result string
+ * @ret rc Return status code
+ *
+ * The result string is allocated dynamically using
+ * BootServices::AllocatePool(), and the caller is responsible for
+ * eventually calling BootServices::FreePool().
+ */
+static int efi_snp_hii_append ( struct efi_snp_device *snpdev __unused,
+ const char *key, const char *value,
+ wchar_t **results ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ size_t len;
+ void *new;
+
+ /* Allocate new string */
+ len = ( ( *results ? ( wcslen ( *results ) + 1 /* "&" */ ) : 0 ) +
+ strlen ( key ) + 1 /* "=" */ + strlen ( value ) + 1 /* NUL */ );
+ bs->AllocatePool ( EfiBootServicesData, ( len * sizeof ( wchar_t ) ),
+ &new );
+ if ( ! new )
+ return -ENOMEM;
+
+ /* Populate string */
+ efi_snprintf ( new, len, "%ls%s%s=%s", ( *results ? *results : L"" ),
+ ( *results ? L"&" : L"" ), key, value );
+ bs->FreePool ( *results );
+ *results = new;
+
+ return 0;
+}
+
+/**
+ * Fetch HII setting
+ *
+ * @v snpdev SNP device
+ * @v key Key
+ * @v value Value
+ * @v results Result string
+ * @v have_setting Flag indicating detection of a setting
+ * @ret rc Return status code
+ */
+static int efi_snp_hii_fetch ( struct efi_snp_device *snpdev,
+ const char *key, const char *value,
+ wchar_t **results, int *have_setting ) {
+ struct settings *settings = efi_snp_hii_settings ( snpdev );
+ struct setting *setting;
+ int len;
+ char *buf;
+ char *encoded;
+ int i;
+ int rc;
+
+ /* Handle ConfigHdr components */
+ if ( ( strcasecmp ( key, "GUID" ) == 0 ) ||
+ ( strcasecmp ( key, "NAME" ) == 0 ) ||
+ ( strcasecmp ( key, "PATH" ) == 0 ) ) {
+ return efi_snp_hii_append ( snpdev, key, value, results );
+ }
+ if ( have_setting )
+ *have_setting = 1;
+
+ /* Do nothing more unless we have a settings block */
+ if ( ! settings ) {
+ rc = -ENOTSUP;
+ goto err_no_settings;
+ }
+
+ /* Identify setting */
+ setting = find_setting ( key );
+ if ( ! setting ) {
+ DBGC ( snpdev, "SNPDEV %p no such setting \"%s\"\n",
+ snpdev, key );
+ rc = -ENODEV;
+ goto err_find_setting;
+ }
+
+ /* Encode value */
+ if ( setting_exists ( settings, setting ) ) {
+
+ /* Calculate formatted length */
+ len = fetchf_setting ( settings, setting, NULL, 0 );
+ if ( len < 0 ) {
+ rc = len;
+ DBGC ( snpdev, "SNPDEV %p could not fetch %s: %s\n",
+ snpdev, setting->name, strerror ( rc ) );
+ goto err_fetchf_len;
+ }
+
+ /* Allocate buffer for formatted value and HII-encoded value */
+ buf = zalloc ( len + 1 /* NUL */ + ( len * 4 ) + 1 /* NUL */ );
+ if ( ! buf ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ encoded = ( buf + len + 1 /* NUL */ );
+
+ /* Format value */
+ fetchf_setting ( settings, setting, buf, ( len + 1 /* NUL */ ));
+ for ( i = 0 ; i < len ; i++ ) {
+ sprintf ( ( encoded + ( 4 * i ) ), "%04x",
+ *( ( uint8_t * ) buf + i ) );
+ }
+
+ } else {
+
+ /* Non-existent or inapplicable setting */
+ buf = NULL;
+ encoded = "";
+ }
+
+ /* Append results */
+ if ( ( rc = efi_snp_hii_append ( snpdev, key, encoded,
+ results ) ) != 0 ) {
+ goto err_append;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_append:
+ free ( buf );
+ err_alloc:
+ err_fetchf_len:
+ err_find_setting:
+ err_no_settings:
+ return rc;
+}
+
+/**
+ * Fetch HII setting
+ *
+ * @v snpdev SNP device
+ * @v key Key
+ * @v value Value
+ * @v results Result string (unused)
+ * @v have_setting Flag indicating detection of a setting (unused)
+ * @ret rc Return status code
+ */
+static int efi_snp_hii_store ( struct efi_snp_device *snpdev,
+ const char *key, const char *value,
+ wchar_t **results __unused,
+ int *have_setting __unused ) {
+ struct settings *settings = efi_snp_hii_settings ( snpdev );
+ struct setting *setting;
+ char *buf;
+ char tmp[5];
+ char *endp;
+ int len;
+ int i;
+ int rc;
+
+ /* Handle ConfigHdr components */
+ if ( ( strcasecmp ( key, "GUID" ) == 0 ) ||
+ ( strcasecmp ( key, "NAME" ) == 0 ) ||
+ ( strcasecmp ( key, "PATH" ) == 0 ) ) {
+ /* Nothing to do */
+ return 0;
+ }
+
+ /* Do nothing more unless we have a settings block */
+ if ( ! settings ) {
+ rc = -ENOTSUP;
+ goto err_no_settings;
+ }
+
+ /* Identify setting */
+ setting = find_setting ( key );
+ if ( ! setting ) {
+ DBGC ( snpdev, "SNPDEV %p no such setting \"%s\"\n",
+ snpdev, key );
+ rc = -ENODEV;
+ goto err_find_setting;
+ }
+
+ /* Allocate buffer */
+ len = ( strlen ( value ) / 4 );
+ buf = zalloc ( len + 1 /* NUL */ );
+ if ( ! buf ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+
+ /* Decode value */
+ tmp[4] = '\0';
+ for ( i = 0 ; i < len ; i++ ) {
+ memcpy ( tmp, ( value + ( i * 4 ) ), 4 );
+ buf[i] = strtoul ( tmp, &endp, 16 );
+ if ( endp != &tmp[4] ) {
+ DBGC ( snpdev, "SNPDEV %p invalid character %s\n",
+ snpdev, tmp );
+ rc = -EINVAL;
+ goto err_inval;
+ }
+ }
+
+ /* Store value */
+ if ( ( rc = storef_setting ( settings, setting, buf ) ) != 0 ) {
+ DBGC ( snpdev, "SNPDEV %p could not store \"%s\" into %s: %s\n",
+ snpdev, buf, setting->name, strerror ( rc ) );
+ goto err_storef;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_storef:
+ err_inval:
+ free ( buf );
+ err_alloc:
+ err_find_setting:
+ err_no_settings:
+ return rc;
+}
+
+/**
+ * Process portion of HII configuration string
+ *
+ * @v snpdev SNP device
+ * @v string HII configuration string
+ * @v progress Progress through HII configuration string
+ * @v results Results string
+ * @v have_setting Flag indicating detection of a setting (unused)
+ * @v process Function used to process key=value pairs
+ * @ret rc Return status code
+ */
+static int efi_snp_hii_process ( struct efi_snp_device *snpdev,
+ wchar_t *string, wchar_t **progress,
+ wchar_t **results, int *have_setting,
+ int ( * process ) ( struct efi_snp_device *,
+ const char *key,
+ const char *value,
+ wchar_t **results,
+ int *have_setting ) ) {
+ wchar_t *wkey = string;
+ wchar_t *wend = string;
+ wchar_t *wvalue = NULL;
+ size_t key_len;
+ size_t value_len;
+ void *temp;
+ char *key;
+ char *value;
+ int rc;
+
+ /* Locate key, value (if any), and end */
+ while ( *wend ) {
+ if ( *wend == L'&' )
+ break;
+ if ( *(wend++) == L'=' )
+ wvalue = wend;
+ }
+
+ /* Allocate memory for key and value */
+ key_len = ( ( wvalue ? ( wvalue - 1 ) : wend ) - wkey );
+ value_len = ( wvalue ? ( wend - wvalue ) : 0 );
+ temp = zalloc ( key_len + 1 /* NUL */ + value_len + 1 /* NUL */ );
+ if ( ! temp )
+ return -ENOMEM;
+ key = temp;
+ value = ( temp + key_len + 1 /* NUL */ );
+
+ /* Copy key and value */
+ while ( key_len-- )
+ key[key_len] = wkey[key_len];
+ while ( value_len-- )
+ value[value_len] = wvalue[value_len];
+
+ /* Process key and value */
+ if ( ( rc = process ( snpdev, key, value, results,
+ have_setting ) ) != 0 ) {
+ goto err;
+ }
+
+ /* Update progress marker */
+ *progress = wend;
+
+ err:
+ /* Free temporary storage */
+ free ( temp );
+
+ return rc;
+}
+
+/**
+ * Fetch configuration
+ *
+ * @v hii HII configuration access protocol
+ * @v request Configuration to fetch
+ * @ret progress Progress made through configuration to fetch
+ * @ret results Query results
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
+ EFI_STRING request, EFI_STRING *progress,
+ EFI_STRING *results ) {
+ struct efi_snp_device *snpdev =
+ container_of ( hii, struct efi_snp_device, hii );
+ int have_setting = 0;
+ wchar_t *pos;
+ int rc;
+
+ DBGC ( snpdev, "SNPDEV %p ExtractConfig request \"%ls\"\n",
+ snpdev, request );
+
+ /* Initialise results */
+ *results = NULL;
+
+ /* Process all request fragments */
+ for ( pos = *progress = request ; *progress && **progress ;
+ pos = *progress + 1 ) {
+ if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress,
+ results, &have_setting,
+ efi_snp_hii_fetch ) ) != 0 ) {
+ return RC_TO_EFIRC ( rc );
+ }
+ }
+
+ /* If we have no explicit request, return all settings */
+ if ( ! have_setting ) {
+ struct setting *setting;
+
+ for_each_table_entry ( setting, SETTINGS ) {
+ if ( ! efi_snp_hii_setting_applies ( snpdev, setting ) )
+ continue;
+ if ( ( rc = efi_snp_hii_fetch ( snpdev, setting->name,
+ NULL, results,
+ NULL ) ) != 0 ) {
+ return RC_TO_EFIRC ( rc );
+ }
+ }
+ }
+
+ DBGC ( snpdev, "SNPDEV %p ExtractConfig results \"%ls\"\n",
+ snpdev, *results );
+ return 0;
+}
+
+/**
+ * Store configuration
+ *
+ * @v hii HII configuration access protocol
+ * @v config Configuration to store
+ * @ret progress Progress made through configuration to store
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
+ EFI_STRING config, EFI_STRING *progress ) {
+ struct efi_snp_device *snpdev =
+ container_of ( hii, struct efi_snp_device, hii );
+ wchar_t *pos;
+ int rc;
+
+ DBGC ( snpdev, "SNPDEV %p RouteConfig \"%ls\"\n", snpdev, config );
+
+ /* Process all request fragments */
+ for ( pos = *progress = config ; *progress && **progress ;
+ pos = *progress + 1 ) {
+ if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress,
+ NULL, NULL,
+ efi_snp_hii_store ) ) != 0 ) {
+ return RC_TO_EFIRC ( rc );
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Handle form actions
+ *
+ * @v hii HII configuration access protocol
+ * @v action Form browser action
+ * @v question_id Question ID
+ * @v type Type of value
+ * @v value Value
+ * @ret action_request Action requested by driver
+ * @ret efirc EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_hii_callback ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
+ EFI_BROWSER_ACTION action __unused,
+ EFI_QUESTION_ID question_id __unused,
+ UINT8 type __unused, EFI_IFR_TYPE_VALUE *value __unused,
+ EFI_BROWSER_ACTION_REQUEST *action_request __unused ) {
+ struct efi_snp_device *snpdev =
+ container_of ( hii, struct efi_snp_device, hii );
+
+ DBGC ( snpdev, "SNPDEV %p Callback\n", snpdev );
+ return EFI_UNSUPPORTED;
+}
+
+/** HII configuration access protocol */
+static EFI_HII_CONFIG_ACCESS_PROTOCOL efi_snp_device_hii = {
+ .ExtractConfig = efi_snp_hii_extract_config,
+ .RouteConfig = efi_snp_hii_route_config,
+ .Callback = efi_snp_hii_callback,
+};
+
+/**
+ * Install HII protocol and packages for SNP device
+ *
+ * @v snpdev SNP device
+ * @ret rc Return status code
+ */
+int efi_snp_hii_install ( struct efi_snp_device *snpdev ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ int efirc;
+ int rc;
+
+ /* Initialise HII protocol */
+ memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) );
+
+ /* Create HII package list */
+ snpdev->package_list = efi_snp_hii_package_list ( snpdev );
+ if ( ! snpdev->package_list ) {
+ DBGC ( snpdev, "SNPDEV %p could not create HII package list\n",
+ snpdev );
+ rc = -ENOMEM;
+ goto err_build_package_list;
+ }
+
+ /* Add HII packages */
+ if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list,
+ snpdev->handle,
+ &snpdev->hii_handle ) ) != 0 ) {
+ DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n",
+ snpdev, efi_strerror ( efirc ) );
+ rc = EFIRC_TO_RC ( efirc );
+ goto err_new_package_list;
+ }
+
+ /* Install HII protocol */
+ if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
+ &snpdev->handle,
+ &efi_hii_config_access_protocol_guid, &snpdev->hii,
+ NULL ) ) != 0 ) {
+ DBGC ( snpdev, "SNPDEV %p could not install HII protocol: %s\n",
+ snpdev, efi_strerror ( efirc ) );
+ rc = EFIRC_TO_RC ( efirc );
+ goto err_install_protocol;
+ }
+
+ return 0;
+
+ bs->UninstallMultipleProtocolInterfaces (
+ snpdev->handle,
+ &efi_hii_config_access_protocol_guid, &snpdev->hii,
+ NULL );
+ err_install_protocol:
+ efihii->RemovePackageList ( efihii, snpdev->hii_handle );
+ err_new_package_list:
+ free ( snpdev->package_list );
+ snpdev->package_list = NULL;
+ err_build_package_list:
+ return rc;
+}
+
+/**
+ * Uninstall HII protocol and package for SNP device
+ *
+ * @v snpdev SNP device
+ */
+void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+
+ bs->UninstallMultipleProtocolInterfaces (
+ snpdev->handle,
+ &efi_hii_config_access_protocol_guid, &snpdev->hii,
+ NULL );
+ efihii->RemovePackageList ( efihii, snpdev->hii_handle );
+ free ( snpdev->package_list );
+ snpdev->package_list = NULL;
+}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/interface/smbios/smbios_settings.c
^
|
@@ -120,14 +120,21 @@
if ( tag_len == 0 ) {
/* String */
- return read_smbios_string ( &structure,
- buf[tag_offset],
- data, len );
+ if ( ( rc = read_smbios_string ( &structure,
+ buf[tag_offset],
+ data, len ) ) < 0 ) {
+ return rc;
+ }
+ if ( ! setting->type )
+ setting->type = &setting_type_string;
+ return rc;
} else {
/* Raw data */
if ( len > tag_len )
len = tag_len;
memcpy ( data, &buf[tag_offset], len );
+ if ( ! setting->type )
+ setting->type = &setting_type_hex;
return tag_len;
}
}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/80211/net80211.c
^
|
@@ -387,9 +387,6 @@
/* ---------- 802.11 link-layer protocol ---------- */
-/** 802.11 broadcast MAC address */
-static u8 net80211_ll_broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
/**
* Determine whether a transmission rate uses ERP/OFDM
*
@@ -763,7 +760,7 @@
return NULL;
netdev->ll_protocol = &net80211_ll_protocol;
- netdev->ll_broadcast = net80211_ll_broadcast;
+ netdev->ll_broadcast = eth_broadcast;
netdev->max_pkt_len = IEEE80211_MAX_DATA_LEN;
netdev_init ( netdev, &net80211_netdev_ops );
@@ -1399,7 +1396,7 @@
ctx->probe = iob;
rc = net80211_tx_mgmt ( dev, IEEE80211_STYPE_PROBE_REQ,
- net80211_ll_broadcast,
+ eth_broadcast,
iob_disown ( siob ) );
if ( rc ) {
DBGC ( dev, "802.11 %p send probe failed: "
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/arp.c
^
|
@@ -180,13 +180,16 @@
struct net_device *netdev = arp->netdev;
struct net_protocol *net_protocol = arp->net_protocol;
struct io_buffer *iobuf;
- struct io_buffer *tmp;
+
+ /* Take ownership from cache */
+ list_del ( &arp->list );
/* Stop timer */
stop_timer ( &arp->timer );
/* Discard any outstanding I/O buffers */
- list_for_each_entry_safe ( iobuf, tmp, &arp->tx_queue, list ) {
+ while ( ( iobuf = list_first_entry ( &arp->tx_queue, struct io_buffer,
+ list ) ) != NULL ) {
DBGC2 ( arp, "ARP %p %s %s %s discarding deferred packet: "
"%s\n", arp, netdev->name, net_protocol->name,
net_protocol->ntoa ( arp->net_dest ), strerror ( rc ) );
@@ -198,8 +201,7 @@
net_protocol->name, net_protocol->ntoa ( arp->net_dest ),
strerror ( rc ) );
- /* Remove from cache and drop reference */
- list_del ( &arp->list );
+ /* Drop remaining reference */
ref_put ( &arp->refcnt );
}
@@ -518,12 +520,13 @@
struct arp_entry *arp;
/* Drop oldest cache entry, if any */
- list_for_each_entry_reverse ( arp, &arp_entries, list ) {
+ arp = list_last_entry ( &arp_entries, struct arp_entry, list );
+ if ( arp ) {
arp_destroy ( arp, -ENOBUFS );
return 1;
+ } else {
+ return 0;
}
-
- return 0;
}
/** ARP cache discarder
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/ethernet.c
^
|
@@ -39,7 +39,7 @@
*/
/** Ethernet broadcast MAC address */
-static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
/**
* Add Ethernet link-layer header
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/infiniband.c
^
|
@@ -168,6 +168,7 @@
* @v send_cq Send completion queue
* @v num_recv_wqes Number of receive work queue entries
* @v recv_cq Receive completion queue
+ * @v op Queue pair operations
* @ret qp Queue pair
*
* The queue pair will be left in the INIT state; you must call
@@ -178,7 +179,8 @@
unsigned int num_send_wqes,
struct ib_completion_queue *send_cq,
unsigned int num_recv_wqes,
- struct ib_completion_queue *recv_cq ) {
+ struct ib_completion_queue *recv_cq,
+ struct ib_queue_pair_operations *op ) {
struct ib_queue_pair *qp;
size_t total_size;
int rc;
@@ -210,6 +212,7 @@
qp->recv.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) +
( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ));
INIT_LIST_HEAD ( &qp->mgids );
+ qp->op = op;
/* Perform device-specific initialisation and get QPN */
if ( ( rc = ibdev->op->create_qp ( ibdev, qp ) ) != 0 ) {
@@ -260,7 +263,6 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av New address vector, if applicable
* @ret rc Return status code
*/
int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
@@ -302,7 +304,7 @@
}
for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) {
if ( ( iobuf = qp->recv.iobufs[i] ) != NULL ) {
- ib_complete_recv ( ibdev, qp, NULL, iobuf,
+ ib_complete_recv ( ibdev, qp, NULL, NULL, iobuf,
-ECANCELED );
}
}
@@ -381,14 +383,14 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
* @v iobuf I/O buffer
* @ret rc Return status code
*/
int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
struct io_buffer *iobuf ) {
- struct ib_address_vector av_copy;
+ struct ib_address_vector dest_copy;
int rc;
/* Check queue fill level */
@@ -399,21 +401,21 @@
}
/* Use default address vector if none specified */
- if ( ! av )
- av = &qp->av;
+ if ( ! dest )
+ dest = &qp->av;
/* Make modifiable copy of address vector */
- memcpy ( &av_copy, av, sizeof ( av_copy ) );
- av = &av_copy;
+ memcpy ( &dest_copy, dest, sizeof ( dest_copy ) );
+ dest = &dest_copy;
/* Fill in optional parameters in address vector */
- if ( ! av->qkey )
- av->qkey = qp->qkey;
- if ( ! av->rate )
- av->rate = IB_RATE_2_5;
+ if ( ! dest->qkey )
+ dest->qkey = qp->qkey;
+ if ( ! dest->rate )
+ dest->rate = IB_RATE_2_5;
/* Post to hardware */
- if ( ( rc = ibdev->op->post_send ( ibdev, qp, av, iobuf ) ) != 0 ) {
+ if ( ( rc = ibdev->op->post_send ( ibdev, qp, dest, iobuf ) ) != 0 ) {
DBGC ( ibdev, "IBDEV %p QPN %#lx could not post send WQE: "
"%s\n", ibdev, qp->qpn, strerror ( rc ) );
return rc;
@@ -484,16 +486,19 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector, or NULL
+ * @v dest Destination address vector, or NULL
+ * @v source Source address vector, or NULL
* @v iobuf I/O buffer
* @v rc Completion status code
*/
void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest,
+ struct ib_address_vector *source,
struct io_buffer *iobuf, int rc ) {
if ( qp->recv.cq->op->complete_recv ) {
- qp->recv.cq->op->complete_recv ( ibdev, qp, av, iobuf, rc );
+ qp->recv.cq->op->complete_recv ( ibdev, qp, dest, source,
+ iobuf, rc );
} else {
free_iob ( iobuf );
}
@@ -514,7 +519,7 @@
while ( qp->recv.fill < qp->recv.num_wqes ) {
/* Allocate I/O buffer */
- iobuf = alloc_iob ( IB_MAX_PAYLOAD_SIZE );
+ iobuf = qp->op->alloc_iob ( IB_MAX_PAYLOAD_SIZE );
if ( ! iobuf ) {
/* Non-fatal; we will refill on next attempt */
return;
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/infiniband/ib_cmrc.c
^
|
@@ -220,13 +220,15 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector, or NULL
+ * @v dest Destination address vector, or NULL
+ * @v source Source address vector, or NULL
* @v iobuf I/O buffer
* @v rc Completion status code
*/
static void ib_cmrc_complete_recv ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp,
- struct ib_address_vector *av __unused,
+ struct ib_address_vector *dest __unused,
+ struct ib_address_vector *source __unused,
struct io_buffer *iobuf, int rc ) {
struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp );
@@ -257,6 +259,11 @@
.complete_recv = ib_cmrc_complete_recv,
};
+/** Infiniband CMRC queue pair operations */
+static struct ib_queue_pair_operations ib_cmrc_queue_pair_ops = {
+ .alloc_iob = alloc_iob,
+};
+
/**
* Send data via CMRC
*
@@ -410,7 +417,8 @@
/* Create queue pair */
cmrc->qp = ib_create_qp ( ibdev, IB_QPT_RC, IB_CMRC_NUM_SEND_WQES,
- cmrc->cq, IB_CMRC_NUM_RECV_WQES, cmrc->cq );
+ cmrc->cq, IB_CMRC_NUM_RECV_WQES, cmrc->cq,
+ &ib_cmrc_queue_pair_ops );
if ( ! cmrc->qp ) {
DBGC ( cmrc, "CMRC %p could not create queue pair\n", cmrc );
rc = -ENOMEM;
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/infiniband/ib_mi.c
^
|
@@ -112,13 +112,15 @@
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v av Address vector
+ * @v dest Destination address vector
+ * @v source Source address vector
* @v iobuf I/O buffer
* @v rc Completion status code
*/
static void ib_mi_complete_recv ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_address_vector *av,
+ struct ib_address_vector *dest __unused,
+ struct ib_address_vector *source,
struct io_buffer *iobuf, int rc ) {
struct ib_mad_interface *mi = ib_qp_get_ownerdata ( qp );
union ib_mad *mad;
@@ -152,7 +154,7 @@
DBGC2_HDA ( mi, 0, mad, sizeof ( *mad ) );
/* Handle MAD */
- if ( ( rc = ib_mi_handle ( ibdev, mi, mad, av ) ) != 0 )
+ if ( ( rc = ib_mi_handle ( ibdev, mi, mad, source ) ) != 0 )
goto out;
out:
@@ -164,6 +166,11 @@
.complete_recv = ib_mi_complete_recv,
};
+/** Management interface queue pair operations */
+static struct ib_queue_pair_operations ib_mi_queue_pair_ops = {
+ .alloc_iob = alloc_iob,
+};
+
/**
* Transmit MAD
*
@@ -353,7 +360,8 @@
/* Create queue pair */
mi->qp = ib_create_qp ( ibdev, type, IB_MI_NUM_SEND_WQES, mi->cq,
- IB_MI_NUM_RECV_WQES, mi->cq );
+ IB_MI_NUM_RECV_WQES, mi->cq,
+ &ib_mi_queue_pair_ops );
if ( ! mi->qp ) {
DBGC ( mi, "MI %p could not allocate queue pair\n", mi );
goto err_create_qp;
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/infiniband/ib_packet.c
^
|
@@ -42,11 +42,12 @@
* @v iobuf I/O buffer to contain headers
* @v qp Queue pair
* @v payload_len Payload length
- * @v av Address vector
+ * @v dest Destination address vector
+ * @ret rc Return status code
*/
int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf,
struct ib_queue_pair *qp, size_t payload_len,
- const struct ib_address_vector *av ) {
+ const struct ib_address_vector *dest ) {
struct ib_local_route_header *lrh;
struct ib_global_route_header *grh;
struct ib_base_transport_header *bth;
@@ -59,7 +60,8 @@
unsigned int lnh;
DBGC2 ( ibdev, "IBDEV %p TX %04x:%08lx => %04x:%08lx (key %08lx)\n",
- ibdev, ibdev->lid, qp->ext_qpn, av->lid, av->qpn, av->qkey );
+ ibdev, ibdev->lid, qp->ext_qpn, dest->lid, dest->qpn,
+ dest->qkey );
/* Calculate packet length */
pad_len = ( (-payload_len) & 0x3 );
@@ -71,7 +73,7 @@
deth = iob_push ( iobuf, sizeof ( *deth ) );
bth = iob_push ( iobuf, sizeof ( *bth ) );
grh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len );
- grh = ( av->gid_present ?
+ grh = ( dest->gid_present ?
iob_push ( iobuf, sizeof ( *grh ) ) : NULL );
lrh = iob_push ( iobuf, sizeof ( *lrh ) );
lrh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len );
@@ -80,8 +82,8 @@
vl = ( ( qp->ext_qpn == IB_QPN_SMI ) ? IB_VL_SMP : IB_VL_DEFAULT );
lrh->vl__lver = ( vl << 4 );
lnh = ( grh ? IB_LNH_GRH : IB_LNH_BTH );
- lrh->sl__lnh = ( ( av->sl << 4 ) | lnh );
- lrh->dlid = htons ( av->lid );
+ lrh->sl__lnh = ( ( dest->sl << 4 ) | lnh );
+ lrh->dlid = htons ( dest->lid );
lrh->length = htons ( lrh_len >> 2 );
lrh->slid = htons ( ibdev->lid );
@@ -93,18 +95,18 @@
grh->nxthdr = IB_GRH_NXTHDR_IBA;
grh->hoplmt = 0;
memcpy ( &grh->sgid, &ibdev->gid, sizeof ( grh->sgid ) );
- memcpy ( &grh->dgid, &av->gid, sizeof ( grh->dgid ) );
+ memcpy ( &grh->dgid, &dest->gid, sizeof ( grh->dgid ) );
}
/* Construct BTH */
bth->opcode = BTH_OPCODE_UD_SEND;
bth->se__m__padcnt__tver = ( pad_len << 4 );
bth->pkey = htons ( ibdev->pkey );
- bth->dest_qp = htonl ( av->qpn );
+ bth->dest_qp = htonl ( dest->qpn );
bth->ack__psn = htonl ( ( qp->send.psn++ ) & 0xffffffUL );
/* Construct DETH */
- deth->qkey = htonl ( av->qkey );
+ deth->qkey = htonl ( dest->qkey );
deth->src_qp = htonl ( qp->ext_qpn );
DBGCP_HDA ( ibdev, 0, iobuf->data,
@@ -120,11 +122,14 @@
* @v iobuf I/O buffer containing headers
* @v qp Queue pair to fill in, or NULL
* @v payload_len Payload length to fill in, or NULL
- * @v av Address vector to fill in
+ * @v dest Destination address vector to fill in
+ * @v source Source address vector to fill in
+ * @ret rc Return status code
*/
int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf,
struct ib_queue_pair **qp, size_t *payload_len,
- struct ib_address_vector *av ) {
+ struct ib_address_vector *dest,
+ struct ib_address_vector *source ) {
struct ib_local_route_header *lrh;
struct ib_global_route_header *grh;
struct ib_base_transport_header *bth;
@@ -132,15 +137,14 @@
size_t orig_iob_len = iob_len ( iobuf );
unsigned int lnh;
size_t pad_len;
- unsigned long qpn;
- unsigned int lid;
/* Clear return values */
if ( qp )
*qp = NULL;
if ( payload_len )
*payload_len = 0;
- memset ( av, 0, sizeof ( *av ) );
+ memset ( dest, 0, sizeof ( *dest ) );
+ memset ( source, 0, sizeof ( *source ) );
/* Extract LRH */
if ( iob_len ( iobuf ) < sizeof ( *lrh ) ) {
@@ -150,10 +154,11 @@
}
lrh = iobuf->data;
iob_pull ( iobuf, sizeof ( *lrh ) );
- av->lid = ntohs ( lrh->slid );
- av->sl = ( lrh->sl__lnh >> 4 );
+ dest->lid = ntohs ( lrh->dlid );
+ dest->sl = ( lrh->sl__lnh >> 4 );
+ source->lid = ntohs ( lrh->slid );
+ source->sl = ( lrh->sl__lnh >> 4 );
lnh = ( lrh->sl__lnh & 0x3 );
- lid = ntohs ( lrh->dlid );
/* Reject unsupported packets */
if ( ! ( ( lnh == IB_LNH_BTH ) || ( lnh == IB_LNH_GRH ) ) ) {
@@ -171,8 +176,10 @@
}
grh = iobuf->data;
iob_pull ( iobuf, sizeof ( *grh ) );
- av->gid_present = 1;
- memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) );
+ dest->gid_present = 1;
+ memcpy ( &dest->gid, &grh->dgid, sizeof ( dest->gid ) );
+ source->gid_present = 1;
+ memcpy ( &source->gid, &grh->sgid, sizeof ( source->gid ) );
} else {
grh = NULL;
}
@@ -190,7 +197,7 @@
ibdev, bth->opcode );
return -ENOTSUP;
}
- qpn = ntohl ( bth->dest_qp );
+ dest->qpn = ntohl ( bth->dest_qp );
/* Extract DETH */
if ( iob_len ( iobuf ) < sizeof ( *deth ) ) {
@@ -200,8 +207,8 @@
}
deth = iobuf->data;
iob_pull ( iobuf, sizeof ( *deth ) );
- av->qpn = ntohl ( deth->src_qp );
- av->qkey = ntohl ( deth->qkey );
+ source->qpn = ntohl ( deth->src_qp );
+ source->qkey = ntohl ( deth->qkey );
/* Calculate payload length, if applicable */
if ( payload_len ) {
@@ -213,7 +220,7 @@
/* Determine destination QP, if applicable */
if ( qp ) {
- if ( IB_LID_MULTICAST ( lid ) && grh ) {
+ if ( IB_LID_MULTICAST ( dest->lid ) && grh ) {
if ( ! ( *qp = ib_find_qp_mgid ( ibdev, &grh->dgid ))){
DBGC ( ibdev, "IBDEV %p RX for unknown MGID "
IB_GID_FMT "\n",
@@ -221,9 +228,9 @@
return -ENODEV;
}
} else {
- if ( ! ( *qp = ib_find_qp_qpn ( ibdev, qpn ) ) ) {
+ if ( ! ( *qp = ib_find_qp_qpn ( ibdev, dest->qpn ) ) ) {
DBGC ( ibdev, "IBDEV %p RX for nonexistent "
- "QPN %lx\n", ibdev, qpn );
+ "QPN %lx\n", ibdev, dest->qpn );
return -ENODEV;
}
}
@@ -231,9 +238,9 @@
}
DBGC2 ( ibdev, "IBDEV %p RX %04x:%08lx <= %04x:%08lx (key %08x)\n",
- ibdev, lid, ( IB_LID_MULTICAST( lid ) ?
- ( qp ? (*qp)->ext_qpn : -1UL ) : qpn ),
- av->lid, av->qpn, ntohl ( deth->qkey ) );
+ ibdev, dest->lid, ( IB_LID_MULTICAST ( dest->lid ) ?
+ ( qp ? (*qp)->ext_qpn : -1UL ) : dest->qpn ),
+ source->lid, source->qpn, ntohl ( deth->qkey ) );
DBGCP_HDA ( ibdev, 0,
( iobuf->data - ( orig_iob_len - iob_len ( iobuf ) ) ),
( orig_iob_len - iob_len ( iobuf ) ) );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/netdevice.c
^
|
@@ -486,6 +486,7 @@
err_probe:
for_each_table_entry_continue_reverse ( driver, NET_DRIVERS )
driver->remove ( netdev );
+ clear_settings ( netdev_settings ( netdev ) );
unregister_settings ( netdev_settings ( netdev ) );
err_register_settings:
return rc;
@@ -570,6 +571,7 @@
driver->remove ( netdev );
/* Unregister per-netdev configuration settings */
+ clear_settings ( netdev_settings ( netdev ) );
unregister_settings ( netdev_settings ( netdev ) );
/* Remove from device list */
@@ -672,13 +674,6 @@
struct ll_protocol *ll_protocol = netdev->ll_protocol;
int rc;
- /* Force a poll on the netdevice to (potentially) clear any
- * backed-up TX completions. This is needed on some network
- * devices to avoid excessive losses due to small TX ring
- * sizes.
- */
- netdev_poll ( netdev );
-
/* Add link-layer header */
if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, ll_source,
net_protocol->net_proto ) ) != 0 ) {
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/retry.c
^
|
@@ -177,11 +177,10 @@
}
/**
- * Single-step the retry timer list
+ * Poll the retry timer list
*
- * @v process Retry timer process
*/
-static void retry_step ( struct process *process __unused ) {
+void retry_poll ( void ) {
struct retry_timer *timer;
unsigned long now = currticks();
unsigned long used;
@@ -200,5 +199,14 @@
}
}
+/**
+ * Single-step the retry timer list
+ *
+ * @v process Retry timer process
+ */
+static void retry_step ( struct process *process __unused ) {
+ retry_poll();
+}
+
/** Retry timer process */
PERMANENT_PROCESS ( retry_process, retry_step );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/tcp/ftp.c
^
|
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
@@ -34,6 +53,7 @@
FTP_USER,
FTP_PASS,
FTP_TYPE,
+ FTP_SIZE,
FTP_PASV,
FTP_RETR,
FTP_WAIT,
@@ -68,6 +88,8 @@
char status_text[5];
/** Passive-mode parameters, as text */
char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */
+ /** File size, as text */
+ char filesize[20];
};
/**
@@ -157,6 +179,7 @@
[FTP_USER] = { "USER ", ftp_user },
[FTP_PASS] = { "PASS ", ftp_password },
[FTP_TYPE] = { "TYPE I", NULL },
+ [FTP_SIZE] = { "SIZE ", ftp_uri_path },
[FTP_PASV] = { "PASV", NULL },
[FTP_RETR] = { "RETR ", ftp_uri_path },
[FTP_WAIT] = { NULL, NULL },
@@ -234,6 +257,14 @@
if ( status_major == '1' )
return;
+ /* If the SIZE command is not supported by the server, we go to
+ * the next step.
+ */
+ if ( ( status_major == '5' ) && ( ftp->state == FTP_SIZE ) ) {
+ ftp_next_state ( ftp );
+ return;
+ }
+
/* Anything other than success (2xx) or, in the case of a
* repsonse to a "USER" command, a password prompt (3xx), is a
* fatal error.
@@ -245,6 +276,26 @@
return;
}
+ /* Parse file size */
+ if ( ftp->state == FTP_SIZE ) {
+ size_t filesize;
+ char *endptr;
+
+ /* Parse size */
+ filesize = strtoul ( ftp->filesize, &endptr, 10 );
+ if ( *endptr != '\0' ) {
+ DBGC ( ftp, "FTP %p invalid SIZE \"%s\"\n",
+ ftp, ftp->filesize );
+ ftp_done ( ftp, -EPROTO );
+ return;
+ }
+
+ /* Use seek() to notify recipient of filesize */
+ DBGC ( ftp, "FTP %p file size is %zd bytes\n", ftp, filesize );
+ xfer_seek ( &ftp->xfer, filesize );
+ xfer_seek ( &ftp->xfer, 0 );
+ }
+
/* Open passive connection when we get "PASV" response */
if ( ftp->state == FTP_PASV ) {
char *ptr = ftp->passive_text;
@@ -295,35 +346,33 @@
while ( len-- ) {
c = *(data++);
- switch ( c ) {
- case '\r' :
- case '\n' :
+ if ( ( c == '\r' ) || ( c == '\n' ) ) {
/* End of line: call ftp_reply() to handle
* completed reply. Avoid calling ftp_reply()
* twice if we receive both \r and \n.
*/
- if ( recvsize == 0 )
+ if ( recvbuf != ftp->status_text )
ftp_reply ( ftp );
/* Start filling up the status code buffer */
recvbuf = ftp->status_text;
recvsize = sizeof ( ftp->status_text ) - 1;
- break;
- case '(' :
+ } else if ( ( ftp->state == FTP_PASV ) && ( c == '(' ) ) {
/* Start filling up the passive parameter buffer */
recvbuf = ftp->passive_text;
recvsize = sizeof ( ftp->passive_text ) - 1;
- break;
- case ')' :
+ } else if ( ( ftp->state == FTP_PASV ) && ( c == ')' ) ) {
/* Stop filling the passive parameter buffer */
recvsize = 0;
- break;
- default :
+ } else if ( ( ftp->state == FTP_SIZE ) && ( c == ' ' ) ) {
+ /* Start filling up the file size buffer */
+ recvbuf = ftp->filesize;
+ recvsize = sizeof ( ftp->filesize ) - 1;
+ } else {
/* Fill up buffer if applicable */
if ( recvsize > 0 ) {
*(recvbuf++) = c;
recvsize--;
}
- break;
}
}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/tcp/httpcore.c
^
|
@@ -60,9 +60,6 @@
#define EIO_CONTENT_LENGTH __einfo_error ( EINFO_EIO_CONTENT_LENGTH )
#define EINFO_EIO_CONTENT_LENGTH \
__einfo_uniqify ( EINFO_EIO, 0x02, "Content length mismatch" )
-#define EIO_CHUNK __einfo_error ( EINFO_EIO_CHUNK )
-#define EINFO_EIO_CHUNK \
- __einfo_uniqify ( EINFO_EIO, 0x03, "Terminated mid-chunk" )
#define EINVAL_RESPONSE __einfo_error ( EINFO_EINVAL_RESPONSE )
#define EINFO_EINVAL_RESPONSE \
__einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid content length" )
@@ -111,7 +108,14 @@
HTTP_RX_RESPONSE = 0,
HTTP_RX_HEADER,
HTTP_RX_CHUNK_LEN,
+ /* In HTTP_RX_DATA, it is acceptable for the server to close
+ * the connection (unless we are in the middle of a chunked
+ * transfer).
+ */
HTTP_RX_DATA,
+ /* In the following states, it is acceptable for the server to
+ * close the connection.
+ */
HTTP_RX_TRAILER,
HTTP_RX_IDLE,
HTTP_RX_DEAD,
@@ -251,10 +255,14 @@
static void http_done ( struct http_request *http ) {
int rc;
- /* If we are in the middle of a chunked transfer, force an error */
- if ( http->chunked ) {
- DBGC ( http, "HTTP %p terminated mid-chunk\n", http );
- http_close ( http, -EIO_CHUNK );
+ /* If we are not at an appropriate stage of the protocol
+ * (including being in the middle of a chunked transfer),
+ * force an error.
+ */
+ if ( ( http->rx_state < HTTP_RX_DATA ) || ( http->chunked != 0 ) ) {
+ DBGC ( http, "HTTP %p connection closed unexpectedly in state "
+ "%d\n", http, http->rx_state );
+ http_close ( http, -ECONNRESET );
return;
}
@@ -354,8 +362,9 @@
return -EINVAL_RESPONSE;
http->code = strtoul ( spc, NULL, 10 );
- /* Move to received headers */
- http->rx_state = HTTP_RX_HEADER;
+ /* Move to receive headers */
+ http->rx_state = ( ( http->flags & HTTP_HEAD_ONLY ) ?
+ HTTP_RX_TRAILER : HTTP_RX_HEADER );
return 0;
}
@@ -689,8 +698,7 @@
}
/* Move to next state */
- if ( ( http->rx_state == HTTP_RX_HEADER ) &&
- ( ! ( http->flags & HTTP_HEAD_ONLY ) ) ) {
+ if ( http->rx_state == HTTP_RX_HEADER ) {
DBGC ( http, "HTTP %p start of data\n", http );
http->rx_state = ( http->chunked ?
HTTP_RX_CHUNK_LEN : HTTP_RX_DATA );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/tls.c
^
|
@@ -49,10 +49,122 @@
#include <ipxe/tls.h>
/* Disambiguate the various error causes */
-#define EACCES_WRONG_NAME \
- __einfo_error ( EINFO_EACCES_WRONG_NAME )
-#define EINFO_EACCES_WRONG_NAME \
- __einfo_uniqify ( EINFO_EACCES, 0x02, "Incorrect server name" )
+#define EACCES_WRONG_NAME __einfo_error ( EINFO_EACCES_WRONG_NAME )
+#define EINFO_EACCES_WRONG_NAME \
+ __einfo_uniqify ( EINFO_EACCES, 0x02, \
+ "Incorrect server name" )
+#define EINVAL_CHANGE_CIPHER __einfo_error ( EINFO_EINVAL_CHANGE_CIPHER )
+#define EINFO_EINVAL_CHANGE_CIPHER \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, \
+ "Invalid Change Cipher record" )
+#define EINVAL_ALERT __einfo_error ( EINFO_EINVAL_ALERT )
+#define EINFO_EINVAL_ALERT \
+ __einfo_uniqify ( EINFO_EINVAL, 0x02, \
+ "Invalid Alert record" )
+#define EINVAL_HELLO __einfo_error ( EINFO_EINVAL_HELLO )
+#define EINFO_EINVAL_HELLO \
+ __einfo_uniqify ( EINFO_EINVAL, 0x03, \
+ "Invalid Server Hello record" )
+#define EINVAL_CERTIFICATE __einfo_error ( EINFO_EINVAL_CERTIFICATE )
+#define EINFO_EINVAL_CERTIFICATE \
+ __einfo_uniqify ( EINFO_EINVAL, 0x04, \
+ "Invalid Certificate" )
+#define EINVAL_CERTIFICATES __einfo_error ( EINFO_EINVAL_CERTIFICATES )
+#define EINFO_EINVAL_CERTIFICATES \
+ __einfo_uniqify ( EINFO_EINVAL, 0x05, \
+ "Invalid Server Certificate record" )
+#define EINVAL_HELLO_DONE __einfo_error ( EINFO_EINVAL_HELLO_DONE )
+#define EINFO_EINVAL_HELLO_DONE \
+ __einfo_uniqify ( EINFO_EINVAL, 0x06, \
+ "Invalid Server Hello Done record" )
+#define EINVAL_FINISHED __einfo_error ( EINFO_EINVAL_FINISHED )
+#define EINFO_EINVAL_FINISHED \
+ __einfo_uniqify ( EINFO_EINVAL, 0x07, \
+ "Invalid Server Finished record" )
+#define EINVAL_HANDSHAKE __einfo_error ( EINFO_EINVAL_HANDSHAKE )
+#define EINFO_EINVAL_HANDSHAKE \
+ __einfo_uniqify ( EINFO_EINVAL, 0x08, \
+ "Invalid Handshake record" )
+#define EINVAL_STREAM __einfo_error ( EINFO_EINVAL_STREAM )
+#define EINFO_EINVAL_STREAM \
+ __einfo_uniqify ( EINFO_EINVAL, 0x09, \
+ "Invalid stream-ciphered record" )
+#define EINVAL_BLOCK __einfo_error ( EINFO_EINVAL_BLOCK )
+#define EINFO_EINVAL_BLOCK \
+ __einfo_uniqify ( EINFO_EINVAL, 0x0a, \
+ "Invalid block-ciphered record" )
+#define EINVAL_PADDING __einfo_error ( EINFO_EINVAL_PADDING )
+#define EINFO_EINVAL_PADDING \
+ __einfo_uniqify ( EINFO_EINVAL, 0x0b, \
+ "Invalid block padding" )
+#define EINVAL_RX_STATE __einfo_error ( EINFO_EINVAL_RX_STATE )
+#define EINFO_EINVAL_RX_STATE \
+ __einfo_uniqify ( EINFO_EINVAL, 0x0c, \
+ "Invalid receive state" )
+#define EINVAL_MAC __einfo_error ( EINFO_EINVAL_MAC )
+#define EINFO_EINVAL_MAC \
+ __einfo_uniqify ( EINFO_EINVAL, 0x0d, \
+ "Invalid MAC" )
+#define EINVAL_NON_DATA __einfo_error ( EINFO_EINVAL_NON_DATA )
+#define EINFO_EINVAL_NON_DATA \
+ __einfo_uniqify ( EINFO_EINVAL, 0x0e, \
+ "Overlength non-data record" )
+#define EIO_ALERT __einfo_error ( EINFO_EIO_ALERT )
+#define EINFO_EIO_ALERT \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, \
+ "Unknown alert level" )
+#define ENOMEM_CONTEXT __einfo_error ( EINFO_ENOMEM_CONTEXT )
+#define EINFO_ENOMEM_CONTEXT \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x01, \
+ "Not enough space for crypto context" )
+#define ENOMEM_CERTIFICATE __einfo_error ( EINFO_ENOMEM_CERTIFICATE )
+#define EINFO_ENOMEM_CERTIFICATE \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x02, \
+ "Not enough space for certificate" )
+#define ENOMEM_CHAIN __einfo_error ( EINFO_ENOMEM_CHAIN )
+#define EINFO_ENOMEM_CHAIN \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x03, \
+ "Not enough space for certificate chain" )
+#define ENOMEM_TX_PLAINTEXT __einfo_error ( EINFO_ENOMEM_TX_PLAINTEXT )
+#define EINFO_ENOMEM_TX_PLAINTEXT \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x04, \
+ "Not enough space for transmitted plaintext" )
+#define ENOMEM_TX_CIPHERTEXT __einfo_error ( EINFO_ENOMEM_TX_CIPHERTEXT )
+#define EINFO_ENOMEM_TX_CIPHERTEXT \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x05, \
+ "Not enough space for transmitted ciphertext" )
+#define ENOMEM_RX_DATA __einfo_error ( EINFO_ENOMEM_RX_DATA )
+#define EINFO_ENOMEM_RX_DATA \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x07, \
+ "Not enough space for received data" )
+#define ENOTSUP_CIPHER __einfo_error ( EINFO_ENOTSUP_CIPHER )
+#define EINFO_ENOTSUP_CIPHER \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \
+ "Unsupported cipher" )
+#define ENOTSUP_NULL __einfo_error ( EINFO_ENOTSUP_NULL )
+#define EINFO_ENOTSUP_NULL \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x02, \
+ "Refusing to use null cipher" )
+#define ENOTSUP_SIG_HASH __einfo_error ( EINFO_ENOTSUP_SIG_HASH )
+#define EINFO_ENOTSUP_SIG_HASH \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x03, \
+ "Unsupported signature and hash algorithm" )
+#define ENOTSUP_VERSION __einfo_error ( EINFO_ENOTSUP_VERSION )
+#define EINFO_ENOTSUP_VERSION \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x04, \
+ "Unsupported protocol version" )
+#define EPERM_ALERT __einfo_error ( EINFO_EPERM_ALERT )
+#define EINFO_EPERM_ALERT \
+ __einfo_uniqify ( EINFO_EPERM, 0x01, \
+ "Received fatal alert" )
+#define EPERM_VERIFY __einfo_error ( EINFO_EPERM_VERIFY )
+#define EINFO_EPERM_VERIFY \
+ __einfo_uniqify ( EINFO_EPERM, 0x02, \
+ "Handshake verification failed" )
+#define EPROTO_VERSION __einfo_error ( EINFO_EPROTO_VERSION )
+#define EINFO_EPROTO_VERSION \
+ __einfo_uniqify ( EINFO_EPROTO, 0x01, \
+ "Illegal protocol version upgrade" )
static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
const void *data, size_t len );
@@ -187,13 +299,18 @@
static void free_tls ( struct refcnt *refcnt ) {
struct tls_session *tls =
container_of ( refcnt, struct tls_session, refcnt );
+ struct io_buffer *iobuf;
+ struct io_buffer *tmp;
/* Free dynamically-allocated resources */
tls_clear_cipher ( tls, &tls->tx_cipherspec );
tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
tls_clear_cipher ( tls, &tls->rx_cipherspec );
tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
- free ( tls->rx_data );
+ list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) {
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
+ }
x509_chain_put ( tls->chain );
/* Free TLS structure itself */
@@ -640,7 +757,7 @@
if ( ! dynamic ) {
DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
"context\n", tls, total );
- return -ENOMEM;
+ return -ENOMEM_CONTEXT;
}
/* Assign storage */
@@ -674,7 +791,7 @@
if ( ! suite ) {
DBGC ( tls, "TLS %p does not support cipher %04x\n",
tls, ntohs ( cipher_suite ) );
- return -ENOTSUP;
+ return -ENOTSUP_CIPHER;
}
/* Set ciphers */
@@ -707,7 +824,7 @@
/* Sanity check */
if ( pending->suite == &tls_cipher_suite_null ) {
DBGC ( tls, "TLS %p refusing to use null cipher\n", tls );
- return -ENOTSUP;
+ return -ENOTSUP_NULL;
}
tls_clear_cipher ( tls, active );
@@ -905,7 +1022,7 @@
hello.extensions.max_fragment_length_len
= htons ( sizeof ( hello.extensions.max_fragment_length ) );
hello.extensions.max_fragment_length.max
- = TLS_MAX_FRAGMENT_LENGTH_2048;
+ = TLS_MAX_FRAGMENT_LENGTH_4096;
return tls_send_handshake ( tls, &hello, sizeof ( hello ) );
}
@@ -957,7 +1074,7 @@
*/
certificate = zalloc ( sizeof ( *certificate ) );
if ( ! certificate )
- return -ENOMEM;
+ return -ENOMEM_CERTIFICATE;
/* Populate record */
certificate->type_length =
@@ -1059,7 +1176,7 @@
DBGC ( tls, "TLS %p could not identify (%s,%s) "
"signature and hash algorithm\n", tls,
pubkey->name, digest->name );
- rc = -ENOTSUP;
+ rc = -ENOTSUP_SIG_HASH;
goto err_sig_hash;
}
}
@@ -1179,7 +1296,7 @@
if ( ( len != 1 ) || ( *( ( uint8_t * ) data ) != 1 ) ) {
DBGC ( tls, "TLS %p received invalid Change Cipher\n", tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_CHANGE_CIPHER;
}
if ( ( rc = tls_change_cipher ( tls, &tls->rx_cipherspec_pending,
@@ -1214,7 +1331,7 @@
if ( end != ( data + len ) ) {
DBGC ( tls, "TLS %p received overlength Alert\n", tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_ALERT;
}
switch ( alert->level ) {
@@ -1225,11 +1342,11 @@
case TLS_ALERT_FATAL:
DBGC ( tls, "TLS %p received fatal alert %d\n",
tls, alert->description );
- return -EPERM;
+ return -EPERM_ALERT;
default:
DBGC ( tls, "TLS %p received unknown alert level %d"
"(alert %d)\n", tls, alert->level, alert->description );
- return -EIO;
+ return -EIO_ALERT;
}
}
@@ -1263,7 +1380,7 @@
if ( end > ( data + len ) ) {
DBGC ( tls, "TLS %p received underlength Server Hello\n", tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_HELLO;
}
/* Check and store protocol version */
@@ -1271,13 +1388,13 @@
if ( version < TLS_VERSION_TLS_1_0 ) {
DBGC ( tls, "TLS %p does not support protocol version %d.%d\n",
tls, ( version >> 8 ), ( version & 0xff ) );
- return -ENOTSUP;
+ return -ENOTSUP_VERSION;
}
if ( version > tls->version ) {
DBGC ( tls, "TLS %p server attempted to illegally upgrade to "
"protocol version %d.%d\n",
tls, ( version >> 8 ), ( version & 0xff ) );
- return -EPROTO;
+ return -EPROTO_VERSION;
}
tls->version = version;
DBGC ( tls, "TLS %p using protocol version %d.%d\n",
@@ -1334,7 +1451,7 @@
/* Create certificate chain */
tls->chain = x509_alloc_chain();
if ( ! tls->chain ) {
- rc = -ENOMEM;
+ rc = -ENOMEM_CHAIN;
goto err_alloc_chain;
}
@@ -1348,7 +1465,7 @@
if ( next > end ) {
DBGC ( tls, "TLS %p overlength certificate:\n", tls );
DBGC_HDA ( tls, 0, data, ( end - data ) );
- rc = -EINVAL;
+ rc = -EINVAL_CERTIFICATE;
goto err_overlength;
}
@@ -1401,7 +1518,7 @@
DBGC ( tls, "TLS %p received overlength Server Certificate\n",
tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_CERTIFICATES;
}
/* Parse certificate chain */
@@ -1456,7 +1573,7 @@
DBGC ( tls, "TLS %p received overlength Server Hello Done\n",
tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_HELLO_DONE;
}
/* Begin certificate validation */
@@ -1492,7 +1609,7 @@
if ( end != ( data + len ) ) {
DBGC ( tls, "TLS %p received overlength Finished\n", tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_FINISHED;
}
/* Verify data */
@@ -1503,7 +1620,7 @@
if ( memcmp ( verify_data, finished->verify_data,
sizeof ( verify_data ) ) != 0 ) {
DBGC ( tls, "TLS %p verification failed\n", tls );
- return -EPERM;
+ return -EPERM_VERIFY;
}
/* Mark server as finished */
@@ -1543,7 +1660,7 @@
DBGC ( tls, "TLS %p received overlength Handshake\n",
tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_HANDSHAKE;
}
switch ( handshake->type ) {
@@ -1595,31 +1712,71 @@
*
* @v tls TLS session
* @v type Record type
- * @v data Plaintext record
- * @v len Length of plaintext record
+ * @v rx_data List of received data buffers
* @ret rc Return status code
*/
static int tls_new_record ( struct tls_session *tls, unsigned int type,
- const void *data, size_t len ) {
+ struct list_head *rx_data ) {
+ struct io_buffer *iobuf;
+ int ( * handler ) ( struct tls_session *tls, const void *data,
+ size_t len );
+ int rc;
+
+ /* Deliver data records to the plainstream interface */
+ if ( type == TLS_TYPE_DATA ) {
+
+ /* Fail unless we are ready to receive data */
+ if ( ! tls_ready ( tls ) )
+ return -ENOTCONN;
+ /* Deliver each I/O buffer in turn */
+ while ( ( iobuf = list_first_entry ( rx_data, struct io_buffer,
+ list ) ) ) {
+ list_del ( &iobuf->list );
+ if ( ( rc = xfer_deliver_iob ( &tls->plainstream,
+ iobuf ) ) != 0 ) {
+ DBGC ( tls, "TLS %p could not deliver data: "
+ "%s\n", tls, strerror ( rc ) );
+ return rc;
+ }
+ }
+ return 0;
+ }
+
+ /* For all other records, fail unless we have exactly one I/O buffer */
+ iobuf = list_first_entry ( rx_data, struct io_buffer, list );
+ assert ( iobuf != NULL );
+ list_del ( &iobuf->list );
+ if ( ! list_empty ( rx_data ) ) {
+ DBGC ( tls, "TLS %p overlength non-data record\n", tls );
+ free_iob ( iobuf );
+ return -EINVAL_NON_DATA;
+ }
+
+ /* Determine handler */
switch ( type ) {
case TLS_TYPE_CHANGE_CIPHER:
- return tls_new_change_cipher ( tls, data, len );
+ handler = tls_new_change_cipher;
+ break;
case TLS_TYPE_ALERT:
- return tls_new_alert ( tls, data, len );
+ handler = tls_new_alert;
+ break;
case TLS_TYPE_HANDSHAKE:
- return tls_new_handshake ( tls, data, len );
- case TLS_TYPE_DATA:
- if ( ! tls_ready ( tls ) )
- return -ENOTCONN;
- return xfer_deliver_raw ( &tls->plainstream, data, len );
+ handler = tls_new_handshake;
+ break;
default:
/* RFC4346 says that we should just ignore unknown
* record types.
*/
+ handler = NULL;
DBGC ( tls, "TLS %p ignoring record type %d\n", tls, type );
- return 0;
+ break;
}
+
+ /* Handle record and free I/O buffer */
+ rc = ( handler ? handler ( tls, iobuf->data, iob_len ( iobuf ) ) : 0 );
+ free_iob ( iobuf );
+ return rc;
}
/******************************************************************************
@@ -1630,9 +1787,56 @@
*/
/**
+ * Initialise HMAC
+ *
+ * @v cipherspec Cipher specification
+ * @v ctx Context
+ * @v seq Sequence number
+ * @v tlshdr TLS header
+ */
+static void tls_hmac_init ( struct tls_cipherspec *cipherspec, void *ctx,
+ uint64_t seq, struct tls_header *tlshdr ) {
+ struct digest_algorithm *digest = cipherspec->suite->digest;
+
+ hmac_init ( digest, ctx, cipherspec->mac_secret, &digest->digestsize );
+ seq = cpu_to_be64 ( seq );
+ hmac_update ( digest, ctx, &seq, sizeof ( seq ) );
+ hmac_update ( digest, ctx, tlshdr, sizeof ( *tlshdr ) );
+}
+
+/**
+ * Update HMAC
+ *
+ * @v cipherspec Cipher specification
+ * @v ctx Context
+ * @v data Data
+ * @v len Length of data
+ */
+static void tls_hmac_update ( struct tls_cipherspec *cipherspec, void *ctx,
+ const void *data, size_t len ) {
+ struct digest_algorithm *digest = cipherspec->suite->digest;
+
+ hmac_update ( digest, ctx, data, len );
+}
+
+/**
+ * Finalise HMAC
+ *
+ * @v cipherspec Cipher specification
+ * @v ctx Context
+ * @v mac HMAC to fill in
+ */
+static void tls_hmac_final ( struct tls_cipherspec *cipherspec, void *ctx,
+ void *hmac ) {
+ struct digest_algorithm *digest = cipherspec->suite->digest;
+
+ hmac_final ( digest, ctx, cipherspec->mac_secret,
+ &digest->digestsize, hmac );
+}
+
+/**
* Calculate HMAC
*
- * @v tls TLS session
* @v cipherspec Cipher specification
* @v seq Sequence number
* @v tlshdr TLS header
@@ -1640,21 +1844,15 @@
* @v len Length of data
* @v mac HMAC to fill in
*/
-static void tls_hmac ( struct tls_session *tls __unused,
- struct tls_cipherspec *cipherspec,
+static void tls_hmac ( struct tls_cipherspec *cipherspec,
uint64_t seq, struct tls_header *tlshdr,
const void *data, size_t len, void *hmac ) {
struct digest_algorithm *digest = cipherspec->suite->digest;
- uint8_t digest_ctx[digest->ctxsize];
+ uint8_t ctx[digest->ctxsize];
- hmac_init ( digest, digest_ctx, cipherspec->mac_secret,
- &digest->digestsize );
- seq = cpu_to_be64 ( seq );
- hmac_update ( digest, digest_ctx, &seq, sizeof ( seq ) );
- hmac_update ( digest, digest_ctx, tlshdr, sizeof ( *tlshdr ) );
- hmac_update ( digest, digest_ctx, data, len );
- hmac_final ( digest, digest_ctx, cipherspec->mac_secret,
- &digest->digestsize, hmac );
+ tls_hmac_init ( cipherspec, ctx, seq, tlshdr );
+ tls_hmac_update ( cipherspec, ctx, data, len );
+ tls_hmac_final ( cipherspec, ctx, hmac );
}
/**
@@ -1769,8 +1967,7 @@
plaintext_tlshdr.length = htons ( len );
/* Calculate MAC */
- tls_hmac ( tls, cipherspec, tls->tx_seq, &plaintext_tlshdr,
- data, len, mac );
+ tls_hmac ( cipherspec, tls->tx_seq, &plaintext_tlshdr, data, len, mac );
/* Allocate and assemble plaintext struct */
if ( is_stream_cipher ( cipher ) ) {
@@ -1783,7 +1980,7 @@
if ( ! plaintext ) {
DBGC ( tls, "TLS %p could not allocate %zd bytes for "
"plaintext\n", tls, plaintext_len );
- rc = -ENOMEM;
+ rc = -ENOMEM_TX_PLAINTEXT;
goto done;
}
@@ -1796,7 +1993,7 @@
if ( ! ciphertext ) {
DBGC ( tls, "TLS %p could not allocate %zd bytes for "
"ciphertext\n", tls, ciphertext_len );
- rc = -ENOMEM;
+ rc = -ENOMEM_TX_CIPHERTEXT;
goto done;
}
@@ -1837,36 +2034,25 @@
* Split stream-ciphered record into data and MAC portions
*
* @v tls TLS session
- * @v plaintext Plaintext record
- * @v plaintext_len Length of record
- * @ret data Data
- * @ret len Length of data
- * @ret digest MAC digest
+ * @v rx_data List of received data buffers
+ * @v mac MAC to fill in
* @ret rc Return status code
*/
static int tls_split_stream ( struct tls_session *tls,
- void *plaintext, size_t plaintext_len,
- void **data, size_t *len, void **digest ) {
- void *content;
- size_t content_len;
- void *mac;
- size_t mac_len;
-
- /* Decompose stream-ciphered data */
- mac_len = tls->rx_cipherspec.suite->digest->digestsize;
- if ( plaintext_len < mac_len ) {
- DBGC ( tls, "TLS %p received underlength record\n", tls );
- DBGC_HD ( tls, plaintext, plaintext_len );
- return -EINVAL;
+ struct list_head *rx_data, void **mac ) {
+ size_t mac_len = tls->rx_cipherspec.suite->digest->digestsize;
+ struct io_buffer *iobuf;
+
+ /* Extract MAC */
+ iobuf = list_last_entry ( rx_data, struct io_buffer, list );
+ assert ( iobuf != NULL );
+ if ( iob_len ( iobuf ) < mac_len ) {
+ DBGC ( tls, "TLS %p received underlength MAC\n", tls );
+ DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
+ return -EINVAL_STREAM;
}
- content_len = ( plaintext_len - mac_len );
- content = plaintext;
- mac = ( content + content_len );
-
- /* Fill in return values */
- *data = content;
- *len = content_len;
- *digest = mac;
+ iob_unput ( iobuf, mac_len );
+ *mac = iobuf->tail;
return 0;
}
@@ -1875,65 +2061,56 @@
* Split block-ciphered record into data and MAC portions
*
* @v tls TLS session
- * @v plaintext Plaintext record
- * @v plaintext_len Length of record
- * @ret data Data
- * @ret len Length of data
- * @ret digest MAC digest
+ * @v rx_data List of received data buffers
+ * @v mac MAC to fill in
* @ret rc Return status code
*/
static int tls_split_block ( struct tls_session *tls,
- void *plaintext, size_t plaintext_len,
- void **data, size_t *len,
- void **digest ) {
- void *iv;
+ struct list_head *rx_data, void **mac ) {
+ size_t mac_len = tls->rx_cipherspec.suite->digest->digestsize;
+ struct io_buffer *iobuf;
size_t iv_len;
- void *content;
- size_t content_len;
- void *mac;
- size_t mac_len;
- void *padding;
+ uint8_t *padding_final;
+ uint8_t *padding;
size_t padding_len;
- unsigned int i;
-
- /* Sanity check */
- if ( plaintext_len < 1 ) {
- DBGC ( tls, "TLS %p received underlength record\n", tls );
- DBGC_HD ( tls, plaintext, plaintext_len );
- return -EINVAL;
- }
/* TLSv1.1 and later use an explicit IV */
+ iobuf = list_first_entry ( rx_data, struct io_buffer, list );
iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ?
tls->rx_cipherspec.suite->cipher->blocksize : 0 );
-
- /* Decompose block-ciphered data */
- mac_len = tls->rx_cipherspec.suite->digest->digestsize;
- padding_len = *( ( uint8_t * ) ( plaintext + plaintext_len - 1 ) );
- if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) {
- DBGC ( tls, "TLS %p received underlength record\n", tls );
- DBGC_HD ( tls, plaintext, plaintext_len );
- return -EINVAL;
- }
- content_len = ( plaintext_len - iv_len - mac_len - padding_len - 1 );
- iv = plaintext;
- content = ( iv + iv_len );
- mac = ( content + content_len );
- padding = ( mac + mac_len );
-
- /* Verify padding bytes */
- for ( i = 0 ; i < padding_len ; i++ ) {
- if ( *( ( uint8_t * ) ( padding + i ) ) != padding_len ) {
+ if ( iob_len ( iobuf ) < iv_len ) {
+ DBGC ( tls, "TLS %p received underlength IV\n", tls );
+ DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
+ return -EINVAL_BLOCK;
+ }
+ iob_pull ( iobuf, iv_len );
+
+ /* Extract and verify padding */
+ iobuf = list_last_entry ( rx_data, struct io_buffer, list );
+ padding_final = ( iobuf->tail - 1 );
+ padding_len = *padding_final;
+ if ( ( padding_len + 1 ) > iob_len ( iobuf ) ) {
+ DBGC ( tls, "TLS %p received underlength padding\n", tls );
+ DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
+ return -EINVAL_BLOCK;
+ }
+ iob_unput ( iobuf, ( padding_len + 1 ) );
+ for ( padding = iobuf->tail ; padding < padding_final ; padding++ ) {
+ if ( *padding != padding_len ) {
DBGC ( tls, "TLS %p received bad padding\n", tls );
- DBGC_HD ( tls, plaintext, plaintext_len );
- return -EINVAL;
+ DBGC_HD ( tls, padding, padding_len );
+ return -EINVAL_PADDING;
}
}
- /* Fill in return values */
- *data = content;
- *len = content_len;
- *digest = mac;
+ /* Extract MAC */
+ if ( iob_len ( iobuf ) < mac_len ) {
+ DBGC ( tls, "TLS %p received underlength MAC\n", tls );
+ DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) );
+ return -EINVAL_BLOCK;
+ }
+ iob_unput ( iobuf, mac_len );
+ *mac = iobuf->tail;
return 0;
}
@@ -1943,71 +2120,65 @@
*
* @v tls TLS session
* @v tlshdr Record header
- * @v ciphertext Ciphertext record
+ * @v rx_data List of received data buffers
* @ret rc Return status code
*/
static int tls_new_ciphertext ( struct tls_session *tls,
struct tls_header *tlshdr,
- const void *ciphertext ) {
+ struct list_head *rx_data ) {
struct tls_header plaintext_tlshdr;
struct tls_cipherspec *cipherspec = &tls->rx_cipherspec;
struct cipher_algorithm *cipher = cipherspec->suite->cipher;
- size_t record_len = ntohs ( tlshdr->length );
- void *plaintext = NULL;
- void *data;
- size_t len;
+ struct digest_algorithm *digest = cipherspec->suite->digest;
+ uint8_t ctx[digest->ctxsize];
+ uint8_t verify_mac[digest->digestsize];
+ struct io_buffer *iobuf;
void *mac;
- size_t mac_len = cipherspec->suite->digest->digestsize;
- uint8_t verify_mac[mac_len];
+ size_t len = 0;
int rc;
- /* Allocate buffer for plaintext */
- plaintext = malloc ( record_len );
- if ( ! plaintext ) {
- DBGC ( tls, "TLS %p could not allocate %zd bytes for "
- "decryption buffer\n", tls, record_len );
- rc = -ENOMEM;
- goto done;
+ /* Decrypt the received data */
+ list_for_each_entry ( iobuf, &tls->rx_data, list ) {
+ cipher_decrypt ( cipher, cipherspec->cipher_ctx,
+ iobuf->data, iobuf->data, iob_len ( iobuf ) );
}
- /* Decrypt the record */
- cipher_decrypt ( cipher, cipherspec->cipher_ctx,
- ciphertext, plaintext, record_len );
-
/* Split record into content and MAC */
if ( is_stream_cipher ( cipher ) ) {
- if ( ( rc = tls_split_stream ( tls, plaintext, record_len,
- &data, &len, &mac ) ) != 0 )
- goto done;
+ if ( ( rc = tls_split_stream ( tls, rx_data, &mac ) ) != 0 )
+ return rc;
} else {
- if ( ( rc = tls_split_block ( tls, plaintext, record_len,
- &data, &len, &mac ) ) != 0 )
- goto done;
+ if ( ( rc = tls_split_block ( tls, rx_data, &mac ) ) != 0 )
+ return rc;
+ }
+
+ /* Calculate total length */
+ DBGC2 ( tls, "Received plaintext data:\n" );
+ list_for_each_entry ( iobuf, rx_data, list ) {
+ DBGC2_HD ( tls, iobuf->data, iob_len ( iobuf ) );
+ len += iob_len ( iobuf );
}
/* Verify MAC */
plaintext_tlshdr.type = tlshdr->type;
plaintext_tlshdr.version = tlshdr->version;
plaintext_tlshdr.length = htons ( len );
- tls_hmac ( tls, cipherspec, tls->rx_seq, &plaintext_tlshdr,
- data, len, verify_mac);
- if ( memcmp ( mac, verify_mac, mac_len ) != 0 ) {
+ tls_hmac_init ( cipherspec, ctx, tls->rx_seq, &plaintext_tlshdr );
+ list_for_each_entry ( iobuf, rx_data, list ) {
+ tls_hmac_update ( cipherspec, ctx, iobuf->data,
+ iob_len ( iobuf ) );
+ }
+ tls_hmac_final ( cipherspec, ctx, verify_mac );
+ if ( memcmp ( mac, verify_mac, sizeof ( verify_mac ) ) != 0 ) {
DBGC ( tls, "TLS %p failed MAC verification\n", tls );
- DBGC_HD ( tls, plaintext, record_len );
- goto done;
+ return -EINVAL_MAC;
}
- DBGC2 ( tls, "Received plaintext data:\n" );
- DBGC2_HD ( tls, data, len );
-
/* Process plaintext record */
- if ( ( rc = tls_new_record ( tls, tlshdr->type, data, len ) ) != 0 )
- goto done;
+ if ( ( rc = tls_new_record ( tls, tlshdr->type, rx_data ) ) != 0 )
+ return rc;
- rc = 0;
- done:
- free ( plaintext );
- return rc;
+ return 0;
}
/******************************************************************************
@@ -2087,20 +2258,61 @@
*/
static int tls_newdata_process_header ( struct tls_session *tls ) {
size_t data_len = ntohs ( tls->rx_header.length );
+ size_t remaining = data_len;
+ size_t frag_len;
+ struct io_buffer *iobuf;
+ struct io_buffer *tmp;
+ int rc;
- /* Allocate data buffer now that we know the length */
- assert ( tls->rx_data == NULL );
- tls->rx_data = malloc ( data_len );
- if ( ! tls->rx_data ) {
- DBGC ( tls, "TLS %p could not allocate %zd bytes "
- "for receive buffer\n", tls, data_len );
- return -ENOMEM;
+ /* Allocate data buffers now that we know the length */
+ assert ( list_empty ( &tls->rx_data ) );
+ while ( remaining ) {
+
+ /* Calculate fragment length. Ensure that no block is
+ * smaller than TLS_RX_MIN_BUFSIZE (by increasing the
+ * allocation length if necessary).
+ */
+ frag_len = remaining;
+ if ( frag_len > TLS_RX_BUFSIZE )
+ frag_len = TLS_RX_BUFSIZE;
+ remaining -= frag_len;
+ if ( remaining < TLS_RX_MIN_BUFSIZE ) {
+ frag_len += remaining;
+ remaining = 0;
+ }
+
+ /* Allocate buffer */
+ iobuf = alloc_iob_raw ( frag_len, TLS_RX_ALIGN, 0 );
+ if ( ! iobuf ) {
+ DBGC ( tls, "TLS %p could not allocate %zd of %zd "
+ "bytes for receive buffer\n", tls,
+ remaining, data_len );
+ rc = -ENOMEM_RX_DATA;
+ goto err;
+ }
+
+ /* Ensure tailroom is exactly what we asked for. This
+ * will result in unaligned I/O buffers when the
+ * fragment length is unaligned, which can happen only
+ * before we switch to using a block cipher.
+ */
+ iob_reserve ( iobuf, ( iob_tailroom ( iobuf ) - frag_len ) );
+
+ /* Add I/O buffer to list */
+ list_add_tail ( &iobuf->list, &tls->rx_data );
}
/* Move to data state */
tls->rx_state = TLS_RX_DATA;
return 0;
+
+ err:
+ list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) {
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
+ }
+ return rc;
}
/**
@@ -2110,22 +2322,31 @@
* @ret rc Returned status code
*/
static int tls_newdata_process_data ( struct tls_session *tls ) {
+ struct io_buffer *iobuf;
int rc;
+ /* Move current buffer to end of list */
+ iobuf = list_first_entry ( &tls->rx_data, struct io_buffer, list );
+ list_del ( &iobuf->list );
+ list_add_tail ( &iobuf->list, &tls->rx_data );
+
+ /* Continue receiving data if any space remains */
+ iobuf = list_first_entry ( &tls->rx_data, struct io_buffer, list );
+ if ( iob_tailroom ( iobuf ) )
+ return 0;
+
/* Process record */
if ( ( rc = tls_new_ciphertext ( tls, &tls->rx_header,
- tls->rx_data ) ) != 0 )
+ &tls->rx_data ) ) != 0 )
return rc;
/* Increment RX sequence number */
tls->rx_seq += 1;
- /* Free data buffer */
- free ( tls->rx_data );
- tls->rx_data = NULL;
-
/* Return to header state */
+ assert ( list_empty ( &tls->rx_data ) );
tls->rx_state = TLS_RX_HEADER;
+ iob_unput ( &tls->rx_header_iobuf, sizeof ( tls->rx_header ) );
return 0;
}
@@ -2142,45 +2363,43 @@
struct io_buffer *iobuf,
struct xfer_metadata *xfer __unused ) {
size_t frag_len;
- void *buf;
- size_t buf_len;
int ( * process ) ( struct tls_session *tls );
+ struct io_buffer *dest;
int rc;
while ( iob_len ( iobuf ) ) {
+
/* Select buffer according to current state */
switch ( tls->rx_state ) {
case TLS_RX_HEADER:
- buf = &tls->rx_header;
- buf_len = sizeof ( tls->rx_header );
+ dest = &tls->rx_header_iobuf;
process = tls_newdata_process_header;
break;
case TLS_RX_DATA:
- buf = tls->rx_data;
- buf_len = ntohs ( tls->rx_header.length );
+ dest = list_first_entry ( &tls->rx_data,
+ struct io_buffer, list );
+ assert ( dest != NULL );
process = tls_newdata_process_data;
break;
default:
assert ( 0 );
- rc = -EINVAL;
+ rc = -EINVAL_RX_STATE;
goto done;
}
/* Copy data portion to buffer */
- frag_len = ( buf_len - tls->rx_rcvd );
- if ( frag_len > iob_len ( iobuf ) )
- frag_len = iob_len ( iobuf );
- memcpy ( ( buf + tls->rx_rcvd ), iobuf->data, frag_len );
- tls->rx_rcvd += frag_len;
+ frag_len = iob_len ( iobuf );
+ if ( frag_len > iob_tailroom ( dest ) )
+ frag_len = iob_tailroom ( dest );
+ memcpy ( iob_put ( dest, frag_len ), iobuf->data, frag_len );
iob_pull ( iobuf, frag_len );
/* Process data if buffer is now full */
- if ( tls->rx_rcvd == buf_len ) {
+ if ( iob_tailroom ( dest ) == 0 ) {
if ( ( rc = process ( tls ) ) != 0 ) {
tls_close ( tls, rc );
goto done;
}
- tls->rx_rcvd = 0;
}
}
rc = 0;
@@ -2413,6 +2632,9 @@
tls->handshake_digest = &sha256_algorithm;
tls->handshake_ctx = tls->handshake_sha256_ctx;
tls->tx_pending = TLS_TX_CLIENT_HELLO;
+ iob_populate ( &tls->rx_header_iobuf, &tls->rx_header, 0,
+ sizeof ( tls->rx_header ) );
+ INIT_LIST_HEAD ( &tls->rx_data );
/* Add pending operations for server and client Finished messages */
pending_get ( &tls->client_negotiation );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/udp/dhcp.c
^
|
@@ -938,10 +938,18 @@
dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
dhcphdr->op = dhcp_op[msgtype];
- dhcphdr->hlen = dhcp_chaddr ( netdev, dhcphdr->chaddr,
- &dhcphdr->flags );
+ dhcphdr->hlen = netdev->ll_protocol->ll_addr_len;
+ memcpy ( dhcphdr->chaddr, netdev->ll_addr,
+ netdev->ll_protocol->ll_addr_len );
memcpy ( dhcphdr->options, options, options_len );
+ /* If the local link-layer address functions only as a name
+ * (i.e. cannot be used as a destination address), then
+ * request broadcast responses.
+ */
+ if ( netdev->ll_protocol->flags & LL_NAME_ONLY )
+ dhcphdr->flags |= htons ( BOOTP_FL_BROADCAST );
+
/* If the network device already has an IPv4 address then
* unicast responses from the DHCP server may be rejected, so
* request broadcast responses.
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/aes_cbc_test.c
^
|
@@ -169,9 +169,21 @@
*
*/
static void aes_cbc_test_exec ( void ) {
+ struct cipher_algorithm *cipher = &aes_cbc_algorithm;
+ /* Correctness tests */
aes_cbc_ok ( &test_128 );
aes_cbc_ok ( &test_256 );
+
+ /* Speed tests */
+ DBG ( "AES128 encryption required %ld cycles per byte\n",
+ cbc_cost_encrypt ( cipher, test_128.key_len ) );
+ DBG ( "AES128 decryption required %ld cycles per byte\n",
+ cbc_cost_decrypt ( cipher, test_128.key_len ) );
+ DBG ( "AES256 encryption required %ld cycles per byte\n",
+ cbc_cost_encrypt ( cipher, test_256.key_len ) );
+ DBG ( "AES256 decryption required %ld cycles per byte\n",
+ cbc_cost_decrypt ( cipher, test_256.key_len ) );
}
/** AES-in-CBC-mode self-test */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/cbc_test.c
^
|
@@ -29,9 +29,11 @@
#undef NDEBUG
#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ipxe/crypto.h>
+#include <ipxe/profile.h>
#include "cbc_test.h"
/**
@@ -49,8 +51,8 @@
int cbc_test_encrypt ( struct cipher_algorithm *cipher, const void *key,
size_t key_len, const void *iv, const void *plaintext,
const void *expected_ciphertext, size_t len ) {
- uint8_t ctx[ cipher->ctxsize ];
- uint8_t ciphertext[ len ];
+ uint8_t ctx[cipher->ctxsize];
+ uint8_t ciphertext[len];
int rc;
/* Initialise cipher */
@@ -80,8 +82,8 @@
int cbc_test_decrypt ( struct cipher_algorithm *cipher, const void *key,
size_t key_len, const void *iv, const void *ciphertext,
const void *expected_plaintext, size_t len ) {
- uint8_t ctx[ cipher->ctxsize ];
- uint8_t plaintext[ len ];
+ uint8_t ctx[cipher->ctxsize];
+ uint8_t plaintext[len];
int rc;
/* Initialise cipher */
@@ -95,3 +97,75 @@
/* Verify result */
return ( memcmp ( plaintext, expected_plaintext, len ) == 0 );
}
+
+/**
+ * Calculate CBC encryption or decryption cost
+ *
+ * @v cipher Cipher algorithm
+ * @v key_len Length of key
+ * @v op Encryption or decryption operation
+ * @ret cost Cost (in cycles per byte)
+ */
+static unsigned long cbc_cost ( struct cipher_algorithm *cipher,
+ size_t key_len,
+ void ( * op ) ( struct cipher_algorithm *cipher,
+ void *ctx, const void *src,
+ void *dst, size_t len ) ) {
+ static uint8_t random[8192]; /* Too large for stack */
+ uint8_t key[key_len];
+ uint8_t iv[cipher->blocksize];
+ uint8_t ctx[cipher->ctxsize];
+ union profiler profiler;
+ unsigned long long elapsed;
+ unsigned long cost;
+ unsigned int i;
+ int rc;
+
+ /* Fill buffer with pseudo-random data */
+ srand ( 0x1234568 );
+ for ( i = 0 ; i < sizeof ( random ) ; i++ )
+ random[i] = rand();
+ for ( i = 0 ; i < sizeof ( key ) ; i++ )
+ key[i] = rand();
+ for ( i = 0 ; i < sizeof ( iv ) ; i++ )
+ iv[i] = rand();
+
+ /* Initialise cipher */
+ rc = cipher_setkey ( cipher, ctx, key, key_len );
+ assert ( rc == 0 );
+ cipher_setiv ( cipher, ctx, iv );
+
+ /* Time operation */
+ profile ( &profiler );
+ op ( cipher, ctx, random, random, sizeof ( random ) );
+ elapsed = profile ( &profiler );
+
+ /* Round to nearest whole number of cycles per byte */
+ cost = ( ( elapsed + ( sizeof ( random ) / 2 ) ) / sizeof ( random ) );
+
+ return cost;
+}
+
+/**
+ * Calculate CBC encryption cost
+ *
+ * @v cipher Cipher algorithm
+ * @v key_len Length of key
+ * @ret cost Cost (in cycles per byte)
+ */
+unsigned long cbc_cost_encrypt ( struct cipher_algorithm *cipher,
+ size_t key_len ) {
+ return cbc_cost ( cipher, key_len, cipher_encrypt );
+}
+
+/**
+ * Calculate CBC decryption cost
+ *
+ * @v cipher Cipher algorithm
+ * @v key_len Length of key
+ * @ret cost Cost (in cycles per byte)
+ */
+unsigned long cbc_cost_decrypt ( struct cipher_algorithm *cipher,
+ size_t key_len ) {
+ return cbc_cost ( cipher, key_len, cipher_decrypt );
+}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/cbc_test.h
^
|
@@ -15,6 +15,10 @@
size_t key_len, const void *iv,
const void *ciphertext,
const void *expected_plaintext, size_t len );
+extern unsigned long cbc_cost_encrypt ( struct cipher_algorithm *cipher,
+ size_t key_len );
+extern unsigned long cbc_cost_decrypt ( struct cipher_algorithm *cipher,
+ size_t key_len );
/**
* Report CBC encryption test result
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/digest_test.c
^
|
@@ -25,8 +25,10 @@
*
*/
+#include <stdlib.h>
#include <string.h>
#include <ipxe/crypto.h>
+#include <ipxe/profile.h>
#include "digest_test.h"
/**
@@ -68,3 +70,36 @@
/* Compare against expected output */
return ( memcmp ( expected, out, sizeof ( out ) ) == 0 );
}
+
+/**
+ * Calculate digest algorithm cost
+ *
+ * @v digest Digest algorithm
+ * @ret cost Cost (in cycles per byte)
+ */
+unsigned long digest_cost ( struct digest_algorithm *digest ) {
+ static uint8_t random[8192]; /* Too large for stack */
+ uint8_t ctx[digest->ctxsize];
+ uint8_t out[digest->digestsize];
+ union profiler profiler;
+ unsigned long long elapsed;
+ unsigned long cost;
+ unsigned int i;
+
+ /* Fill buffer with pseudo-random data */
+ srand ( 0x1234568 );
+ for ( i = 0 ; i < sizeof ( random ) ; i++ )
+ random[i] = rand();
+
+ /* Time digest calculation */
+ profile ( &profiler );
+ digest_init ( digest, ctx );
+ digest_update ( digest, ctx, random, sizeof ( random ) );
+ digest_final ( digest, ctx, out );
+ elapsed = profile ( &profiler );
+
+ /* Round to nearest whole number of cycles per byte */
+ cost = ( ( elapsed + ( sizeof ( random ) / 2 ) ) / sizeof ( random ) );
+
+ return cost;
+}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/digest_test.h
^
|
@@ -19,6 +19,7 @@
extern int digest_test ( struct digest_algorithm *digest,
struct digest_test_fragments *fragments,
void *data, size_t len, void *expected );
+extern unsigned long digest_cost ( struct digest_algorithm *digest );
/**
* Report digest test result
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/md5_test.c
^
|
@@ -70,9 +70,11 @@
static void md5_test_exec ( void ) {
struct digest_algorithm *digest = &md5_algorithm;
struct md5_test_vector *test;
+ unsigned long cost;
unsigned int i;
unsigned int j;
+ /* Correctness test */
for ( i = 0 ; i < ( sizeof ( md5_test_vectors ) /
sizeof ( md5_test_vectors[0] ) ) ; i++ ) {
test = &md5_test_vectors[i];
@@ -85,6 +87,10 @@
test->data, test->len, test->digest );
}
}
+
+ /* Speed test */
+ cost = digest_cost ( digest );
+ DBG ( "MD5 required %ld cycles per byte\n", cost );
}
/** MD5 self-test */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/settings_test.c
^
|
@@ -240,8 +240,6 @@
/* "hex" setting type */
storef_ok ( &test_settings, &test_hex_setting,
- "", RAW ( 0x00 ) );
- storef_ok ( &test_settings, &test_hex_setting,
":", RAW ( 0x00, 0x00 ) );
storef_ok ( &test_settings, &test_hex_setting,
"1:2:", RAW ( 0x01, 0x02, 0x00 ) );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/sha1_test.c
^
|
@@ -75,9 +75,11 @@
static void sha1_test_exec ( void ) {
struct digest_algorithm *digest = &sha1_algorithm;
struct sha1_test_vector *test;
+ unsigned long cost;
unsigned int i;
unsigned int j;
+ /* Correctness test */
for ( i = 0 ; i < ( sizeof ( sha1_test_vectors ) /
sizeof ( sha1_test_vectors[0] ) ) ; i++ ) {
test = &sha1_test_vectors[i];
@@ -90,6 +92,10 @@
test->data, test->len, test->digest );
}
}
+
+ /* Speed test */
+ cost = digest_cost ( digest );
+ DBG ( "SHA1 required %ld cycles per byte\n", cost );
}
/** SHA-1 self-test */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/sha256_test.c
^
|
@@ -78,9 +78,11 @@
static void sha256_test_exec ( void ) {
struct digest_algorithm *digest = &sha256_algorithm;
struct sha256_test_vector *test;
+ unsigned long cost;
unsigned int i;
unsigned int j;
+ /* Correctness test */
for ( i = 0 ; i < ( sizeof ( sha256_test_vectors ) /
sizeof ( sha256_test_vectors[0] ) ) ; i++ ) {
test = &sha256_test_vectors[i];
@@ -93,6 +95,10 @@
test->data, test->len, test->digest );
}
}
+
+ /* Speed test */
+ cost = digest_cost ( digest );
+ DBG ( "SHA256 required %ld cycles per byte\n", cost );
}
/** SHA-256 self-test */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/usr/dhcpmgmt.c
^
|
@@ -38,10 +38,6 @@
*/
int dhcp ( struct net_device *netdev ) {
- struct dhcphdr *dhcphdr;
- typeof ( dhcphdr->chaddr ) chaddr;
- unsigned int hlen;
- unsigned int i;
int rc;
/* Check we can open the interface first */
@@ -53,12 +49,8 @@
return rc;
/* Perform DHCP */
- printf ( "DHCP (%s", netdev->name );
- hlen = dhcp_chaddr ( netdev, chaddr, NULL );
- for ( i = 0 ; i < hlen ; i++ )
- printf ( "%c%02x", ( i ? ':' : ' ' ), chaddr[i] );
- printf ( ")" );
-
+ printf ( "DHCP (%s %s)", netdev->name,
+ netdev->ll_protocol->ntoa ( netdev->ll_addr ) );
if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 ) {
rc = monojob_wait ( "" );
} else if ( rc > 0 ) {
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/usr/nslookup.c
^
|
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2012 Patrick Plenefisch <phplenefisch@wpi.edu>.
+ *
+ * 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.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/resolv.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/monojob.h>
+#include <ipxe/settings.h>
+#include <usr/nslookup.h>
+
+/** @file
+ *
+ * Standalone name resolution
+ *
+ */
+
+/** A name resolution request */
+struct nslookup {
+ /** Reference count for this object */
+ struct refcnt refcnt;
+
+ /** Job control interface */
+ struct interface job;
+ /** Data transfer interface */
+ struct interface resolver;
+
+ /** Setting name */
+ const char *setting_name;
+};
+
+/**
+ * Terminate name resolution
+ *
+ * @v nslookup Name resolution request
+ * @v rc Reason for termination
+ */
+static void nslookup_close ( struct nslookup *nslookup, int rc ) {
+
+ /* Shut down interfaces */
+ intf_shutdown ( &nslookup->resolver, rc );
+ intf_shutdown ( &nslookup->job, rc );
+}
+
+/**
+ * Handle resolved name
+ *
+ * @v nslookup Name resolution request
+ * @v sa Completed socket address
+ */
+static void nslookup_resolv_done ( struct nslookup *nslookup,
+ struct sockaddr *sa ) {
+ struct sockaddr_in *sin;
+ struct setting_type *type;
+ void *data;
+ size_t len;
+ int rc;
+
+ /* Extract address */
+ switch ( sa->sa_family ) {
+ case AF_INET:
+ sin = ( ( struct sockaddr_in * ) sa );
+ data = &sin->sin_addr;
+ len = sizeof ( sin->sin_addr );
+ type = &setting_type_ipv4;
+ break;
+ default:
+ rc = -ENOTSUP;
+ goto err;
+ }
+
+ /* Save in specified setting */
+ if ( ( rc = store_named_setting ( nslookup->setting_name, type,
+ data, len ) ) != 0 )
+ goto err;
+
+ err:
+ /* Terminate name resolution */
+ nslookup_close ( nslookup, rc );
+}
+
+/** Name resolution resolver interface operations */
+static struct interface_operation nslookup_resolver_operations[] = {
+ INTF_OP ( resolv_done, struct nslookup *, nslookup_resolv_done ),
+ INTF_OP ( intf_close, struct nslookup *, nslookup_close ),
+};
+
+/** Name resolution resolver interface descriptor */
+static struct interface_descriptor nslookup_resolver_desc =
+ INTF_DESC_PASSTHRU ( struct nslookup, resolver,
+ nslookup_resolver_operations, job );
+
+/** Name resolution job control interface operations */
+static struct interface_operation nslookup_job_operations[] = {
+ INTF_OP ( intf_close, struct nslookup *, nslookup_close ),
+};
+
+/** Name resolution job control interface descriptor */
+static struct interface_descriptor nslookup_job_desc =
+ INTF_DESC_PASSTHRU ( struct nslookup, job,
+ nslookup_job_operations, resolver );
+
+/**
+ * Initiate standalone name resolution
+ *
+ * @v job Parent interface
+ * @v name Name to resolve
+ * @v setting_name Setting name
+ * @ret rc Return status code
+ */
+static int resolv_setting ( struct interface *job, const char *name,
+ const char *setting_name ) {
+ struct nslookup *nslookup;
+ struct sockaddr sa;
+ char *setting_name_copy;
+ int rc;
+
+ /* Allocate and initialise structure */
+ nslookup = zalloc ( sizeof ( *nslookup ) + strlen ( setting_name )
+ + 1 /* NUL */ );
+ if ( ! nslookup )
+ return -ENOMEM;
+ ref_init ( &nslookup->refcnt, NULL );
+ intf_init ( &nslookup->job, &nslookup_job_desc, &nslookup->refcnt );
+ intf_init ( &nslookup->resolver, &nslookup_resolver_desc,
+ &nslookup->refcnt );
+ setting_name_copy = ( ( void * ) ( nslookup + 1 ) );
+ strcpy ( setting_name_copy, setting_name );
+ nslookup->setting_name = setting_name_copy;
+
+ /* Start name resolution */
+ memset ( &sa, 0, sizeof ( sa ) );
+ if ( ( rc = resolv ( &nslookup->resolver, name, &sa ) ) != 0 )
+ goto err_resolv;
+
+ /* Attach parent interface, mortalise self, and return */
+ intf_plug_plug ( &nslookup->job, job );
+ ref_put ( &nslookup->refcnt );
+ return 0;
+
+ err_resolv:
+ ref_put ( &nslookup->refcnt );
+ return rc;
+}
+
+/**
+ * Perform (blocking) standalone name resolution
+ *
+ * @v name Name to resolve
+ * @v setting_name Setting name
+ * @ret rc Return status code
+ */
+int nslookup ( const char *name, const char *setting_name ) {
+ int rc;
+
+ /* Perform name resolution */
+ if ( ( rc = resolv_setting ( &monojob, name, setting_name ) ) == 0 )
+ rc = monojob_wait ( NULL );
+ if ( rc != 0 ) {
+ printf ( "Could not resolve %s: %s\n", name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/util/Option/ROM.pm
^
|
@@ -180,6 +180,7 @@
use constant JMP_SHORT => 0xeb;
use constant JMP_NEAR => 0xe9;
+use constant CALL_NEAR => 0xe8;
sub pack_init {
my $dest = shift;
@@ -203,6 +204,9 @@
} elsif ( $jump == JMP_NEAR ) {
my $offset = unpack ( "xS", $instr );
return ( $offset + 6 );
+ } elsif ( $jump == CALL_NEAR ) {
+ my $offset = unpack ( "xS", $instr );
+ return ( $offset + 6 );
} elsif ( $jump == 0 ) {
return 0;
} else {
@@ -392,6 +396,25 @@
=pod
+=item C<< undi_header () >>
+
+Return a C<Option::ROM::UNDI> object representing the ROM's UNDI header,
+if present.
+
+=cut
+
+sub undi_header {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ my $offset = $hash->{undi_header};
+ return undef unless $offset != 0;
+
+ return Option::ROM::UNDI->new ( $self->{data}, $offset );
+}
+
+=pod
+
=item C<< ipxe_header () >>
Return a C<Option::ROM::iPXE> object representing the ROM's iPXE
@@ -588,6 +611,67 @@
}
##############################################################################
+#
+# Option::ROM::UNDI
+#
+##############################################################################
+
+package Option::ROM::UNDI;
+
+use strict;
+use warnings;
+use Carp;
+use bytes;
+
+sub new {
+ my $class = shift;
+ my $data = shift;
+ my $offset = shift;
+
+ my $hash = {};
+ tie %$hash, "Option::ROM::Fields", {
+ data => $data,
+ offset => $offset,
+ length => 0x16,
+ fields => {
+ signature => { offset => 0x00, length => 0x04, pack => "a4" },
+ struct_length => { offset => 0x04, length => 0x01, pack => "C" },
+ checksum => { offset => 0x05, length => 0x01, pack => "C" },
+ struct_revision =>{ offset => 0x06, length => 0x01, pack => "C" },
+ version_revision =>{ offset => 0x07, length => 0x01, pack => "C" },
+ version_minor => { offset => 0x08, length => 0x01, pack => "C" },
+ version_major => { offset => 0x09, length => 0x01, pack => "C" },
+ loader_entry => { offset => 0x0a, length => 0x02, pack => "S" },
+ stack_size => { offset => 0x0c, length => 0x02, pack => "S" },
+ data_size => { offset => 0x0e, length => 0x02, pack => "S" },
+ code_size => { offset => 0x10, length => 0x02, pack => "S" },
+ bus_type => { offset => 0x12, length => 0x04, pack => "a4" },
+ },
+ };
+ bless $hash, $class;
+
+ # Retrieve true length of structure
+ my $self = tied ( %$hash );
+ $self->{length} = $hash->{struct_length};
+
+ return $hash;
+}
+
+sub checksum {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ return $self->checksum();
+}
+
+sub fix_checksum {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ $hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff );
+}
+
+##############################################################################
#
# Option::ROM::iPXE
#
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/util/disrom.pl
^
|
@@ -85,6 +85,22 @@
printf "\n";
}
+ my $undi = $rom->undi_header();
+ if ( $undi ) {
+ printf "UNDI header:\n\n";
+ printf " %-16s %s\n", "Signature:", $undi->{signature};
+ printf " %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $undi->{checksum},
+ ( ( $undi->checksum == 0 ) ? "" : "INCORRECT: " ), $undi->checksum;
+ printf " %-16s %d.%d.%d\n", "UNDI version:", $undi->{version_major},
+ $undi->{version_minor}, $undi->{version_revision};
+ printf " %-16s 0x%04x\n", "Loader entry:", $undi->{loader_entry};
+ printf " %-16s 0x%04x\n", "Stack size:", $undi->{stack_size};
+ printf " %-16s 0x%04x\n", "Data size:", $undi->{data_size};
+ printf " %-16s 0x%04x\n", "Code size:", $undi->{code_size};
+ printf " %-16s %s\n", "Bus type:", $undi->{bus_type};
+ printf "\n";
+ }
+
my $ipxe = $rom->ipxe_header();
if ( $ipxe ) {
printf "iPXE header:\n\n";
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/util/einfo.c
^
|
@@ -93,10 +93,11 @@
( ( ( char * ) einfo ) + einfo->desc ) );
}
+ /* Unmap file */
+ munmap ( start, len );
}
- /* Unmap and close file */
- munmap ( start, len );
+ /* Close file */
close ( fd );
}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/util/fixrom.pl
^
|
@@ -32,6 +32,7 @@
my $image = $rom;
while ( $image ) {
$image->pnp_header->fix_checksum() if $image->pnp_header;
+ $image->undi_header->fix_checksum() if $image->undi_header;
$image->ipxe_header->fix_checksum() if $image->ipxe_header;
$image->fix_checksum();
$image = $image->next_image();
|