manual merge
authorJoshua Oreman <oremanj@krypton.lan>
Sat, 2 May 2009 20:07:40 +0000 (13:07 -0700)
committerJoshua Oreman <oremanj@krypton.lan>
Sat, 2 May 2009 20:07:40 +0000 (13:07 -0700)
29 files changed:
contrib/bochs/README.qemu
src/Makefile
src/Makefile.housekeeping
src/README.pixify [deleted file]
src/arch/i386/Makefile
src/arch/i386/Makefile.pcbios
src/arch/i386/core/etherboot.prefix.lds [deleted file]
src/arch/i386/core/prefixudata.lds [deleted file]
src/arch/i386/core/prefixzdata.lds [deleted file]
src/arch/i386/core/realmode.c [deleted file]
src/arch/i386/core/start16.lds [deleted file]
src/arch/i386/core/start16z.lds [deleted file]
src/arch/i386/firmware/pcbios/e820mangler.S
src/arch/i386/firmware/pcbios/fakee820.c
src/arch/i386/image/multiboot.c
src/arch/i386/include/callbacks_arch.h [deleted file]
src/arch/i386/interface/pxe/pxe_entry.S
src/arch/i386/prefix/pxeprefix.S
src/arch/i386/prefix/unnrv2b16.S [new file with mode: 0644]
src/core/gdbstub.c
src/image/elf.c
src/include/compiler.h
src/include/gpxe/smbios.h
src/interface/smbios/smbios_settings.c
src/net/dhcppkt.c
src/util/dskpad.pl [deleted file]
src/util/fwtools.c
src/util/padimg.pl [new file with mode: 0755]
src/util/zbin.c

index 1857510..0c38897 100644 (file)
@@ -47,13 +47,13 @@ To get qemu running is fairly simple:
 
 8.  Build gPXE floppy disk images and pad to 1.44MB
       pushd ../../src
-      make bin/rtl8139.pdsk
+      make bin/rtl8139.dsk
       popd
 
 9.  Start qemu
       ./qemu/i386-softmmu/qemu -L qemu/pc-bios \
                               -net nic,model=rtl8139 -net tap,ifname=tap0 \
-                              -boot a -fda ../../src/bin/rtl8139.pdsk 
+                              -boot a -fda ../../src/bin/rtl8139.dsk
 
 You should see qemu start up, load up gPXE and attempt to boot from
 the network.
index 4d1e89d..6184a19 100644 (file)
@@ -35,6 +35,7 @@ PARSEROM      := $(PERL) ./util/parserom.pl
 MAKEROM                := $(PERL) ./util/makerom.pl
 SYMCHECK       := $(PERL) ./util/symcheck.pl
 SORTOBJDUMP    := $(PERL) ./util/sortobjdump.pl
+PADIMG         := $(PERL) ./util/padimg.pl
 NRV2B          := ./util/nrv2b
 ZBIN           := ./util/zbin
 ELF2EFI32      := ./util/elf2efi32
index 8aebca8..72d63b5 100644 (file)
@@ -419,23 +419,6 @@ define src_template
        @$(MKDIR) -p $(dir $(2))
        @$(RM) $(2)
        @$(TOUCH) $(2)
-       $(foreach OBJ,$(if $(OBJS_$(4)),$(OBJS_$(4)),$(4)), \
-               $(call obj_template,$(1),$(2),$(3),$(OBJ)))
-       @$(PARSEROM) $(1) >> $(2)
-
-endef
-
-# obj_template : generate Makefile rules for a given resultant object
-# of a particular source file.  (We can have multiple objects per
-# source file via the OBJS_xxx list.)
-#
-# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c")
-# $(2) is the full path to the .d file (e.g. "bin/deps/drivers/net/rtl8139.d")
-# $(3) is the source type (e.g. "c")
-# $(4) is the object name (e.g. "rtl8139")
-#
-define obj_template
-
        @$(CPP) $(CFLAGS) $(CFLAGS_$(3)) $(CFLAGS_$(4)) -DOBJECT=$(4) \
                -Wno-error -MM $(1) -MG -MP | \
                sed 's/\.o\s*:/_DEPS =/' >> $(2)
@@ -454,6 +437,7 @@ define obj_template
                 '\n$(2) : $$($(4)_DEPS)\n' \
                 '\nTAGS : $$($(4)_DEPS)\n' \
                >> $(2)
+       @$(PARSEROM) $(1) >> $(2)
 
 endef
 
@@ -664,6 +648,37 @@ $(BIN)/%.tmp : $(BLIB) $(MAKEDEPS) $(LDSCRIPT)
 $(BIN)/%.map : $(BIN)/%.tmp
        @less $(BIN)/$*.tmp.map
 
+# Get objects list for the specified target
+#
+define objs_list
+       $(sort $(foreach OBJ_SYMBOL,\
+                $(filter obj_%,$(shell $(NM) $(1) | cut -d" " -f3)),\
+                $(patsubst obj_%,%,$(OBJ_SYMBOL))))
+endef
+$(BIN)/%.objs : $(BIN)/%.tmp
+       $(Q)$(ECHO) $(call objs_list,$<)
+$(BIN)/%.sizes : $(BIN)/%.tmp
+       $(Q)$(SIZE) -t $(foreach OBJ,$(call objs_list,$<),$(BIN)/$(OBJ).o) | \
+               sort -g
+
+# Get dependency list for the specified target
+#
+define deps_list
+       $(sort $(foreach OBJ,$(call objs_list,$(1)),$($(OBJ)_DEPS)))
+endef
+$(BIN)/%.deps : $(BIN)/%.tmp
+       $(Q)$(ECHO) $(call deps_list,$<)
+
+# Get unneeded source files for the specified target
+#
+define nodeps_list
+       $(sort $(filter-out $(call deps_list,$<),\
+                $(foreach BOBJ,$(BOBJS),\
+                  $($(basename $(notdir $(BOBJ)))_DEPS))))
+endef
+$(BIN)/%.nodeps : $(BIN)/%.tmp
+       $(Q)$(ECHO) $(call nodeps_list,$<)
+
 # Extract compression information from intermediate object file
 #
 $(BIN)/%.zinfo : $(BIN)/%.tmp
@@ -724,6 +739,7 @@ define media_template
        @$(ECHO_E) '$$(BIN)/%.$(1) : $$(BIN)/%.$(1).zbin' \
                  '\n\t$$(QM)$(ECHO) "  [FINISH] $$@"' \
                  '\n\t$$(Q)$$(CP) $$< $$@' \
+                 '\n\t$$(Q)$$(PAD_$(1))' \
                  '\n\t$$(Q)$$(FINALISE_$(1))' \
                > $(2)
 
@@ -836,6 +852,16 @@ CLEANUP += $(ICCFIX)
 $(FIREBUG) : util/firebug.c util/fwtools.c $(MAKEDEPS)
        $(QM)$(ECHO) "  [HOSTCC] $@"
        $(Q)$(HOST_CC) -idirafter include -O2 -o $@ $< util/fwtools.c -lraw1394
+CLEANUP += $(FIREBUG)
+
+###############################################################################
+#
+# The FireWire image server
+#
+$(FIRESERVE) : util/fireserve.c util/fwtools.c $(MAKEDEPS)
+       $(QM)$(ECHO) "  [HOSTCC] $@"
+       $(Q)$(HOST_CC) -idirafter include -O2 -o $@ $< util/fwtools.c -lraw1394
+CLEANUP += $(FIRESERVE)
 
 ###############################################################################
 #
