aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--com32/menu/menu.h1
-rw-r--r--com32/menu/menumain.c25
-rw-r--r--com32/menu/readconfig.c5
-rw-r--r--com32/modules/chain.c13
-rw-r--r--core/kernel.inc2
-rw-r--r--core/ldlinux.asm35
-rw-r--r--core/pxe.inc1
-rw-r--r--core/pxelinux.asm319
-rw-r--r--core/runkernel.inc18
-rw-r--r--doc/menu.txt8
-rw-r--r--gpxe/gpxe.diff15
-rw-r--r--gpxe/pxelinux.gpxe1
-rw-r--r--gpxe/src/Makefile24
-rw-r--r--gpxe/src/Makefile.housekeeping220
-rw-r--r--gpxe/src/README.pixify90
-rw-r--r--gpxe/src/arch/i386/Makefile33
-rw-r--r--gpxe/src/arch/i386/Makefile.pcbios29
-rw-r--r--gpxe/src/arch/i386/core/basemem_packet.c2
-rw-r--r--gpxe/src/arch/i386/core/etherboot.prefix.lds100
-rw-r--r--gpxe/src/arch/i386/core/pic8259.c2
-rw-r--r--gpxe/src/arch/i386/core/prefixudata.lds8
-rw-r--r--gpxe/src/arch/i386/core/prefixzdata.lds8
-rw-r--r--gpxe/src/arch/i386/core/rdtsc_timer.c2
-rw-r--r--gpxe/src/arch/i386/core/realmode.c23
-rw-r--r--gpxe/src/arch/i386/core/relocate.c2
-rw-r--r--gpxe/src/arch/i386/core/setjmp.S2
-rw-r--r--gpxe/src/arch/i386/core/stack.S2
-rw-r--r--gpxe/src/arch/i386/core/stack16.S2
-rw-r--r--gpxe/src/arch/i386/core/start16.lds8
-rw-r--r--gpxe/src/arch/i386/core/start16z.lds65
-rw-r--r--gpxe/src/arch/i386/core/timer2.c2
-rw-r--r--gpxe/src/arch/i386/core/virtaddr.S2
-rw-r--r--gpxe/src/arch/i386/core/x86_io.c2
-rw-r--r--gpxe/src/arch/i386/drivers/net/undi.c4
-rw-r--r--gpxe/src/arch/i386/drivers/net/undiisr.S6
-rw-r--r--gpxe/src/arch/i386/drivers/net/undiload.c7
-rw-r--r--gpxe/src/arch/i386/drivers/net/undinet.c273
-rw-r--r--gpxe/src/arch/i386/drivers/net/undionly.c2
-rw-r--r--gpxe/src/arch/i386/drivers/net/undipreload.c2
-rw-r--r--gpxe/src/arch/i386/drivers/net/undirom.c2
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/basemem.c2
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/bios_console.c2
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/e820mangler.S5
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/fakee820.c2
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/gateA20.c2
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/hidemem.c2
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/memmap.c2
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/pnpbios.c2
-rw-r--r--gpxe/src/arch/i386/hci/commands/pxe_cmd.c33
-rw-r--r--gpxe/src/arch/i386/image/bootsector.c2
-rw-r--r--gpxe/src/arch/i386/image/bzimage.c483
-rw-r--r--gpxe/src/arch/i386/image/com32.c2
-rw-r--r--gpxe/src/arch/i386/image/comboot.c2
-rw-r--r--gpxe/src/arch/i386/image/elfboot.c2
-rw-r--r--gpxe/src/arch/i386/image/eltorito.c2
-rw-r--r--gpxe/src/arch/i386/image/multiboot.c44
-rw-r--r--gpxe/src/arch/i386/image/pxe_image.c18
-rw-r--r--gpxe/src/arch/i386/include/basemem.h2
-rw-r--r--gpxe/src/arch/i386/include/basemem_packet.h2
-rw-r--r--gpxe/src/arch/i386/include/bios.h2
-rw-r--r--gpxe/src/arch/i386/include/biosint.h2
-rw-r--r--gpxe/src/arch/i386/include/bits/byteswap.h2
-rw-r--r--gpxe/src/arch/i386/include/bits/compiler.h2
-rw-r--r--gpxe/src/arch/i386/include/bits/endian.h2
-rw-r--r--gpxe/src/arch/i386/include/bits/errfile.h3
-rw-r--r--gpxe/src/arch/i386/include/bits/io.h2
-rw-r--r--gpxe/src/arch/i386/include/bits/nap.h2
-rw-r--r--gpxe/src/arch/i386/include/bits/smbios.h2
-rw-r--r--gpxe/src/arch/i386/include/bits/stdint.h6
-rw-r--r--gpxe/src/arch/i386/include/bits/timer.h2
-rw-r--r--gpxe/src/arch/i386/include/bits/uaccess.h2
-rw-r--r--gpxe/src/arch/i386/include/bits/umalloc.h2
-rw-r--r--gpxe/src/arch/i386/include/bootsector.h2
-rw-r--r--gpxe/src/arch/i386/include/bzimage.h5
-rw-r--r--gpxe/src/arch/i386/include/callbacks_arch.h243
-rw-r--r--gpxe/src/arch/i386/include/comboot.h2
-rw-r--r--gpxe/src/arch/i386/include/fakee820.h2
-rw-r--r--gpxe/src/arch/i386/include/gpxe/abft.h2
-rw-r--r--gpxe/src/arch/i386/include/gpxe/bios_nap.h2
-rw-r--r--gpxe/src/arch/i386/include/gpxe/bios_smbios.h2
-rw-r--r--gpxe/src/arch/i386/include/gpxe/bios_timer.h2
-rw-r--r--gpxe/src/arch/i386/include/gpxe/ibft.h2
-rw-r--r--gpxe/src/arch/i386/include/gpxe/memtop_umalloc.h2
-rw-r--r--gpxe/src/arch/i386/include/gpxe/rdtsc_timer.h2
-rw-r--r--gpxe/src/arch/i386/include/gpxe/sbft.h125
-rw-r--r--gpxe/src/arch/i386/include/gpxe/timer2.h2
-rw-r--r--gpxe/src/arch/i386/include/gpxe/x86_io.h2
-rw-r--r--gpxe/src/arch/i386/include/int13.h2
-rw-r--r--[-rwxr-xr-x]gpxe/src/arch/i386/include/librm.h2
-rw-r--r--gpxe/src/arch/i386/include/limits.h2
-rw-r--r--gpxe/src/arch/i386/include/memsizes.h2
-rw-r--r--gpxe/src/arch/i386/include/multiboot.h2
-rw-r--r--gpxe/src/arch/i386/include/pic8259.h2
-rw-r--r--gpxe/src/arch/i386/include/pnpbios.h2
-rw-r--r--gpxe/src/arch/i386/include/pxe.h3
-rw-r--r--gpxe/src/arch/i386/include/pxe_api.h68
-rw-r--r--gpxe/src/arch/i386/include/pxe_call.h28
-rw-r--r--gpxe/src/arch/i386/include/pxe_types.h2
-rw-r--r--gpxe/src/arch/i386/include/pxeparent.h11
-rw-r--r--gpxe/src/arch/i386/include/realmode.h2
-rw-r--r--gpxe/src/arch/i386/include/registers.h2
-rw-r--r--gpxe/src/arch/i386/include/setjmp.h2
-rw-r--r--gpxe/src/arch/i386/include/undi.h2
-rw-r--r--gpxe/src/arch/i386/include/undiload.h2
-rw-r--r--gpxe/src/arch/i386/include/undinet.h2
-rw-r--r--gpxe/src/arch/i386/include/undipreload.h2
-rw-r--r--gpxe/src/arch/i386/include/undirom.h2
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/abft.c2
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/aoeboot.c62
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/bios_nap.c2
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/bios_smbios.c2
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/bios_timer.c2
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/biosint.c2
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/ib_srpboot.c73
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/ibft.c17
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/int13.c79
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/iscsiboot.c20
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/keepsan.c26
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c2
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/pcibios.c2
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/sbft.c105
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_call.c93
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_entry.S2
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_file.c42
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_loader.c5
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_preboot.c25
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_tftp.c17
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_udp.c2
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_undi.c215
-rw-r--r--gpxe/src/arch/i386/interface/pxeparent/pxeparent.c201
-rw-r--r--gpxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c69
-rw-r--r--gpxe/src/arch/i386/interface/syslinux/com32_call.c2
-rw-r--r--gpxe/src/arch/i386/interface/syslinux/com32_wrapper.S2
-rw-r--r--gpxe/src/arch/i386/interface/syslinux/comboot_call.c31
-rw-r--r--gpxe/src/arch/i386/interface/syslinux/comboot_resolv.c2
-rw-r--r--gpxe/src/arch/i386/prefix/bImageprefix.S611
-rw-r--r--gpxe/src/arch/i386/prefix/bootpart.S2
-rw-r--r--gpxe/src/arch/i386/prefix/comprefix.S46
-rw-r--r--gpxe/src/arch/i386/prefix/dskprefix.S6
-rw-r--r--gpxe/src/arch/i386/prefix/elf_dprefix.S94
-rw-r--r--gpxe/src/arch/i386/prefix/elfprefix.S94
-rwxr-xr-xgpxe/src/arch/i386/prefix/exeprefix.S41
-rw-r--r--gpxe/src/arch/i386/prefix/hdprefix.S6
-rw-r--r--gpxe/src/arch/i386/prefix/hromprefix.S12
-rw-r--r--gpxe/src/arch/i386/prefix/kkpxeprefix.S5
-rw-r--r--gpxe/src/arch/i386/prefix/kpxeprefix.S2
-rw-r--r--gpxe/src/arch/i386/prefix/libprefix.S2
-rw-r--r--gpxe/src/arch/i386/prefix/lkrnprefix.S6
-rw-r--r--gpxe/src/arch/i386/prefix/lmelf_dprefix.S161
-rw-r--r--gpxe/src/arch/i386/prefix/lmelf_prefix.S161
-rw-r--r--gpxe/src/arch/i386/prefix/nbiprefix.S8
-rw-r--r--gpxe/src/arch/i386/prefix/pxeprefix.S100
-rw-r--r--gpxe/src/arch/i386/prefix/romprefix.S480
-rw-r--r--gpxe/src/arch/i386/prefix/undiloader.S49
-rw-r--r--gpxe/src/arch/i386/prefix/unnrv2b.S2
-rw-r--r--gpxe/src/arch/i386/prefix/unnrv2b16.S9
-rw-r--r--gpxe/src/arch/i386/prefix/xromprefix.S9
-rw-r--r--gpxe/src/arch/i386/scripts/i386-kir.lds1
-rw-r--r--gpxe/src/arch/i386/scripts/i386.lds11
-rw-r--r--gpxe/src/arch/i386/transitions/libkir.S2
-rw-r--r--[-rwxr-xr-x]gpxe/src/arch/i386/transitions/librm.S2
-rw-r--r--[-rwxr-xr-x]gpxe/src/arch/i386/transitions/librm_mgmt.c2
-rw-r--r--gpxe/src/arch/x86/Makefile2
-rw-r--r--gpxe/src/arch/x86/core/pcidirect.c2
-rw-r--r--gpxe/src/arch/x86/core/x86_string.c2
-rw-r--r--gpxe/src/arch/x86/include/bits/pci_io.h2
-rw-r--r--gpxe/src/arch/x86/include/bits/string.h2
-rw-r--r--gpxe/src/arch/x86/include/gpxe/efi/efix86_nap.h2
-rw-r--r--gpxe/src/arch/x86/include/gpxe/pcibios.h2
-rw-r--r--gpxe/src/arch/x86/include/gpxe/pcidirect.h2
-rw-r--r--gpxe/src/arch/x86/interface/efi/efix86_nap.c2
-rw-r--r--gpxe/src/arch/x86/prefix/efidrvprefix.c2
-rw-r--r--gpxe/src/arch/x86/prefix/efiprefix.c2
-rw-r--r--gpxe/src/arch/x86/scripts/efi.lds1
-rw-r--r--gpxe/src/arch/x86_64/include/bits/stdint.h2
-rw-r--r--gpxe/src/config/config.c (renamed from gpxe/src/core/config.c)50
-rw-r--r--gpxe/src/config/config_net80211.c50
-rw-r--r--gpxe/src/config/config_romprefix.c24
-rw-r--r--gpxe/src/config/console.h2
-rw-r--r--gpxe/src/config/defaults.h2
-rw-r--r--gpxe/src/config/defaults/pcbios.h6
-rw-r--r--gpxe/src/config/general.h31
-rw-r--r--gpxe/src/config/ioapi.h2
-rw-r--r--gpxe/src/config/nap.h2
-rw-r--r--gpxe/src/config/serial.h9
-rw-r--r--gpxe/src/config/timer.h2
-rw-r--r--gpxe/src/config/umalloc.h2
-rw-r--r--gpxe/src/core/acpi.c2
-rw-r--r--gpxe/src/core/ansiesc.c2
-rw-r--r--gpxe/src/core/asprintf.c2
-rw-r--r--gpxe/src/core/base64.c2
-rw-r--r--gpxe/src/core/basename.c2
-rw-r--r--gpxe/src/core/bitmap.c2
-rw-r--r--gpxe/src/core/bitops.c2
-rw-r--r--gpxe/src/core/console.c11
-rw-r--r--gpxe/src/core/cpio.c2
-rw-r--r--gpxe/src/core/ctype.c48
-rw-r--r--gpxe/src/core/cwuri.c2
-rw-r--r--gpxe/src/core/debug.c3
-rw-r--r--gpxe/src/core/device.c9
-rw-r--r--gpxe/src/core/downloader.c27
-rw-r--r--gpxe/src/core/exec.c14
-rw-r--r--gpxe/src/core/filter.c2
-rw-r--r--gpxe/src/core/gdbstub.c17
-rw-r--r--gpxe/src/core/getkey.c2
-rw-r--r--gpxe/src/core/getopt.c2
-rw-r--r--gpxe/src/core/image.c10
-rw-r--r--gpxe/src/core/init.c25
-rw-r--r--gpxe/src/core/interface.c2
-rw-r--r--gpxe/src/core/iobuf.c2
-rw-r--r--gpxe/src/core/job.c10
-rw-r--r--gpxe/src/core/linebuf.c2
-rw-r--r--gpxe/src/core/main.c9
-rw-r--r--gpxe/src/core/malloc.c2
-rw-r--r--gpxe/src/core/misc.c17
-rw-r--r--gpxe/src/core/monojob.c2
-rw-r--r--gpxe/src/core/nvo.c2
-rw-r--r--gpxe/src/core/open.c41
-rw-r--r--gpxe/src/core/posix_io.c4
-rw-r--r--gpxe/src/core/process.c24
-rw-r--r--gpxe/src/core/random.c2
-rw-r--r--gpxe/src/core/refcnt.c2
-rw-r--r--gpxe/src/core/resolv.c53
-rw-r--r--gpxe/src/core/serial.c2
-rw-r--r--gpxe/src/core/settings.c500
-rw-r--r--gpxe/src/core/string.c2
-rw-r--r--gpxe/src/core/timer.c2
-rw-r--r--gpxe/src/core/uri.c165
-rw-r--r--gpxe/src/core/uuid.c2
-rw-r--r--gpxe/src/core/vsprintf.c2
-rw-r--r--gpxe/src/core/xfer.c5
-rw-r--r--gpxe/src/crypto/aes_wrap.c123
-rw-r--r--gpxe/src/crypto/arc4.c131
-rw-r--r--gpxe/src/crypto/asn1.c2
-rw-r--r--gpxe/src/crypto/axtls_aes.c15
-rw-r--r--gpxe/src/crypto/cbc.c2
-rw-r--r--gpxe/src/crypto/chap.c2
-rw-r--r--gpxe/src/crypto/crandom.c55
-rw-r--r--gpxe/src/crypto/crc32.c54
-rw-r--r--gpxe/src/crypto/crypto_null.c2
-rw-r--r--gpxe/src/crypto/hmac.c2
-rw-r--r--gpxe/src/crypto/md5.c14
-rw-r--r--gpxe/src/crypto/sha1extra.c165
-rw-r--r--gpxe/src/crypto/x509.c2
-rw-r--r--gpxe/src/doc/pxe_extensions33
-rw-r--r--gpxe/src/doxygen.cfg434
-rw-r--r--gpxe/src/drivers/bitbash/bitbash.c2
-rw-r--r--gpxe/src/drivers/bitbash/i2c_bit.c2
-rw-r--r--gpxe/src/drivers/bitbash/spi_bit.c53
-rw-r--r--gpxe/src/drivers/block/ata.c27
-rw-r--r--gpxe/src/drivers/block/ramdisk.c2
-rw-r--r--gpxe/src/drivers/block/scsi.c93
-rw-r--r--gpxe/src/drivers/block/srp.c523
-rw-r--r--gpxe/src/drivers/bus/eisa.c7
-rw-r--r--gpxe/src/drivers/bus/isa.c9
-rw-r--r--gpxe/src/drivers/bus/isapnp.c9
-rw-r--r--gpxe/src/drivers/bus/mca.c9
-rw-r--r--gpxe/src/drivers/bus/pci.c9
-rw-r--r--gpxe/src/drivers/bus/pcibackup.c90
-rw-r--r--gpxe/src/drivers/bus/pciextra.c7
-rw-r--r--gpxe/src/drivers/infiniband/MT25218_PRM.h2
-rw-r--r--gpxe/src/drivers/infiniband/MT25408_PRM.h8
-rw-r--r--gpxe/src/drivers/infiniband/arbel.c18
-rw-r--r--gpxe/src/drivers/infiniband/arbel.h2
-rw-r--r--gpxe/src/drivers/infiniband/hermon.c702
-rw-r--r--gpxe/src/drivers/infiniband/hermon.h91
-rw-r--r--gpxe/src/drivers/infiniband/ib_sma.c553
-rw-r--r--gpxe/src/drivers/infiniband/linda.c99
-rw-r--r--gpxe/src/drivers/infiniband/linda.h5
-rw-r--r--gpxe/src/drivers/infiniband/linda_fw.c2
-rw-r--r--gpxe/src/drivers/infiniband/mlx_bitops.h14
-rw-r--r--gpxe/src/drivers/infiniband/qib_7220_regs.h11
-rwxr-xr-x[-rw-r--r--]gpxe/src/drivers/infiniband/qib_genbits.pl29
-rw-r--r--gpxe/src/drivers/net/3c509.c2
-rw-r--r--gpxe/src/drivers/net/3c509.h2
-rw-r--r--gpxe/src/drivers/net/3c515.c1
-rw-r--r--gpxe/src/drivers/net/3c529.c2
-rw-r--r--gpxe/src/drivers/net/3c595.c30
-rw-r--r--gpxe/src/drivers/net/3c595.h2
-rw-r--r--gpxe/src/drivers/net/3c5x9.c2
-rw-r--r--gpxe/src/drivers/net/3c90x.c1837
-rw-r--r--gpxe/src/drivers/net/3c90x.h302
-rw-r--r--gpxe/src/drivers/net/3c90x.txt307
-rw-r--r--gpxe/src/drivers/net/amd8111e.c4
-rw-r--r--gpxe/src/drivers/net/amd8111e.h2
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k.c1700
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k.h1279
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k_attach.c340
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k_caps.c154
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k_desc.c544
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k_dma.c631
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k_eeprom.c1760
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k_gpio.c122
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k_initvals.c1560
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k_pcu.c534
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k_phy.c2586
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k_qcu.c394
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k_reset.c1176
-rw-r--r--gpxe/src/drivers/net/ath5k/ath5k_rfkill.c107
-rw-r--r--gpxe/src/drivers/net/ath5k/base.h145
-rw-r--r--gpxe/src/drivers/net/ath5k/desc.h332
-rw-r--r--gpxe/src/drivers/net/ath5k/eeprom.h451
-rw-r--r--gpxe/src/drivers/net/ath5k/reg.h2589
-rw-r--r--gpxe/src/drivers/net/ath5k/rfbuffer.h1181
-rw-r--r--gpxe/src/drivers/net/ath5k/rfgain.h516
-rw-r--r--gpxe/src/drivers/net/atl1e.c1758
-rw-r--r--gpxe/src/drivers/net/atl1e.h1031
-rw-r--r--gpxe/src/drivers/net/b44.c20
-rw-r--r--gpxe/src/drivers/net/b44.h3
-rw-r--r--gpxe/src/drivers/net/bnx2.c10
-rw-r--r--gpxe/src/drivers/net/bnx2.h108
-rw-r--r--gpxe/src/drivers/net/cs89x0.c2
-rw-r--r--gpxe/src/drivers/net/cs89x0.h2
-rw-r--r--gpxe/src/drivers/net/davicom.c10
-rw-r--r--gpxe/src/drivers/net/depca.c2
-rw-r--r--gpxe/src/drivers/net/dmfe.c10
-rw-r--r--gpxe/src/drivers/net/e1000/e1000.c392
-rw-r--r--gpxe/src/drivers/net/e1000/e1000.h2
-rw-r--r--gpxe/src/drivers/net/e1000/e1000_hw.c156
-rw-r--r--gpxe/src/drivers/net/e1000/e1000_hw.h20
-rw-r--r--gpxe/src/drivers/net/e1000/e1000_osdep.h1
-rw-r--r--gpxe/src/drivers/net/eepro.c2
-rw-r--r--gpxe/src/drivers/net/eepro100.c1692
-rw-r--r--gpxe/src/drivers/net/eepro100.h206
-rw-r--r--gpxe/src/drivers/net/epic100.c6
-rw-r--r--gpxe/src/drivers/net/epic100.h2
-rw-r--r--gpxe/src/drivers/net/etherfabric.c92
-rw-r--r--gpxe/src/drivers/net/etherfabric.h2
-rw-r--r--gpxe/src/drivers/net/etherfabric_nic.h3
-rw-r--r--gpxe/src/drivers/net/forcedeth.c102
-rw-r--r--gpxe/src/drivers/net/hfa384x.h2
-rw-r--r--gpxe/src/drivers/net/ipoib.c878
-rw-r--r--gpxe/src/drivers/net/legacy.c6
-rw-r--r--gpxe/src/drivers/net/mtd80x.c74
-rw-r--r--gpxe/src/drivers/net/mtnic.c13
-rw-r--r--gpxe/src/drivers/net/mtnic.h3
-rw-r--r--gpxe/src/drivers/net/myri10ge.c1041
-rw-r--r--gpxe/src/drivers/net/myri10ge_mcp.h514
-rw-r--r--gpxe/src/drivers/net/natsemi.c8
-rw-r--r--gpxe/src/drivers/net/natsemi.h2
-rw-r--r--gpxe/src/drivers/net/ne2k_isa.c2
-rw-r--r--[-rwxr-xr-x]gpxe/src/drivers/net/ns83820.c4
-rw-r--r--gpxe/src/drivers/net/ns8390.c24
-rw-r--r--gpxe/src/drivers/net/ns8390.h2
-rw-r--r--gpxe/src/drivers/net/p80211hdr.h2
-rw-r--r--gpxe/src/drivers/net/pcnet32.c20
-rw-r--r--gpxe/src/drivers/net/phantom/nx_bitops.h2
-rw-r--r--gpxe/src/drivers/net/phantom/nxhal_nic_interface.h2
-rw-r--r--gpxe/src/drivers/net/phantom/phantom.c22
-rw-r--r--gpxe/src/drivers/net/phantom/phantom.h2
-rw-r--r--gpxe/src/drivers/net/phantom/phantom_hw.h2
-rw-r--r--gpxe/src/drivers/net/pnic.c6
-rw-r--r--gpxe/src/drivers/net/pnic_api.h2
-rw-r--r--gpxe/src/drivers/net/prism2.c2
-rw-r--r--gpxe/src/drivers/net/prism2_pci.c8
-rw-r--r--gpxe/src/drivers/net/prism2_plx.c24
-rw-r--r--gpxe/src/drivers/net/r8169.c27
-rw-r--r--gpxe/src/drivers/net/r8169.h83
-rw-r--r--gpxe/src/drivers/net/rtl8139.c63
-rw-r--r--gpxe/src/drivers/net/rtl818x/rtl8180.c17
-rw-r--r--gpxe/src/drivers/net/rtl818x/rtl8180_grf5101.c186
-rw-r--r--gpxe/src/drivers/net/rtl818x/rtl8180_max2820.c158
-rw-r--r--gpxe/src/drivers/net/rtl818x/rtl8180_sa2400.c217
-rw-r--r--gpxe/src/drivers/net/rtl818x/rtl8185.c14
-rw-r--r--gpxe/src/drivers/net/rtl818x/rtl8185_rtl8225.c804
-rw-r--r--gpxe/src/drivers/net/rtl818x/rtl818x.c855
-rw-r--r--gpxe/src/drivers/net/rtl818x/rtl818x.h359
-rw-r--r--gpxe/src/drivers/net/sis190.c1179
-rw-r--r--gpxe/src/drivers/net/sis190.h311
-rw-r--r--gpxe/src/drivers/net/sis900.c12
-rw-r--r--gpxe/src/drivers/net/sis900.h2
-rwxr-xr-xgpxe/src/drivers/net/skge.c2472
-rwxr-xr-xgpxe/src/drivers/net/skge.h2623
-rw-r--r--gpxe/src/drivers/net/sky2.c2399
-rw-r--r--gpxe/src/drivers/net/sky2.h2176
-rw-r--r--gpxe/src/drivers/net/smc9000.c3
-rw-r--r--gpxe/src/drivers/net/smc9000.h11
-rw-r--r--gpxe/src/drivers/net/sundance.c15
-rw-r--r--gpxe/src/drivers/net/tg3.c67
-rw-r--r--gpxe/src/drivers/net/tg3.h109
-rw-r--r--gpxe/src/drivers/net/tlan.c125
-rw-r--r--gpxe/src/drivers/net/tlan.h37
-rw-r--r--gpxe/src/drivers/net/tulip.c74
-rw-r--r--gpxe/src/drivers/net/via-rhine.c10
-rw-r--r--gpxe/src/drivers/net/via-velocity.c2
-rw-r--r--gpxe/src/drivers/net/virtio-net.c2
-rw-r--r--gpxe/src/drivers/net/w89c840.c6
-rw-r--r--gpxe/src/drivers/net/wlan_compat.h2
-rw-r--r--gpxe/src/drivers/nvs/nvs.c2
-rw-r--r--gpxe/src/drivers/nvs/spi.c2
-rw-r--r--gpxe/src/drivers/nvs/threewire.c55
-rw-r--r--gpxe/src/hci/commands/autoboot_cmd.c2
-rw-r--r--gpxe/src/hci/commands/config_cmd.c2
-rw-r--r--gpxe/src/hci/commands/dhcp_cmd.c2
-rw-r--r--gpxe/src/hci/commands/digest_cmd.c120
-rw-r--r--gpxe/src/hci/commands/ifmgmt_cmd.c21
-rw-r--r--gpxe/src/hci/commands/image_cmd.c25
-rw-r--r--gpxe/src/hci/commands/iwmgmt_cmd.c69
-rw-r--r--gpxe/src/hci/commands/login_cmd.c2
-rw-r--r--gpxe/src/hci/commands/nvo_cmd.c2
-rw-r--r--gpxe/src/hci/commands/route_cmd.c2
-rw-r--r--gpxe/src/hci/commands/sanboot_cmd.c2
-rw-r--r--gpxe/src/hci/commands/time_cmd.c84
-rw-r--r--gpxe/src/hci/editstring.c2
-rw-r--r--gpxe/src/hci/mucurses/ansi_screen.c2
-rw-r--r--gpxe/src/hci/mucurses/clear.c2
-rw-r--r--gpxe/src/hci/mucurses/colour.c2
-rw-r--r--gpxe/src/hci/mucurses/cursor.h2
-rw-r--r--gpxe/src/hci/mucurses/mucurses.c2
-rw-r--r--gpxe/src/hci/mucurses/mucurses.h2
-rw-r--r--gpxe/src/hci/mucurses/print.c2
-rw-r--r--gpxe/src/hci/mucurses/widgets/editbox.c2
-rw-r--r--gpxe/src/hci/mucurses/winattrs.c2
-rw-r--r--gpxe/src/hci/mucurses/wininit.c2
-rw-r--r--gpxe/src/hci/readline.c2
-rw-r--r--gpxe/src/hci/shell.c9
-rw-r--r--gpxe/src/hci/shell_banner.c2
-rw-r--r--gpxe/src/hci/strerror.c19
-rw-r--r--gpxe/src/hci/tui/login_ui.c2
-rw-r--r--gpxe/src/hci/tui/settings_ui.c12
-rw-r--r--gpxe/src/hci/wireless_errors.c118
-rw-r--r--gpxe/src/image/efi_image.c2
-rw-r--r--gpxe/src/image/elf.c57
-rw-r--r--gpxe/src/image/embedded.c2
-rw-r--r--gpxe/src/image/script.c10
-rw-r--r--gpxe/src/image/segment.c13
-rw-r--r--gpxe/src/include/assert.h2
-rw-r--r--gpxe/src/include/byteswap.h2
-rw-r--r--gpxe/src/include/compiler.h345
-rw-r--r--gpxe/src/include/console.h7
-rw-r--r--gpxe/src/include/ctype.h4
-rw-r--r--gpxe/src/include/curses.h2
-rw-r--r--gpxe/src/include/debug.h28
-rw-r--r--gpxe/src/include/dhcp.h12
-rw-r--r--gpxe/src/include/elf.h2
-rw-r--r--gpxe/src/include/endian.h2
-rw-r--r--gpxe/src/include/errno.h2
-rw-r--r--gpxe/src/include/etherboot.h2
-rw-r--r--gpxe/src/include/getopt.h2
-rw-r--r--gpxe/src/include/gpxe/acpi.h2
-rw-r--r--gpxe/src/include/gpxe/aes.h22
-rw-r--r--gpxe/src/include/gpxe/ansiesc.h2
-rw-r--r--gpxe/src/include/gpxe/aoe.h2
-rw-r--r--gpxe/src/include/gpxe/api.h2
-rw-r--r--gpxe/src/include/gpxe/arc4.h22
-rw-r--r--gpxe/src/include/gpxe/arp.h9
-rw-r--r--gpxe/src/include/gpxe/asn1.h2
-rw-r--r--gpxe/src/include/gpxe/ata.h4
-rw-r--r--gpxe/src/include/gpxe/base64.h2
-rw-r--r--gpxe/src/include/gpxe/bitbash.h2
-rw-r--r--gpxe/src/include/gpxe/bitmap.h2
-rw-r--r--gpxe/src/include/gpxe/bitops.h2
-rw-r--r--gpxe/src/include/gpxe/blockdev.h2
-rw-r--r--gpxe/src/include/gpxe/cbc.h2
-rw-r--r--gpxe/src/include/gpxe/chap.h2
-rw-r--r--gpxe/src/include/gpxe/command.h6
-rw-r--r--gpxe/src/include/gpxe/cpio.h2
-rw-r--r--gpxe/src/include/gpxe/crc32.h10
-rw-r--r--gpxe/src/include/gpxe/crypto.h8
-rw-r--r--gpxe/src/include/gpxe/device.h7
-rw-r--r--gpxe/src/include/gpxe/dhcp.h23
-rw-r--r--gpxe/src/include/gpxe/dhcpopts.h2
-rw-r--r--gpxe/src/include/gpxe/dhcppkt.h2
-rw-r--r--gpxe/src/include/gpxe/dns.h2
-rw-r--r--gpxe/src/include/gpxe/downloader.h2
-rw-r--r--gpxe/src/include/gpxe/eapol.h112
-rw-r--r--gpxe/src/include/gpxe/editbox.h2
-rw-r--r--gpxe/src/include/gpxe/editstring.h2
-rw-r--r--gpxe/src/include/gpxe/efi/efi.h21
-rw-r--r--gpxe/src/include/gpxe/efi/efi_io.h2
-rw-r--r--gpxe/src/include/gpxe/efi/efi_pci.h2
-rw-r--r--gpxe/src/include/gpxe/efi/efi_smbios.h2
-rw-r--r--gpxe/src/include/gpxe/efi/efi_timer.h2
-rw-r--r--gpxe/src/include/gpxe/efi/efi_uaccess.h2
-rw-r--r--gpxe/src/include/gpxe/efi/efi_umalloc.h2
-rw-r--r--gpxe/src/include/gpxe/eisa.h7
-rw-r--r--gpxe/src/include/gpxe/elf.h2
-rw-r--r--gpxe/src/include/gpxe/errfile.h29
-rw-r--r--gpxe/src/include/gpxe/errortab.h6
-rw-r--r--gpxe/src/include/gpxe/ethernet.h28
-rw-r--r--gpxe/src/include/gpxe/fakedhcp.h2
-rw-r--r--gpxe/src/include/gpxe/features.h14
-rw-r--r--gpxe/src/include/gpxe/filter.h2
-rw-r--r--gpxe/src/include/gpxe/ftp.h2
-rw-r--r--gpxe/src/include/gpxe/gdbserial.h2
-rw-r--r--gpxe/src/include/gpxe/gdbstub.h6
-rw-r--r--gpxe/src/include/gpxe/gdbudp.h2
-rw-r--r--gpxe/src/include/gpxe/hidemem.h2
-rw-r--r--gpxe/src/include/gpxe/hmac.h2
-rw-r--r--gpxe/src/include/gpxe/http.h2
-rw-r--r--gpxe/src/include/gpxe/i2c.h2
-rw-r--r--gpxe/src/include/gpxe/ib_cm.h72
-rw-r--r--gpxe/src/include/gpxe/ib_cmrc.h20
-rw-r--r--gpxe/src/include/gpxe/ib_mad.h205
-rw-r--r--gpxe/src/include/gpxe/ib_mcast.h48
-rw-r--r--gpxe/src/include/gpxe/ib_mi.h135
-rw-r--r--gpxe/src/include/gpxe/ib_packet.h14
-rw-r--r--gpxe/src/include/gpxe/ib_pathrec.h76
-rw-r--r--gpxe/src/include/gpxe/ib_sma.h59
-rw-r--r--gpxe/src/include/gpxe/ib_smc.h2
-rw-r--r--gpxe/src/include/gpxe/ib_srp.h79
-rw-r--r--gpxe/src/include/gpxe/icmp.h2
-rw-r--r--gpxe/src/include/gpxe/icmp6.h2
-rw-r--r--gpxe/src/include/gpxe/ieee80211.h1160
-rw-r--r--gpxe/src/include/gpxe/if_arp.h2
-rw-r--r--gpxe/src/include/gpxe/if_ether.h3
-rw-r--r--gpxe/src/include/gpxe/image.h8
-rw-r--r--gpxe/src/include/gpxe/in.h3
-rw-r--r--gpxe/src/include/gpxe/infiniband.h218
-rw-r--r--gpxe/src/include/gpxe/init.h13
-rw-r--r--gpxe/src/include/gpxe/interface.h2
-rw-r--r--gpxe/src/include/gpxe/io.h2
-rw-r--r--gpxe/src/include/gpxe/iobuf.h2
-rw-r--r--gpxe/src/include/gpxe/ip.h2
-rw-r--r--gpxe/src/include/gpxe/ip6.h2
-rw-r--r--gpxe/src/include/gpxe/ipoib.h31
-rw-r--r--gpxe/src/include/gpxe/isa.h7
-rw-r--r--gpxe/src/include/gpxe/isa_ids.h2
-rw-r--r--gpxe/src/include/gpxe/isapnp.h7
-rw-r--r--gpxe/src/include/gpxe/iscsi.h17
-rw-r--r--gpxe/src/include/gpxe/job.h4
-rw-r--r--gpxe/src/include/gpxe/keys.h2
-rw-r--r--gpxe/src/include/gpxe/linebuf.h2
-rw-r--r--gpxe/src/include/gpxe/linux_compat.h2
-rw-r--r--gpxe/src/include/gpxe/list.h2
-rw-r--r--gpxe/src/include/gpxe/login_ui.h2
-rw-r--r--gpxe/src/include/gpxe/malloc.h2
-rw-r--r--gpxe/src/include/gpxe/mca.h7
-rw-r--r--gpxe/src/include/gpxe/md5.h2
-rw-r--r--gpxe/src/include/gpxe/memmap.h2
-rw-r--r--gpxe/src/include/gpxe/monojob.h2
-rw-r--r--gpxe/src/include/gpxe/nap.h2
-rw-r--r--gpxe/src/include/gpxe/net80211.h1186
-rw-r--r--gpxe/src/include/gpxe/netdevice.h135
-rw-r--r--gpxe/src/include/gpxe/null_nap.h2
-rw-r--r--gpxe/src/include/gpxe/nvo.h2
-rw-r--r--gpxe/src/include/gpxe/nvs.h2
-rw-r--r--gpxe/src/include/gpxe/open.h14
-rw-r--r--gpxe/src/include/gpxe/pci.h52
-rw-r--r--gpxe/src/include/gpxe/pci_ids.h3
-rw-r--r--gpxe/src/include/gpxe/pci_io.h2
-rw-r--r--gpxe/src/include/gpxe/pcibackup.h33
-rw-r--r--gpxe/src/include/gpxe/posix_io.h2
-rw-r--r--gpxe/src/include/gpxe/process.h9
-rw-r--r--gpxe/src/include/gpxe/profile.h2
-rw-r--r--gpxe/src/include/gpxe/ramdisk.h2
-rw-r--r--gpxe/src/include/gpxe/rarp.h2
-rw-r--r--gpxe/src/include/gpxe/rc80211.h19
-rw-r--r--gpxe/src/include/gpxe/refcnt.h2
-rw-r--r--gpxe/src/include/gpxe/resolv.h8
-rw-r--r--gpxe/src/include/gpxe/retry.h2
-rw-r--r--gpxe/src/include/gpxe/rotate.h2
-rw-r--r--gpxe/src/include/gpxe/rsa.h2
-rw-r--r--gpxe/src/include/gpxe/sanboot.h10
-rw-r--r--gpxe/src/include/gpxe/scsi.h31
-rw-r--r--gpxe/src/include/gpxe/sec80211.h83
-rw-r--r--gpxe/src/include/gpxe/segment.h2
-rw-r--r--gpxe/src/include/gpxe/serial.h2
-rw-r--r--gpxe/src/include/gpxe/settings.h64
-rw-r--r--gpxe/src/include/gpxe/settings_ui.h2
-rw-r--r--gpxe/src/include/gpxe/sha1.h11
-rw-r--r--gpxe/src/include/gpxe/shell.h2
-rw-r--r--gpxe/src/include/gpxe/shell_banner.h2
-rw-r--r--gpxe/src/include/gpxe/smbios.h21
-rw-r--r--gpxe/src/include/gpxe/socket.h2
-rw-r--r--gpxe/src/include/gpxe/spi.h10
-rw-r--r--gpxe/src/include/gpxe/spi_bit.h2
-rw-r--r--gpxe/src/include/gpxe/srp.h868
-rw-r--r--gpxe/src/include/gpxe/tables.h263
-rw-r--r--gpxe/src/include/gpxe/tcp.h12
-rw-r--r--gpxe/src/include/gpxe/tcpip.h15
-rw-r--r--gpxe/src/include/gpxe/tftp.h2
-rw-r--r--gpxe/src/include/gpxe/threewire.h16
-rw-r--r--gpxe/src/include/gpxe/timer.h2
-rw-r--r--gpxe/src/include/gpxe/tls.h2
-rw-r--r--gpxe/src/include/gpxe/uaccess.h2
-rw-r--r--gpxe/src/include/gpxe/udp.h2
-rw-r--r--gpxe/src/include/gpxe/umalloc.h2
-rw-r--r--gpxe/src/include/gpxe/uri.h46
-rw-r--r--gpxe/src/include/gpxe/uuid.h2
-rw-r--r--gpxe/src/include/gpxe/vsprintf.h2
-rw-r--r--gpxe/src/include/gpxe/wpa.h503
-rw-r--r--gpxe/src/include/gpxe/x509.h2
-rw-r--r--gpxe/src/include/gpxe/xfer.h2
-rw-r--r--gpxe/src/include/hci/ifmgmt_cmd.h30
-rw-r--r--gpxe/src/include/igmp.h42
-rw-r--r--gpxe/src/include/lib.h42
-rw-r--r--gpxe/src/include/libgen.h2
-rw-r--r--gpxe/src/include/little_bswap.h2
-rw-r--r--gpxe/src/include/mii.h122
-rw-r--r--gpxe/src/include/nfs.h63
-rw-r--r--gpxe/src/include/nic.h4
-rw-r--r--gpxe/src/include/nmb.h22
-rw-r--r--gpxe/src/include/readline/readline.h2
-rw-r--r--gpxe/src/include/stdarg.h2
-rw-r--r--gpxe/src/include/stddef.h2
-rw-r--r--gpxe/src/include/stdint.h12
-rw-r--r--gpxe/src/include/stdio.h2
-rw-r--r--gpxe/src/include/stdlib.h2
-rw-r--r--gpxe/src/include/string.h2
-rw-r--r--gpxe/src/include/strings.h2
-rw-r--r--gpxe/src/include/unistd.h2
-rw-r--r--gpxe/src/include/usr/autoboot.h6
-rw-r--r--gpxe/src/include/usr/dhcpmgmt.h2
-rw-r--r--gpxe/src/include/usr/ifmgmt.h2
-rw-r--r--gpxe/src/include/usr/imgmgmt.h2
-rw-r--r--gpxe/src/include/usr/iwmgmt.h17
-rw-r--r--gpxe/src/include/usr/route.h2
-rw-r--r--gpxe/src/interface/efi/efi_console.c2
-rw-r--r--gpxe/src/interface/efi/efi_init.c18
-rw-r--r--gpxe/src/interface/efi/efi_io.c2
-rw-r--r--gpxe/src/interface/efi/efi_pci.c2
-rw-r--r--gpxe/src/interface/efi/efi_smbios.c2
-rw-r--r--gpxe/src/interface/efi/efi_snp.c21
-rw-r--r--gpxe/src/interface/efi/efi_strerror.c2
-rw-r--r--gpxe/src/interface/efi/efi_timer.c2
-rw-r--r--gpxe/src/interface/efi/efi_uaccess.c2
-rw-r--r--gpxe/src/interface/efi/efi_umalloc.c2
-rw-r--r--gpxe/src/interface/smbios/smbios.c2
-rw-r--r--gpxe/src/interface/smbios/smbios_settings.c27
-rw-r--r--gpxe/src/libgcc/icc.c8
-rw-r--r--gpxe/src/net/80211/net80211.c2829
-rw-r--r--gpxe/src/net/80211/rc80211.c371
-rw-r--r--gpxe/src/net/80211/sec80211.c503
-rw-r--r--gpxe/src/net/80211/wep.c303
-rw-r--r--gpxe/src/net/80211/wpa.c973
-rw-r--r--gpxe/src/net/80211/wpa_ccmp.c528
-rw-r--r--gpxe/src/net/80211/wpa_psk.c125
-rw-r--r--gpxe/src/net/80211/wpa_tkip.c586
-rw-r--r--gpxe/src/net/aoe.c15
-rw-r--r--gpxe/src/net/arp.c13
-rw-r--r--gpxe/src/net/cachedhcp.c76
-rw-r--r--gpxe/src/net/dhcpopts.c21
-rw-r--r--gpxe/src/net/dhcppkt.c14
-rw-r--r--gpxe/src/net/eapol.c85
-rw-r--r--gpxe/src/net/ethernet.c56
-rw-r--r--gpxe/src/net/fakedhcp.c2
-rw-r--r--gpxe/src/net/icmp.c2
-rw-r--r--gpxe/src/net/infiniband.c405
-rw-r--r--gpxe/src/net/infiniband/ib_cm.c413
-rw-r--r--gpxe/src/net/infiniband/ib_cmrc.c436
-rw-r--r--gpxe/src/net/infiniband/ib_mcast.c218
-rw-r--r--gpxe/src/net/infiniband/ib_mi.c406
-rw-r--r--gpxe/src/net/infiniband/ib_packet.c (renamed from gpxe/src/drivers/infiniband/ib_packet.c)36
-rw-r--r--gpxe/src/net/infiniband/ib_pathrec.c296
-rw-r--r--gpxe/src/net/infiniband/ib_sma.c369
-rw-r--r--gpxe/src/net/infiniband/ib_smc.c (renamed from gpxe/src/drivers/infiniband/ib_smc.c)31
-rw-r--r--gpxe/src/net/infiniband/ib_srp.c406
-rw-r--r--gpxe/src/net/iobpad.c2
-rw-r--r--gpxe/src/net/ipv4.c41
-rw-r--r--gpxe/src/net/mii.c147
-rw-r--r--gpxe/src/net/netdev_settings.c38
-rw-r--r--gpxe/src/net/netdevice.c66
-rw-r--r--gpxe/src/net/nullnet.c2
-rw-r--r--gpxe/src/net/rarp.c2
-rw-r--r--gpxe/src/net/retry.c3
-rw-r--r--gpxe/src/net/tcp.c141
-rw-r--r--gpxe/src/net/tcp/ftp.c30
-rw-r--r--gpxe/src/net/tcp/http.c64
-rw-r--r--gpxe/src/net/tcp/https.c2
-rw-r--r--gpxe/src/net/tcp/iscsi.c79
-rw-r--r--gpxe/src/net/tcpip.c17
-rw-r--r--gpxe/src/net/tls.c4
-rw-r--r--gpxe/src/net/udp.c4
-rw-r--r--gpxe/src/net/udp/dhcp.c419
-rw-r--r--gpxe/src/net/udp/dns.c4
-rw-r--r--gpxe/src/net/udp/slam.c6
-rw-r--r--gpxe/src/net/udp/tftp.c139
-rw-r--r--gpxe/src/proto/fsp.c243
-rw-r--r--gpxe/src/proto/igmp.c167
-rw-r--r--gpxe/src/proto/nfs.c616
-rw-r--r--gpxe/src/proto/nmb.c110
-rw-r--r--gpxe/src/tests/uri_test.c7
-rw-r--r--gpxe/src/usr/autoboot.c64
-rw-r--r--gpxe/src/usr/dhcpmgmt.c23
-rw-r--r--gpxe/src/usr/ifmgmt.c42
-rw-r--r--gpxe/src/usr/imgmgmt.c4
-rw-r--r--gpxe/src/usr/iwmgmt.c244
-rw-r--r--gpxe/src/usr/pxemenu.c4
-rw-r--r--gpxe/src/usr/route.c4
-rw-r--r--gpxe/src/util/.gitignore1
-rwxr-xr-xgpxe/src/util/diffsize.pl101
-rwxr-xr-xgpxe/src/util/dskpad.pl12
-rw-r--r--gpxe/src/util/elf2efi.c7
-rwxr-xr-xgpxe/src/util/geniso5
-rwxr-xr-xgpxe/src/util/genliso51
-rwxr-xr-xgpxe/src/util/gensdsk65
-rw-r--r--gpxe/src/util/iccfix.c156
-rwxr-xr-xgpxe/src/util/licence.pl149
-rwxr-xr-xgpxe/src/util/makerom.pl30
-rwxr-xr-xgpxe/src/util/modrom.pl4
-rwxr-xr-xgpxe/src/util/padimg.pl44
-rw-r--r--gpxe/src/util/parserom.pl3
-rw-r--r--gpxe/src/util/zbin.c144
-rw-r--r--utils/mkdiskimage.in16
695 files changed, 64396 insertions, 9856 deletions
diff --git a/com32/menu/menu.h b/com32/menu/menu.h
index 52b4e4dc..1e596e1d 100644
--- a/com32/menu/menu.h
+++ b/com32/menu/menu.h
@@ -180,6 +180,7 @@ extern struct menu *root_menu, *start_menu, *hide_menu, *menu_list;
/* These are global parameters regardless of which menu we're displaying */
extern int shiftkey;
extern int hiddenmenu;
+extern int clearmenu;
extern long long totaltimeout;
void parse_configs(char **argv);
diff --git a/com32/menu/menumain.c b/com32/menu/menumain.c
index cbeb9a18..0c392646 100644
--- a/com32/menu/menumain.c
+++ b/com32/menu/menumain.c
@@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
- * Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
*
* 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
@@ -616,8 +616,9 @@ static inline int shift_is_held(void)
static void print_timeout_message(int tol, int row, const char *msg)
{
+ static int last_msg_len = 0;
char buf[256];
- int nc = 0, nnc;
+ int nc = 0, nnc, padc;
const char *tp = msg;
char tc;
char *tq = buf;
@@ -686,9 +687,17 @@ static void print_timeout_message(int tol, int row, const char *msg)
}
*tq = '\0';
- /* Let's hope 4 spaces on each side is enough... */
- printf("\033[%d;%dH\2#14 %s ", row,
- HSHIFT + 1 + ((WIDTH - nc - 8) >> 1), buf);
+ if (nc >= last_msg_len) {
+ padc = 0;
+ } else {
+ padc = (last_msg_len - nc + 1) >> 1;
+ }
+
+ printf("\033[%d;%dH\2#14%*s%s%*s", row,
+ HSHIFT + 1 + ((WIDTH - nc) >> 1) - padc,
+ padc, "", buf, padc, "");
+
+ last_msg_len = nc;
}
/* Set the background screen, etc. */
@@ -724,6 +733,9 @@ static const char *do_hidden_menu(void)
}
}
+ /* Clear the message from the screen */
+ print_timeout_message(0, HIDDEN_ROW, "");
+
if (cm->ontimeout)
return cm->ontimeout;
else
@@ -1118,6 +1130,9 @@ int main(int argc, char *argv[])
local_cursor_enable(true);
cmdline = run_menu();
+ if (clearmenu)
+ clear_screen();
+
local_cursor_enable(false);
printf("\033[?25h\033[%d;1H\033[0m", END_ROW);
diff --git a/com32/menu/readconfig.c b/com32/menu/readconfig.c
index a248721e..d4c8848c 100644
--- a/com32/menu/readconfig.c
+++ b/com32/menu/readconfig.c
@@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 2004-2009 H. Peter Anvin - All Rights Reserved
- * Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
*
* 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
@@ -34,6 +34,7 @@ struct menu *root_menu, *start_menu, *hide_menu, *menu_list;
/* These are global parameters regardless of which menu we're displaying */
int shiftkey = 0; /* Only display menu if shift key pressed */
int hiddenmenu = 0;
+int clearmenu = 0;
long long totaltimeout = 0;
/* Keep track of global default */
@@ -690,6 +691,8 @@ static void parse_config_file(FILE * f)
m->menu_background = refdup_word(&p);
} else if ((ep = looking_at(p, "hidden"))) {
hiddenmenu = 1;
+ } else if ((ep = looking_at(p, "clear"))) {
+ clearmenu = 1;
} else if ((ep = is_message_name(p, &msgnr))) {
refstr_put(m->messages[msgnr]);
m->messages[msgnr] = refstrdup(skipspace(ep));
diff --git a/com32/modules/chain.c b/com32/modules/chain.c
index 2dd80746..458ea890 100644
--- a/com32/modules/chain.c
+++ b/com32/modules/chain.c
@@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
- * Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
*
* 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
@@ -394,10 +394,13 @@ static struct part_entry *find_logical_partition(int whichpart, char *table,
/* Adjust the offset to account for the extended partition itself */
ptab[i].start_lba += self->start_lba;
- /* Sanity check entry: must not extend outside the extended partition.
- This is necessary since some OSes put crap in some entries. */
- if (ptab[i].start_lba + ptab[i].length <= self->start_lba ||
- ptab[i].start_lba >= self->start_lba + self->length)
+ /*
+ * Sanity check entry: must not extend outside the
+ * extended partition. This is necessary since some OSes
+ * put crap in some entries. Note that root is non-NULL here.
+ */
+ if (ptab[i].start_lba + ptab[i].length <= root->start_lba ||
+ ptab[i].start_lba >= root->start_lba + root->length)
continue;
/* OK, it's a data partition. Is it the one we're looking for? */
diff --git a/core/kernel.inc b/core/kernel.inc
index 9b888cc8..5e1c7a39 100644
--- a/core/kernel.inc
+++ b/core/kernel.inc
@@ -85,6 +85,8 @@ HEADER_ID equ 'HdrS' ; HdrS (in littleendian hex)
; Flags for the su_loadflags field
;
LOAD_HIGH equ 01h ; Large kernel, load high
+QUIET_FLAG equ 20h ; Quiet the kernel
+KEEP_SEGMENTS equ 40h ; Don't reload segments
CAN_USE_HEAP equ 80h ; Boot loader reports heap size
;
diff --git a/core/ldlinux.asm b/core/ldlinux.asm
index ba7e8040..0808e6e8 100644
--- a/core/ldlinux.asm
+++ b/core/ldlinux.asm
@@ -116,6 +116,7 @@ RootDirSize resd 1 ; Root dir size in sectors
TotalSectors resd 1 ; Total number of sectors
ClustSize resd 1 ; Bytes/cluster
ClustMask resd 1 ; Sectors/cluster - 1
+Clusters resd 1 ; Total number of clusters
CopySuper resb 1 ; Distinguish .bs versus .bss
DriveNumber resb 1 ; BIOS drive number
ClustShift resb 1 ; Shift count for sectors/cluster
@@ -183,24 +184,31 @@ getfattype:
sub eax,[DataArea]
shr eax,cl ; cl == ClustShift
mov cl,nextcluster_fat12-(nextcluster+2)
- cmp eax,4085 ; FAT12 limit
- jb .setsize
+ cmp eax,0xFF4 ; FAT12 limit
+ jbe .setsize
mov cl,nextcluster_fat16-(nextcluster+2)
- cmp eax,65525 ; FAT16 limit
- jb .setsize
+ cmp eax,0xFFF4 ; FAT16 limit
+ jbe .setsize
;
; FAT32, root directory is a cluster chain
;
+ mov ecx,0x0FFFFFF4 ; Max possible cluster count
+ cmp eax,ecx
+ jb .oksize
+ mov eax,ecx
+.oksize:
+
mov cl,[ClustShift]
- mov eax,[bootsec+44] ; Root directory cluster
- sub eax,2
- shl eax,cl
- add eax,[DataArea]
- mov [RootDir],eax
+ mov edx,[bootsec+44] ; Root directory cluster
+ sub edx,2
+ shl edx,cl
+ add edx,[DataArea]
+ mov [RootDir],edx
mov cl,nextcluster_fat28-(nextcluster+2)
mov byte [SuperSize],superblock_len_fat32
.setsize:
mov byte [nextcluster+1],cl
+ mov [Clusters],eax ; Total clusters
;
; Common initialization code
@@ -1242,7 +1250,8 @@ nextcluster_fat12:
shr cx,4
.even: and cx,0FFFh
movzx edi,cx
- cmp di,0FF0h
+ lea ax,[di-2]
+ cmp ax,[Clusters]
pop si
pop cx
pop bx
@@ -1264,7 +1273,8 @@ nextcluster_fat16:
add bx,bx
and bx,1FEh
movzx edi,word [gs:si+bx]
- cmp di,0FFF0h
+ lea ax,[di-2]
+ cmp ax,[Clusters]
pop bx
pop si
pop eax
@@ -1285,7 +1295,8 @@ nextcluster_fat28:
and bx,1FCh
mov edi,dword [gs:si+bx]
and edi,0FFFFFFFh ; 28 bits only
- cmp edi,0FFFFFF0h
+ lea eax,[edi-2]
+ cmp eax,[Clusters]
pop bx
pop si
pop eax
diff --git a/core/pxe.inc b/core/pxe.inc
index 7471c4f0..2fd1edb7 100644
--- a/core/pxe.inc
+++ b/core/pxe.inc
@@ -71,6 +71,7 @@
%define PXENV_GET_FILE_SIZE 0x00e4
%define PXENV_FILE_EXEC 0x00e5
%define PXENV_FILE_API_CHECK 0x00e6
+%define PXENV_FILE_EXIT_HOOK 0x00e7
; Exit codes
%define PXENV_EXIT_SUCCESS 0x0000
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index 651dd4c3..01159f16 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -8,7 +8,7 @@
; MS-DOS floppies.
;
; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-; Copyright 2009 Intel Corporation; author: H. Peter Anvin
+; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
;
; 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
@@ -48,7 +48,7 @@ TFTP_LARGEBLK equ (TFTP_MTU-20-8-4) ; MTU - IP hdr - UDP hdr - TFTP hdr
; Standard TFTP block size
TFTP_BLOCKSIZE_LG2 equ 9 ; log2(bytes/block)
TFTP_BLOCKSIZE equ (1 << TFTP_BLOCKSIZE_LG2)
-%assign USE_PXE_PROVIDED_STACK 1 ; Use stack provided by PXE?
+%assign USE_PXE_PROVIDED_STACK 0 ; Use stack provided by PXE?
SECTOR_SHIFT equ TFTP_BLOCKSIZE_LG2
SECTOR_SIZE equ TFTP_BLOCKSIZE
@@ -217,7 +217,7 @@ packet_buf_size equ $-packet_buf
; PXELINUX needs more BSS than the other derivatives;
; therefore we relocate it from 7C00h on startup.
;
-StackBuf equ $ ; Base of stack if we use our own
+StackBuf equ $-44 ; Base of stack if we use our own
;
; Primary entry point.
@@ -332,80 +332,7 @@ adhcp_copy:
mov si,copyright_str
call writestr_early
-;
-; Look to see if we are on an EFI CSM system. Some EFI
-; CSM systems put the BEV stack in low memory, which means
-; a return to the PXE stack will crash the system. However,
-; INT 18h works reliably, so in that case hack the stack and
-; point the "return address" to an INT 18h instruction.
-;
-; Hack the stack instead of the much simpler "just invoke INT 18h
-; if we want to reset", so that chainloading other NBPs will work.
-;
-efi_csm_workaround:
- les bp,[InitStack] ; GS:SP -> original stack
- les bx,[es:bp+44] ; Return address
- cmp word [es:bx],18CDh ; Already pointing to INT 18h?
- je .skip
- ; Search memory from E0000 to FFFFF for a $EFI structure
- mov bx,0E000h
-.scan_mem:
- mov es,bx
- cmp dword [es:0],'IFE$' ; $EFI is byte-reversed...
- jne .not_here
- ;
- ; Verify the table. We don't check the checksum because
- ; it seems some CSMs leave it at zero.
- ;
- movzx cx,byte [es:5] ; Table length
- cmp cx,83 ; 83 bytes is the current length...
- jae .found_it
-
-.not_here:
- inc bx
- jnz .scan_mem
- jmp .skip ; No $EFI structure found
-
- ;
- ; Found a $EFI structure. Move down the original stack
- ; and put an INT 18h instruction there instead.
- ;
-.found_it:
-%if USE_PXE_PROVIDED_STACK
- mov cx,efi_csm_hack_size
- mov si,sp
- sub sp,cx
- mov di,sp
- mov ax,ss
- mov es,ax
- sub [InitStack],cx
- sub [BaseStack],cx
-%else
- les si,[InitStack]
- lea di,[si-efi_csm_hack_size]
- mov [InitStack],di
-%endif
- lea cx,[bp+52] ; End of the stack we care about
- sub cx,si
- es rep movsb
- mov [es:di-8],di ; Clobber the return address
- mov [es:di-6],es
- mov si,efi_csm_hack
- mov cx,efi_csm_hack_size
- rep movsb
-
-.skip:
-
- section .data
- alignz 4
-efi_csm_hack:
- int 18h
- jmp 0F000h:0FFF0h
- hlt
-efi_csm_hack_size equ $-efi_csm_hack
-
- section .text
;
; Assume API version 2.1, in case we find the !PXE structure without
@@ -751,6 +678,33 @@ udp_init:
.success:
;
+; Check to see if we're using gPXE
+;
+%if GPXE
+ ; If we get here, the gPXE status is unknown.
+ mov di,gpxe_file_api_check
+ mov bx,PXENV_FILE_API_CHECK ; BH = 0
+ call pxenv
+ jc .nogood
+ cmp dword [di+4],0xe9c17b20
+ jne .nogood
+ mov eax,[di+12]
+ mov [GPXEFuncs],eax
+ not ax ; Set bits of *missing* functions...
+ and ax,01001011b ; The functions we care about
+ setz bh
+.nogood:
+ mov [HasGPXE],bh
+
+ section .data
+ alignb 4
+GPXEFuncs dd 0
+HasGPXE db 0
+
+ section .text
+%endif
+
+;
; Common initialization code
;
%include "cpuinit.inc"
@@ -1599,42 +1553,31 @@ is_gpxe:
jc .ret ; Not a URL, don't bother
.again:
cmp byte [HasGPXE],1
- ja .unknown
+ jnb .ret
; CF=1 if not available (0),
; CF=0 if known available (1).
-.ret: ret
-.unknown:
- ; If we get here, the gPXE status is unknown.
- push es
- pushad
- push ds
- pop es
- mov di,gpxe_file_api_check
- mov bx,PXENV_FILE_API_CHECK ; BH = 0
- call pxenv
- jc .nogood
- cmp dword [di+4],0xe9c17b20
- jne .nogood
- mov ax,[di+12] ; Don't care about the upper half...
- not ax ; Set bits of *missing* functions...
- and ax,01001011b ; The functions we care about
- setz bh
- jz .done
-.nogood:
+ inc word [GPXEWarningCtr]
+ jnz .skip
+
+ push si
mov si,gpxe_warning_msg
- call writestr_early
-.done:
- mov [HasGPXE],bh
- popad
- pop es
- jmp .again
+ call writestr
+ pop si
+.skip:
+ stc
+
+.ret: ret
+
section .data
+ alignz 2
+GPXEWarningCtr:
+ dw -1 ; Print msg when it goes to 0
gpxe_warning_msg:
db 'URL syntax, but gPXE extensions not detected, '
db 'trying plain TFTP...', CR, LF, 0
-HasGPXE db -1 ; Unknown
+
section .text
%endif
@@ -2152,10 +2095,11 @@ get_packet_gpxe:
; This function unloads the PXE and UNDI stacks and unclaims
; the memory.
;
-unload_pxe:
- cmp byte [KeepPXE],0 ; Should we keep PXE around?
- jne reset_pxe
+reset_pxe:
+ or byte [KeepPXE],1
+ ; Fall through
+unload_pxe:
push ds
push es
@@ -2163,6 +2107,9 @@ unload_pxe:
mov ds,ax
mov es,ax
+ cmp byte [KeepPXE],0 ; Should we keep PXE around?
+ jne do_reset_pxe
+
mov si,new_api_unload
cmp byte [APIVer+1],2 ; Major API version >= 2?
jae .new_api
@@ -2233,16 +2180,168 @@ unload_pxe:
; We want to keep PXE around, but still we should reset
; it to the standard bootup configuration
-reset_pxe:
- push es
- push cs
- pop es
+do_reset_pxe:
+ TRACER 'A'
+
mov bx,PXENV_UDP_CLOSE
mov di,pxe_udp_close_pkt
call pxenv
+
+ TRACER 'B'
+
+%if GPXE
+ test byte [GPXEFuncs],80h ; gPXE special unload?
+ jz .plain
+
+ TRACER 'C'
+
+ mov bx,PXENV_FILE_EXIT_HOOK
+ mov di,pxe_file_exit_hook
+ call pxenv
+ jc .plain
+
+ TRACER 'D'
+
+ ; Now we actually need to exit back to gPXE, which will
+ ; give control back to us on the *new* "original stack"...
+ pushfd
+ pushad
+ push ds
+ push fs
+ push gs
+ mov [PXEStack],sp
+ mov [PXEStack+2],ss
+ lss sp,[InitStack]
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ popad
+ popfd
+ xor ax,ax
+ retf
+.resume:
+ cli
+
+ TRACER 'E'
+
+ ; gPXE will have a stack frame looking much like our
+ ; InitStack, except it has a magic cookie at the top,
+ ; and the segment registers are in reverse order.
+ pop eax
+ pop ax
+ pop bx
+ pop cx
+ pop dx
+ push ax
+ push bx
+ push cx
+ push dx
+ mov [cs:InitStack],sp
+ mov [cs:InitStack+2],ss
+ lss sp,[cs:PXEStack]
+ pop gs
+ pop fs
+ pop ds
+ popad
+ popfd
+%endif ; GPXE
+
+.plain:
+ TRACER 'F'
+
+;
+; Look to see if we are on an EFI CSM system. Some EFI
+; CSM systems put the BEV stack in low memory, which means
+; a return to the PXE stack will crash the system. However,
+; INT 18h works reliably, so in that case hack the stack and
+; point the "return address" to an INT 18h instruction.
+;
+; Hack the stack instead of the much simpler "just invoke INT 18h
+; if we want to reset", so that chainloading other NBPs will work.
+;
+efi_csm_workaround:
+ les bp,[InitStack] ; ES:BP -> original stack
+ les bx,[es:bp+44] ; ES:BX -> Return address
+ cmp word [es:bx],18CDh ; Already pointing to INT 18h?
+ je .skip
+
+ ; Search memory from E0000 to FFFFF for a $EFI structure
+ mov bx,0E000h
+.scan_mem:
+ mov es,bx
+ cmp dword [es:0],'IFE$' ; $EFI is byte-reversed...
+ jne .not_here
+ ;
+ ; Verify the table. We don't check the checksum because
+ ; it seems some CSMs leave it at zero.
+ ;
+ movzx cx,byte [es:5] ; Table length
+ cmp cx,83 ; 83 bytes is the current length...
+ jae .found_it
+
+.not_here:
+ inc bx
+ jnz .scan_mem
+ jmp .skip ; No $EFI structure found
+
+ ;
+ ; Found a $EFI structure. Move down the original stack
+ ; and put an INT 18h instruction there instead.
+ ;
+.found_it:
+%if USE_PXE_PROVIDED_STACK
+ mov cx,efi_csm_hack_size
+ mov si,sp
+ sub sp,cx
+ mov di,sp
+ mov ax,ss
+ mov es,ax
+ sub [InitStack],cx
+ sub [BaseStack],cx
+%else
+ les si,[InitStack]
+ lea di,[si-efi_csm_hack_size]
+ mov [InitStack],di
+%endif
+ lea cx,[bp+52] ; End of the stack we care about
+ sub cx,si
+ es rep movsb
+ mov [es:di-8],di ; Clobber the return address
+ mov [es:di-6],es
+ mov si,efi_csm_hack
+ mov cx,efi_csm_hack_size
+ rep movsb
+
+.skip:
+ TRACER 'G'
+
+.done:
pop es
+ pop ds
ret
+
+ section .data
+ alignz 4
+efi_csm_hack:
+ int 18h
+ jmp 0F000h:0FFF0h
+ hlt
+efi_csm_hack_size equ $-efi_csm_hack
+
+
+
+%if GPXE
+ alignz 4
+pxe_file_exit_hook:
+.status: dw 0
+.offset: dw do_reset_pxe.resume
+.seg: dw 0
+%endif
+
+ section .text
+
;
; gendotquad
;
diff --git a/core/runkernel.inc b/core/runkernel.inc
index f6ede382..e738706f 100644
--- a/core/runkernel.inc
+++ b/core/runkernel.inc
@@ -1,7 +1,7 @@
;; -----------------------------------------------------------------------
;;
;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
+;; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
;;
;; 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
@@ -140,16 +140,16 @@ parse_cmdline:
opt_vga:
mov ax,[es:di-1]
mov bx,-1
- cmp ax,'=nor' ; vga=normal
+ cmp ax,'=n' ; vga=normal
je .vc0
dec bx ; bx <- -2
- cmp ax,'=ext' ; vga=ext
+ cmp ax,'=e' ; vga=ext
je .vc0
dec bx ; bx <- -3
- cmp ax,'=ask' ; vga=ask
+ cmp ax,'=a' ; vga=ask
je .vc0
mov bx,0x0f04 ; bx <- 0x0f04 (current mode)
- cmp ax,'=cur' ; vga=current
+ cmp ax,'=c' ; vga=current
je .vc0
call parseint_esdi ; vga=<number>
jc .skip ; Not an integer
@@ -168,7 +168,7 @@ opt_mem:
ret
opt_quiet:
- mov byte [QuietBoot],1
+ mov byte [QuietBoot],QUIET_FLAG
ret
%if IS_PXELINUX
@@ -228,6 +228,8 @@ new_kernel:
; we were provided.
;
mov al,[es:su_loadflags]
+ or al,[QuietBoot] ; Set QUIET_FLAG if needed
+ mov [es:su_loadflags],al
mov [LoadFlags],al
any_kernel:
@@ -458,7 +460,7 @@ setup_move:
; BX points to the final real mode segment, and will be loaded
; into DS.
- test byte [QuietBoot],01h ; Don't clear the mode if quiet
+ test byte [QuietBoot],QUIET_FLAG
jz replace_bootstrap
jmp replace_bootstrap_noclearmode
@@ -631,7 +633,7 @@ loadinitrd:
; assumes CS == DS
;
writestr_qchk:
- test byte [QuietBoot],01h
+ test byte [QuietBoot],QUIET_FLAG
jz writestr
ret
diff --git a/doc/menu.txt b/doc/menu.txt
index e1601249..c912c1df 100644
--- a/doc/menu.txt
+++ b/doc/menu.txt
@@ -48,6 +48,14 @@ MENU HIDDEN
All that is displayed is a timeout message.
+MENU CLEAR
+
+ Clear the screen when exiting the menu, instead of leaving the
+ menu displayed. For vesamenu, this means the graphical
+ background is still displayed without the menu itself for as
+ long as the screen remains in graphics mode.
+
+
MENU SHIFTKEY
Exit the menu system immediately unless either the Shift or Alt
diff --git a/gpxe/gpxe.diff b/gpxe/gpxe.diff
new file mode 100644
index 00000000..3df08a21
--- /dev/null
+++ b/gpxe/gpxe.diff
@@ -0,0 +1,15 @@
+diff --git a/gpxe/src/config/general.h b/gpxe/src/config/general.h
+index 0a9e625..de51f9f 100644
+--- a/gpxe/src/config/general.h
++++ b/gpxe/src/config/general.h
+@@ -55,8 +55,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
+
+ #define DOWNLOAD_PROTO_TFTP /* Trivial File Transfer Protocol */
+ #define DOWNLOAD_PROTO_HTTP /* Hypertext Transfer Protocol */
+-#undef DOWNLOAD_PROTO_HTTPS /* Secure Hypertext Transfer Protocol */
+-#undef DOWNLOAD_PROTO_FTP /* File Transfer Protocol */
++#define DOWNLOAD_PROTO_HTTPS /* Secure Hypertext Transfer Protocol */
++#define DOWNLOAD_PROTO_FTP /* File Transfer Protocol */
+ #undef DOWNLOAD_PROTO_TFTM /* Multicast Trivial File Transfer Protocol */
+ #undef DOWNLOAD_PROTO_SLAM /* Scalable Local Area Multicast */
+
diff --git a/gpxe/pxelinux.gpxe b/gpxe/pxelinux.gpxe
index 51fe222e..c267d136 100644
--- a/gpxe/pxelinux.gpxe
+++ b/gpxe/pxelinux.gpxe
@@ -1,4 +1,5 @@
#!gpxe
+set use-cached 1
dhcp net0
imgload pxelinux.0
boot pxelinux.0
diff --git a/gpxe/src/Makefile b/gpxe/src/Makefile
index a627d967..cc91d78f 100644
--- a/gpxe/src/Makefile
+++ b/gpxe/src/Makefile
@@ -22,7 +22,7 @@ ECHO := echo
PRINTF := printf
PERL := /usr/bin/perl
CC := $(CROSS_COMPILE)gcc
-CPP := $(CROSS_COMPILE)gcc -E -Wp,-Wall
+CPP := $(CC) -E
AS := $(CROSS_COMPILE)as
LD := $(CROSS_COMPILE)ld
SIZE := $(CROSS_COMPILE)size
@@ -35,12 +35,17 @@ 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
+LICENCE := $(PERL) ./util/licence.pl
NRV2B := ./util/nrv2b
ZBIN := ./util/zbin
ELF2EFI32 := ./util/elf2efi32
ELF2EFI64 := ./util/elf2efi64
EFIROM := ./util/efirom
+ICCFIX := ./util/iccfix
DOXYGEN := doxygen
+BINUTILS_DIR := /usr
+BFD_DIR := $(BINUTILS_DIR)
###############################################################################
#
@@ -49,13 +54,14 @@ DOXYGEN := doxygen
SRCDIRS :=
SRCDIRS += libgcc
SRCDIRS += core
-SRCDIRS += proto
-SRCDIRS += net net/tcp net/udp
+SRCDIRS += net net/tcp net/udp net/infiniband net/80211
SRCDIRS += image
SRCDIRS += drivers/bus
SRCDIRS += drivers/net
SRCDIRS += drivers/net/e1000
SRCDIRS += drivers/net/phantom
+SRCDIRS += drivers/net/rtl818x
+SRCDIRS += drivers/net/ath5k
SRCDIRS += drivers/block
SRCDIRS += drivers/nvs
SRCDIRS += drivers/bitbash
@@ -66,6 +72,7 @@ SRCDIRS += crypto crypto/axtls crypto/matrixssl
SRCDIRS += hci hci/commands hci/tui
SRCDIRS += hci/mucurses hci/mucurses/widgets
SRCDIRS += usr
+SRCDIRS += config
# NON_AUTO_SRCS lists files that are excluded from the normal
# automatic build system.
@@ -73,6 +80,11 @@ SRCDIRS += usr
NON_AUTO_SRCS :=
NON_AUTO_SRCS += drivers/net/prism2.c
+# INCDIRS lists the include path
+#
+INCDIRS :=
+INCDIRS += include .
+
###############################################################################
#
# Default build target: build the most common targets and print out a
@@ -115,9 +127,9 @@ install :
#
# Version number calculations
#
-VERSION_MAJOR = 0
-VERSION_MINOR = 9
-VERSION_PATCH = 7
+VERSION_MAJOR = 1
+VERSION_MINOR = 0
+VERSION_PATCH = 0
EXTRAVERSION =
MM_VERSION = $(VERSION_MAJOR).$(VERSION_MINOR)
VERSION = $(MM_VERSION).$(VERSION_PATCH)$(EXTRAVERSION)
diff --git a/gpxe/src/Makefile.housekeeping b/gpxe/src/Makefile.housekeeping
index 2ab842e6..1f5e115f 100644
--- a/gpxe/src/Makefile.housekeeping
+++ b/gpxe/src/Makefile.housekeeping
@@ -54,6 +54,14 @@ echo :
###############################################################################
#
+# Generate a usable "seq" substitute
+#
+define seq
+ $(shell awk 'BEGIN { for ( i = $(1) ; i <= $(2) ; i++ ) print i }')
+endef
+
+###############################################################################
+#
# Determine host OS
#
HOST_OS := $(shell uname -s)
@@ -62,6 +70,22 @@ hostos :
###############################################################################
#
+# Determine compiler
+
+CCDEFS := $(shell $(CC) -E -x c -c /dev/null -dM | cut -d" " -f2)
+ccdefs:
+ @$(ECHO) $(CCDEFS)
+
+ifeq ($(filter __ICC,$(CCDEFS)),__ICC)
+CCTYPE := icc
+else
+CCTYPE := gcc
+endif
+cctype:
+ @$(ECHO) $(CCTYPE)
+
+###############################################################################
+#
# Check for tools that can cause failed builds
#
.toolcheck :
@@ -103,10 +127,30 @@ oldgas :
# default, even when -ffreestanding is specified. We therefore need
# to disable -fstack-protector if the compiler supports it.
#
+ifeq ($(CCTYPE),gcc)
SP_TEST = $(CC) -fno-stack-protector -x c -c /dev/null \
-o /dev/null >/dev/null 2>&1
SP_FLAGS := $(shell $(SP_TEST) && $(ECHO) '-fno-stack-protector')
CFLAGS += $(SP_FLAGS)
+endif
+
+# gcc 4.4 generates .eh_frame sections by default, which distort the
+# output of "size". Inhibit this.
+#
+ifeq ($(CCTYPE),gcc)
+CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -x c -c /dev/null \
+ -o /dev/null >/dev/null 2>&1
+CFI_FLAGS := $(shell $(CFI_TEST) && $(ECHO) '-fno-dwarf2-cfi-asm')
+CFLAGS += $(CFI_FLAGS)
+endif
+
+# Some versions of gas choke on division operators, treating them as
+# comment markers. Specifying --divide will work around this problem,
+# but isn't available on older gas versions.
+#
+DIVIDE_TEST = $(AS) --divide /dev/null -o /dev/null 2>/dev/null
+DIVIDE_FLAGS := $(shell $(DIVIDE_TEST) && $(ECHO) '--divide')
+ASFLAGS += $(DIVIDE_FLAGS)
###############################################################################
#
@@ -248,6 +292,11 @@ MAKEDEPS += arch/$(ARCH)/Makefile
include arch/$(ARCH)/Makefile
endif
+# Include architecture-specific include path
+ifdef ARCH
+INCDIRS += arch/$(ARCH)/include
+endif
+
###############################################################################
#
# Source file handling
@@ -276,12 +325,45 @@ autosrcs :
ifdef BIN
+# INCDIRS lists the include path
+incdirs :
+ @$(ECHO) $(INCDIRS)
+
# Common flags
#
-CFLAGS += -I include -I arch/$(ARCH)/include -I .
-CFLAGS += -Os -ffreestanding
-CFLAGS += -Wall -W -Wformat-nonliteral
+CFLAGS += $(foreach INC,$(INCDIRS),-I$(INC))
+CFLAGS += -Os
CFLAGS += -g
+ifeq ($(CCTYPE),gcc)
+CFLAGS += -ffreestanding
+CFLAGS += -Wall -W -Wformat-nonliteral
+endif
+ifeq ($(CCTYPE),icc)
+CFLAGS += -fno-builtin
+CFLAGS += -no-ip
+CFLAGS += -no-gcc
+CFLAGS += -diag-disable 111 # Unreachable code
+CFLAGS += -diag-disable 128 # Unreachable loop
+CFLAGS += -diag-disable 170 # Array boundary checks
+CFLAGS += -diag-disable 177 # Unused functions
+CFLAGS += -diag-disable 181 # printf() format checks
+CFLAGS += -diag-disable 188 # enum strictness
+CFLAGS += -diag-disable 193 # Undefined preprocessor identifiers
+CFLAGS += -diag-disable 280 # switch ( constant )
+CFLAGS += -diag-disable 310 # K&R parameter lists
+CFLAGS += -diag-disable 424 # Extra semicolon
+CFLAGS += -diag-disable 589 # Declarations mid-code
+CFLAGS += -diag-disable 593 # Unused variables
+CFLAGS += -diag-disable 810 # Casting ints to smaller ints
+CFLAGS += -diag-disable 981 # Sequence point violations
+CFLAGS += -diag-disable 1292 # Ignored attributes
+CFLAGS += -diag-disable 1338 # void pointer arithmetic
+CFLAGS += -diag-disable 1361 # Variable-length arrays
+CFLAGS += -diag-disable 1418 # Missing prototypes
+CFLAGS += -diag-disable 1419 # Missing prototypes
+CFLAGS += -diag-disable 1599 # Hidden variables
+CFLAGS += -Wall -Wmissing-declarations
+endif
CFLAGS += $(EXTRA_CFLAGS)
ASFLAGS += $(EXTRA_ASFLAGS)
LDFLAGS += $(EXTRA_LDFLAGS)
@@ -314,11 +396,21 @@ OBJ_CFLAGS = $(CFLAGS_$(OBJECT)) -DOBJECT=$(subst -,_,$(OBJECT))
$(BIN)/%.flags :
@$(ECHO) $(OBJ_CFLAGS)
+# ICC requires postprocessing objects to fix up table alignments
+#
+ifeq ($(CCTYPE),icc)
+POST_O = && $(ICCFIX) $@
+POST_O_DEPS := $(ICCFIX)
+else
+POST_O :=
+POST_O_DEPS :=
+endif
+
# Rules for specific object types.
#
COMPILE_c = $(CC) $(CFLAGS) $(CFLAGS_c) $(OBJ_CFLAGS)
-RULE_c = $(Q)$(COMPILE_c) -c $< -o $@
-RULE_c_to_dbg%.o = $(Q)$(COMPILE_c) -Ddebug_$(OBJECT)=$* -c $< -o $@
+RULE_c = $(Q)$(COMPILE_c) -c $< -o $@ $(POST_O)
+RULE_c_to_dbg%.o = $(Q)$(COMPILE_c) -Ddebug_$(subst -,_,$(OBJECT))=$* -c $< -o $@ $(POST_O)
RULE_c_to_c = $(Q)$(COMPILE_c) -E -c $< > $@
RULE_c_to_s = $(Q)$(COMPILE_c) -S -g0 -c $< -o $@
@@ -346,39 +438,25 @@ 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) -MT "$(4)_DEPS" -MG -MP | \
- sed 's/_DEPS\s*:/_DEPS =/' >> $(2)
- @$(ECHO_E) '\n$$(BIN)/$(4).o : $(1) $$(MAKEDEPS) $$($(4)_DEPS)' \
+ -Wno-error -MM $(1) -MG -MP | \
+ sed 's/\.o\s*:/_DEPS =/' >> $(2)
+ @$(ECHO_E) '\n$$(BIN)/$(4).o :' \
+ '$(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(4)_DEPS)' \
'\n\t$$(QM)$(ECHO) " [BUILD] $$@"' \
'\n\t$$(RULE_$(3))\n' \
'\nBOBJS += $$(BIN)/$(4).o\n' \
$(foreach TGT,$(DEBUG_TARGETS), \
$(if $(RULE_$(3)_to_$(TGT)), \
- '\n$$(BIN)/$(4).$(TGT) : $(1) $$(MAKEDEPS) $$($(4)_DEPS)' \
+ '\n$$(BIN)/$(4).$(TGT) :' \
+ '$(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(4)_DEPS)' \
'\n\t$$(QM)$(ECHO) " [BUILD] $$@"' \
'\n\t$$(RULE_$(3)_to_$(TGT))\n' \
'\n$(TGT)_OBJS += $$(BIN)/$(4).$(TGT)\n' ) ) \
'\n$(2) : $$($(4)_DEPS)\n' \
'\nTAGS : $$($(4)_DEPS)\n' \
>> $(2)
+ @$(PARSEROM) $(1) >> $(2)
endef
@@ -415,7 +493,7 @@ roms :
#
EMBEDDED_LIST := $(BIN)/.embedded.list
ifeq ($(wildcard $(EMBEDDED_LIST)),)
-EMBEDDED_LIST_IMAGE :=
+EMBEDDED_LIST_IMAGE := <invalid>
else
EMBEDDED_LIST_IMAGE := $(shell cat $(EMBEDDED_LIST))
endif
@@ -428,7 +506,7 @@ $(EMBEDDED_LIST) :
VERYCLEANUP += $(EMBEDDED_LIST)
EMBEDDED_FILES := $(subst $(COMMA), ,$(EMBEDDED_IMAGE))
-EMBED_ALL := $(foreach i,$(shell seq 1 $(words $(EMBEDDED_FILES))),\
+EMBED_ALL := $(foreach i,$(call seq,1,$(words $(EMBEDDED_FILES))),\
EMBED ( $(i), \"$(word $(i), $(EMBEDDED_FILES))\",\
\"$(notdir $(word $(i),$(EMBEDDED_FILES)))\" ))
@@ -550,7 +628,7 @@ $(BIN)/%.info :
#
BLIB_LIST := $(BIN)/.blib.list
ifeq ($(wildcard $(BLIB_LIST)),)
-BLIB_LIST_OBJS :=
+BLIB_LIST_OBJS := <invalid>
else
BLIB_LIST_OBJS := $(shell cat $(BLIB_LIST))
endif
@@ -589,6 +667,55 @@ $(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,$<),$(wildcard $(BIN)/$(subst _,?,$(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,$(1)),\
+ $(foreach BOBJ,$(BOBJS),\
+ $($(basename $(notdir $(BOBJ)))_DEPS))))
+endef
+$(BIN)/%.nodeps : $(BIN)/%.tmp
+ $(Q)$(ECHO) $(call nodeps_list,$<)
+
+# Get licensing verdict for the specified target
+#
+define unlicensed_deps_list
+ $(shell grep -L FILE_LICENCE $(call deps_list,$(1)))
+endef
+define licence_list
+ $(patsubst __licence_%,%,\
+ $(filter __licence_%,$(shell $(NM) $(1) | cut -d" " -f3)))
+endef
+$(BIN)/%.licence : $(BIN)/%.tmp
+ $(QM)$(ECHO) " [LICENCE] $@"
+ $(Q)$(if $(strip $(call unlicensed_deps_list,$<)),\
+ echo -n "Unable to determine licence because the following " ;\
+ echo "files are missing a licence declaration:" ;\
+ echo $(call unlicensed_deps_list,$<);\
+ exit 1,\
+ $(LICENCE) $(call licence_list,$<))
+
# Extract compression information from intermediate object file
#
$(BIN)/%.zinfo : $(BIN)/%.tmp
@@ -649,6 +776,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)
@@ -702,6 +830,9 @@ endif # defined(BIN)
#
FINALISE_rom = $(MAKEROM) $(MAKEROM_FLAGS) $(TGT_MAKEROM_FLAGS) \
-i$(IDENT) -s 0 $@
+FINALISE_hrom = $(FINALISE_rom)
+FINALISE_xrom = $(MAKEROM) $(MAKEROM_FLAGS) $(TGT_MAKEROM_FLAGS) \
+ -i$(IDENT) -n -s 0 $@
# Some ROMs require specific flags to be passed to makerom.pl
#
@@ -726,16 +857,18 @@ CLEANUP += $(ZBIN)
#
# The EFI image converter
#
+ELF2EFI_CFLAGS := -I$(BINUTILS_DIR)/include -I$(BFD_DIR)/include \
+ -idirafter include -L$(BINUTILS_DIR)/lib -L$(BFD_DIR)/lib \
+ -lbfd -liberty -lz
+
$(ELF2EFI32) : util/elf2efi.c $(MAKEDEPS)
$(QM)$(ECHO) " [HOSTCC] $@"
- $(Q)$(HOST_CC) -DMDE_CPU_IA32 -idirafter include -O2 \
- -o $@ $< -lbfd -liberty
+ $(Q)$(HOST_CC) $(ELF2EFI_CFLAGS) -DMDE_CPU_IA32 -O2 -o $@ $<
CLEANUP += $(ELF2EFI32)
$(ELF2EFI64) : util/elf2efi.c $(MAKEDEPS)
$(QM)$(ECHO) " [HOSTCC] $@"
- $(Q)$(HOST_CC) -DMDE_CPU_X64 -idirafter include -O2 \
- -o $@ $< -lbfd -liberty
+ $(Q)$(HOST_CC) $(ELF2EFI_CFLAGS) -DMDE_CPU_X64 -O2 -o $@ $<
CLEANUP += $(ELF2EFI64)
$(EFIROM) : util/efirom.c $(MAKEDEPS)
@@ -745,6 +878,15 @@ CLEANUP += $(EFIROM)
###############################################################################
#
+# The ICC fixup utility
+#
+$(ICCFIX) : util/iccfix.c $(MAKEDEPS)
+ $(QM)$(ECHO) " [HOSTCC] $@"
+ $(Q)$(HOST_CC) -idirafter include -O2 -o $@ $<
+CLEANUP += $(ICCFIX)
+
+###############################################################################
+#
# Auto-incrementing build serial number. Append "bs" to your list of
# build targets to get a serial number printed at the end of the
# build. Enable -DBUILD_SERIAL in order to see it when the code runs.
@@ -823,20 +965,24 @@ endif # defined(BIN)
ifdef BIN
$(BIN)/doxygen.cfg : doxygen.cfg $(MAKEDEPS)
- $(PERL) -pe 's{\@SRCDIRS\@}{$(SRCDIRS)}; ' \
+ $(Q)$(PERL) -pe 's{\@SRCDIRS\@}{$(SRCDIRS)}; ' \
+ -e 's{\@INCDIRS\@}{$(filter-out .,$(INCDIRS))}; ' \
-e 's{\@BIN\@}{$(BIN)}; ' \
-e 's{\@ARCH\@}{$(ARCH)}; ' \
$< > $@
$(BIN)/doc : $(BIN)/doxygen.cfg
- $(DOXYGEN) $<
+ $(Q)$(DOXYGEN) $<
.PHONY : $(BIN)/doc
-VERYCLEANUP += $(BIN)/doc
-
doc : $(BIN)/doc
+doc-clean :
+ $(Q)$(RM) -r $(BIN)/doc
+
+VERYCLEANUP += $(BIN)/doc
+
docview :
@[ -f $(BIN)/doc/html/index.html ] || $(MAKE) $(BIN)/doc
@if [ -n "$$BROWSER" ] ; then \
diff --git a/gpxe/src/README.pixify b/gpxe/src/README.pixify
deleted file mode 100644
index 9aef25d9..00000000
--- a/gpxe/src/README.pixify
+++ /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.
diff --git a/gpxe/src/arch/i386/Makefile b/gpxe/src/arch/i386/Makefile
index 1392bbac..dd8da802 100644
--- a/gpxe/src/arch/i386/Makefile
+++ b/gpxe/src/arch/i386/Makefile
@@ -4,22 +4,33 @@ CFLAGS += -march=i386
# Code size reduction.
#
-CFLAGS += -fstrength-reduce -fomit-frame-pointer
+CFLAGS += -fomit-frame-pointer
+
+# Code size reduction.
+#
+ifeq ($(CCTYPE),gcc)
+CFLAGS += -fstrength-reduce
+endif
# Code size reduction. gcc3 needs a different syntax to gcc2 if you
# want to avoid spurious warnings.
#
+ifeq ($(CCTYPE),gcc)
GCC_VERSION := $(subst ., ,$(shell $(CC) -dumpversion))
GCC_MAJOR := $(firstword $(GCC_VERSION))
ifeq ($(GCC_MAJOR),2)
CFLAGS += -malign-jumps=1 -malign-loops=1 -malign-functions=1
else
CFLAGS += -falign-jumps=1 -falign-loops=1 -falign-functions=1
-endif
+endif # gcc2
+endif # gcc
-# Code size reduction. This is almost always a win. The kernel uses it, too.
+# Code size reduction. This is almost always a win. The kernel uses
+# it, too.
#
+ifeq ($(CCTYPE),gcc)
CFLAGS += -mpreferred-stack-boundary=2
+endif
# Code size reduction. Use regparm for all functions - C functions
# called from assembly (or vice versa) need __asmcall now
@@ -27,7 +38,9 @@ CFLAGS += -mpreferred-stack-boundary=2
CFLAGS += -mregparm=3
# Code size reduction. Use -mrtd (same __asmcall requirements as above)
+ifeq ($(CCTYPE),gcc)
CFLAGS += -mrtd
+endif
# Code size reduction. This is the logical complement to -mregparm=3.
# It doesn't currently buy us anything, but if anything ever tries to
@@ -67,7 +80,9 @@ SRCDIRS += arch/i386/drivers
SRCDIRS += arch/i386/drivers/net
SRCDIRS += arch/i386/interface/pcbios
SRCDIRS += arch/i386/interface/pxe
+SRCDIRS += arch/i386/interface/pxeparent
SRCDIRS += arch/i386/interface/syslinux
+SRCDIRS += arch/i386/hci/commands
# The various xxx_loader.c files are #included into core/loader.c and
# should not be compiled directly.
@@ -76,11 +91,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
@@ -101,13 +111,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"
#
diff --git a/gpxe/src/arch/i386/Makefile.pcbios b/gpxe/src/arch/i386/Makefile.pcbios
index 64b3dac2..e38fbca0 100644
--- a/gpxe/src/arch/i386/Makefile.pcbios
+++ b/gpxe/src/arch/i386/Makefile.pcbios
@@ -11,21 +11,24 @@ LDFLAGS += -N --no-check-sections
# Media types.
#
MEDIA += rom
+MEDIA += hrom
+MEDIA += xrom
MEDIA += pxe
MEDIA += kpxe
MEDIA += kkpxe
-MEDIA += elf
-MEDIA += elfd
-MEDIA += lmelf
-MEDIA += lmelfd
MEDIA += lkrn
-MEDIA += bImage
MEDIA += dsk
MEDIA += nbi
MEDIA += hd
MEDIA += raw
-MEDIA += com
-MEDIA += exe
+
+# Padding rules
+#
+PAD_rom = $(PADIMG) --blksize=512 --byte=0xff $@
+PAD_hrom = $(PAD_rom)
+PAD_xrom = $(PAD_rom)
+PAD_dsk = $(PADIMG) --blksize=512 $@
+PAD_hd = $(PADIMG) --blksize=32768 $@
# rule to make a non-emulation ISO boot image
NON_AUTO_MEDIA += iso
@@ -39,6 +42,12 @@ NON_AUTO_MEDIA += liso
$(QM)$(ECHO) " [GENLISO] $@"
$(Q)bash util/genliso $@ $<
+# rule to make a syslinux floppy image (mountable, bootable)
+NON_AUTO_MEDIA += sdsk
+%sdsk: %lkrn util/gensdsk
+ $(QM)$(ECHO) " [GENSDSK] $@"
+ $(Q)bash util/gensdsk $@ $<
+
# Special target for building Master Boot Record binary
$(BIN)/mbr.bin : $(BIN)/mbr.o
$(QM)$(ECHO) " [OBJCOPY] $@"
@@ -53,3 +62,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/gpxe/src/arch/i386/core/basemem_packet.c b/gpxe/src/arch/i386/core/basemem_packet.c
index 64e0bcc1..d487cce3 100644
--- a/gpxe/src/arch/i386/core/basemem_packet.c
+++ b/gpxe/src/arch/i386/core/basemem_packet.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
diff --git a/gpxe/src/arch/i386/core/etherboot.prefix.lds b/gpxe/src/arch/i386/core/etherboot.prefix.lds
deleted file mode 100644
index 3550a2a3..00000000
--- a/gpxe/src/arch/i386/core/etherboot.prefix.lds
+++ /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/gpxe/src/arch/i386/core/pic8259.c b/gpxe/src/arch/i386/core/pic8259.c
index 8a0433dd..1e2d23c5 100644
--- a/gpxe/src/arch/i386/core/pic8259.c
+++ b/gpxe/src/arch/i386/core/pic8259.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/io.h>
#include <pic8259.h>
diff --git a/gpxe/src/arch/i386/core/prefixudata.lds b/gpxe/src/arch/i386/core/prefixudata.lds
deleted file mode 100644
index 1c76128e..00000000
--- a/gpxe/src/arch/i386/core/prefixudata.lds
+++ /dev/null
@@ -1,8 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-
-SECTIONS {
- .prefix.udata : {
- *(*)
- }
-}
diff --git a/gpxe/src/arch/i386/core/prefixzdata.lds b/gpxe/src/arch/i386/core/prefixzdata.lds
deleted file mode 100644
index bf6ea977..00000000
--- a/gpxe/src/arch/i386/core/prefixzdata.lds
+++ /dev/null
@@ -1,8 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-
-SECTIONS {
- .prefix.zdata : {
- *(*)
- }
-}
diff --git a/gpxe/src/arch/i386/core/rdtsc_timer.c b/gpxe/src/arch/i386/core/rdtsc_timer.c
index 443c8ada..76679173 100644
--- a/gpxe/src/arch/i386/core/rdtsc_timer.c
+++ b/gpxe/src/arch/i386/core/rdtsc_timer.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/** @file
*
* RDTSC timer
diff --git a/gpxe/src/arch/i386/core/realmode.c b/gpxe/src/arch/i386/core/realmode.c
deleted file mode 100644
index 9a77bd8a..00000000
--- a/gpxe/src/arch/i386/core/realmode.c
+++ /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/gpxe/src/arch/i386/core/relocate.c b/gpxe/src/arch/i386/core/relocate.c
index bdc8498e..44e764fe 100644
--- a/gpxe/src/arch/i386/core/relocate.c
+++ b/gpxe/src/arch/i386/core/relocate.c
@@ -9,6 +9,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/*
* The linker passes in the symbol _max_align, which is the alignment
* that we must preserve, in bytes.
diff --git a/gpxe/src/arch/i386/core/setjmp.S b/gpxe/src/arch/i386/core/setjmp.S
index 59a1b7cb..03727148 100644
--- a/gpxe/src/arch/i386/core/setjmp.S
+++ b/gpxe/src/arch/i386/core/setjmp.S
@@ -1,5 +1,7 @@
/* setjmp and longjmp. Use of these functions is deprecated. */
+FILE_LICENCE ( GPL2_OR_LATER )
+
.text
.arch i386
.code32
diff --git a/gpxe/src/arch/i386/core/stack.S b/gpxe/src/arch/i386/core/stack.S
index da66d239..737ec0ee 100644
--- a/gpxe/src/arch/i386/core/stack.S
+++ b/gpxe/src/arch/i386/core/stack.S
@@ -1,3 +1,5 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
.arch i386
/****************************************************************************
diff --git a/gpxe/src/arch/i386/core/stack16.S b/gpxe/src/arch/i386/core/stack16.S
index d1251f06..523f0288 100644
--- a/gpxe/src/arch/i386/core/stack16.S
+++ b/gpxe/src/arch/i386/core/stack16.S
@@ -1,3 +1,5 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
.arch i386
/****************************************************************************
diff --git a/gpxe/src/arch/i386/core/start16.lds b/gpxe/src/arch/i386/core/start16.lds
deleted file mode 100644
index 544fc78f..00000000
--- a/gpxe/src/arch/i386/core/start16.lds
+++ /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/gpxe/src/arch/i386/core/start16z.lds b/gpxe/src/arch/i386/core/start16z.lds
deleted file mode 100644
index 711bcf7b..00000000
--- a/gpxe/src/arch/i386/core/start16z.lds
+++ /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 );
-}
-
diff --git a/gpxe/src/arch/i386/core/timer2.c b/gpxe/src/arch/i386/core/timer2.c
index bb589ecc..6e76b2eb 100644
--- a/gpxe/src/arch/i386/core/timer2.c
+++ b/gpxe/src/arch/i386/core/timer2.c
@@ -11,6 +11,8 @@
* your option) any later version.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stddef.h>
#include <gpxe/timer2.h>
#include <gpxe/io.h>
diff --git a/gpxe/src/arch/i386/core/virtaddr.S b/gpxe/src/arch/i386/core/virtaddr.S
index cf6da4f6..aae1e1ed 100644
--- a/gpxe/src/arch/i386/core/virtaddr.S
+++ b/gpxe/src/arch/i386/core/virtaddr.S
@@ -4,6 +4,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER )
+
#include "librm.h"
.arch i386
diff --git a/gpxe/src/arch/i386/core/x86_io.c b/gpxe/src/arch/i386/core/x86_io.c
index 424a96cc..d2c363b9 100644
--- a/gpxe/src/arch/i386/core/x86_io.c
+++ b/gpxe/src/arch/i386/core/x86_io.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/io.h>
#include <gpxe/x86_io.h>
diff --git a/gpxe/src/arch/i386/drivers/net/undi.c b/gpxe/src/arch/i386/drivers/net/undi.c
index 1090cc94..c6e253c0 100644
--- a/gpxe/src/arch/i386/drivers/net/undi.c
+++ b/gpxe/src/arch/i386/drivers/net/undi.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
@@ -135,7 +137,7 @@ static void undipci_remove ( struct pci_device *pci ) {
}
static struct pci_device_id undipci_nics[] = {
-PCI_ROM ( 0xffff, 0xffff, "undipci", "UNDI (PCI)" ),
+PCI_ROM ( 0xffff, 0xffff, "undipci", "UNDI (PCI)", 0 ),
};
struct pci_driver undipci_driver __pci_driver = {
diff --git a/gpxe/src/arch/i386/drivers/net/undiisr.S b/gpxe/src/arch/i386/drivers/net/undiisr.S
index 2b31b414..b27effe1 100644
--- a/gpxe/src/arch/i386/drivers/net/undiisr.S
+++ b/gpxe/src/arch/i386/drivers/net/undiisr.S
@@ -1,3 +1,5 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
#define PXENV_UNDI_ISR 0x0014
#define PXENV_UNDI_ISR_IN_START 1
#define PXENV_UNDI_ISR_OUT_OURS 0
@@ -29,7 +31,7 @@ undiisr:
movw %ax, %ds
/* Check that we have an UNDI entry point */
- cmpw $0, undinet_entry_point
+ cmpw $0, pxeparent_entry_point
je chain
/* Issue UNDI API call */
@@ -40,7 +42,7 @@ undiisr:
pushw %es
pushw %di
pushw %bx
- lcall *undinet_entry_point
+ lcall *pxeparent_entry_point
cli /* Just in case */
addw $6, %sp
cmpw $PXENV_UNDI_ISR_OUT_OURS, funcflag
diff --git a/gpxe/src/arch/i386/drivers/net/undiload.c b/gpxe/src/arch/i386/drivers/net/undiload.c
index dbd9e7c2..1d4e88d7 100644
--- a/gpxe/src/arch/i386/drivers/net/undiload.c
+++ b/gpxe/src/arch/i386/drivers/net/undiload.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -90,11 +92,10 @@ int undi_load ( struct undi_device *undi, struct undi_rom *undirom ) {
undi_loader_entry = undirom->loader_entry;
__asm__ __volatile__ ( REAL_CODE ( "pushw %%ds\n\t"
"pushw %%ax\n\t"
- "lcall *%c2\n\t"
+ "lcall *undi_loader_entry\n\t"
"addw $4, %%sp\n\t" )
: "=a" ( exit )
- : "a" ( __from_data16 ( &undi_loader ) ),
- "p" ( __from_data16 ( &undi_loader_entry ) )
+ : "a" ( __from_data16 ( &undi_loader ) )
: "ebx", "ecx", "edx", "esi", "edi", "ebp" );
/* UNDI API calls may rudely change the status of A20 and not
diff --git a/gpxe/src/arch/i386/drivers/net/undinet.c b/gpxe/src/arch/i386/drivers/net/undinet.c
index d6db6f7c..83b79e7f 100644
--- a/gpxe/src/arch/i386/drivers/net/undinet.c
+++ b/gpxe/src/arch/i386/drivers/net/undinet.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <pxe.h>
#include <realmode.h>
@@ -30,6 +32,7 @@
#include <gpxe/ethernet.h>
#include <undi.h>
#include <undinet.h>
+#include <pxeparent.h>
/** @file
@@ -60,179 +63,8 @@ struct undi_nic {
static void undinet_close ( struct net_device *netdev );
-/*****************************************************************************
- *
- * UNDI API call
- *
- *****************************************************************************
- */
-
-/**
- * Name UNDI API call
- *
- * @v function API call number
- * @ret name API call name
- */
-static inline __attribute__ (( always_inline )) const char *
-undinet_function_name ( unsigned int function ) {
- switch ( function ) {
- case PXENV_START_UNDI:
- return "PXENV_START_UNDI";
- case PXENV_STOP_UNDI:
- return "PXENV_STOP_UNDI";
- case PXENV_UNDI_STARTUP:
- return "PXENV_UNDI_STARTUP";
- case PXENV_UNDI_CLEANUP:
- return "PXENV_UNDI_CLEANUP";
- case PXENV_UNDI_INITIALIZE:
- return "PXENV_UNDI_INITIALIZE";
- case PXENV_UNDI_RESET_ADAPTER:
- return "PXENV_UNDI_RESET_ADAPTER";
- case PXENV_UNDI_SHUTDOWN:
- return "PXENV_UNDI_SHUTDOWN";
- case PXENV_UNDI_OPEN:
- return "PXENV_UNDI_OPEN";
- case PXENV_UNDI_CLOSE:
- return "PXENV_UNDI_CLOSE";
- case PXENV_UNDI_TRANSMIT:
- return "PXENV_UNDI_TRANSMIT";
- case PXENV_UNDI_SET_MCAST_ADDRESS:
- return "PXENV_UNDI_SET_MCAST_ADDRESS";
- case PXENV_UNDI_SET_STATION_ADDRESS:
- return "PXENV_UNDI_SET_STATION_ADDRESS";
- case PXENV_UNDI_SET_PACKET_FILTER:
- return "PXENV_UNDI_SET_PACKET_FILTER";
- case PXENV_UNDI_GET_INFORMATION:
- return "PXENV_UNDI_GET_INFORMATION";
- case PXENV_UNDI_GET_STATISTICS:
- return "PXENV_UNDI_GET_STATISTICS";
- case PXENV_UNDI_CLEAR_STATISTICS:
- return "PXENV_UNDI_CLEAR_STATISTICS";
- case PXENV_UNDI_INITIATE_DIAGS:
- return "PXENV_UNDI_INITIATE_DIAGS";
- case PXENV_UNDI_FORCE_INTERRUPT:
- return "PXENV_UNDI_FORCE_INTERRUPT";
- case PXENV_UNDI_GET_MCAST_ADDRESS:
- return "PXENV_UNDI_GET_MCAST_ADDRESS";
- case PXENV_UNDI_GET_NIC_TYPE:
- return "PXENV_UNDI_GET_NIC_TYPE";
- case PXENV_UNDI_GET_IFACE_INFO:
- return "PXENV_UNDI_GET_IFACE_INFO";
- /*
- * Duplicate case value; this is a bug in the PXE specification.
- *
- * case PXENV_UNDI_GET_STATE:
- * return "PXENV_UNDI_GET_STATE";
- */
- case PXENV_UNDI_ISR:
- return "PXENV_UNDI_ISR";
- default:
- return "UNKNOWN API CALL";
- }
-}
-
-/**
- * UNDI parameter block
- *
- * Used as the paramter block for all UNDI API calls. Resides in base
- * memory.
- */
-static union u_PXENV_ANY __bss16 ( undinet_params );
-#define undinet_params __use_data16 ( undinet_params )
-
-/** UNDI entry point
- *
- * Used as the indirection vector for all UNDI API calls. Resides in
- * base memory.
- */
-SEGOFF16_t __bss16 ( undinet_entry_point );
-#define undinet_entry_point __use_data16 ( undinet_entry_point )
-
-/**
- * Issue UNDI API call
- *
- * @v undinic UNDI NIC
- * @v function API call number
- * @v params UNDI parameter block
- * @v params_len Length of UNDI parameter block
- * @ret rc Return status code
- */
-static int undinet_call ( struct undi_nic *undinic, unsigned int function,
- void *params, size_t params_len ) {
- PXENV_EXIT_t exit;
- int discard_b, discard_D;
- int rc;
-
- /* Copy parameter block and entry point */
- assert ( params_len <= sizeof ( undinet_params ) );
- memcpy ( &undinet_params, params, params_len );
-
- /* Call real-mode entry point. This calling convention will
- * work with both the !PXE and the PXENV+ entry points.
- */
- __asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t"
- "pushw %%di\n\t"
- "pushw %%bx\n\t"
- "lcall *%c3\n\t"
- "addw $6, %%sp\n\t" )
- : "=a" ( exit ), "=b" ( discard_b ),
- "=D" ( discard_D )
- : "p" ( __from_data16 ( &undinet_entry_point )),
- "b" ( function ),
- "D" ( __from_data16 ( &undinet_params ) )
- : "ecx", "edx", "esi", "ebp" );
-
- /* UNDI API calls may rudely change the status of A20 and not
- * bother to restore it afterwards. Intel is known to be
- * guilty of this.
- *
- * Note that we will return to this point even if A20 gets
- * screwed up by the UNDI driver, because Etherboot always
- * resides in an even megabyte of RAM.
- */
- gateA20_set();
-
- /* Determine return status code based on PXENV_EXIT and
- * PXENV_STATUS
- */
- if ( exit == PXENV_EXIT_SUCCESS ) {
- rc = 0;
- } else {
- rc = -undinet_params.Status;
- /* Paranoia; don't return success for the combination
- * of PXENV_EXIT_FAILURE but PXENV_STATUS_SUCCESS
- */
- if ( rc == 0 )
- rc = -EIO;
- }
-
- /* If anything goes wrong, print as much debug information as
- * it's possible to give.
- */
- if ( rc != 0 ) {
- SEGOFF16_t rm_params = {
- .segment = rm_ds,
- .offset = __from_data16 ( &undinet_params ),
- };
-
- DBGC ( undinic, "UNDINIC %p %s failed: %s\n", undinic,
- undinet_function_name ( function ), strerror ( rc ) );
- DBGC ( undinic, "UNDINIC %p parameters at %04x:%04x length "
- "%#02zx, entry point at %04x:%04x\n", undinic,
- rm_params.segment, rm_params.offset, params_len,
- undinet_entry_point.segment,
- undinet_entry_point.offset );
- DBGC ( undinic, "UNDINIC %p parameters provided:\n", undinic );
- DBGC_HDA ( undinic, rm_params, params, params_len );
- DBGC ( undinic, "UNDINIC %p parameters returned:\n", undinic );
- DBGC_HDA ( undinic, rm_params, &undinet_params, params_len );
- }
-
- /* Copy parameter block back */
- memcpy ( params, &undinet_params, params_len );
-
- return rc;
-}
+/** Address of UNDI entry point */
+static SEGOFF16_t undinet_entry;
/*****************************************************************************
*
@@ -335,7 +167,6 @@ static struct s_PXENV_UNDI_TBD __data16 ( undinet_tbd );
*/
static int undinet_transmit ( struct net_device *netdev,
struct io_buffer *iobuf ) {
- struct undi_nic *undinic = netdev->priv;
struct s_PXENV_UNDI_TRANSMIT undi_transmit;
size_t len = iob_len ( iobuf );
int rc;
@@ -368,9 +199,9 @@ static int undinet_transmit ( struct net_device *netdev,
undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet );
/* Issue PXE API call */
- if ( ( rc = undinet_call ( undinic, PXENV_UNDI_TRANSMIT,
- &undi_transmit,
- sizeof ( undi_transmit ) ) ) != 0 )
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_TRANSMIT,
+ &undi_transmit,
+ sizeof ( undi_transmit ) ) ) != 0 )
goto done;
/* Free I/O buffer */
@@ -440,8 +271,9 @@ static void undinet_poll ( struct net_device *netdev ) {
/* Run through the ISR loop */
while ( 1 ) {
- if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
- sizeof ( undi_isr ) ) ) != 0 )
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_ISR,
+ &undi_isr,
+ sizeof ( undi_isr ) ) ) != 0 )
break;
switch ( undi_isr.FuncFlag ) {
case PXENV_UNDI_ISR_OUT_TRANSMIT:
@@ -537,8 +369,8 @@ static int undinet_open ( struct net_device *netdev ) {
*/
memcpy ( undi_set_address.StationAddress, netdev->ll_addr,
sizeof ( undi_set_address.StationAddress ) );
- undinet_call ( undinic, PXENV_UNDI_SET_STATION_ADDRESS,
- &undi_set_address, sizeof ( undi_set_address ) );
+ pxeparent_call ( undinet_entry, PXENV_UNDI_SET_STATION_ADDRESS,
+ &undi_set_address, sizeof ( undi_set_address ) );
/* Open NIC. We ask for promiscuous operation, since it's the
* only way to ask for all multicast addresses. On any
@@ -547,8 +379,8 @@ static int undinet_open ( struct net_device *netdev ) {
*/
memset ( &undi_open, 0, sizeof ( undi_open ) );
undi_open.PktFilter = ( FLTR_DIRECTED | FLTR_BRDCST | FLTR_PRMSCS );
- if ( ( rc = undinet_call ( undinic, PXENV_UNDI_OPEN, &undi_open,
- sizeof ( undi_open ) ) ) != 0 )
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_OPEN,
+ &undi_open, sizeof ( undi_open ) ) ) != 0 )
goto err;
DBGC ( undinic, "UNDINIC %p opened\n", undinic );
@@ -573,8 +405,9 @@ static void undinet_close ( struct net_device *netdev ) {
/* Ensure ISR has exited cleanly */
while ( undinic->isr_processing ) {
undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
- if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
- sizeof ( undi_isr ) ) ) != 0 )
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_ISR,
+ &undi_isr,
+ sizeof ( undi_isr ) ) ) != 0 )
break;
switch ( undi_isr.FuncFlag ) {
case PXENV_UNDI_ISR_OUT_TRANSMIT:
@@ -589,8 +422,8 @@ static void undinet_close ( struct net_device *netdev ) {
}
/* Close NIC */
- undinet_call ( undinic, PXENV_UNDI_CLOSE, &undi_close,
- sizeof ( undi_close ) );
+ pxeparent_call ( undinet_entry, PXENV_UNDI_CLOSE,
+ &undi_close, sizeof ( undi_close ) );
/* Disable interrupt and unhook ISR */
disable_irq ( undinic->irq );
@@ -650,7 +483,7 @@ int undinet_probe ( struct undi_device *undi ) {
undi_set_drvdata ( undi, netdev );
netdev->dev = &undi->dev;
memset ( undinic, 0, sizeof ( *undinic ) );
- undinet_entry_point = undi->entry;
+ undinet_entry = undi->entry;
DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi );
/* Hook in UNDI stack */
@@ -661,9 +494,9 @@ int undinet_probe ( struct undi_device *undi ) {
start_undi.DX = undi->isapnp_read_port;
start_undi.ES = BIOS_SEG;
start_undi.DI = find_pnp_bios();
- if ( ( rc = undinet_call ( undinic, PXENV_START_UNDI,
- &start_undi,
- sizeof ( start_undi ) ) ) != 0 )
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_START_UNDI,
+ &start_undi,
+ sizeof ( start_undi ) ) ) != 0 )
goto err_start_undi;
}
undi->flags |= UNDI_FL_STARTED;
@@ -671,24 +504,25 @@ int undinet_probe ( struct undi_device *undi ) {
/* Bring up UNDI stack */
if ( ! ( undi->flags & UNDI_FL_INITIALIZED ) ) {
memset ( &undi_startup, 0, sizeof ( undi_startup ) );
- if ( ( rc = undinet_call ( undinic, PXENV_UNDI_STARTUP,
- &undi_startup,
- sizeof ( undi_startup ) ) ) != 0 )
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_STARTUP,
+ &undi_startup,
+ sizeof ( undi_startup ) ) ) != 0 )
goto err_undi_startup;
memset ( &undi_initialize, 0, sizeof ( undi_initialize ) );
- if ( ( rc = undinet_call ( undinic, PXENV_UNDI_INITIALIZE,
- &undi_initialize,
- sizeof ( undi_initialize ))) != 0 )
+ if ( ( rc = pxeparent_call ( undinet_entry,
+ PXENV_UNDI_INITIALIZE,
+ &undi_initialize,
+ sizeof ( undi_initialize ))) != 0 )
goto err_undi_initialize;
}
undi->flags |= UNDI_FL_INITIALIZED;
/* Get device information */
memset ( &undi_info, 0, sizeof ( undi_info ) );
- if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_INFORMATION,
- &undi_info, sizeof ( undi_info ) ) ) != 0 )
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_GET_INFORMATION,
+ &undi_info, sizeof ( undi_info ) ) ) != 0 )
goto err_undi_get_information;
- memcpy ( netdev->ll_addr, undi_info.PermNodeAddress, ETH_ALEN );
+ memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
undinic->irq = undi_info.IntNumber;
if ( undinic->irq > IRQ_MAX ) {
DBGC ( undinic, "UNDINIC %p invalid IRQ %d\n",
@@ -696,16 +530,17 @@ int undinet_probe ( struct undi_device *undi ) {
goto err_bad_irq;
}
DBGC ( undinic, "UNDINIC %p is %s on IRQ %d\n",
- undinic, eth_ntoa ( netdev->ll_addr ), undinic->irq );
+ undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq );
/* Get interface information */
memset ( &undi_iface, 0, sizeof ( undi_iface ) );
- if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_IFACE_INFO,
- &undi_iface,
- sizeof ( undi_iface ) ) ) != 0 )
+ if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_GET_IFACE_INFO,
+ &undi_iface,
+ sizeof ( undi_iface ) ) ) != 0 )
goto err_undi_get_iface_info;
- DBGC ( undinic, "UNDINIC %p has type %s and link speed %d\n",
- undinic, undi_iface.IfaceType, undi_iface.LinkSpeed );
+ DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
+ undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
+ undi_iface.ServiceFlags );
if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
sizeof ( undi_iface.IfaceType ) ) == 0 ) {
DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n",
@@ -730,17 +565,17 @@ int undinet_probe ( struct undi_device *undi ) {
err_undi_initialize:
/* Shut down UNDI stack */
memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
- undinet_call ( undinic, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
- sizeof ( undi_shutdown ) );
+ pxeparent_call ( undinet_entry, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
+ sizeof ( undi_shutdown ) );
memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
- undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
- sizeof ( undi_cleanup ) );
+ pxeparent_call ( undinet_entry, PXENV_UNDI_CLEANUP, &undi_cleanup,
+ sizeof ( undi_cleanup ) );
undi->flags &= ~UNDI_FL_INITIALIZED;
err_undi_startup:
/* Unhook UNDI stack */
memset ( &stop_undi, 0, sizeof ( stop_undi ) );
- undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
- sizeof ( stop_undi ) );
+ pxeparent_call ( undinet_entry, PXENV_STOP_UNDI, &stop_undi,
+ sizeof ( stop_undi ) );
undi->flags &= ~UNDI_FL_STARTED;
err_start_undi:
netdev_nullify ( netdev );
@@ -771,22 +606,22 @@ void undinet_remove ( struct undi_device *undi ) {
/* Shut down UNDI stack */
memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
- undinet_call ( undinic, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
- sizeof ( undi_shutdown ) );
+ pxeparent_call ( undinet_entry, PXENV_UNDI_SHUTDOWN,
+ &undi_shutdown, sizeof ( undi_shutdown ) );
memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
- undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
- sizeof ( undi_cleanup ) );
+ pxeparent_call ( undinet_entry, PXENV_UNDI_CLEANUP,
+ &undi_cleanup, sizeof ( undi_cleanup ) );
undi->flags &= ~UNDI_FL_INITIALIZED;
/* Unhook UNDI stack */
memset ( &stop_undi, 0, sizeof ( stop_undi ) );
- undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
- sizeof ( stop_undi ) );
+ pxeparent_call ( undinet_entry, PXENV_STOP_UNDI, &stop_undi,
+ sizeof ( stop_undi ) );
undi->flags &= ~UNDI_FL_STARTED;
}
/* Clear entry point */
- memset ( &undinet_entry_point, 0, sizeof ( undinet_entry_point ) );
+ memset ( &undinet_entry, 0, sizeof ( undinet_entry ) );
/* Free network device */
netdev_nullify ( netdev );
diff --git a/gpxe/src/arch/i386/drivers/net/undionly.c b/gpxe/src/arch/i386/drivers/net/undionly.c
index 4cdce677..7dfb5d15 100644
--- a/gpxe/src/arch/i386/drivers/net/undionly.c
+++ b/gpxe/src/arch/i386/drivers/net/undionly.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
diff --git a/gpxe/src/arch/i386/drivers/net/undipreload.c b/gpxe/src/arch/i386/drivers/net/undipreload.c
index e29d150a..a4b2f4ac 100644
--- a/gpxe/src/arch/i386/drivers/net/undipreload.c
+++ b/gpxe/src/arch/i386/drivers/net/undipreload.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <realmode.h>
#include <undipreload.h>
diff --git a/gpxe/src/arch/i386/drivers/net/undirom.c b/gpxe/src/arch/i386/drivers/net/undirom.c
index e5782781..2463d969 100644
--- a/gpxe/src/arch/i386/drivers/net/undirom.c
+++ b/gpxe/src/arch/i386/drivers/net/undirom.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
diff --git a/gpxe/src/arch/i386/firmware/pcbios/basemem.c b/gpxe/src/arch/i386/firmware/pcbios/basemem.c
index b126d2a7..1ba7d1f6 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/basemem.c
+++ b/gpxe/src/arch/i386/firmware/pcbios/basemem.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <realmode.h>
#include <bios.h>
diff --git a/gpxe/src/arch/i386/firmware/pcbios/bios_console.c b/gpxe/src/arch/i386/firmware/pcbios/bios_console.c
index 91363772..1d18e54c 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/bios_console.c
+++ b/gpxe/src/arch/i386/firmware/pcbios/bios_console.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <assert.h>
#include <realmode.h>
#include <console.h>
diff --git a/gpxe/src/arch/i386/firmware/pcbios/e820mangler.S b/gpxe/src/arch/i386/firmware/pcbios/e820mangler.S
index decb0835..99ca519b 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/e820mangler.S
+++ b/gpxe/src/arch/i386/firmware/pcbios/e820mangler.S
@@ -15,7 +15,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
.text
.arch i386
.code16
@@ -235,6 +237,7 @@ get_underlying_e820:
popw %di
incw %bx
movl %edx, %eax
+ clc
ret
2:
/* If the requested region is earlier than the cached region,
diff --git a/gpxe/src/arch/i386/firmware/pcbios/fakee820.c b/gpxe/src/arch/i386/firmware/pcbios/fakee820.c
index 552bf41d..ea116fe5 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/fakee820.c
+++ b/gpxe/src/arch/i386/firmware/pcbios/fakee820.c
@@ -15,6 +15,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <realmode.h>
#include <biosint.h>
diff --git a/gpxe/src/arch/i386/firmware/pcbios/gateA20.c b/gpxe/src/arch/i386/firmware/pcbios/gateA20.c
index 34e3ac52..1a71472d 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/gateA20.c
+++ b/gpxe/src/arch/i386/firmware/pcbios/gateA20.c
@@ -1,3 +1,5 @@
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdio.h>
#include <realmode.h>
#include <bios.h>
diff --git a/gpxe/src/arch/i386/firmware/pcbios/hidemem.c b/gpxe/src/arch/i386/firmware/pcbios/hidemem.c
index 620b62e0..17082c35 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/hidemem.c
+++ b/gpxe/src/arch/i386/firmware/pcbios/hidemem.c
@@ -15,6 +15,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <assert.h>
#include <realmode.h>
#include <biosint.h>
diff --git a/gpxe/src/arch/i386/firmware/pcbios/memmap.c b/gpxe/src/arch/i386/firmware/pcbios/memmap.c
index ff387d93..8a30dbae 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/memmap.c
+++ b/gpxe/src/arch/i386/firmware/pcbios/memmap.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <errno.h>
#include <realmode.h>
diff --git a/gpxe/src/arch/i386/firmware/pcbios/pnpbios.c b/gpxe/src/arch/i386/firmware/pcbios/pnpbios.c
index 420d2ae8..c572914f 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/pnpbios.c
+++ b/gpxe/src/arch/i386/firmware/pcbios/pnpbios.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <string.h>
#include <errno.h>
diff --git a/gpxe/src/arch/i386/hci/commands/pxe_cmd.c b/gpxe/src/arch/i386/hci/commands/pxe_cmd.c
new file mode 100644
index 00000000..b5df2d1b
--- /dev/null
+++ b/gpxe/src/arch/i386/hci/commands/pxe_cmd.c
@@ -0,0 +1,33 @@
+#include <gpxe/netdevice.h>
+#include <gpxe/command.h>
+#include <hci/ifmgmt_cmd.h>
+#include <pxe_call.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+static int startpxe_payload ( struct net_device *netdev ) {
+ if ( netdev->state & NETDEV_OPEN )
+ pxe_activate ( netdev );
+ return 0;
+}
+
+static int startpxe_exec ( int argc, char **argv ) {
+ return ifcommon_exec ( argc, argv, startpxe_payload,
+ "Activate PXE on" );
+}
+
+static int stoppxe_exec ( int argc __unused, char **argv __unused ) {
+ pxe_deactivate();
+ return 0;
+}
+
+struct command pxe_commands[] __command = {
+ {
+ .name = "startpxe",
+ .exec = startpxe_exec,
+ },
+ {
+ .name = "stoppxe",
+ .exec = stoppxe_exec,
+ },
+};
diff --git a/gpxe/src/arch/i386/image/bootsector.c b/gpxe/src/arch/i386/image/bootsector.c
index 0f297a26..f96cf201 100644
--- a/gpxe/src/arch/i386/image/bootsector.c
+++ b/gpxe/src/arch/i386/image/bootsector.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
diff --git a/gpxe/src/arch/i386/image/bzimage.c b/gpxe/src/arch/i386/image/bzimage.c
index 47d46ca4..19450990 100644
--- a/gpxe/src/arch/i386/image/bzimage.c
+++ b/gpxe/src/arch/i386/image/bzimage.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
@@ -42,9 +44,11 @@ FEATURE ( FEATURE_IMAGE, "bzImage", DHCP_EB_FEATURE_BZIMAGE, 1 );
struct image_type bzimage_image_type __image_type ( PROBE_NORMAL );
/**
- * bzImage load context
+ * bzImage context
*/
-struct bzimage_load_context {
+struct bzimage_context {
+ /** Boot protocol version */
+ unsigned int version;
/** Real-mode kernel portion load segment address */
unsigned int rm_kernel_seg;
/** Real-mode kernel portion load address */
@@ -55,28 +59,14 @@ struct bzimage_load_context {
size_t rm_heap;
/** Command line (offset from rm_kernel) */
size_t rm_cmdline;
+ /** Command line maximum length */
+ size_t cmdline_size;
/** Real-mode kernel portion total memory size */
size_t rm_memsz;
/** Non-real-mode kernel portion load address */
userptr_t pm_kernel;
/** Non-real-mode kernel portion file and memory size */
size_t pm_sz;
-};
-
-/**
- * bzImage execution context
- */
-struct bzimage_exec_context {
- /** Real-mode kernel portion load segment address */
- unsigned int rm_kernel_seg;
- /** Real-mode kernel portion load address */
- userptr_t rm_kernel;
- /** Real-mode heap top (offset from rm_kernel) */
- size_t rm_heap;
- /** Command line (offset from rm_kernel) */
- size_t rm_cmdline;
- /** Command line maximum length */
- size_t cmdline_size;
/** Video mode */
unsigned int vid_mode;
/** Memory limit */
@@ -85,18 +75,178 @@ struct bzimage_exec_context {
physaddr_t ramdisk_image;
/** Initrd size */
physaddr_t ramdisk_size;
+
+ /** Command line magic block */
+ struct bzimage_cmdline cmdline_magic;
+ /** bzImage header */
+ struct bzimage_header bzhdr;
};
/**
+ * Parse bzImage header
+ *
+ * @v image bzImage file
+ * @v bzimg bzImage context
+ * @v src bzImage to parse
+ * @ret rc Return status code
+ */
+static int bzimage_parse_header ( struct image *image,
+ struct bzimage_context *bzimg,
+ userptr_t src ) {
+ unsigned int syssize;
+ int is_bzimage;
+
+ /* Sanity check */
+ if ( image->len < ( BZI_HDR_OFFSET + sizeof ( bzimg->bzhdr ) ) ) {
+ DBGC ( image, "bzImage %p too short for kernel header\n",
+ image );
+ return -ENOEXEC;
+ }
+
+ /* Read in header structures */
+ memset ( bzimg, 0, sizeof ( *bzimg ) );
+ copy_from_user ( &bzimg->cmdline_magic, src, BZI_CMDLINE_OFFSET,
+ sizeof ( bzimg->cmdline_magic ) );
+ copy_from_user ( &bzimg->bzhdr, src, BZI_HDR_OFFSET,
+ sizeof ( bzimg->bzhdr ) );
+
+ /* Calculate size of real-mode portion */
+ bzimg->rm_filesz =
+ ( ( bzimg->bzhdr.setup_sects ? bzimg->bzhdr.setup_sects : 4 ) + 1 ) << 9;
+ if ( bzimg->rm_filesz > image->len ) {
+ DBGC ( image, "bzImage %p too short for %zd byte of setup\n",
+ image, bzimg->rm_filesz );
+ return -ENOEXEC;
+ }
+ bzimg->rm_memsz = BZI_ASSUMED_RM_SIZE;
+
+ /* Calculate size of protected-mode portion */
+ bzimg->pm_sz = ( image->len - bzimg->rm_filesz );
+ syssize = ( ( bzimg->pm_sz + 15 ) / 16 );
+
+ /* Check for signatures and determine version */
+ if ( bzimg->bzhdr.boot_flag != BZI_BOOT_FLAG ) {
+ DBGC ( image, "bzImage %p missing 55AA signature\n", image );
+ return -ENOEXEC;
+ }
+ if ( bzimg->bzhdr.header == BZI_SIGNATURE ) {
+ /* 2.00+ */
+ bzimg->version = bzimg->bzhdr.version;
+ } else {
+ /* Pre-2.00. Check that the syssize field is correct,
+ * as a guard against accepting arbitrary binary data,
+ * since the 55AA check is pretty lax. Note that the
+ * syssize field is unreliable for protocols between
+ * 2.00 and 2.03 inclusive, so we should not always
+ * check this field.
+ */
+ bzimg->version = 0x0100;
+ if ( bzimg->bzhdr.syssize != syssize ) {
+ DBGC ( image, "bzImage %p bad syssize %x (expected "
+ "%x)\n", image, bzimg->bzhdr.syssize, syssize );
+ return -ENOEXEC;
+ }
+ }
+
+ /* Determine image type */
+ is_bzimage = ( ( bzimg->version >= 0x0200 ) ?
+ ( bzimg->bzhdr.loadflags & BZI_LOAD_HIGH ) : 0 );
+
+ /* Calculate load address of real-mode portion */
+ bzimg->rm_kernel_seg = ( is_bzimage ? 0x1000 : 0x9000 );
+ bzimg->rm_kernel = real_to_user ( bzimg->rm_kernel_seg, 0 );
+
+ /* Allow space for the stack and heap */
+ bzimg->rm_memsz += BZI_STACK_SIZE;
+ bzimg->rm_heap = bzimg->rm_memsz;
+
+ /* Allow space for the command line */
+ bzimg->rm_cmdline = bzimg->rm_memsz;
+ bzimg->rm_memsz += BZI_CMDLINE_SIZE;
+
+ /* Calculate load address of protected-mode portion */
+ bzimg->pm_kernel = phys_to_user ( is_bzimage ? BZI_LOAD_HIGH_ADDR
+ : BZI_LOAD_LOW_ADDR );
+
+ /* Extract video mode */
+ bzimg->vid_mode = bzimg->bzhdr.vid_mode;
+
+ /* Extract memory limit */
+ bzimg->mem_limit = ( ( bzimg->version >= 0x0203 ) ?
+ bzimg->bzhdr.initrd_addr_max : BZI_INITRD_MAX );
+
+ /* Extract command line size */
+ bzimg->cmdline_size = ( ( bzimg->version >= 0x0206 ) ?
+ bzimg->bzhdr.cmdline_size : BZI_CMDLINE_SIZE );
+
+ DBGC ( image, "bzImage %p version %04x RM %#lx+%#zx PM %#lx+%#zx "
+ "cmdlen %zd\n", image, bzimg->version,
+ user_to_phys ( bzimg->rm_kernel, 0 ), bzimg->rm_filesz,
+ user_to_phys ( bzimg->pm_kernel, 0 ), bzimg->pm_sz,
+ bzimg->cmdline_size );
+
+ return 0;
+}
+
+/**
+ * Update bzImage header in loaded kernel
+ *
+ * @v image bzImage file
+ * @v bzimg bzImage context
+ * @v dst bzImage to update
+ */
+static void bzimage_update_header ( struct image *image,
+ struct bzimage_context *bzimg,
+ userptr_t dst ) {
+
+ /* Set loader type */
+ if ( bzimg->version >= 0x0200 )
+ bzimg->bzhdr.type_of_loader = BZI_LOADER_TYPE_GPXE;
+
+ /* Set heap end pointer */
+ if ( bzimg->version >= 0x0201 ) {
+ bzimg->bzhdr.heap_end_ptr = ( bzimg->rm_heap - 0x200 );
+ bzimg->bzhdr.loadflags |= BZI_CAN_USE_HEAP;
+ }
+
+ /* Set command line */
+ if ( bzimg->version >= 0x0202 ) {
+ bzimg->bzhdr.cmd_line_ptr = user_to_phys ( bzimg->rm_kernel,
+ bzimg->rm_cmdline );
+ } else {
+ bzimg->cmdline_magic.magic = BZI_CMDLINE_MAGIC;
+ bzimg->cmdline_magic.offset = bzimg->rm_cmdline;
+ bzimg->bzhdr.setup_move_size = bzimg->rm_memsz;
+ }
+
+ /* Set video mode */
+ bzimg->bzhdr.vid_mode = bzimg->vid_mode;
+
+ /* Set initrd address */
+ if ( bzimg->version >= 0x0200 ) {
+ bzimg->bzhdr.ramdisk_image = bzimg->ramdisk_image;
+ bzimg->bzhdr.ramdisk_size = bzimg->ramdisk_size;
+ }
+
+ /* Write out header structures */
+ copy_to_user ( dst, BZI_CMDLINE_OFFSET, &bzimg->cmdline_magic,
+ sizeof ( bzimg->cmdline_magic ) );
+ copy_to_user ( dst, BZI_HDR_OFFSET, &bzimg->bzhdr,
+ sizeof ( bzimg->bzhdr ) );
+
+ DBGC ( image, "bzImage %p vidmode %d\n", image, bzimg->vid_mode );
+}
+
+/**
* Parse kernel command line for bootloader parameters
*
* @v image bzImage file
- * @v exec_ctx Execution context
+ * @v bzimg bzImage context
* @v cmdline Kernel command line
* @ret rc Return status code
*/
static int bzimage_parse_cmdline ( struct image *image,
- struct bzimage_exec_context *exec_ctx,
+ struct bzimage_context *bzimg,
const char *cmdline ) {
char *vga;
char *mem;
@@ -105,13 +255,13 @@ static int bzimage_parse_cmdline ( struct image *image,
if ( ( vga = strstr ( cmdline, "vga=" ) ) ) {
vga += 4;
if ( strcmp ( vga, "normal" ) == 0 ) {
- exec_ctx->vid_mode = BZI_VID_MODE_NORMAL;
+ bzimg->vid_mode = BZI_VID_MODE_NORMAL;
} else if ( strcmp ( vga, "ext" ) == 0 ) {
- exec_ctx->vid_mode = BZI_VID_MODE_EXT;
+ bzimg->vid_mode = BZI_VID_MODE_EXT;
} else if ( strcmp ( vga, "ask" ) == 0 ) {
- exec_ctx->vid_mode = BZI_VID_MODE_ASK;
+ bzimg->vid_mode = BZI_VID_MODE_ASK;
} else {
- exec_ctx->vid_mode = strtoul ( vga, &vga, 0 );
+ bzimg->vid_mode = strtoul ( vga, &vga, 0 );
if ( *vga && ( *vga != ' ' ) ) {
DBGC ( image, "bzImage %p strange \"vga=\""
"terminator '%c'\n", image, *vga );
@@ -122,17 +272,17 @@ static int bzimage_parse_cmdline ( struct image *image,
/* Look for "mem=" */
if ( ( mem = strstr ( cmdline, "mem=" ) ) ) {
mem += 4;
- exec_ctx->mem_limit = strtoul ( mem, &mem, 0 );
+ bzimg->mem_limit = strtoul ( mem, &mem, 0 );
switch ( *mem ) {
case 'G':
case 'g':
- exec_ctx->mem_limit <<= 10;
+ bzimg->mem_limit <<= 10;
case 'M':
case 'm':
- exec_ctx->mem_limit <<= 10;
+ bzimg->mem_limit <<= 10;
case 'K':
case 'k':
- exec_ctx->mem_limit <<= 10;
+ bzimg->mem_limit <<= 10;
break;
case '\0':
case ' ':
@@ -142,7 +292,7 @@ static int bzimage_parse_cmdline ( struct image *image,
"terminator '%c'\n", image, *mem );
break;
}
- exec_ctx->mem_limit -= 1;
+ bzimg->mem_limit -= 1;
}
return 0;
@@ -152,20 +302,20 @@ static int bzimage_parse_cmdline ( struct image *image,
* Set command line
*
* @v image bzImage image
- * @v exec_ctx Execution context
+ * @v bzimg bzImage context
* @v cmdline Kernel command line
* @ret rc Return status code
*/
static int bzimage_set_cmdline ( struct image *image,
- struct bzimage_exec_context *exec_ctx,
+ struct bzimage_context *bzimg,
const char *cmdline ) {
size_t cmdline_len;
/* Copy command line down to real-mode portion */
cmdline_len = ( strlen ( cmdline ) + 1 );
- if ( cmdline_len > exec_ctx->cmdline_size )
- cmdline_len = exec_ctx->cmdline_size;
- copy_to_user ( exec_ctx->rm_kernel, exec_ctx->rm_cmdline,
+ if ( cmdline_len > bzimg->cmdline_size )
+ cmdline_len = bzimg->cmdline_size;
+ copy_to_user ( bzimg->rm_kernel, bzimg->rm_cmdline,
cmdline, cmdline_len );
DBGC ( image, "bzImage %p command line \"%s\"\n", image, cmdline );
@@ -217,14 +367,16 @@ static size_t bzimage_load_initrd ( struct image *image,
}
/* Copy in initrd image body */
+ if ( address )
+ memcpy_user ( address, offset, initrd->data, 0, initrd->len );
+ offset += initrd->len;
if ( address ) {
DBGC ( image, "bzImage %p has initrd %p at [%lx,%lx)\n",
- image, initrd, address, ( address + offset ) );
- memcpy_user ( address, offset, initrd->data, 0,
- initrd->len );
+ image, initrd, user_to_phys ( address, 0 ),
+ user_to_phys ( address, offset ) );
}
- offset += initrd->len;
+ /* Round up to 4-byte boundary */
offset = ( ( offset + 0x03 ) & ~0x03 );
return offset;
}
@@ -233,20 +385,19 @@ static size_t bzimage_load_initrd ( struct image *image,
* Load initrds, if any
*
* @v image bzImage image
- * @v exec_ctx Execution context
+ * @v bzimg bzImage context
* @ret rc Return status code
*/
static int bzimage_load_initrds ( struct image *image,
- struct bzimage_exec_context *exec_ctx ) {
+ struct bzimage_context *bzimg ) {
struct image *initrd;
size_t total_len = 0;
physaddr_t address;
int rc;
/* Add up length of all initrd images */
- for_each_image ( initrd ) {
+ for_each_image ( initrd )
total_len += bzimage_load_initrd ( image, initrd, UNULL );
- }
/* Give up if no initrd images found */
if ( ! total_len )
@@ -268,7 +419,7 @@ static int bzimage_load_initrds ( struct image *image,
return -ENOBUFS;
}
/* Check that we are within the kernel's range */
- if ( ( address + total_len - 1 ) > exec_ctx->mem_limit )
+ if ( ( address + total_len - 1 ) > bzimg->mem_limit )
continue;
/* Prepare and verify segment */
if ( ( rc = prep_segment ( phys_to_user ( address ), 0,
@@ -279,8 +430,8 @@ static int bzimage_load_initrds ( struct image *image,
}
/* Record initrd location */
- exec_ctx->ramdisk_image = address;
- exec_ctx->ramdisk_size = total_len;
+ bzimg->ramdisk_image = address;
+ bzimg->ramdisk_size = total_len;
/* Construct initrd */
DBGC ( image, "bzImage %p constructing initrd at [%lx,%lx)\n",
@@ -300,60 +451,37 @@ static int bzimage_load_initrds ( struct image *image,
* @ret rc Return status code
*/
static int bzimage_exec ( struct image *image ) {
- struct bzimage_exec_context exec_ctx;
- struct bzimage_header bzhdr;
+ struct bzimage_context bzimg;
const char *cmdline = ( image->cmdline ? image->cmdline : "" );
int rc;
- /* Initialise context */
- memset ( &exec_ctx, 0, sizeof ( exec_ctx ) );
-
- /* Retrieve kernel header */
- exec_ctx.rm_kernel_seg = image->priv.ul;
- exec_ctx.rm_kernel = real_to_user ( exec_ctx.rm_kernel_seg, 0 );
- copy_from_user ( &bzhdr, exec_ctx.rm_kernel, BZI_HDR_OFFSET,
- sizeof ( bzhdr ) );
- exec_ctx.rm_cmdline = exec_ctx.rm_heap =
- ( bzhdr.heap_end_ptr + 0x200 );
- exec_ctx.vid_mode = bzhdr.vid_mode;
- if ( bzhdr.version >= 0x0203 ) {
- exec_ctx.mem_limit = bzhdr.initrd_addr_max;
- } else {
- exec_ctx.mem_limit = BZI_INITRD_MAX;
- }
- if ( bzhdr.version >= 0x0206 ) {
- exec_ctx.cmdline_size = bzhdr.cmdline_size;
- } else {
- exec_ctx.cmdline_size = BZI_CMDLINE_SIZE;
- }
- DBG ( "cmdline_size = %zd\n", exec_ctx.cmdline_size );
+ /* Read and parse header from loaded kernel */
+ if ( ( rc = bzimage_parse_header ( image, &bzimg,
+ image->priv.user ) ) != 0 )
+ return rc;
+ assert ( bzimg.rm_kernel == image->priv.user );
/* Parse command line for bootloader parameters */
- if ( ( rc = bzimage_parse_cmdline ( image, &exec_ctx, cmdline ) ) != 0)
+ if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0)
return rc;
/* Store command line */
- if ( ( rc = bzimage_set_cmdline ( image, &exec_ctx, cmdline ) ) != 0 )
+ if ( ( rc = bzimage_set_cmdline ( image, &bzimg, cmdline ) ) != 0 )
return rc;
/* Load any initrds */
- if ( ( rc = bzimage_load_initrds ( image, &exec_ctx ) ) != 0 )
+ if ( ( rc = bzimage_load_initrds ( image, &bzimg ) ) != 0 )
return rc;
- /* Update and store kernel header */
- bzhdr.vid_mode = exec_ctx.vid_mode;
- bzhdr.ramdisk_image = exec_ctx.ramdisk_image;
- bzhdr.ramdisk_size = exec_ctx.ramdisk_size;
- copy_to_user ( exec_ctx.rm_kernel, BZI_HDR_OFFSET, &bzhdr,
- sizeof ( bzhdr ) );
+ /* Update kernel header */
+ bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
/* Prepare for exiting */
shutdown ( SHUTDOWN_BOOT );
DBGC ( image, "bzImage %p jumping to RM kernel at %04x:0000 "
- "(stack %04x:%04zx)\n", image,
- ( exec_ctx.rm_kernel_seg + 0x20 ),
- exec_ctx.rm_kernel_seg, exec_ctx.rm_heap );
+ "(stack %04x:%04zx)\n", image, ( bzimg.rm_kernel_seg + 0x20 ),
+ bzimg.rm_kernel_seg, bzimg.rm_heap );
/* Jump to the kernel */
__asm__ __volatile__ ( REAL_CODE ( "movw %w0, %%ds\n\t"
@@ -365,9 +493,9 @@ static int bzimage_exec ( struct image *image ) {
"pushw %w2\n\t"
"pushw $0\n\t"
"lret\n\t" )
- : : "r" ( exec_ctx.rm_kernel_seg ),
- "r" ( exec_ctx.rm_heap ),
- "r" ( exec_ctx.rm_kernel_seg + 0x20 ) );
+ : : "r" ( bzimg.rm_kernel_seg ),
+ "r" ( bzimg.rm_heap ),
+ "r" ( bzimg.rm_kernel_seg + 0x20 ) );
/* There is no way for the image to return, since we provide
* no return address.
@@ -378,192 +506,49 @@ static int bzimage_exec ( struct image *image ) {
}
/**
- * Load and parse bzImage header
- *
- * @v image bzImage file
- * @v load_ctx Load context
- * @v bzhdr Buffer for bzImage header
- * @ret rc Return status code
- */
-static int bzimage_load_header ( struct image *image,
- struct bzimage_load_context *load_ctx,
- struct bzimage_header *bzhdr ) {
-
- /* Sanity check */
- if ( image->len < ( BZI_HDR_OFFSET + sizeof ( *bzhdr ) ) ) {
- DBGC ( image, "bzImage %p too short for kernel header\n",
- image );
- return -ENOEXEC;
- }
-
- /* Read and verify header */
- copy_from_user ( bzhdr, image->data, BZI_HDR_OFFSET,
- sizeof ( *bzhdr ) );
- if ( bzhdr->header != BZI_SIGNATURE ) {
- DBGC ( image, "bzImage %p bad signature %08x\n",
- image, bzhdr->header );
- return -ENOEXEC;
- }
-
- /* We don't support ancient kernels */
- if ( bzhdr->version < 0x0200 ) {
- DBGC ( image, "bzImage %p version %04x not supported\n",
- image, bzhdr->version );
- return -ENOTSUP;
- }
-
- /* Calculate load address and size of real-mode portion */
- load_ctx->rm_kernel_seg = ( ( bzhdr->loadflags & BZI_LOAD_HIGH ) ?
- 0x1000 : /* 1000:0000 (bzImage) */
- 0x9000 ); /* 9000:0000 (zImage) */
- load_ctx->rm_kernel = real_to_user ( load_ctx->rm_kernel_seg, 0 );
- load_ctx->rm_filesz =
- ( ( bzhdr->setup_sects ? bzhdr->setup_sects : 4 ) + 1 ) << 9;
- load_ctx->rm_memsz = BZI_ASSUMED_RM_SIZE;
- if ( load_ctx->rm_filesz > image->len ) {
- DBGC ( image, "bzImage %p too short for %zd byte of setup\n",
- image, load_ctx->rm_filesz );
- return -ENOEXEC;
- }
-
- /* Calculate load address and size of non-real-mode portion */
- load_ctx->pm_kernel = ( ( bzhdr->loadflags & BZI_LOAD_HIGH ) ?
- phys_to_user ( BZI_LOAD_HIGH_ADDR ) :
- phys_to_user ( BZI_LOAD_LOW_ADDR ) );
- load_ctx->pm_sz = ( image->len - load_ctx->rm_filesz );
-
- DBGC ( image, "bzImage %p version %04x RM %#zx bytes PM %#zx bytes\n",
- image, bzhdr->version, load_ctx->rm_filesz, load_ctx->pm_sz );
- return 0;
-}
-
-/**
- * Load real-mode portion of bzImage
+ * Load bzImage image into memory
*
* @v image bzImage file
- * @v load_ctx Load context
* @ret rc Return status code
*/
-static int bzimage_load_real ( struct image *image,
- struct bzimage_load_context *load_ctx ) {
+int bzimage_load ( struct image *image ) {
+ struct bzimage_context bzimg;
int rc;
- /* Allow space for the stack and heap */
- load_ctx->rm_memsz += BZI_STACK_SIZE;
- load_ctx->rm_heap = load_ctx->rm_memsz;
+ /* Read and parse header from image */
+ if ( ( rc = bzimage_parse_header ( image, &bzimg,
+ image->data ) ) != 0 )
+ return rc;
- /* Allow space for the command line */
- load_ctx->rm_cmdline = load_ctx->rm_memsz;
- load_ctx->rm_memsz += BZI_CMDLINE_SIZE;
+ /* This is a bzImage image, valid or otherwise */
+ if ( ! image->type )
+ image->type = &bzimage_image_type;
- /* Prepare, verify, and load the real-mode segment */
- if ( ( rc = prep_segment ( load_ctx->rm_kernel, load_ctx->rm_filesz,
- load_ctx->rm_memsz ) ) != 0 ) {
+ /* Prepare segments */
+ if ( ( rc = prep_segment ( bzimg.rm_kernel, bzimg.rm_filesz,
+ bzimg.rm_memsz ) ) != 0 ) {
DBGC ( image, "bzImage %p could not prepare RM segment: %s\n",
image, strerror ( rc ) );
return rc;
}
- memcpy_user ( load_ctx->rm_kernel, 0, image->data, 0,
- load_ctx->rm_filesz );
-
- return 0;
-}
-
-/**
- * Load non-real-mode portion of bzImage
- *
- * @v image bzImage file
- * @v load_ctx Load context
- * @ret rc Return status code
- */
-static int bzimage_load_non_real ( struct image *image,
- struct bzimage_load_context *load_ctx ) {
- int rc;
-
- /* Prepare, verify and load the non-real-mode segment */
- if ( ( rc = prep_segment ( load_ctx->pm_kernel, load_ctx->pm_sz,
- load_ctx->pm_sz ) ) != 0 ) {
+ if ( ( rc = prep_segment ( bzimg.pm_kernel, bzimg.pm_sz,
+ bzimg.pm_sz ) ) != 0 ) {
DBGC ( image, "bzImage %p could not prepare PM segment: %s\n",
image, strerror ( rc ) );
return rc;
}
- memcpy_user ( load_ctx->pm_kernel, 0, image->data, load_ctx->rm_filesz,
- load_ctx->pm_sz );
-
- return 0;
-}
-
-/**
- * Update and store bzImage header
- *
- * @v image bzImage file
- * @v load_ctx Load context
- * @v bzhdr Original bzImage header
- * @ret rc Return status code
- */
-static int bzimage_write_header ( struct image *image __unused,
- struct bzimage_load_context *load_ctx,
- struct bzimage_header *bzhdr ) {
- struct bzimage_cmdline cmdline;
-
- /* Update the header and copy it into the loaded kernel */
- bzhdr->type_of_loader = BZI_LOADER_TYPE_GPXE;
- if ( bzhdr->version >= 0x0201 ) {
- bzhdr->heap_end_ptr = ( load_ctx->rm_heap - 0x200 );
- bzhdr->loadflags |= BZI_CAN_USE_HEAP;
- }
- if ( bzhdr->version >= 0x0202 ) {
- bzhdr->cmd_line_ptr = user_to_phys ( load_ctx->rm_kernel,
- load_ctx->rm_cmdline );
- } else {
- cmdline.magic = BZI_CMDLINE_MAGIC;
- cmdline.offset = load_ctx->rm_cmdline;
- copy_to_user ( load_ctx->rm_kernel, BZI_CMDLINE_OFFSET,
- &cmdline, sizeof ( cmdline ) );
- bzhdr->setup_move_size = load_ctx->rm_memsz;
- }
- copy_to_user ( load_ctx->rm_kernel, BZI_HDR_OFFSET,
- bzhdr, sizeof ( *bzhdr ) );
-
- return 0;
-}
-
-/**
- * Load bzImage image into memory
- *
- * @v image bzImage file
- * @ret rc Return status code
- */
-int bzimage_load ( struct image *image ) {
- struct bzimage_load_context load_ctx;
- struct bzimage_header bzhdr;
- int rc;
-
- /* Initialise context */
- memset ( &load_ctx, 0, sizeof ( load_ctx ) );
- /* Load and verify header */
- if ( ( rc = bzimage_load_header ( image, &load_ctx, &bzhdr ) ) != 0 )
- return rc;
-
- /* This is a bzImage image, valid or otherwise */
- if ( ! image->type )
- image->type = &bzimage_image_type;
-
- /* Load real-mode portion */
- if ( ( rc = bzimage_load_real ( image, &load_ctx ) ) != 0 )
- return rc;
-
- /* Load non-real-mode portion */
- if ( ( rc = bzimage_load_non_real ( image, &load_ctx ) ) != 0 )
- return rc;
+ /* 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 */
- if ( ( rc = bzimage_write_header ( image, &load_ctx, &bzhdr ) ) != 0 )
- return rc;
+ bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
/* Record real-mode segment in image private data field */
- image->priv.ul = load_ctx.rm_kernel_seg;
+ image->priv.user = bzimg.rm_kernel;
return 0;
}
diff --git a/gpxe/src/arch/i386/image/com32.c b/gpxe/src/arch/i386/image/com32.c
index d1b9a59f..6ab347c1 100644
--- a/gpxe/src/arch/i386/image/com32.c
+++ b/gpxe/src/arch/i386/image/com32.c
@@ -23,6 +23,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
diff --git a/gpxe/src/arch/i386/image/comboot.c b/gpxe/src/arch/i386/image/comboot.c
index 40e32185..a00b2b95 100644
--- a/gpxe/src/arch/i386/image/comboot.c
+++ b/gpxe/src/arch/i386/image/comboot.c
@@ -23,6 +23,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
diff --git a/gpxe/src/arch/i386/image/elfboot.c b/gpxe/src/arch/i386/image/elfboot.c
index c8daf72b..a41040e8 100644
--- a/gpxe/src/arch/i386/image/elfboot.c
+++ b/gpxe/src/arch/i386/image/elfboot.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <errno.h>
#include <elf.h>
#include <gpxe/image.h>
diff --git a/gpxe/src/arch/i386/image/eltorito.c b/gpxe/src/arch/i386/image/eltorito.c
index 9d573106..53eb2c02 100644
--- a/gpxe/src/arch/i386/image/eltorito.c
+++ b/gpxe/src/arch/i386/image/eltorito.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
diff --git a/gpxe/src/arch/i386/image/multiboot.c b/gpxe/src/arch/i386/image/multiboot.c
index 52bb10f6..5b620956 100644
--- a/gpxe/src/arch/i386/image/multiboot.c
+++ b/gpxe/src/arch/i386/image/multiboot.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
@@ -139,10 +141,11 @@ static void multiboot_build_memmap ( struct image *image,
/**
* Add command line in base memory
*
+ * @v imgname Image name
* @v cmdline Command line
* @ret physaddr Physical address of command line
*/
-physaddr_t multiboot_add_cmdline ( const char *cmdline ) {
+physaddr_t multiboot_add_cmdline ( const char *imgname, const char *cmdline ) {
char *mb_cmdline;
if ( ! cmdline )
@@ -153,7 +156,7 @@ physaddr_t multiboot_add_cmdline ( const char *cmdline ) {
mb_cmdline_offset +=
( snprintf ( mb_cmdline,
( sizeof ( mb_cmdlines ) - mb_cmdline_offset ),
- "%s", cmdline ) + 1 );
+ "%s %s", imgname, cmdline ) + 1 );
/* Truncate to terminating NUL in buffer if necessary */
if ( mb_cmdline_offset > sizeof ( mb_cmdlines ) )
@@ -208,8 +211,8 @@ multiboot_build_module_list ( struct image *image,
( ( count - insert ) * sizeof ( *module ) ) );
module->mod_start = start;
module->mod_end = end;
- module->string =
- multiboot_add_cmdline ( module_image->cmdline );
+ module->string = multiboot_add_cmdline ( module_image->name,
+ module_image->cmdline );
module->reserved = 0;
/* We promise to page-align modules */
@@ -264,10 +267,8 @@ static int multiboot_exec ( struct image *image ) {
memset ( &mbinfo, 0, sizeof ( mbinfo ) );
mbinfo.flags = ( MBI_FLAG_LOADER | MBI_FLAG_MEM | MBI_FLAG_MMAP |
MBI_FLAG_CMDLINE | MBI_FLAG_MODS );
- multiboot_build_memmap ( image, &mbinfo, mbmemmap,
- ( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) );
mb_cmdline_offset = 0;
- mbinfo.cmdline = multiboot_add_cmdline ( image->cmdline );
+ mbinfo.cmdline = multiboot_add_cmdline ( image->name, image->cmdline );
mbinfo.mods_count = multiboot_build_module_list ( image, mbmodules,
( sizeof(mbmodules) / sizeof(mbmodules[0]) ) );
mbinfo.mods_addr = virt_to_phys ( mbmodules );
@@ -279,6 +280,12 @@ static int multiboot_exec ( struct image *image ) {
*/
shutdown ( SHUTDOWN_BOOT );
+ /* Build memory map after unhiding bootloader memory regions as part of
+ * shutting everything down.
+ */
+ multiboot_build_memmap ( image, &mbinfo, mbmemmap,
+ ( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) );
+
/* Jump to OS with flat physical addressing */
DBGC ( image, "MULTIBOOT %p starting execution at %lx\n",
image, entry );
@@ -360,6 +367,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 +446,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/gpxe/src/arch/i386/image/pxe_image.c b/gpxe/src/arch/i386/image/pxe_image.c
index 90550d83..63429f87 100644
--- a/gpxe/src/arch/i386/image/pxe_image.c
+++ b/gpxe/src/arch/i386/image/pxe_image.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
@@ -42,28 +44,24 @@ struct image_type pxe_image_type __image_type ( PROBE_PXE );
* @ret rc Return status code
*/
static int pxe_exec ( struct image *image ) {
+ struct net_device *netdev;
int rc;
- /* Ensure that PXE stack is ready to use */
- pxe_init_structures();
- pxe_hook_int1a();
-
/* Arbitrarily pick the most recently opened network device */
- pxe_set_netdev ( last_opened_netdev() );
-
- /* Many things will break if pxe_netdev is NULL */
- if ( ! pxe_netdev ) {
+ if ( ( netdev = last_opened_netdev() ) == NULL ) {
DBGC ( image, "IMAGE %p could not locate PXE net device\n",
image );
return -ENODEV;
}
+ /* Activate PXE */
+ pxe_activate ( netdev );
+
/* Start PXE NBP */
rc = pxe_start_nbp();
/* Deactivate PXE */
- pxe_set_netdev ( NULL );
- pxe_unhook_int1a();
+ pxe_deactivate();
return rc;
}
diff --git a/gpxe/src/arch/i386/include/basemem.h b/gpxe/src/arch/i386/include/basemem.h
index cd5668e0..c477c7fe 100644
--- a/gpxe/src/arch/i386/include/basemem.h
+++ b/gpxe/src/arch/i386/include/basemem.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <realmode.h>
#include <bios.h>
diff --git a/gpxe/src/arch/i386/include/basemem_packet.h b/gpxe/src/arch/i386/include/basemem_packet.h
index e4d4f49c..3cb47767 100644
--- a/gpxe/src/arch/i386/include/basemem_packet.h
+++ b/gpxe/src/arch/i386/include/basemem_packet.h
@@ -1,6 +1,8 @@
#ifndef BASEMEM_PACKET_H
#define BASEMEM_PACKET_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <realmode.h>
/** Maximum length of base memory packet buffer */
diff --git a/gpxe/src/arch/i386/include/bios.h b/gpxe/src/arch/i386/include/bios.h
index 979a092c..70bb73da 100644
--- a/gpxe/src/arch/i386/include/bios.h
+++ b/gpxe/src/arch/i386/include/bios.h
@@ -1,6 +1,8 @@
#ifndef BIOS_H
#define BIOS_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
#define BDA_SEG 0x0040
#define BDA_FBMS 0x0013
#define BDA_NUM_DRIVES 0x0075
diff --git a/gpxe/src/arch/i386/include/biosint.h b/gpxe/src/arch/i386/include/biosint.h
index d365cf01..ab466af3 100644
--- a/gpxe/src/arch/i386/include/biosint.h
+++ b/gpxe/src/arch/i386/include/biosint.h
@@ -6,6 +6,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <realmode.h>
struct segoff;
diff --git a/gpxe/src/arch/i386/include/bits/byteswap.h b/gpxe/src/arch/i386/include/bits/byteswap.h
index 98418c29..ddbd40ed 100644
--- a/gpxe/src/arch/i386/include/bits/byteswap.h
+++ b/gpxe/src/arch/i386/include/bits/byteswap.h
@@ -1,6 +1,8 @@
#ifndef ETHERBOOT_BITS_BYTESWAP_H
#define ETHERBOOT_BITS_BYTESWAP_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
static inline __attribute__ ((always_inline, const)) uint16_t
__bswap_variable_16(uint16_t x)
{
diff --git a/gpxe/src/arch/i386/include/bits/compiler.h b/gpxe/src/arch/i386/include/bits/compiler.h
index 119a9a21..000db0c1 100644
--- a/gpxe/src/arch/i386/include/bits/compiler.h
+++ b/gpxe/src/arch/i386/include/bits/compiler.h
@@ -1,6 +1,8 @@
#ifndef _BITS_COMPILER_H
#define _BITS_COMPILER_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
#ifndef ASSEMBLY
/** Declare a function with standard calling conventions */
diff --git a/gpxe/src/arch/i386/include/bits/endian.h b/gpxe/src/arch/i386/include/bits/endian.h
index 413e702d..84188542 100644
--- a/gpxe/src/arch/i386/include/bits/endian.h
+++ b/gpxe/src/arch/i386/include/bits/endian.h
@@ -1,6 +1,8 @@
#ifndef ETHERBOOT_BITS_ENDIAN_H
#define ETHERBOOT_BITS_ENDIAN_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
#define __BYTE_ORDER __LITTLE_ENDIAN
#endif /* ETHERBOOT_BITS_ENDIAN_H */
diff --git a/gpxe/src/arch/i386/include/bits/errfile.h b/gpxe/src/arch/i386/include/bits/errfile.h
index 5ea8a318..32b8a085 100644
--- a/gpxe/src/arch/i386/include/bits/errfile.h
+++ b/gpxe/src/arch/i386/include/bits/errfile.h
@@ -1,6 +1,8 @@
#ifndef _BITS_ERRFILE_H
#define _BITS_ERRFILE_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @addtogroup errfile Error file identifiers
* @{
@@ -12,6 +14,7 @@
#define ERRFILE_bios_smbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00030000 )
#define ERRFILE_biosint ( ERRFILE_ARCH | ERRFILE_CORE | 0x00040000 )
#define ERRFILE_int13 ( ERRFILE_ARCH | ERRFILE_CORE | 0x00050000 )
+#define ERRFILE_pxeparent ( ERRFILE_ARCH | ERRFILE_CORE | 0x00060000 )
#define ERRFILE_bootsector ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
#define ERRFILE_bzimage ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )
diff --git a/gpxe/src/arch/i386/include/bits/io.h b/gpxe/src/arch/i386/include/bits/io.h
index dd0ee444..eded9778 100644
--- a/gpxe/src/arch/i386/include/bits/io.h
+++ b/gpxe/src/arch/i386/include/bits/io.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/x86_io.h>
#endif /* _BITS_IO_H */
diff --git a/gpxe/src/arch/i386/include/bits/nap.h b/gpxe/src/arch/i386/include/bits/nap.h
index f8ba7a7c..1354f6bb 100644
--- a/gpxe/src/arch/i386/include/bits/nap.h
+++ b/gpxe/src/arch/i386/include/bits/nap.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/bios_nap.h>
#include <gpxe/efi/efix86_nap.h>
diff --git a/gpxe/src/arch/i386/include/bits/smbios.h b/gpxe/src/arch/i386/include/bits/smbios.h
index 647ea19e..a68413aa 100644
--- a/gpxe/src/arch/i386/include/bits/smbios.h
+++ b/gpxe/src/arch/i386/include/bits/smbios.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/bios_smbios.h>
#endif /* _BITS_SMBIOS_H */
diff --git a/gpxe/src/arch/i386/include/bits/stdint.h b/gpxe/src/arch/i386/include/bits/stdint.h
index 6ccf0971..8edf1319 100644
--- a/gpxe/src/arch/i386/include/bits/stdint.h
+++ b/gpxe/src/arch/i386/include/bits/stdint.h
@@ -1,8 +1,10 @@
#ifndef _BITS_STDINT_H
#define _BITS_STDINT_H
-typedef unsigned int size_t;
-typedef signed int ssize_t;
+FILE_LICENCE ( GPL2_OR_LATER );
+
+typedef __SIZE_TYPE__ size_t;
+typedef signed long ssize_t;
typedef signed long off_t;
typedef unsigned char uint8_t;
diff --git a/gpxe/src/arch/i386/include/bits/timer.h b/gpxe/src/arch/i386/include/bits/timer.h
index 99666d84..32e6bd47 100644
--- a/gpxe/src/arch/i386/include/bits/timer.h
+++ b/gpxe/src/arch/i386/include/bits/timer.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/bios_timer.h>
#include <gpxe/rdtsc_timer.h>
diff --git a/gpxe/src/arch/i386/include/bits/uaccess.h b/gpxe/src/arch/i386/include/bits/uaccess.h
index 0ecc5028..2bb52e02 100644
--- a/gpxe/src/arch/i386/include/bits/uaccess.h
+++ b/gpxe/src/arch/i386/include/bits/uaccess.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <librm.h>
#endif /* _BITS_UACCESS_H */
diff --git a/gpxe/src/arch/i386/include/bits/umalloc.h b/gpxe/src/arch/i386/include/bits/umalloc.h
index dcbd0a6b..17ba2cb2 100644
--- a/gpxe/src/arch/i386/include/bits/umalloc.h
+++ b/gpxe/src/arch/i386/include/bits/umalloc.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/memtop_umalloc.h>
#endif /* _BITS_UMALLOC_H */
diff --git a/gpxe/src/arch/i386/include/bootsector.h b/gpxe/src/arch/i386/include/bootsector.h
index e9071052..8730fbfc 100644
--- a/gpxe/src/arch/i386/include/bootsector.h
+++ b/gpxe/src/arch/i386/include/bootsector.h
@@ -6,6 +6,8 @@
* x86 bootsector image format
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
extern int call_bootsector ( unsigned int segment, unsigned int offset,
unsigned int drive );
diff --git a/gpxe/src/arch/i386/include/bzimage.h b/gpxe/src/arch/i386/include/bzimage.h
index aee058ae..42b31fe4 100644
--- a/gpxe/src/arch/i386/include/bzimage.h
+++ b/gpxe/src/arch/i386/include/bzimage.h
@@ -1,6 +1,8 @@
#ifndef _BZIMAGE_H
#define _BZIMAGE_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
/**
@@ -75,6 +77,9 @@ struct bzimage_header {
/** Offset of bzImage header within kernel image */
#define BZI_HDR_OFFSET 0x1f1
+/** bzImage boot flag value */
+#define BZI_BOOT_FLAG 0xaa55
+
/** bzImage magic signature value */
#define BZI_SIGNATURE 0x53726448
diff --git a/gpxe/src/arch/i386/include/callbacks_arch.h b/gpxe/src/arch/i386/include/callbacks_arch.h
deleted file mode 100644
index f9cba488..00000000
--- a/gpxe/src/arch/i386/include/callbacks_arch.h
+++ /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 */
diff --git a/gpxe/src/arch/i386/include/comboot.h b/gpxe/src/arch/i386/include/comboot.h
index 56661a80..1232f0a7 100644
--- a/gpxe/src/arch/i386/include/comboot.h
+++ b/gpxe/src/arch/i386/include/comboot.h
@@ -7,6 +7,8 @@
* SYSLINUX COMBOOT
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <setjmp.h>
#include <gpxe/in.h>
diff --git a/gpxe/src/arch/i386/include/fakee820.h b/gpxe/src/arch/i386/include/fakee820.h
index f1fe8aff..9d00fb67 100644
--- a/gpxe/src/arch/i386/include/fakee820.h
+++ b/gpxe/src/arch/i386/include/fakee820.h
@@ -1,6 +1,8 @@
#ifndef _FAKEE820_H
#define _FAKEE820_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
extern void fake_e820 ( void );
extern void unfake_e820 ( void );
diff --git a/gpxe/src/arch/i386/include/gpxe/abft.h b/gpxe/src/arch/i386/include/gpxe/abft.h
index 1c651ef1..9065e61a 100644
--- a/gpxe/src/arch/i386/include/gpxe/abft.h
+++ b/gpxe/src/arch/i386/include/gpxe/abft.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <gpxe/acpi.h>
#include <gpxe/if_ether.h>
diff --git a/gpxe/src/arch/i386/include/gpxe/bios_nap.h b/gpxe/src/arch/i386/include/gpxe/bios_nap.h
index f1c721e9..c32429b9 100644
--- a/gpxe/src/arch/i386/include/gpxe/bios_nap.h
+++ b/gpxe/src/arch/i386/include/gpxe/bios_nap.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#ifdef NAP_PCBIOS
#define NAP_PREFIX_pcbios
#else
diff --git a/gpxe/src/arch/i386/include/gpxe/bios_smbios.h b/gpxe/src/arch/i386/include/gpxe/bios_smbios.h
index 0a6f277a..83726b11 100644
--- a/gpxe/src/arch/i386/include/gpxe/bios_smbios.h
+++ b/gpxe/src/arch/i386/include/gpxe/bios_smbios.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#ifdef SMBIOS_PCBIOS
#define SMBIOS_PREFIX_pcbios
#else
diff --git a/gpxe/src/arch/i386/include/gpxe/bios_timer.h b/gpxe/src/arch/i386/include/gpxe/bios_timer.h
index 7e3caa3c..ed9df522 100644
--- a/gpxe/src/arch/i386/include/gpxe/bios_timer.h
+++ b/gpxe/src/arch/i386/include/gpxe/bios_timer.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#ifdef TIMER_PCBIOS
#define TIMER_PREFIX_pcbios
#else
diff --git a/gpxe/src/arch/i386/include/gpxe/ibft.h b/gpxe/src/arch/i386/include/gpxe/ibft.h
index 5eef547b..c41e2e40 100644
--- a/gpxe/src/arch/i386/include/gpxe/ibft.h
+++ b/gpxe/src/arch/i386/include/gpxe/ibft.h
@@ -28,6 +28,8 @@
*
*/
+FILE_LICENCE ( BSD2 );
+
/** @file
*
* iSCSI boot firmware table
diff --git a/gpxe/src/arch/i386/include/gpxe/memtop_umalloc.h b/gpxe/src/arch/i386/include/gpxe/memtop_umalloc.h
index a3cd2c01..eaf7025b 100644
--- a/gpxe/src/arch/i386/include/gpxe/memtop_umalloc.h
+++ b/gpxe/src/arch/i386/include/gpxe/memtop_umalloc.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#ifdef UMALLOC_MEMTOP
#define UMALLOC_PREFIX_memtop
#else
diff --git a/gpxe/src/arch/i386/include/gpxe/rdtsc_timer.h b/gpxe/src/arch/i386/include/gpxe/rdtsc_timer.h
index 0e03d707..67ba22f0 100644
--- a/gpxe/src/arch/i386/include/gpxe/rdtsc_timer.h
+++ b/gpxe/src/arch/i386/include/gpxe/rdtsc_timer.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#ifdef TIMER_RDTSC
#define TIMER_PREFIX_rdtsc
#else
diff --git a/gpxe/src/arch/i386/include/gpxe/sbft.h b/gpxe/src/arch/i386/include/gpxe/sbft.h
new file mode 100644
index 00000000..30038436
--- /dev/null
+++ b/gpxe/src/arch/i386/include/gpxe/sbft.h
@@ -0,0 +1,125 @@
+#ifndef _GPXE_SBFT_H
+#define _GPXE_SBFT_H
+
+/*
+ * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+/** @file
+ *
+ * SRP boot firmware table
+ *
+ * The working draft specification for the SRP boot firmware table can
+ * be found at
+ *
+ * http://etherboot.org/wiki/srp/sbft
+ *
+ */
+
+#include <stdint.h>
+#include <gpxe/acpi.h>
+#include <gpxe/scsi.h>
+#include <gpxe/srp.h>
+#include <gpxe/ib_srp.h>
+
+/** SRP Boot Firmware Table signature */
+#define SBFT_SIG "sBFT"
+
+/** An offset from the start of the sBFT */
+typedef uint16_t sbft_off_t;
+
+/**
+ * SRP Boot Firmware Table
+ */
+struct sbft_table {
+ /** ACPI header */
+ struct acpi_description_header acpi;
+ /** Offset to SCSI subtable */
+ sbft_off_t scsi_offset;
+ /** Offset to SRP subtable */
+ sbft_off_t srp_offset;
+ /** Offset to IB subtable, if present */
+ sbft_off_t ib_offset;
+ /** Reserved */
+ uint8_t reserved[6];
+} __attribute__ (( packed ));
+
+/**
+ * sBFT SCSI subtable
+ */
+struct sbft_scsi_subtable {
+ /** LUN */
+ struct scsi_lun lun;
+} __attribute__ (( packed ));
+
+/**
+ * sBFT SRP subtable
+ */
+struct sbft_srp_subtable {
+ /** Initiator and target ports */
+ struct srp_port_ids port_ids;
+} __attribute__ (( packed ));
+
+/**
+ * sBFT IB subtable
+ */
+struct sbft_ib_subtable {
+ /** Source GID */
+ struct ib_gid sgid;
+ /** Destination GID */
+ struct ib_gid dgid;
+ /** Service ID */
+ struct ib_gid_half service_id;
+ /** Partition key */
+ uint16_t pkey;
+ /** Reserved */
+ uint8_t reserved[6];
+} __attribute__ (( packed ));
+
+/**
+ * An sBFT created by gPXE
+ */
+struct gpxe_sbft {
+ /** The table header */
+ struct sbft_table table;
+ /** The SCSI subtable */
+ struct sbft_scsi_subtable scsi;
+ /** The SRP subtable */
+ struct sbft_srp_subtable srp;
+ /** The IB subtable */
+ struct sbft_ib_subtable ib;
+} __attribute__ (( packed, aligned ( 16 ) ));
+
+struct srp_device;
+
+extern int sbft_fill_data ( struct srp_device *srp );
+
+#endif /* _GPXE_SBFT_H */
diff --git a/gpxe/src/arch/i386/include/gpxe/timer2.h b/gpxe/src/arch/i386/include/gpxe/timer2.h
index 59705fa2..8f119515 100644
--- a/gpxe/src/arch/i386/include/gpxe/timer2.h
+++ b/gpxe/src/arch/i386/include/gpxe/timer2.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
extern void timer2_udelay ( unsigned long usecs );
#endif /* _GPXE_TIMER2_H */
diff --git a/gpxe/src/arch/i386/include/gpxe/x86_io.h b/gpxe/src/arch/i386/include/gpxe/x86_io.h
index b1ae3bac..beb5b22a 100644
--- a/gpxe/src/arch/i386/include/gpxe/x86_io.h
+++ b/gpxe/src/arch/i386/include/gpxe/x86_io.h
@@ -15,6 +15,8 @@
* into a machine with such an old CPU anyway.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#ifdef IOAPI_X86
#define IOAPI_PREFIX_x86
#else
diff --git a/gpxe/src/arch/i386/include/int13.h b/gpxe/src/arch/i386/include/int13.h
index bf6d0318..e1884d94 100644
--- a/gpxe/src/arch/i386/include/int13.h
+++ b/gpxe/src/arch/i386/include/int13.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <gpxe/list.h>
#include <realmode.h>
diff --git a/gpxe/src/arch/i386/include/librm.h b/gpxe/src/arch/i386/include/librm.h
index 9eb2767a..f193f5e3 100755..100644
--- a/gpxe/src/arch/i386/include/librm.h
+++ b/gpxe/src/arch/i386/include/librm.h
@@ -1,6 +1,8 @@
#ifndef LIBRM_H
#define LIBRM_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
/* Segment selectors as used in our protected-mode GDTs.
*
* Don't change these unless you really know what you're doing.
diff --git a/gpxe/src/arch/i386/include/limits.h b/gpxe/src/arch/i386/include/limits.h
index f13db267..031b6c57 100644
--- a/gpxe/src/arch/i386/include/limits.h
+++ b/gpxe/src/arch/i386/include/limits.h
@@ -1,6 +1,8 @@
#ifndef LIMITS_H
#define LIMITS_H 1
+FILE_LICENCE ( GPL2_OR_LATER );
+
/* Number of bits in a `char' */
#define CHAR_BIT 8
diff --git a/gpxe/src/arch/i386/include/memsizes.h b/gpxe/src/arch/i386/include/memsizes.h
index 6222fd66..7b217494 100644
--- a/gpxe/src/arch/i386/include/memsizes.h
+++ b/gpxe/src/arch/i386/include/memsizes.h
@@ -1,6 +1,8 @@
#ifndef _MEMSIZES_H
#define _MEMSIZES_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <basemem.h>
/**
diff --git a/gpxe/src/arch/i386/include/multiboot.h b/gpxe/src/arch/i386/include/multiboot.h
index 4ca7089b..44614c73 100644
--- a/gpxe/src/arch/i386/include/multiboot.h
+++ b/gpxe/src/arch/i386/include/multiboot.h
@@ -8,6 +8,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
/** The magic number for the Multiboot header */
diff --git a/gpxe/src/arch/i386/include/pic8259.h b/gpxe/src/arch/i386/include/pic8259.h
index 0c501a9c..f8e20c4c 100644
--- a/gpxe/src/arch/i386/include/pic8259.h
+++ b/gpxe/src/arch/i386/include/pic8259.h
@@ -4,6 +4,8 @@
* Initially written by Michael Brown (mcb30).
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#ifndef PIC8259_H
#define PIC8259_H
diff --git a/gpxe/src/arch/i386/include/pnpbios.h b/gpxe/src/arch/i386/include/pnpbios.h
index ab31c699..4c20e73e 100644
--- a/gpxe/src/arch/i386/include/pnpbios.h
+++ b/gpxe/src/arch/i386/include/pnpbios.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/* BIOS segment address */
#define BIOS_SEG 0xf000
diff --git a/gpxe/src/arch/i386/include/pxe.h b/gpxe/src/arch/i386/include/pxe.h
index 6d332ac7..041ee7ba 100644
--- a/gpxe/src/arch/i386/include/pxe.h
+++ b/gpxe/src/arch/i386/include/pxe.h
@@ -1,6 +1,8 @@
#ifndef PXE_H
#define PXE_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include "pxe_types.h"
#include "pxe_api.h"
#include <gpxe/device.h>
@@ -65,6 +67,7 @@ union u_PXENV_ANY {
struct s_PXENV_GET_FILE_SIZE get_file_size;
struct s_PXENV_FILE_EXEC file_exec;
struct s_PXENV_FILE_API_CHECK file_api_check;
+ struct s_PXENV_FILE_EXIT_HOOK file_exit_hook;
};
typedef union u_PXENV_ANY PXENV_ANY_t;
diff --git a/gpxe/src/arch/i386/include/pxe_api.h b/gpxe/src/arch/i386/include/pxe_api.h
index b3d4bca8..92f046f7 100644
--- a/gpxe/src/arch/i386/include/pxe_api.h
+++ b/gpxe/src/arch/i386/include/pxe_api.h
@@ -15,6 +15,31 @@
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * As an alternative, at your option, you may use this file under the
+ * following terms, known as the "MIT license":
+ *
+ * Copyright (c) 2005-2009 Michael Brown <mbrown@fensystems.co.uk>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
*/
/** @file
@@ -23,6 +48,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include "pxe_types.h"
/** @addtogroup pxe Preboot eXecution Environment (PXE) API
@@ -1415,6 +1442,25 @@ extern PXENV_EXIT_t pxenv_undi_get_nic_type (
/** PXE API function code for pxenv_undi_get_iface_info() */
#define PXENV_UNDI_GET_IFACE_INFO 0x0013
+/** Broadcast supported */
+#define SUPPORTED_BROADCAST 0x0001
+/** Multicast supported */
+#define SUPPORTED_MULTICAST 0x0002
+/** Functional/group addressing supported */
+#define SUPPORTED_GROUP 0x0004
+/** Promiscuous mode supported */
+#define SUPPORTED_PROMISCUOUS 0x0008
+/** Software settable station address */
+#define SUPPORTED_SET_STATION_ADDRESS 0x0010
+/** InitiateDiagnostics supported */
+#define SUPPORTED_DIAGNOSTICS 0x0040
+/** Reset MAC supported */
+#define SUPPORTED_RESET 0x0400
+/** Open / Close Adapter supported */
+#define SUPPORTED_OPEN_CLOSE 0x0800
+/** Interrupt Request supported */
+#define SUPPORTED_IRQ 0x1000
+
/** Parameter block for pxenv_undi_get_iface_info() */
struct s_PXENV_UNDI_GET_IFACE_INFO {
PXENV_STATUS_t Status; /**< PXE status code */
@@ -1732,6 +1778,28 @@ extern PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_a
/** @} */ /* pxenv_file_api_check */
+/** @defgroup pxenv_file_exit_hook PXENV_FILE_EXIT_HOOK
+ *
+ * FILE EXIT HOOK
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_exit_hook() */
+#define PXENV_FILE_EXIT_HOOK 0x00e7
+
+/** Parameter block for pxenv_file_exit_hook() */
+struct s_PXENV_FILE_EXIT_HOOK {
+ PXENV_STATUS_t Status; /**< PXE status code */
+ SEGOFF16_t Hook; /**< SEG16:OFF16 to jump to */
+} PACKED;
+
+typedef struct s_PXENV_FILE_EXIT_HOOK PXENV_FILE_EXIT_HOOK_t;
+
+extern PXENV_EXIT_t pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK *file_exit_hook );
+
+/** @} */ /* pxenv_file_exit_hook */
+
/** @} */ /* pxe_file_api */
/** @defgroup pxe_loader_api PXE Loader API
diff --git a/gpxe/src/arch/i386/include/pxe_call.h b/gpxe/src/arch/i386/include/pxe_call.h
index 2f3ea15a..4d245616 100644
--- a/gpxe/src/arch/i386/include/pxe_call.h
+++ b/gpxe/src/arch/i386/include/pxe_call.h
@@ -6,9 +6,13 @@
* PXE API entry point
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <pxe_api.h>
#include <realmode.h>
+struct net_device;
+
/** PXE load address segment */
#define PXE_LOAD_SEGMENT 0
@@ -26,10 +30,28 @@ extern struct s_PXE __text16 ( ppxe );
extern struct s_PXENV __text16 ( pxenv );
#define pxenv __use_text16 ( pxenv )
-extern void pxe_hook_int1a ( void );
-extern int pxe_unhook_int1a ( void );
-extern void pxe_init_structures ( void );
+extern void pxe_activate ( struct net_device *netdev );
+extern int pxe_deactivate ( void );
extern int pxe_start_nbp ( void );
extern __asmcall void pxe_api_call ( struct i386_all_regs *ix86 );
+extern int _pxe_api_call_weak ( struct i386_all_regs *ix86 )
+ __attribute__ (( weak ));
+
+/**
+ * Dispatch PXE API call weakly
+ *
+ * @v ix86 Registers for PXE call
+ * @ret present Zero if the PXE stack is present, nonzero if not
+ *
+ * A successful return only indicates that the PXE stack was available
+ * for dispatching the call; it says nothing about the success of
+ * whatever the call asked for.
+ */
+static inline int pxe_api_call_weak ( struct i386_all_regs *ix86 )
+{
+ if ( _pxe_api_call_weak != NULL )
+ return _pxe_api_call_weak ( ix86 );
+ return -1;
+}
#endif /* _PXE_CALL_H */
diff --git a/gpxe/src/arch/i386/include/pxe_types.h b/gpxe/src/arch/i386/include/pxe_types.h
index dd9092ef..a6516d25 100644
--- a/gpxe/src/arch/i386/include/pxe_types.h
+++ b/gpxe/src/arch/i386/include/pxe_types.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <errno.h> /* PXE status codes */
diff --git a/gpxe/src/arch/i386/include/pxeparent.h b/gpxe/src/arch/i386/include/pxeparent.h
new file mode 100644
index 00000000..b31e24a7
--- /dev/null
+++ b/gpxe/src/arch/i386/include/pxeparent.h
@@ -0,0 +1,11 @@
+#ifndef PXEPARENT_H
+#define PXEPARENT_H
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <pxe_types.h>
+
+extern int pxeparent_call ( SEGOFF16_t entry, unsigned int function,
+ void *params, size_t params_len );
+
+#endif
diff --git a/gpxe/src/arch/i386/include/realmode.h b/gpxe/src/arch/i386/include/realmode.h
index 26e6dd77..a0a830b9 100644
--- a/gpxe/src/arch/i386/include/realmode.h
+++ b/gpxe/src/arch/i386/include/realmode.h
@@ -10,6 +10,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/*
* Declaration of variables in .data16
*
diff --git a/gpxe/src/arch/i386/include/registers.h b/gpxe/src/arch/i386/include/registers.h
index e68fa85a..2839e2bd 100644
--- a/gpxe/src/arch/i386/include/registers.h
+++ b/gpxe/src/arch/i386/include/registers.h
@@ -10,6 +10,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
/**
diff --git a/gpxe/src/arch/i386/include/setjmp.h b/gpxe/src/arch/i386/include/setjmp.h
index c18d03e1..5d3c11b6 100644
--- a/gpxe/src/arch/i386/include/setjmp.h
+++ b/gpxe/src/arch/i386/include/setjmp.h
@@ -1,6 +1,8 @@
#ifndef ETHERBOOT_SETJMP_H
#define ETHERBOOT_SETJMP_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <realmode.h>
diff --git a/gpxe/src/arch/i386/include/undi.h b/gpxe/src/arch/i386/include/undi.h
index c6253d0a..de6925b6 100644
--- a/gpxe/src/arch/i386/include/undi.h
+++ b/gpxe/src/arch/i386/include/undi.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#ifndef ASSEMBLY
#include <gpxe/device.h>
diff --git a/gpxe/src/arch/i386/include/undiload.h b/gpxe/src/arch/i386/include/undiload.h
index bfc11874..426830e8 100644
--- a/gpxe/src/arch/i386/include/undiload.h
+++ b/gpxe/src/arch/i386/include/undiload.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
struct undi_device;
struct undi_rom;
diff --git a/gpxe/src/arch/i386/include/undinet.h b/gpxe/src/arch/i386/include/undinet.h
index 1a4a385e..c3c17c11 100644
--- a/gpxe/src/arch/i386/include/undinet.h
+++ b/gpxe/src/arch/i386/include/undinet.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
struct undi_device;
extern int undinet_probe ( struct undi_device *undi );
diff --git a/gpxe/src/arch/i386/include/undipreload.h b/gpxe/src/arch/i386/include/undipreload.h
index d9bc8cb9..de9b8fb5 100644
--- a/gpxe/src/arch/i386/include/undipreload.h
+++ b/gpxe/src/arch/i386/include/undipreload.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <realmode.h>
#include <undi.h>
diff --git a/gpxe/src/arch/i386/include/undirom.h b/gpxe/src/arch/i386/include/undirom.h
index a2636007..86d7077b 100644
--- a/gpxe/src/arch/i386/include/undirom.h
+++ b/gpxe/src/arch/i386/include/undirom.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <pxe_types.h>
/** An UNDI PCI device ID */
diff --git a/gpxe/src/arch/i386/interface/pcbios/abft.c b/gpxe/src/arch/i386/interface/pcbios/abft.c
index af28bbcf..86941728 100644
--- a/gpxe/src/arch/i386/interface/pcbios/abft.c
+++ b/gpxe/src/arch/i386/interface/pcbios/abft.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <realmode.h>
#include <gpxe/aoe.h>
#include <gpxe/netdevice.h>
diff --git a/gpxe/src/arch/i386/interface/pcbios/aoeboot.c b/gpxe/src/arch/i386/interface/pcbios/aoeboot.c
index 6e1e51cb..2670b15d 100644
--- a/gpxe/src/arch/i386/interface/pcbios/aoeboot.c
+++ b/gpxe/src/arch/i386/interface/pcbios/aoeboot.c
@@ -1,58 +1,74 @@
#include <stdint.h>
#include <string.h>
+#include <stdlib.h>
#include <stdio.h>
-#include <byteswap.h>
+#include <errno.h>
#include <gpxe/aoe.h>
#include <gpxe/ata.h>
#include <gpxe/netdevice.h>
-#include <gpxe/settings.h>
#include <gpxe/sanboot.h>
#include <gpxe/abft.h>
#include <int13.h>
+FILE_LICENCE ( GPL2_OR_LATER );
+
static int aoeboot ( const char *root_path ) {
- struct ata_device ata;
- struct int13_drive drive;
+ struct ata_device *ata;
+ struct int13_drive *drive;
int rc;
- memset ( &ata, 0, sizeof ( ata ) );
- memset ( &drive, 0, sizeof ( drive ) );
-
- printf ( "AoE booting from %s\n", root_path );
+ ata = zalloc ( sizeof ( *ata ) );
+ if ( ! ata ) {
+ rc = -ENOMEM;
+ goto err_alloc_ata;
+ }
+ drive = zalloc ( sizeof ( *drive ) );
+ if ( ! drive ) {
+ rc = -ENOMEM;
+ goto err_alloc_drive;
+ }
/* FIXME: ugly, ugly hack */
struct net_device *netdev = last_opened_netdev();
- if ( ( rc = aoe_attach ( &ata, netdev, root_path ) ) != 0 ) {
+ if ( ( rc = aoe_attach ( ata, netdev, root_path ) ) != 0 ) {
printf ( "Could not attach AoE device: %s\n",
strerror ( rc ) );
- goto error_attach;
+ goto err_attach;
}
- if ( ( rc = init_atadev ( &ata ) ) != 0 ) {
+ if ( ( rc = init_atadev ( ata ) ) != 0 ) {
printf ( "Could not initialise AoE device: %s\n",
strerror ( rc ) );
- goto error_init;
+ goto err_init;
}
/* FIXME: ugly, ugly hack */
struct aoe_session *aoe =
- container_of ( ata.backend, struct aoe_session, refcnt );
+ container_of ( ata->backend, struct aoe_session, refcnt );
abft_fill_data ( aoe );
- drive.blockdev = &ata.blockdev;
+ drive->blockdev = &ata->blockdev;
- register_int13_drive ( &drive );
- printf ( "Registered as BIOS drive %#02x\n", drive.drive );
- printf ( "Booting from BIOS drive %#02x\n", drive.drive );
- rc = int13_boot ( drive.drive );
+ register_int13_drive ( drive );
+ printf ( "Registered as BIOS drive %#02x\n", drive->drive );
+ printf ( "Booting from BIOS drive %#02x\n", drive->drive );
+ rc = int13_boot ( drive->drive );
printf ( "Boot failed\n" );
- printf ( "Unregistering BIOS drive %#02x\n", drive.drive );
- unregister_int13_drive ( &drive );
+ /* Leave drive registered, if instructed to do so */
+ if ( keep_san() )
+ return rc;
+
+ printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
+ unregister_int13_drive ( drive );
- error_init:
- aoe_detach ( &ata );
- error_attach:
+ err_init:
+ aoe_detach ( ata );
+ err_attach:
+ free ( drive );
+ err_alloc_drive:
+ free ( ata );
+ err_alloc_ata:
return rc;
}
diff --git a/gpxe/src/arch/i386/interface/pcbios/bios_nap.c b/gpxe/src/arch/i386/interface/pcbios/bios_nap.c
index 2f4a0513..e38cac7a 100644
--- a/gpxe/src/arch/i386/interface/pcbios/bios_nap.c
+++ b/gpxe/src/arch/i386/interface/pcbios/bios_nap.c
@@ -1,6 +1,8 @@
#include <gpxe/nap.h>
#include <realmode.h>
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* Save power by halting the CPU until the next interrupt
*
diff --git a/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c b/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c
index efaaef0d..094214bd 100644
--- a/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c
+++ b/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <string.h>
#include <errno.h>
diff --git a/gpxe/src/arch/i386/interface/pcbios/bios_timer.c b/gpxe/src/arch/i386/interface/pcbios/bios_timer.c
index 0b475ea3..8ecf7c12 100644
--- a/gpxe/src/arch/i386/interface/pcbios/bios_timer.c
+++ b/gpxe/src/arch/i386/interface/pcbios/bios_timer.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/** @file
*
* BIOS timer
diff --git a/gpxe/src/arch/i386/interface/pcbios/biosint.c b/gpxe/src/arch/i386/interface/pcbios/biosint.c
index 1306f918..a193defa 100644
--- a/gpxe/src/arch/i386/interface/pcbios/biosint.c
+++ b/gpxe/src/arch/i386/interface/pcbios/biosint.c
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* Hook INT vector
*
diff --git a/gpxe/src/arch/i386/interface/pcbios/ib_srpboot.c b/gpxe/src/arch/i386/interface/pcbios/ib_srpboot.c
new file mode 100644
index 00000000..b1cbc337
--- /dev/null
+++ b/gpxe/src/arch/i386/interface/pcbios/ib_srpboot.c
@@ -0,0 +1,73 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <gpxe/sanboot.h>
+#include <int13.h>
+#include <gpxe/srp.h>
+#include <gpxe/sbft.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+static int ib_srpboot ( const char *root_path ) {
+ struct scsi_device *scsi;
+ struct int13_drive *drive;
+ int rc;
+
+ scsi = zalloc ( sizeof ( *scsi ) );
+ if ( ! scsi ) {
+ rc = -ENOMEM;
+ goto err_alloc_scsi;
+ }
+ drive = zalloc ( sizeof ( *drive ) );
+ if ( ! drive ) {
+ rc = -ENOMEM;
+ goto err_alloc_drive;
+ }
+
+ if ( ( rc = srp_attach ( scsi, root_path ) ) != 0 ) {
+ printf ( "Could not attach IB_SRP device: %s\n",
+ strerror ( rc ) );
+ goto err_attach;
+ }
+ if ( ( rc = init_scsidev ( scsi ) ) != 0 ) {
+ printf ( "Could not initialise IB_SRP device: %s\n",
+ strerror ( rc ) );
+ goto err_init;
+ }
+
+ drive->blockdev = &scsi->blockdev;
+
+ /* FIXME: ugly, ugly hack */
+ struct srp_device *srp =
+ container_of ( scsi->backend, struct srp_device, refcnt );
+ sbft_fill_data ( srp );
+
+ register_int13_drive ( drive );
+ printf ( "Registered as BIOS drive %#02x\n", drive->drive );
+ printf ( "Booting from BIOS drive %#02x\n", drive->drive );
+ rc = int13_boot ( drive->drive );
+ printf ( "Boot failed\n" );
+
+ /* Leave drive registered, if instructed to do so */
+ if ( keep_san() )
+ return rc;
+
+ printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
+ unregister_int13_drive ( drive );
+
+ err_init:
+ srp_detach ( scsi );
+ err_attach:
+ free ( drive );
+ err_alloc_drive:
+ free ( scsi );
+ err_alloc_scsi:
+ return rc;
+}
+
+struct sanboot_protocol ib_srp_sanboot_protocol __sanboot_protocol = {
+ .prefix = "ib_srp:",
+ .boot = ib_srpboot,
+};
diff --git a/gpxe/src/arch/i386/interface/pcbios/ibft.c b/gpxe/src/arch/i386/interface/pcbios/ibft.c
index 43d1f85f..adf8e6b9 100644
--- a/gpxe/src/arch/i386/interface/pcbios/ibft.c
+++ b/gpxe/src/arch/i386/interface/pcbios/ibft.c
@@ -25,6 +25,8 @@
*
*/
+FILE_LICENCE ( BSD2 );
+
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -35,6 +37,7 @@
#include <gpxe/acpi.h>
#include <gpxe/in.h>
#include <gpxe/netdevice.h>
+#include <gpxe/ethernet.h>
#include <gpxe/dhcp.h>
#include <gpxe/iscsi.h>
#include <gpxe/ibft.h>
@@ -234,7 +237,8 @@ static int ibft_set_string_option ( struct ibft_string_block *strings,
*/
static const char * ibft_string ( struct ibft_string_block *strings,
struct ibft_string *string ) {
- return ( ( ( char * ) strings->table ) + string->offset );
+ return ( string->offset ?
+ ( ( ( char * ) strings->table ) + string->offset ) : NULL );
}
/**
@@ -248,6 +252,7 @@ static const char * ibft_string ( struct ibft_string_block *strings,
static int ibft_fill_nic ( struct ibft_nic *nic,
struct ibft_string_block *strings,
struct net_device *netdev ) {
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
struct in_addr netmask_addr = { 0 };
unsigned int netmask_count = 0;
int rc;
@@ -276,10 +281,12 @@ static int ibft_fill_nic ( struct ibft_nic *nic,
DBG ( "iBFT NIC subnet = /%d\n", nic->subnet_mask_prefix );
/* Extract values from net-device configuration */
- memcpy ( nic->mac_address, netdev->ll_addr,
- sizeof ( nic->mac_address ) );
- DBG ( "iBFT NIC MAC = %s\n",
- netdev->ll_protocol->ntoa ( nic->mac_address ) );
+ if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr,
+ nic->mac_address ) ) != 0 ) {
+ DBG ( "Could not determine iBFT MAC: %s\n", strerror ( rc ) );
+ return rc;
+ }
+ DBG ( "iBFT NIC MAC = %s\n", eth_ntoa ( nic->mac_address ) );
nic->pci_bus_dev_func = netdev->dev->desc.location;
DBG ( "iBFT NIC PCI = %04x\n", nic->pci_bus_dev_func );
diff --git a/gpxe/src/arch/i386/interface/pcbios/int13.c b/gpxe/src/arch/i386/interface/pcbios/int13.c
index 2e9de5cb..87b613a8 100644
--- a/gpxe/src/arch/i386/interface/pcbios/int13.c
+++ b/gpxe/src/arch/i386/interface/pcbios/int13.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <limits.h>
#include <byteswap.h>
@@ -50,6 +52,48 @@ extern void int13_wrapper ( void );
static LIST_HEAD ( drives );
/**
+ * Number of BIOS drives
+ *
+ * Note that this is the number of drives in the system as a whole
+ * (i.e. a mirror of the counter at 40:75), rather than a count of the
+ * number of emulated drives.
+ */
+static uint8_t num_drives;
+
+/**
+ * Update BIOS drive count
+ */
+static void int13_set_num_drives ( void ) {
+ struct int13_drive *drive;
+
+ /* Get current drive count */
+ get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
+
+ /* Ensure count is large enough to cover all of our emulated drives */
+ list_for_each_entry ( drive, &drives, list ) {
+ if ( num_drives <= ( drive->drive & 0x7f ) )
+ num_drives = ( ( drive->drive & 0x7f ) + 1 );
+ }
+
+ /* Update current drive count */
+ put_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
+}
+
+/**
+ * Check number of drives
+ */
+static void int13_check_num_drives ( void ) {
+ uint8_t check_num_drives;
+
+ get_real ( check_num_drives, BDA_SEG, BDA_NUM_DRIVES );
+ if ( check_num_drives != num_drives ) {
+ int13_set_num_drives();
+ DBG ( "INT13 fixing up number of drives from %d to %d\n",
+ check_num_drives, num_drives );
+ }
+}
+
+/**
* INT 13, 00 - Reset disk system
*
* @v drive Emulated drive
@@ -98,6 +142,7 @@ static int int13_rw_sectors ( struct int13_drive *drive,
unsigned long lba;
unsigned int count;
userptr_t buffer;
+ int rc;
/* Validate blocksize */
if ( blockdev->blksize != INT13_BLKSIZE ) {
@@ -122,8 +167,10 @@ static int int13_rw_sectors ( struct int13_drive *drive,
head, sector, lba, ix86->segs.es, ix86->regs.bx, count );
/* Read from / write to block device */
- if ( io ( blockdev, lba, count, buffer ) != 0 )
+ if ( ( rc = io ( blockdev, lba, count, buffer ) ) != 0 ) {
+ DBG ( "INT 13 failed: %s\n", strerror ( rc ) );
return -INT13_STATUS_READ_ERROR;
+ }
return 0;
}
@@ -202,9 +249,13 @@ static int int13_get_parameters ( struct int13_drive *drive,
*/
static int int13_get_disk_type ( struct int13_drive *drive,
struct i386_all_regs *ix86 ) {
+ uint32_t blocks;
+
DBG ( "Get disk type\n" );
- ix86->regs.cx = ( drive->cylinders >> 16 );
- ix86->regs.dx = ( drive->cylinders & 0xffff );
+ blocks = ( ( drive->blockdev->blocks <= 0xffffffffUL ) ?
+ drive->blockdev->blocks : 0xffffffffUL );
+ ix86->regs.cx = ( blocks >> 16 );
+ ix86->regs.dx = ( blocks & 0xffff );
return INT13_DISK_TYPE_HDD;
}
@@ -248,6 +299,7 @@ static int int13_extended_rw ( struct int13_drive *drive,
uint64_t lba;
unsigned long count;
userptr_t buffer;
+ int rc;
/* Read parameters from disk address structure */
copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si, sizeof ( addr ));
@@ -259,8 +311,10 @@ static int int13_extended_rw ( struct int13_drive *drive,
addr.buffer.segment, addr.buffer.offset, count );
/* Read from / write to block device */
- if ( io ( blockdev, lba, count, buffer ) != 0 )
+ if ( ( rc = io ( blockdev, lba, count, buffer ) ) != 0 ) {
+ DBG ( "INT 13 failed: %s\n", strerror ( rc ) );
return -INT13_STATUS_READ_ERROR;
+ }
return 0;
}
@@ -328,6 +382,9 @@ static __asmcall void int13 ( struct i386_all_regs *ix86 ) {
struct int13_drive *drive;
int status;
+ /* Check BIOS hasn't killed off our drive */
+ int13_check_num_drives();
+
list_for_each_entry ( drive, &drives, list ) {
if ( bios_drive != drive->drive ) {
@@ -387,7 +444,7 @@ static __asmcall void int13 ( struct i386_all_regs *ix86 ) {
/* Negative status indicates an error */
if ( status < 0 ) {
status = -status;
- DBG ( "INT13 failed with status %x\n", status );
+ DBG ( "INT 13 returning failure status %x\n", status );
} else {
ix86->flags &= ~CF;
}
@@ -543,7 +600,6 @@ void register_int13_drive ( struct int13_drive *drive ) {
/* Assign natural drive number */
get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
drive->natural_drive = ( num_drives | 0x80 );
- num_drives++;
/* Assign drive number */
if ( ( drive->drive & 0xff ) == 0xff ) {
@@ -552,13 +608,8 @@ void register_int13_drive ( struct int13_drive *drive ) {
} else {
/* Use specified drive number (+0x80 if necessary) */
drive->drive |= 0x80;
- if ( num_drives <= ( drive->drive & 0x7f ) )
- num_drives = ( ( drive->drive & 0x7f ) + 1 );
}
- /* Update BIOS drive count */
- put_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
-
DBG ( "Registered INT13 drive %02x (naturally %02x) with C/H/S "
"geometry %d/%d/%d\n", drive->drive, drive->natural_drive,
drive->cylinders, drive->heads, drive->sectors_per_track );
@@ -569,6 +620,9 @@ void register_int13_drive ( struct int13_drive *drive ) {
/* Add to list of emulated drives */
list_add ( &drive->list, &drives );
+
+ /* Update BIOS drive count */
+ int13_set_num_drives();
}
/**
@@ -652,7 +706,8 @@ int int13_boot ( unsigned int drive ) {
/* Jump to boot sector */
if ( ( rc = call_bootsector ( 0x0, 0x7c00, drive ) ) != 0 ) {
- DBG ( "INT 13 drive %02x boot returned\n", drive );
+ DBG ( "INT 13 drive %02x boot returned: %s\n",
+ drive, strerror ( rc ) );
return rc;
}
diff --git a/gpxe/src/arch/i386/interface/pcbios/iscsiboot.c b/gpxe/src/arch/i386/interface/pcbios/iscsiboot.c
index 02aec4ba..00efd8ff 100644
--- a/gpxe/src/arch/i386/interface/pcbios/iscsiboot.c
+++ b/gpxe/src/arch/i386/interface/pcbios/iscsiboot.c
@@ -4,26 +4,16 @@
#include <stdio.h>
#include <errno.h>
#include <gpxe/iscsi.h>
-#include <gpxe/settings.h>
-#include <gpxe/dhcp.h>
#include <gpxe/netdevice.h>
#include <gpxe/ibft.h>
-#include <gpxe/init.h>
#include <gpxe/sanboot.h>
#include <int13.h>
-#include <usr/autoboot.h>
-struct setting keep_san_setting __setting = {
- .name = "keep-san",
- .description = "Preserve SAN connection",
- .tag = DHCP_EB_KEEP_SAN,
- .type = &setting_type_int8,
-};
+FILE_LICENCE ( GPL2_OR_LATER );
static int iscsiboot ( const char *root_path ) {
struct scsi_device *scsi;
struct int13_drive *drive;
- int keep_san;
int rc;
scsi = zalloc ( sizeof ( *scsi ) );
@@ -37,8 +27,6 @@ static int iscsiboot ( const char *root_path ) {
goto err_alloc_drive;
}
- printf ( "iSCSI booting from %s\n", root_path );
-
if ( ( rc = iscsi_attach ( scsi, root_path ) ) != 0 ) {
printf ( "Could not attach iSCSI device: %s\n",
strerror ( rc ) );
@@ -65,12 +53,8 @@ static int iscsiboot ( const char *root_path ) {
printf ( "Boot failed\n" );
/* Leave drive registered, if instructed to do so */
- keep_san = fetch_intz_setting ( NULL, &keep_san_setting );
- if ( keep_san ) {
- printf ( "Preserving connection to SAN disk\n" );
- shutdown_exit_flags |= SHUTDOWN_KEEP_DEVICES;
+ if ( keep_san() )
return rc;
- }
printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
unregister_int13_drive ( drive );
diff --git a/gpxe/src/arch/i386/interface/pcbios/keepsan.c b/gpxe/src/arch/i386/interface/pcbios/keepsan.c
new file mode 100644
index 00000000..904e017d
--- /dev/null
+++ b/gpxe/src/arch/i386/interface/pcbios/keepsan.c
@@ -0,0 +1,26 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <gpxe/settings.h>
+#include <gpxe/dhcp.h>
+#include <gpxe/init.h>
+#include <gpxe/sanboot.h>
+#include <usr/autoboot.h>
+
+struct setting keep_san_setting __setting = {
+ .name = "keep-san",
+ .description = "Preserve SAN connection",
+ .tag = DHCP_EB_KEEP_SAN,
+ .type = &setting_type_int8,
+};
+
+int keep_san ( void ) {
+ int keep_san;
+
+ keep_san = fetch_intz_setting ( NULL, &keep_san_setting );
+ if ( ! keep_san )
+ return 0;
+
+ printf ( "Preserving connection to SAN disk\n" );
+ shutdown_exit_flags |= SHUTDOWN_KEEP_DEVICES;
+ return 1;
+}
diff --git a/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c b/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
index 744d8e30..0645fe63 100644
--- a/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
+++ b/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
diff --git a/gpxe/src/arch/i386/interface/pcbios/pcibios.c b/gpxe/src/arch/i386/interface/pcbios/pcibios.c
index 81b4fd3c..f2c3880c 100644
--- a/gpxe/src/arch/i386/interface/pcbios/pcibios.c
+++ b/gpxe/src/arch/i386/interface/pcbios/pcibios.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <gpxe/pci.h>
#include <realmode.h>
diff --git a/gpxe/src/arch/i386/interface/pcbios/sbft.c b/gpxe/src/arch/i386/interface/pcbios/sbft.c
new file mode 100644
index 00000000..12927c77
--- /dev/null
+++ b/gpxe/src/arch/i386/interface/pcbios/sbft.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FILE_LICENCE ( BSD2 );
+
+/** @file
+ *
+ * SRP boot firmware table
+ *
+ */
+
+#include <assert.h>
+#include <realmode.h>
+#include <gpxe/srp.h>
+#include <gpxe/ib_srp.h>
+#include <gpxe/acpi.h>
+#include <gpxe/sbft.h>
+
+#define sbftab __use_data16 ( sbftab )
+/** The sBFT used by gPXE */
+struct gpxe_sbft __data16 ( sbftab ) = {
+ /* Table header */
+ .table = {
+ /* ACPI header */
+ .acpi = {
+ .signature = SBFT_SIG,
+ .length = sizeof ( sbftab ),
+ .revision = 1,
+ .oem_id = "FENSYS",
+ .oem_table_id = "gPXE",
+ },
+ .scsi_offset = offsetof ( typeof ( sbftab ), scsi ),
+ .srp_offset = offsetof ( typeof ( sbftab ), srp ),
+ .ib_offset = offsetof ( typeof ( sbftab ), ib ),
+ },
+};
+
+/**
+ * Fill in all variable portions of sBFT
+ *
+ * @v srp SRP device
+ * @ret rc Return status code
+ */
+int sbft_fill_data ( struct srp_device *srp ) {
+ struct sbft_scsi_subtable *sbft_scsi = &sbftab.scsi;
+ struct sbft_srp_subtable *sbft_srp = &sbftab.srp;
+ struct sbft_ib_subtable *sbft_ib = &sbftab.ib;
+ struct ib_srp_parameters *ib_params;
+ struct segoff rm_sbftab = {
+ .segment = rm_ds,
+ .offset = __from_data16 ( &sbftab ),
+ };
+
+ /* Fill in the SCSI subtable */
+ memcpy ( &sbft_scsi->lun, &srp->lun, sizeof ( sbft_scsi->lun ) );
+
+ /* Fill in the SRP subtable */
+ memcpy ( &sbft_srp->port_ids, &srp->port_ids,
+ sizeof ( sbft_srp->port_ids ) );
+
+ /* Fill in the IB subtable */
+ assert ( srp->transport == &ib_srp_transport );
+ ib_params = ib_srp_params ( srp );
+ memcpy ( &sbft_ib->sgid, &ib_params->sgid, sizeof ( sbft_ib->sgid ) );
+ memcpy ( &sbft_ib->dgid, &ib_params->dgid, sizeof ( sbft_ib->dgid ) );
+ memcpy ( &sbft_ib->service_id, &ib_params->service_id,
+ sizeof ( sbft_ib->service_id ) );
+ sbft_ib->pkey = ib_params->pkey;
+
+ /* Update checksum */
+ acpi_fix_checksum ( &sbftab.table.acpi );
+
+ DBGC ( &sbftab, "SRP Boot Firmware Table at %04x:%04x:\n",
+ rm_sbftab.segment, rm_sbftab.offset );
+ DBGC_HDA ( &sbftab, rm_sbftab, &sbftab, sizeof ( sbftab ) );
+
+ return 0;
+}
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_call.c b/gpxe/src/arch/i386/interface/pxe/pxe_call.c
index 06dee25c..66a9b1e2 100644
--- a/gpxe/src/arch/i386/interface/pxe/pxe_call.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_call.c
@@ -16,7 +16,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/uaccess.h>
+#include <gpxe/init.h>
#include <registers.h>
#include <biosint.h>
#include <pxe.h>
@@ -34,6 +37,9 @@ extern struct segoff __text16 ( pxe_int_1a_vector );
/** INT 1A handler */
extern void pxe_int_1a ( void );
+/** INT 1A hooked flag */
+static int int_1a_hooked = 0;
+
/** A function pointer to hold any PXE API call
*
* Used by pxe_api_call() to avoid large swathes of duplicated code.
@@ -98,6 +104,7 @@ union pxenv_call {
PXENV_EXIT_t ( * get_file_size ) ( struct s_PXENV_GET_FILE_SIZE * );
PXENV_EXIT_t ( * file_exec ) ( struct s_PXENV_FILE_EXEC * );
PXENV_EXIT_t ( * file_api_check ) ( struct s_PXENV_FILE_API_CHECK * );
+ PXENV_EXIT_t ( * file_exit_hook ) ( struct s_PXENV_FILE_EXIT_HOOK * );
};
/**
@@ -304,6 +311,10 @@ __asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) {
pxenv_call.file_api_check = pxenv_file_api_check;
param_len = sizeof ( pxenv_any.file_api_check );
break;
+ case PXENV_FILE_EXIT_HOOK:
+ pxenv_call.file_exit_hook = pxenv_file_exit_hook;
+ param_len = sizeof ( pxenv_any.file_exit_hook );
+ break;
default:
DBG ( "PXENV_UNKNOWN_%hx", opcode );
pxenv_call.unknown = pxenv_unknown;
@@ -334,6 +345,18 @@ __asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) {
}
/**
+ * Dispatch weak PXE API call with PXE stack available
+ *
+ * @v ix86 Registers for PXE call
+ * @ret present Zero (PXE stack present)
+ */
+int _pxe_api_call_weak ( struct i386_all_regs *ix86 )
+{
+ pxe_api_call ( ix86 );
+ return 0;
+}
+
+/**
* Dispatch PXE loader call
*
* @v es:di Address of PXE parameter block
@@ -362,25 +385,6 @@ __asmcall void pxe_loader_call ( struct i386_all_regs *ix86 ) {
}
/**
- * Hook INT 1A for PXE
- *
- */
-void pxe_hook_int1a ( void ) {
- hook_bios_interrupt ( 0x1a, ( unsigned int ) pxe_int_1a,
- &pxe_int_1a_vector );
-}
-
-/**
- * Unhook INT 1A for PXE
- *
- * @ret rc Return status code
- */
-int pxe_unhook_int1a ( void ) {
- return unhook_bios_interrupt ( 0x1a, ( unsigned int ) pxe_int_1a,
- &pxe_int_1a_vector );
-}
-
-/**
* Calculate byte checksum as used by PXE
*
* @v data Data
@@ -401,7 +405,7 @@ static uint8_t pxe_checksum ( void *data, size_t size ) {
* Initialise !PXE and PXENV+ structures
*
*/
-void pxe_init_structures ( void ) {
+static void pxe_init_structures ( void ) {
uint32_t rm_cs_phys = ( rm_cs << 4 );
uint32_t rm_ds_phys = ( rm_ds << 4 );
@@ -427,6 +431,55 @@ void pxe_init_structures ( void ) {
pxenv.Checksum -= pxe_checksum ( &pxenv, sizeof ( pxenv ) );
}
+/** PXE structure initialiser */
+struct init_fn pxe_init_fn __init_fn ( INIT_NORMAL ) = {
+ .initialise = pxe_init_structures,
+};
+
+/**
+ * Activate PXE stack
+ *
+ * @v netdev Net device to use as PXE net device
+ */
+void pxe_activate ( struct net_device *netdev ) {
+
+ /* Ensure INT 1A is hooked */
+ if ( ! int_1a_hooked ) {
+ hook_bios_interrupt ( 0x1a, ( unsigned int ) pxe_int_1a,
+ &pxe_int_1a_vector );
+ int_1a_hooked = 1;
+ }
+
+ /* Set PXE network device */
+ pxe_set_netdev ( netdev );
+}
+
+/**
+ * Deactivate PXE stack
+ *
+ * @ret rc Return status code
+ */
+int pxe_deactivate ( void ) {
+ int rc;
+
+ /* Clear PXE network device */
+ pxe_set_netdev ( NULL );
+
+ /* Ensure INT 1A is unhooked, if possible */
+ if ( int_1a_hooked ) {
+ if ( ( rc = unhook_bios_interrupt ( 0x1a,
+ (unsigned int) pxe_int_1a,
+ &pxe_int_1a_vector ))!= 0){
+ DBG ( "Could not unhook INT 1A: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+ int_1a_hooked = 0;
+ }
+
+ return 0;
+}
+
/**
* Start PXE NBP at 0000:7c00
*
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_entry.S b/gpxe/src/arch/i386/interface/pxe/pxe_entry.S
index 0e8c8e2d..0d3a57cd 100644
--- a/gpxe/src/arch/i386/interface/pxe/pxe_entry.S
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_entry.S
@@ -17,6 +17,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER )
+
.arch i386
/****************************************************************************
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_file.c b/gpxe/src/arch/i386/interface/pxe/pxe_file.c
index 41674588..8d832123 100644
--- a/gpxe/src/arch/i386/interface/pxe/pxe_file.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_file.c
@@ -12,9 +12,12 @@
#include <gpxe/posix_io.h>
#include <gpxe/features.h>
#include <pxe.h>
+#include <realmode.h>
/*
* Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ * Portions (C) 2010 Shao Miller <shao.miller@yrdsb.edu.on.ca>.
+ * [PXE exit hook logic]
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -31,6 +34,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 2 );
/**
@@ -228,6 +233,9 @@ PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) {
return PXENV_EXIT_SUCCESS;
}
+segoff_t __data16 ( pxe_exit_hook ) = { 0, 0 };
+#define pxe_exit_hook __use_data16 ( pxe_exit_hook )
+
/**
* FILE API CHECK
*
@@ -258,7 +266,41 @@ PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_chec
file_api_check->Magic = 0xe9c17b20;
file_api_check->Provider = 0x45585067; /* "gPXE" */
file_api_check->APIMask = 0x0000007f; /* Functions e0-e6 */
+ /* Check to see if we have a PXE exit hook */
+ if ( pxe_exit_hook.segment | pxe_exit_hook.offset )
+ /* Function e7, also */
+ file_api_check->APIMask |= 0x00000080;
file_api_check->Flags = 0; /* None defined */
return PXENV_EXIT_SUCCESS;
}
}
+
+/**
+ * FILE EXIT HOOK
+ *
+ * @v file_exit_hook Pointer to a struct
+ * s_PXENV_FILE_EXIT_HOOK
+ * @v s_PXENV_FILE_EXIT_HOOK::Hook SEG16:OFF16 to jump to
+ * @ret #PXENV_EXIT_SUCCESS Successfully set hook
+ * @ret #PXENV_EXIT_FAILURE We're not an NBP build
+ * @ret s_PXENV_FILE_EXIT_HOOK::Status PXE status code
+ *
+ */
+PXENV_EXIT_t pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK
+ *file_exit_hook ) {
+ DBG ( "PXENV_FILE_EXIT_HOOK" );
+
+ /* Check to see if we have a PXE exit hook */
+ if ( pxe_exit_hook.segment | pxe_exit_hook.offset ) {
+ /* We'll jump to the specified SEG16:OFF16 during exit */
+ pxe_exit_hook.segment = file_exit_hook->Hook.segment;
+ pxe_exit_hook.offset = file_exit_hook->Hook.offset;
+ file_exit_hook->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
+ }
+
+ DBG ( " not NBP" );
+ file_exit_hook->Status = PXENV_STATUS_UNSUPPORTED;
+ return PXENV_EXIT_FAILURE;
+}
+
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_loader.c b/gpxe/src/arch/i386/interface/pxe/pxe_loader.c
index d228a36d..b35caf77 100644
--- a/gpxe/src/arch/i386/interface/pxe/pxe_loader.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_loader.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/init.h>
#include "pxe.h"
#include "pxe_call.h"
@@ -37,9 +39,6 @@ PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader ) {
DBG ( "[PXENV_UNDI_LOADER to CS %04x DS %04x]",
undi_loader->UNDI_CS, undi_loader->UNDI_DS );
- /* Set up PXE data structures */
- pxe_init_structures();
-
/* Fill in UNDI loader structure */
undi_loader->PXEptr.segment = rm_cs;
undi_loader->PXEptr.offset = __from_text16 ( &ppxe );
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_preboot.c b/gpxe/src/arch/i386/interface/pxe/pxe_preboot.c
index 193abc3d..3939c7bf 100644
--- a/gpxe/src/arch/i386/interface/pxe/pxe_preboot.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_preboot.c
@@ -23,6 +23,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
@@ -35,6 +37,7 @@
#include <gpxe/init.h>
#include <gpxe/if_ether.h>
#include <basemem_packet.h>
+#include <biosint.h>
#include "pxe.h"
#include "pxe_call.h"
@@ -294,11 +297,8 @@ PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) {
}
DBG ( " using netdev %s", netdev->name );
- /* Save as PXE net device */
- pxe_set_netdev ( netdev );
-
- /* Hook INT 1A */
- pxe_hook_int1a();
+ /* Activate PXE */
+ pxe_activate ( netdev );
start_undi->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
@@ -311,15 +311,20 @@ PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) {
PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ) {
DBG ( "PXENV_STOP_UNDI" );
- /* Unhook INT 1A */
- pxe_unhook_int1a();
-
- /* Clear PXE net device */
- pxe_set_netdev ( NULL );
+ /* Deactivate PXE */
+ pxe_deactivate();
/* Prepare for unload */
shutdown ( SHUTDOWN_BOOT );
+ /* Check to see if we still have any hooked interrupts */
+ if ( hooked_bios_interrupts != 0 ) {
+ DBG ( "PXENV_STOP_UNDI failed: %d interrupts still hooked\n",
+ hooked_bios_interrupts );
+ stop_undi->Status = PXENV_STATUS_KEEP_UNDI;
+ return PXENV_EXIT_FAILURE;
+ }
+
stop_undi->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
}
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_tftp.c b/gpxe/src/arch/i386/interface/pxe/pxe_tftp.c
index 715a0b61..0e3ca3c5 100644
--- a/gpxe/src/arch/i386/interface/pxe/pxe_tftp.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_tftp.c
@@ -22,6 +22,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
@@ -138,7 +140,7 @@ static void pxe_tftp_xfer_close ( struct xfer_interface *xfer __unused,
static struct xfer_interface_operations pxe_tftp_xfer_ops = {
.close = pxe_tftp_xfer_close,
- .vredirect = xfer_vopen,
+ .vredirect = xfer_vreopen,
.window = unlimited_xfer_window,
.alloc_iob = default_xfer_alloc_iob,
.deliver_iob = pxe_tftp_xfer_deliver_iob,
@@ -163,7 +165,8 @@ static struct xfer_interface_operations pxe_tftp_xfer_ops = {
* @ret rc Return status code
*/
static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port,
- const unsigned char *filename, size_t blksize ) {
+ const unsigned char *filename, size_t blksize,
+ int sizeonly ) {
char uri_string[PXE_TFTP_URI_LEN];
struct in_addr address;
int rc;
@@ -183,7 +186,8 @@ static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port,
if ( blksize < TFTP_DEFAULT_BLKSIZE )
blksize = TFTP_DEFAULT_BLKSIZE;
snprintf ( uri_string, sizeof ( uri_string ),
- "tftp://%s:%d%s%s?blksize=%zd",
+ "tftp%s://%s:%d%s%s?blksize=%zd",
+ sizeonly ? "size" : "",
inet_ntoa ( address ), ntohs ( port ),
( ( filename[0] == '/' ) ? "" : "/" ), filename, blksize );
DBG ( " %s", uri_string );
@@ -252,7 +256,8 @@ PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) {
if ( ( rc = pxe_tftp_open ( tftp_open->ServerIPAddress,
tftp_open->TFTPPort,
tftp_open->FileName,
- tftp_open->PacketSize ) ) != 0 ) {
+ tftp_open->PacketSize,
+ 0) ) != 0 ) {
tftp_open->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE;
}
@@ -486,7 +491,7 @@ PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
/* Open TFTP file */
if ( ( rc = pxe_tftp_open ( tftp_read_file->ServerIPAddress, 0,
- tftp_read_file->FileName, 0 ) ) != 0 ) {
+ tftp_read_file->FileName, 0, 0 ) ) != 0 ) {
tftp_read_file->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE;
}
@@ -556,7 +561,7 @@ PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE
/* Open TFTP file */
if ( ( rc = pxe_tftp_open ( tftp_get_fsize->ServerIPAddress, 0,
- tftp_get_fsize->FileName, 0 ) ) != 0 ) {
+ tftp_get_fsize->FileName, 0, 1 ) ) != 0 ) {
tftp_get_fsize->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE;
}
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_udp.c b/gpxe/src/arch/i386/interface/pxe/pxe_udp.c
index 033b1ad9..f4702201 100644
--- a/gpxe/src/arch/i386/interface/pxe/pxe_udp.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_udp.c
@@ -30,6 +30,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/** A PXE UDP connection */
struct pxe_udp_connection {
/** Data transfer interface to UDP stack */
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_undi.c b/gpxe/src/arch/i386/interface/pxe/pxe_undi.c
index 4e4a3da0..c9b67c06 100644
--- a/gpxe/src/arch/i386/interface/pxe/pxe_undi.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_undi.c
@@ -22,6 +22,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -88,12 +90,26 @@ static void pxe_netdev_close ( void ) {
undi_tx_count = 0;
}
+/**
+ * Dump multicast address list
+ *
+ * @v mcast PXE multicast address list
+ */
+static void pxe_dump_mcast_list ( struct s_PXENV_UNDI_MCAST_ADDRESS *mcast ) {
+ struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
+ unsigned int i;
+
+ for ( i = 0 ; i < mcast->MCastAddrCount ; i++ ) {
+ DBG ( " %s", ll_protocol->ntoa ( mcast->McastAddr[i] ) );
+ }
+}
+
/* PXENV_UNDI_STARTUP
*
* Status: working
*/
PXENV_EXIT_t pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) {
- DBG ( "PXENV_UNDI_STARTUP" );
+ DBG ( "PXENV_UNDI_STARTUP\n" );
undi_startup->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
@@ -104,7 +120,7 @@ PXENV_EXIT_t pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) {
* Status: working
*/
PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) {
- DBG ( "PXENV_UNDI_CLEANUP" );
+ DBG ( "PXENV_UNDI_CLEANUP\n" );
pxe_netdev_close();
@@ -118,7 +134,8 @@ PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) {
*/
PXENV_EXIT_t pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE
*undi_initialize ) {
- DBG ( "PXENV_UNDI_INITIALIZE" );
+ DBG ( "PXENV_UNDI_INITIALIZE protocolini %08x\n",
+ undi_initialize->ProtocolIni );
undi_initialize->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
@@ -133,9 +150,13 @@ PXENV_EXIT_t pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET
int rc;
DBG ( "PXENV_UNDI_RESET_ADAPTER" );
+ pxe_dump_mcast_list ( &undi_reset_adapter->R_Mcast_Buf );
+ DBG ( "\n" );
pxe_netdev_close();
if ( ( rc = pxe_netdev_open() ) != 0 ) {
+ DBG ( "PXENV_UNDI_RESET_ADAPTER could not reopen %s: %s\n",
+ pxe_netdev->name, strerror ( rc ) );
undi_reset_adapter->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE;
}
@@ -150,7 +171,7 @@ PXENV_EXIT_t pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET
*/
PXENV_EXIT_t pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN
*undi_shutdown ) {
- DBG ( "PXENV_UNDI_SHUTDOWN" );
+ DBG ( "PXENV_UNDI_SHUTDOWN\n" );
pxe_netdev_close();
@@ -165,9 +186,14 @@ PXENV_EXIT_t pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN
PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) {
int rc;
- DBG ( "PXENV_UNDI_OPEN" );
+ DBG ( "PXENV_UNDI_OPEN flag %04x filter %04x",
+ undi_open->OpenFlag, undi_open->PktFilter );
+ pxe_dump_mcast_list ( &undi_open->R_Mcast_Buf );
+ DBG ( "\n" );
if ( ( rc = pxe_netdev_open() ) != 0 ) {
+ DBG ( "PXENV_UNDI_OPEN could not open %s: %s\n",
+ pxe_netdev->name, strerror ( rc ) );
undi_open->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE;
}
@@ -181,7 +207,7 @@ PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) {
* Status: working
*/
PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) {
- DBG ( "PXENV_UNDI_CLOSE" );
+ DBG ( "PXENV_UNDI_CLOSE\n" );
pxe_netdev_close();
@@ -207,7 +233,13 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
unsigned int i;
int rc;
- DBG ( "PXENV_UNDI_TRANSMIT" );
+ DBG2 ( "PXENV_UNDI_TRANSMIT" );
+
+ /* Forcibly enable interrupts at this point, to work around
+ * callers that never call PXENV_UNDI_OPEN before attempting
+ * to use the UNDI API.
+ */
+ netdev_irq ( pxe_netdev, 1 );
/* Identify network-layer protocol */
switch ( undi_transmit->Protocol ) {
@@ -219,25 +251,29 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
ll_hlen = 0;
break;
default:
+ DBG2 ( " %02x invalid protocol\n", undi_transmit->Protocol );
undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
return PXENV_EXIT_FAILURE;
}
- DBG ( " %s", ( net_protocol ? net_protocol->name : "RAW" ) );
+ DBG2 ( " %s", ( net_protocol ? net_protocol->name : "RAW" ) );
/* Calculate total packet length */
copy_from_real ( &tbd, undi_transmit->TBD.segment,
undi_transmit->TBD.offset, sizeof ( tbd ) );
len = tbd.ImmedLength;
- DBG ( " %d", tbd.ImmedLength );
+ DBG2 ( " %04x:%04x+%x", tbd.Xmit.segment, tbd.Xmit.offset,
+ tbd.ImmedLength );
for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) {
datablk = &tbd.DataBlock[i];
len += datablk->TDDataLen;
- DBG ( "+%d", datablk->TDDataLen );
+ DBG2 ( " %04x:%04x+%x", datablk->TDDataPtr.segment,
+ datablk->TDDataPtr.offset, datablk->TDDataLen );
}
/* Allocate and fill I/O buffer */
iobuf = alloc_iob ( ll_hlen + len );
if ( ! iobuf ) {
+ DBG2 ( " could not allocate iobuf\n" );
undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES;
return PXENV_EXIT_FAILURE;
}
@@ -262,45 +298,57 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
undi_transmit->DestAddr.offset,
ll_protocol->ll_addr_len );
ll_dest = destaddr;
+ DBG2 ( " DEST %s", ll_protocol->ntoa ( ll_dest ) );
} else {
- DBG ( " BCAST" );
- ll_dest = ll_protocol->ll_broadcast;
+ ll_dest = pxe_netdev->ll_broadcast;
+ DBG2 ( " BCAST" );
}
/* Add link-layer header */
- if ( ( rc = ll_protocol->push ( iobuf, ll_dest,
+ if ( ( rc = ll_protocol->push ( pxe_netdev, iobuf, ll_dest,
pxe_netdev->ll_addr,
net_protocol->net_proto ))!=0){
+ DBG2 ( " could not add link-layer header: %s\n",
+ strerror ( rc ) );
free_iob ( iobuf );
undi_transmit->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE;
}
}
+ /* Flag transmission as in-progress. Do this before starting
+ * to transmit the packet, because the ISR may trigger before
+ * we return from netdev_tx().
+ */
+ undi_tx_count++;
+
/* Transmit packet */
+ DBG2 ( "\n" );
if ( ( rc = netdev_tx ( pxe_netdev, iobuf ) ) != 0 ) {
+ DBG2 ( "PXENV_UNDI_TRANSMIT could not transmit: %s\n",
+ strerror ( rc ) );
+ undi_tx_count--;
undi_transmit->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE;
}
- /* Flag transmission as in-progress */
- undi_tx_count++;
-
undi_transmit->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
}
/* PXENV_UNDI_SET_MCAST_ADDRESS
*
- * Status: stub (no PXE multicast support)
+ * Status: working (for NICs that support receive-all-multicast)
*/
PXENV_EXIT_t
pxenv_undi_set_mcast_address ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS
*undi_set_mcast_address ) {
DBG ( "PXENV_UNDI_SET_MCAST_ADDRESS" );
+ pxe_dump_mcast_list ( &undi_set_mcast_address->R_Mcast_Buf );
+ DBG ( "\n" );
- undi_set_mcast_address->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
+ undi_set_mcast_address->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
}
/* PXENV_UNDI_SET_STATION_ADDRESS
@@ -310,13 +358,16 @@ pxenv_undi_set_mcast_address ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS
PXENV_EXIT_t
pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS
*undi_set_station_address ) {
+ struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
- DBG ( "PXENV_UNDI_SET_STATION_ADDRESS" );
+ DBG ( "PXENV_UNDI_SET_STATION_ADDRESS %s",
+ ll_protocol->ntoa ( undi_set_station_address->StationAddress ) );
/* If adapter is open, the change will have no effect; return
* an error
*/
if ( pxe_netdev->state & NETDEV_OPEN ) {
+ DBG ( " failed: netdev is open\n" );
undi_set_station_address->Status =
PXENV_STATUS_UNDI_INVALID_STATE;
return PXENV_EXIT_FAILURE;
@@ -325,8 +376,9 @@ pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS
/* Update MAC address */
memcpy ( pxe_netdev->ll_addr,
&undi_set_station_address->StationAddress,
- pxe_netdev->ll_protocol->ll_addr_len );
+ ll_protocol->ll_addr_len );
+ DBG ( "\n" );
undi_set_station_address->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
}
@@ -339,10 +391,17 @@ pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS
PXENV_EXIT_t
pxenv_undi_set_packet_filter ( struct s_PXENV_UNDI_SET_PACKET_FILTER
*undi_set_packet_filter ) {
- DBG ( "PXENV_UNDI_SET_PACKET_FILTER" );
- undi_set_packet_filter->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
+ DBG ( "PXENV_UNDI_SET_PACKET_FILTER %02x\n",
+ undi_set_packet_filter->filter );
+
+ /* Pretend that we succeeded, otherwise the 3Com DOS UNDI
+ * driver refuses to load. (We ignore the filter value in the
+ * PXENV_UNDI_OPEN call anyway.)
+ */
+ undi_set_packet_filter->Status = PXENV_STATUS_SUCCESS;
+
+ return PXENV_EXIT_SUCCESS;
}
/* PXENV_UNDI_GET_INFORMATION
@@ -353,6 +412,7 @@ PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION
*undi_get_information ) {
struct device *dev = pxe_netdev->dev;
struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
+ size_t ll_addr_len = ll_protocol->ll_addr_len;
DBG ( "PXENV_UNDI_GET_INFORMATION" );
@@ -361,17 +421,14 @@ PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION
/* Cheat: assume all cards can cope with this */
undi_get_information->MaxTranUnit = ETH_MAX_MTU;
undi_get_information->HwType = ntohs ( ll_protocol->ll_proto );
- undi_get_information->HwAddrLen = ll_protocol->ll_addr_len;
- /* Cheat: assume card is always configured with its permanent
- * node address. This is a valid assumption within Etherboot
- * at the time of writing.
- */
+ undi_get_information->HwAddrLen = ll_addr_len;
+ assert ( ll_addr_len <=
+ sizeof ( undi_get_information->CurrentNodeAddress ) );
memcpy ( &undi_get_information->CurrentNodeAddress,
pxe_netdev->ll_addr,
sizeof ( undi_get_information->CurrentNodeAddress ) );
- memcpy ( &undi_get_information->PermNodeAddress,
- pxe_netdev->ll_addr,
- sizeof ( undi_get_information->PermNodeAddress ) );
+ ll_protocol->init_addr ( pxe_netdev->hw_addr,
+ &undi_get_information->PermNodeAddress );
undi_get_information->ROMAddress = 0;
/* nic.rom_info->rom_segment; */
/* We only provide the ability to receive or transmit a single
@@ -380,6 +437,10 @@ PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION
undi_get_information->RxBufCt = 1;
undi_get_information->TxBufCt = 1;
+ DBG ( " io %04x irq %d mtu %d %s %s\n",
+ undi_get_information->BaseIo, undi_get_information->IntNumber,
+ undi_get_information->MaxTranUnit, ll_protocol->name,
+ ll_protocol->ntoa ( &undi_get_information->CurrentNodeAddress ));
undi_get_information->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
}
@@ -397,6 +458,11 @@ PXENV_EXIT_t pxenv_undi_get_statistics ( struct s_PXENV_UNDI_GET_STATISTICS
undi_get_statistics->RcvCRCErrors = pxe_netdev->rx_stats.bad;
undi_get_statistics->RcvResourceErrors = pxe_netdev->rx_stats.bad;
+ DBG ( " txok %d rxok %d rxcrc %d rxrsrc %d\n",
+ undi_get_statistics->XmtGoodFrames,
+ undi_get_statistics->RcvGoodFrames,
+ undi_get_statistics->RcvCRCErrors,
+ undi_get_statistics->RcvResourceErrors );
undi_get_statistics->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
}
@@ -407,7 +473,7 @@ PXENV_EXIT_t pxenv_undi_get_statistics ( struct s_PXENV_UNDI_GET_STATISTICS
*/
PXENV_EXIT_t pxenv_undi_clear_statistics ( struct s_PXENV_UNDI_CLEAR_STATISTICS
*undi_clear_statistics ) {
- DBG ( "PXENV_UNDI_CLEAR_STATISTICS" );
+ DBG ( "PXENV_UNDI_CLEAR_STATISTICS\n" );
memset ( &pxe_netdev->tx_stats, 0, sizeof ( pxe_netdev->tx_stats ) );
memset ( &pxe_netdev->rx_stats, 0, sizeof ( pxe_netdev->rx_stats ) );
@@ -423,7 +489,7 @@ PXENV_EXIT_t pxenv_undi_clear_statistics ( struct s_PXENV_UNDI_CLEAR_STATISTICS
*/
PXENV_EXIT_t pxenv_undi_initiate_diags ( struct s_PXENV_UNDI_INITIATE_DIAGS
*undi_initiate_diags ) {
- DBG ( "PXENV_UNDI_INITIATE_DIAGS" );
+ DBG ( "PXENV_UNDI_INITIATE_DIAGS failed: unsupported\n" );
undi_initiate_diags->Status = PXENV_STATUS_UNSUPPORTED;
return PXENV_EXIT_FAILURE;
@@ -436,7 +502,7 @@ PXENV_EXIT_t pxenv_undi_initiate_diags ( struct s_PXENV_UNDI_INITIATE_DIAGS
*/
PXENV_EXIT_t pxenv_undi_force_interrupt ( struct s_PXENV_UNDI_FORCE_INTERRUPT
*undi_force_interrupt ) {
- DBG ( "PXENV_UNDI_FORCE_INTERRUPT" );
+ DBG ( "PXENV_UNDI_FORCE_INTERRUPT failed: unsupported\n" );
undi_force_interrupt->Status = PXENV_STATUS_UNSUPPORTED;
return PXENV_EXIT_FAILURE;
@@ -444,15 +510,28 @@ PXENV_EXIT_t pxenv_undi_force_interrupt ( struct s_PXENV_UNDI_FORCE_INTERRUPT
/* PXENV_UNDI_GET_MCAST_ADDRESS
*
- * Status: stub (no PXE multicast support)
+ * Status: working
*/
PXENV_EXIT_t
pxenv_undi_get_mcast_address ( struct s_PXENV_UNDI_GET_MCAST_ADDRESS
*undi_get_mcast_address ) {
- DBG ( "PXENV_UNDI_GET_MCAST_ADDRESS" );
+ struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
+ struct in_addr ip = { .s_addr = undi_get_mcast_address->InetAddr };
+ int rc;
- undi_get_mcast_address->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
+ DBG ( "PXENV_UNDI_GET_MCAST_ADDRESS %s", inet_ntoa ( ip ) );
+
+ if ( ( rc = ll_protocol->mc_hash ( AF_INET, &ip,
+ undi_get_mcast_address->MediaAddr ))!=0){
+ DBG ( " failed: %s\n", strerror ( rc ) );
+ undi_get_mcast_address->Status = PXENV_STATUS ( rc );
+ return PXENV_EXIT_FAILURE;
+ }
+ DBG ( "=>%s\n",
+ ll_protocol->ntoa ( undi_get_mcast_address->MediaAddr ) );
+
+ undi_get_mcast_address->Status = PXENV_STATUS_SUCCESS;
+ return PXENV_EXIT_SUCCESS;
}
/* PXENV_UNDI_GET_NIC_TYPE
@@ -484,6 +563,13 @@ PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE
*/
undi_get_nic_type->info.pci.SubVendor_ID = 0xffff;
undi_get_nic_type->info.pci.SubDevice_ID = 0xffff;
+ DBG ( " PCI %02x:%02x.%x %04x:%04x (%04x:%04x) %02x%02x%02x "
+ "rev %02x\n", PCI_BUS ( info->BusDevFunc ),
+ PCI_SLOT ( info->BusDevFunc ),
+ PCI_FUNC ( info->BusDevFunc ), info->Vendor_ID,
+ info->Dev_ID, info->SubVendor_ID, info->SubDevice_ID,
+ info->Base_Class, info->Sub_Class, info->Prog_Intf,
+ info->Rev );
break; }
case BUS_TYPE_ISAPNP: {
struct pnp_nic_info *info = &undi_get_nic_type->info.pnp;
@@ -495,8 +581,12 @@ PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE
/* Cheat: remaining fields are probably unnecessary,
* and would require adding extra code to isapnp.c.
*/
+ DBG ( " ISAPnP CSN %04x %08x %02x%02x%02x\n",
+ info->CardSelNum, info->EISA_Dev_ID,
+ info->Base_Class, info->Sub_Class, info->Prog_Intf );
break; }
default:
+ DBG ( " failed: unknown bus type\n" );
undi_get_nic_type->Status = PXENV_STATUS_FAILURE;
return PXENV_EXIT_FAILURE;
}
@@ -517,12 +607,18 @@ PXENV_EXIT_t pxenv_undi_get_iface_info ( struct s_PXENV_UNDI_GET_IFACE_INFO
* Most PXE stacks seem to take this approach.
*/
snprintf ( ( char * ) undi_get_iface_info->IfaceType,
- sizeof ( undi_get_iface_info->IfaceType ), "gPXE" );
+ sizeof ( undi_get_iface_info->IfaceType ), "DIX+802.3" );
undi_get_iface_info->LinkSpeed = 10000000; /* 10 Mbps */
- undi_get_iface_info->ServiceFlags = 0;
+ undi_get_iface_info->ServiceFlags =
+ ( SUPPORTED_BROADCAST | SUPPORTED_MULTICAST |
+ SUPPORTED_SET_STATION_ADDRESS | SUPPORTED_RESET |
+ SUPPORTED_OPEN_CLOSE | SUPPORTED_IRQ );
memset ( undi_get_iface_info->Reserved, 0,
sizeof(undi_get_iface_info->Reserved) );
+ DBG ( " %s %dbps flags %08x\n", undi_get_iface_info->IfaceType,
+ undi_get_iface_info->LinkSpeed,
+ undi_get_iface_info->ServiceFlags );
undi_get_iface_info->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
}
@@ -533,7 +629,7 @@ PXENV_EXIT_t pxenv_undi_get_iface_info ( struct s_PXENV_UNDI_GET_IFACE_INFO
*/
PXENV_EXIT_t pxenv_undi_get_state ( struct s_PXENV_UNDI_GET_STATE
*undi_get_state ) {
- DBG ( "PXENV_UNDI_GET_STATE" );
+ DBG ( "PXENV_UNDI_GET_STATE failed: unsupported\n" );
undi_get_state->Status = PXENV_STATUS_UNSUPPORTED;
return PXENV_EXIT_FAILURE;
@@ -555,7 +651,10 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
unsigned int prottype;
int rc;
- DBG ( "PXENV_UNDI_ISR" );
+ /* Use coloured debug, since UNDI ISR messages are likely to
+ * be interspersed amongst other UNDI messages.
+ */
+ DBGC2 ( &pxenv_undi_isr, "PXENV_UNDI_ISR" );
/* Just in case some idiot actually looks at these fields when
* we weren't meant to fill them in...
@@ -568,7 +667,7 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
switch ( undi_isr->FuncFlag ) {
case PXENV_UNDI_ISR_IN_START :
- DBG ( " START" );
+ DBGC2 ( &pxenv_undi_isr, " START" );
/* Call poll(). This should acknowledge the device
* interrupt and queue up any received packet.
@@ -579,13 +678,14 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
netdev_irq ( pxe_netdev, 0 );
/* Always say it was ours for the sake of simplicity */
+ DBGC2 ( &pxenv_undi_isr, " OURS" );
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS;
break;
case PXENV_UNDI_ISR_IN_PROCESS :
- DBG ( " PROCESS" );
- /* Fall through */
case PXENV_UNDI_ISR_IN_GET_NEXT :
- DBG ( " GET_NEXT" );
+ DBGC2 ( &pxenv_undi_isr, " %s",
+ ( ( undi_isr->FuncFlag == PXENV_UNDI_ISR_IN_PROCESS ) ?
+ "PROCESS" : "GET_NEXT" ) );
/* Some dumb NBPs (e.g. emBoot's winBoot/i) never call
* PXENV_UNDI_ISR with FuncFlag=PXENV_UNDI_ISR_START;
@@ -600,7 +700,7 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
* netdev TX queue is empty, report the TX completion.
*/
if ( undi_tx_count && list_empty ( &pxe_netdev->tx_queue ) ) {
- DBG ( " TXC" );
+ DBGC2 ( &pxenv_undi_isr, " TXC" );
undi_tx_count--;
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_TRANSMIT;
break;
@@ -609,7 +709,7 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
/* Remove first packet from netdev RX queue */
iobuf = netdev_rx_dequeue ( pxe_netdev );
if ( ! iobuf ) {
- DBG ( " DONE" );
+ DBGC2 ( &pxenv_undi_isr, " DONE" );
/* No more packets remaining */
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
/* Re-enable interrupts */
@@ -619,17 +719,18 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
/* Copy packet to base memory buffer */
len = iob_len ( iobuf );
- DBG ( " RX %zd", len );
+ DBGC2 ( &pxenv_undi_isr, " RX" );
if ( len > sizeof ( basemem_packet ) ) {
/* Should never happen */
+ DBGC2 ( &pxenv_undi_isr, " overlength (%zx)", len );
len = sizeof ( basemem_packet );
}
memcpy ( basemem_packet, iobuf->data, len );
/* Strip link-layer header */
ll_protocol = pxe_netdev->ll_protocol;
- if ( ( rc = ll_protocol->pull ( iobuf, &ll_dest, &ll_source,
- &net_proto ) ) != 0 ) {
+ if ( ( rc = ll_protocol->pull ( pxe_netdev, iobuf, &ll_dest,
+ &ll_source, &net_proto )) !=0){
/* Assume unknown net_proto and no ll_source */
net_proto = 0;
ll_source = NULL;
@@ -655,7 +756,6 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
prottype = P_UNKNOWN;
break;
}
- DBG ( " %s", ( net_protocol ? net_protocol->name : "RAW" ) );
/* Fill in UNDI_ISR structure */
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_RECEIVE;
@@ -666,12 +766,18 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
undi_isr->Frame.offset = __from_data16 ( basemem_packet );
undi_isr->ProtType = prottype;
undi_isr->PktType = XMT_DESTADDR;
+ DBGC2 ( &pxenv_undi_isr, " %04x:%04x+%x(%x) %s hlen %d",
+ undi_isr->Frame.segment, undi_isr->Frame.offset,
+ undi_isr->BufferLength, undi_isr->FrameLength,
+ ( net_protocol ? net_protocol->name : "RAW" ),
+ undi_isr->FrameHeaderLength );
/* Free packet */
free_iob ( iobuf );
break;
default :
- DBG ( " INVALID(%04x)", undi_isr->FuncFlag );
+ DBGC2 ( &pxenv_undi_isr, " INVALID(%04x)\n",
+ undi_isr->FuncFlag );
/* Should never happen */
undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
@@ -679,6 +785,7 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
return PXENV_EXIT_FAILURE;
}
+ DBGC2 ( &pxenv_undi_isr, "\n" );
undi_isr->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
}
diff --git a/gpxe/src/arch/i386/interface/pxeparent/pxeparent.c b/gpxe/src/arch/i386/interface/pxeparent/pxeparent.c
new file mode 100644
index 00000000..582db5d2
--- /dev/null
+++ b/gpxe/src/arch/i386/interface/pxeparent/pxeparent.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/dhcp.h>
+#include <pxeparent.h>
+#include <pxe_api.h>
+#include <pxe_types.h>
+#include <pxe.h>
+
+/** @file
+ *
+ * Call interface to parent PXE stack
+ *
+ */
+
+/**
+ * Name PXE API call
+ *
+ * @v function API call number
+ * @ret name API call name
+ */
+static inline __attribute__ (( always_inline )) const char *
+pxeparent_function_name ( unsigned int function ) {
+ switch ( function ) {
+ case PXENV_START_UNDI:
+ return "PXENV_START_UNDI";
+ case PXENV_STOP_UNDI:
+ return "PXENV_STOP_UNDI";
+ case PXENV_UNDI_STARTUP:
+ return "PXENV_UNDI_STARTUP";
+ case PXENV_UNDI_CLEANUP:
+ return "PXENV_UNDI_CLEANUP";
+ case PXENV_UNDI_INITIALIZE:
+ return "PXENV_UNDI_INITIALIZE";
+ case PXENV_UNDI_RESET_ADAPTER:
+ return "PXENV_UNDI_RESET_ADAPTER";
+ case PXENV_UNDI_SHUTDOWN:
+ return "PXENV_UNDI_SHUTDOWN";
+ case PXENV_UNDI_OPEN:
+ return "PXENV_UNDI_OPEN";
+ case PXENV_UNDI_CLOSE:
+ return "PXENV_UNDI_CLOSE";
+ case PXENV_UNDI_TRANSMIT:
+ return "PXENV_UNDI_TRANSMIT";
+ case PXENV_UNDI_SET_MCAST_ADDRESS:
+ return "PXENV_UNDI_SET_MCAST_ADDRESS";
+ case PXENV_UNDI_SET_STATION_ADDRESS:
+ return "PXENV_UNDI_SET_STATION_ADDRESS";
+ case PXENV_UNDI_SET_PACKET_FILTER:
+ return "PXENV_UNDI_SET_PACKET_FILTER";
+ case PXENV_UNDI_GET_INFORMATION:
+ return "PXENV_UNDI_GET_INFORMATION";
+ case PXENV_UNDI_GET_STATISTICS:
+ return "PXENV_UNDI_GET_STATISTICS";
+ case PXENV_UNDI_CLEAR_STATISTICS:
+ return "PXENV_UNDI_CLEAR_STATISTICS";
+ case PXENV_UNDI_INITIATE_DIAGS:
+ return "PXENV_UNDI_INITIATE_DIAGS";
+ case PXENV_UNDI_FORCE_INTERRUPT:
+ return "PXENV_UNDI_FORCE_INTERRUPT";
+ case PXENV_UNDI_GET_MCAST_ADDRESS:
+ return "PXENV_UNDI_GET_MCAST_ADDRESS";
+ case PXENV_UNDI_GET_NIC_TYPE:
+ return "PXENV_UNDI_GET_NIC_TYPE";
+ case PXENV_UNDI_GET_IFACE_INFO:
+ return "PXENV_UNDI_GET_IFACE_INFO";
+ /*
+ * Duplicate case value; this is a bug in the PXE specification.
+ *
+ * case PXENV_UNDI_GET_STATE:
+ * return "PXENV_UNDI_GET_STATE";
+ */
+ case PXENV_UNDI_ISR:
+ return "PXENV_UNDI_ISR";
+ case PXENV_GET_CACHED_INFO:
+ return "PXENV_GET_CACHED_INFO";
+ default:
+ return "UNKNOWN API CALL";
+ }
+}
+
+/**
+ * PXE parent parameter block
+ *
+ * Used as the paramter block for all parent PXE API calls. Resides in base
+ * memory.
+ */
+static union u_PXENV_ANY __bss16 ( pxeparent_params );
+#define pxeparent_params __use_data16 ( pxeparent_params )
+
+/** PXE parent entry point
+ *
+ * Used as the indirection vector for all parent PXE API calls. Resides in
+ * base memory.
+ */
+SEGOFF16_t __bss16 ( pxeparent_entry_point );
+#define pxeparent_entry_point __use_data16 ( pxeparent_entry_point )
+
+/**
+ * Issue parent PXE API call
+ *
+ * @v entry Parent PXE stack entry point
+ * @v function API call number
+ * @v params PXE parameter block
+ * @v params_len Length of PXE parameter block
+ * @ret rc Return status code
+ */
+int pxeparent_call ( SEGOFF16_t entry, unsigned int function,
+ void *params, size_t params_len ) {
+ PXENV_EXIT_t exit;
+ int discard_b, discard_D;
+ int rc;
+
+ /* Copy parameter block and entry point */
+ assert ( params_len <= sizeof ( pxeparent_params ) );
+ memcpy ( &pxeparent_params, params, params_len );
+ memcpy ( &pxeparent_entry_point, &entry, sizeof ( entry ) );
+
+ /* Call real-mode entry point. This calling convention will
+ * work with both the !PXE and the PXENV+ entry points.
+ */
+ __asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t"
+ "pushw %%di\n\t"
+ "pushw %%bx\n\t"
+ "lcall *pxeparent_entry_point\n\t"
+ "addw $6, %%sp\n\t" )
+ : "=a" ( exit ), "=b" ( discard_b ),
+ "=D" ( discard_D )
+ : "b" ( function ),
+ "D" ( __from_data16 ( &pxeparent_params ) )
+ : "ecx", "edx", "esi", "ebp" );
+
+ /* PXE API calls may rudely change the status of A20 and not
+ * bother to restore it afterwards. Intel is known to be
+ * guilty of this.
+ *
+ * Note that we will return to this point even if A20 gets
+ * screwed up by the parent PXE stack, because Etherboot always
+ * resides in an even megabyte of RAM.
+ */
+ gateA20_set();
+
+ /* Determine return status code based on PXENV_EXIT and
+ * PXENV_STATUS
+ */
+ if ( exit == PXENV_EXIT_SUCCESS ) {
+ rc = 0;
+ } else {
+ rc = -pxeparent_params.Status;
+ /* Paranoia; don't return success for the combination
+ * of PXENV_EXIT_FAILURE but PXENV_STATUS_SUCCESS
+ */
+ if ( rc == 0 )
+ rc = -EIO;
+ }
+
+ /* If anything goes wrong, print as much debug information as
+ * it's possible to give.
+ */
+ if ( rc != 0 ) {
+ SEGOFF16_t rm_params = {
+ .segment = rm_ds,
+ .offset = __from_data16 ( &pxeparent_params ),
+ };
+
+ DBG ( "PXEPARENT %s failed: %s\n",
+ pxeparent_function_name ( function ), strerror ( rc ) );
+ DBG ( "PXEPARENT parameters at %04x:%04x length "
+ "%#02zx, entry point at %04x:%04x\n",
+ rm_params.segment, rm_params.offset, params_len,
+ pxeparent_entry_point.segment,
+ pxeparent_entry_point.offset );
+ DBG ( "PXEPARENT parameters provided:\n" );
+ DBG_HDA ( rm_params, params, params_len );
+ DBG ( "PXEPARENT parameters returned:\n" );
+ DBG_HDA ( rm_params, &pxeparent_params, params_len );
+ }
+
+ /* Copy parameter block back */
+ memcpy ( params, &pxeparent_params, params_len );
+
+ return rc;
+}
+
diff --git a/gpxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c b/gpxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c
new file mode 100644
index 00000000..66059437
--- /dev/null
+++ b/gpxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <gpxe/dhcp.h>
+#include <gpxe/netdevice.h>
+#include <undipreload.h>
+#include <pxeparent.h>
+#include <realmode.h>
+#include <pxe_api.h>
+
+/**
+ * Present cached DHCP packet if it exists
+ */
+void __weak_impl ( get_cached_dhcpack ) ( void ) {
+ struct undi_device *undi;
+ struct s_PXENV_GET_CACHED_INFO get_cached_info;
+ int rc;
+
+ /* Use preloaded UNDI device to get at PXE entry point */
+ undi = &preloaded_undi;
+ if ( ! undi->entry.segment ) {
+ DBG ( "PXEDHCP no preloaded UNDI device found\n" );
+ return;
+ }
+
+ /* Check that stack is available to get cached info */
+ if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) {
+ DBG ( "PXEDHCP stack was unloaded, no cache available\n" );
+ return;
+ }
+
+ /* Obtain cached DHCP packet */
+ memset ( &get_cached_info, 0, sizeof ( get_cached_info ) );
+ get_cached_info.PacketType = PXENV_PACKET_TYPE_DHCP_ACK;
+
+ if ( ( rc = pxeparent_call ( undi->entry, PXENV_GET_CACHED_INFO,
+ &get_cached_info,
+ sizeof ( get_cached_info ) ) ) != 0 ) {
+ DBG ( "PXEDHCP GET_CACHED_INFO failed: %s\n", strerror ( rc ) );
+ return;
+ }
+
+ DBG ( "PXEDHCP got cached info at %04x:%04x length %d\n",
+ get_cached_info.Buffer.segment, get_cached_info.Buffer.offset,
+ get_cached_info.BufferSize );
+
+ /* Present cached DHCP packet */
+ store_cached_dhcpack ( real_to_user ( get_cached_info.Buffer.segment,
+ get_cached_info.Buffer.offset ),
+ get_cached_info.BufferSize );
+}
diff --git a/gpxe/src/arch/i386/interface/syslinux/com32_call.c b/gpxe/src/arch/i386/interface/syslinux/com32_call.c
index 4a782dce..d2c3f918 100644
--- a/gpxe/src/arch/i386/interface/syslinux/com32_call.c
+++ b/gpxe/src/arch/i386/interface/syslinux/com32_call.c
@@ -21,6 +21,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <realmode.h>
#include <comboot.h>
diff --git a/gpxe/src/arch/i386/interface/syslinux/com32_wrapper.S b/gpxe/src/arch/i386/interface/syslinux/com32_wrapper.S
index 08d7398a..5c5bd139 100644
--- a/gpxe/src/arch/i386/interface/syslinux/com32_wrapper.S
+++ b/gpxe/src/arch/i386/interface/syslinux/com32_wrapper.S
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER )
+
.text
.arch i386
.code32
diff --git a/gpxe/src/arch/i386/interface/syslinux/comboot_call.c b/gpxe/src/arch/i386/interface/syslinux/comboot_call.c
index bf6c4c66..0a17bf13 100644
--- a/gpxe/src/arch/i386/interface/syslinux/comboot_call.c
+++ b/gpxe/src/arch/i386/interface/syslinux/comboot_call.c
@@ -21,6 +21,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <errno.h>
#include <realmode.h>
#include <biosint.h>
@@ -37,6 +39,8 @@
#include <gpxe/init.h>
#include <gpxe/image.h>
#include <usr/imgmgmt.h>
+#include "config/console.h"
+#include "config/serial.h"
/** The "SYSLINUX" version string */
static char __data16_array ( syslinux_version, [] ) = "gPXE " VERSION;
@@ -324,7 +328,7 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
case 0x0001: /* Get Version */
/* Number of INT 22h API functions available */
- ix86->regs.ax = 0x001B;
+ ix86->regs.ax = 0x001D;
/* SYSLINUX version number */
ix86->regs.ch = 0; /* major */
@@ -441,8 +445,10 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
break;
case 0x0009: /* Call PXE Stack */
- pxe_api_call ( ix86 );
- ix86->flags &= ~CF;
+ if ( pxe_api_call_weak ( ix86 ) != 0 )
+ ix86->flags |= CF;
+ else
+ ix86->flags &= ~CF;
break;
case 0x000A: /* Get Derivative-Specific Information */
@@ -454,8 +460,14 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
break;
case 0x000B: /* Get Serial Console Configuration */
- /* FIXME: stub */
+#if defined(CONSOLE_SERIAL) && !defined(COMPRESERVE)
+ ix86->regs.dx = COMCONSOLE;
+ ix86->regs.cx = 115200 / COMSPEED;
+ ix86->regs.bx = 0;
+#else
ix86->regs.dx = 0;
+#endif
+
ix86->flags &= ~CF;
break;
@@ -629,6 +641,17 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
break;
+ case 0x001C: /* Get pointer to auxilliary data vector */
+ /* FIXME: stub */
+ ix86->regs.cx = 0; /* Size of the ADV */
+ ix86->flags &= ~CF;
+ break;
+
+ case 0x001D: /* Write auxilliary data vector */
+ /* FIXME: stub */
+ ix86->flags &= ~CF;
+ break;
+
default:
DBG ( "COMBOOT unknown int22 function %04x\n", ix86->regs.ax );
break;
diff --git a/gpxe/src/arch/i386/interface/syslinux/comboot_resolv.c b/gpxe/src/arch/i386/interface/syslinux/comboot_resolv.c
index 41c3af7a..30ac502e 100644
--- a/gpxe/src/arch/i386/interface/syslinux/comboot_resolv.c
+++ b/gpxe/src/arch/i386/interface/syslinux/comboot_resolv.c
@@ -5,6 +5,8 @@
#include <gpxe/process.h>
#include <gpxe/resolv.h>
+FILE_LICENCE ( GPL2_OR_LATER );
+
static int comboot_resolv_rc;
static struct in_addr comboot_resolv_addr;
diff --git a/gpxe/src/arch/i386/prefix/bImageprefix.S b/gpxe/src/arch/i386/prefix/bImageprefix.S
deleted file mode 100644
index 30020f73..00000000
--- a/gpxe/src/arch/i386/prefix/bImageprefix.S
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- Copyright (C) 2000, Entity Cyber, Inc.
-
- Authors: Gary Byers (gb@thinguin.org)
- Marty Connor (mdc@thinguin.org)
- Eric Biederman (ebiederman@lnxi.com)
-
- This code also derives a lot from arch/i386/boot/setup.S in
- the linux kernel.
-
- This software may be used and distributed according to the terms
- of the GNU Public License (GPL), incorporated herein by reference.
-
- Description:
-
- This is just a little bit of code and data that can get prepended
- to an Etherboot ROM image in order to allow LILO to load the
- result as if it were a Linux kernel image.
-
- A real Linux kernel image consists of a one-sector boot loader
- (to load the image from a floppy disk), followed a few sectors
- of setup code, followed by the kernel code itself. There's
- a table in the first sector (starting at offset 497) that indicates
- how many sectors of setup code follow the first sector and which
- contains some other parameters that aren't interesting in this
- case.
-
- When LILO loads the sectors that comprise a kernel image, it doesn't
- execute the code in the first sector (since that code would try to
- load the image from a floppy disk.) The code in the first sector
- below doesn't expect to get executed (and prints an error message
- if it ever -is- executed.) LILO's only interested in knowing the
- number of setup sectors advertised in the table (at offset 497 in
- the first sector.)
-
- Etherboot doesn't require much in the way of setup code.
- Historically, the Linux kernel required at least 4 sectors of
- setup code. Current versions of LILO look at the byte at
- offset 497 in the first sector to indicate how many sectors
- of setup code are contained in the image.
-
- The setup code that is present here does a lot of things
- exactly the way the linux kernel does them instead of in
- ways more typical of etherboot. Generally this is so
- the code can be strongly compatible with the linux kernel.
- In addition the general etherboot technique of enabling the a20
- after we switch into protected mode does not work if etherboot
- is being loaded at 1MB.
-*/
-
- .equ CR0_PE,1
-
-#ifdef GAS291
-#define DATA32 data32;
-#define ADDR32 addr32;
-#define LJMPI(x) ljmp x
-#else
-#define DATA32 data32
-#define ADDR32 addr32
-/* newer GAS295 require #define LJMPI(x) ljmp *x */
-#define LJMPI(x) ljmp x
-#endif
-
-/* Simple and small GDT entries for booting only */
-#define GDT_ENTRY_BOOT_CS 2
-#define GDT_ENTRY_BOOT_DS (GDT_ENTRY_BOOT_CS + 1)
-#define __BOOT_CS (GDT_ENTRY_BOOT_CS * 8)
-#define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8)
-
-
-#define SETUPSECS 4 /* Minimal nr of setup-sectors */
-#define PREFIXSIZE ((SETUPSECS+1)*512)
-#define PREFIXPGH (PREFIXSIZE / 16 )
-#define BOOTSEG 0x07C0 /* original address of boot-sector */
-#define INITSEG 0x9000 /* we move boot here - out of the way */
-#define SETUPSEG 0x9020 /* setup starts here */
-#define SYSSEG 0x1000 /* system loaded at 0x10000 (65536). */
-
-#define DELTA_INITSEG (SETUPSEG - INITSEG) /* 0x0020 */
-
-/* Signature words to ensure LILO loaded us right */
-#define SIG1 0xAA55
-#define SIG2 0x5A5A
-
- .text
- .code16
- .arch i386
- .org 0
- .section ".prefix", "ax", @progbits
-_prefix:
-
-/*
- This is a minimal boot sector. If anyone tries to execute it (e.g., if
- a .lkrn file is dd'ed to a floppy), print an error message.
-*/
-
-bootsector:
- jmp $BOOTSEG, $go - _prefix /* reload cs:ip to match relocation addr */
-go:
- movw $0x2000, %di /* 0x2000 is arbitrary value >= length
- of bootsect + room for stack */
-
- movw $BOOTSEG, %ax
- movw %ax,%ds
- movw %ax,%es
-
- cli
- movw %ax, %ss /* put stack at BOOTSEG:0x2000. */
- movw %di,%sp
- sti
-
- movw $why_end-why, %cx
- movw $why - _prefix, %si
-
- movw $0x0007, %bx /* page 0, attribute 7 (normal) */
- movb $0x0e, %ah /* write char, tty mode */
-prloop:
- lodsb
- int $0x10
- loop prloop
-freeze: jmp freeze
-
-why: .ascii "This image cannot be loaded from a floppy disk.\r\n"
-why_end:
-
-
- .org 497
-setup_sects:
- .byte SETUPSECS
-root_flags:
- .word 0
-syssize:
- .word _verbatim_size_pgh - PREFIXPGH
-swap_dev:
- .word 0
-ram_size:
- .word 0
-vid_mode:
- .word 0
-root_dev:
- .word 0
-boot_flag:
- .word 0xAA55
-
-/*
- We're now at the beginning of the second sector of the image -
- where the setup code goes.
-
- We don't need to do too much setup for Etherboot.
-
- This code gets loaded at SETUPSEG:0. It wants to start
- executing the Etherboot image that's loaded at SYSSEG:0 and
- whose entry point is SYSSEG:0.
-*/
-setup_code:
- jmp trampoline
-# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
-
- .ascii "HdrS" # header signature
- .word 0x0203 # header version number (>= 0x0105)
- # or else old loadlin-1.5 will fail)
-realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
-start_sys_seg: .word SYSSEG # low load segment (obsolete)
- .word kernel_version - setup_code
- # pointing to kernel version string
- # above section of header is compatible
- # with loadlin-1.5 (header v1.5). Don't
- # change it.
-
-type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin,
- # Bootlin, SYSLX, bootsect...)
- # See Documentation/i386/boot.txt for
- # assigned ids
-
-# flags, unused bits must be zero (RFU) bit within loadflags
-loadflags:
-LOADED_HIGH = 1 # If set, the kernel is loaded high
-CAN_USE_HEAP = 0x80 # If set, the loader also has set
- # heap_end_ptr to tell how much
- # space behind setup.S can be used for
- # heap purposes.
- # Only the loader knows what is free
- .byte LOADED_HIGH
-
-setup_move_size: .word 0x8000 # size to move, when setup is not
- # loaded at 0x90000. We will move setup
- # to 0x90000 then just before jumping
- # into the kernel. However, only the
- # loader knows how much data behind
- # us also needs to be loaded.
-
-code32_start: # here loaders can put a different
- # start address for 32-bit code.
- .long 0x100000 # 0x100000 = default for big kernel
-
-ramdisk_image: .long 0 # address of loaded ramdisk image
- # Here the loader puts the 32-bit
- # address where it loaded the image.
- # This only will be read by the kernel.
-
-ramdisk_size: .long 0 # its size in bytes
-
-bootsect_kludge:
- .long 0 # obsolete
-
-heap_end_ptr: .word 0 # (Header version 0x0201 or later)
- # space from here (exclusive) down to
- # end of setup code can be used by setup
- # for local heap purposes.
-
-pad1: .word 0
-cmd_line_ptr: .long 0 # (Header version 0x0202 or later)
- # If nonzero, a 32-bit pointer
- # to the kernel command line.
- # The command line should be
- # located between the start of
- # setup and the end of low
- # memory (0xa0000), or it may
- # get overwritten before it
- # gets read. If this field is
- # used, there is no longer
- # anything magical about the
- # 0x90000 segment; the setup
- # can be located anywhere in
- # low memory 0x10000 or higher.
-
-ramdisk_max: .long 0 # (Header version 0x0203 or later)
- # The highest safe address for
- # the contents of an initrd
-
-trampoline: call start_of_setup
-trampoline_end:
- .space 1024
-# End of setup header #####################################################
-
-start_of_setup:
-# Set %ds = %cs, we know that SETUPSEG = %cs at this point
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %ds
-# Check signature at end of setup
- cmpw $SIG1, (setup_sig1 - setup_code)
- jne bad_sig
-
- cmpw $SIG2, (setup_sig2 - setup_code)
- jne bad_sig
-
- jmp good_sig1
-
-# Routine to print asciiz string at ds:si
-prtstr:
- lodsb
- andb %al, %al
- jz fin
-
- call prtchr
- jmp prtstr
-
-fin: ret
-
-# Part of above routine, this one just prints ascii al
-prtchr: pushw %ax
- pushw %cx
- movw $7,%bx
- movw $0x01, %cx
- movb $0x0e, %ah
- int $0x10
- popw %cx
- popw %ax
- ret
-
-no_sig_mess: .string "No setup signature found ..."
-
-good_sig1:
- jmp good_sig
-
-# We now have to find the rest of the setup code/data
-bad_sig:
- movw %cs, %ax # SETUPSEG
- subw $DELTA_INITSEG, %ax # INITSEG
- movw %ax, %ds
- xorb %bh, %bh
- movb (497), %bl # get setup sect from bootsect
- subw $4, %bx # LILO loads 4 sectors of setup
- shlw $8, %bx # convert to words (1sect=2^8 words)
- movw %bx, %cx
- shrw $3, %bx # convert to segment
- addw $SYSSEG, %bx
- movw %bx, %cs:(start_sys_seg - setup_code)
-# Move rest of setup code/data to here
- movw $2048, %di # four sectors loaded by LILO
- subw %si, %si
- pushw %cs
- popw %es
- movw $SYSSEG, %ax
- movw %ax, %ds
- rep
- movsw
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %ds
- cmpw $SIG1, (setup_sig1 - setup_code)
- jne no_sig
-
- cmpw $SIG2, (setup_sig2 - setup_code)
- jne no_sig
-
- jmp good_sig
-
-no_sig:
- lea (no_sig_mess - setup_code), %si
- call prtstr
-
-no_sig_loop:
- hlt
- jmp no_sig_loop
-
-good_sig:
- cmpw $0, %cs:(realmode_swtch - setup_code)
- jz rmodeswtch_normal
-
- lcall *%cs:(realmode_swtch - setup_code)
- jmp rmodeswtch_end
-
-rmodeswtch_normal:
- pushw %cs
- call default_switch
-
-rmodeswtch_end:
-# we get the code32 start address and modify the below 'jmpi'
-# (loader may have changed it)
- movl %cs:(code32_start - setup_code), %eax
- movl %eax, %cs:(code32 - setup_code)
-
-# then we load the segment descriptors
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %ds
-
-#
-# Enable A20. This is at the very best an annoying procedure.
-# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin.
-#
-
-A20_TEST_LOOPS = 32 # Iterations per wait
-A20_ENABLE_LOOPS = 255 # Total loops to try
-
-a20_try_loop:
-
- # First, see if we are on a system with no A20 gate.
-a20_none:
- call a20_test
- jnz a20_done
-
- # Next, try the BIOS (INT 0x15, AX=0x2401)
-a20_bios:
- movw $0x2401, %ax
- pushfl # Be paranoid about flags
- int $0x15
- popfl
-
- call a20_test
- jnz a20_done
-
- # Try enabling A20 through the keyboard controller
-a20_kbc:
- call empty_8042
-
- call a20_test # Just in case the BIOS worked
- jnz a20_done # but had a delayed reaction.
-
- movb $0xD1, %al # command write
- outb %al, $0x64
- call empty_8042
-
- movb $0xDF, %al # A20 on
- outb %al, $0x60
- call empty_8042
-
- # Wait until a20 really *is* enabled; it can take a fair amount of
- # time on certain systems; Toshiba Tecras are known to have this
- # problem.
-a20_kbc_wait:
- xorw %cx, %cx
-a20_kbc_wait_loop:
- call a20_test
- jnz a20_done
- loop a20_kbc_wait_loop
-
- # Final attempt: use "configuration port A"
-a20_fast:
- inb $0x92, %al # Configuration Port A
- orb $0x02, %al # "fast A20" version
- andb $0xFE, %al # don't accidentally reset
- outb %al, $0x92
-
- # Wait for configuration port A to take effect
-a20_fast_wait:
- xorw %cx, %cx
-a20_fast_wait_loop:
- call a20_test
- jnz a20_done
- loop a20_fast_wait_loop
-
- # A20 is still not responding. Try frobbing it again.
- #
- decb (a20_tries - setup_code)
- jnz a20_try_loop
-
- movw $(a20_err_msg - setup_code), %si
- call prtstr
-
-a20_die:
- hlt
- jmp a20_die
-
-a20_tries:
- .byte A20_ENABLE_LOOPS
-
-a20_err_msg:
- .ascii "linux: fatal error: A20 gate not responding!"
- .byte 13, 10, 0
-
- # If we get here, all is good
-a20_done:
- # Leave the idt alone
-
- # set up gdt
- xorl %eax, %eax # Compute gdt_base
- movw %ds, %ax # (Convert %ds:gdt to a linear ptr)
- shll $4, %eax
- addl $(bImage_gdt - setup_code), %eax
- movl %eax, (bImage_gdt_48+2 - setup_code)
- DATA32 lgdt %ds:(bImage_gdt_48 - setup_code) # load gdt with whatever is
- # appropriate
-
- # Switch to protected mode
- movl %cr0, %eax
- orb $CR0_PE, %al
- movl %eax, %cr0
-
- DATA32 ljmp *%ds:(code32 - setup_code)
-code32:
- .long 0x100000
- .word __BOOT_CS, 0
-
-# Here's a bunch of information about your current kernel..
-kernel_version: .ascii "Etherboot "
- .ascii VERSION
- .byte 0
-
-# This is the default real mode switch routine.
-# to be called just before protected mode transition
-default_switch:
- cli # no interrupts allowed !
- movb $0x80, %al # disable NMI for bootup
- # sequence
- outb %al, $0x70
- lret
-
-# This routine tests whether or not A20 is enabled. If so, it
-# exits with zf = 0.
-#
-# The memory address used, 0x200, is the int $0x80 vector, which
-# should be safe.
-
-A20_TEST_ADDR = 4*0x80
-
-a20_test:
- pushw %cx
- pushw %ax
- xorw %cx, %cx
- movw %cx, %fs # Low memory
- decw %cx
- movw %cx, %gs # High memory area
- movw $A20_TEST_LOOPS, %cx
- movw %fs:(A20_TEST_ADDR), %ax
- pushw %ax
-a20_test_wait:
- incw %ax
- movw %ax, %fs:(A20_TEST_ADDR)
- call delay # Serialize and make delay constant
- cmpw %gs:(A20_TEST_ADDR+0x10), %ax
- loope a20_test_wait
-
- popw %fs:(A20_TEST_ADDR)
- popw %ax
- popw %cx
- ret
-
-
-# This routine checks that the keyboard command queue is empty
-# (after emptying the output buffers)
-#
-# Some machines have delusions that the keyboard buffer is always full
-# with no keyboard attached...
-#
-# If there is no keyboard controller, we will usually get 0xff
-# to all the reads. With each IO taking a microsecond and
-# a timeout of 100,000 iterations, this can take about half a
-# second ("delay" == outb to port 0x80). That should be ok,
-# and should also be plenty of time for a real keyboard controller
-# to empty.
-#
-
-empty_8042:
- pushl %ecx
- movl $100000, %ecx
-
-empty_8042_loop:
- decl %ecx
- jz empty_8042_end_loop
-
- call delay
-
- inb $0x64, %al # 8042 status port
- testb $1, %al # output buffer?
- jz no_output
-
- call delay
- inb $0x60, %al # read it
- jmp empty_8042_loop
-
-no_output:
- testb $2, %al # is input buffer full?
- jnz empty_8042_loop # yes - loop
-empty_8042_end_loop:
- popl %ecx
-
-
-# Delay is needed after doing I/O
-delay:
- outb %al,$0x80
- ret
-
-# Descriptor tables
-#
-# NOTE: The intel manual says gdt should be sixteen bytes aligned for
-# efficiency reasons. However, there are machines which are known not
-# to boot with misaligned GDTs, so alter this at your peril! If you alter
-# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two
-# empty GDT entries (one for NULL and one reserved).
-#
-# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is
-# true for the Voyager Quad CPU card which will not boot without
-# This directive. 16 byte aligment is recommended by intel.
-#
- .balign 16
-bImage_gdt:
- .fill GDT_ENTRY_BOOT_CS,8,0
-
- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
- .word 0 # base address = 0
- .word 0x9A00 # code read/exec
- .word 0x00CF # granularity = 4096, 386
- # (+5th nibble of limit)
-
- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
- .word 0 # base address = 0
- .word 0x9200 # data read/write
- .word 0x00CF # granularity = 4096, 386
- # (+5th nibble of limit)
-bImage_gdt_end:
- .balign 4
-
- .word 0 # alignment byte
-bImage_idt_48:
- .word 0 # idt limit = 0
- .long 0 # idt base = 0L
-
- .word 0 # alignment byte
-bImage_gdt_48:
- .word bImage_gdt_end - bImage_gdt - 1 # gdt limit
- .long bImage_gdt_48 - setup_code # gdt base (filled in later)
-
- .section ".text16", "ax", @progbits
-prefix_exit:
- int $0x19 /* should try to boot machine */
-prefix_exit_end:
- .previous
-
-
- .org (PREFIXSIZE - 4)
-# Setup signature -- must be last
-setup_sig1: .word SIG1
-setup_sig2: .word SIG2
- /* Etherboot expects to be contiguous in memory once loaded.
- * The linux bImage protocol does not do this, but since we
- * don't need any information that's left in the prefix, it
- * doesn't matter: we just have to ensure that we make it to _start
- *
- * protected_start will live at 0x100000 and it will be the
- * the first code called as we enter protected mode.
- */
- .code32
-protected_start:
- /* Load segment registers */
- movw $__BOOT_DS, %ax
- movw %ax, %ss
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %fs
- movw %ax, %gs
-
- /* Use the internal etherboot stack */
- movl $(_prefix_stack_end - protected_start + 0x100000), %esp
-
- pushl $0 /* No parameters to preserve for exit path */
- pushl $0 /* Use prefix exit path mechanism */
-
- jmp _start
-/*
- That's about it.
-*/
diff --git a/gpxe/src/arch/i386/prefix/bootpart.S b/gpxe/src/arch/i386/prefix/bootpart.S
index d60fe9bc..968da1a3 100644
--- a/gpxe/src/arch/i386/prefix/bootpart.S
+++ b/gpxe/src/arch/i386/prefix/bootpart.S
@@ -1,3 +1,5 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
#define BOOT_SEG 0x07c0
#define EXEC_SEG 0x0100
#define STACK_SEG 0x0200
diff --git a/gpxe/src/arch/i386/prefix/comprefix.S b/gpxe/src/arch/i386/prefix/comprefix.S
deleted file mode 100644
index 2cbbca50..00000000
--- a/gpxe/src/arch/i386/prefix/comprefix.S
+++ /dev/null
@@ -1,46 +0,0 @@
-/* We need a real mode stack that won't be stomped on by Etherboot
- which starts at 0x20000. Choose something that's sufficiently high,
- but not in DOC territory. Note that we couldn't do this in a real
- .com program since stack variables are in the same segment as the
- code and data, but this isn't really a .com program, it just looks
- like one to make DOS load it into memory. It still has the 64kB
- limitation of .com files though. */
-#define STACK_SEG 0x7000
-#define STACK_SIZE 0x4000
-
- .text
- .code16
- .arch i386
- .section ".prefix", "ax", @progbits
-
-/* Cheat a little with the relocations: .COM files are loaded at 0x100 */
-_prefix:
- /* Set up temporary stack */
- movw $STACK_SEG, %ax
- movw %ax, %ss
- movw $STACK_SIZE, %sp
-
- pushl $0 /* No parameters to preserve for exit path */
- pushw $0 /* Dummy return address - use prefix_exit */
-
- /* Calculate segment address of image start */
- pushw %cs
- popw %ax
- addw $(0x100/16), %ax
- pushw %ax
- pushw $_start
- /* Calculated lcall to _start with %cs:0000 = image start */
- lret
-
- .section ".text16", "ax", @progbits
-prefix_exit:
- movw $0x4c00,%ax /* return to DOS */
- int $0x21 /* reach this on Quit */
-prefix_exit_end:
- .previous
-
-/* The body of etherboot is attached here at build time.
- * Force 16 byte alignment
- */
- .align 16,0
-_body:
diff --git a/gpxe/src/arch/i386/prefix/dskprefix.S b/gpxe/src/arch/i386/prefix/dskprefix.S
index 0156812a..60d351f7 100644
--- a/gpxe/src/arch/i386/prefix/dskprefix.S
+++ b/gpxe/src/arch/i386/prefix/dskprefix.S
@@ -16,6 +16,8 @@
* getting whole tracks at a time whenever possible.
*/
+FILE_LICENCE ( GPL2_ONLY )
+
.equ BOOTSEG, 0x07C0 /* original address of boot-sector */
.equ SYSSEG, 0x1000 /* system loaded at SYSSEG<<4 */
@@ -144,9 +146,9 @@ got_sectors:
/* Jump to loaded copy */
ljmp $SYSSEG, $start_runtime
-endseg: .word SYSSEG + _filesz_pgh
+endseg: .word SYSSEG
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
- .ascii "SUBW"
+ .ascii "ADDW"
.long endseg
.long 16
.long 0
diff --git a/gpxe/src/arch/i386/prefix/elf_dprefix.S b/gpxe/src/arch/i386/prefix/elf_dprefix.S
deleted file mode 100644
index 0eac77e0..00000000
--- a/gpxe/src/arch/i386/prefix/elf_dprefix.S
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "elf.h"
-
- .arch i386
- .section ".prefix", "a", @progbits
-
-#define LOAD_ADDR 0x10000
-
- /* ELF Header */
- .globl elf_header
-elf_header:
-e_ident: .byte 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
-e_type: .short ET_DYN
-e_machine: .short EM_386
-e_version: .long 1
-e_entry: .long LOAD_ADDR + _start - elf_header
-e_phoff: .long elf_program_header - elf_header
-e_shoff: .long 0
-e_flags: .long 0
-e_ehsize: .short elf_header_end - elf_header
-e_phentsize: .short ELF32_PHDR_SIZE
-e_phnum: .short (elf_program_header_end - elf_program_header)/ELF32_PHDR_SIZE
-e_shentsize: .short 0
-e_shnum: .short 0
-e_shstrndx: .short 0
-elf_header_end:
-
-elf_program_header:
-phdr1_p_type: .long PT_NOTE
-phdr1_p_offset: .long elf_note - elf_header
-phdr1_p_vaddr: .long elf_note
-phdr1_p_paddr: .long elf_note
-phdr1_p_filesz: .long elf_note_end - elf_note
-phdr1_p_memsz: .long elf_note_end - elf_note
-phdr1_p_flags: .long PF_R | PF_W | PF_X
-phdr1_p_align: .long 0
-
-/* The decompressor */
-phdr2_p_type: .long PT_LOAD
-phdr2_p_offset: .long 0
-phdr2_p_vaddr: .long elf_header
-phdr2_p_paddr: .long LOAD_ADDR
-phdr2_p_filesz: .long _verbatim_size
-phdr2_p_memsz: .long _image_size
-phdr2_p_flags: .long PF_R | PF_W | PF_X
-phdr2_p_align: .long 16
-
-elf_program_header_end:
-
- .globl elf_note
-elf_note:
- .balign 4
- .int 2f - 1f
- .int 4f - 3f
- .int EIN_PROGRAM_NAME
-1: .asciz "ELFBoot"
-2:
- .balign 4
-3:
- .asciz "Etherboot"
-4:
-
-
- .balign 4
- .int 2f - 1f
- .int 4f - 3f
- .int EIN_PROGRAM_VERSION
-1: .asciz "ELFBoot"
-2:
- .balign 4
-3:
- .asciz VERSION
-4:
-
-#if 0
- .balign 4
- .int 2f - 1f
- .int 4f - 3f
- .int EIN_PROGRAM_CHECKSUM
-1: .asciz "ELFBoot"
-2:
- .balign 4
-3:
- .word 0
-4:
-#endif
- .balign 4
-elf_note_end:
-
- /* Dummy routines to satisfy the build */
- .section ".text16", "ax", @progbits
-prefix_exit:
-
-prefix_exit_end:
- .previous
diff --git a/gpxe/src/arch/i386/prefix/elfprefix.S b/gpxe/src/arch/i386/prefix/elfprefix.S
deleted file mode 100644
index d712753a..00000000
--- a/gpxe/src/arch/i386/prefix/elfprefix.S
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "elf.h"
-
- .arch i386
- .section ".prefix", "a", @progbits
-
-#define LOAD_ADDR 0x10000
-
- /* ELF Header */
- .globl elf_header
-elf_header:
-e_ident: .byte 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
-e_type: .short ET_EXEC
-e_machine: .short EM_386
-e_version: .long 1
-e_entry: .long LOAD_ADDR + _start - elf_header
-e_phoff: .long elf_program_header - elf_header
-e_shoff: .long 0
-e_flags: .long 0
-e_ehsize: .short elf_header_end - elf_header
-e_phentsize: .short ELF32_PHDR_SIZE
-e_phnum: .short (elf_program_header_end - elf_program_header)/ELF32_PHDR_SIZE
-e_shentsize: .short 0
-e_shnum: .short 0
-e_shstrndx: .short 0
-elf_header_end:
-
-elf_program_header:
-phdr1_p_type: .long PT_NOTE
-phdr1_p_offset: .long elf_note - elf_header
-phdr1_p_vaddr: .long elf_note
-phdr1_p_paddr: .long elf_note
-phdr1_p_filesz: .long elf_note_end - elf_note
-phdr1_p_memsz: .long elf_note_end - elf_note
-phdr1_p_flags: .long PF_R | PF_W | PF_X
-phdr1_p_align: .long 0
-
-/* The decompressor */
-phdr2_p_type: .long PT_LOAD
-phdr2_p_offset: .long 0
-phdr2_p_vaddr: .long elf_header
-phdr2_p_paddr: .long LOAD_ADDR
-phdr2_p_filesz: .long _verbatim_size
-phdr2_p_memsz: .long _image_size
-phdr2_p_flags: .long PF_R | PF_W | PF_X
-phdr2_p_align: .long 16
-
-elf_program_header_end:
-
- .globl elf_note
-elf_note:
- .balign 4
- .int 2f - 1f
- .int 4f - 3f
- .int EIN_PROGRAM_NAME
-1: .asciz "ELFBoot"
-2:
- .balign 4
-3:
- .asciz "Etherboot"
-4:
-
-
- .balign 4
- .int 2f - 1f
- .int 4f - 3f
- .int EIN_PROGRAM_VERSION
-1: .asciz "ELFBoot"
-2:
- .balign 4
-3:
- .asciz VERSION
-4:
-
-#if 0
- .balign 4
- .int 2f - 1f
- .int 4f - 3f
- .int EIN_PROGRAM_CHECKSUM
-1: .asciz "ELFBoot"
-2:
- .balign 4
-3:
- .word 0
-4:
-#endif
- .balign 4
-elf_note_end:
-
- /* Dummy routines to satisfy the build */
- .section ".text16", "ax", @progbits
-prefix_exit:
-
-prefix_exit_end:
- .previous
diff --git a/gpxe/src/arch/i386/prefix/exeprefix.S b/gpxe/src/arch/i386/prefix/exeprefix.S
deleted file mode 100755
index f1b402b7..00000000
--- a/gpxe/src/arch/i386/prefix/exeprefix.S
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- Prefix for .exe images
- Doesn't work yet, even though it starts off the same as a .com
- image as shown by DOS debug.
-*/
-
- .text
- .code16
- .arch i386
- .section ".prefix", "ax", @progbits
-
-_prefix:
- .byte 'M', 'Z'
- .short _exe_size_tail /* tail */
- .short _exe_size_pages /* pages */
- .short 0 /* relocations */
- .short 2 /* header paras */
- .short _exe_bss_size /* min */
- .short 0xFFFF /* max paras */
- .short _exe_ss_offset /* SS */
- .short _stack_size /* SP */
- .short 0 /* checksum */
- .short 0 /* IP */
- .short 0 /* CS */
- .short 0x1C /* reloc offset */
- .short 0 /* overlay number */
- .short 0 /* fill */
- .short 0 /* fill */
-
- .section ".text16", "ax", @progbits
-prefix_exit:
- movw $0x4c00,%ax /* return to DOS */
- int $0x21 /* reach this on Quit */
-prefix_exit_end:
- .previous
-
-/* The body of etherboot is attached here at build time.
- * Force 16 byte alignment
- */
- .align 16,0
-_body:
diff --git a/gpxe/src/arch/i386/prefix/hdprefix.S b/gpxe/src/arch/i386/prefix/hdprefix.S
index 086d7f45..05767567 100644
--- a/gpxe/src/arch/i386/prefix/hdprefix.S
+++ b/gpxe/src/arch/i386/prefix/hdprefix.S
@@ -1,3 +1,5 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
.text
.arch i386
.section ".prefix", "awx", @progbits
@@ -63,10 +65,10 @@ max_sector:
max_head:
.byte 0
load_length:
- .long _filesz_sect
+ .long 0
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
- .ascii "SUBL"
+ .ascii "ADDL"
.long load_length
.long 512
.long 0
diff --git a/gpxe/src/arch/i386/prefix/hromprefix.S b/gpxe/src/arch/i386/prefix/hromprefix.S
new file mode 100644
index 00000000..03acf1e2
--- /dev/null
+++ b/gpxe/src/arch/i386/prefix/hromprefix.S
@@ -0,0 +1,12 @@
+/*****************************************************************************
+ * ROM prefix that relocates to HIGHMEM_LOADPOINT during POST if PMM allocation
+ * fails. Intended to be used, with caution, on BIOSes that support PCI3.00 but
+ * have limited PMM support, such as most AMI BIOSes.
+ *****************************************************************************
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#define SHRINK_WITHOUT_PMM
+
+#include "romprefix.S"
diff --git a/gpxe/src/arch/i386/prefix/kkpxeprefix.S b/gpxe/src/arch/i386/prefix/kkpxeprefix.S
index e0bea0cd..02cc6fee 100644
--- a/gpxe/src/arch/i386/prefix/kkpxeprefix.S
+++ b/gpxe/src/arch/i386/prefix/kkpxeprefix.S
@@ -3,6 +3,11 @@
*****************************************************************************
*/
+FILE_LICENCE ( GPL2_OR_LATER )
+
+/* Since we have the whole stack, we can use cached DHCP information */
+REQUEST_OBJECT ( pxeparent_dhcp )
+
#define PXELOADER_KEEP_UNDI
#define PXELOADER_KEEP_PXE
#include "pxeprefix.S"
diff --git a/gpxe/src/arch/i386/prefix/kpxeprefix.S b/gpxe/src/arch/i386/prefix/kpxeprefix.S
index d708604b..923faccc 100644
--- a/gpxe/src/arch/i386/prefix/kpxeprefix.S
+++ b/gpxe/src/arch/i386/prefix/kpxeprefix.S
@@ -3,5 +3,7 @@
*****************************************************************************
*/
+FILE_LICENCE ( GPL2_OR_LATER )
+
#define PXELOADER_KEEP_UNDI
#include "pxeprefix.S"
diff --git a/gpxe/src/arch/i386/prefix/libprefix.S b/gpxe/src/arch/i386/prefix/libprefix.S
index 42189135..9e6ba6f0 100644
--- a/gpxe/src/arch/i386/prefix/libprefix.S
+++ b/gpxe/src/arch/i386/prefix/libprefix.S
@@ -17,6 +17,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER )
+
.arch i386
/**
diff --git a/gpxe/src/arch/i386/prefix/lkrnprefix.S b/gpxe/src/arch/i386/prefix/lkrnprefix.S
index 094263d2..101d0388 100644
--- a/gpxe/src/arch/i386/prefix/lkrnprefix.S
+++ b/gpxe/src/arch/i386/prefix/lkrnprefix.S
@@ -34,6 +34,8 @@
*/
+FILE_LICENCE ( GPL_ANY )
+
#define SETUPSECS 4 /* Minimal nr of setup-sectors */
#define PREFIXSIZE ((SETUPSECS+1)*512)
#define PREFIXPGH (PREFIXSIZE / 16 )
@@ -92,10 +94,10 @@ setup_sects:
root_flags:
.word 0
syssize:
- .long _filesz_pgh - PREFIXPGH
+ .long -PREFIXPGH
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
- .ascii "SUBL"
+ .ascii "ADDL"
.long syssize
.long 16
.long 0
diff --git a/gpxe/src/arch/i386/prefix/lmelf_dprefix.S b/gpxe/src/arch/i386/prefix/lmelf_dprefix.S
deleted file mode 100644
index 93534df5..00000000
--- a/gpxe/src/arch/i386/prefix/lmelf_dprefix.S
+++ /dev/null
@@ -1,161 +0,0 @@
-#include "elf.h"
- .arch sledgehammer
- .code32
- .equ FLAT_CODE_SEG,_pmcs-_gdt
- .equ FLAT_DATA_SEG,_pmds-_gdt
- .equ MSR_K6_EFER, 0xC0000080
- .equ EFER_LME, 0x00000100
- .equ X86_CR4_PAE, 0x00000020
- .equ CR0_PG, 0x80000000
-
- .section ".prefix", "ax", @progbits
-
-#define LOAD_ADDR 0x10000
-
- /* ELF Header */
- .globl elf_header
-elf_header:
-e_ident: .byte 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
-e_type: .short ET_DYN
-e_machine: .short EM_X86_64
-e_version: .long 1
-e_entry: .long LOAD_ADDR + elf_start - elf_header
-e_phoff: .long elf_program_header - elf_header
-e_shoff: .long 0
-e_flags: .long 0
-e_ehsize: .short elf_header_end - elf_header
-e_phentsize: .short ELF32_PHDR_SIZE
-e_phnum: .short (elf_program_header_end - elf_program_header)/ELF32_PHDR_SIZE
-e_shentsize: .short 0
-e_shnum: .short 0
-e_shstrndx: .short 0
-elf_header_end:
-
-elf_program_header:
-phdr1_p_type: .long PT_NOTE
-phdr1_p_offset: .long elf_note - elf_header
-phdr1_p_vaddr: .long elf_note
-phdr1_p_paddr: .long elf_note
-phdr1_p_filesz: .long elf_note_end - elf_note
-phdr1_p_memsz: .long elf_note_end - elf_note
-phdr1_p_flags: .long PF_R | PF_W | PF_X
-phdr1_p_align: .long 0
-
-/* The decompressor */
-phdr2_p_type: .long PT_LOAD
-phdr2_p_offset: .long 0
-phdr2_p_vaddr: .long elf_header
-phdr2_p_paddr: .long LOAD_ADDR
-phdr2_p_filesz: .long _verbatim_size
-phdr2_p_memsz: .long _image_size
-phdr2_p_flags: .long PF_R | PF_W | PF_X
-phdr2_p_align: .long 16
-
-elf_program_header_end:
-
- .globl elf_note
-elf_note:
- .balign 4
- .int 2f - 1f
- .int 4f - 3f
- .int EIN_PROGRAM_NAME
-1: .asciz "ELFBoot"
-2:
- .balign 4
-3:
- .asciz "Etherboot"
-4:
-
-
- .balign 4
- .int 2f - 1f
- .int 4f - 3f
- .int EIN_PROGRAM_VERSION
-1: .asciz "ELFBoot"
-2:
- .balign 4
-3:
- .asciz VERSION
-4:
-
-#if 0
- .balign 4
- .int 2f - 1f
- .int 4f - 3f
- .int EIN_PROGRAM_CHECKSUM
-1: .asciz "ELFBoot"
-2:
- .balign 4
-3:
- .word 0
-4:
-#endif
- .balign 4
-elf_note_end:
-
-elf_start:
- .code64
- /* Reload the gdt to something I know */
- leaq _gdt(%rip), %rax
- movq %rax, 0x02 + gdtptr(%rip)
- lgdt gdtptr(%rip)
-
- /* Enter 32bit compatibility mode */
- leaq elf_start32(%rip), %rax
- movl %eax, 0x00 + elf_start32_addr(%rip)
- ljmp *elf_start32_addr(%rip)
-
-elf_start32:
- .code32
- /* Reload the data segments */
- movl $FLAT_DATA_SEG, %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %ss
-
- /* Disable paging */
- movl %cr0, %eax
- andl $~CR0_PG, %eax
- movl %eax, %cr0
-
- /* Disable long mode */
- movl $MSR_K6_EFER, %ecx
- rdmsr
- andl $~EFER_LME, %eax
- wrmsr
-
- /* Disable PAE */
- movl %cr4, %eax
- andl $~X86_CR4_PAE, %eax
- movl %eax, %cr4
-
- /* Save the first argument */
- pushl %ebx
- jmp _start
-
-gdtptr:
- .word _gdt_end - _gdt -1
- .long _gdt
- .long 0
-_gdt:
-elf_start32_addr:
- .long elf_start32
- .long FLAT_CODE_SEG
-_pmcs:
- /* 32 bit protected mode code segment, base 0 */
- .word 0xffff,0
- .byte 0,0x9f,0xcf,0
-
-_pmds:
- /* 32 bit protected mode data segment, base 0 */
- .word 0xffff,0
- .byte 0,0x93,0xcf,0
-_gdt_end:
-
-
- /* Dummy routines to satisfy the build */
- .section ".text16", "ax", @progbits
-prefix_exit:
-
-prefix_exit_end:
- .previous
diff --git a/gpxe/src/arch/i386/prefix/lmelf_prefix.S b/gpxe/src/arch/i386/prefix/lmelf_prefix.S
deleted file mode 100644
index 3c1e7251..00000000
--- a/gpxe/src/arch/i386/prefix/lmelf_prefix.S
+++ /dev/null
@@ -1,161 +0,0 @@
-#include "elf.h"
- .arch sledgehammer
- .code32
- .equ FLAT_CODE_SEG,_pmcs-_gdt
- .equ FLAT_DATA_SEG,_pmds-_gdt
- .equ MSR_K6_EFER, 0xC0000080
- .equ EFER_LME, 0x00000100
- .equ X86_CR4_PAE, 0x00000020
- .equ CR0_PG, 0x80000000
-
- .section ".prefix", "ax", @progbits
-
-#define LOAD_ADDR 0x10000
-
- /* ELF Header */
- .globl elf_header
-elf_header:
-e_ident: .byte 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
-e_type: .short ET_EXEC
-e_machine: .short EM_X86_64
-e_version: .long 1
-e_entry: .long LOAD_ADDR + elf_start - elf_header
-e_phoff: .long elf_program_header - elf_header
-e_shoff: .long 0
-e_flags: .long 0
-e_ehsize: .short elf_header_end - elf_header
-e_phentsize: .short ELF32_PHDR_SIZE
-e_phnum: .short (elf_program_header_end - elf_program_header)/ELF32_PHDR_SIZE
-e_shentsize: .short 0
-e_shnum: .short 0
-e_shstrndx: .short 0
-elf_header_end:
-
-elf_program_header:
-phdr1_p_type: .long PT_NOTE
-phdr1_p_offset: .long elf_note - elf_header
-phdr1_p_vaddr: .long elf_note
-phdr1_p_paddr: .long elf_note
-phdr1_p_filesz: .long elf_note_end - elf_note
-phdr1_p_memsz: .long elf_note_end - elf_note
-phdr1_p_flags: .long PF_R | PF_W | PF_X
-phdr1_p_align: .long 0
-
-/* The decompressor */
-phdr2_p_type: .long PT_LOAD
-phdr2_p_offset: .long 0
-phdr2_p_vaddr: .long elf_header
-phdr2_p_paddr: .long LOAD_ADDR
-phdr2_p_filesz: .long _verbatim_size
-phdr2_p_memsz: .long _image_size
-phdr2_p_flags: .long PF_R | PF_W | PF_X
-phdr2_p_align: .long 16
-
-elf_program_header_end:
-
- .globl elf_note
-elf_note:
- .balign 4
- .int 2f - 1f
- .int 4f - 3f
- .int EIN_PROGRAM_NAME
-1: .asciz "ELFBoot"
-2:
- .balign 4
-3:
- .asciz "Etherboot"
-4:
-
-
- .balign 4
- .int 2f - 1f
- .int 4f - 3f
- .int EIN_PROGRAM_VERSION
-1: .asciz "ELFBoot"
-2:
- .balign 4
-3:
- .asciz VERSION
-4:
-
-#if 0
- .balign 4
- .int 2f - 1f
- .int 4f - 3f
- .int EIN_PROGRAM_CHECKSUM
-1: .asciz "ELFBoot"
-2:
- .balign 4
-3:
- .word 0
-4:
-#endif
- .balign 4
-elf_note_end:
-
-elf_start:
- .code64
- /* Reload the gdt to something I know */
- leaq _gdt(%rip), %rax
- movq %rax, 0x02 + gdtptr(%rip)
- lgdt gdtptr(%rip)
-
- /* Enter 32bit compatibility mode */
- leaq elf_start32(%rip), %rax
- movl %eax, 0x00 + elf_start32_addr(%rip)
- ljmp *elf_start32_addr(%rip)
-
-elf_start32:
- .code32
- /* Reload the data segments */
- movl $FLAT_DATA_SEG, %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %ss
-
- /* Disable paging */
- movl %cr0, %eax
- andl $~CR0_PG, %eax
- movl %eax, %cr0
-
- /* Disable long mode */
- movl $MSR_K6_EFER, %ecx
- rdmsr
- andl $~EFER_LME, %eax
- wrmsr
-
- /* Disable PAE */
- movl %cr4, %eax
- andl $~X86_CR4_PAE, %eax
- movl %eax, %cr4
-
- /* Save the first argument */
- pushl %ebx
- jmp _start
-
-gdtptr:
- .word _gdt_end - _gdt -1
- .long _gdt
- .long 0
-_gdt:
-elf_start32_addr:
- .long elf_start32
- .long FLAT_CODE_SEG
-_pmcs:
- /* 32 bit protected mode code segment, base 0 */
- .word 0xffff,0
- .byte 0,0x9f,0xcf,0
-
-_pmds:
- /* 32 bit protected mode data segment, base 0 */
- .word 0xffff,0
- .byte 0,0x93,0xcf,0
-_gdt_end:
-
-
- /* Dummy routines to satisfy the build */
- .section ".text16", "ax", @progbits
-prefix_exit:
-
-prefix_exit_end:
- .previous
diff --git a/gpxe/src/arch/i386/prefix/nbiprefix.S b/gpxe/src/arch/i386/prefix/nbiprefix.S
index 4fb4acb1..607d80fb 100644
--- a/gpxe/src/arch/i386/prefix/nbiprefix.S
+++ b/gpxe/src/arch/i386/prefix/nbiprefix.S
@@ -30,16 +30,16 @@ segment_header:
.byte 0
.byte 0x04 /* Last segment */
.long 0x00007e00
-imglen: .long _filesz - 512
-memlen: .long _filesz - 512
+imglen: .long -512
+memlen: .long -512
.size segment_header, . - segment_header
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
- .ascii "SUBL"
+ .ascii "ADDL"
.long imglen
.long 1
.long 0
- .ascii "SUBL"
+ .ascii "ADDL"
.long memlen
.long 1
.long 0
diff --git a/gpxe/src/arch/i386/prefix/pxeprefix.S b/gpxe/src/arch/i386/prefix/pxeprefix.S
index b3b7947f..e728c482 100644
--- a/gpxe/src/arch/i386/prefix/pxeprefix.S
+++ b/gpxe/src/arch/i386/prefix/pxeprefix.S
@@ -1,8 +1,13 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
#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 +16,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
@@ -105,20 +112,13 @@ have_pxenv:
/* Record entry point and UNDI segments */
pushl %es:0x0a(%bx) /* Entry point */
- popl entry_segoff
pushw %es:0x24(%bx) /* UNDI code segment */
pushw %es:0x26(%bx) /* UNDI code size */
- popl undi_code_segoff
pushw %es:0x20(%bx) /* UNDI data segment */
pushw %es:0x22(%bx) /* UNDI data size */
- popl undi_data_segoff
/* Print "PXENV+ at <address>" */
movw $10f, %si
- call print_message
- call print_segoff
- movb $( ',' ), %al
- call print_character
jmp check_have_stack
.section ".prefix.data", "aw", @progbits
10: .asciz " PXENV+ at "
@@ -129,19 +129,13 @@ have_ppxe:
movw %es, ppxe_segment
pushl %es:0x10(%bx) /* Entry point */
- popl entry_segoff
pushw %es:0x30(%bx) /* UNDI code segment */
pushw %es:0x36(%bx) /* UNDI code size */
- popl undi_code_segoff
pushw %es:0x28(%bx) /* UNDI data segment */
pushw %es:0x2e(%bx) /* UNDI data size */
- popl undi_data_segoff
+
/* Print "!PXE at <address>" */
movw $10f, %si
- call print_message
- call print_segoff
- movb $( ',' ), %al
- call print_character
jmp check_have_stack
.section ".prefix.data", "aw", @progbits
10: .asciz " !PXE at "
@@ -201,6 +195,17 @@ memory_scan_common:
*****************************************************************************
*/
check_have_stack:
+ /* Save common values pushed onto the stack */
+ popl undi_data_segoff
+ popl undi_code_segoff
+ popl entry_segoff
+
+ /* Print have !PXE/PXENV+ message; structure pointer in %es:%bx */
+ call print_message
+ call print_segoff
+ movb $( ',' ), %al
+ call print_character
+
/* Check for entry point */
movl entry_segoff, %eax
testl %eax, %eax
@@ -309,8 +314,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 "
@@ -321,12 +324,47 @@ 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
*****************************************************************************
*/
@@ -339,6 +377,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
@@ -551,7 +597,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
@@ -595,7 +643,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
@@ -605,6 +653,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:
@@ -668,6 +718,13 @@ run_gpxe:
lret
.section ".text16", "ax", @progbits
1:
+ /* Update the exit hook */
+ movw %cs,pxe_exit_hook+2
+ push %ax
+ mov $2f,%ax
+ mov %ax,pxe_exit_hook
+ pop %ax
+
/* Run main program */
pushl $main
pushw %cs
@@ -681,7 +738,10 @@ run_gpxe:
movw %di, %ss
movl %ebp, %esp
- /* Check PXE stack magic */
+ /* Jump to hook if applicable */
+ ljmpw *pxe_exit_hook
+
+2: /* Check PXE stack magic */
popl %eax
cmpl $STACK_MAGIC, %eax
jne 1f
diff --git a/gpxe/src/arch/i386/prefix/romprefix.S b/gpxe/src/arch/i386/prefix/romprefix.S
index 7d532375..02e54976 100644
--- a/gpxe/src/arch/i386/prefix/romprefix.S
+++ b/gpxe/src/arch/i386/prefix/romprefix.S
@@ -6,6 +6,8 @@
* table so using a noticeable amount of stack space is a no-no.
*/
+FILE_LICENCE ( GPL2_OR_LATER )
+
#include <config/general.h>
#define PNP_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'n' << 16 ) + ( 'P' << 24 ) )
@@ -23,6 +25,19 @@
*/
#define ROM_BANNER_TIMEOUT ( 2 * ( 18 * BANNER_TIMEOUT ) / 10 )
+/* We can load a ROM in two ways: have the BIOS load all of it (.rom prefix)
+ * or have the BIOS load a stub that loads the rest using PCI (.xrom prefix).
+ * The latter is not as widely supported, but allows the use of large ROMs
+ * on some systems with crowded option ROM space.
+ */
+
+#ifdef LOAD_ROM_FROM_PCI
+#define ROM_SIZE_VALUE _prefix_filesz_sect /* Amount to load in BIOS */
+#else
+#define ROM_SIZE_VALUE 0 /* Load amount (before compr. fixup) */
+#endif
+
+
.text
.code16
.arch i386
@@ -31,10 +46,12 @@
.org 0x00
romheader:
.word 0xAA55 /* BIOS extension signature */
-romheader_size: .byte _filesz_sect /* Size in 512-byte blocks */
+romheader_size: .byte ROM_SIZE_VALUE /* Size in 512-byte blocks */
jmp init /* Initialisation vector */
checksum:
- .byte 0
+ .byte 0, 0
+real_size:
+ .word 0
.org 0x16
.word undiheader
.org 0x18
@@ -42,12 +59,18 @@ checksum:
.org 0x1a
.word pnpheader
.size romheader, . - romheader
-
+
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
- .ascii "SUBB"
+#ifndef LOAD_ROM_FROM_PCI
+ .ascii "ADDB"
.long romheader_size
.long 512
.long 0
+#endif
+ .ascii "ADDB"
+ .long real_size
+ .long 512
+ .long 0
.previous
pciheader:
@@ -59,27 +82,29 @@ pciheader:
.byte 0x03 /* PCI data structure revision */
.byte 0x02, 0x00, 0x00 /* Class code */
pciheader_image_length:
- .word _filesz_sect /* Image length */
+ .word ROM_SIZE_VALUE /* Image length */
.word 0x0001 /* Revision level */
.byte 0x00 /* Code type */
.byte 0x80 /* Last image indicator */
pciheader_runtime_length:
- .word _filesz_sect /* Maximum run-time image length */
+ .word ROM_SIZE_VALUE /* Maximum run-time image length */
.word 0x0000 /* Configuration utility code header */
.word 0x0000 /* DMTF CLP entry point */
.equ pciheader_len, . - pciheader
.size pciheader, . - pciheader
-
+
+#ifndef LOAD_ROM_FROM_PCI
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
- .ascii "SUBW"
+ .ascii "ADDW"
.long pciheader_image_length
.long 512
.long 0
- .ascii "SUBW"
+ .ascii "ADDW"
.long pciheader_runtime_length
.long 512
.long 0
.previous
+#endif
pnpheader:
.ascii "$PnP" /* Signature */
@@ -124,6 +149,7 @@ prodstr_pci_id:
.size prodstr, . - prodstr
.globl undiheader
+ .weak undiloader
undiheader:
.ascii "UNDI" /* Signature */
.byte undiheader_len /* Length of structure */
@@ -172,6 +198,11 @@ init:
call print_message
call print_pci_busdevfn
+#ifdef LOAD_ROM_FROM_PCI
+ /* Save PCI bus:dev.fn for later use */
+ movw %ax, pci_busdevfn
+#endif
+
/* Fill in product name string, if possible */
movw $prodstr_pci_id, %di
call print_pci_busdevfn
@@ -196,6 +227,9 @@ init:
jne no_pci3
testb %ah, %ah
jnz no_pci3
+#ifdef LOAD_ROM_FROM_PCI
+ incb pcibios_present
+#endif
movw $init_message_pci, %si
xorw %di, %di
call print_message
@@ -236,24 +270,37 @@ no_pci3:
popl %edx
popl %ebx
- /* Check for PnP BIOS */
- testw $0x0f, %bx /* PnP signature must be aligned - bochs */
- jnz no_bbs /* uses unalignment to indicate 'fake' PnP. */
- cmpl $PNP_SIGNATURE, %es:0(%bx)
- jne no_bbs
+ /* Check for PnP BIOS. Although %es:di should point to the
+ * PnP BIOS signature on entry, some BIOSes fail to do this.
+ */
+ movw $( 0xf000 - 1 ), %bx
+pnp_scan:
+ incw %bx
+ jz no_pnp
+ movw %bx, %es
+ cmpl $PNP_SIGNATURE, %es:0
+ jne pnp_scan
+ xorw %dx, %dx
+ xorw %si, %si
+ movzbw %es:5, %cx
+1: es lodsb
+ addb %al, %dl
+ loop 1b
+ jnz pnp_scan
/* Is PnP: print PnP message */
movw $init_message_pnp, %si
xorw %di, %di
call print_message
/* Check for BBS */
- pushw %es:0x1b(%bx) /* Real-mode data segment */
+ pushw %es:0x1b /* Real-mode data segment */
pushw %ds /* &(bbs_version) */
pushw $bbs_version
pushw $PNP_GET_BBS_VERSION
- lcall *%es:0xd(%bx)
+ lcall *%es:0xd
addw $8, %sp
testw %ax, %ax
je got_bbs
+no_pnp: /* Not PnP-compliant - therefore cannot be BBS-compliant */
no_bbs: /* Not BBS-compliant - must hook INT 19 */
movw $init_message_int19, %si
xorw %di, %di
@@ -294,7 +341,7 @@ pmm_scan:
/* We have PMM and so a 1kB stack: preserve upper register halves */
pushal
/* Calculate required allocation size in %esi */
- movzbl romheader_size, %eax
+ movzwl real_size, %eax
shll $9, %eax
addl $_textdata_memsz, %eax
orw $0xffff, %ax /* Ensure allocation size is at least 64kB */
@@ -336,6 +383,7 @@ got_pmm: /* PMM allocation succeeded */
call print_character
movw %si, %ax
call print_hex_byte
+pmm_copy:
/* Copy ROM to PMM block */
xorw %ax, %ax
movw %ax, %es
@@ -347,11 +395,43 @@ got_pmm: /* PMM allocation succeeded */
movl %edi, decompress_to
/* Shrink ROM */
movb $_prefix_memsz_sect, romheader_size
+#if defined(SHRINK_WITHOUT_PMM) || defined(LOAD_ROM_FROM_PCI)
+ jmp pmm_done
+pmm_fail:
+ /* Print marker and copy ourselves to high memory */
+ movl $HIGHMEM_LOADPOINT, image_source
+ xorw %di, %di
+ movb $( '!' ), %al
+ call print_character
+ jmp pmm_copy
+pmm_done:
+#else
pmm_fail:
+#endif
/* Restore upper register halves */
popal
+#if defined(LOAD_ROM_FROM_PCI)
+ call load_from_pci
+ jc load_err
+ jmp load_ok
no_pmm:
+ /* Cannot continue without PMM - print error message */
+ xorw %di, %di
+ movw $init_message_no_pmm, %si
+ call print_message
+load_err:
+ /* Wait for five seconds to let user see message */
+ movw $90, %cx
+1: call wait_for_tick
+ loop 1b
+ /* Mark environment as invalid and return */
+ movl $0, decompress_to
+ jmp out
+load_ok:
+#else
+no_pmm:
+#endif
/* Update checksum */
xorw %bx, %bx
xorw %si, %si
@@ -396,14 +476,14 @@ no_pmm:
movw $init_message_done, %si
call print_message
popf
- jnz 2f
+ jnz out
/* Ctrl-B was pressed: invoke gPXE. The keypress will be
* picked up by the initial shell prompt, and we will drop
* into a shell.
*/
pushw %cs
call exec
-2:
+out:
/* Restore registers */
popw %gs
popw %fs
@@ -450,6 +530,11 @@ init_message_bbs:
init_message_pmm:
.asciz " PMM"
.size init_message_pmm, . - init_message_pmm
+#ifdef LOAD_ROM_FROM_PCI
+init_message_no_pmm:
+ .asciz "\nPMM required but not present!\n"
+ .size init_message_no_pmm, . - init_message_no_pmm
+#endif
init_message_int19:
.asciz " INT19"
.size init_message_int19, . - init_message_int19
@@ -467,6 +552,7 @@ init_message_done:
*
* May be either within option ROM space, or within PMM-allocated block.
*/
+ .globl image_source
image_source:
.long 0
.size image_source, . - image_source
@@ -474,11 +560,32 @@ image_source:
/* Temporary decompression area
*
* May be either at HIGHMEM_LOADPOINT, or within PMM-allocated block.
+ * If a PCI ROM load fails, this will be set to zero.
*/
+ .globl decompress_to
decompress_to:
.long HIGHMEM_LOADPOINT
.size decompress_to, . - decompress_to
+#ifdef LOAD_ROM_FROM_PCI
+
+/* Set if the PCI BIOS is present, even <3.0 */
+pcibios_present:
+ .byte 0
+ .byte 0 /* for alignment */
+ .size pcibios_present, . - pcibios_present
+
+/* PCI bus:device.function word
+ *
+ * Filled in by init in the .xrom case, so the remainder of the ROM
+ * can be located.
+ */
+pci_busdevfn:
+ .word 0
+ .size pci_busdevfn, . - pci_busdevfn
+
+#endif
+
/* BBS version
*
* Filled in by BBS BIOS. We ignore the value.
@@ -497,6 +604,289 @@ bev_entry:
lret
.size bev_entry, . - bev_entry
+
+#ifdef LOAD_ROM_FROM_PCI
+
+#define PCI_ROM_ADDRESS 0x30 /* Bits 31:11 address, 10:1 reserved */
+#define PCI_ROM_ADDRESS_ENABLE 0x00000001
+#define PCI_ROM_ADDRESS_MASK 0xfffff800
+
+#define PCIBIOS_READ_WORD 0xb109
+#define PCIBIOS_READ_DWORD 0xb10a
+#define PCIBIOS_WRITE_WORD 0xb10c
+#define PCIBIOS_WRITE_DWORD 0xb10d
+
+/* Determine size of PCI BAR
+ *
+ * %bx : PCI bus:dev.fn to probe
+ * %di : Address of BAR to find size of
+ * %edx : Mask of address bits within BAR
+ *
+ * %ecx : Size for a memory resource,
+ * 1 for an I/O resource (bit 0 set).
+ * CF : Set on error or nonexistent device (all-ones read)
+ *
+ * All other registers saved.
+ */
+pci_bar_size:
+ /* Save registers */
+ pushw %ax
+ pushl %esi
+ pushl %edx
+
+ /* Read current BAR value */
+ movw $PCIBIOS_READ_DWORD, %ax
+ int $0x1a
+
+ /* Check for device existence and save it */
+ testb $1, %cl /* I/O bit? */
+ jz 1f
+ andl $1, %ecx /* If so, exit with %ecx = 1 */
+ jmp 99f
+1: notl %ecx
+ testl %ecx, %ecx /* Set ZF iff %ecx was all-ones */
+ notl %ecx
+ jnz 1f
+ stc /* All ones - exit with CF set */
+ jmp 99f
+1: movl %ecx, %esi /* Save in %esi */
+
+ /* Write all ones to BAR */
+ movl %edx, %ecx
+ movw $PCIBIOS_WRITE_DWORD, %ax
+ int $0x1a
+
+ /* Read back BAR */
+ movw $PCIBIOS_READ_DWORD, %ax
+ int $0x1a
+
+ /* Find decode size from least set bit in mask BAR */
+ bsfl %ecx, %ecx /* Find least set bit, log2(decode size) */
+ jz 1f /* Mask BAR should not be zero */
+ xorl %edx, %edx
+ incl %edx
+ shll %cl, %edx /* %edx = decode size */
+ jmp 2f
+1: xorl %edx, %edx /* Return zero size for mask BAR zero */
+
+ /* Restore old BAR value */
+2: movl %esi, %ecx
+ movw $PCIBIOS_WRITE_DWORD, %ax
+ int $0x1a
+
+ movl %edx, %ecx /* Return size in %ecx */
+
+ /* Restore registers and return */
+99: popl %edx
+ popl %esi
+ popw %ax
+ ret
+
+ .size pci_bar_size, . - pci_bar_size
+
+/* PCI ROM loader
+ *
+ * Called from init in the .xrom case to load the non-prefix code
+ * using the PCI ROM BAR.
+ *
+ * Returns with carry flag set on error. All registers saved.
+ */
+load_from_pci:
+ /*
+ * Use PCI BIOS access to config space. The calls take
+ *
+ * %ah : 0xb1 %al : function
+ * %bx : bus/dev/fn
+ * %di : config space address
+ * %ecx : value to write (for writes)
+ *
+ * %ecx : value read (for reads)
+ * %ah : return code
+ * CF : error indication
+ *
+ * All registers not used for return are preserved.
+ */
+
+ /* Save registers and set up %es for big real mode */
+ pushal
+ pushw %es
+ xorw %ax, %ax
+ movw %ax, %es
+
+ /* Check PCI BIOS presence */
+ cmpb $0, pcibios_present
+ jz err_pcibios
+
+ /* Load existing PCI ROM BAR */
+ movw $PCIBIOS_READ_DWORD, %ax
+ movw pci_busdevfn, %bx
+ movw $PCI_ROM_ADDRESS, %di
+ int $0x1a
+
+ /* Maybe it's already enabled? */
+ testb $PCI_ROM_ADDRESS_ENABLE, %cl
+ jz 1f
+ movb $1, %dl /* Flag indicating no deinit required */
+ movl %ecx, %ebp
+ jmp check_rom
+
+ /* Determine PCI BAR decode size */
+1: movl $PCI_ROM_ADDRESS_MASK, %edx
+ call pci_bar_size /* Returns decode size in %ecx */
+ jc err_size_insane /* CF => no ROM BAR, %ecx == ffffffff */
+
+ /* Check sanity of decode size */
+ xorl %eax, %eax
+ movw real_size, %ax
+ shll $9, %eax /* %eax = ROM size */
+ cmpl %ecx, %eax
+ ja err_size_insane /* Insane if decode size < ROM size */
+ cmpl $0x100000, %ecx
+ jae err_size_insane /* Insane if decode size >= 1MB */
+
+ /* Find a place to map the BAR
+ * In theory we should examine e820 and all PCI BARs to find a
+ * free region. However, we run at POST when e820 may not be
+ * available, and memory reads of an unmapped location are
+ * de facto standardized to return all-ones. Thus, we can get
+ * away with searching high memory (0xf0000000 and up) on
+ * multiples of the ROM BAR decode size for a sufficiently
+ * large all-ones region.
+ */
+ movl %ecx, %edx /* Save ROM BAR size in %edx */
+ movl $0xf0000000, %ebp
+ xorl %eax, %eax
+ notl %eax /* %eax = all ones */
+bar_search:
+ movl %ebp, %edi
+ movl %edx, %ecx
+ shrl $2, %ecx
+ addr32 repe scasl /* Scan %es:edi for anything not all-ones */
+ jz bar_found
+ addl %edx, %ebp
+ testl $0x80000000, %ebp
+ jz err_no_bar
+ jmp bar_search
+
+bar_found:
+ movl %edi, %ebp
+ /* Save current BAR value on stack to restore later */
+ movw $PCIBIOS_READ_DWORD, %ax
+ movw $PCI_ROM_ADDRESS, %di
+ int $0x1a
+ pushl %ecx
+
+ /* Map the ROM */
+ movw $PCIBIOS_WRITE_DWORD, %ax
+ movl %ebp, %ecx
+ orb $PCI_ROM_ADDRESS_ENABLE, %cl
+ int $0x1a
+
+ xorb %dl, %dl /* %dl = 0 : ROM was not already mapped */
+check_rom:
+ /* Check and copy ROM - enter with %dl set to skip unmapping,
+ * %ebp set to mapped ROM BAR address.
+ * We check up to prodstr_separator for equality, since anything past
+ * that may have been modified. Since our check includes the checksum
+ * byte over the whole ROM stub, that should be sufficient.
+ */
+ xorb %dh, %dh /* %dh = 0 : ROM did not fail integrity check */
+
+ /* Verify ROM integrity */
+ xorl %esi, %esi
+ movl %ebp, %edi
+ movl $prodstr_separator, %ecx
+ addr32 repe cmpsb
+ jz copy_rom
+ incb %dh /* ROM failed integrity check */
+ movl %ecx, %ebp /* Save number of bytes left */
+ jmp skip_load
+
+copy_rom:
+ /* Print BAR address and indicate whether we mapped it ourselves */
+ movb $( ' ' ), %al
+ xorw %di, %di
+ call print_character
+ movl %ebp, %eax
+ call print_hex_dword
+ movb $( '-' ), %al /* '-' for self-mapped */
+ subb %dl, %al
+ subb %dl, %al /* '+' = '-' - 2 for BIOS-mapped */
+ call print_character
+
+ /* Copy ROM at %ebp to PMM or highmem block */
+ movl %ebp, %esi
+ movl image_source, %edi
+ movzwl real_size, %ecx
+ shll $9, %ecx
+ addr32 es rep movsb
+ movl %edi, decompress_to
+skip_load:
+ testb %dl, %dl /* Was ROM already mapped? */
+ jnz skip_unmap
+
+ /* Unmap the ROM by restoring old ROM BAR */
+ movw $PCIBIOS_WRITE_DWORD, %ax
+ movw $PCI_ROM_ADDRESS, %di
+ popl %ecx
+ int $0x1a
+
+skip_unmap:
+ /* Error handling */
+ testb %dh, %dh
+ jnz err_rom_invalid
+ clc
+ jmp 99f
+
+err_pcibios: /* No PCI BIOS available */
+ movw $load_message_no_pcibios, %si
+ xorl %eax, %eax /* "error code" is zero */
+ jmp 1f
+err_size_insane: /* BAR has size (%ecx) that is insane */
+ movw $load_message_size_insane, %si
+ movl %ecx, %eax
+ jmp 1f
+err_no_bar: /* No space of sufficient size (%edx) found */
+ movw $load_message_no_bar, %si
+ movl %edx, %eax
+ jmp 1f
+err_rom_invalid: /* Loaded ROM does not match (%ebp bytes left) */
+ movw $load_message_rom_invalid, %si
+ movzbl romheader_size, %eax
+ shll $9, %eax
+ subl %ebp, %eax
+ decl %eax /* %eax is now byte index of failure */
+
+1: /* Error handler - print message at %si and dword in %eax */
+ xorw %di, %di
+ call print_message
+ call print_hex_dword
+ stc
+99: popw %es
+ popal
+ ret
+
+ .size load_from_pci, . - load_from_pci
+
+load_message_no_pcibios:
+ .asciz "\nNo PCI BIOS found! "
+ .size load_message_no_pcibios, . - load_message_no_pcibios
+
+load_message_size_insane:
+ .asciz "\nROM resource has invalid size "
+ .size load_message_size_insane, . - load_message_size_insane
+
+load_message_no_bar:
+ .asciz "\nNo memory hole of sufficient size "
+ .size load_message_no_bar, . - load_message_no_bar
+
+load_message_rom_invalid:
+ .asciz "\nLoaded ROM is invalid at "
+ .size load_message_rom_invalid, . - load_message_rom_invalid
+
+#endif /* LOAD_ROM_FROM_PCI */
+
+
/* INT19 entry point
*
* Called via the hooked INT 19 if we detected a non-PnP BIOS. We
@@ -557,6 +947,14 @@ exec: /* Set %ds = %cs */
pushw %cs
popw %ds
+#ifdef LOAD_ROM_FROM_PCI
+ /* Don't execute if load was invalid */
+ cmpl $0, decompress_to
+ jne 1f
+ lret
+1:
+#endif
+
/* Print message as soon as possible */
movw $prodstr, %si
xorw %di, %di
@@ -616,50 +1014,6 @@ exec_message:
.asciz " starting execution\n"
.size exec_message, . - exec_message
-/* UNDI loader
- *
- * Called by an external program to load our PXE stack.
- */
-undiloader:
- /* Save registers */
- pushl %esi
- pushl %edi
- pushw %ds
- pushw %es
- pushw %bx
- /* ROM segment address to %ds */
- pushw %cs
- popw %ds
- /* UNDI loader parameter structure address into %es:%di */
- movw %sp, %bx
- movw %ss:18(%bx), %di
- movw %ss:20(%bx), %es
- /* Install to specified real-mode addresses */
- pushw %di
- movw %es:12(%di), %bx
- movw %es:14(%di), %ax
- movl image_source, %esi
- movl decompress_to, %edi
- call install_prealloc
- popw %di
- /* Call UNDI loader C code */
- pushl $pxe_loader_call
- pushw %cs
- pushw $1f
- pushw %ax
- pushw $prot_call
- lret
-1: popw %bx /* discard */
- popw %bx /* discard */
- /* Restore registers and return */
- popw %bx
- popw %es
- popw %ds
- popl %edi
- popl %esi
- lret
- .size undiloader, . - undiloader
-
/* Wait for key press specified by %bl (masked by %bh)
*
* Used by init and INT19 code when prompting user. If the specified
diff --git a/gpxe/src/arch/i386/prefix/undiloader.S b/gpxe/src/arch/i386/prefix/undiloader.S
new file mode 100644
index 00000000..36c1bef3
--- /dev/null
+++ b/gpxe/src/arch/i386/prefix/undiloader.S
@@ -0,0 +1,49 @@
+ .text
+ .code16
+ .arch i386
+ .section ".prefix", "ax", @progbits
+
+/* UNDI loader
+ *
+ * Called by an external program to load our PXE stack.
+ */
+ .globl undiloader
+undiloader:
+ /* Save registers */
+ pushl %esi
+ pushl %edi
+ pushw %ds
+ pushw %es
+ pushw %bx
+ /* ROM segment address to %ds */
+ pushw %cs
+ popw %ds
+ /* UNDI loader parameter structure address into %es:%di */
+ movw %sp, %bx
+ movw %ss:18(%bx), %di
+ movw %ss:20(%bx), %es
+ /* Install to specified real-mode addresses */
+ pushw %di
+ movw %es:12(%di), %bx
+ movw %es:14(%di), %ax
+ movl image_source, %esi
+ movl decompress_to, %edi
+ call install_prealloc
+ popw %di
+ /* Call UNDI loader C code */
+ pushl $pxe_loader_call
+ pushw %cs
+ pushw $1f
+ pushw %ax
+ pushw $prot_call
+ lret
+1: popw %bx /* discard */
+ popw %bx /* discard */
+ /* Restore registers and return */
+ popw %bx
+ popw %es
+ popw %ds
+ popl %edi
+ popl %esi
+ lret
+ .size undiloader, . - undiloader
diff --git a/gpxe/src/arch/i386/prefix/unnrv2b.S b/gpxe/src/arch/i386/prefix/unnrv2b.S
index 70167a14..f5724c13 100644
--- a/gpxe/src/arch/i386/prefix/unnrv2b.S
+++ b/gpxe/src/arch/i386/prefix/unnrv2b.S
@@ -20,6 +20,8 @@
* Michael Brown 9 Mar 2005
*/
+FILE_LICENCE ( GPL2_OR_LATER )
+
/****************************************************************************
* This file provides the decompress() and decompress16() functions
* which can be called in order to decompress an image compressed with
diff --git a/gpxe/src/arch/i386/prefix/unnrv2b16.S b/gpxe/src/arch/i386/prefix/unnrv2b16.S
new file mode 100644
index 00000000..b24c2846
--- /dev/null
+++ b/gpxe/src/arch/i386/prefix/unnrv2b16.S
@@ -0,0 +1,9 @@
+/*
+ * 16-bit version of the decompressor
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#define CODE16
+#include "unnrv2b.S"
diff --git a/gpxe/src/arch/i386/prefix/xromprefix.S b/gpxe/src/arch/i386/prefix/xromprefix.S
new file mode 100644
index 00000000..d7c861f5
--- /dev/null
+++ b/gpxe/src/arch/i386/prefix/xromprefix.S
@@ -0,0 +1,9 @@
+/*
+ * ROM prefix that loads the bulk of the ROM using direct PCI accesses,
+ * so as not to take up much option ROM space on PCI <3.0 systems.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#define LOAD_ROM_FROM_PCI
+#include "romprefix.S"
diff --git a/gpxe/src/arch/i386/scripts/i386-kir.lds b/gpxe/src/arch/i386/scripts/i386-kir.lds
index b213c605..c19480f0 100644
--- a/gpxe/src/arch/i386/scripts/i386-kir.lds
+++ b/gpxe/src/arch/i386/scripts/i386-kir.lds
@@ -130,6 +130,7 @@ SECTIONS {
/DISCARD/ : {
*(.comment)
*(.note)
+ *(.discard)
}
/*
diff --git a/gpxe/src/arch/i386/scripts/i386.lds b/gpxe/src/arch/i386/scripts/i386.lds
index 8a0c6733..33c75f90 100644
--- a/gpxe/src/arch/i386/scripts/i386.lds
+++ b/gpxe/src/arch/i386/scripts/i386.lds
@@ -152,6 +152,7 @@ SECTIONS {
*(.eh_frame.*)
*(.rel)
*(.rel.*)
+ *(.discard)
}
/*
@@ -193,17 +194,9 @@ SECTIONS {
* Values calculated to save code from doing it
*
*/
+ _prefix_filesz_sect = ( ( _prefix_filesz + 511 ) / 512 );
_prefix_memsz_pgh = ( ( _prefix_memsz + 15 ) / 16 );
_prefix_memsz_sect = ( ( _prefix_memsz + 511 ) / 512 );
_text16_memsz_pgh = ( ( _text16_memsz + 15 ) / 16 );
_data16_memsz_pgh = ( ( _data16_memsz + 15 ) / 16 );
-
- /*
- * File size in paragraphs and sectors. Note that wherever the
- * _filesz variables are used, there must be a corresponding
- * .zinfo.fixup section.
- *
- */
- _filesz_pgh = ( ( _filesz + 15 ) / 16 );
- _filesz_sect = ( ( _filesz + 511 ) / 512 );
}
diff --git a/gpxe/src/arch/i386/transitions/libkir.S b/gpxe/src/arch/i386/transitions/libkir.S
index 1023ddd0..1176fcce 100644
--- a/gpxe/src/arch/i386/transitions/libkir.S
+++ b/gpxe/src/arch/i386/transitions/libkir.S
@@ -5,6 +5,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER )
+
/****************************************************************************
* This file defines libkir: an interface between external and
* internal environments when -DKEEP_IT_REAL is used, so that both
diff --git a/gpxe/src/arch/i386/transitions/librm.S b/gpxe/src/arch/i386/transitions/librm.S
index 8cf1f7f5..cb27ef35 100755..100644
--- a/gpxe/src/arch/i386/transitions/librm.S
+++ b/gpxe/src/arch/i386/transitions/librm.S
@@ -5,6 +5,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER )
+
/* Drag in local definitions */
#include "librm.h"
diff --git a/gpxe/src/arch/i386/transitions/librm_mgmt.c b/gpxe/src/arch/i386/transitions/librm_mgmt.c
index 50569f8e..f00be811 100755..100644
--- a/gpxe/src/arch/i386/transitions/librm_mgmt.c
+++ b/gpxe/src/arch/i386/transitions/librm_mgmt.c
@@ -5,6 +5,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <realmode.h>
diff --git a/gpxe/src/arch/x86/Makefile b/gpxe/src/arch/x86/Makefile
index a7c4bc0e..f5f67ac7 100644
--- a/gpxe/src/arch/x86/Makefile
+++ b/gpxe/src/arch/x86/Makefile
@@ -1,6 +1,6 @@
# Include common x86 headers
#
-CFLAGS += -Iarch/x86/include
+INCDIRS += arch/x86/include
# x86-specific directories containing source files
#
diff --git a/gpxe/src/arch/x86/core/pcidirect.c b/gpxe/src/arch/x86/core/pcidirect.c
index db17215e..2c61d9ca 100644
--- a/gpxe/src/arch/x86/core/pcidirect.c
+++ b/gpxe/src/arch/x86/core/pcidirect.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/io.h>
#include <gpxe/pci.h>
diff --git a/gpxe/src/arch/x86/core/x86_string.c b/gpxe/src/arch/x86/core/x86_string.c
index c0224c7a..5838ebac 100644
--- a/gpxe/src/arch/x86/core/x86_string.c
+++ b/gpxe/src/arch/x86/core/x86_string.c
@@ -22,6 +22,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
/**
diff --git a/gpxe/src/arch/x86/include/bits/pci_io.h b/gpxe/src/arch/x86/include/bits/pci_io.h
index 0fbb439d..f6efcdac 100644
--- a/gpxe/src/arch/x86/include/bits/pci_io.h
+++ b/gpxe/src/arch/x86/include/bits/pci_io.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/pcibios.h>
#include <gpxe/pcidirect.h>
diff --git a/gpxe/src/arch/x86/include/bits/string.h b/gpxe/src/arch/x86/include/bits/string.h
index 42ddeddf..a68868ac 100644
--- a/gpxe/src/arch/x86/include/bits/string.h
+++ b/gpxe/src/arch/x86/include/bits/string.h
@@ -21,6 +21,8 @@
* 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 );
diff --git a/gpxe/src/arch/x86/include/gpxe/efi/efix86_nap.h b/gpxe/src/arch/x86/include/gpxe/efi/efix86_nap.h
index 91424c54..833c922c 100644
--- a/gpxe/src/arch/x86/include/gpxe/efi/efix86_nap.h
+++ b/gpxe/src/arch/x86/include/gpxe/efi/efix86_nap.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#ifdef NAP_EFIX86
#define NAP_PREFIX_efix86
#else
diff --git a/gpxe/src/arch/x86/include/gpxe/pcibios.h b/gpxe/src/arch/x86/include/gpxe/pcibios.h
index b86f5abd..93a6eb8a 100644
--- a/gpxe/src/arch/x86/include/gpxe/pcibios.h
+++ b/gpxe/src/arch/x86/include/gpxe/pcibios.h
@@ -9,6 +9,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#ifdef PCIAPI_PCBIOS
#define PCIAPI_PREFIX_pcbios
#else
diff --git a/gpxe/src/arch/x86/include/gpxe/pcidirect.h b/gpxe/src/arch/x86/include/gpxe/pcidirect.h
index fe433c6f..8b705fb2 100644
--- a/gpxe/src/arch/x86/include/gpxe/pcidirect.h
+++ b/gpxe/src/arch/x86/include/gpxe/pcidirect.h
@@ -1,6 +1,8 @@
#ifndef _PCIDIRECT_H
#define _PCIDIRECT_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <gpxe/io.h>
diff --git a/gpxe/src/arch/x86/interface/efi/efix86_nap.c b/gpxe/src/arch/x86/interface/efi/efix86_nap.c
index 45e99a68..89a4e3ba 100644
--- a/gpxe/src/arch/x86/interface/efi/efix86_nap.c
+++ b/gpxe/src/arch/x86/interface/efi/efix86_nap.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/nap.h>
#include <gpxe/efi/efi.h>
diff --git a/gpxe/src/arch/x86/prefix/efidrvprefix.c b/gpxe/src/arch/x86/prefix/efidrvprefix.c
index 5f631588..36d56508 100644
--- a/gpxe/src/arch/x86/prefix/efidrvprefix.c
+++ b/gpxe/src/arch/x86/prefix/efidrvprefix.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
#include <gpxe/init.h>
#include <gpxe/efi/efi.h>
diff --git a/gpxe/src/arch/x86/prefix/efiprefix.c b/gpxe/src/arch/x86/prefix/efiprefix.c
index b05b744d..4cc9e04a 100644
--- a/gpxe/src/arch/x86/prefix/efiprefix.c
+++ b/gpxe/src/arch/x86/prefix/efiprefix.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
#include <gpxe/efi/efi.h>
diff --git a/gpxe/src/arch/x86/scripts/efi.lds b/gpxe/src/arch/x86/scripts/efi.lds
index aac31056..7525b81b 100644
--- a/gpxe/src/arch/x86/scripts/efi.lds
+++ b/gpxe/src/arch/x86/scripts/efi.lds
@@ -101,5 +101,6 @@ SECTIONS {
*(.eh_frame.*)
*(.rel)
*(.rel.*)
+ *(.discard)
}
}
diff --git a/gpxe/src/arch/x86_64/include/bits/stdint.h b/gpxe/src/arch/x86_64/include/bits/stdint.h
index 23bae9c4..9eb72e9c 100644
--- a/gpxe/src/arch/x86_64/include/bits/stdint.h
+++ b/gpxe/src/arch/x86_64/include/bits/stdint.h
@@ -1,7 +1,7 @@
#ifndef _BITS_STDINT_H
#define _BITS_STDINT_H
-typedef unsigned long size_t;
+typedef __SIZE_TYPE__ size_t;
typedef signed long ssize_t;
typedef signed long off_t;
diff --git a/gpxe/src/core/config.c b/gpxe/src/config/config.c
index bd0d66ec..a6e76220 100644
--- a/gpxe/src/core/config.c
+++ b/gpxe/src/config/config.c
@@ -5,9 +5,29 @@
* your option) any later version.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <config/general.h>
#include <config/console.h>
+/** @file
+ *
+ * Configuration options
+ *
+ * This file contains macros that pull various objects into the link
+ * based on definitions in configuration header files. Ideally it
+ * should be the only place in gPXE where one might need to use #ifdef
+ * for compile-time options.
+ *
+ * In the fairly common case where an object should only be considered
+ * for inclusion if the subsystem it depends on is present, its
+ * configuration macros should be placed in a file named
+ * <tt>config_<i>subsystem</i>.c</tt>, where @e subsystem is the
+ * object basename of the main source file for that subsystem. The
+ * build system will pull in that file if @c subsystem.c is included
+ * in the final gPXE executable built.
+ */
+
/*
* Build ID string calculations
*
@@ -72,15 +92,23 @@ REQUIRE_OBJECT ( ipv4 );
#endif
/*
+ * Drag in all requested PXE support
+ *
+ */
+#ifdef PXE_MENU
+REQUIRE_OBJECT ( pxemenu );
+#endif
+#ifdef PXE_STACK
+REQUIRE_OBJECT ( pxe_call );
+#endif
+
+/*
* Drag in all requested download protocols
*
*/
#ifdef DOWNLOAD_PROTO_TFTP
REQUIRE_OBJECT ( tftp );
#endif
-#ifdef DOWNLOAD_PROTO_NFS
-REQUIRE_OBJECT ( nfs );
-#endif
#ifdef DOWNLOAD_PROTO_HTTP
REQUIRE_OBJECT ( http );
#endif
@@ -107,6 +135,9 @@ REQUIRE_OBJECT ( iscsiboot );
#ifdef SANBOOT_PROTO_AOE
REQUIRE_OBJECT ( aoeboot );
#endif
+#ifdef SANBOOT_PROTO_IB_SRP
+REQUIRE_OBJECT ( ib_srpboot );
+#endif
/*
* Drag in all requested resolvers
@@ -115,9 +146,6 @@ REQUIRE_OBJECT ( aoeboot );
#ifdef DNS_RESOLVER
REQUIRE_OBJECT ( dns );
#endif
-#ifdef NMB_RESOLVER
-REQUIRE_OBJECT ( nmb );
-#endif
/*
* Drag in all requested image formats
@@ -181,6 +209,7 @@ REQUIRE_OBJECT ( config_cmd );
#ifdef IFMGMT_CMD
REQUIRE_OBJECT ( ifmgmt_cmd );
#endif
+/* IWMGMT_CMD is brought in by net80211.c if requested */
#ifdef ROUTE_CMD
REQUIRE_OBJECT ( route_cmd );
#endif
@@ -196,6 +225,15 @@ REQUIRE_OBJECT ( sanboot_cmd );
#ifdef LOGIN_CMD
REQUIRE_OBJECT ( login_cmd );
#endif
+#ifdef TIME_CMD
+REQUIRE_OBJECT ( time_cmd );
+#endif
+#ifdef DIGEST_CMD
+REQUIRE_OBJECT ( digest_cmd );
+#endif
+#ifdef PXE_CMD
+REQUIRE_OBJECT ( pxe_cmd );
+#endif
/*
* Drag in miscellaneous objects
diff --git a/gpxe/src/config/config_net80211.c b/gpxe/src/config/config_net80211.c
new file mode 100644
index 00000000..b33c363b
--- /dev/null
+++ b/gpxe/src/config/config_net80211.c
@@ -0,0 +1,50 @@
+/*
+ * 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, or (at
+ * your option) any later version.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/general.h>
+
+/** @file
+ *
+ * 802.11 configuration options
+ *
+ */
+
+/*
+ * Drag in 802.11-specific commands
+ *
+ */
+#ifdef IWMGMT_CMD
+REQUIRE_OBJECT ( iwmgmt_cmd );
+#endif
+
+/*
+ * Drag in 802.11 error message tables
+ *
+ */
+#ifdef ERRMSG_80211
+REQUIRE_OBJECT ( wireless_errors );
+#endif
+
+/*
+ * Drag in 802.11 cryptosystems and handshaking protocols
+ *
+ */
+#ifdef CRYPTO_80211_WEP
+REQUIRE_OBJECT ( wep );
+#endif
+
+#ifdef CRYPTO_80211_WPA2
+#define CRYPTO_80211_WPA
+REQUIRE_OBJECT ( wpa_ccmp );
+#endif
+
+#ifdef CRYPTO_80211_WPA
+REQUIRE_OBJECT ( wpa_psk );
+REQUIRE_OBJECT ( wpa_tkip );
+#endif
diff --git a/gpxe/src/config/config_romprefix.c b/gpxe/src/config/config_romprefix.c
new file mode 100644
index 00000000..85f1e78a
--- /dev/null
+++ b/gpxe/src/config/config_romprefix.c
@@ -0,0 +1,24 @@
+/*
+ * 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, or (at
+ * your option) any later version.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <config/general.h>
+
+/** @file
+ *
+ * ROM prefix configuration options
+ *
+ */
+
+/*
+ * Provide UNDI loader if PXE stack is requested
+ *
+ */
+#ifdef PXE_STACK
+REQUIRE_OBJECT ( undiloader );
+#endif
diff --git a/gpxe/src/config/console.h b/gpxe/src/config/console.h
index b4ea1dda..be3242dd 100644
--- a/gpxe/src/config/console.h
+++ b/gpxe/src/config/console.h
@@ -10,6 +10,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <config/defaults.h>
//#define CONSOLE_PCBIOS /* Default BIOS console */
diff --git a/gpxe/src/config/defaults.h b/gpxe/src/config/defaults.h
index 1f55ef3c..389c0b07 100644
--- a/gpxe/src/config/defaults.h
+++ b/gpxe/src/config/defaults.h
@@ -1,6 +1,8 @@
#ifndef CONFIG_DEFAULTS_H
#define CONFIG_DEFAULTS_H
+FILE_LICENCE ( GPL2_OR_LATER );
+
#define CONFIG_DEFAULTS(_platform) <config/defaults/_platform.h>
#include CONFIG_DEFAULTS(PLATFORM)
diff --git a/gpxe/src/config/defaults/pcbios.h b/gpxe/src/config/defaults/pcbios.h
index 4359e1a4..c09105cc 100644
--- a/gpxe/src/config/defaults/pcbios.h
+++ b/gpxe/src/config/defaults/pcbios.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#define UACCESS_LIBRM
#define IOAPI_X86
#define PCIAPI_PCBIOS
@@ -23,6 +25,10 @@
#define IMAGE_BZIMAGE /* Linux bzImage image support */
#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */
+#define PXE_STACK /* PXE stack in gPXE - required for PXELINUX */
+#define PXE_MENU /* PXE menu booting */
+#define PXE_CMD /* PXE commands */
+
#define SANBOOT_PROTO_ISCSI /* iSCSI protocol */
#define SANBOOT_PROTO_AOE /* AoE protocol */
diff --git a/gpxe/src/config/general.h b/gpxe/src/config/general.h
index a3d563c2..de51f9f8 100644
--- a/gpxe/src/config/general.h
+++ b/gpxe/src/config/general.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <config/defaults.h>
/*
@@ -40,18 +42,23 @@
#define NET_PROTO_IPV4 /* IPv4 protocol */
/*
+ * PXE support
+ *
+ */
+//#undef PXE_STACK /* PXE stack in gPXE - you want this! */
+//#undef PXE_MENU /* PXE menu booting */
+
+/*
* Download protocols
*
*/
#define DOWNLOAD_PROTO_TFTP /* Trivial File Transfer Protocol */
-#define DOWNLOAD_PROTO_NFS /* Network File System */
#define DOWNLOAD_PROTO_HTTP /* Hypertext Transfer Protocol */
#define DOWNLOAD_PROTO_HTTPS /* Secure Hypertext Transfer Protocol */
#define DOWNLOAD_PROTO_FTP /* File Transfer Protocol */
#undef DOWNLOAD_PROTO_TFTM /* Multicast Trivial File Transfer Protocol */
#undef DOWNLOAD_PROTO_SLAM /* Scalable Local Area Multicast */
-#undef DOWNLOAD_PROTO_FSP /* FSP? */
/*
* SAN boot protocols
@@ -60,6 +67,15 @@
//#undef SANBOOT_PROTO_ISCSI /* iSCSI protocol */
//#undef SANBOOT_PROTO_AOE /* AoE protocol */
+//#undef SANBOOT_PROTO_IB_SRP /* Infiniband SCSI RDMA protocol */
+
+/*
+ * 802.11 cryptosystems and handshaking protocols
+ *
+ */
+#define CRYPTO_80211_WEP /* WEP encryption (deprecated and insecure!) */
+#define CRYPTO_80211_WPA /* WPA Personal, authenticating with passphrase */
+#define CRYPTO_80211_WPA2 /* Add support for stronger WPA cryptography */
/*
* Name resolution modules
@@ -67,7 +83,6 @@
*/
#define DNS_RESOLVER /* DNS resolver */
-#undef NMB_RESOLVER /* NMB resolver */
/*
* Image types
@@ -96,11 +111,21 @@
#define NVO_CMD /* Non-volatile option storage commands */
#define CONFIG_CMD /* Option configuration console */
#define IFMGMT_CMD /* Interface management commands */
+#define IWMGMT_CMD /* Wireless interface management commands */
#define ROUTE_CMD /* Routing table management commands */
#define IMAGE_CMD /* Image management commands */
#define DHCP_CMD /* DHCP management commands */
#define SANBOOT_CMD /* SAN boot commands */
#define LOGIN_CMD /* Login command */
+#undef TIME_CMD /* Time commands */
+#undef DIGEST_CMD /* Image crypto digest commands */
+//#undef PXE_CMD /* PXE commands */
+
+/*
+ * Error message tables to include
+ *
+ */
+#undef ERRMSG_80211 /* All 802.11 error descriptions (~3.3kb) */
/*
* Obscure configuration options
diff --git a/gpxe/src/config/ioapi.h b/gpxe/src/config/ioapi.h
index 7726a0f0..8ddd557b 100644
--- a/gpxe/src/config/ioapi.h
+++ b/gpxe/src/config/ioapi.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <config/defaults.h>
//#undef PCIAPI_PCBIOS /* Access via PCI BIOS */
diff --git a/gpxe/src/config/nap.h b/gpxe/src/config/nap.h
index 8648d925..1b981355 100644
--- a/gpxe/src/config/nap.h
+++ b/gpxe/src/config/nap.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <config/defaults.h>
//#undef NAP_PCBIOS
diff --git a/gpxe/src/config/serial.h b/gpxe/src/config/serial.h
index 984a7a9c..44272d1f 100644
--- a/gpxe/src/config/serial.h
+++ b/gpxe/src/config/serial.h
@@ -11,7 +11,14 @@
*
*/
-#define COMCONSOLE 0x3f8 /* I/O port address */
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define COM1 0x3f8
+#define COM2 0x2f8
+#define COM3 0x3e8
+#define COM4 0x2e8
+
+#define COMCONSOLE COM1 /* I/O port address */
/* Keep settings from a previous user of the serial port (e.g. lilo or
* LinuxBIOS), ignoring COMSPEED, COMDATA, COMPARITY and COMSTOP.
diff --git a/gpxe/src/config/timer.h b/gpxe/src/config/timer.h
index 7c3f3521..cc6a93d1 100644
--- a/gpxe/src/config/timer.h
+++ b/gpxe/src/config/timer.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <config/defaults.h>
//#undef TIMER_PCBIOS
diff --git a/gpxe/src/config/umalloc.h b/gpxe/src/config/umalloc.h
index de4019e5..65febf1f 100644
--- a/gpxe/src/config/umalloc.h
+++ b/gpxe/src/config/umalloc.h
@@ -7,6 +7,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <config/defaults.h>
#endif /* CONFIG_UMALLOC_H */
diff --git a/gpxe/src/core/acpi.c b/gpxe/src/core/acpi.c
index 94b7b2a1..b65f4d48 100644
--- a/gpxe/src/core/acpi.c
+++ b/gpxe/src/core/acpi.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/acpi.h>
/** @file
diff --git a/gpxe/src/core/ansiesc.c b/gpxe/src/core/ansiesc.c
index 6b820ada..31306e2a 100644
--- a/gpxe/src/core/ansiesc.c
+++ b/gpxe/src/core/ansiesc.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <assert.h>
#include <gpxe/ansiesc.h>
diff --git a/gpxe/src/core/asprintf.c b/gpxe/src/core/asprintf.c
index 94d7e7c4..03cf45cf 100644
--- a/gpxe/src/core/asprintf.c
+++ b/gpxe/src/core/asprintf.c
@@ -4,6 +4,8 @@
#include <stdio.h>
#include <errno.h>
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* Write a formatted string to newly allocated memory.
*
diff --git a/gpxe/src/core/base64.c b/gpxe/src/core/base64.c
index e54821e3..5619ef7b 100644
--- a/gpxe/src/core/base64.c
+++ b/gpxe/src/core/base64.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <string.h>
#include <assert.h>
diff --git a/gpxe/src/core/basename.c b/gpxe/src/core/basename.c
index 7340c0d5..a481c54f 100644
--- a/gpxe/src/core/basename.c
+++ b/gpxe/src/core/basename.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
diff --git a/gpxe/src/core/bitmap.c b/gpxe/src/core/bitmap.c
index d0266471..bbe9cbaa 100644
--- a/gpxe/src/core/bitmap.c
+++ b/gpxe/src/core/bitmap.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <errno.h>
#include <gpxe/bitmap.h>
diff --git a/gpxe/src/core/bitops.c b/gpxe/src/core/bitops.c
index 53abaaea..1bca9e47 100644
--- a/gpxe/src/core/bitops.c
+++ b/gpxe/src/core/bitops.c
@@ -1,5 +1,7 @@
#include <strings.h>
+FILE_LICENCE ( GPL2_OR_LATER );
+
int __flsl ( long x ) {
unsigned long value = x;
int ls = 0;
diff --git a/gpxe/src/core/console.c b/gpxe/src/core/console.c
index c9773f71..e22d2601 100644
--- a/gpxe/src/core/console.c
+++ b/gpxe/src/core/console.c
@@ -5,10 +5,7 @@
/** @file */
-static struct console_driver console_drivers[0]
- __table_start ( struct console_driver, console );
-static struct console_driver console_drivers_end[0]
- __table_end ( struct console_driver, console );
+FILE_LICENCE ( GPL2_OR_LATER );
/**
* Write a single character to each console device.
@@ -28,8 +25,7 @@ void putchar ( int character ) {
if ( character == '\n' )
putchar ( '\r' );
- for ( console = console_drivers; console < console_drivers_end ;
- console++ ) {
+ for_each_table_entry ( console, CONSOLES ) {
if ( ( ! console->disabled ) && console->putchar )
console->putchar ( character );
}
@@ -51,8 +47,7 @@ void putchar ( int character ) {
static struct console_driver * has_input ( void ) {
struct console_driver *console;
- for ( console = console_drivers; console < console_drivers_end ;
- console++ ) {
+ for_each_table_entry ( console, CONSOLES ) {
if ( ( ! console->disabled ) && console->iskey ) {
if ( console->iskey () )
return console;
diff --git a/gpxe/src/core/cpio.c b/gpxe/src/core/cpio.c
index 7d2e8828..b303fa35 100644
--- a/gpxe/src/core/cpio.c
+++ b/gpxe/src/core/cpio.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/** @file
*
* CPIO archives
diff --git a/gpxe/src/core/ctype.c b/gpxe/src/core/ctype.c
new file mode 100644
index 00000000..6185bb2f
--- /dev/null
+++ b/gpxe/src/core/ctype.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Character types
+ *
+ */
+
+#include <ctype.h>
+
+/**
+ * Check to see if character is a space
+ *
+ * @v c Character
+ * @ret isspace Character is a space
+ */
+int isspace ( int c ) {
+ switch ( c ) {
+ case ' ' :
+ case '\f' :
+ case '\n' :
+ case '\r' :
+ case '\t' :
+ case '\v' :
+ return 1;
+ default:
+ return 0;
+ }
+}
diff --git a/gpxe/src/core/cwuri.c b/gpxe/src/core/cwuri.c
index 81fd900e..65e01b21 100644
--- a/gpxe/src/core/cwuri.c
+++ b/gpxe/src/core/cwuri.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stddef.h>
#include <gpxe/uri.h>
diff --git a/gpxe/src/core/debug.c b/gpxe/src/core/debug.c
index 500a7ac0..8f929309 100644
--- a/gpxe/src/core/debug.c
+++ b/gpxe/src/core/debug.c
@@ -36,7 +36,8 @@ static void dbg_hex_dump_da_row ( unsigned long dispaddr, const void *data,
printf ( " " );
continue;
}
- printf ( " %02x", bytes[i] );
+ printf ( "%c%02x",
+ ( ( ( i % 16 ) == 8 ) ? '-' : ' ' ), bytes[i] );
}
printf ( " : " );
for ( i = offset ; i < ( offset + 16 ) ; i++ ) {
diff --git a/gpxe/src/core/device.c b/gpxe/src/core/device.c
index 84915c2d..96ccc9ff 100644
--- a/gpxe/src/core/device.c
+++ b/gpxe/src/core/device.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <gpxe/list.h>
#include <gpxe/tables.h>
@@ -29,11 +31,6 @@
*
*/
-static struct root_device root_devices[0]
- __table_start ( struct root_device, root_devices );
-static struct root_device root_devices_end[0]
- __table_end ( struct root_device, root_devices );
-
/** Registered root devices */
static LIST_HEAD ( devices );
@@ -77,7 +74,7 @@ static void probe_devices ( void ) {
struct root_device *rootdev;
int rc;
- for ( rootdev = root_devices; rootdev < root_devices_end; rootdev++ ) {
+ for_each_table_entry ( rootdev, ROOT_DEVICES ) {
list_add ( &rootdev->dev.siblings, &devices );
INIT_LIST_HEAD ( &rootdev->dev.children );
if ( ( rc = rootdev_probe ( rootdev ) ) != 0 )
diff --git a/gpxe/src/core/downloader.c b/gpxe/src/core/downloader.c
index 0a443db2..86c144dc 100644
--- a/gpxe/src/core/downloader.c
+++ b/gpxe/src/core/downloader.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
@@ -124,18 +126,37 @@ static int downloader_ensure_size ( struct downloader *downloader,
* @v job Downloader job control interface
*/
static void downloader_job_kill ( struct job_interface *job ) {
- struct downloader *downloader =
+ struct downloader *downloader =
container_of ( job, struct downloader, job );
/* Terminate download */
downloader_finished ( downloader, -ECANCELED );
}
+/**
+ * Report progress of download job
+ *
+ * @v job Downloader job control interface
+ * @v progress Progress report to fill in
+ */
+static void downloader_job_progress ( struct job_interface *job,
+ struct job_progress *progress ) {
+ struct downloader *downloader =
+ container_of ( job, struct downloader, job );
+
+ /* This is not entirely accurate, since downloaded data may
+ * arrive out of order (e.g. with multicast protocols), but
+ * it's a reasonable first approximation.
+ */
+ progress->completed = downloader->pos;
+ progress->total = downloader->image->len;
+}
+
/** Downloader job control interface operations */
static struct job_interface_operations downloader_job_operations = {
.done = ignore_job_done,
.kill = downloader_job_kill,
- .progress = ignore_job_progress,
+ .progress = downloader_job_progress,
};
/****************************************************************************
@@ -205,7 +226,7 @@ static void downloader_xfer_close ( struct xfer_interface *xfer, int rc ) {
/** Downloader data transfer interface operations */
static struct xfer_interface_operations downloader_xfer_operations = {
.close = downloader_xfer_close,
- .vredirect = xfer_vopen,
+ .vredirect = xfer_vreopen,
.window = unlimited_xfer_window,
.alloc_iob = default_xfer_alloc_iob,
.deliver_iob = downloader_xfer_deliver_iob,
diff --git a/gpxe/src/core/exec.c b/gpxe/src/core/exec.c
index a9861b60..6c16aa44 100644
--- a/gpxe/src/core/exec.c
+++ b/gpxe/src/core/exec.c
@@ -16,10 +16,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <ctype.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
@@ -34,11 +37,6 @@
*
*/
-static struct command commands[0]
- __table_start ( struct command, commands );
-static struct command commands_end[0]
- __table_end ( struct command, commands );
-
/* Avoid dragging in getopt.o unless a command really uses it */
int optind;
int nextchar;
@@ -78,7 +76,7 @@ int execv ( const char *command, char * const argv[] ) {
reset_getopt();
/* Hand off to command implementation */
- for ( cmd = commands ; cmd < commands_end ; cmd++ ) {
+ for_each_table_entry ( cmd, COMMANDS ) {
if ( strcmp ( command, cmd->name ) == 0 )
return cmd->exec ( argc, ( char ** ) argv );
}
@@ -173,7 +171,7 @@ static int split_args ( char *args, char * argv[] ) {
while ( 1 ) {
/* Skip over any whitespace / convert to NUL */
- while ( *args == ' ' ) {
+ while ( isspace ( *args ) ) {
if ( argv )
*args = '\0';
args++;
@@ -186,7 +184,7 @@ static int split_args ( char *args, char * argv[] ) {
argv[argc] = args;
argc++;
/* Skip to start of next whitespace, if any */
- while ( *args && ( *args != ' ' ) ) {
+ while ( *args && ! isspace ( *args ) ) {
args++;
}
}
diff --git a/gpxe/src/core/filter.c b/gpxe/src/core/filter.c
index f9ebe7cf..a8bee7dc 100644
--- a/gpxe/src/core/filter.c
+++ b/gpxe/src/core/filter.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/xfer.h>
#include <gpxe/filter.h>
diff --git a/gpxe/src/core/gdbstub.c b/gpxe/src/core/gdbstub.c
index bbed344f..c8083955 100644
--- a/gpxe/src/core/gdbstub.c
+++ b/gpxe/src/core/gdbstub.c
@@ -54,10 +54,6 @@ struct gdbstub {
int len; /* length of payload */
};
-/* Transports */
-static struct gdb_transport gdb_transport_start[0] __table_start ( struct gdb_transport, gdb_transports );
-static struct gdb_transport gdb_transport_end[0] __table_end ( struct gdb_transport, gdb_transports );
-
/* Packet parser states */
static void gdbstub_state_new ( struct gdbstub *stub, char ch );
static void gdbstub_state_data ( struct gdbstub *stub, char ch );
@@ -348,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 );
}
}
@@ -387,7 +381,8 @@ void gdbstub_handler ( int signo, gdbreg_t *regs ) {
struct gdb_transport *find_gdb_transport ( const char *name ) {
struct gdb_transport *trans;
- for ( trans = gdb_transport_start; trans < gdb_transport_end; trans++ ) {
+
+ for_each_table_entry ( trans, GDB_TRANSPORTS ) {
if ( strcmp ( trans->name, name ) == 0 ) {
return trans;
}
diff --git a/gpxe/src/core/getkey.c b/gpxe/src/core/getkey.c
index 787c9027..dbd074cc 100644
--- a/gpxe/src/core/getkey.c
+++ b/gpxe/src/core/getkey.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <ctype.h>
#include <console.h>
#include <gpxe/process.h>
diff --git a/gpxe/src/core/getopt.c b/gpxe/src/core/getopt.c
index 6de412bb..b67da0c1 100644
--- a/gpxe/src/core/getopt.c
+++ b/gpxe/src/core/getopt.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <string.h>
#include <stdio.h>
diff --git a/gpxe/src/core/image.c b/gpxe/src/core/image.c
index 277d09a9..24fe51ab 100644
--- a/gpxe/src/core/image.c
+++ b/gpxe/src/core/image.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
@@ -37,12 +39,6 @@
/** List of registered images */
struct list_head images = LIST_HEAD_INIT ( images );
-/** List of image types */
-static struct image_type image_types[0]
- __table_start ( struct image_type, image_types );
-static struct image_type image_types_end[0]
- __table_end ( struct image_type, image_types );
-
/**
* Free executable/loadable image
*
@@ -219,7 +215,7 @@ int image_autoload ( struct image *image ) {
return image_load ( image );
/* Otherwise probe for a suitable type */
- for ( type = image_types ; type < image_types_end ; type++ ) {
+ for_each_table_entry ( type, IMAGE_TYPES ) {
DBGC ( image, "IMAGE %p trying type %s\n", image, type->name );
rc = image_load_type ( image, type );
if ( image->type == NULL )
diff --git a/gpxe/src/core/init.c b/gpxe/src/core/init.c
index 50e199ce..cd0f6dcc 100644
--- a/gpxe/src/core/init.c
+++ b/gpxe/src/core/init.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/device.h>
#include <gpxe/init.h>
@@ -25,18 +27,6 @@
*
*/
-/** Registered initialisation functions */
-static struct init_fn init_fns[0]
- __table_start ( struct init_fn, init_fns );
-static struct init_fn init_fns_end[0]
- __table_end ( struct init_fn, init_fns );
-
-/** Registered startup/shutdown functions */
-static struct startup_fn startup_fns[0]
- __table_start ( struct startup_fn, startup_fns );
-static struct startup_fn startup_fns_end[0]
- __table_end ( struct startup_fn, startup_fns );
-
/** "startup() has been called" flag */
static int started = 0;
@@ -54,9 +44,8 @@ void initialise ( void ) {
struct init_fn *init_fn;
/* Call registered initialisation functions */
- for ( init_fn = init_fns ; init_fn < init_fns_end ; init_fn++ ) {
+ for_each_table_entry ( init_fn, INIT_FNS )
init_fn->initialise ();
- }
}
/**
@@ -73,8 +62,7 @@ void startup ( void ) {
return;
/* Call registered startup functions */
- for ( startup_fn = startup_fns ; startup_fn < startup_fns_end ;
- startup_fn++ ) {
+ for_each_table_entry ( startup_fn, STARTUP_FNS ) {
if ( startup_fn->startup )
startup_fn->startup();
}
@@ -90,7 +78,7 @@ void startup ( void ) {
* This function reverses the actions of startup(), and leaves gPXE in
* a state ready to be removed from memory. You may call startup()
* again after calling shutdown().
-
+ *
* Call this function only once, before either exiting main() or
* starting up a non-returnable image.
*/
@@ -101,8 +89,7 @@ void shutdown ( int flags ) {
return;
/* Call registered shutdown functions (in reverse order) */
- for ( startup_fn = startup_fns_end - 1 ; startup_fn >= startup_fns ;
- startup_fn-- ) {
+ for_each_table_entry_reverse ( startup_fn, STARTUP_FNS ) {
if ( startup_fn->shutdown )
startup_fn->shutdown ( flags );
}
diff --git a/gpxe/src/core/interface.c b/gpxe/src/core/interface.c
index 37aabfe0..43d58ed2 100644
--- a/gpxe/src/core/interface.c
+++ b/gpxe/src/core/interface.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/interface.h>
/** @file
diff --git a/gpxe/src/core/iobuf.c b/gpxe/src/core/iobuf.c
index cc4aedea..1ce7890e 100644
--- a/gpxe/src/core/iobuf.c
+++ b/gpxe/src/core/iobuf.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <errno.h>
#include <gpxe/malloc.h>
diff --git a/gpxe/src/core/job.c b/gpxe/src/core/job.c
index 6c2faf30..438064ef 100644
--- a/gpxe/src/core/job.c
+++ b/gpxe/src/core/job.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <errno.h>
#include <gpxe/job.h>
@@ -42,6 +44,14 @@ void job_kill ( struct job_interface *job ) {
job_put ( dest );
}
+void job_progress ( struct job_interface *job,
+ struct job_progress *progress ) {
+ struct job_interface *dest = job_get_dest ( job );
+
+ dest->op->progress ( dest, progress );
+ job_put ( dest );
+}
+
/****************************************************************************
*
* Helper methods
diff --git a/gpxe/src/core/linebuf.c b/gpxe/src/core/linebuf.c
index d02f37c3..221f4e1a 100644
--- a/gpxe/src/core/linebuf.c
+++ b/gpxe/src/core/linebuf.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
diff --git a/gpxe/src/core/main.c b/gpxe/src/core/main.c
index bd2428f0..d07d24c0 100644
--- a/gpxe/src/core/main.c
+++ b/gpxe/src/core/main.c
@@ -9,11 +9,11 @@ Literature dealing with the network protocols:
DHCP - RFC2131, RFC2132 (options)
TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
- NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)
- IGMP - RFC1112
**************************************************************************/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdio.h>
#include <gpxe/init.h>
#include <gpxe/features.h>
@@ -27,9 +27,6 @@ Literature dealing with the network protocols:
#define BOLD "\033[1m"
#define CYAN "\033[36m"
-static struct feature features[0] __table_start ( struct feature, features );
-static struct feature features_end[0] __table_end ( struct feature, features );
-
/**
* Main entry point
*
@@ -61,7 +58,7 @@ __asmcall int main ( void ) {
NORMAL " -- Open Source Boot Firmware -- "
CYAN "http://etherboot.org" NORMAL "\n"
"Features:" );
- for ( feature = features ; feature < features_end ; feature++ )
+ for_each_table_entry ( feature, FEATURES )
printf ( " %s", feature->name );
printf ( "\n" );
diff --git a/gpxe/src/core/malloc.c b/gpxe/src/core/malloc.c
index db7f1bed..8b0bc24d 100644
--- a/gpxe/src/core/malloc.c
+++ b/gpxe/src/core/malloc.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stddef.h>
#include <stdint.h>
#include <string.h>
diff --git a/gpxe/src/core/misc.c b/gpxe/src/core/misc.c
index 1f51272d..c19591bb 100644
--- a/gpxe/src/core/misc.c
+++ b/gpxe/src/core/misc.c
@@ -2,7 +2,10 @@
MISC Support Routines
**************************************************************************/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
+#include <ctype.h>
#include <byteswap.h>
#include <gpxe/in.h>
#include <gpxe/timer.h>
@@ -30,20 +33,6 @@ int inet_aton ( const char *cp, struct in_addr *inp ) {
return 0;
}
-int isspace ( int c ) {
- switch ( c ) {
- case ' ':
- case '\f':
- case '\n':
- case '\r':
- case '\t':
- case '\v':
- return 1;
- default:
- return 0;
- }
-}
-
unsigned long strtoul ( const char *p, char **endp, int base ) {
unsigned long ret = 0;
unsigned int charval;
diff --git a/gpxe/src/core/monojob.c b/gpxe/src/core/monojob.c
index 657bfd7a..a24b559e 100644
--- a/gpxe/src/core/monojob.c
+++ b/gpxe/src/core/monojob.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <stdio.h>
#include <errno.h>
diff --git a/gpxe/src/core/nvo.c b/gpxe/src/core/nvo.c
index e5c07d98..3dbf51d3 100644
--- a/gpxe/src/core/nvo.c
+++ b/gpxe/src/core/nvo.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
diff --git a/gpxe/src/core/open.c b/gpxe/src/core/open.c
index db8d92e6..70b427ba 100644
--- a/gpxe/src/core/open.c
+++ b/gpxe/src/core/open.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdarg.h>
#include <string.h>
#include <errno.h>
@@ -30,18 +32,6 @@
*
*/
-/** Registered URI openers */
-static struct uri_opener uri_openers[0]
- __table_start ( struct uri_opener, uri_openers );
-static struct uri_opener uri_openers_end[0]
- __table_end ( struct uri_opener, uri_openers );
-
-/** Registered socket openers */
-static struct socket_opener socket_openers[0]
- __table_start ( struct socket_opener, socket_openers );
-static struct socket_opener socket_openers_end[0]
- __table_end ( struct socket_opener, socket_openers );
-
/**
* Open URI
*
@@ -63,8 +53,10 @@ int xfer_open_uri ( struct xfer_interface *xfer, struct uri *uri ) {
return -ENOMEM;
/* Find opener which supports this URI scheme */
- for ( opener = uri_openers ; opener < uri_openers_end ; opener++ ) {
+ for_each_table_entry ( opener, URI_OPENERS ) {
if ( strcmp ( resolved_uri->scheme, opener->scheme ) == 0 ) {
+ DBGC ( xfer, "XFER %p opening %s URI\n",
+ xfer, opener->scheme );
rc = opener->open ( xfer, resolved_uri );
goto done;
}
@@ -121,7 +113,7 @@ int xfer_open_socket ( struct xfer_interface *xfer, int semantics,
socket_semantics_name ( semantics ),
socket_family_name ( peer->sa_family ) );
- for ( opener = socket_openers; opener < socket_openers_end; opener++ ){
+ for_each_table_entry ( opener, SOCKET_OPENERS ) {
if ( ( opener->semantics == semantics ) &&
( opener->family == peer->sa_family ) ) {
return opener->open ( xfer, peer, local );
@@ -182,3 +174,24 @@ int xfer_open ( struct xfer_interface *xfer, int type, ... ) {
va_end ( args );
return rc;
}
+
+/**
+ * Reopen location
+ *
+ * @v xfer Data transfer interface
+ * @v type Location type
+ * @v args Remaining arguments depend upon location type
+ * @ret rc Return status code
+ *
+ * This will close the existing connection and open a new connection
+ * using xfer_vopen(). It is intended to be used as a .vredirect
+ * method handler.
+ */
+int xfer_vreopen ( struct xfer_interface *xfer, int type, va_list args ) {
+
+ /* Close existing connection */
+ xfer_close ( xfer, 0 );
+
+ /* Open new location */
+ return xfer_vopen ( xfer, type, args );
+}
diff --git a/gpxe/src/core/posix_io.c b/gpxe/src/core/posix_io.c
index e0459bdf..e6b1a0f6 100644
--- a/gpxe/src/core/posix_io.c
+++ b/gpxe/src/core/posix_io.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
#include <string.h>
#include <errno.h>
@@ -137,7 +139,7 @@ posix_file_xfer_deliver_iob ( struct xfer_interface *xfer,
/** POSIX file data transfer interface operations */
static struct xfer_interface_operations posix_file_xfer_operations = {
.close = posix_file_xfer_close,
- .vredirect = xfer_vopen,
+ .vredirect = xfer_vreopen,
.window = unlimited_xfer_window,
.alloc_iob = default_xfer_alloc_iob,
.deliver_iob = posix_file_xfer_deliver_iob,
diff --git a/gpxe/src/core/process.c b/gpxe/src/core/process.c
index 6a687140..9c13e020 100644
--- a/gpxe/src/core/process.c
+++ b/gpxe/src/core/process.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <gpxe/list.h>
#include <gpxe/init.h>
#include <gpxe/process.h>
@@ -31,21 +33,22 @@
/** Process run queue */
static LIST_HEAD ( run_queue );
-/** Registered permanent processes */
-static struct process processes[0]
- __table_start ( struct process, processes );
-static struct process processes_end[0]
- __table_end ( struct process, processes );
-
/**
* Add process to process list
*
* @v process Process
+ *
+ * It is safe to call process_add() multiple times; further calls will
+ * have no effect.
*/
void process_add ( struct process *process ) {
- DBGC ( process, "PROCESS %p starting\n", process );
- ref_get ( process->refcnt );
- list_add_tail ( &process->list, &run_queue );
+ if ( list_empty ( &process->list ) ) {
+ DBGC ( process, "PROCESS %p starting\n", process );
+ ref_get ( process->refcnt );
+ list_add_tail ( &process->list, &run_queue );
+ } else {
+ DBGC ( process, "PROCESS %p already started\n", process );
+ }
}
/**
@@ -93,9 +96,8 @@ void step ( void ) {
static void init_processes ( void ) {
struct process *process;
- for ( process = processes ; process < processes_end ; process++ ) {
+ for_each_table_entry ( process, PERMANENT_PROCESSES )
process_add ( process );
- }
}
/** Process initialiser */
diff --git a/gpxe/src/core/random.c b/gpxe/src/core/random.c
index d34e763a..6e7374e3 100644
--- a/gpxe/src/core/random.c
+++ b/gpxe/src/core/random.c
@@ -4,6 +4,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
#include <gpxe/timer.h>
diff --git a/gpxe/src/core/refcnt.c b/gpxe/src/core/refcnt.c
index 30bb6dea..f2286cac 100644
--- a/gpxe/src/core/refcnt.c
+++ b/gpxe/src/core/refcnt.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
#include <gpxe/refcnt.h>
diff --git a/gpxe/src/core/resolv.c b/gpxe/src/core/resolv.c
index f4a587f1..6f01f93e 100644
--- a/gpxe/src/core/resolv.c
+++ b/gpxe/src/core/resolv.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -150,12 +152,6 @@ struct resolver numeric_resolver __resolver ( RESOLV_NUMERIC ) = {
***************************************************************************
*/
-/** Registered name resolvers */
-static struct resolver resolvers[0]
- __table_start ( struct resolver, resolvers );
-static struct resolver resolvers_end[0]
- __table_end ( struct resolver, resolvers );
-
/** A name resolution multiplexer */
struct resolv_mux {
/** Reference counter */
@@ -223,7 +219,7 @@ static void resolv_mux_done ( struct resolv_interface *resolv,
/* Attempt next child resolver, if possible */
mux->resolver++;
- if ( mux->resolver >= resolvers_end ) {
+ if ( mux->resolver >= table_end ( RESOLVERS ) ) {
DBGC ( mux, "RESOLV %p failed to resolve name\n", mux );
goto finished;
}
@@ -262,7 +258,7 @@ int resolv ( struct resolv_interface *resolv, const char *name,
return -ENOMEM;
resolv_init ( &mux->parent, &null_resolv_ops, &mux->refcnt );
resolv_init ( &mux->child, &resolv_mux_child_ops, &mux->refcnt );
- mux->resolver = resolvers;
+ mux->resolver = table_start ( RESOLVERS );
memcpy ( &mux->sa, sa, sizeof ( mux->sa ) );
memcpy ( mux->name, name, name_len );
@@ -308,9 +304,36 @@ struct named_socket {
int have_local;
};
+/**
+ * Finish using named socket
+ *
+ * @v named Named socket
+ * @v rc Reason for finish
+ */
+static void named_done ( struct named_socket *named, int rc ) {
+
+ /* Close all interfaces */
+ resolv_nullify ( &named->resolv );
+ xfer_nullify ( &named->xfer );
+ xfer_close ( &named->xfer, rc );
+}
+
+/**
+ * Handle close() event
+ *
+ * @v xfer Data transfer interface
+ * @v rc Reason for close
+ */
+static void named_xfer_close ( struct xfer_interface *xfer, int rc ) {
+ struct named_socket *named =
+ container_of ( xfer, struct named_socket, xfer );
+
+ named_done ( named, rc );
+}
+
/** Named socket opener data transfer interface operations */
static struct xfer_interface_operations named_xfer_ops = {
- .close = ignore_xfer_close,
+ .close = named_xfer_close,
.vredirect = ignore_xfer_vredirect,
.window = no_xfer_window,
.alloc_iob = default_xfer_alloc_iob,
@@ -330,10 +353,6 @@ static void named_resolv_done ( struct resolv_interface *resolv,
struct named_socket *named =
container_of ( resolv, struct named_socket, resolv );
- /* Unplug resolver and nullify data transfer interface */
- resolv_unplug ( &named->resolv );
- xfer_nullify ( &named->xfer );
-
/* Redirect if name resolution was successful */
if ( rc == 0 ) {
rc = xfer_redirect ( &named->xfer, LOCATION_SOCKET,
@@ -342,12 +361,8 @@ static void named_resolv_done ( struct resolv_interface *resolv,
&named->local : NULL ) );
}
- /* Close data transfer interface if redirection failed */
- if ( rc != 0 )
- xfer_close ( &named->xfer, rc );
-
- /* Unplug data transfer interface */
- xfer_unplug ( &named->xfer );
+ /* Terminate resolution */
+ named_done ( named, rc );
}
/** Named socket opener name resolution interface operations */
diff --git a/gpxe/src/core/serial.c b/gpxe/src/core/serial.c
index 5b3be39c..d35e89e9 100644
--- a/gpxe/src/core/serial.c
+++ b/gpxe/src/core/serial.c
@@ -11,6 +11,8 @@
* parity, 1 stop bit (8N1). This can be changed in init_serial().
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include "stddef.h"
#include <gpxe/init.h>
#include <gpxe/io.h>
diff --git a/gpxe/src/core/settings.c b/gpxe/src/core/settings.c
index f34eb664..7d83101c 100644
--- a/gpxe/src/core/settings.c
+++ b/gpxe/src/core/settings.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
@@ -37,85 +39,326 @@
*
*/
-/** Registered settings */
-static struct setting settings[0]
- __table_start ( struct setting, settings );
-static struct setting settings_end[0]
- __table_end ( struct setting, settings );
+/******************************************************************************
+ *
+ * Generic settings blocks
+ *
+ ******************************************************************************
+ */
-/** Registered setting types */
-static struct setting_type setting_types[0]
- __table_start ( struct setting_type, setting_types );
-static struct setting_type setting_types_end[0]
- __table_end ( struct setting_type, setting_types );
+/**
+ * A generic setting
+ *
+ */
+struct generic_setting {
+ /** List of generic settings */
+ struct list_head list;
+ /** Setting */
+ struct setting setting;
+ /** Size of setting name */
+ size_t name_len;
+ /** Size of setting data */
+ size_t data_len;
+};
-/** Registered settings applicators */
-static struct settings_applicator settings_applicators[0]
- __table_start ( struct settings_applicator, settings_applicators );
-static struct settings_applicator settings_applicators_end[0]
- __table_end ( struct settings_applicator, settings_applicators );
+/**
+ * Get generic setting name
+ *
+ * @v generic Generic setting
+ * @ret name Generic setting name
+ */
+static inline void * generic_setting_name ( struct generic_setting *generic ) {
+ return ( ( ( void * ) generic ) + sizeof ( *generic ) );
+}
-/******************************************************************************
+/**
+ * Get generic setting data
*
- * Registered settings blocks
+ * @v generic Generic setting
+ * @ret data Generic setting data
+ */
+static inline void * generic_setting_data ( struct generic_setting *generic ) {
+ return ( ( ( void * ) generic ) + sizeof ( *generic ) +
+ generic->name_len );
+}
+
+/**
+ * Find generic setting
*
- ******************************************************************************
+ * @v generics Generic settings block
+ * @v setting Setting to find
+ * @ret generic Generic setting, or NULL
*/
+static struct generic_setting *
+find_generic_setting ( struct generic_settings *generics,
+ struct setting *setting ) {
+ struct generic_setting *generic;
+
+ list_for_each_entry ( generic, &generics->list, list ) {
+ if ( setting_cmp ( &generic->setting, setting ) == 0 )
+ return generic;
+ }
+ return NULL;
+}
/**
- * Store value of simple setting
+ * Store value of generic setting
*
- * @v options DHCP option block
+ * @v settings Settings block
* @v setting Setting to store
* @v data Setting data, or NULL to clear setting
* @v len Length of setting data
* @ret rc Return status code
*/
-int simple_settings_store ( struct settings *settings, struct setting *setting,
- const void *data, size_t len ) {
- struct simple_settings *simple =
- container_of ( settings, struct simple_settings, settings );
- return dhcpopt_extensible_store ( &simple->dhcpopts, setting->tag,
- data, len );
+int generic_settings_store ( struct settings *settings,
+ struct setting *setting,
+ const void *data, size_t len ) {
+ struct generic_settings *generics =
+ container_of ( settings, struct generic_settings, settings );
+ struct generic_setting *old;
+ struct generic_setting *new = NULL;
+ size_t name_len;
+
+ /* Identify existing generic setting, if any */
+ old = find_generic_setting ( generics, setting );
+
+ /* Create new generic setting, if required */
+ if ( len ) {
+ /* Allocate new generic setting */
+ name_len = ( strlen ( setting->name ) + 1 );
+ new = zalloc ( sizeof ( *new ) + name_len + len );
+ if ( ! new )
+ return -ENOMEM;
+
+ /* Populate new generic setting */
+ new->name_len = name_len;
+ new->data_len = len;
+ memcpy ( &new->setting, setting, sizeof ( new->setting ) );
+ new->setting.name = generic_setting_name ( new );
+ memcpy ( generic_setting_name ( new ),
+ setting->name, name_len );
+ memcpy ( generic_setting_data ( new ), data, len );
+ }
+
+ /* Delete existing generic setting, if any */
+ if ( old ) {
+ list_del ( &old->list );
+ free ( old );
+ }
+
+ /* Add new setting to list, if any */
+ if ( new )
+ list_add ( &new->list, &generics->list );
+
+ return 0;
}
/**
- * Fetch value of simple setting
+ * Fetch value of generic setting
*
- * @v options DHCP option block
+ * @v settings Settings block
* @v setting Setting to fetch
* @v data Buffer to fill with setting data
* @v len Length of buffer
* @ret len Length of setting data, or negative error
*/
-int simple_settings_fetch ( struct settings *settings, struct setting *setting,
- void *data, size_t len ) {
- struct simple_settings *simple =
- container_of ( settings, struct simple_settings, settings );
- return dhcpopt_fetch ( &simple->dhcpopts, setting->tag, data, len );
+int generic_settings_fetch ( struct settings *settings,
+ struct setting *setting,
+ void *data, size_t len ) {
+ struct generic_settings *generics =
+ container_of ( settings, struct generic_settings, settings );
+ struct generic_setting *generic;
+
+ /* Find generic setting */
+ generic = find_generic_setting ( generics, setting );
+ if ( ! generic )
+ return -ENOENT;
+
+ /* Copy out generic setting data */
+ if ( len > generic->data_len )
+ len = generic->data_len;
+ memcpy ( data, generic_setting_data ( generic ), len );
+ return generic->data_len;
+}
+
+/**
+ * Clear generic settings block
+ *
+ * @v settings Settings block
+ */
+void generic_settings_clear ( struct settings *settings ) {
+ struct generic_settings *generics =
+ container_of ( settings, struct generic_settings, settings );
+ struct generic_setting *generic;
+ struct generic_setting *tmp;
+
+ list_for_each_entry_safe ( generic, tmp, &generics->list, list ) {
+ list_del ( &generic->list );
+ free ( generic );
+ }
+ assert ( list_empty ( &generics->list ) );
}
-/** Simple settings operations */
-struct settings_operations simple_settings_operations = {
- .store = simple_settings_store,
- .fetch = simple_settings_fetch,
+/** Generic settings operations */
+struct settings_operations generic_settings_operations = {
+ .store = generic_settings_store,
+ .fetch = generic_settings_fetch,
+ .clear = generic_settings_clear,
};
-/** Root simple settings block */
-struct simple_settings simple_settings_root = {
+/******************************************************************************
+ *
+ * Registered settings blocks
+ *
+ ******************************************************************************
+ */
+
+/** Root generic settings block */
+struct generic_settings generic_settings_root = {
.settings = {
.refcnt = NULL,
.name = "",
.siblings =
- LIST_HEAD_INIT ( simple_settings_root.settings.siblings ),
+ LIST_HEAD_INIT ( generic_settings_root.settings.siblings ),
.children =
- LIST_HEAD_INIT ( simple_settings_root.settings.children ),
- .op = &simple_settings_operations,
+ LIST_HEAD_INIT ( generic_settings_root.settings.children ),
+ .op = &generic_settings_operations,
},
+ .list = LIST_HEAD_INIT ( generic_settings_root.list ),
};
/** Root settings block */
-#define settings_root simple_settings_root.settings
+#define settings_root generic_settings_root.settings
+
+/**
+ * Find child named settings block
+ *
+ * @v parent Parent settings block
+ * @v name Name within this parent
+ * @ret settings Settings block, or NULL
+ */
+static struct settings * find_child_settings ( struct settings *parent,
+ const char *name ) {
+ struct settings *settings;
+
+ /* Treat empty name as meaning "this block" */
+ if ( ! *name )
+ return parent;
+
+ /* Look for child with matching name */
+ list_for_each_entry ( settings, &parent->children, siblings ) {
+ if ( strcmp ( settings->name, name ) == 0 )
+ return settings;
+ }
+
+ return NULL;
+}
+
+/**
+ * Find or create child named settings block
+ *
+ * @v parent Parent settings block
+ * @v name Name within this parent
+ * @ret settings Settings block, or NULL
+ */
+static struct settings * autovivify_child_settings ( struct settings *parent,
+ const char *name ) {
+ struct {
+ struct generic_settings generic;
+ char name[ strlen ( name ) + 1 /* NUL */ ];
+ } *new_child;
+ struct settings *settings;
+
+ /* Return existing settings, if existent */
+ if ( ( settings = find_child_settings ( parent, name ) ) != NULL )
+ return settings;
+
+ /* Create new generic settings block */
+ new_child = zalloc ( sizeof ( *new_child ) );
+ if ( ! new_child ) {
+ DBGC ( parent, "Settings %p could not create child %s\n",
+ parent, name );
+ return NULL;
+ }
+ memcpy ( new_child->name, name, sizeof ( new_child->name ) );
+ generic_settings_init ( &new_child->generic, NULL, new_child->name );
+ settings = &new_child->generic.settings;
+ register_settings ( settings, parent );
+ return settings;
+}
+
+/**
+ * Return settings block name (for debug only)
+ *
+ * @v settings Settings block
+ * @ret name Settings block name
+ */
+static const char * settings_name ( struct settings *settings ) {
+ static char buf[64];
+ char tmp[ sizeof ( buf ) ];
+ int count;
+
+ for ( count = 0 ; settings ; settings = settings->parent ) {
+ memcpy ( tmp, buf, sizeof ( tmp ) );
+ snprintf ( buf, sizeof ( buf ), "%s%c%s", settings->name,
+ ( count++ ? '.' : '\0' ), tmp );
+ }
+ return ( buf + 1 );
+}
+
+/**
+ * Parse settings block name
+ *
+ * @v name Name
+ * @v get_child Function to find or create child settings block
+ * @ret settings Settings block, or NULL
+ */
+static struct settings *
+parse_settings_name ( const char *name,
+ struct settings * ( * get_child ) ( struct settings *,
+ const char * ) ) {
+ struct settings *settings = &settings_root;
+ char name_copy[ strlen ( name ) + 1 ];
+ char *subname;
+ char *remainder;
+
+ /* Create modifiable copy of name */
+ memcpy ( name_copy, name, sizeof ( name_copy ) );
+ remainder = name_copy;
+
+ /* Parse each name component in turn */
+ while ( remainder ) {
+ struct net_device *netdev;
+
+ subname = remainder;
+ remainder = strchr ( subname, '.' );
+ if ( remainder )
+ *(remainder++) = '\0';
+
+ /* Special case "netX" root settings block */
+ if ( ( subname == name_copy ) && ! strcmp ( subname, "netX" ) &&
+ ( ( netdev = last_opened_netdev() ) != NULL ) )
+ settings = get_child ( settings, netdev->name );
+ else
+ settings = get_child ( settings, subname );
+
+ if ( ! settings )
+ break;
+ }
+
+ return settings;
+}
+
+/**
+ * Find named settings block
+ *
+ * @v name Name
+ * @ret settings Settings block, or NULL
+ */
+struct settings * find_settings ( const char *name ) {
+
+ return parse_settings_name ( name, find_child_settings );
+}
/**
* Apply all settings
@@ -127,8 +370,7 @@ static int apply_settings ( void ) {
int rc;
/* Call all settings applicators */
- for ( applicator = settings_applicators ;
- applicator < settings_applicators_end ; applicator++ ) {
+ for_each_table_entry ( applicator, SETTINGS_APPLICATORS ) {
if ( ( rc = applicator->apply() ) != 0 ) {
DBG ( "Could not apply settings using applicator "
"%p: %s\n", applicator, strerror ( rc ) );
@@ -199,7 +441,8 @@ int register_settings ( struct settings *settings, struct settings *parent ) {
ref_get ( parent->refcnt );
settings->parent = parent;
list_add_tail ( &settings->siblings, &parent->children );
- DBGC ( settings, "Settings %p registered\n", settings );
+ DBGC ( settings, "Settings %p (\"%s\") registered\n",
+ settings, settings_name ( settings ) );
/* Fix up settings priority */
reprioritise_settings ( settings );
@@ -217,63 +460,19 @@ int register_settings ( struct settings *settings, struct settings *parent ) {
*/
void unregister_settings ( struct settings *settings ) {
+ DBGC ( settings, "Settings %p (\"%s\") unregistered\n",
+ settings, settings_name ( settings ) );
+
/* Remove from list of settings */
ref_put ( settings->refcnt );
ref_put ( settings->parent->refcnt );
settings->parent = NULL;
list_del ( &settings->siblings );
- DBGC ( settings, "Settings %p unregistered\n", settings );
/* Apply potentially-updated settings */
apply_settings();
}
-/**
- * Find child named settings block
- *
- * @v parent Parent settings block
- * @v name Name within this parent
- * @ret settings Settings block, or NULL
- */
-struct settings * find_child_settings ( struct settings *parent,
- const char *name ) {
- struct settings *settings;
- size_t len;
-
- /* NULL parent => add to settings root */
- if ( parent == NULL )
- parent = &settings_root;
-
- /* Look for a child whose name matches the initial component */
- list_for_each_entry ( settings, &parent->children, siblings ) {
- len = strlen ( settings->name );
- if ( strncmp ( name, settings->name, len ) != 0 )
- continue;
- if ( name[len] == 0 )
- return settings;
- if ( name[len] == '.' )
- return find_child_settings ( settings,
- ( name + len + 1 ) );
- }
-
- return NULL;
-}
-
-/**
- * Find named settings block
- *
- * @v name Name
- * @ret settings Settings block, or NULL
- */
-struct settings * find_settings ( const char *name ) {
-
- /* If name is empty, use the root */
- if ( ! *name )
- return &settings_root;
-
- return find_child_settings ( &settings_root, name );
-}
-
/******************************************************************************
*
* Core settings routines
@@ -298,6 +497,10 @@ int store_setting ( struct settings *settings, struct setting *setting,
if ( ! settings )
settings = &settings_root;
+ /* Sanity check */
+ if ( ! settings->op->store )
+ return -ENOTSUP;
+
/* Store setting */
if ( ( rc = settings->op->store ( settings, setting,
data, len ) ) != 0 )
@@ -345,6 +548,10 @@ int fetch_setting ( struct settings *settings, struct setting *setting,
if ( ! settings )
settings = &settings_root;
+ /* Sanity check */
+ if ( ! settings->op->fetch )
+ return -ENOTSUP;
+
/* Try this block first */
if ( ( ret = settings->op->fetch ( settings, setting,
data, len ) ) >= 0 )
@@ -411,7 +618,7 @@ int fetch_string_setting_copy ( struct settings *settings,
struct setting *setting,
char **data ) {
int len;
- int check_len;
+ int check_len = 0;
len = fetch_setting_len ( settings, setting );
if ( len < 0 )
@@ -421,7 +628,8 @@ int fetch_string_setting_copy ( struct settings *settings,
if ( ! *data )
return -ENOMEM;
- fetch_string_setting ( settings, setting, *data, ( len + 1 ) );
+ check_len = fetch_string_setting ( settings, setting, *data,
+ ( len + 1 ) );
assert ( check_len == len );
return len;
}
@@ -504,7 +712,8 @@ int fetch_uint_setting ( struct settings *settings, struct setting *setting,
return len;
/* Mask off sign-extended bits */
- *value = ( svalue & ( -1UL >> ( sizeof ( long ) - len ) ) );
+ assert ( len <= ( int ) sizeof ( long ) );
+ *value = ( svalue & ( -1UL >> ( 8 * ( sizeof ( long ) - len ) ) ) );
return len;
}
@@ -559,6 +768,16 @@ int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
}
/**
+ * Clear settings block
+ *
+ * @v settings Settings block
+ */
+void clear_settings ( struct settings *settings ) {
+ if ( settings->op->clear )
+ settings->op->clear ( settings );
+}
+
+/**
* Compare two settings
*
* @v a Setting to compare
@@ -572,8 +791,12 @@ int setting_cmp ( struct setting *a, struct setting *b ) {
if ( a->tag && ( a->tag == b->tag ) )
return 0;
- /* Otherwise, compare the names */
- return strcmp ( a->name, b->name );
+ /* Otherwise, if the settings have names, compare them */
+ if ( a->name && b->name && a->name[0] )
+ return strcmp ( a->name, b->name );
+
+ /* Otherwise, return a non-match */
+ return ( ! 0 );
}
/******************************************************************************
@@ -614,7 +837,7 @@ int storef_setting ( struct settings *settings, struct setting *setting,
static struct setting * find_setting ( const char *name ) {
struct setting *setting;
- for ( setting = settings ; setting < settings_end ; setting++ ) {
+ for_each_table_entry ( setting, SETTINGS ) {
if ( strcmp ( name, setting->name ) == 0 )
return setting;
}
@@ -622,6 +845,26 @@ static struct setting * find_setting ( const char *name ) {
}
/**
+ * Parse setting name as tag number
+ *
+ * @v name Name
+ * @ret tag Tag number, or 0 if not a valid number
+ */
+static unsigned int parse_setting_tag ( const char *name ) {
+ char *tmp = ( ( char * ) name );
+ unsigned int tag = 0;
+
+ while ( 1 ) {
+ tag = ( ( tag << 8 ) | strtoul ( tmp, &tmp, 0 ) );
+ if ( *tmp == 0 )
+ return tag;
+ if ( *tmp != '.' )
+ return 0;
+ tmp++;
+ }
+}
+
+/**
* Find setting type
*
* @v name Name
@@ -630,7 +873,7 @@ static struct setting * find_setting ( const char *name ) {
static struct setting_type * find_setting_type ( const char *name ) {
struct setting_type *type;
- for ( type = setting_types ; type < setting_types_end ; type++ ) {
+ for_each_table_entry ( type, SETTING_TYPES ) {
if ( strcmp ( name, type->name ) == 0 )
return type;
}
@@ -641,30 +884,38 @@ static struct setting_type * find_setting_type ( const char *name ) {
* Parse setting name
*
* @v name Name of setting
+ * @v get_child Function to find or create child settings block
* @v settings Settings block to fill in
* @v setting Setting to fill in
+ * @v tmp_name Buffer for copy of setting name
* @ret rc Return status code
*
* Interprets a name of the form
* "[settings_name/]tag_name[:type_name]" and fills in the appropriate
* fields.
+ *
+ * The @c tmp_name buffer must be large enough to hold a copy of the
+ * setting name.
*/
-static int parse_setting_name ( const char *name, struct settings **settings,
- struct setting *setting ) {
- char tmp_name[ strlen ( name ) + 1 ];
+static int
+parse_setting_name ( const char *name,
+ struct settings * ( * get_child ) ( struct settings *,
+ const char * ),
+ struct settings **settings, struct setting *setting,
+ char *tmp_name ) {
char *settings_name;
char *setting_name;
char *type_name;
struct setting *named_setting;
- char *tmp;
/* Set defaults */
*settings = &settings_root;
memset ( setting, 0, sizeof ( *setting ) );
- setting->type = &setting_type_hex;
+ setting->name = "";
+ setting->type = &setting_type_string;
/* Split name into "[settings_name/]setting_name[:type_name]" */
- memcpy ( tmp_name, name, sizeof ( tmp_name ) );
+ strcpy ( tmp_name, name );
if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
*(setting_name++) = 0;
settings_name = tmp_name;
@@ -677,7 +928,7 @@ static int parse_setting_name ( const char *name, struct settings **settings,
/* Identify settings block, if specified */
if ( settings_name ) {
- *settings = find_settings ( settings_name );
+ *settings = parse_settings_name ( settings_name, get_child );
if ( *settings == NULL ) {
DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
settings_name, name );
@@ -685,25 +936,16 @@ static int parse_setting_name ( const char *name, struct settings **settings,
}
}
- /* Identify tag number */
+ /* Identify setting */
if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
+ /* Matches a defined named setting; use that setting */
memcpy ( setting, named_setting, sizeof ( *setting ) );
- } else {
- /* Unrecognised name: try to interpret as a tag number */
- tmp = setting_name;
- while ( 1 ) {
- setting->tag = ( ( setting->tag << 8 ) |
- strtoul ( tmp, &tmp, 0 ) );
- if ( *tmp == 0 )
- break;
- if ( *tmp != '.' ) {
- DBG ( "Invalid setting \"%s\" in \"%s\"\n",
- setting_name, name );
- return -ENOENT;
- }
- tmp++;
- }
+ } else if ( ( setting->tag = parse_setting_tag ( setting_name ) ) !=0){
+ /* Is a valid numeric tag; use the tag */
setting->tag |= (*settings)->tag_magic;
+ } else {
+ /* Use the arbitrary name */
+ setting->name = setting_name;
}
/* Identify setting type, if specified */
@@ -729,9 +971,11 @@ static int parse_setting_name ( const char *name, struct settings **settings,
int storef_named_setting ( const char *name, const char *value ) {
struct settings *settings;
struct setting setting;
+ char tmp_name[ strlen ( name ) + 1 ];
int rc;
- if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
+ if ( ( rc = parse_setting_name ( name, autovivify_child_settings,
+ &settings, &setting, tmp_name )) != 0)
return rc;
return storef_setting ( settings, &setting, value );
}
@@ -747,9 +991,11 @@ int storef_named_setting ( const char *name, const char *value ) {
int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
struct settings *settings;
struct setting setting;
+ char tmp_name[ strlen ( name ) + 1 ];
int rc;
- if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
+ if ( ( rc = parse_setting_name ( name, find_child_settings,
+ &settings, &setting, tmp_name )) != 0)
return rc;
return fetchf_setting ( settings, &setting, buf, len );
}
@@ -839,7 +1085,7 @@ static int fetchf_uristring ( struct settings *settings,
fetch_string_setting ( settings, setting, raw_buf,
sizeof ( raw_buf ) );
- return uri_encode ( raw_buf, buf, len );
+ return uri_encode ( raw_buf, buf, len, URI_FRAGMENT );
}
}
@@ -1180,7 +1426,7 @@ struct setting filename_setting __setting = {
/** Root path setting */
struct setting root_path_setting __setting = {
.name = "root-path",
- .description = "NFS/iSCSI root path",
+ .description = "iSCSI root path",
.tag = DHCP_ROOT_PATH,
.type = &setting_type_string,
};
diff --git a/gpxe/src/core/string.c b/gpxe/src/core/string.c
index 2e17bdcb..190007a4 100644
--- a/gpxe/src/core/string.c
+++ b/gpxe/src/core/string.c
@@ -10,6 +10,8 @@
* published by the Free Software Foundation.
*/
+FILE_LICENCE ( GPL2_ONLY );
+
/*
* stupid library routines.. The optimized versions should generally be found
* as inline code in <asm-xx/string.h>
diff --git a/gpxe/src/core/timer.c b/gpxe/src/core/timer.c
index d71e3da1..096d07ec 100644
--- a/gpxe/src/core/timer.c
+++ b/gpxe/src/core/timer.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <unistd.h>
/**
diff --git a/gpxe/src/core/uri.c b/gpxe/src/core/uri.c
index 7bb46da0..6a1f2e59 100644
--- a/gpxe/src/core/uri.c
+++ b/gpxe/src/core/uri.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/** @file
*
* Uniform Resource Identifiers
@@ -74,6 +76,7 @@ struct uri * parse_uri ( const char *uri_string ) {
char *tmp;
char *path = NULL;
char *authority = NULL;
+ int i;
size_t raw_len;
/* Allocate space for URI struct and a copy of the string */
@@ -83,7 +86,7 @@ struct uri * parse_uri ( const char *uri_string ) {
return NULL;
raw = ( ( ( char * ) uri ) + sizeof ( *uri ) );
- /* Zero URI struct and copy in the raw string */
+ /* Copy in the raw string */
memcpy ( raw, uri_string, raw_len );
/* Start by chopping off the fragment, if it exists */
@@ -169,6 +172,14 @@ struct uri * parse_uri ( const char *uri_string ) {
uri->port = tmp;
}
+ /* Decode fields that should be decoded */
+ for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) {
+ const char *field = uri_get_field ( uri, i );
+ if ( field && ( URI_ENCODED & ( 1 << i ) ) )
+ uri_decode ( field, ( char * ) field,
+ strlen ( field ) + 1 /* NUL */ );
+ }
+
done:
DBG ( "URI \"%s\" split into", uri_string );
dump_uri ( uri );
@@ -196,71 +207,65 @@ unsigned int uri_port ( struct uri *uri, unsigned int default_port ) {
* @v buf Buffer to fill with URI string
* @v size Size of buffer
* @v uri URI to write into buffer, or NULL
+ * @v fields Bitmask of fields to include in URI string, or URI_ALL
* @ret len Length of URI string
*/
-int unparse_uri ( char *buf, size_t size, struct uri *uri ) {
+int unparse_uri ( char *buf, size_t size, struct uri *uri,
+ unsigned int fields ) {
+ /* List of characters that typically go before certain fields */
+ static char separators[] = { /* scheme */ 0, /* opaque */ ':',
+ /* user */ 0, /* password */ ':',
+ /* host */ '@', /* port */ ':',
+ /* path */ 0, /* query */ '?',
+ /* fragment */ '#' };
int used = 0;
+ int i;
DBG ( "URI unparsing" );
dump_uri ( uri );
DBG ( "\n" );
+ /* Ensure buffer is NUL-terminated */
+ if ( size )
+ buf[0] = '\0';
+
/* Special-case NULL URI */
- if ( ! uri ) {
- if ( size )
- buf[0] = '\0';
+ if ( ! uri )
return 0;
- }
-
- /* Special-case opaque URIs */
- if ( uri->opaque ) {
- return ssnprintf ( ( buf + used ), ( size - used ),
- "%s:%s", uri->scheme, uri->opaque );
- }
- /* scheme:// */
- if ( uri->scheme ) {
- used += ssnprintf ( ( buf + used ), ( size - used ),
- "%s://", uri->scheme );
- }
-
- /* [user[:password]@]host[:port] */
- if ( uri->host ) {
- if ( uri->user ) {
- used += ssnprintf ( ( buf + used ), ( size - used ),
- "%s", uri->user );
- if ( uri->password ) {
- used += ssnprintf ( ( buf + used ),
- ( size - used ),
- ":%s", uri->password );
+ /* Iterate through requested fields */
+ for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) {
+ const char *field = uri_get_field ( uri, i );
+ char sep = separators[i];
+
+ /* Ensure `fields' only contains bits for fields that exist */
+ if ( ! field )
+ fields &= ~( 1 << i );
+
+ /* Store this field if we were asked to */
+ if ( fields & ( 1 << i ) ) {
+ /* Print :// if we're non-opaque and had a scheme */
+ if ( ( fields & URI_SCHEME_BIT ) &&
+ ( i > URI_OPAQUE ) ) {
+ used += ssnprintf ( buf + used, size - used,
+ "://" );
+ /* Only print :// once */
+ fields &= ~URI_SCHEME_BIT;
}
- used += ssnprintf ( ( buf + used ), ( size - used ),
- "@" );
- }
- used += ssnprintf ( ( buf + used ), ( size - used ), "%s",
- uri->host );
- if ( uri->port ) {
- used += ssnprintf ( ( buf + used ), ( size - used ),
- ":%s", uri->port );
- }
- }
-
- /* /path */
- if ( uri->path ) {
- used += ssnprintf ( ( buf + used ), ( size - used ),
- "%s", uri->path );
- }
- /* ?query */
- if ( uri->query ) {
- used += ssnprintf ( ( buf + used ), ( size - used ),
- "?%s", uri->query );
- }
-
- /* #fragment */
- if ( uri->fragment ) {
- used += ssnprintf ( ( buf + used ), ( size - used ),
- "#%s", uri->fragment );
+ /* Only print separator if an earlier field exists */
+ if ( sep && ( fields & ( ( 1 << i ) - 1 ) ) )
+ used += ssnprintf ( buf + used, size - used,
+ "%c", sep );
+
+ /* Print contents of field, possibly encoded */
+ if ( URI_ENCODED & ( 1 << i ) )
+ used += uri_encode ( field, buf + used,
+ size - used, i );
+ else
+ used += ssnprintf ( buf + used, size - used,
+ "%s", field );
+ }
}
return used;
@@ -275,10 +280,10 @@ int unparse_uri ( char *buf, size_t size, struct uri *uri ) {
* Creates a modifiable copy of a URI.
*/
struct uri * uri_dup ( struct uri *uri ) {
- size_t len = ( unparse_uri ( NULL, 0, uri ) + 1 );
+ size_t len = ( unparse_uri ( NULL, 0, uri, URI_ALL ) + 1 );
char buf[len];
- unparse_uri ( buf, len, uri );
+ unparse_uri ( buf, len, uri, URI_ALL );
return parse_uri ( buf );
}
@@ -391,16 +396,31 @@ struct uri * resolve_uri ( struct uri *base_uri,
* Test for unreserved URI characters
*
* @v c Character to test
+ * @v field Field of URI in which character lies
* @ret is_unreserved Character is an unreserved character
*/
-static int is_unreserved_uri_char ( int c ) {
+static int is_unreserved_uri_char ( int c, int field ) {
/* According to RFC3986, the unreserved character set is
*
* A-Z a-z 0-9 - _ . ~
+ *
+ * but we also pass & ; = in queries, / in paths,
+ * and everything in opaques
*/
- return ( isupper ( c ) || islower ( c ) || isdigit ( c ) ||
- ( c == '-' ) || ( c == '_' ) ||
- ( c == '.' ) || ( c == '~' ) );
+ int ok = ( isupper ( c ) || islower ( c ) || isdigit ( c ) ||
+ ( c == '-' ) || ( c == '_' ) ||
+ ( c == '.' ) || ( c == '~' ) );
+
+ if ( field == URI_QUERY )
+ ok = ok || ( c == ';' ) || ( c == '&' ) || ( c == '=' );
+
+ if ( field == URI_PATH )
+ ok = ok || ( c == '/' );
+
+ if ( field == URI_OPAQUE )
+ ok = 1;
+
+ return ok;
}
/**
@@ -409,18 +429,20 @@ static int is_unreserved_uri_char ( int c ) {
* @v raw_string String to be URI-encoded
* @v buf Buffer to contain encoded string
* @v len Length of buffer
+ * @v field Field of URI in which string lies
* @ret len Length of encoded string (excluding NUL)
*/
-size_t uri_encode ( const char *raw_string, char *buf, size_t len ) {
+size_t uri_encode ( const char *raw_string, char *buf, ssize_t len,
+ int field ) {
ssize_t remaining = len;
size_t used;
unsigned char c;
- if ( len )
+ if ( len > 0 )
buf[0] = '\0';
while ( ( c = *(raw_string++) ) ) {
- if ( is_unreserved_uri_char ( c ) ) {
+ if ( is_unreserved_uri_char ( c, field ) ) {
used = ssnprintf ( buf, remaining, "%c", c );
} else {
used = ssnprintf ( buf, remaining, "%%%02X", c );
@@ -439,17 +461,17 @@ size_t uri_encode ( const char *raw_string, char *buf, size_t len ) {
* @v buf Buffer to contain decoded string
* @v len Length of buffer
* @ret len Length of decoded string (excluding NUL)
+ *
+ * This function may be used in-place, with @a buf the same as
+ * @a encoded_string.
*/
-size_t uri_decode ( const char *encoded_string, char *buf, size_t len ) {
- ssize_t remaining = len;
+size_t uri_decode ( const char *encoded_string, char *buf, ssize_t len ) {
+ ssize_t remaining;
char hexbuf[3];
char *hexbuf_end;
unsigned char c;
- if ( len )
- buf[0] = '\0';
-
- while ( *encoded_string ) {
+ for ( remaining = len; *encoded_string; remaining-- ) {
if ( *encoded_string == '%' ) {
encoded_string++;
snprintf ( hexbuf, sizeof ( hexbuf ), "%s",
@@ -459,7 +481,12 @@ size_t uri_decode ( const char *encoded_string, char *buf, size_t len ) {
} else {
c = *(encoded_string++);
}
- ssnprintf ( buf++, remaining--, "%c", c );
+ if ( remaining > 1 )
+ *buf++ = c;
}
+
+ if ( len )
+ *buf = 0;
+
return ( len - remaining );
}
diff --git a/gpxe/src/core/uuid.c b/gpxe/src/core/uuid.c
index a3a82c68..2b67d55d 100644
--- a/gpxe/src/core/uuid.c
+++ b/gpxe/src/core/uuid.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdio.h>
#include <byteswap.h>
diff --git a/gpxe/src/core/vsprintf.c b/gpxe/src/core/vsprintf.c
index 4457fe4f..21ab2429 100644
--- a/gpxe/src/core/vsprintf.c
+++ b/gpxe/src/core/vsprintf.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stddef.h>
#include <stdarg.h>
#include <stdio.h>
diff --git a/gpxe/src/core/xfer.c b/gpxe/src/core/xfer.c
index 9ed19da2..1ec6f9d3 100644
--- a/gpxe/src/core/xfer.c
+++ b/gpxe/src/core/xfer.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <stdio.h>
#include <errno.h>
@@ -43,11 +45,14 @@ static struct xfer_metadata dummy_metadata;
*/
void xfer_close ( struct xfer_interface *xfer, int rc ) {
struct xfer_interface *dest = xfer_get_dest ( xfer );
+ struct xfer_interface_operations *op = xfer->op;
DBGC ( xfer, "XFER %p->%p close\n", xfer, dest );
xfer_unplug ( xfer );
+ xfer_nullify ( xfer );
dest->op->close ( dest, rc );
+ xfer->op = op;
xfer_put ( dest );
}
diff --git a/gpxe/src/crypto/aes_wrap.c b/gpxe/src/crypto/aes_wrap.c
new file mode 100644
index 00000000..d7f94af0
--- /dev/null
+++ b/gpxe/src/crypto/aes_wrap.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <string.h>
+#include <gpxe/crypto.h>
+#include <gpxe/aes.h>
+
+/**
+ * Wrap a key or other data using AES Key Wrap (RFC 3394)
+ *
+ * @v kek Key Encryption Key, 16 bytes
+ * @v src Data to encrypt
+ * @v nblk Number of 8-byte blocks in @a data
+ * @ret dest Encrypted data (8 bytes longer than input)
+ *
+ * The algorithm is implemented such that @a src and @a dest may point
+ * to the same buffer.
+ */
+int aes_wrap ( const void *kek, const void *src, void *dest, int nblk )
+{
+ u8 *A = dest;
+ u8 B[16];
+ u8 *R;
+ int i, j;
+ void *aes_ctx = malloc ( AES_CTX_SIZE );
+
+ if ( ! aes_ctx )
+ return -1;
+
+ cipher_setkey ( &aes_algorithm, aes_ctx, kek, 16 );
+
+ /* Set up */
+ memset ( A, 0xA6, sizeof ( A ) );
+ memmove ( dest + 8, src, nblk * 8 );
+
+ /* Wrap */
+ for ( j = 0; j < 6; j++ ) {
+ R = dest + 8;
+ for ( i = 1; i <= nblk; i++ ) {
+ memcpy ( B, A, 8 );
+ memcpy ( B + 8, R, 8 );
+ cipher_encrypt ( &aes_algorithm, aes_ctx, B, B, 16 );
+ memcpy ( A, B, 8 );
+ A[7] ^= ( nblk * j ) + i;
+ memcpy ( R, B + 8, 8 );
+ R += 8;
+ }
+ }
+
+ free ( aes_ctx );
+ return 0;
+}
+
+/**
+ * Unwrap a key or other data using AES Key Wrap (RFC 3394)
+ *
+ * @v kek Key Encryption Key, 16 bytes
+ * @v src Data to decrypt
+ * @v nblk Number of 8-byte blocks in @e plaintext key
+ * @ret dest Decrypted data (8 bytes shorter than input)
+ * @ret rc Zero on success, nonzero on IV mismatch
+ *
+ * The algorithm is implemented such that @a src and @a dest may point
+ * to the same buffer.
+ */
+int aes_unwrap ( const void *kek, const void *src, void *dest, int nblk )
+{
+ u8 A[8], B[16];
+ u8 *R;
+ int i, j;
+ void *aes_ctx = malloc ( AES_CTX_SIZE );
+
+ if ( ! aes_ctx )
+ return -1;
+
+ cipher_setkey ( &aes_algorithm, aes_ctx, kek, 16 );
+
+ /* Set up */
+ memcpy ( A, src, 8 );
+ memmove ( dest, src + 8, nblk * 8 );
+
+ /* Unwrap */
+ for ( j = 5; j >= 0; j-- ) {
+ R = dest + ( nblk - 1 ) * 8;
+ for ( i = nblk; i >= 1; i-- ) {
+ memcpy ( B, A, 8 );
+ memcpy ( B + 8, R, 8 );
+ B[7] ^= ( nblk * j ) + i;
+ cipher_decrypt ( &aes_algorithm, aes_ctx, B, B, 16 );
+ memcpy ( A, B, 8 );
+ memcpy ( R, B + 8, 8 );
+ R -= 8;
+ }
+ }
+
+ free ( aes_ctx );
+
+ /* Check IV */
+ for ( i = 0; i < 8; i++ ) {
+ if ( A[i] != 0xA6 )
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/gpxe/src/crypto/arc4.c b/gpxe/src/crypto/arc4.c
new file mode 100644
index 00000000..e58fba7c
--- /dev/null
+++ b/gpxe/src/crypto/arc4.c
@@ -0,0 +1,131 @@
+/*
+ * The ARC4 stream cipher.
+ *
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/crypto.h>
+#include <gpxe/arc4.h>
+
+#define SWAP( ary, i, j ) \
+ ({ u8 temp = ary[i]; ary[i] = ary[j]; ary[j] = temp; })
+
+/**
+ * Set ARC4 key
+ *
+ * @v ctxv ARC4 encryption context
+ * @v keyv Key to set
+ * @v keylen Length of key
+ *
+ * If an initialisation vector is to be used, it should be prepended
+ * to the key; ARC4 does not implement the @c setiv function because
+ * there is no standard length for an initialisation vector in the
+ * cipher.
+ */
+static int arc4_setkey ( void *ctxv, const void *keyv, size_t keylen )
+{
+ struct arc4_ctx *ctx = ctxv;
+ const u8 *key = keyv;
+ u8 *S = ctx->state;
+ int i, j;
+
+ for ( i = 0; i < 256; i++ ) {
+ S[i] = i;
+ }
+
+ for ( i = j = 0; i < 256; i++ ) {
+ j = ( j + S[i] + key[i % keylen] ) & 0xff;
+ SWAP ( S, i, j );
+ }
+
+ ctx->i = ctx->j = 0;
+ return 0;
+}
+
+/**
+ * Perform ARC4 encryption or decryption
+ *
+ * @v ctxv ARC4 encryption context
+ * @v srcv Data to encrypt or decrypt
+ * @v dstv Location to store encrypted or decrypted data
+ * @v len Length of data to operate on
+ *
+ * ARC4 is a stream cipher that works by generating a stream of PRNG
+ * data based on the key, and XOR'ing it with the data to be
+ * encrypted. Since XOR is symmetric, encryption and decryption in
+ * ARC4 are the same operation.
+ *
+ * If you pass a @c NULL source or destination pointer, @a len
+ * keystream bytes will be consumed without encrypting any data.
+ */
+static void arc4_xor ( void *ctxv, const void *srcv, void *dstv,
+ size_t len )
+{
+ struct arc4_ctx *ctx = ctxv;
+ const u8 *src = srcv;
+ u8 *dst = dstv;
+ u8 *S = ctx->state;
+ int i = ctx->i, j = ctx->j;
+
+ while ( len-- ) {
+ i = ( i + 1 ) & 0xff;
+ j = ( j + S[i] ) & 0xff;
+ SWAP ( S, i, j );
+ if ( srcv && dstv )
+ *dst++ = *src++ ^ S[(S[i] + S[j]) & 0xff];
+ }
+
+ ctx->i = i;
+ ctx->j = j;
+}
+
+static void arc4_setiv ( void *ctx __unused, const void *iv __unused )
+{
+ /* ARC4 does not use a fixed-length IV */
+}
+
+
+/**
+ * Perform ARC4 encryption or decryption, skipping initial keystream bytes
+ *
+ * @v key ARC4 encryption key
+ * @v keylen Key length
+ * @v skip Number of bytes of keystream to skip
+ * @v src Message to encrypt or decrypt
+ * @v msglen Length of message
+ * @ret dst Encrypted or decrypted message
+ */
+void arc4_skip ( const void *key, size_t keylen, size_t skip,
+ const void *src, void *dst, size_t msglen )
+{
+ struct arc4_ctx ctx;
+ arc4_setkey ( &ctx, key, keylen );
+ arc4_xor ( &ctx, NULL, NULL, skip );
+ arc4_xor ( &ctx, src, dst, msglen );
+}
+
+struct cipher_algorithm arc4_algorithm = {
+ .name = "ARC4",
+ .ctxsize = ARC4_CTX_SIZE,
+ .blocksize = 1,
+ .setkey = arc4_setkey,
+ .setiv = arc4_setiv,
+ .encrypt = arc4_xor,
+ .decrypt = arc4_xor,
+};
diff --git a/gpxe/src/crypto/asn1.c b/gpxe/src/crypto/asn1.c
index 25e7495b..154a8a84 100644
--- a/gpxe/src/crypto/asn1.c
+++ b/gpxe/src/crypto/asn1.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
diff --git a/gpxe/src/crypto/axtls_aes.c b/gpxe/src/crypto/axtls_aes.c
index 51e1924e..8bd37586 100644
--- a/gpxe/src/crypto/axtls_aes.c
+++ b/gpxe/src/crypto/axtls_aes.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <errno.h>
#include <byteswap.h>
@@ -30,17 +32,6 @@
*
*/
-/** Basic AES blocksize */
-#define AES_BLOCKSIZE 16
-
-/** AES context */
-struct aes_context {
- /** AES context for AXTLS */
- AES_CTX axtls_ctx;
- /** Cipher is being used for decrypting */
- int decrypting;
-};
-
/**
* Set key
*
@@ -152,7 +143,7 @@ static void aes_decrypt ( void *ctx, const void *src, void *dst,
}
/** Basic AES algorithm */
-static struct cipher_algorithm aes_algorithm = {
+struct cipher_algorithm aes_algorithm = {
.name = "aes",
.ctxsize = sizeof ( struct aes_context ),
.blocksize = AES_BLOCKSIZE,
diff --git a/gpxe/src/crypto/cbc.c b/gpxe/src/crypto/cbc.c
index c7116ea9..1710203c 100644
--- a/gpxe/src/crypto/cbc.c
+++ b/gpxe/src/crypto/cbc.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <string.h>
#include <assert.h>
#include <gpxe/crypto.h>
diff --git a/gpxe/src/crypto/chap.c b/gpxe/src/crypto/chap.c
index d0784d25..8aa224c4 100644
--- a/gpxe/src/crypto/chap.c
+++ b/gpxe/src/crypto/chap.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
diff --git a/gpxe/src/crypto/crandom.c b/gpxe/src/crypto/crandom.c
new file mode 100644
index 00000000..9828482e
--- /dev/null
+++ b/gpxe/src/crypto/crandom.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Cryptographically strong random number generator
+ *
+ * Currently the cryptographic part is not implemented, and this just
+ * uses random().
+ */
+
+#include <gpxe/crypto.h>
+#include <stdlib.h>
+
+/**
+ * Get cryptographically strong random bytes
+ *
+ * @v buf Buffer in which to store random bytes
+ * @v len Number of random bytes to generate
+ *
+ * @b WARNING: This function is currently underimplemented, and does
+ * not give numbers any stronger than random()!
+ */
+void get_random_bytes ( void *buf, size_t len )
+{
+ u8 *bufp = buf;
+
+ /*
+ * Somewhat arbitrarily, choose the 0x00FF0000-masked byte
+ * returned by random() as having good entropy. PRNGs often
+ * don't provide good entropy in lower bits, and the top byte
+ * might show a pattern because of sign issues.
+ */
+
+ while ( len-- ) {
+ *bufp++ = ( random() >> 16 ) & 0xFF;
+ }
+}
diff --git a/gpxe/src/crypto/crc32.c b/gpxe/src/crypto/crc32.c
new file mode 100644
index 00000000..0cc314e8
--- /dev/null
+++ b/gpxe/src/crypto/crc32.c
@@ -0,0 +1,54 @@
+/*
+ * Little-endian CRC32 implementation.
+ *
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/crc32.h>
+
+#define CRCPOLY 0xedb88320
+
+/**
+ * Calculate 32-bit little-endian CRC checksum
+ *
+ * @v seed Initial value
+ * @v data Data to checksum
+ * @v len Length of data
+ *
+ * Usually @a seed is initially zero or all one bits, depending on the
+ * protocol. To continue a CRC checksum over multiple calls, pass the
+ * return value from one call as the @a seed parameter to the next.
+ */
+u32 crc32_le ( u32 seed, const void *data, size_t len )
+{
+ u32 crc = seed;
+ const u8 *src = data;
+ u32 mult;
+ int i;
+
+ while ( len-- ) {
+ crc ^= *src++;
+ for ( i = 0; i < 8; i++ ) {
+ mult = ( crc & 1 ) ? CRCPOLY : 0;
+ crc = ( crc >> 1 ) ^ mult;
+ }
+ }
+
+ return crc;
+}
diff --git a/gpxe/src/crypto/crypto_null.c b/gpxe/src/crypto/crypto_null.c
index 8cc9217a..61efb34e 100644
--- a/gpxe/src/crypto/crypto_null.c
+++ b/gpxe/src/crypto/crypto_null.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
diff --git a/gpxe/src/crypto/hmac.c b/gpxe/src/crypto/hmac.c
index be0298a7..d64730c0 100644
--- a/gpxe/src/crypto/hmac.c
+++ b/gpxe/src/crypto/hmac.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
/**
* @file
*
diff --git a/gpxe/src/crypto/md5.c b/gpxe/src/crypto/md5.c
index 76fb8a69..8c606398 100644
--- a/gpxe/src/crypto/md5.c
+++ b/gpxe/src/crypto/md5.c
@@ -20,36 +20,36 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <string.h>
#include <byteswap.h>
#include <gpxe/crypto.h>
#include <gpxe/md5.h>
-#define __md5step __attribute__ (( regparm ( 3 ) ))
-
struct md5_step {
- u32 __md5step ( * f ) ( u32 b, u32 c, u32 d );
+ u32 ( * f ) ( u32 b, u32 c, u32 d );
u8 coefficient;
u8 constant;
};
-static u32 __md5step f1(u32 b, u32 c, u32 d)
+static u32 f1(u32 b, u32 c, u32 d)
{
return ( d ^ ( b & ( c ^ d ) ) );
}
-static u32 __md5step f2(u32 b, u32 c, u32 d)
+static u32 f2(u32 b, u32 c, u32 d)
{
return ( c ^ ( d & ( b ^ c ) ) );
}
-static u32 __md5step f3(u32 b, u32 c, u32 d)
+static u32 f3(u32 b, u32 c, u32 d)
{
return ( b ^ c ^ d );
}
-static u32 __md5step f4(u32 b, u32 c, u32 d)
+static u32 f4(u32 b, u32 c, u32 d)
{
return ( c ^ ( b | ~d ) );
}
diff --git a/gpxe/src/crypto/sha1extra.c b/gpxe/src/crypto/sha1extra.c
new file mode 100644
index 00000000..c144a0f6
--- /dev/null
+++ b/gpxe/src/crypto/sha1extra.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/crypto.h>
+#include <gpxe/sha1.h>
+#include <gpxe/hmac.h>
+#include <stdint.h>
+#include <byteswap.h>
+
+/**
+ * SHA1 pseudorandom function for creating derived keys
+ *
+ * @v key Master key with which this call is associated
+ * @v key_len Length of key
+ * @v label NUL-terminated ASCII string describing purpose of PRF data
+ * @v data Further data that should be included in the PRF
+ * @v data_len Length of further PRF data
+ * @v prf_len Bytes of PRF to generate
+ * @ret prf Pseudorandom function bytes
+ *
+ * This is the PRF variant used by 802.11, defined in IEEE 802.11-2007
+ * 8.5.5.1. EAP-FAST uses a different SHA1-based PRF, and TLS uses an
+ * MD5-based PRF.
+ */
+void prf_sha1 ( const void *key, size_t key_len, const char *label,
+ const void *data, size_t data_len, void *prf, size_t prf_len )
+{
+ u32 blk;
+ u8 keym[key_len]; /* modifiable copy of key */
+ u8 in[strlen ( label ) + 1 + data_len + 1]; /* message to HMAC */
+ u8 *in_blknr; /* pointer to last byte of in, block number */
+ u8 out[SHA1_SIZE]; /* HMAC-SHA1 result */
+ u8 sha1_ctx[SHA1_CTX_SIZE]; /* SHA1 context */
+ const size_t label_len = strlen ( label );
+
+ /* The HMAC-SHA-1 is calculated using the given key on the
+ message text `label', followed by a NUL, followed by one
+ byte indicating the block number (0 for first). */
+
+ memcpy ( keym, key, key_len );
+
+ memcpy ( in, label, strlen ( label ) + 1 );
+ memcpy ( in + label_len + 1, data, data_len );
+ in_blknr = in + label_len + 1 + data_len;
+
+ for ( blk = 0 ;; blk++ ) {
+ *in_blknr = blk;
+
+ hmac_init ( &sha1_algorithm, sha1_ctx, keym, &key_len );
+ hmac_update ( &sha1_algorithm, sha1_ctx, in, sizeof ( in ) );
+ hmac_final ( &sha1_algorithm, sha1_ctx, keym, &key_len, out );
+
+ if ( prf_len <= SHA1_SIZE ) {
+ memcpy ( prf, out, prf_len );
+ break;
+ }
+
+ memcpy ( prf, out, SHA1_SIZE );
+ prf_len -= SHA1_SIZE;
+ prf += SHA1_SIZE;
+ }
+}
+
+/**
+ * PBKDF2 key derivation function inner block operation
+ *
+ * @v passphrase Passphrase from which to derive key
+ * @v pass_len Length of passphrase
+ * @v salt Salt to include in key
+ * @v salt_len Length of salt
+ * @v iterations Number of iterations of SHA1 to perform
+ * @v blocknr Index of this block, starting at 1
+ * @ret block SHA1_SIZE bytes of PBKDF2 data
+ *
+ * The operation of this function is described in RFC 2898.
+ */
+static void pbkdf2_sha1_f ( const void *passphrase, size_t pass_len,
+ const void *salt, size_t salt_len,
+ int iterations, u32 blocknr, u8 *block )
+{
+ u8 pass[pass_len]; /* modifiable passphrase */
+ u8 in[salt_len + 4]; /* input buffer to first round */
+ u8 last[SHA1_SIZE]; /* output of round N, input of N+1 */
+ u8 sha1_ctx[SHA1_CTX_SIZE];
+ u8 *next_in = in; /* changed to `last' after first round */
+ int next_size = sizeof ( in );
+ int i, j;
+
+ blocknr = htonl ( blocknr );
+
+ memcpy ( pass, passphrase, pass_len );
+ memcpy ( in, salt, salt_len );
+ memcpy ( in + salt_len, &blocknr, 4 );
+ memset ( block, 0, SHA1_SIZE );
+
+ for ( i = 0; i < iterations; i++ ) {
+ hmac_init ( &sha1_algorithm, sha1_ctx, pass, &pass_len );
+ hmac_update ( &sha1_algorithm, sha1_ctx, next_in, next_size );
+ hmac_final ( &sha1_algorithm, sha1_ctx, pass, &pass_len, last );
+
+ for ( j = 0; j < SHA1_SIZE; j++ ) {
+ block[j] ^= last[j];
+ }
+
+ next_in = last;
+ next_size = SHA1_SIZE;
+ }
+}
+
+/**
+ * PBKDF2 key derivation function using SHA1
+ *
+ * @v passphrase Passphrase from which to derive key
+ * @v pass_len Length of passphrase
+ * @v salt Salt to include in key
+ * @v salt_len Length of salt
+ * @v iterations Number of iterations of SHA1 to perform
+ * @v key_len Length of key to generate
+ * @ret key Generated key bytes
+ *
+ * This is used most notably in 802.11 WPA passphrase hashing, in
+ * which case the salt is the SSID, 4096 iterations are used, and a
+ * 32-byte key is generated that serves as the Pairwise Master Key for
+ * EAPOL authentication.
+ *
+ * The operation of this function is further described in RFC 2898.
+ */
+void pbkdf2_sha1 ( const void *passphrase, size_t pass_len,
+ const void *salt, size_t salt_len,
+ int iterations, void *key, size_t key_len )
+{
+ u32 blocks = ( key_len + SHA1_SIZE - 1 ) / SHA1_SIZE;
+ u32 blk;
+ u8 buf[SHA1_SIZE];
+
+ for ( blk = 1; blk <= blocks; blk++ ) {
+ pbkdf2_sha1_f ( passphrase, pass_len, salt, salt_len,
+ iterations, blk, buf );
+ if ( key_len <= SHA1_SIZE ) {
+ memcpy ( key, buf, key_len );
+ break;
+ }
+
+ memcpy ( key, buf, SHA1_SIZE );
+ key_len -= SHA1_SIZE;
+ key += SHA1_SIZE;
+ }
+}
diff --git a/gpxe/src/crypto/x509.c b/gpxe/src/crypto/x509.c
index 35adfa38..31ed412f 100644
--- a/gpxe/src/crypto/x509.c
+++ b/gpxe/src/crypto/x509.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdlib.h>
#include <string.h>
#include <errno.h>
diff --git a/gpxe/src/doc/pxe_extensions b/gpxe/src/doc/pxe_extensions
index 92269cfc..8ff14a95 100644
--- a/gpxe/src/doc/pxe_extensions
+++ b/gpxe/src/doc/pxe_extensions
@@ -277,3 +277,36 @@ Provider: Set to 0x45585067 ("gPXE"). Another implementation of this
APIMask: Bitmask of supported API functions (one bit for each function
in the range 00e0h to 00ffh).
Flags: Set to zero, reserved for future use.
+
+
+
+
+FILE EXIT HOOK
+
+Op-Code: PXENV_FILE_EXIT_HOOK (00e7h)
+
+Input: Far pointer to a t_PXENV_FILE_EXIT_HOOK parameter
+ structure that has been initialized by the caller.
+
+Output: PXENV_EXIT_SUCCESS or PXENV_EXIT_FAILURE must be
+ returned in AX. The Status field in the parameter
+ structure must be set to one of the values represented
+ by the PXENV_STATUS_xxx constants.
+
+Description: Modify the exit path to jump to the specified code.
+ Only valid for pxeprefix-based builds.
+
+typedef struct s_PXENV_FILE_EXIT_HOOK {
+ PXENV_STATUS_t Status;
+ SEGOFF16_t Hook;
+} t_PXENV_FILE_EXIT_HOOK;
+
+
+Set before calling API service:
+
+Hook: The SEG16:OFF16 of the code to jump to.
+
+
+Returned from API service:
+
+Status: See PXENV_STATUS_xxx constants.
diff --git a/gpxe/src/doxygen.cfg b/gpxe/src/doxygen.cfg
index 5c429094..0ee87ad9 100644
--- a/gpxe/src/doxygen.cfg
+++ b/gpxe/src/doxygen.cfg
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.4
+# Doxyfile 1.5.7.1
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
@@ -14,10 +14,18 @@
# Project related configuration options
#---------------------------------------------------------------------------
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
-PROJECT_NAME = Etherboot
+PROJECT_NAME = gPXE
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
@@ -45,24 +53,15 @@ CREATE_SUBDIRS = NO
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
-# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
-# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
-# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
-# Swedish, and Ukrainian.
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene,
+# Spanish, Swedish, and Ukrainian.
OUTPUT_LANGUAGE = English
-# This tag can be used to specify the encoding used in the generated output.
-# The encoding is not always determined by the language that is chosen,
-# but also whether or not the output is meant for Windows or non-Windows users.
-# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
-# forces the Windows encoding (this is the default for the Windows binary),
-# whereas setting the tag to NO uses a Unix-style encoding (the default for
-# all platforms other than Windows).
-
-USE_WINDOWS_ENCODING = NO
-
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
# the file and class documentation (similar to JavaDoc).
@@ -93,7 +92,7 @@ ABBREVIATE_BRIEF =
# Doxygen will generate a detailed section even if there is only a brief
# description.
-ALWAYS_DETAILED_SEC = NO
+ALWAYS_DETAILED_SEC = YES
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
@@ -106,7 +105,7 @@ INLINE_INHERITED_MEMB = NO
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
-FULL_PATH_NAMES = NO
+FULL_PATH_NAMES = YES
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user-defined part of the path. Stripping is
@@ -135,11 +134,19 @@ SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like the Qt-style comments (thus requiring an
-# explicit @brief command for a brief description.
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
JAVADOC_AUTOBRIEF = YES
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
# treat a multi-line C++ special comment block (i.e. a block of //! or ///
# comments) as a brief description. This used to be the default behaviour.
@@ -148,26 +155,12 @@ JAVADOC_AUTOBRIEF = YES
MULTILINE_CPP_IS_BRIEF = NO
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member
-# documentation.
-
-DETAILS_AT_TOP = YES
-
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# re-implements.
INHERIT_DOCS = YES
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC = NO
-
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
# a new page for each member. If set to NO, the documentation of a member will
# be part of the file/class/namespace that contains it.
@@ -197,13 +190,61 @@ ALIASES = v=@param \
OPTIMIZE_OUTPUT_FOR_C = YES
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
-# only. Doxygen will then generate output that is more tailored for Java.
-# For instance, namespaces will be presented as packages, qualified scopes
-# will look different, etc.
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
OPTIMIZE_OUTPUT_JAVA = NO
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = YES
+
# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
# the same type (for instance a group of public functions) to be put as a
# subgroup of that type (e.g. under the Public Functions section). Set it to
@@ -212,6 +253,32 @@ OPTIMIZE_OUTPUT_JAVA = NO
SUBGROUPING = YES
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
@@ -221,7 +288,7 @@ SUBGROUPING = YES
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-EXTRACT_ALL = NO
+EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
@@ -246,6 +313,14 @@ EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
@@ -300,7 +375,7 @@ HIDE_SCOPE_NAMES = NO
# will put a list of the files that are included by a file in the documentation
# of that file.
-SHOW_INCLUDE_FILES = NO
+SHOW_INCLUDE_FILES = YES
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
@@ -321,6 +396,12 @@ SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
# sorted by fully-qualified names, including namespaces. If set to
# NO (the default), the class list will be sorted only by class name,
@@ -378,20 +459,41 @@ SHOW_USED_FILES = YES
# If the sources in your project are distributed over multiple directories
# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is YES.
+# in the documentation. The default is NO.
SHOW_DIRECTORIES = YES
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from the
-# version control system). Doxygen will invoke the program by executing (via
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command <command> <input-file>, where <command> is the value of
# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the progam writes to standard output
+# provided by doxygen. Whatever the program writes to standard output
# is used as the file version. See the manual for examples.
FILE_VERSION_FILTER =
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE =
+
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
@@ -426,7 +528,7 @@ WARN_IF_DOC_ERROR = YES
# wrong or incomplete parameter documentation, but not about the absence of
# documentation.
-WARN_NO_PARAMDOC = NO
+WARN_NO_PARAMDOC = YES
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
@@ -453,28 +555,34 @@ WARN_LOGFILE =
# with spaces.
INPUT = @SRCDIRS@ \
- include \
- include/gpxe \
- arch/@ARCH@/include \
+ @INCDIRS@ \
+ config \
doc
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank the following patterns are tested:
# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
FILE_PATTERNS = *.c \
*.h \
- *.S \
*.dox
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
-RECURSIVE = NO
+RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should
# excluded from the INPUT source files. This way you can easily exclude a
@@ -496,6 +604,14 @@ EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
@@ -561,7 +677,7 @@ SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
-INLINE_SOURCES = NO
+INLINE_SOURCES = YES
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
@@ -569,17 +685,24 @@ INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = NO
-# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# If the REFERENCED_BY_RELATION tag is set to YES
# then for each documented function all documented
# functions referencing it will be listed.
REFERENCED_BY_RELATION = YES
-# If the REFERENCES_RELATION tag is set to YES (the default)
+# If the REFERENCES_RELATION tag is set to YES
# then for each documented function all documented entities
# called/used by that function will be listed.
-REFERENCES_RELATION = NO
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
# If the USE_HTAGS tag is set to YES then the references to source code
# will point to the HTML generated by the htags(1) tool instead of doxygen
@@ -666,9 +789,43 @@ HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
# of the generated HTML documentation.
GENERATE_HTMLHELP = NO
@@ -693,6 +850,12 @@ HHC_LOCATION =
GENERATE_CHI = NO
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
# controls whether a binary table of contents is generated (YES) or a
# normal table of contents (NO) in the .chm file.
@@ -702,7 +865,39 @@ BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members
# to the contents of the HTML help documentation and to the tree view.
-TOC_EXPAND = NO
+TOC_EXPAND = YES
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#namespace">Qt Help Project / Namespace</a>.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#virtual-folders">Qt Help Project / Virtual Folders</a>.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file .
+
+QHG_LOCATION =
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
# top of each HTML page. The value NO (the default) enables the index and
@@ -715,14 +910,22 @@ DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
-# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one that
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
-# probably better off using the HTML help feature.
+# probably better off using the HTML help feature. Other possible values
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
-GENERATE_TREEVIEW = NO
+GENERATE_TREEVIEW = NONE