[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/Makefile
|
@@ -169,11 +169,6 @@
ifneq ($(GITVERSION),)
VERSION += ($(GITVERSION))
endif
-CFLAGS += -DVERSION_MAJOR=$(VERSION_MAJOR) \
- -DVERSION_MINOR=$(VERSION_MINOR) \
- -DVERSION_PATCH=$(VERSION_PATCH) \
- -DVERSION="\"$(VERSION)\""
-IDENT = '$(@F) $(VERSION) (GPL) ipxe.org'
version :
@$(ECHO) "$(VERSION)"
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/Makefile.housekeeping
^
|
@@ -162,9 +162,12 @@
# output of "size". Inhibit this.
#
ifeq ($(CCTYPE),gcc)
-CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -x c -c /dev/null \
+CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -fno-exceptions -fno-unwind-tables \
+ -fno-asynchronous-unwind-tables -x c -c /dev/null \
-o /dev/null >/dev/null 2>&1
-CFI_FLAGS := $(shell $(CFI_TEST) && $(ECHO) '-fno-dwarf2-cfi-asm')
+CFI_FLAGS := $(shell $(CFI_TEST) && \
+ $(ECHO) '-fno-dwarf2-cfi-asm -fno-exceptions ' \
+ '-fno-unwind-tables -fno-asynchronous-unwind-tables')
WORKAROUND_CFLAGS += $(CFI_FLAGS)
endif
@@ -650,6 +653,17 @@
$(BIN)/clientcert.o : override CC := env CCACHE_DISABLE=1 $(CC)
+# Version number
+#
+CFLAGS_version += -DVERSION_MAJOR=$(VERSION_MAJOR) \
+ -DVERSION_MINOR=$(VERSION_MINOR) \
+ -DVERSION_PATCH=$(VERSION_PATCH) \
+ -DVERSION="\"$(VERSION)\""
+# Make sure the version number gets updated on every git checkout
+ifneq ($(GITVERSION),)
+$(BIN)/version.o : ../.git/index
+endif
+
# We automatically generate rules for any file mentioned in AUTO_SRCS
# using the following set of templates. It would be cleaner to use
# $(eval ...), but this function exists only in GNU make >= 3.80.
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/image/bzimage.c
^
|
@@ -33,6 +33,7 @@
#include <assert.h>
#include <realmode.h>
#include <bzimage.h>
+#include <initrd.h>
#include <ipxe/uaccess.h>
#include <ipxe/image.h>
#include <ipxe/segment.h>
@@ -304,11 +305,10 @@
* @v image bzImage image
* @v bzimg bzImage context
* @v cmdline Kernel command line
- * @ret rc Return status code
*/
-static int bzimage_set_cmdline ( struct image *image,
- struct bzimage_context *bzimg,
- const char *cmdline ) {
+static void bzimage_set_cmdline ( struct image *image,
+ struct bzimage_context *bzimg,
+ const char *cmdline ) {
size_t cmdline_len;
/* Copy command line down to real-mode portion */
@@ -318,8 +318,6 @@
copy_to_user ( bzimg->rm_kernel, bzimg->rm_cmdline,
cmdline, cmdline_len );
DBGC ( image, "bzImage %p command line \"%s\"\n", image, cmdline );
-
- return 0;
}
/**
@@ -354,7 +352,7 @@
* @v image bzImage image
* @v initrd initrd image
* @v address Address at which to load, or UNULL
- * @ret len Length of loaded image, rounded up to 4 bytes
+ * @ret len Length of loaded image, rounded up to INITRD_ALIGN
*/
static size_t bzimage_load_initrd ( struct image *image,
struct image *initrd,
@@ -364,6 +362,7 @@
struct cpio_header cpio;
size_t offset = 0;
size_t name_len;
+ size_t pad_len;
/* Do not include kernel image itself as an initrd */
if ( initrd == image )
@@ -371,8 +370,6 @@
/* Create cpio header before non-prebuilt images */
if ( filename && filename[0] ) {
- 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 */ );
@@ -402,80 +399,146 @@
/* Copy in initrd image body */
if ( address )
- memcpy_user ( address, offset, initrd->data, 0, initrd->len );
- offset += initrd->len;
+ memmove_user ( address, offset, initrd->data, 0, initrd->len );
if ( address ) {
- DBGC ( image, "bzImage %p has initrd %p at [%lx,%lx)\n",
- image, initrd, user_to_phys ( address, 0 ),
- user_to_phys ( address, offset ) );
+ DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)"
+ "%s%s\n", image, initrd, user_to_phys ( address, 0 ),
+ user_to_phys ( address, offset ),
+ user_to_phys ( address, ( offset + initrd->len ) ),
+ ( filename ? " " : "" ), ( filename ? filename : "" ) );
+ DBGC2_MD5A ( image, user_to_phys ( address, offset ),
+ user_to_virt ( address, offset ), initrd->len );
}
+ offset += initrd->len;
+
+ /* Round up to multiple of INITRD_ALIGN and zero-pad */
+ pad_len = ( ( -offset ) & ( INITRD_ALIGN - 1 ) );
+ if ( address )
+ memset_user ( address, offset, 0, pad_len );
+ offset += pad_len;
- /* Round up to 4-byte boundary */
- offset = ( ( offset + 0x03 ) & ~0x03 );
return offset;
}
/**
- * Load initrds, if any
+ * Check that initrds can be loaded
*
* @v image bzImage image
* @v bzimg bzImage context
* @ret rc Return status code
*/
-static int bzimage_load_initrds ( struct image *image,
- struct bzimage_context *bzimg ) {
+static int bzimage_check_initrds ( struct image *image,
+ struct bzimage_context *bzimg ) {
struct image *initrd;
- size_t total_len = 0;
- physaddr_t address;
+ userptr_t bottom;
+ size_t len = 0;
int rc;
- /* Add up length of all initrd images */
- for_each_image ( initrd )
- total_len += bzimage_load_initrd ( image, initrd, UNULL );
+ /* Calculate total loaded length of initrds */
+ for_each_image ( initrd ) {
- /* Give up if no initrd images found */
- if ( ! total_len )
- return 0;
+ /* Skip kernel */
+ if ( initrd == image )
+ continue;
- /* Find a suitable start address. Try 1MB boundaries,
- * starting from the downloaded kernel image itself and
- * working downwards until we hit an available region.
+ /* Calculate length */
+ len += bzimage_load_initrd ( image, initrd, UNULL );
+
+ DBGC ( image, "bzImage %p initrd %p from [%#08lx,%#08lx)%s%s\n",
+ image, initrd, user_to_phys ( initrd->data, 0 ),
+ user_to_phys ( initrd->data, initrd->len ),
+ ( initrd->cmdline ? " " : "" ),
+ ( initrd->cmdline ? initrd->cmdline : "" ) );
+ DBGC2_MD5A ( image, user_to_phys ( initrd->data, 0 ),
+ user_to_virt ( initrd->data, 0 ), initrd->len );
+ }
+
+ /* Calculate lowest usable address */
+ bottom = userptr_add ( bzimg->pm_kernel, bzimg->pm_sz );
+
+ /* Check that total length fits within space available for
+ * reshuffling. This is a conservative check, since CPIO
+ * headers are not present during reshuffling, but this
+ * doesn't hurt and keeps the code simple.
*/
- for ( address = ( user_to_phys ( image->data, 0 ) & ~0xfffff ) ; ;
- address -= 0x100000 ) {
- /* Check that we're not going to overwrite the
- * kernel itself. This check isn't totally
- * accurate, but errs on the side of caution.
- */
- if ( address <= ( BZI_LOAD_HIGH_ADDR + image->len ) ) {
- DBGC ( image, "bzImage %p could not find a location "
- "for initrd\n", image );
- return -ENOBUFS;
- }
- /* Check that we are within the kernel's range */
- if ( ( address + total_len - 1 ) > bzimg->mem_limit )
- continue;
- /* Prepare and verify segment */
- if ( ( rc = prep_segment ( phys_to_user ( address ), 0,
- total_len ) ) != 0 )
- continue;
- /* Use this address */
- break;
+ if ( ( rc = initrd_reshuffle_check ( len, bottom ) ) != 0 ) {
+ DBGC ( image, "bzImage %p failed reshuffle check: %s\n",
+ image, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Check that total length fits within kernel's memory limit */
+ if ( user_to_phys ( bottom, len ) > bzimg->mem_limit ) {
+ DBGC ( image, "bzImage %p not enough space for initrds\n",
+ image );
+ return -ENOBUFS;
}
- /* Record initrd location */
- bzimg->ramdisk_image = address;
- bzimg->ramdisk_size = total_len;
+ return 0;
+}
+
+/**
+ * Load initrds, if any
+ *
+ * @v image bzImage image
+ * @v bzimg bzImage context
+ */
+static void bzimage_load_initrds ( struct image *image,
+ struct bzimage_context *bzimg ) {
+ struct image *initrd;
+ struct image *highest = NULL;
+ struct image *other;
+ userptr_t top;
+ userptr_t dest;
+ size_t len;
- /* Construct initrd */
- DBGC ( image, "bzImage %p constructing initrd at [%lx,%lx)\n",
- image, address, ( address + total_len ) );
+ /* Reshuffle initrds into desired order */
+ initrd_reshuffle ( userptr_add ( bzimg->pm_kernel, bzimg->pm_sz ) );
+
+ /* Find highest initrd */
for_each_image ( initrd ) {
- address += bzimage_load_initrd ( image, initrd,
- phys_to_user ( address ) );
+ if ( ( highest == NULL ) ||
+ ( userptr_sub ( initrd->data, highest->data ) > 0 ) ) {
+ highest = initrd;
+ }
}
- return 0;
+ /* Do nothing if there are no initrds */
+ if ( ! highest )
+ return;
+
+ /* Find highest usable address */
+ top = userptr_add ( highest->data,
+ ( ( highest->len + INITRD_ALIGN - 1 ) &
+ ~( INITRD_ALIGN - 1 ) ) );
+ if ( user_to_phys ( top, 0 ) > bzimg->mem_limit )
+ top = phys_to_user ( bzimg->mem_limit );
+ DBGC ( image, "bzImage %p loading initrds from %#08lx downwards\n",
+ image, user_to_phys ( top, 0 ) );
+
+ /* Load initrds in order */
+ for_each_image ( initrd ) {
+
+ /* Calculate cumulative length of following
+ * initrds (including padding).
+ */
+ len = 0;
+ for_each_image ( other ) {
+ if ( other == initrd )
+ len = 0;
+ len += bzimage_load_initrd ( image, other, UNULL );
+ }
+
+ /* Load initrd at this address */
+ dest = userptr_add ( top, -len );
+ bzimage_load_initrd ( image, initrd, dest );
+
+ /* Record initrd location */
+ if ( ! bzimg->ramdisk_image ) {
+ bzimg->ramdisk_image = user_to_phys ( dest, 0 );
+ bzimg->ramdisk_size = len;
+ }
+ }
}
/**
@@ -508,33 +571,37 @@
return rc;
}
+ /* Parse command line for bootloader parameters */
+ if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0)
+ return rc;
+
+ /* Check that initrds can be loaded */
+ if ( ( rc = bzimage_check_initrds ( image, &bzimg ) ) != 0 )
+ return rc;
+
+ /* Remove kernel from image list (without invalidating image pointer) */
+ unregister_image ( image_get ( image ) );
+
/* Load segments */
memcpy_user ( bzimg.rm_kernel, 0, image->data,
0, bzimg.rm_filesz );
memcpy_user ( bzimg.pm_kernel, 0, image->data,
bzimg.rm_filesz, bzimg.pm_sz );
- /* Update and write out header */
- bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
-
- /* Parse command line for bootloader parameters */
- if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0)
- return rc;
-
/* Store command line */
- if ( ( rc = bzimage_set_cmdline ( image, &bzimg, cmdline ) ) != 0 )
- return rc;
+ bzimage_set_cmdline ( image, &bzimg, cmdline );
+
+ /* Prepare for exiting. Must do this before loading initrds,
+ * since loading the initrds will corrupt the external heap.
+ */
+ shutdown_boot();
/* Load any initrds */
- if ( ( rc = bzimage_load_initrds ( image, &bzimg ) ) != 0 )
- return rc;
+ bzimage_load_initrds ( image, &bzimg );
/* Update kernel header */
bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
- /* Prepare for exiting */
- shutdown_boot();
-
DBGC ( image, "bzImage %p jumping to RM kernel at %04x:0000 "
"(stack %04x:%04zx)\n", image, ( bzimg.rm_kernel_seg + 0x20 ),
bzimg.rm_kernel_seg, bzimg.rm_heap );
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/image/initrd.c
^
|
@@ -0,0 +1,300 @@
+/*
+ * 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 <errno.h>
+#include <initrd.h>
+#include <ipxe/image.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/init.h>
+#include <ipxe/memblock.h>
+
+/** @file
+ *
+ * Initial ramdisk (initrd) reshuffling
+ *
+ */
+
+/** Maximum address available for initrd */
+userptr_t initrd_top;
+
+/** Minimum address available for initrd */
+userptr_t initrd_bottom;
+
+/**
+ * Squash initrds as high as possible in memory
+ *
+ * @v top Highest possible address
+ * @ret used Lowest address used by initrds
+ */
+static userptr_t initrd_squash_high ( userptr_t top ) {
+ userptr_t current = top;
+ struct image *initrd;
+ struct image *highest;
+ size_t len;
+
+ /* Squash up any initrds already within or below the region */
+ while ( 1 ) {
+
+ /* Find the highest image not yet in its final position */
+ highest = NULL;
+ for_each_image ( initrd ) {
+ if ( ( userptr_sub ( initrd->data, current ) < 0 ) &&
+ ( ( highest == NULL ) ||
+ ( userptr_sub ( initrd->data,
+ highest->data ) > 0 ) ) ) {
+ highest = initrd;
+ }
+ }
+ if ( ! highest )
+ break;
+
+ /* Move this image to its final position */
+ len = ( ( highest->len + INITRD_ALIGN - 1 ) &
+ ~( INITRD_ALIGN - 1 ) );
+ current = userptr_sub ( current, len );
+ DBGC ( &images, "INITRD squashing %s [%#08lx,%#08lx)->"
+ "[%#08lx,%#08lx)\n", highest->name,
+ user_to_phys ( highest->data, 0 ),
+ user_to_phys ( highest->data, highest->len ),
+ user_to_phys ( current, 0 ),
+ user_to_phys ( current, highest->len ) );
+ memmove_user ( current, 0, highest->data, 0, highest->len );
+ highest->data = current;
+ }
+
+ /* Copy any remaining initrds (e.g. embedded images) to the region */
+ for_each_image ( initrd ) {
+ if ( userptr_sub ( initrd->data, top ) >= 0 ) {
+ len = ( ( initrd->len + INITRD_ALIGN - 1 ) &
+ ~( INITRD_ALIGN - 1 ) );
+ current = userptr_sub ( current, len );
+ DBGC ( &images, "INITRD copying %s [%#08lx,%#08lx)->"
+ "[%#08lx,%#08lx)\n", initrd->name,
+ user_to_phys ( initrd->data, 0 ),
+ user_to_phys ( initrd->data, initrd->len ),
+ user_to_phys ( current, 0 ),
+ user_to_phys ( current, initrd->len ) );
+ memcpy_user ( current, 0, initrd->data, 0,
+ initrd->len );
+ initrd->data = current;
+ }
+ }
+
+ return current;
+}
+
+/**
+ * Swap position of two adjacent initrds
+ *
+ * @v low Lower initrd
+ * @v high Higher initrd
+ * @v free Free space
+ * @v free_len Length of free space
+ */
+static void initrd_swap ( struct image *low, struct image *high,
+ userptr_t free, size_t free_len ) {
+ size_t len = 0;
+ size_t frag_len;
+ size_t new_len;
+
+ DBGC ( &images, "INITRD swapping %s [%#08lx,%#08lx)<->[%#08lx,%#08lx) "
+ "%s\n", low->name, user_to_phys ( low->data, 0 ),
+ user_to_phys ( low->data, low->len ),
+ user_to_phys ( high->data, 0 ),
+ user_to_phys ( high->data, high->len ), high->name );
+
+ /* Round down length of free space */
+ free_len &= ~( INITRD_ALIGN - 1 );
+ assert ( free_len > 0 );
+
+ /* Swap image data */
+ while ( len < high->len ) {
+
+ /* Calculate maximum fragment length */
+ frag_len = ( high->len - len );
+ if ( frag_len > free_len )
+ frag_len = free_len;
+ new_len = ( ( len + frag_len + INITRD_ALIGN - 1 ) &
+ ~( INITRD_ALIGN - 1 ) );
+
+ /* Swap fragments */
+ memcpy_user ( free, 0, high->data, len, frag_len );
+ memmove_user ( low->data, new_len, low->data, len, low->len );
+ memcpy_user ( low->data, len, free, 0, frag_len );
+ len = new_len;
+ }
+
+ /* Adjust data pointers */
+ high->data = low->data;
+ low->data = userptr_add ( low->data, len );
+}
+
+/**
+ * Swap position of any two adjacent initrds not currently in the correct order
+ *
+ * @v free Free space
+ * @v free_len Length of free space
+ * @ret swapped A pair of initrds was swapped
+ */
+static int initrd_swap_any ( userptr_t free, size_t free_len ) {
+ struct image *low;
+ struct image *high;
+ size_t padded_len;
+ userptr_t adjacent;
+
+ /* Find any pair of initrds that can be swapped */
+ for_each_image ( low ) {
+
+ /* Calculate location of adjacent image (if any) */
+ padded_len = ( ( low->len + INITRD_ALIGN - 1 ) &
+ ~( INITRD_ALIGN - 1 ) );
+ adjacent = userptr_add ( low->data, padded_len );
+
+ /* Search for adjacent image */
+ for_each_image ( high ) {
+
+ /* If we have found the adjacent image, swap and exit */
+ if ( high->data == adjacent ) {
+ initrd_swap ( low, high, free, free_len );
+ return 1;
+ }
+
+ /* Stop search if all remaining potential
+ * adjacent images are already in the correct
+ * order.
+ */
+ if ( high == low )
+ break;
+ }
+ }
+
+ /* Nothing swapped */
+ return 0;
+}
+
+/**
+ * Dump initrd locations (for debug)
+ *
+ */
+static void initrd_dump ( void ) {
+ struct image *initrd;
+
+ /* Do nothing unless debugging is enabled */
+ if ( ! DBG_LOG )
+ return;
+
+ /* Dump initrd locations */
+ for_each_image ( initrd ) {
+ DBGC ( &images, "INITRD %s at [%#08lx,%#08lx)\n",
+ initrd->name, user_to_phys ( initrd->data, 0 ),
+ user_to_phys ( initrd->data, initrd->len ) );
+ DBGC2_MD5A ( &images, user_to_phys ( initrd->data, 0 ),
+ user_to_virt ( initrd->data, 0 ), initrd->len );
+ }
+}
+
+/**
+ * Reshuffle initrds into desired order at top of memory
+ *
+ * @v bottom Lowest address available for initrds
+ *
+ * After this function returns, the initrds have been rearranged in
+ * memory and the external heap structures will have been corrupted.
+ * Reshuffling must therefore take place immediately prior to jumping
+ * to the loaded OS kernel; no further execution within iPXE is
+ * permitted.
+ */
+void initrd_reshuffle ( userptr_t bottom ) {
+ userptr_t top;
+ userptr_t used;
+ userptr_t free;
+ size_t free_len;
+
+ /* Calculate limits of available space for initrds */
+ top = initrd_top;
+ if ( userptr_sub ( initrd_bottom, bottom ) > 0 )
+ bottom = initrd_bottom;
+
+ /* Debug */
+ DBGC ( &images, "INITRD region [%#08lx,%#08lx)\n",
+ user_to_phys ( bottom, 0 ), user_to_phys ( top, 0 ) );
+ initrd_dump();
+
+ /* Squash initrds as high as possible in memory */
+ used = initrd_squash_high ( top );
+
+ /* Calculate available free space */
+ free = bottom;
+ free_len = userptr_sub ( used, free );
+
+ /* Bubble-sort initrds into desired order */
+ while ( initrd_swap_any ( free, free_len ) ) {}
+
+ /* Debug */
+ initrd_dump();
+}
+
+/**
+ * Check that there is enough space to reshuffle initrds
+ *
+ * @v len Total length of initrds (including padding)
+ * @v bottom Lowest address available for initrds
+ * @ret rc Return status code
+ */
+int initrd_reshuffle_check ( size_t len, userptr_t bottom ) {
+ userptr_t top;
+ size_t available;
+
+ /* Calculate limits of available space for initrds */
+ top = initrd_top;
+ if ( userptr_sub ( initrd_bottom, bottom ) > 0 )
+ bottom = initrd_bottom;
+ available = userptr_sub ( top, bottom );
+
+ /* Allow for a sensible minimum amount of free space */
+ len += INITRD_MIN_FREE_LEN;
+
+ /* Check for available space */
+ return ( ( len < available ) ? 0 : -ENOBUFS );
+}
+
+/**
+ * initrd startup function
+ *
+ */
+static void initrd_startup ( void ) {
+ size_t len;
+
+ /* Record largest memory block available. Do this after any
+ * allocations made during driver startup (e.g. large host
+ * memory blocks for Infiniband devices, which may still be in
+ * use at the time of rearranging if a SAN device is hooked)
+ * but before any allocations for downloaded images (which we
+ * can safely reuse when rearranging).
+ */
+ len = largest_memblock ( &initrd_bottom );
+ initrd_top = userptr_add ( initrd_bottom, len );
+}
+
+/** initrd startup function */
+struct startup_fn startup_initrd __startup_fn ( STARTUP_LATE ) = {
+ .startup = initrd_startup,
+};
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/image/multiboot.c
^
|
@@ -39,6 +39,7 @@
#include <ipxe/init.h>
#include <ipxe/features.h>
#include <ipxe/uri.h>
+#include <ipxe/version.h>
FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 );
@@ -247,7 +248,7 @@
#define mbinfo __use_data16 ( mbinfo )
/** The multiboot bootloader name */
-static char __data16_array ( mb_bootloader_name, [] ) = "iPXE " VERSION;
+static char __bss16_array ( mb_bootloader_name, [32] );
#define mb_bootloader_name __use_data16 ( mb_bootloader_name )
/** The multiboot memory map */
@@ -420,6 +421,8 @@
mbinfo.cmdline = multiboot_add_cmdline ( image );
mbinfo.mods_addr = virt_to_phys ( mbmodules );
mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
+ snprintf ( mb_bootloader_name, sizeof ( mb_bootloader_name ),
+ "iPXE %s", product_version );
mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name );
if ( ( rc = multiboot_add_modules ( image, max, &mbinfo, mbmodules,
( sizeof ( mbmodules ) /
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/image/nbi.c
^
|
@@ -10,6 +10,7 @@
#include <ipxe/fakedhcp.h>
#include <ipxe/image.h>
#include <ipxe/features.h>
+#include <ipxe/version.h>
/** @file
*
@@ -94,12 +95,6 @@
uint16_t flags; /* Bit flags */
};
-/** Info passed to NBI image */
-static struct ebinfo loaderinfo = {
- VERSION_MAJOR, VERSION_MINOR,
- 0
-};
-
/**
* Prepare a segment for an NBI image
*
@@ -281,6 +276,10 @@
* @ret rc Return status code, if image returns
*/
static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) {
+ struct ebinfo loaderinfo = {
+ product_major_version, product_minor_version,
+ 0
+ };
int discard_D, discard_S, discard_b;
int rc;
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/include/initrd.h
^
|
@@ -0,0 +1,29 @@
+#ifndef _INITRD_H
+#define _INITRD_H
+
+/** @file
+ *
+ * Initial ramdisk (initrd) reshuffling
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/uaccess.h>
+
+/** Minimum alignment for initrds
+ *
+ * Chosen to maximise memcpy() speeds
+ */
+#define INITRD_ALIGN 4
+
+/** Minimum free space required to reshuffle initrds
+ *
+ * Chosen to avoid absurdly long reshuffling times
+ */
+#define INITRD_MIN_FREE_LEN ( 512 * 1024 )
+
+extern void initrd_reshuffle ( userptr_t bottom );
+extern int initrd_reshuffle_check ( size_t len, userptr_t bottom );
+
+#endif /* _INITRD_H */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/include/librm.h
^
|
@@ -68,6 +68,12 @@
return trivial_userptr_add ( userptr, offset );
}
+static inline __always_inline off_t
+UACCESS_INLINE ( librm, userptr_sub ) ( userptr_t userptr,
+ userptr_t subtrahend ) {
+ return trivial_userptr_sub ( userptr, subtrahend );
+}
+
static inline __always_inline void
UACCESS_INLINE ( librm, memcpy_user ) ( userptr_t dest, off_t dest_off,
userptr_t src, off_t src_off,
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/interface/pcbios/memtop_umalloc.c
^
|
@@ -31,6 +31,7 @@
#include <ipxe/uaccess.h>
#include <ipxe/hidemem.h>
#include <ipxe/io.h>
+#include <ipxe/memblock.h>
#include <ipxe/umalloc.h>
/** Alignment of external allocated memory */
@@ -59,53 +60,14 @@
/**
* Initialise external heap
*
- * @ret rc Return status code
*/
-static int init_eheap ( void ) {
- struct memory_map memmap;
- unsigned int i;
-
- DBG ( "Allocating external heap\n" );
-
- get_memmap ( &memmap );
- heap_size = 0;
- for ( i = 0 ; i < memmap.count ; i++ ) {
- struct memory_region *region = &memmap.regions[i];
- unsigned long r_start, r_end;
- unsigned long r_size;
-
- DBG ( "Considering [%llx,%llx)\n", region->start, region->end);
-
- /* Truncate block to 4GB */
- if ( region->start > UINT_MAX ) {
- DBG ( "...starts after 4GB\n" );
- continue;
- }
- r_start = region->start;
- if ( region->end > UINT_MAX ) {
- DBG ( "...end truncated to 4GB\n" );
- r_end = 0; /* =4GB, given the wraparound */
- } else {
- r_end = region->end;
- }
-
- /* Use largest block */
- r_size = ( r_end - r_start );
- if ( r_size > heap_size ) {
- DBG ( "...new best block found\n" );
- top = bottom = phys_to_user ( r_end );
- heap_size = r_size;
- }
- }
-
- if ( ! heap_size ) {
- DBG ( "No external heap available\n" );
- return -ENOMEM;
- }
+static void init_eheap ( void ) {
+ userptr_t base;
+ heap_size = largest_memblock ( &base );
+ bottom = top = userptr_add ( base, heap_size );
DBG ( "External heap grows downwards from %lx (size %zx)\n",
user_to_phys ( top, 0 ), heap_size );
- return 0;
}
/**
@@ -144,13 +106,10 @@
struct external_memory extmem;
userptr_t new = ptr;
size_t align;
- int rc;
- /* Initialise external memory allocator if necessary */
- if ( bottom == top ) {
- if ( ( rc = init_eheap() ) != 0 )
- return UNULL;
- }
+ /* (Re)initialise external memory allocator if necessary */
+ if ( bottom == top )
+ init_eheap();
/* Get block properties into extmem */
if ( ptr && ( ptr != UNOWHERE ) ) {
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/i386/interface/syslinux/comboot_call.c
^
|
@@ -39,12 +39,13 @@
#include <ipxe/serial.h>
#include <ipxe/init.h>
#include <ipxe/image.h>
+#include <ipxe/version.h>
#include <usr/imgmgmt.h>
#include "config/console.h"
#include "config/serial.h"
/** The "SYSLINUX" version string */
-static char __data16_array ( syslinux_version, [] ) = "\r\niPXE " VERSION;
+static char __bss16_array ( syslinux_version, [32] );
#define syslinux_version __use_data16 ( syslinux_version )
/** The "SYSLINUX" copyright string */
@@ -326,6 +327,10 @@
/* SYSLINUX derivative ID */
ix86->regs.dl = BZI_LOADER_TYPE_IPXE;
+ /* SYSLINUX version */
+ snprintf ( syslinux_version, sizeof ( syslinux_version ),
+ "\r\niPXE %s", product_version );
+
/* SYSLINUX version and copyright strings */
ix86->segs.es = rm_ds;
ix86->regs.si = ( ( unsigned ) __from_data16 ( syslinux_version ) );
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/x86/core/x86_string.c
^
|
@@ -35,7 +35,8 @@
* @v len Length
* @ret dest Destination address
*/
-void * __memcpy ( void *dest, const void *src, size_t len ) {
+void * __attribute__ (( noinline )) __memcpy ( void *dest, const void *src,
+ size_t len ) {
void *edi = dest;
const void *esi = src;
int discard_ecx;
@@ -56,3 +57,134 @@
: "memory" );
return dest;
}
+
+/**
+ * Copy memory area backwards
+ *
+ * @v dest Destination address
+ * @v src Source address
+ * @v len Length
+ * @ret dest Destination address
+ */
+void * __attribute__ (( noinline )) __memcpy_reverse ( void *dest,
+ const void *src,
+ size_t len ) {
+ void *edi = ( dest + len - 1 );
+ const void *esi = ( src + len - 1 );
+ int discard_ecx;
+
+ /* Assume memmove() is not performance-critical, and perform a
+ * bytewise copy for simplicity.
+ */
+ __asm__ __volatile__ ( "std\n\t"
+ "rep movsb\n\t"
+ "cld\n\t"
+ : "=&D" ( edi ), "=&S" ( esi ),
+ "=&c" ( discard_ecx )
+ : "0" ( edi ), "1" ( esi ),
+ "2" ( len )
+ : "memory" );
+ return dest;
+}
+
+
+/**
+ * Copy (possibly overlapping) memory area
+ *
+ * @v dest Destination address
+ * @v src Source address
+ * @v len Length
+ * @ret dest Destination address
+ */
+void * __memmove ( void *dest, const void *src, size_t len ) {
+
+ if ( dest <= src ) {
+ return __memcpy ( dest, src, len );
+ } else {
+ return __memcpy_reverse ( dest, src, len );
+ }
+}
+
+/**
+ * Swap memory areas
+ *
+ * @v dest Destination address
+ * @v src Source address
+ * @v len Length
+ * @ret dest Destination address
+ */
+void * memswap ( void *dest, void *src, size_t len ) {
+ size_t discard_c;
+ int discard;
+
+ __asm__ __volatile__ ( "\n1:\n\t"
+ "dec %2\n\t"
+ "js 2f\n\t"
+ "movb (%0,%2), %b3\n\t"
+ "xchgb (%1,%2), %b3\n\t"
+ "movb %b3, (%0,%2)\n\t"
+ "jmp 1b\n\t"
+ "2:\n\t"
+ : "=r" ( src ), "=r" ( dest ),
+ "=&c" ( discard_c ), "=&q" ( discard )
+ : "0" ( src ), "1" ( dest ), "2" ( len )
+ : "memory" );
+
+ return dest;
+}
+
+/**
+ * Calculate length of string
+ *
+ * @v string String
+ * @ret len Length (excluding NUL)
+ */
+size_t strlen ( const char *string ) {
+ const char *discard_D;
+ size_t len_plus_one;
+
+ __asm__ __volatile__ ( "repne scasb\n\t"
+ "not %1\n\t"
+ : "=&D" ( discard_D ), "=&c" ( len_plus_one )
+ : "0" ( string ), "1" ( -1UL ), "a" ( 0 ) );
+
+ return ( len_plus_one - 1 );
+}
+
+/**
+ * Compare strings (up to a specified length)
+ *
+ * @v str1 First string
+ * @v str2 Second string
+ * @v len Maximum length
+ * @ret diff Difference
+ */
+int strncmp ( const char *str1, const char *str2, size_t len ) {
+ const void *discard_S;
+ const void *discard_D;
+ size_t discard_c;
+ int diff;
+
+ __asm__ __volatile__ ( "\n1:\n\t"
+ "dec %2\n\t"
+ "js 2f\n\t"
+ "lodsb\n\t"
+ "scasb\n\t"
+ "jne 3f\n\t"
+ "testb %b3, %b3\n\t"
+ "jnz 1b\n\t"
+ /* Equal */
+ "\n2:\n\t"
+ "xor %3, %3\n\t"
+ "jmp 4f\n\t"
+ /* Not equal; CF indicates difference */
+ "\n3:\n\t"
+ "sbb %3, %3\n\t"
+ "orb $1, %b3\n\t"
+ "\n4:\n\t"
+ : "=&S" ( discard_S ), "=&D" ( discard_D ),
+ "=&c" ( discard_c ), "=&a" ( diff )
+ : "0" ( str1 ), "1" ( str2 ), "2" ( len ) );
+
+ return diff;
+}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/x86/include/bits/errfile.h
^
|
@@ -32,6 +32,7 @@
#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_initrd ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000c0000 )
#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/arch/x86/include/bits/string.h
^
|
@@ -1,44 +1,46 @@
-#ifndef ETHERBOOT_BITS_STRING_H
-#define ETHERBOOT_BITS_STRING_H
+#ifndef X86_BITS_STRING_H
+#define X86_BITS_STRING_H
+
/*
- * Taken from Linux /usr/include/asm/string.h
- * All except memcpy, memmove, memset and memcmp removed.
+ * 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.
*
- * Non-standard memswap() function added because it saves quite a bit
- * of code (mbrown@fensystems.co.uk).
+ * 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.
*/
-/*
- * This string-include defines all string functions as inline
- * functions. Use gcc. It also assumes ds=es=data space, this should be
- * normal. Most of the string-functions are rather heavily hand-optimized,
- * see especially strtok,strstr,str[c]spn. They should work, but are not
- * very easy to understand. Everything is done entirely within the register
- * set, making the functions fast and clean. String instructions have been
- * used through-out, making for "slightly" unclear code :-)
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Optimised string operations
*
- * NO Copyright (C) 1991, 1992 Linus Torvalds,
- * consider these trivial functions to be PD.
*/
-FILE_LICENCE ( PUBLIC_DOMAIN );
-
#define __HAVE_ARCH_MEMCPY
extern void * __memcpy ( void *dest, const void *src, size_t len );
+extern void * __memcpy_reverse ( void *dest, const void *src, size_t len );
-#if 0
-static inline __attribute__ (( always_inline )) void *
-__memcpy ( void *dest, const void *src, size_t len ) {
- int d0, d1, d2;
- __asm__ __volatile__ ( "rep ; movsb"
- : "=&c" ( d0 ), "=&S" ( d1 ), "=&D" ( d2 )
- : "0" ( len ), "1" ( src ), "2" ( dest )
- : "memory" );
- return dest;
-}
-#endif
-
+/**
+ * Copy memory area (where length is a compile-time constant)
+ *
+ * @v dest Destination address
+ * @v src Source address
+ * @v len Length
+ * @ret dest Destination address
+ */
static inline __attribute__ (( always_inline )) void *
__constant_memcpy ( void *dest, const void *src, size_t len ) {
union {
@@ -150,103 +152,81 @@
return dest;
}
-#define memcpy( dest, src, len ) \
- ( __builtin_constant_p ( (len) ) ? \
- __constant_memcpy ( (dest), (src), (len) ) : \
- __memcpy ( (dest), (src), (len) ) )
+/**
+ * Copy memory area
+ *
+ * @v dest Destination address
+ * @v src Source address
+ * @v len Length
+ * @ret dest Destination address
+ */
+static inline __attribute__ (( always_inline )) void *
+memcpy ( void *dest, const void *src, size_t len ) {
+ if ( __builtin_constant_p ( len ) ) {
+ return __constant_memcpy ( dest, src, len );
+ } else {
+ return __memcpy ( dest, src, len );
+ }
+}
#define __HAVE_ARCH_MEMMOVE
-static inline void * memmove(void * dest,const void * src, size_t n)
-{
-int d0, d1, d2;
-if (dest<src)
-__asm__ __volatile__(
- "cld\n\t"
- "rep\n\t"
- "movsb"
- : "=&c" (d0), "=&S" (d1), "=&D" (d2)
- :"0" (n),"1" (src),"2" (dest)
- : "memory");
-else
-__asm__ __volatile__(
- "std\n\t"
- "rep\n\t"
- "movsb\n\t"
- "cld"
- : "=&c" (d0), "=&S" (d1), "=&D" (d2)
- :"0" (n),
- "1" (n-1+(const char *)src),
- "2" (n-1+(char *)dest)
- :"memory");
-return dest;
+
+extern void * __memmove ( void *dest, const void *src, size_t len );
+
+/**
+ * Copy (possibly overlapping) memory area
+ *
+ * @v dest Destination address
+ * @v src Source address
+ * @v len Length
+ * @ret dest Destination address
+ */
+static inline __attribute__ (( always_inline )) void *
+memmove ( void *dest, const void *src, size_t len ) {
+ ssize_t offset = ( dest - src );
+
+ if ( __builtin_constant_p ( offset ) ) {
+ if ( offset <= 0 ) {
+ return memcpy ( dest, src, len );
+ } else {
+ return __memcpy_reverse ( dest, src, len );
+ }
+ } else {
+ return __memmove ( dest, src, len );
+ }
}
#define __HAVE_ARCH_MEMSET
-static inline void * memset(void *s, int c,size_t count)
-{
-int d0, d1;
-__asm__ __volatile__(
- "cld\n\t"
- "rep\n\t"
- "stosb"
- : "=&c" (d0), "=&D" (d1)
- :"a" (c),"1" (s),"0" (count)
- :"memory");
-return s;
+
+/**
+ * Fill memory region
+ *
+ * @v dest Destination address
+ * @v fill Fill pattern
+ * @v len Length
+ * @ret dest Destination address
+ */
+static inline void * memset ( void *dest, int fill, size_t len ) {
+ void *discard_D;
+ size_t discard_c;
+
+ __asm__ __volatile__ ( "rep stosb"
+ : "=&D" ( discard_D ), "=&c" ( discard_c )
+ : "0" ( dest ), "1" ( len ), "a" ( fill )
+ : "memory" );
+ return dest;
}
#define __HAVE_ARCH_MEMSWAP
-static inline void * memswap(void *dest, void *src, size_t n)
-{
-long d0, d1, d2, d3;
-__asm__ __volatile__(
- "\n1:\t"
- "movb (%2),%%al\n\t"
- "xchgb (%1),%%al\n\t"
- "inc %1\n\t"
- "stosb\n\t"
- "loop 1b"
- : "=&c" (d0), "=&S" (d1), "=&D" (d2), "=&a" (d3)
- : "0" (n), "1" (src), "2" (dest)
- : "memory" );
-return dest;
-}
+
+extern void * memswap ( void *dest, void *src, size_t len );
#define __HAVE_ARCH_STRNCMP
-static inline int strncmp(const char * cs,const char * ct,size_t count)
-{
-register int __res;
-int d0, d1, d2;
-__asm__ __volatile__(
- "1:\tdecl %3\n\t"
- "js 2f\n\t"
- "lodsb\n\t"
- "scasb\n\t"
- "jne 3f\n\t"
- "testb %%al,%%al\n\t"
- "jne 1b\n"
- "2:\txorl %%eax,%%eax\n\t"
- "jmp 4f\n"
- "3:\tsbbl %%eax,%%eax\n\t"
- "orb $1,%%al\n"
- "4:"
- :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
- :"1" (cs),"2" (ct),"3" (count));
-return __res;
-}
+
+extern int strncmp ( const char *str1, const char *str2, size_t len );
#define __HAVE_ARCH_STRLEN
-static inline size_t strlen(const char * s)
-{
-int d0;
-register int __res;
-__asm__ __volatile__(
- "repne\n\t"
- "scasb\n\t"
- "notl %0\n\t"
- "decl %0"
- :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
-return __res;
-}
-#endif /* ETHERBOOT_BITS_STRING_H */
+extern size_t strlen ( const char *string );
+
+#endif /* X86_BITS_STRING_H */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/arch/x86_64/Makefile
^
|
@@ -26,6 +26,18 @@
#
CFLAGS += -Ui386
+# Add -maccumulate-outgoing-args if required by this version of gcc
+#
+ifeq ($(CCTYPE),gcc)
+MS_ABI_TEST_CODE := extern void __attribute__ (( ms_abi )) ms_abi(); \
+ void sysv_abi ( void ) { ms_abi(); }
+MS_ABI_TEST = $(ECHO) '$(MS_ABI_TEST_CODE)' | \
+ $(CC) -m64 -mno-accumulate-outgoing-args -x c -c - -o /dev/null \
+ >/dev/null 2>&1
+MS_ABI_FLAGS := $(shell $(MS_ABI_TEST) || $(ECHO) '-maccumulate-outgoing-args')
+WORKAROUND_CFLAGS += $(MS_ABI_FLAGS)
+endif
+
# x86_64-specific directories containing source files
#
SRCDIRS += arch/x86_64/prefix
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/list.c
^
|
@@ -0,0 +1,84 @@
+/*
+ * 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
+ *
+ * Linked lists
+ *
+ */
+
+#include <ipxe/list.h>
+
+void extern_list_add ( struct list_head *new, struct list_head *head ) {
+ inline_list_add ( new, head );
+}
+
+void extern_list_add_tail ( struct list_head *new, struct list_head *head ) {
+ inline_list_add_tail ( new, head );
+}
+
+void extern_list_del ( struct list_head *list ) {
+ inline_list_del ( list );
+}
+
+int extern_list_empty ( const struct list_head *list ) {
+ return inline_list_empty ( list );
+}
+
+int extern_list_is_singular ( const struct list_head *list ) {
+ return inline_list_is_singular ( list );
+}
+
+int extern_list_is_last ( const struct list_head *list,
+ const struct list_head *head ) {
+ return inline_list_is_last ( list, head );
+}
+
+void extern_list_cut_position ( struct list_head *new,
+ struct list_head *list,
+ struct list_head *entry ) {
+ inline_list_cut_position ( new, list, entry );
+}
+
+void extern_list_splice ( const struct list_head *list,
+ struct list_head *entry ) {
+ inline_list_splice ( list, entry );
+}
+
+void extern_list_splice_tail ( const struct list_head *list,
+ struct list_head *entry ) {
+ inline_list_splice_tail ( list, entry );
+}
+
+void extern_list_splice_init ( struct list_head *list,
+ struct list_head *entry ) {
+ inline_list_splice_init ( list, entry );
+}
+
+void extern_list_splice_tail_init ( struct list_head *list,
+ struct list_head *entry ) {
+ inline_list_splice_tail_init ( list, entry );
+}
+
+int extern_list_contains ( struct list_head *entry,
+ struct list_head *head ) {
+ return inline_list_contains ( entry, head );
+}
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/main.c
^
|
@@ -21,6 +21,7 @@
#include <ipxe/shell.h>
#include <ipxe/image.h>
#include <ipxe/keys.h>
+#include <ipxe/version.h>
#include <usr/prompt.h>
#include <usr/autoboot.h>
#include <config/general.h>
@@ -82,10 +83,10 @@
* do so.
*
*/
- printf ( NORMAL "\n\n" PRODUCT_NAME "\n" BOLD "iPXE " VERSION
+ printf ( NORMAL "\n\n" PRODUCT_NAME "\n" BOLD "iPXE %s"
NORMAL " -- Open Source Network Boot Firmware -- "
CYAN "http://ipxe.org" NORMAL "\n"
- "Features:" );
+ "Features:", product_version );
for_each_table_entry ( feature, FEATURES )
printf ( " %s", feature->name );
printf ( "\n" );
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/memblock.c
^
|
@@ -0,0 +1,81 @@
+/*
+ * 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
+ *
+ * Largest memory block
+ *
+ */
+
+#include <stdint.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/io.h>
+#include <ipxe/memblock.h>
+
+/**
+ * Find largest usable memory region
+ *
+ * @ret start Start of region
+ * @ret len Length of region
+ */
+size_t largest_memblock ( userptr_t *start ) {
+ struct memory_map memmap;
+ struct memory_region *region;
+ physaddr_t max = ~( ( physaddr_t ) 0 );
+ physaddr_t region_start;
+ physaddr_t region_end;
+ size_t region_len;
+ unsigned int i;
+ size_t len = 0;
+
+ /* Avoid returning uninitialised data on error */
+ *start = UNULL;
+
+ /* Scan through all memory regions */
+ get_memmap ( &memmap );
+ for ( i = 0 ; i < memmap.count ; i++ ) {
+ region = &memmap.regions[i];
+ DBG ( "Considering [%llx,%llx)\n", region->start, region->end );
+
+ /* Truncate block to maximum physical address */
+ if ( region->start > max ) {
+ DBG ( "...starts after maximum address %lx\n", max );
+ continue;
+ }
+ region_start = region->start;
+ if ( region->end > max ) {
+ DBG ( "...end truncated to maximum address %lx\n", max);
+ region_end = 0; /* =max, given the wraparound */
+ } else {
+ region_end = region->end;
+ }
+ region_len = ( region_end - region_start );
+
+ /* Use largest block */
+ if ( region_len > len ) {
+ DBG ( "...new best block found\n" );
+ *start = phys_to_user ( region_start );
+ len = region_len;
+ }
+ }
+
+ return len;
+}
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/core/version.c
^
|
@@ -0,0 +1,41 @@
+/*
+ * 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
+ *
+ * Version number
+ *
+ */
+
+#include <ipxe/features.h>
+#include <ipxe/version.h>
+
+/** Version number feature */
+FEATURE_VERSION ( VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH );
+
+/** Product major version */
+const int product_major_version = VERSION_MAJOR;
+
+/** Product minor version */
+const int product_minor_version = VERSION_MINOR;
+
+/** Product version string */
+const char *product_version = VERSION;
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/efi/efi_uaccess.h
^
|
@@ -56,6 +56,12 @@
return trivial_userptr_add ( userptr, offset );
}
+static inline __always_inline off_t
+UACCESS_INLINE ( efi, userptr_sub ) ( userptr_t userptr,
+ userptr_t subtrahend ) {
+ return trivial_userptr_sub ( userptr, subtrahend );
+}
+
static inline __always_inline void
UACCESS_INLINE ( efi, memcpy_user ) ( userptr_t dest, off_t dest_off,
userptr_t src, off_t src_off,
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/linux/linux_uaccess.h
^
|
@@ -71,6 +71,12 @@
return trivial_userptr_add(userptr, offset);
}
+static inline __always_inline off_t
+UACCESS_INLINE(linux, userptr_sub)(userptr_t userptr, userptr_t subtrahend)
+{
+ return trivial_userptr_sub ( userptr, subtrahend );
+}
+
static inline __always_inline void
UACCESS_INLINE(linux, memcpy_user)(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len)
{
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/list.h
^
|
@@ -42,9 +42,9 @@
*
* @v list List head
*/
-#define INIT_LIST_HEAD( list ) do { \
- (list)->next = (list); \
- (list)->prev = (list); \
+#define INIT_LIST_HEAD( list ) do { \
+ (list)->next = (list); \
+ (list)->prev = (list); \
} while ( 0 )
/**
@@ -52,43 +52,35 @@
*
* @v list List entry or head
*/
-#define list_check( list ) ( { \
- assert ( (list) != NULL ); \
- assert ( (list)->prev != NULL ); \
- assert ( (list)->next != NULL ); \
- assert ( (list)->next->prev == (list) ); \
- assert ( (list)->prev->next == (list) ); \
+#define list_check( list ) ( { \
+ assert ( (list) != NULL ); \
+ assert ( (list)->prev != NULL ); \
+ assert ( (list)->next != NULL ); \
+ assert ( (list)->next->prev == (list) ); \
+ assert ( (list)->prev->next == (list) ); \
} )
/**
- * Insert a list entry between two known consecutive entries
- *
- * @v new New list entry
- * @v prev Previous list entry
- * @v next Next list entry
- */
-static inline void __list_add ( struct list_head *new,
- struct list_head *prev,
- struct list_head *next ) {
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-/**
* Add a new entry to the head of a list
*
* @v new New entry to be added
* @v head List head, or entry after which to add the new entry
*/
-static inline void list_add ( struct list_head *new, struct list_head *head ) {
- __list_add ( new, head, head->next );
-}
-#define list_add( new, head ) do { \
- list_check ( (head) ); \
- list_add ( (new), (head) ); \
+#define list_add( new, head ) do { \
+ list_check ( (head) ); \
+ extern_list_add ( (new), (head) ); \
} while ( 0 )
+static inline void inline_list_add ( struct list_head *new,
+ struct list_head *head ) {
+ struct list_head *prev = head;
+ struct list_head *next = head->next;
+ next->prev = (new);
+ (new)->next = next;
+ (new)->prev = prev;
+ prev->next = (new);
+}
+extern void extern_list_add ( struct list_head *new,
+ struct list_head *head );
/**
* Add a new entry to the tail of a list
@@ -96,26 +88,21 @@
* @v new New entry to be added
* @v head List head, or entry before which to add the new entry
*/
-static inline void list_add_tail ( struct list_head *new,
- struct list_head *head ) {
- __list_add ( new, head->prev, head );
-}
-#define list_add_tail( new, head ) do { \
- list_check ( (head) ); \
- list_add_tail ( (new), (head) ); \
+#define list_add_tail( new, head ) do { \
+ list_check ( (head) ); \
+ extern_list_add_tail ( (new), (head) ); \
} while ( 0 )
-
-/**
- * Delete a list entry between two known consecutive entries
- *
- * @v prev Previous list entry
- * @v next Next list entry
- */
-static inline void __list_del ( struct list_head *prev,
- struct list_head *next ) {
- next->prev = prev;
- prev->next = next;
+static inline void inline_list_add_tail ( struct list_head *new,
+ struct list_head *head ) {
+ struct list_head *prev = head->prev;
+ struct list_head *next = head;
+ next->prev = (new);
+ (new)->next = next;
+ (new)->prev = prev;
+ prev->next = (new);
}
+extern void extern_list_add_tail ( struct list_head *new,
+ struct list_head *head );
/**
* Delete an entry from a list
@@ -125,37 +112,43 @@
* Note that list_empty() on entry does not return true after this;
* the entry is in an undefined state.
*/
-static inline void list_del ( struct list_head *list ) {
- __list_del ( list->prev, list->next );
-}
-#define list_del( list ) do { \
- list_check ( (list) ); \
- list_del ( (list) ); \
+#define list_del( list ) do { \
+ list_check ( (list) ); \
+ inline_list_del ( (list) ); \
} while ( 0 )
+static inline void inline_list_del ( struct list_head *list ) {
+ struct list_head *next = (list)->next;
+ struct list_head *prev = (list)->prev;
+ next->prev = prev;
+ prev->next = next;
+}
+extern void extern_list_del ( struct list_head *list );
/**
* Test whether a list is empty
*
* @v list List head
*/
-static inline int list_empty ( const struct list_head *list ) {
+#define list_empty( list ) ( { \
+ list_check ( (list) ); \
+ inline_list_empty ( (list) ); } )
+static inline int inline_list_empty ( const struct list_head *list ) {
return ( list->next == list );
}
-#define list_empty( list ) ( { \
- list_check ( (list) ); \
- list_empty ( (list) ); } )
+extern int extern_list_empty ( const struct list_head *list );
/**
* Test whether a list has just one entry
*
* @v list List to test
*/
-static inline int list_is_singular ( const struct list_head *list ) {
+#define list_is_singular( list ) ( { \
+ list_check ( (list) ); \
+ inline_list_is_singular ( (list) ); } )
+static inline int inline_list_is_singular ( const struct list_head *list ) {
return ( ( ! list_empty ( list ) ) && ( list->next == list->prev ) );
}
-#define list_is_singular( list ) ( { \
- list_check ( (list) ); \
- list_is_singular ( (list) ); } )
+extern int extern_list_is_singular ( const struct list_head *list );
/**
* Test whether an entry is the last entry in list
@@ -163,14 +156,16 @@
* @v list List entry to test
* @v head List head
*/
-static inline int list_is_last ( const struct list_head *list,
- const struct list_head *head ) {
+#define list_is_last( list, head ) ( { \
+ list_check ( (list) ); \
+ list_check ( (head) ); \
+ inline_list_is_last ( (list), (head) ); } )
+static inline int inline_list_is_last ( const struct list_head *list,
+ const struct list_head *head ) {
return ( list->next == head );
}
-#define list_is_last( list, head ) ( { \
- list_check ( (list) ); \
- list_check ( (head) ); \
- list_is_last ( (list), (head) ); } )
+extern int extern_list_is_last ( const struct list_head *list,
+ const struct list_head *head );
/**
* Cut a list into two
@@ -183,9 +178,16 @@
* @c new, which should be an empty list. @c entry may be equal to @c
* list, in which case no entries are moved.
*/
-static inline void list_cut_position ( struct list_head *new,
- struct list_head *list,
- struct list_head *entry ) {
+#define list_cut_position( new, list, entry ) do { \
+ list_check ( (new) ); \
+ assert ( list_empty ( (new) ) ); \
+ list_check ( (list) ); \
+ list_check ( (entry) ); \
+ extern_list_cut_position ( (new), (list), (entry) ); \
+ } while ( 0 )
+static inline void inline_list_cut_position ( struct list_head *new,
+ struct list_head *list,
+ struct list_head *entry ) {
struct list_head *first = entry->next;
if ( list != entry ) {
@@ -197,13 +199,9 @@
list->next->prev = list;
}
}
-#define list_cut_position( new, list, entry ) do { \
- list_check ( (new) ); \
- assert ( list_empty ( (new) ) ); \
- list_check ( (list) ); \
- list_check ( (entry) ); \
- list_cut_position ( (new), (list), (entry) ); \
- } while ( 0 )
+extern void extern_list_cut_position ( struct list_head *new,
+ struct list_head *list,
+ struct list_head *entry );
/**
* Move all entries from one list into another list
@@ -215,8 +213,13 @@
* list is left in an undefined state; use @c list_splice_init() if
* you want @c list to become an empty list.
*/
-static inline void list_splice ( const struct list_head *list,
- struct list_head *entry ) {
+#define list_splice( list, entry ) do { \
+ list_check ( (list) ); \
+ list_check ( (entry) ); \
+ extern_list_splice ( (list), (entry) ); \
+ } while ( 0 )
+static inline void inline_list_splice ( const struct list_head *list,
+ struct list_head *entry ) {
struct list_head *first = list->next;
struct list_head *last = list->prev;
@@ -227,11 +230,8 @@
first->prev->next = first;
}
}
-#define list_splice( list, entry ) do { \
- list_check ( (list) ); \
- list_check ( (entry) ); \
- list_splice ( (list), (entry) ); \
- } while ( 0 )
+extern void extern_list_splice ( const struct list_head *list,
+ struct list_head *entry );
/**
* Move all entries from one list into another list
@@ -243,8 +243,13 @@
* list is left in an undefined state; use @c list_splice_tail_init() if
* you want @c list to become an empty list.
*/
-static inline void list_splice_tail ( const struct list_head *list,
- struct list_head *entry ) {
+#define list_splice_tail( list, entry ) do { \
+ list_check ( (list) ); \
+ list_check ( (entry) ); \
+ extern_list_splice_tail ( (list), (entry) ); \
+ } while ( 0 )
+static inline void inline_list_splice_tail ( const struct list_head *list,
+ struct list_head *entry ) {
struct list_head *first = list->next;
struct list_head *last = list->prev;
@@ -255,11 +260,8 @@
last->next->prev = last;
}
}
-#define list_splice_tail( list, entry ) do { \
- list_check ( (list) ); \
- list_check ( (entry) ); \
- list_splice_tail ( (list), (entry) ); \
- } while ( 0 )
+extern void extern_list_splice_tail ( const struct list_head *list,
+ struct list_head *entry );
/**
* Move all entries from one list into another list and reinitialise empty list
@@ -269,16 +271,18 @@
*
* All entries from @c list are inserted after @c entry.
*/
-static inline void list_splice_init ( struct list_head *list,
- struct list_head *entry ) {
+#define list_splice_init( list, entry ) do { \
+ list_check ( (list) ); \
+ list_check ( (entry) ); \
+ extern_list_splice_init ( (list), (entry) ); \
+ } while ( 0 )
+static inline void inline_list_splice_init ( struct list_head *list,
+ struct list_head *entry ) {
list_splice ( list, entry );
INIT_LIST_HEAD ( list );
}
-#define list_splice_init( list, entry ) do { \
- list_check ( (list) ); \
- list_check ( (entry) ); \
- list_splice_init ( (list), (entry) ); \
- } while ( 0 )
+extern void extern_list_splice_init ( struct list_head *list,
+ struct list_head *entry );
/**
* Move all entries from one list into another list and reinitialise empty list
@@ -288,16 +292,19 @@
*
* All entries from @c list are inserted before @c entry.
*/
-static inline void list_splice_tail_init ( struct list_head *list,
- struct list_head *entry ) {
+#define list_splice_tail_init( list, entry ) do { \
+ list_check ( (list) ); \
+ list_check ( (entry) ); \
+ extern_list_splice_tail_init ( (list), (entry) ); \
+ } while ( 0 )
+
+static inline void inline_list_splice_tail_init ( struct list_head *list,
+ struct list_head *entry ) {
list_splice_tail ( list, entry );
INIT_LIST_HEAD ( list );
}
-#define list_splice_tail_init( list, entry ) do { \
- list_check ( (list) ); \
- list_check ( (entry) ); \
- list_splice_tail_init ( (list), (entry) ); \
- } while ( 0 )
+extern void extern_list_splice_tail_init ( struct list_head *list,
+ struct list_head *entry );
/**
* Get the container of a list entry
@@ -307,8 +314,8 @@
* @v member Name of list field within containing type
* @ret container Containing object
*/
-#define list_entry( list, type, member ) ( { \
- list_check ( (list) ); \
+#define list_entry( list, type, member ) ( { \
+ list_check ( (list) ); \
container_of ( list, type, member ); } )
/**
@@ -319,9 +326,9 @@
* @v member Name of list field within containing type
* @ret first First list entry, or NULL
*/
-#define list_first_entry( list, type, member ) \
- ( list_empty ( (list) ) ? \
- ( type * ) NULL : \
+#define list_first_entry( list, type, member ) \
+ ( list_empty ( (list) ) ? \
+ ( type * ) NULL : \
list_entry ( (list)->next, type, member ) )
/**
@@ -332,9 +339,9 @@
* @v member Name of list field within containing type
* @ret first First list entry, or NULL
*/
-#define list_last_entry( list, type, member ) \
- ( list_empty ( (list) ) ? \
- ( type * ) NULL : \
+#define list_last_entry( list, type, member ) \
+ ( list_empty ( (list) ) ? \
+ ( type * ) NULL : \
list_entry ( (list)->prev, type, member ) )
/**
@@ -424,8 +431,12 @@
* @v head List head
* @ret present List contains specified entry
*/
-static inline int list_contains ( struct list_head *entry,
- struct list_head *head ) {
+#define list_contains( entry, head ) ( { \
+ list_check ( (head) ); \
+ list_check ( (entry) ); \
+ extern_list_contains ( (entry), (head) ); } )
+static inline int inline_list_contains ( struct list_head *entry,
+ struct list_head *head ) {
struct list_head *tmp;
list_for_each ( tmp, head ) {
@@ -434,10 +445,8 @@
}
return 0;
}
-#define list_contains( entry, head ) ( { \
- list_check ( (head) ); \
- list_check ( (entry) ); \
- list_contains ( (entry), (head) ); } )
+extern int extern_list_contains ( struct list_head *entry,
+ struct list_head *head );
/**
* Test if list contains a specified entry
@@ -446,7 +455,7 @@
* @v head List head
* @ret present List contains specified entry
*/
-#define list_contains_entry( entry, head, member ) \
+#define list_contains_entry( entry, head, member ) \
list_contains ( &(entry)->member, (head) )
/**
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/memblock.h
^
|
@@ -0,0 +1,17 @@
+#ifndef _IPXE_MEMBLOCK_H
+#define _IPXE_MEMBLOCK_H
+
+/** @file
+ *
+ * Largest memory block
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <ipxe/uaccess.h>
+
+extern size_t largest_memblock ( userptr_t *start );
+
+#endif /* _IPXE_MEMBLOCK_H */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/uaccess.h
^
|
@@ -83,6 +83,18 @@
}
/**
+ * Subtract user pointers
+ *
+ * @v userptr User pointer
+ * @v subtrahend User pointer to be subtracted
+ * @ret offset Offset
+ */
+static inline __always_inline off_t
+trivial_userptr_sub ( userptr_t userptr, userptr_t subtrahend ) {
+ return ( userptr - subtrahend );
+}
+
+/**
* Copy data between user buffers
*
* @v dest Destination
@@ -240,6 +252,15 @@
userptr_t userptr_add ( userptr_t userptr, off_t offset );
/**
+ * Subtract user pointers
+ *
+ * @v userptr User pointer
+ * @v subtrahend User pointer to be subtracted
+ * @ret offset Offset
+ */
+off_t userptr_sub ( userptr_t userptr, userptr_t subtrahend );
+
+/**
* Convert virtual address to a physical address
*
* @v addr Virtual address
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/ipxe/version.h
^
|
@@ -0,0 +1,16 @@
+#ifndef _IPXE_VERSION_H
+#define _IPXE_VERSION_H
+
+/** @file
+ *
+ * Version number
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern const int product_major_version;
+extern const int product_minor_version;
+extern const char *product_version;
+
+#endif /* _IPXE_VERSION_H */
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/include/string.h
^
|
@@ -37,6 +37,7 @@
char * strtok(char * s,const char * ct) __nonnull;
char * strsep(char **s, const char *ct) __nonnull;
void * memset(void * s,int c,size_t count) __nonnull;
+void * memcpy ( void *dest, const void *src, size_t len ) __nonnull;
void * memmove(void * dest,const void *src,size_t count) __nonnull;
int __pure memcmp(const void * cs,const void * ct,
size_t count) __nonnull;
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/interface/efi/efi_snp_hii.c
^
|
@@ -54,6 +54,7 @@
#include <ipxe/nvo.h>
#include <ipxe/device.h>
#include <ipxe/netdevice.h>
+#include <ipxe/version.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_hii.h>
#include <ipxe/efi/efi_snp.h>
@@ -196,7 +197,7 @@
efi_ifr_text_op ( &ifr,
efi_ifr_string ( &ifr, "Version" ),
efi_ifr_string ( &ifr, "Firmware version" ),
- efi_ifr_string ( &ifr, VERSION ) );
+ efi_ifr_string ( &ifr, "%s", product_version ) );
efi_ifr_text_op ( &ifr,
efi_ifr_string ( &ifr, "Driver" ),
efi_ifr_string ( &ifr, "Firmware driver" ),
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/tcp/httpcore.c
^
|
@@ -48,6 +48,7 @@
#include <ipxe/md5.h>
#include <ipxe/blockdev.h>
#include <ipxe/acpi.h>
+#include <ipxe/version.h>
#include <ipxe/http.h>
/* Disambiguate the various error causes */
@@ -1141,11 +1142,11 @@
/* Send request */
if ( ( rc = xfer_printf ( &http->socket,
"%s %s HTTP/1.1\r\n"
- "User-Agent: iPXE/" VERSION "\r\n"
+ "User-Agent: iPXE/%s\r\n"
"Host: %s%s%s\r\n"
"%s%s%s"
"\r\n",
- method, uri, http->uri->host,
+ method, uri, product_version, http->uri->host,
( http->uri->port ?
":" : "" ),
( http->uri->port ?
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/net/udp/dhcp.c
^
|
@@ -91,9 +91,6 @@
DHCP_END
};
-/** Version number feature */
-FEATURE_VERSION ( VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH );
-
/** DHCP server address setting */
struct setting dhcp_server_setting __setting ( SETTING_MISC ) = {
.name = "dhcp-server",
|
[-]
[+]
|
Added |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/string_test.c
^
|
@@ -0,0 +1,133 @@
+/*
+ * 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
+ *
+ * String self-tests
+ *
+ * memcpy() tests are handled separately
+ */
+
+/* Forcibly enable assertions */
+#undef NDEBUG
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ipxe/test.h>
+
+/**
+ * Perform string self-tests
+ *
+ */
+static void string_test_exec ( void ) {
+
+ /* Test strlen() */
+ ok ( strlen ( "" ) == 0 );
+ ok ( strlen ( "Hello" ) == 5 );
+ ok ( strlen ( "Hello world!" ) == 12 );
+ ok ( strlen ( "Hello\0world!" ) == 5 );
+
+ /* Test strnlen() */
+ ok ( strnlen ( "", 0 ) == 0 );
+ ok ( strnlen ( "", 10 ) == 0 );
+ ok ( strnlen ( "Hello", 0 ) == 0 );
+ ok ( strnlen ( "Hello", 3 ) == 3 );
+ ok ( strnlen ( "Hello", 5 ) == 5 );
+ ok ( strnlen ( "Hello", 16 ) == 5 );
+ ok ( strnlen ( "Hello world!", 5 ) == 5 );
+ ok ( strnlen ( "Hello world!", 11 ) == 11 );
+ ok ( strnlen ( "Hello world!", 16 ) == 12 );
+
+ /* Test strchr() */
+ ok ( strchr ( "", 'a' ) == NULL );
+ ok ( *(strchr ( "Testing", 'e' )) == 'e' );
+ ok ( *(strchr ( "Testing", 'g' )) == 'g' );
+ ok ( strchr ( "Testing", 'x' ) == NULL );
+
+ /* Test strcmp() */
+ ok ( strcmp ( "", "" ) == 0 );
+ ok ( strcmp ( "Hello", "Hello" ) == 0 );
+ ok ( strcmp ( "Hello", "hello" ) != 0 );
+ ok ( strcmp ( "Hello", "Hello world!" ) != 0 );
+ ok ( strcmp ( "Hello world!", "Hello" ) != 0 );
+
+ /* Test strncmp() */
+ ok ( strncmp ( "", "", 0 ) == 0 );
+ ok ( strncmp ( "", "", 15 ) == 0 );
+ ok ( strncmp ( "Goodbye", "Goodbye", 16 ) == 0 );
+ ok ( strncmp ( "Goodbye", "Hello", 16 ) != 0 );
+ ok ( strncmp ( "Goodbye", "Goodbye world", 32 ) != 0 );
+ ok ( strncmp ( "Goodbye", "Goodbye world", 7 ) == 0 );
+
+ /* Test memcmp() */
+ ok ( memcmp ( "", "", 0 ) == 0 );
+ ok ( memcmp ( "Foo", "Foo", 3 ) == 0 );
+ ok ( memcmp ( "Foo", "Bar", 3 ) != 0 );
+
+ /* Test memset() */
+ {
+ static uint8_t test[7] = { '>', 1, 1, 1, 1, 1, '<' };
+ static const uint8_t expected[7] = { '>', 0, 0, 0, 0, 0, '<' };
+ memset ( ( test + 1 ), 0, ( sizeof ( test ) - 2 ) );
+ ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 );
+ }
+ {
+ static uint8_t test[4] = { '>', 0, 0, '<' };
+ static const uint8_t expected[4] = { '>', 0xeb, 0xeb, '<' };
+ memset ( ( test + 1 ), 0xeb, ( sizeof ( test ) - 2 ) );
+ ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 );
+ }
+
+ /* Test memmove() */
+ {
+ static uint8_t test[11] =
+ { '>', 1, 2, 3, 4, 5, 6, 7, 8, 9, '<' };
+ static const uint8_t expected[11] =
+ { '>', 3, 4, 5, 6, 7, 8, 7, 8, 9, '<' };
+ memmove ( ( test + 1 ), ( test + 3 ), 6 );
+ ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 );
+ }
+ {
+ static uint8_t test[12] =
+ { '>', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, '<' };
+ static const uint8_t expected[12] =
+ { '>', 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, '<' };
+ memmove ( ( test + 6 ), ( test + 1 ), 5 );
+ ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 );
+ }
+
+ /* Test memswap() */
+ {
+ static uint8_t test[8] =
+ { '>', 1, 2, 3, 7, 8, 9, '<' };
+ static const uint8_t expected[8] =
+ { '>', 7, 8, 9, 1, 2, 3, '<' };
+ memswap ( ( test + 1 ), ( test + 4 ), 3 );
+ ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 );
+ }
+}
+
+/** String self-test */
+struct self_test string_test __self_test = {
+ .name = "string",
+ .exec = string_test_exec,
+};
|
[-]
[+]
|
Changed |
_service:recompress:tar_scm:ipxe-1.0.0git.tar.gz/src/tests/tests.c
^
|
@@ -27,6 +27,7 @@
/* Drag in all applicable self-tests */
REQUIRE_OBJECT ( memcpy_test );
+REQUIRE_OBJECT ( string_test );
REQUIRE_OBJECT ( list_test );
REQUIRE_OBJECT ( byteswap_test );
REQUIRE_OBJECT ( base64_test );
|