diff --git a/src/README.pixify b/src/README.pixify
deleted file mode 100644 (file)
index 9aef25d..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-This file documents the driver changes needed to support use as part
-of a PXE stack.
-
-PROPER WAY
-==========
-
-1. The probe() routine.
-
-There are three additional fields that need to be filled in the nic
-structure: ioaddr, irqno and irq.
-
-  ioaddr is the base I/O address and seems to be for information only;
-  no use will be made of this value other than displaying it on the
-  screen.
-
-  irqno must be the IRQ number for the NIC.  For PCI NICs this can
-  simply be copied from pci->irq.
-
-  irq is a function pointer, like poll and transmit.  It must point to
-  the driver's irq() function.
-
-2. The poll() routine.
-
-This must take an additional parameter: "int retrieve".  Calling
-poll() with retrieve!=0 should function exactly as before.  Calling
-poll() with retrieve==0 indicates that poll() should check for the
-presence of a packet to read, but must *not* read the packet.  The
-packet will be read by a subsequent call to poll() with retrieve!=0.
-
-The easiest way to implement this is to insert the line
-  if ( ! retrieve ) return 1;
-between the "is there a packet ready" and the "fetch packet" parts of
-the existing poll() routine.
-
-Care must be taken that a call to poll() with retrieve==0 does not
-clear the NIC's "packet ready" status indicator, otherwise the
-subsequent call to poll() with retrieve!=0 will fail because it will
-think that there is no packet to read.
-
-poll() should also acknowledge and clear the NIC's "packet received"
-interrupt.  It does not need to worry about enabling/disabling
-interrupts; this is taken care of by calls to the driver's irq()
-routine.
-
-Etherboot will forcibly regenerate an interrupt if a packet remains
-pending after all interrupts have been acknowledged.  You can
-therefore get away with having poll() just acknolwedge and clear all
-NIC interrupts, without particularly worrying about exactly when this
-should be done.
-
-3. The irq() routine.
-
-This is a new routine, with prototype
-  void DRIVER_irq ( struct nic *nic, irq_action_t action );
-"action" takes one of three possible values: ENABLE, DISABLE or FORCE.
-ENABLE and DISABLE mean to enable/disable the NIC's "packet received"
-interrupt.  FORCE means that the NIC should be forced to generate a
-fake "packet received" interrupt.
-
-If you are unable to implement FORCE, your NIC will not work when
-being driven via the UNDI interface under heavy network traffic
-conditions.  Since Etherboot's UNDI driver (make bin/undi.zpxe) is the
-only program known to use this interface, it probably doesn't really
-matter.
-
-
-QUICK AND DIRTY WAY
-===================
-
-It is possible to use the system timer interrupt (IRQ 0) rather than a
-genuine NIC interrupt.  Since there is a constant stream of timer
-interrupts, the net upshot is a whole load of spurious "NIC"
-interrupts that have no effect other than to cause unnecessary PXE API
-calls.  It's inefficient but it works.
-
-To achieve this, simply set nic->irqno=0 in probe() and point nic->irq
-to a dummy routine that does nothing.  Add the line
-  if ( ! retrieve ) return 1;
-at the beginning of poll(), to prevent the packet being read (and
-discarded) when poll() is called with retrieve==0;
-
-
-UNCONVERTED DRIVERS
-===================
-
-Drivers that have not yet been converted should continue to function
-when not used as part of a PXE stack, although there will be a
-harmless compile-time warning about assignment from an incompatible
-pointer type in the probe() function, since the prototype for the
-poll() function is missing the "int retrieve" parameter.
index ca8ba1b..1ca7734 100644 (file)
@@ -89,11 +89,6 @@ NON_AUTO_SRCS        += arch/i386/core/aout_loader.c
 NON_AUTO_SRCS  += arch/i386/core/freebsd_loader.c
 NON_AUTO_SRCS  += arch/i386/core/wince_loader.c
 
-# unnrv2b.S is used to generate a 16-bit as well as a 32-bit object.
-#
-OBJS_unnrv2b   = unnrv2b unnrv2b16
-CFLAGS_unnrv2b16 = -DCODE16
-
 # Include common x86 Makefile
 #
 MAKEDEPS       += arch/x86/Makefile
@@ -114,13 +109,6 @@ NON_AUTO_MEDIA     += fd0
        $(Q)dd if=$< bs=512 conv=sync of=/dev/fd0
        $(Q)sync
 
-# rule to create padded disk images
-NON_AUTO_MEDIA += pdsk
-%pdsk : %dsk
-       $(QM)$(ECHO) "  [DSKPAD] $@"
-       $(Q)cp $< $@
-       $(Q)$(PERL) ./util/dskpad.pl $@
-
 # Add NON_AUTO_MEDIA to the media list, so that they show up in the
 # output of "make"
 #
index 64b3dac..b185418 100644 (file)
@@ -27,6 +27,12 @@ MEDIA                += raw
 MEDIA          += com
 MEDIA          += exe
 
+# Padding rules
+#
+PAD_rom                = $(PADIMG) --blksize=512 --byte=0xff $@
+PAD_dsk                = $(PADIMG) --blksize=512 $@
+PAD_hd         = $(PADIMG) --blksize=512 $@
+
 # rule to make a non-emulation ISO boot image
 NON_AUTO_MEDIA += iso
 %iso:  %lkrn util/geniso
@@ -53,3 +59,9 @@ NON_AUTO_MEDIA        += usb
 %usb: $(BIN)/usbdisk.bin %hd
        $(QM)$(ECHO) "  [FINISH] $@"
        $(Q)cat $^ > $@
+
+# Padded floppy image (e.g. for iLO)
+NON_AUTO_MEDIA += pdsk
+%pdsk : %dsk
+       $(Q)cp $< $@
+       $(Q)$(PADIMG) --blksize=1474560 $@
diff --git a/src/arch/i386/core/etherboot.prefix.lds b/src/arch/i386/core/etherboot.prefix.lds
deleted file mode 100644 (file)
index 3550a2a..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-
-ENTRY(_prefix_start)
-SECTIONS {
-       /* Prefix */
-       .prefix : {
-               _verbatim_start = . ;
-               _prefix_start = . ;
-               *(.prefix)
-               . = ALIGN(16);
-               _prefix_end = . ;
-       } = 0x9090
-       _prefix_size = _prefix_end - _prefix_start;
-
-       .text.nocompress : {
-               *(.prefix.udata)
-       } = 0x9090
-
-       decompress_to = . ;
-       .prefix.zdata : {
-               _compressed = . ;
-               *(.prefix.zdata)
-               _compressed_end = . ;
-       }
-       _compressed_size = _compressed_end - _compressed;
-
-       . = ALIGN(16);
-       _verbatim_end = . ;
-
-
-       /* Size of the core of etherboot in memory */
-       _base_size = _end - _text;
-
-       /* _prefix_size is the length of the non-core etherboot prefix */
-       _prefix_size = _prefix_end - _prefix_start;
-
-       /* _verbatim_size is the actual amount that has to be copied to base memory */
-       _verbatim_size = _verbatim_end - _verbatim_start;
-
-       /* _image_size is the amount of base memory needed to run */
-       _image_size = _base_size +  _prefix_size;
-
-       /* Standard sizes rounded up to paragraphs */
-       _prefix_size_pgh   = (_prefix_size + 15) / 16;
-       _verbatim_size_pgh = (_verbatim_size + 15) / 16;
-       _image_size_pgh    = (_image_size + 15) / 16 ;
-       
-       /* Standard sizes in sectors */
-       _prefix_size_sct   = (_prefix_size + 511) / 512;
-       _verbatim_size_sct = (_verbatim_size + 511) / 512;
-       _image_size_sct    = (_image_size + 511) / 512;
-
-       /* Symbol offsets and sizes for the exe prefix */
-       _exe_hdr_size   = 32;
-       _exe_size       = _verbatim_size; /* Should this be - 32 to exclude the header? */
-       _exe_size_tail  = (_exe_size) % 512;
-       _exe_size_pages = ((_exe_size) + 511) / 512;
-       _exe_bss_size   = ((_image_size - _verbatim_size) + 15) / 16;
-       _exe_ss_offset  = (_stack_offset + _prefix_size - _exe_hdr_size + 15) / 16 ;
-
-       /* This is where we copy the compressed image before decompression.
-        * Prepare to decompress in place.  The end mark is about 8.25 bytes long,
-        * and the worst case symbol is about 16.5 bytes long.  Therefore
-        * We need to reserve at least 25 bytes of slack here.  
-        * Currently I reserve 2048 bytes of just slack to be safe :)
-        * 2048 bytes easily falls within the BSS (the defualt stack is 4096 bytes)
-        * so we really are decompressing in place.
-        * 
-        * Hmm. I missed a trick.  In the very worst case (no compression)
-        * the encoded data is 9/8 the size as it started out so to be completely
-        * safe I need to be 1/8 of the uncompressed code size past the end.
-        * This will still fit compfortably into our bss in any conceivable scenario.
-        */
-       _compressed_copy = _edata + _prefix_size  - _compressed_size +
-               /* The amount to overflow _edata */
-               MAX( ((_edata - _text + 7) / 8) , 2016 ) + 32; 
-       _assert = ASSERT( ( _compressed_copy - _prefix_size ) < _ebss , "Cannot decompress in place" ) ; 
-
-       decompress = DEFINED(decompress) ? decompress : 0;
-       /DISCARD/ : {
-               *(.comment)
-               *(.note)
-       }
-
-       /* Symbols used by the prefixes whose addresses are inconvinient 
-        * to compute, at runtime in the code.
-        */
-       image_basemem_size = DEFINED(image_basemem_size)? image_basemem_size : 65536;
-       image_basemem      = DEFINED(image_basemem)?     image_basemem : 65536;
-       _prefix_real_to_prot          = _real_to_prot         + _prefix_size ;
-       _prefix_prot_to_real          = _prot_to_real         + _prefix_size ;
-       _prefix_image_basemem_size    = image_basemem_size    + _prefix_size ;
-       _prefix_image_basemem         = image_basemem         + _prefix_size ;
-       _prefix_rm_in_call            = _rm_in_call           + _prefix_size ;
-       _prefix_in_call               = _in_call              + _prefix_size ;
-       _prefix_rom                   = rom                   + _prefix_size ;
-       _prefix_rm_etherboot_location = rm_etherboot_location + _prefix_size ;
-       _prefix_stack_end             = _stack_end            + _prefix_size ;
-}
diff --git a/src/arch/i386/core/prefixudata.lds b/src/arch/i386/core/prefixudata.lds
deleted file mode 100644 (file)
index 1c76128..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-
-SECTIONS {
-        .prefix.udata : {
-                     *(*)
-        }
-}
diff --git a/src/arch/i386/core/prefixzdata.lds b/src/arch/i386/core/prefixzdata.lds
deleted file mode 100644 (file)
index bf6ea97..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-
-SECTIONS {
-        .prefix.zdata : {
-                     *(*)
-        }
-}
diff --git a/src/arch/i386/core/realmode.c b/src/arch/i386/core/realmode.c
deleted file mode 100644 (file)
index 9a77bd8..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Real-mode interface: C portions.
- *
- * Initial version by Michael Brown <mbrown@fensystems.co.uk>, January 2004.
- */
-
-#include "realmode.h"
-
-/*
- * Copy data to/from base memory.
- *
- */
-
-#ifdef KEEP_IT_REAL
-
-void memcpy_to_real ( segoff_t dest, void *src, size_t n ) {
-
-}
-
-void memcpy_from_real ( void *dest, segoff_t src, size_t n ) {
-
-}
-
-#endif /* KEEP_IT_REAL */
diff --git a/src/arch/i386/core/start16.lds b/src/arch/i386/core/start16.lds
deleted file mode 100644 (file)
index 544fc78..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/* When linking with an uncompressed image, these symbols are not
- * defined so we provide them here.
- */
-
-__decompressor_uncompressed = 0 ;
-__decompressor__start = 0 ;
-
-INCLUDE arch/i386/core/start16z.lds
diff --git a/src/arch/i386/core/start16z.lds b/src/arch/i386/core/start16z.lds
deleted file mode 100644 (file)
index 711bcf7..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-
-/* Linker-generated symbols are prefixed with a double underscore.
- * Decompressor symbols are prefixed with __decompressor_.  All other
- * symbols are the same as in the original object file, i.e. the
- * runtime addresses.
- */
-
-ENTRY(_start16)
-
-SECTIONS {
-       .text : {
-               *(.text)
-       }
-       .payload : {
-               __payload_start = .;
-               *(.data)
-               __payload_end = .;
-       }
-
-       /* _payload_size is the size of the binary image appended to
-        * start16, in bytes.
-        */
-       __payload_size = __payload_end - __payload_start ;
-
-       /* _size is the size of the runtime image
-        * (start32 + the C code), in bytes.
-        */
-       __size = _end - _start ;
-
-       /* _decompressor_size is the size of the decompressor, in
-        * bytes.  For a non-compressed image, start16.lds sets
-        * _decompressor_uncompressed = _decompressor__start = 0.
-        */
-       __decompressor_size = __decompressor_uncompressed - __decompressor__start ;
-
-       /* image__size is the total size of the image, after
-        * decompression and including the decompressor if applicable.
-        * It is therefore the amount of memory that start16's payload
-        * needs in order to execute, in bytes.
-        */
-       __image_size = __size + __decompressor_size ;
-
-       /* Amount to add to runtime symbols to obtain the offset of
-        * that symbol within the image.
-        */
-       __offset_adjust = __decompressor_size - _start ;
-
-       /* Calculations for the stack
-        */
-       __stack_size = _estack - _stack ;
-       __offset_stack = _stack + __offset_adjust ;
-
-       /* Some symbols will be larger than 16 bits but guaranteed to
-        * be multiples of 16.  We calculate them in paragraphs and
-        * export these symbols which can be used in 16-bit code
-        * without risk of overflow.
-        */
-       __image_size_pgh = ( __image_size / 16 );
-       __start_pgh = ( _start / 16 );
-       __decompressor_size_pgh = ( __decompressor_size / 16 );
-       __offset_stack_pgh = ( __offset_stack / 16 );
-}
-
index 4ba3fb1..decb083 100644 (file)
@@ -489,6 +489,18 @@ get_mangled_e820:
        ret
        .size get_mangled_e820, . - get_mangled_e820
 
+/****************************************************************************
+ * Set/clear CF on the stack as appropriate, assumes stack is as it should
+ * be immediately before IRET
+ ****************************************************************************
+ */
+patch_cf:
+       pushw   %bp
+       movw    %sp, %bp
+       setc    8(%bp)  /* Set/reset CF; clears PF, AF, ZF, SF */
+       popw    %bp
+       ret
+
 /****************************************************************************
  * INT 15,e820 handler
  ****************************************************************************
@@ -500,7 +512,8 @@ int15_e820:
        popw    %ds
        call    get_mangled_e820
        popw    %ds
-       lret    $2
+       call    patch_cf
+       iret
        .size int15_e820, . - int15_e820
        
 /****************************************************************************
@@ -512,7 +525,7 @@ int15_e801:
        /* Call previous handler */
        pushfw
        lcall   *%cs:int15_vector
-       pushfw
+       call    patch_cf
        /* Edit result */
        pushw   %ds
        pushw   %cs:rm_ds
@@ -524,9 +537,7 @@ int15_e801:
        xchgw   %ax, %cx
        xchgw   %bx, %dx
        popw    %ds
-       /* Restore flags returned by previous handler and return */
-       popfw
-       lret    $2
+       iret
        .size int15_e801, . - int15_e801
        
 /****************************************************************************
@@ -538,16 +549,14 @@ int15_88:
        /* Call previous handler */
        pushfw
        lcall   *%cs:int15_vector
-       pushfw
+       call    patch_cf
        /* Edit result */
        pushw   %ds
        pushw   %cs:rm_ds
        popw    %ds
        call    patch_1m
        popw    %ds
-       /* Restore flags returned by previous handler and return */
-       popfw
-       lret    $2
+       iret
        .size int15_88, . - int15_88
                
 /****************************************************************************
index e171edf..552bf41 100644 (file)
@@ -63,6 +63,8 @@ void fake_e820 ( void ) {
                              "cmpl $0x534d4150, %%edx\n\t"
                              "jne 99f\n\t"
                              "pushaw\n\t"
+                             "movw %%sp, %%bp\n\t"
+                             "andb $~0x01, 22(%%bp)\n\t" /* Clear return CF */
                              "leaw e820map(%%bx), %%si\n\t"
                              "cs rep movsb\n\t"
                              "popaw\n\t"
@@ -73,8 +75,7 @@ void fake_e820 ( void ) {
                              "xorl %%ebx,%%ebx\n\t"
                              "\n1:\n\t"
                              "popfw\n\t"
-                             "clc\n\t"
-                             "lret $2\n\t"
+                             "iret\n\t"
                              "\n99:\n\t"
                              "popfw\n\t"
                              "ljmp *%%cs:real_int15_vector\n\t" )
index 52bb10f..1edf6af 100644 (file)
@@ -360,6 +360,13 @@ static int multiboot_load_raw ( struct image *image,
        userptr_t buffer;
        int rc;
 
+       /* Sanity check */
+       if ( ! ( hdr->mb.flags & MB_FLAG_RAW ) ) {
+               DBGC ( image, "MULTIBOOT %p is not flagged as a raw image\n",
+                      image );
+               return -EINVAL;
+       }
+
        /* Verify and prepare segment */
        offset = ( hdr->offset - hdr->mb.header_addr + hdr->mb.load_addr );
        filesz = ( hdr->mb.load_end_addr ?
@@ -432,14 +439,14 @@ static int multiboot_load ( struct image *image ) {
                return -ENOTSUP;
        }
 
-       /* Load the actual image */
-       if ( hdr.mb.flags & MB_FLAG_RAW ) {
-               if ( ( rc = multiboot_load_raw ( image, &hdr ) ) != 0 )
-                       return rc;
-       } else {
-               if ( ( rc = multiboot_load_elf ( image ) ) != 0 )
-                       return rc;
-       }
+       /* There is technically a bit MB_FLAG_RAW to indicate whether
+        * this is an ELF or a raw image.  In practice, grub will use
+        * the ELF header if present, and Solaris relies on this
+        * behaviour.
+        */
+       if ( ( ( rc = multiboot_load_elf ( image ) ) != 0 ) &&
+            ( ( rc = multiboot_load_raw ( image, &hdr ) ) != 0 ) )
+               return rc;
 
        return 0;
 }
diff --git a/src/arch/i386/include/callbacks_arch.h b/src/arch/i386/include/callbacks_arch.h
deleted file mode 100644 (file)
index f9cba48..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/* Callout/callback interface for Etherboot
- *
- * This file provides the mechanisms for making calls from Etherboot
- * to external programs and vice-versa.
- *
- * Initial version by Michael Brown <mbrown@fensystems.co.uk>, January 2004.
- *
- * $Id$
- */
-
-#ifndef CALLBACKS_ARCH_H
-#define CALLBACKS_ARCH_H
-
-/* Skip the definitions that won't make sense to the assembler */
-#ifndef ASSEMBLY
-
-/* Struct to hold general-purpose register values.  PUSHAL and POPAL
- * can work directly with this structure; do not change the order of
- * registers.
- */
-typedef struct {
-       union {
-               uint16_t di;
-               uint32_t edi;
-       };
-       union {
-               uint16_t si;
-               uint32_t esi;
-       };
-       union {
-               uint16_t bp;
-               uint32_t ebp;
-       };
-       union {
-               uint16_t sp;
-               uint32_t esp;
-       };
-       union {
-               struct {
-                       uint8_t bl;
-                       uint8_t bh;
-               } PACKED;
-               uint16_t bx;
-               uint32_t ebx;
-       };
-       union {
-               struct {
-                       uint8_t dl;
-                       uint8_t dh;
-               } PACKED;
-               uint16_t dx;
-               uint32_t edx;
-       };
-       union {
-               struct {
-                       uint8_t cl;
-                       uint8_t ch;
-               } PACKED;
-               uint16_t cx;
-               uint32_t ecx;
-       };
-       union {
-               struct {
-                       uint8_t al;
-                       uint8_t ah;
-               } PACKED;
-               uint16_t ax;
-               uint32_t eax;
-       };
-} regs_t;
-
-/* Struct to hold segment register values.  Don't change the order;
- * many bits of assembly code rely on it.
- */
-typedef struct {
-       uint16_t cs;
-       uint16_t ss;
-       uint16_t ds;
-       uint16_t es;
-       uint16_t fs;
-       uint16_t gs;
-} PACKED seg_regs_t;
-
-/* Struct for a GDT descriptor */
-typedef struct {
-               uint16_t limit;
-               uint32_t address;
-               uint16_t padding;
-} PACKED gdt_descriptor_t;
-
-/* Struct for a GDT entry.  Use GDT_SEGMENT() to fill it in.
- */
-typedef struct {
-       uint16_t limit_0_15;
-       uint16_t base_0_15;
-       uint8_t base_16_23;
-       uint8_t accessed__type__sflag__dpl__present;
-       uint8_t limit_16_19__avl__size__granularity;
-       uint8_t base_24_31;
-} PACKED gdt_segment_t;
-
-#define GDT_SEGMENT(base,limit,type,sflag,dpl,avl,size,granularity) \
-       ( (gdt_segment_t) { \
-               ( (limit) & 0xffff ), \
-               ( (base) & 0xffff ), \
-               ( ( (base) >> 16 ) & 0xff ), \
-               ( ( 1 << 0 ) | ( (type) << 1 ) | \
-                 ( (sflag) << 4 ) | ( (dpl) << 5 ) | ( 1 << 7 ) ), \
-               ( ( (limit) >> 16 ) | \
-                 ( (avl) << 4 ) | ( (size) << 5 ) | ( (granularity) << 7 ) ),\
-               ( (base) >> 24 ) \
-       } )
-#define GDT_SEGMENT_BASE(gdt_segment) \
-       ( (gdt_segment)->base_0_15 | \
-         (gdt_segment)->base_16_23 << 16 | \
-         (gdt_segment)->base_24_31 << 24 )
-#define GDT_SEGMENT_LIMIT(gdt_segment) \
-       ( (gdt_segment)->limit_0_15 | \
-         ( ( (gdt_segment)->limit_16_19__avl__size__granularity \
-             & 0xf ) << 16 ) )
-#define GDT_SEGMENT_GRANULARITY(gdt_segment) \
-       ( ( (gdt_segment)->limit_16_19__avl__size__granularity \
-           & 0x80 ) >> 7 )
-#define GDT_SEGMENT_TYPE(gdt_segment) \
-       ( ( (gdt_segment)->accessed__type__sflag__dpl__present & 0x0e ) >> 1 )
-#define GDT_SEGMENT_SIZE(gdt_segment) \
-       ( ( (gdt_segment)->limit_16_19__avl__size__granularity \
-           & 0x60 ) >> 5 )
-
-#define GDT_TYPE_DATA                  (0x0)
-#define GDT_TYPE_STACK                 (0x2)
-#define GDT_TYPE_WRITEABLE             (0x1)
-#define GDT_TYPE_CODE                  (0x6)
-#define GDT_TYPE_EXEC_ONLY_CODE                (0x4)
-#define GDT_TYPE_CONFORMING            (0x1)
-#define GDT_SFLAG_SYSTEM               (0)
-#define GDT_SFLAG_NORMAL               (1)
-#define GDT_AVL_NORMAL                 (0)
-#define GDT_SIZE_16BIT                 (0x0)
-#define GDT_SIZE_32BIT                 (0x2)
-#define GDT_SIZE_64BIT                 (0x1)
-#define GDT_SIZE_UNKNOWN               (0x3)
-#define GDT_GRANULARITY_SMALL          (0)
-#define GDT_GRANULARITY_LARGE          (1)
-#define GDT_SEGMENT_NORMAL(base,limit,type,size,granularity) \
-       GDT_SEGMENT ( base, limit, type, \
-                     GDT_SFLAG_NORMAL, 0, GDT_AVL_NORMAL, \
-                     size, granularity )
-
-/* Protected mode code segment */
-#define GDT_SEGMENT_PMCS(base) GDT_SEGMENT_NORMAL ( \
-       base, 0xfffff, GDT_TYPE_CODE | GDT_TYPE_CONFORMING, \
-       GDT_SIZE_32BIT, GDT_GRANULARITY_LARGE )
-#define GDT_SEGMENT_PMCS_PHYS GDT_SEGMENT_PMCS(0)
-/* Protected mode data segment */
-#define GDT_SEGMENT_PMDS(base) GDT_SEGMENT_NORMAL ( \
-       base, 0xfffff, GDT_TYPE_DATA | GDT_TYPE_WRITEABLE, \
-       GDT_SIZE_32BIT, GDT_GRANULARITY_LARGE )
-#define GDT_SEGMENT_PMDS_PHYS GDT_SEGMENT_PMDS(0)
-/* Real mode code segment */
-/* Not sure if there's any reason to use GDT_TYPE_EXEC_ONLY_CODE
- * instead of just GDT_TYPE_CODE, but that's what our old GDT did and
- * it worked, so I'm not changing it.
- */
-#define GDT_SEGMENT_RMCS(base) GDT_SEGMENT_NORMAL ( \
-       base, 0xffff, GDT_TYPE_EXEC_ONLY_CODE | GDT_TYPE_CONFORMING, \
-       GDT_SIZE_16BIT, GDT_GRANULARITY_SMALL )
-/* Real mode data segment */
-#define GDT_SEGMENT_RMDS(base) GDT_SEGMENT_NORMAL ( \
-       base, 0xffff, GDT_TYPE_DATA | GDT_TYPE_WRITEABLE, \
-       GDT_SIZE_16BIT, GDT_GRANULARITY_SMALL )
-/* Long mode code segment */
-#define GDT_SEGMENT_LMCS(base) GDT_SEGMENT_NORMAL ( \
-       base, 0xfffff, GDT_TYPE_CODE | GDT_TYPE_CONFORMING, \
-       GDT_SIZE_64BIT, GDT_GRANULARITY_LARGE )
-#define GDT_SEGMENT_LMCS_PHYS GDT_SEGMENT_LMCS(0)
-/* Long mode data segment */
-/* AFIACT, GDT_SIZE_64BIT applies only to code segments */
-#define GDT_SEGMENT_LMDS(base) GDT_SEGMENT_NORMAL ( \
-       base, 0xfffff, GDT_TYPE_DATA | GDT_TYPE_WRITEABLE, \
-       GDT_SIZE_32BIT, GDT_GRANULARITY_LARGE )
-#define GDT_SEGMENT_LMDS_PHYS GDT_SEGMENT_LMDS(0)
-
-/* Template for creating GDT structures (including segment register
- * lists), suitable for passing as parameters to external_call().
- */
-#define GDT_STRUCT_t(num_segments) \
-       struct { \
-               gdt_descriptor_t descriptor; \
-               gdt_segment_t segments[num_segments]; \
-       } PACKED
-/* And utility function for filling it in */
-#define GDT_ADJUST(structure) { \
-       (structure)->descriptor.address = \
-               virt_to_phys(&((structure)->descriptor.limit)); \
-       (structure)->descriptor.limit = \
-               sizeof((structure)->segments) + 8 - 1; \
-       (structure)->descriptor.padding = 0; \
-}
-
-/* Data passed in to in_call() by assembly wrapper.
- */
-typedef struct {
-       regs_t          regs;
-       seg_regs_t      seg_regs;
-       gdt_descriptor_t gdt_desc;
-       uint32_t        flags;
-       struct {
-               uint32_t offset;
-               uint32_t segment;
-       } ret_addr;
-} PACKED i386_pm_in_call_data_t;
-
-typedef struct {
-       seg_regs_t      seg_regs;
-       union {
-               uint16_t        pad;
-               uint16_t        prefix_sp;
-       };
-       uint16_t        flags;
-       struct {
-               uint16_t offset;
-               uint16_t segment;
-       } ret_addr;
-       uint32_t orig_opcode;
-} PACKED i386_rm_in_call_data_t;
-
-typedef struct {
-       i386_pm_in_call_data_t *pm;
-       i386_rm_in_call_data_t *rm;
-} i386_in_call_data_t;
-#define in_call_data_t i386_in_call_data_t
-
-/* Function prototypes
- */
-extern int install_rm_callback_interface ( void *address, size_t available );
-
-#endif /* ASSEMBLY */
-
-#define RM_IN_CALL     (0)
-#define RM_IN_CALL_FAR (2)
-
-#endif /* CALLBACKS_ARCH_H */
index 22ef418..0e8c8e2 100644 (file)
@@ -199,9 +199,12 @@ pxe_int_1a:
        shll    $4, %edx
        addl    $pxenv, %edx
        movw    $0x564e, %ax
+       pushw   %bp
+       movw    %sp, %bp
+       andb    $~0x01, 8(%bp)  /* Clear CF on return */
+       popw    %bp
        popfw
-       clc
-       lret    $2
+       iret
 1:     /* INT 1A,other - pass through */
        popfw
        ljmp    *%cs:pxe_int_1a_vector
index 82b1da1..c6ae12c 100644 (file)
@@ -1,8 +1,11 @@
 #define PXENV_UNDI_SHUTDOWN            0x0005
 #define        PXENV_UNDI_GET_NIC_TYPE         0x0012
+#define PXENV_UNDI_GET_IFACE_INFO      0x0013
 #define        PXENV_STOP_UNDI                 0x0015
 #define PXENV_UNLOAD_STACK             0x0070
 
+#define PXE_HACK_EB54                  0x0001
+
        .text
        .arch i386
        .org 0
@@ -11,6 +14,8 @@
 #include <undi.h>
 
 #define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
+#define EB_MAGIC_1 ( 'E' + ( 't' << 8 ) + ( 'h' << 16 ) + ( 'e' << 24 ) )
+#define EB_MAGIC_2 ( 'r' + ( 'b' << 8 ) + ( 'o' << 16 ) + ( 'o' << 24 ) )
 
 /*****************************************************************************
  * Entry point:        set operating context, print welcome message
@@ -307,8 +312,6 @@ pci_physical_device:
        movw    $10f, %si
        call    print_message
        call    print_pci_busdevfn
-       movb    $0x0a, %al
-       call    print_character
        jmp     99f
        .section ".prefix.data", "aw", @progbits
 10:    .asciz  "         UNDI device is PCI "
@@ -319,11 +322,46 @@ no_physical_device:
        movw    $10f, %si
        call    print_message
        .section ".prefix.data", "aw", @progbits
-10:    .asciz  "         Unable to determine UNDI physical device\n"
+10:    .asciz  "         Unable to determine UNDI physical device"
        .previous
 
 99:
 
+/*****************************************************************************
+ * Determine interface type
+ *****************************************************************************
+ */
+get_iface_type:
+       /* Issue PXENV_UNDI_GET_IFACE_INFO */
+       movw    $PXENV_UNDI_GET_IFACE_INFO, %bx
+       call    pxe_call
+       jnc     1f
+       call    print_pxe_error
+       jmp     99f
+1:     /* Print interface type */
+       movw    $10f, %si
+       call    print_message
+       leaw    ( pxe_parameter_structure + 0x02 ), %si
+       call    print_message
+       .section ".prefix.data", "aw", @progbits
+10:    .asciz  ", type "
+       .previous
+       /* Check for "Etherboot" interface type */
+       cmpl    $EB_MAGIC_1, ( pxe_parameter_structure + 0x02 )
+       jne     99f
+       cmpl    $EB_MAGIC_2, ( pxe_parameter_structure + 0x06 )
+       jne     99f
+       movw    $10f, %si
+       call    print_message
+       .section ".prefix.data", "aw", @progbits
+10:    .asciz  " (workaround enabled)"
+       .previous
+       /* Flag Etherboot workarounds as required */
+       orw     $PXE_HACK_EB54, pxe_hacks
+
+99:    movb    $0x0a, %al
+       call    print_character
+
 /*****************************************************************************
  * Leave NIC in a safe state
  *****************************************************************************
@@ -337,6 +375,14 @@ shutdown_nic:
        call    print_pxe_error
 1:
 unload_base_code:
+       /* Etherboot treats PXENV_UNLOAD_STACK as PXENV_STOP_UNDI, so
+        * we must not issue this call if the underlying stack is
+        * Etherboot and we were not intending to issue a PXENV_STOP_UNDI.
+        */
+#ifdef PXELOADER_KEEP_UNDI
+       testw   $PXE_HACK_EB54, pxe_hacks
+       jnz     99f
+#endif /* PXELOADER_KEEP_UNDI */
        /* Issue PXENV_UNLOAD_STACK */
        movw    $PXENV_UNLOAD_STACK, %bx
        call    pxe_call
@@ -549,7 +595,9 @@ pxe_call:
        testw   %ax, %ax
        jz      1f
        stc
-1:     /* Restore registers and return */
+1:     /* Clear direction flag, for the sake of sanity */
+       cld
+       /* Restore registers and return */
        popw    %es
        popw    %di
        ret
@@ -593,7 +641,7 @@ print_pxe_error:
 pxe_esp:               .long 0
 pxe_ss:                        .word 0
 
-pxe_parameter_structure: .fill 20
+pxe_parameter_structure: .fill 64
 
 undi_code_segoff:
 undi_code_size:                .word 0
@@ -603,6 +651,8 @@ undi_data_segoff:
 undi_data_size:                .word 0
 undi_data_segment:     .word 0
 
+pxe_hacks:             .word 0
+
 /* The following fields are part of a struct undi_device */
 
 undi_device:
diff --git a/src/arch/i386/prefix/unnrv2b16.S b/src/arch/i386/prefix/unnrv2b16.S
new file mode 100644 (file)
index 0000000..da0e6ae
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * 16-bit version of the decompressor
+ *
+ */
+
+#define CODE16
+#include "unnrv2b.S"
index 45df7f2..c808395 100644 (file)
@@ -344,12 +344,10 @@ static void gdbstub_state_cksum2 ( struct gdbstub *stub, char ch ) {
 static void gdbstub_state_wait_ack ( struct gdbstub *stub, char ch ) {
        if ( ch == '+' ) {
                stub->parse = gdbstub_state_new;
-       } else if ( ch == '-' ) {
-               gdbstub_tx_packet ( stub ); /* retransmit */
-       } else if ( ch == '$' ) {
-               /* GDB is reconnecting, drop our packet and listen to GDB */
-               stub->trans->send ( "-", 1 );
-               stub->parse = gdbstub_state_new;
+       } else {
+               /* This retransmit is very aggressive but necessary to keep
+                * in sync with GDB. */
+               gdbstub_tx_packet ( stub );
        }
 }
 
index cb2b0f5..ca650ea 100644 (file)
@@ -42,11 +42,14 @@ typedef Elf32_Off   Elf_Off;
  *
  * @v image            ELF file
  * @v phdr             ELF program header
+ * @v ehdr             ELF executable header
  * @ret rc             Return status code
  */
-static int elf_load_segment ( struct image *image, Elf_Phdr *phdr ) {
+static int elf_load_segment ( struct image *image, Elf_Phdr *phdr,
+                             Elf_Ehdr *ehdr ) {
        physaddr_t dest;
        userptr_t buffer;
+       unsigned long e_offset;
        int rc;
 
        /* Do nothing for non-PT_LOAD segments */
@@ -55,7 +58,7 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr ) {
 
        /* Check segment lies within image */
        if ( ( phdr->p_offset + phdr->p_filesz ) > image->len ) {
-               DBG ( "ELF segment outside ELF file\n" );
+               DBGC ( image, "ELF %p segment outside image\n", image );
                return -ENOEXEC;
        }
 
@@ -67,26 +70,43 @@ static int elf_load_segment ( struct image *image, Elf_Phdr *phdr ) {
        if ( ! dest )
                dest = phdr->p_vaddr;
        if ( ! dest ) {
-               DBG ( "ELF segment loads to physical address 0\n" );
+               DBGC ( image, "ELF %p segment loads to physical address 0\n",
+                      image );
                return -ENOEXEC;
        }
        buffer = phys_to_user ( dest );
 
-       DBG ( "ELF loading segment [%x,%x) to [%x,%x,%x)\n",
-             phdr->p_offset, ( phdr->p_offset + phdr->p_filesz ),
-             phdr->p_paddr, ( phdr->p_paddr + phdr->p_filesz ),
-             ( phdr->p_paddr + phdr->p_memsz ) );
+       DBGC ( image, "ELF %p loading segment [%x,%x) to [%x,%x,%x)\n", image,
+              phdr->p_offset, ( phdr->p_offset + phdr->p_filesz ),
+              phdr->p_paddr, ( phdr->p_paddr + phdr->p_filesz ),
+              ( phdr->p_paddr + phdr->p_memsz ) );
 
        /* Verify and prepare segment */
        if ( ( rc = prep_segment ( buffer, phdr->p_filesz,
                                   phdr->p_memsz ) ) != 0 ) {
-               DBG ( "ELF could not prepare segment: %s\n", strerror ( rc ) );
+               DBGC ( image, "ELF %p could not prepare segment: %s\n",
+                      image, strerror ( rc ) );
                return rc;
        }
 
        /* Copy image to segment */
        memcpy_user ( buffer, 0, image->data, phdr->p_offset, phdr->p_filesz );
 
+       /* Set execution address, if it lies within this segment */
+       if ( ( e_offset = ( ehdr->e_entry - dest ) ) < phdr->p_filesz ) {
+               image->priv.phys = ehdr->e_entry;
+               DBGC ( image, "ELF %p found physical entry point at %lx\n",
+                      image, image->priv.phys );
+       } else if ( ( e_offset = ( ehdr->e_entry - phdr->p_vaddr ) )
+                   < phdr->p_filesz ) {
+               if ( ! image->priv.phys ) {
+                       image->priv.phys = ( dest + e_offset );
+                       DBGC ( image, "ELF %p found virtual entry point at %lx"
+                              " (virt %lx)\n", image, image->priv.phys,
+                              ( ( unsigned long ) ehdr->e_entry ) );
+               }
+       }
+
        return 0;
 }
 
@@ -109,25 +129,32 @@ int elf_load ( struct image *image ) {
        /* Read ELF header */
        copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
        if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) {
-               DBG ( "Invalid ELF signature\n" );
+               DBGC ( image, "ELF %p has invalid signature\n", image );
                return -ENOEXEC;
        }
 
+       /* Invalidate execution address */
+       image->priv.phys = 0;
+
        /* Read ELF program headers */
        for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ;
              phoff += ehdr.e_phentsize, phnum-- ) {
                if ( phoff > image->len ) {
-                       DBG ( "ELF program header %d outside ELF image\n",
-                             phnum );
+                       DBGC ( image, "ELF %p program header %d outside "
+                              "image\n", image, phnum );
                        return -ENOEXEC;
                }
                copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) );
-               if ( ( rc = elf_load_segment ( image, &phdr ) ) != 0 )
+               if ( ( rc = elf_load_segment ( image, &phdr, &ehdr ) ) != 0 )
                        return rc;
        }
 
-       /* Record execution entry point in image private data field */
-       image->priv.phys = ehdr.e_entry;
+       /* Check for a valid execution address */
+       if ( ! image->priv.phys ) {
+               DBGC ( image, "ELF %p entry point %lx outside image\n",
+                      image, ( ( unsigned long ) ehdr.e_entry ) );
+               return -ENOEXEC;
+       }
 
        return 0;
 }
index be3ce46..d23c167 100644 (file)
  *
  */
 
+/* Force visibility of all symbols to "hidden", i.e. inform gcc that
+ * all symbol references resolve strictly within our final binary.
+ * This avoids unnecessary PLT/GOT entries on x86_64.
+ *
+ * This is a stronger claim than specifying "-fvisibility=hidden",
+ * since it also affects symbols marked with "extern".
+ */
+#ifndef ASSEMBLY
+#if __GNUC__ >= 4
+#pragma GCC visibility push(hidden)
+#endif
+#endif /* ASSEMBLY */
+
+/**
+ * @defgroup symmacros Macros to provide or require explicit symbols
+ * @{
+ */
+
+/** Provide a symbol within this object file */
+#ifdef ASSEMBLY
+#define PROVIDE_SYMBOL( _sym )                         \
+       .globl  _sym ;                                  \
+       .comm   _sym, 0
+#else /* ASSEMBLY */
+#define PROVIDE_SYMBOL( _sym )                         \
+       char _sym[0]
+#endif /* ASSEMBLY */
+
+/** Require a symbol within this object file */
+#ifdef ASSEMBLY
+#define REQUIRE_SYMBOL( _sym )                         \
+       .equ    __need_ # _sym, _sym
+#else /* ASSEMBLY */
+#define REQUIRE_SYMBOL( _sym )                         \
+       __asm__ ( ".equ\t__need_" #_sym ", " #_sym )
+#endif /* ASSEMBLY */
+
+/** @} */
+
+/**
+ * @defgroup objmacros Macros to provide or require explicit objects
+ * @{
+ */
+
 /* Not quite sure why cpp requires two levels of macro call in order
  * to actually expand OBJECT...
  */
 #define _H1( x, y ) x ## y
 #undef _H2
 #define _H2( x, y ) _H1 ( x, y )
-#define PREFIX_OBJECT(prefix) _H2 ( prefix, OBJECT )
-#define OBJECT_SYMBOL PREFIX_OBJECT(obj_)
-#undef _STR
-#define _STR(s) #s
-#undef _XSTR
-#define _XSTR(s) _STR(s)
-#define OBJECT_SYMBOL_STR _XSTR ( OBJECT_SYMBOL )
-
-#ifdef ASSEMBLY
+#define PREFIX_OBJECT( _prefix ) _H2 ( _prefix, OBJECT )
+#define OBJECT_SYMBOL PREFIX_OBJECT ( obj_ )
 
-       .globl  OBJECT_SYMBOL
-       .equ    OBJECT_SYMBOL, 0
+/** Always provide the symbol for the current object (defined by -DOBJECT) */
+PROVIDE_SYMBOL ( OBJECT_SYMBOL );
 
-#else /* ASSEMBLY */
+/** Explicitly require another object */
+#define REQUIRE_OBJECT( _obj ) REQUIRE_SYMBOL ( obj_ ## _obj )
 
-__asm__ ( ".globl\t" OBJECT_SYMBOL_STR );
-__asm__ ( ".equ\t" OBJECT_SYMBOL_STR ", 0" );
+/** @} */
 
-/**
- * Drag in an object by object name.
- *
- * Macro to allow objects to explicitly drag in other objects by
- * object name.  Used by config.c.
- *
- */
-#define REQUIRE_OBJECT(object) \
-       __asm__ ( ".equ\tneed_" #object ", obj_" #object );
+/** Select file identifier for errno.h (if used) */
+#define ERRFILE PREFIX_OBJECT ( ERRFILE_ )
 
-/* Force visibility of all symbols to "hidden", i.e. inform gcc that
- * all symbol references resolve strictly within our final binary.
- * This avoids unnecessary PLT/GOT entries on x86_64.
- *
- * This is a stronger claim than specifying "-fvisibility=hidden",
- * since it also affects symbols marked with "extern".
+/** @defgroup dbg Debugging infrastructure
+ * @{
  */
-#if __GNUC__ >= 4
-#pragma GCC visibility push(hidden)
-#endif
+#ifndef ASSEMBLY
 
 /** @def DBG
  *
@@ -117,12 +141,7 @@ __asm__ ( ".equ\t" OBJECT_SYMBOL_STR ", 0" );
  * DEBUG_LEVEL will be inserted into the object file.
  *
  */
-#define DEBUG_SYMBOL PREFIX_OBJECT(debug_)
-
-#if DEBUG_SYMBOL
-#define DEBUG_SYMBOL_STR _XSTR ( DEBUG_SYMBOL )
-__asm__ ( ".equ\tDBGLVL, " DEBUG_SYMBOL_STR );
-#endif
+#define DEBUG_SYMBOL PREFIX_OBJECT ( debug_ )
 
 /** printf() for debugging
  *
@@ -305,8 +324,13 @@ int __debug_disable;
 #define NDEBUG
 #endif
 
-/** Select file identifier for errno.h (if used) */
-#define ERRFILE PREFIX_OBJECT ( ERRFILE_ )
+#endif /* ASSEMBLY */
+/** @} */
+
+/** @defgroup attrs Miscellaneous attributes
+ * @{
+ */
+#ifndef ASSEMBLY
 
 /** Declare a data structure as packed. */
 #define PACKED __attribute__ (( packed ))
@@ -374,11 +398,14 @@ int __debug_disable;
  */
 #define __shared __asm__ ( "_shared_bss" ) __aligned
 
+#endif /* ASSEMBLY */
+/** @} */
+
 /**
  * Optimisation barrier
  */
+#ifndef ASSEMBLY
 #define barrier() __asm__ __volatile__ ( "" : : : "memory" )
-
 #endif /* ASSEMBLY */
 
 #include <bits/compiler.h>
index 2b0fcbd..a294236 100644 (file)
@@ -113,6 +113,25 @@ struct smbios_system_information {
 /** SMBIOS system information structure type */
 #define SMBIOS_TYPE_SYSTEM_INFORMATION 1
 
+/** SMBIOS enclosure information structure */
+struct smbios_enclosure_information {
+       /** SMBIOS structure header */
+       struct smbios_header header;
+       /** Manufacturer string */
+       uint8_t manufacturer;
+       /** Type string */
+       uint8_t type;
+       /** Version string */
+       uint8_t version;
+       /** Serial number string */
+       uint8_t serial;
+       /** Asset tag */
+       uint8_t asset_tag;
+} __attribute__ (( packed ));
+
+/** SMBIOS enclosure information structure type */
+#define SMBIOS_TYPE_ENCLOSURE_INFORMATION 3
+
 /**
  * SMBIOS entry point descriptor
  *
index 61c2d91..ec594c5 100644 (file)
@@ -198,4 +198,12 @@ struct setting smbios_named_settings[] __setting = {
                                           serial ),
                .type = &setting_type_string,
        },
+       {
+               .name = "asset",
+               .description = "Asset tag",
+               .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_ENCLOSURE_INFORMATION,
+                                          struct smbios_enclosure_information,
+                                          asset_tag ),
+               .type = &setting_type_string,
+       },
 };
index 1f2d373..2f3e680 100644 (file)
@@ -155,6 +155,8 @@ int dhcppkt_store ( struct dhcp_packet *dhcppkt, unsigned int tag,
                memset ( field_data, 0, field->len );
                memcpy ( dhcp_packet_field ( dhcppkt->dhcphdr, field ),
                         data, len );
+               /* Erase any equivalent option from the options block */
+               dhcpopt_store ( &dhcppkt->options, tag, NULL, 0 );
                return 0;
        }
 
@@ -181,14 +183,16 @@ int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
                    void *data, size_t len ) {
        struct dhcp_packet_field *field;
        void *field_data;
-       size_t field_len;
+       size_t field_len = 0;
        
-       /* If this is a special field, return it */
+       /* Identify special field, if any */
        if ( ( field = find_dhcp_packet_field ( tag ) ) != NULL ) {
                field_data = dhcp_packet_field ( dhcppkt->dhcphdr, field );
                field_len = field->used_len ( field_data, field->len );
-               if ( ! field_len )
-                       return -ENOENT;
+       }
+
+       /* Return special field, if it exists and is populated */
+       if ( field_len ) {
                if ( len > field_len )
                        len = field_len;
                memcpy ( data, field_data, len );
diff --git a/src/util/dskpad.pl b/src/util/dskpad.pl
deleted file mode 100755 (executable)
index 3ae325e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use warnings;
-
-use constant FLOPPYSIZE => 1440 * 1024;
-
-while ( my $filename = shift ) {
-  die "$filename is not a file\n" unless -f $filename;
-  die "$filename is too large\n" unless ( -s $filename <= FLOPPYSIZE );
-  truncate $filename, FLOPPYSIZE or die "Could not truncate: $!\n";
-}
index 4ae4da7..8fb8f7a 100644 (file)
@@ -94,7 +94,7 @@ int fw_write_ring(raw1394handle_t handle, nodeid_t target,
                  const u8 *buf, int len)
 {
        u32 put = *putptr;
-       u32 end = ring_add(put, len, ring_size);
+       u32 end = fw_ring_add(put, len, ring_size);
        if (end < put) {
                raw1394_write(handle, target, ring_addr + put,
                              ring_size - put, (quadlet_t *)buf);
@@ -119,7 +119,7 @@ int fw_read_ring(raw1394handle_t handle, nodeid_t target,
                 u8 *buf, int len)
 {
        u32 get = *getptr;
-       u32 end = ring_add(get, len, ring_size);
+       u32 end = fw_ring_add(get, len, ring_size);
        if (end < get) {
                raw1394_read(handle, target, ring_addr + get,
                             ring_size - get, (quadlet_t *)buf);
diff --git a/src/util/padimg.pl b/src/util/padimg.pl
new file mode 100755 (executable)
index 0000000..4421aaf
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/perl -w
+
+use strict;
+use warnings;
+use Getopt::Long;
+use Fcntl;
+
+my $verbosity = 0;
+my $blksize = 512;
+my $byte = 0;
+
+my %opts = (
+  'verbose|v+' => sub { $verbosity++; },
+  'quiet|q+' => sub { $verbosity--; },
+  'blksize|s=o' => sub { $blksize = $_[1]; },
+  'byte|b=o' => sub { $byte = $_[1]; },
+);
+
+Getopt::Long::Configure ( 'bundling', 'auto_abbrev' );
+GetOptions ( %opts ) or die "Could not parse command-line options\n";
+
+while ( my $filename = shift ) {
+  die "$filename is not a file\n" unless -f $filename;
+  my $oldsize = -s $filename;
+  my $padsize = ( ( -$oldsize ) % $blksize );
+  my $newsize = ( $oldsize + $padsize );
+  next unless $padsize;
+  if ( $verbosity >= 1 ) {
+      printf "Padding %s from %d to %d bytes with %d x 0x%02x\n",
+            $filename, $oldsize, $newsize, $padsize, $byte;
+  }
+  if ( $byte ) {
+    sysopen ( my $fh, $filename, ( O_WRONLY | O_APPEND ) )
+       or die "Could not open $filename for appending: $!\n";
+    syswrite $fh, ( chr ( $byte ) x $padsize )
+       or die "Could not append to $filename: $!\n";
+    close ( $fh );
+  } else {
+    truncate $filename, $newsize
+       or die "Could not resize $filename: $!\n";
+  }
+  die "Failed to pad $filename\n"
+      unless ( ( ( -s $filename ) % $blksize ) == 0 );
+}
index c1082b3..1513289 100644 (file)
@@ -57,6 +57,10 @@ struct zinfo_file {
        unsigned int num_entries;
 };
 
+static unsigned long align ( unsigned long value, unsigned long align ) {
+       return ( ( value + align - 1 ) & ~( align - 1 ) );
+}
+
 static int read_file ( const char *filename, void **buf, size_t *len ) {
        FILE *file;
        struct stat stat;
@@ -140,14 +144,13 @@ static int process_zinfo_copy ( struct input_file *input,
        struct zinfo_copy *copy = &zinfo->copy;
        size_t offset = copy->offset;
        size_t len = copy->len;
-       unsigned int align = copy->align;
 
        if ( ( offset + len ) > input->len ) {
                fprintf ( stderr, "Input buffer overrun on copy\n" );
                return -1;
        }
 
-       output->len = ( ( output->len + align - 1 ) & ~( align - 1 ) );
+       output->len = align ( output->len, copy->align );
        if ( ( output->len + len ) > output->max_len ) {
                fprintf ( stderr, "Output buffer overrun on copy\n" );
                return -1;
@@ -170,7 +173,6 @@ static int process_zinfo_pack ( struct input_file *input,
        struct zinfo_pack *pack = &zinfo->pack;
        size_t offset = pack->offset;
        size_t len = pack->len;
-       unsigned int align = pack->align;
        unsigned long packed_len;
 
        if ( ( offset + len ) > input->len ) {
@@ -178,7 +180,7 @@ static int process_zinfo_pack ( struct input_file *input,
                return -1;
        }
 
-       output->len = ( ( output->len + align - 1 ) & ~( align - 1 ) );
+       output->len = align ( output->len, pack->align );
        if ( output->len > output->max_len ) {
                fprintf ( stderr, "Output buffer overrun on pack\n" );
                return -1;
@@ -211,7 +213,8 @@ static int process_zinfo_subtract ( struct input_file *input,
                                    size_t datasize ) {
        size_t offset = subtract->offset;
        void *target;
-       long delta;
+       signed long raw_delta;
+       signed long delta;
        unsigned long old;
        unsigned long new;
 
@@ -222,8 +225,9 @@ static int process_zinfo_subtract ( struct input_file *input,
        }
 
        target = ( output->buf + offset );
-       delta = ( ( output->len / subtract->divisor ) -
-                 ( input->len / subtract->divisor ) );
+       raw_delta = ( align ( output->len, subtract->divisor ) -
+                     align ( input->len, subtract->divisor ) );
+       delta = ( raw_delta / ( ( signed long ) subtract->divisor ) );
 
        switch ( datasize ) {
        case 1: {
@@ -251,7 +255,7 @@ static int process_zinfo_subtract ( struct input_file *input,
        }
 
        if ( DEBUG ) {
-               fprintf ( stderr, "SUBx [%#zx,%#zx) (%#lx+(%#lx/%#lx)-(%#lx/%#lx)) = %#lx\n",
+               fprintf ( stderr, "SUBx [%#zx,%#zx) (%#lx+(%#lx/%#x)-(%#lx/%#x)) = %#lx\n",
                          offset, ( offset + datasize ), old, output->len, subtract->divisor,
                          input->len, subtract->divisor, new );
        }