aboutsummaryrefslogtreecommitdiffstats
path: root/gpxe
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-02-17 20:17:17 -0800
committerH. Peter Anvin <hpa@zytor.com>2009-02-17 20:17:17 -0800
commitd0c6656a62113b913948361779d6298fe76f6e61 (patch)
treeefa2541a1abae4760717c6db421ea818114ab6f7 /gpxe
parent85b92a462dab7ce36c48614ea18314f8fc83ca9c (diff)
downloadlwip-d0c6656a62113b913948361779d6298fe76f6e61.tar.gz
lwip-d0c6656a62113b913948361779d6298fe76f6e61.tar.xz
lwip-d0c6656a62113b913948361779d6298fe76f6e61.zip
Update gPXE to version 0.9.6+ 277b84c6e7d49f3cf01c855007f591de8c7cb75f
Update gPXE to version 0.9.6+, from commit 277b84c6e7d49f3cf01c855007f591de8c7cb75f in the main gPXE repository. The only differences is src/config/general.h which has a few protocols added, and src/arch/i386/prefix/boot1a.S which was called boot1a.s in the upstream repository.
Diffstat (limited to 'gpxe')
-rw-r--r--gpxe/.gitignore1
-rw-r--r--gpxe/Makefile9
-rw-r--r--gpxe/VERSION2
-rw-r--r--gpxe/pxelinux.gpxe4
-rw-r--r--gpxe/src/Makefile193
-rw-r--r--gpxe/src/Makefile.housekeeping489
-rw-r--r--gpxe/src/arch/i386/Config148
-rw-r--r--gpxe/src/arch/i386/Makefile140
-rw-r--r--gpxe/src/arch/i386/Makefile.efi10
-rw-r--r--gpxe/src/arch/i386/Makefile.pcbios55
-rw-r--r--gpxe/src/arch/i386/core/dumpregs.c6
-rw-r--r--gpxe/src/arch/i386/core/gdbidt.S8
-rw-r--r--gpxe/src/arch/i386/core/gdbmach.c4
-rw-r--r--gpxe/src/arch/i386/core/nap.c12
-rw-r--r--gpxe/src/arch/i386/core/pic8259.c1
-rw-r--r--gpxe/src/arch/i386/core/rdtsc_timer.c87
-rw-r--r--gpxe/src/arch/i386/core/relocate.c12
-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/start32.S325
-rw-r--r--gpxe/src/arch/i386/core/timer2.c (renamed from gpxe/src/arch/i386/core/i386_timer.c)24
-rw-r--r--gpxe/src/arch/i386/core/video_subr.c2
-rw-r--r--gpxe/src/arch/i386/core/virtaddr.S2
-rw-r--r--gpxe/src/arch/i386/core/x86_io.c94
-rw-r--r--gpxe/src/arch/i386/drivers/net/undiisr.S6
-rw-r--r--gpxe/src/arch/i386/drivers/net/undinet.c71
-rw-r--r--gpxe/src/arch/i386/drivers/net/undionly.c18
-rw-r--r--gpxe/src/arch/i386/drivers/net/undirom.c4
-rw-r--r--gpxe/src/arch/i386/drivers/timer_bios.c57
-rw-r--r--gpxe/src/arch/i386/drivers/timer_rdtsc.c69
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/bios_console.c4
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/e820mangler.S51
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/gateA20.c13
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/hidemem.c32
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/memmap.c29
-rw-r--r--gpxe/src/arch/i386/image/bzimage.c2
-rw-r--r--gpxe/src/arch/i386/image/com32.c44
-rw-r--r--gpxe/src/arch/i386/image/comboot.c44
-rw-r--r--gpxe/src/arch/i386/image/multiboot.c12
-rw-r--r--gpxe/src/arch/i386/image/nbi.c18
-rw-r--r--gpxe/src/arch/i386/image/pxe_image.c14
-rw-r--r--gpxe/src/arch/i386/include/bios.h3
-rw-r--r--gpxe/src/arch/i386/include/biosint.h15
-rw-r--r--gpxe/src/arch/i386/include/bits/byteswap.h45
-rw-r--r--gpxe/src/arch/i386/include/bits/compiler.h25
-rw-r--r--gpxe/src/arch/i386/include/bits/elf.h91
-rw-r--r--gpxe/src/arch/i386/include/bits/elf_x.h5
-rw-r--r--gpxe/src/arch/i386/include/bits/errfile.h6
-rw-r--r--gpxe/src/arch/i386/include/bits/io.h12
-rw-r--r--gpxe/src/arch/i386/include/bits/nap.h13
-rw-r--r--gpxe/src/arch/i386/include/bits/smbios.h12
-rw-r--r--gpxe/src/arch/i386/include/bits/stdint.h8
-rw-r--r--gpxe/src/arch/i386/include/bits/timer.h13
-rw-r--r--gpxe/src/arch/i386/include/bits/timer2.h8
-rw-r--r--gpxe/src/arch/i386/include/bits/uaccess.h8
-rw-r--r--gpxe/src/arch/i386/include/bits/umalloc.h12
-rw-r--r--gpxe/src/arch/i386/include/comboot.h51
-rw-r--r--gpxe/src/arch/i386/include/gdbmach.h2
-rw-r--r--gpxe/src/arch/i386/include/gpxe/abft.h (renamed from gpxe/src/include/gpxe/abft.h)0
-rw-r--r--gpxe/src/arch/i386/include/gpxe/bios_nap.h16
-rw-r--r--gpxe/src/arch/i386/include/gpxe/bios_smbios.h16
-rw-r--r--gpxe/src/arch/i386/include/gpxe/bios_timer.h42
-rw-r--r--gpxe/src/arch/i386/include/gpxe/ibft.h (renamed from gpxe/src/include/gpxe/ibft.h)0
-rw-r--r--gpxe/src/arch/i386/include/gpxe/memtop_umalloc.h16
-rw-r--r--gpxe/src/arch/i386/include/gpxe/rdtsc_timer.h37
-rw-r--r--gpxe/src/arch/i386/include/gpxe/timer2.h12
-rw-r--r--gpxe/src/arch/i386/include/gpxe/x86_io.h151
-rw-r--r--gpxe/src/arch/i386/include/int13.h1
-rw-r--r--gpxe/src/arch/i386/include/io.h265
-rwxr-xr-x[-rw-r--r--]gpxe/src/arch/i386/include/librm.h303
-rw-r--r--gpxe/src/arch/i386/include/pci_io.h35
-rw-r--r--gpxe/src/arch/i386/include/pxe.h (renamed from gpxe/src/include/pxe.h)0
-rw-r--r--gpxe/src/arch/i386/include/pxe_addr.h17
-rw-r--r--gpxe/src/arch/i386/include/pxe_api.h (renamed from gpxe/src/include/pxe_api.h)0
-rw-r--r--gpxe/src/arch/i386/include/pxe_call.h2
-rw-r--r--gpxe/src/arch/i386/include/pxe_types.h (renamed from gpxe/src/include/pxe_types.h)5
-rw-r--r--gpxe/src/arch/i386/include/realmode.h93
-rw-r--r--gpxe/src/arch/i386/include/registers.h13
-rw-r--r--gpxe/src/arch/i386/include/setjmp.h36
-rw-r--r--gpxe/src/arch/i386/include/smbios.h60
-rw-r--r--gpxe/src/arch/i386/include/undi.h10
-rw-r--r--gpxe/src/arch/i386/include/virtaddr.h105
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/abft.c (renamed from gpxe/src/core/abft.c)0
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/aoeboot.c (renamed from gpxe/src/usr/aoeboot.c)27
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/bios_nap.c14
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/bios_smbios.c84
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/bios_timer.c63
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/biosint.c11
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/ibft.c (renamed from gpxe/src/core/ibft.c)0
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/int13.c14
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/iscsiboot.c (renamed from gpxe/src/usr/iscsiboot.c)27
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c (renamed from gpxe/src/arch/i386/core/umalloc.c)34
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/pcibios.c (renamed from gpxe/src/arch/i386/core/pcibios.c)11
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_call.c4
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_entry.S33
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_errors.c (renamed from gpxe/src/interface/pxe/pxe_errors.c)0
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_file.c (renamed from gpxe/src/interface/pxe/pxe_file.c)0
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_loader.c (renamed from gpxe/src/interface/pxe/pxe_loader.c)0
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_preboot.c (renamed from gpxe/src/interface/pxe/pxe_preboot.c)2
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_tftp.c (renamed from gpxe/src/interface/pxe/pxe_tftp.c)13
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_udp.c (renamed from gpxe/src/interface/pxe/pxe_udp.c)0
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_undi.c (renamed from gpxe/src/interface/pxe/pxe_undi.c)30
-rw-r--r--gpxe/src/arch/i386/interface/syslinux/com32_call.c6
-rw-r--r--gpxe/src/arch/i386/interface/syslinux/comboot_call.c229
-rw-r--r--gpxe/src/arch/i386/prefix/boot1a.S410
-rw-r--r--gpxe/src/arch/i386/prefix/dskprefix.S10
-rw-r--r--gpxe/src/arch/i386/prefix/hdprefix.S10
-rw-r--r--gpxe/src/arch/i386/prefix/kkpxeprefix.S8
-rw-r--r--gpxe/src/arch/i386/prefix/libprefix.S200
-rw-r--r--gpxe/src/arch/i386/prefix/lkrnprefix.S10
-rw-r--r--gpxe/src/arch/i386/prefix/nbiprefix.S17
-rw-r--r--gpxe/src/arch/i386/prefix/pxeprefix.S171
-rw-r--r--gpxe/src/arch/i386/prefix/romprefix.S186
-rw-r--r--gpxe/src/arch/i386/scripts/i386.lds279
-rwxr-xr-x[-rw-r--r--]gpxe/src/arch/i386/transitions/librm.S53
-rwxr-xr-x[-rw-r--r--]gpxe/src/arch/i386/transitions/librm_mgmt.c101
-rw-r--r--gpxe/src/arch/x86/Makefile9
-rw-r--r--gpxe/src/arch/x86/Makefile.efi28
-rw-r--r--gpxe/src/arch/x86/core/pcidirect.c (renamed from gpxe/src/arch/i386/core/pcidirect.c)9
-rw-r--r--gpxe/src/arch/x86/core/x86_string.c (renamed from gpxe/src/arch/i386/core/i386_string.c)4
-rw-r--r--gpxe/src/arch/x86/include/bits/pci_io.h13
-rw-r--r--gpxe/src/arch/x86/include/bits/string.h (renamed from gpxe/src/arch/i386/include/bits/string.h)4
-rw-r--r--gpxe/src/arch/x86/include/gpxe/efi/efix86_nap.h16
-rw-r--r--gpxe/src/arch/x86/include/gpxe/pcibios.h (renamed from gpxe/src/arch/i386/include/pcibios.h)55
-rw-r--r--gpxe/src/arch/x86/include/gpxe/pcidirect.h (renamed from gpxe/src/arch/i386/include/pcidirect.h)53
-rw-r--r--gpxe/src/arch/x86/interface/efi/efix86_nap.c46
-rw-r--r--gpxe/src/arch/x86/prefix/efidrvprefix.c44
-rw-r--r--gpxe/src/arch/x86/prefix/efiprefix.c39
-rw-r--r--gpxe/src/arch/x86/scripts/efi.lds105
-rw-r--r--gpxe/src/arch/x86_64/Makefile41
-rw-r--r--gpxe/src/arch/x86_64/Makefile.efi14
-rw-r--r--gpxe/src/arch/x86_64/include/bits/byteswap.h22
-rw-r--r--gpxe/src/arch/x86_64/include/bits/compiler.h14
-rw-r--r--gpxe/src/arch/x86_64/include/bits/endian.h6
-rw-r--r--gpxe/src/arch/x86_64/include/bits/errfile.h11
-rw-r--r--gpxe/src/arch/x86_64/include/bits/io.h10
-rw-r--r--gpxe/src/arch/x86_64/include/bits/nap.h12
-rw-r--r--gpxe/src/arch/x86_64/include/bits/smbios.h10
-rw-r--r--gpxe/src/arch/x86_64/include/bits/stdint.h21
-rw-r--r--gpxe/src/arch/x86_64/include/bits/timer.h10
-rw-r--r--gpxe/src/arch/x86_64/include/bits/uaccess.h10
-rw-r--r--gpxe/src/arch/x86_64/include/bits/umalloc.h10
-rw-r--r--gpxe/src/arch/x86_64/include/gdbmach.h51
-rw-r--r--gpxe/src/arch/x86_64/include/limits.h59
-rw-r--r--gpxe/src/config.h175
-rw-r--r--gpxe/src/config/.gitignore1
-rw-r--r--gpxe/src/config/console.h21
-rw-r--r--gpxe/src/config/defaults.h8
-rw-r--r--gpxe/src/config/defaults/efi.h21
-rw-r--r--gpxe/src/config/defaults/pcbios.h29
-rw-r--r--gpxe/src/config/general.h123
-rw-r--r--gpxe/src/config/ioapi.h15
-rw-r--r--gpxe/src/config/isa.h15
-rw-r--r--gpxe/src/config/nap.h15
-rw-r--r--gpxe/src/config/serial.h28
-rw-r--r--gpxe/src/config/timer.h15
-rw-r--r--gpxe/src/config/umalloc.h12
-rw-r--r--gpxe/src/core/base64.c66
-rw-r--r--gpxe/src/core/config.c44
-rw-r--r--gpxe/src/core/console.c6
-rw-r--r--gpxe/src/core/cwuri.c5
-rw-r--r--gpxe/src/core/debug.c6
-rw-r--r--gpxe/src/core/gdbudp.c2
-rw-r--r--gpxe/src/core/getkey.c14
-rw-r--r--gpxe/src/core/image.c29
-rw-r--r--gpxe/src/core/main.c36
-rw-r--r--gpxe/src/core/malloc.c2
-rw-r--r--gpxe/src/core/monojob.c7
-rw-r--r--gpxe/src/core/null_nap.c3
-rw-r--r--gpxe/src/core/nvo.c2
-rw-r--r--gpxe/src/core/pc_kbd.c2
-rw-r--r--gpxe/src/core/process.c2
-rw-r--r--gpxe/src/core/serial.c2
-rw-r--r--gpxe/src/core/settings.c68
-rw-r--r--gpxe/src/core/timer.c91
-rw-r--r--gpxe/src/core/uri.c8
-rw-r--r--gpxe/src/core/uuid.c2
-rw-r--r--gpxe/src/core/xfer.c11
-rw-r--r--gpxe/src/crypto/asn1.c31
-rw-r--r--gpxe/src/crypto/axtls/axtls_asn1.c867
-rw-r--r--gpxe/src/crypto/cryptoLayer.h120
-rw-r--r--gpxe/src/crypto/framework.c86
-rw-r--r--gpxe/src/crypto/matrixssl/mpi.h487
-rw-r--r--gpxe/src/crypto/matrixssl/pscrypto.h661
-rw-r--r--gpxe/src/crypto/ssl.c136
-rw-r--r--gpxe/src/crypto/ssl.h19
-rw-r--r--gpxe/src/crypto/ssl_constructs.h342
-rw-r--r--gpxe/src/crypto/x509.c181
-rw-r--r--gpxe/src/dl360.gpxe4
-rw-r--r--gpxe/src/drivers/bitbash/i2c_bit.c147
-rw-r--r--gpxe/src/drivers/block/ata.c8
-rw-r--r--gpxe/src/drivers/block/ramdisk.c8
-rw-r--r--gpxe/src/drivers/block/scsi.c40
-rw-r--r--gpxe/src/drivers/bus/eisa.c2
-rw-r--r--gpxe/src/drivers/bus/isa.c6
-rw-r--r--gpxe/src/drivers/bus/isapnp.c4
-rw-r--r--gpxe/src/drivers/bus/mca.c2
-rw-r--r--gpxe/src/drivers/bus/pci.c5
-rw-r--r--gpxe/src/drivers/bus/virtio-pci.c64
-rw-r--r--gpxe/src/drivers/bus/virtio-ring.c134
-rw-r--r--gpxe/src/drivers/infiniband/arbel.c171
-rw-r--r--gpxe/src/drivers/infiniband/hermon.c172
-rw-r--r--gpxe/src/drivers/infiniband/ib_packet.c234
-rw-r--r--gpxe/src/drivers/infiniband/ib_sma.c553
-rw-r--r--gpxe/src/drivers/infiniband/ib_smc.c166
-rw-r--r--gpxe/src/drivers/infiniband/linda.c2397
-rw-r--r--gpxe/src/drivers/infiniband/linda.h271
-rw-r--r--gpxe/src/drivers/infiniband/linda_fw.c1067
-rw-r--r--gpxe/src/drivers/infiniband/qib_7220_regs.h1763
-rw-r--r--gpxe/src/drivers/infiniband/qib_genbits.pl95
-rw-r--r--gpxe/src/drivers/net/3c509.c2
-rw-r--r--gpxe/src/drivers/net/3c515.c2
-rw-r--r--gpxe/src/drivers/net/3c595.c2
-rw-r--r--gpxe/src/drivers/net/3c90x.c4
-rw-r--r--gpxe/src/drivers/net/b44.c949
-rw-r--r--gpxe/src/drivers/net/b44.h467
-rw-r--r--gpxe/src/drivers/net/cs89x0.c4
-rw-r--r--gpxe/src/drivers/net/davicom.c4
-rw-r--r--gpxe/src/drivers/net/dmfe.c20
-rw-r--r--gpxe/src/drivers/net/e1000/e1000.c34
-rw-r--r--gpxe/src/drivers/net/e1000/e1000.h3
-rw-r--r--gpxe/src/drivers/net/e1000/e1000_hw.c14
-rw-r--r--gpxe/src/drivers/net/e1000/e1000_osdep.h50
-rw-r--r--gpxe/src/drivers/net/eepro100.c8
-rw-r--r--gpxe/src/drivers/net/epic100.c4
-rw-r--r--gpxe/src/drivers/net/etherfabric.c5486
-rw-r--r--gpxe/src/drivers/net/etherfabric_nic.h201
-rw-r--r--gpxe/src/drivers/net/forcedeth.c2
-rw-r--r--gpxe/src/drivers/net/ipoib.c579
-rw-r--r--[-rwxr-xr-x]gpxe/src/drivers/net/mtnic.c1038
-rw-r--r--[-rwxr-xr-x]gpxe/src/drivers/net/mtnic.h283
-rw-r--r--gpxe/src/drivers/net/natsemi.c11
-rw-r--r--gpxe/src/drivers/net/ne2k_isa.c373
-rw-r--r--gpxe/src/drivers/net/phantom/phantom.c1517
-rw-r--r--gpxe/src/drivers/net/phantom/phantom.h155
-rw-r--r--gpxe/src/drivers/net/pnic.c2
-rw-r--r--gpxe/src/drivers/net/prism2.c2
-rw-r--r--gpxe/src/drivers/net/prism2_pci.c9
-rw-r--r--gpxe/src/drivers/net/prism2_plx.c5
-rw-r--r--gpxe/src/drivers/net/r8169.c3099
-rw-r--r--gpxe/src/drivers/net/r8169.h566
-rw-r--r--gpxe/src/drivers/net/rtl8139.c3
-rw-r--r--gpxe/src/drivers/net/sis900.c8
-rw-r--r--gpxe/src/drivers/net/sundance.c5
-rw-r--r--gpxe/src/drivers/net/tg3.c5
-rw-r--r--gpxe/src/drivers/net/tulip.c4
-rw-r--r--gpxe/src/drivers/net/via-rhine.c48
-rw-r--r--gpxe/src/drivers/net/via-velocity.c4
-rw-r--r--gpxe/src/drivers/net/virtio-net.c289
-rw-r--r--gpxe/src/drivers/net/w89c840.c4
-rw-r--r--gpxe/src/hci/commands/config_cmd.c2
-rw-r--r--gpxe/src/hci/commands/dhcp_cmd.c90
-rw-r--r--gpxe/src/hci/commands/login_cmd.c27
-rw-r--r--gpxe/src/hci/mucurses/ansi_screen.c2
-rw-r--r--gpxe/src/hci/mucurses/widgets/editbox.c11
-rw-r--r--gpxe/src/hci/mucurses/wininit.c4
-rw-r--r--gpxe/src/hci/tui/login_ui.c135
-rw-r--r--gpxe/src/hci/tui/settings_ui.c2
-rw-r--r--gpxe/src/image/default.gpxe2
-rw-r--r--gpxe/src/image/efi_image.c106
-rw-r--r--gpxe/src/image/elf.c2
-rw-r--r--gpxe/src/image/embed.S7
-rw-r--r--gpxe/src/image/embedded.c109
-rw-r--r--gpxe/src/image/script.c11
-rw-r--r--gpxe/src/include/byteswap.h35
-rw-r--r--gpxe/src/include/compiler.h38
-rw-r--r--gpxe/src/include/elf.h4
-rw-r--r--gpxe/src/include/gpxe/aoe.h33
-rw-r--r--gpxe/src/include/gpxe/api.h82
-rw-r--r--gpxe/src/include/gpxe/asn1.h6
-rw-r--r--gpxe/src/include/gpxe/base64.h24
-rw-r--r--gpxe/src/include/gpxe/bitops.h227
-rw-r--r--gpxe/src/include/gpxe/blockdev.h20
-rw-r--r--gpxe/src/include/gpxe/dhcp.h147
-rw-r--r--gpxe/src/include/gpxe/dhcppkt.h31
-rw-r--r--gpxe/src/include/gpxe/editbox.h12
-rw-r--r--gpxe/src/include/gpxe/efi/Base.h329
-rw-r--r--gpxe/src/include/gpxe/efi/Guid/PcAnsi.h58
-rw-r--r--gpxe/src/include/gpxe/efi/Guid/SmBios.h34
-rw-r--r--gpxe/src/include/gpxe/efi/Ia32/ProcessorBind.h215
-rw-r--r--gpxe/src/include/gpxe/efi/IndustryStandard/Pci22.h601
-rw-r--r--gpxe/src/include/gpxe/efi/IndustryStandard/PeImage.h752
-rw-r--r--gpxe/src/include/gpxe/efi/LICENCE40
-rw-r--r--gpxe/src/include/gpxe/efi/Pi/PiBootMode.h43
-rw-r--r--gpxe/src/include/gpxe/efi/Pi/PiDependency.h47
-rw-r--r--gpxe/src/include/gpxe/efi/Pi/PiDxeCis.h642
-rw-r--r--gpxe/src/include/gpxe/efi/Pi/PiFirmwareFile.h242
-rw-r--r--gpxe/src/include/gpxe/efi/Pi/PiFirmwareVolume.h154
-rw-r--r--gpxe/src/include/gpxe/efi/Pi/PiHob.h295
-rw-r--r--gpxe/src/include/gpxe/efi/Pi/PiMultiPhase.h104
-rw-r--r--gpxe/src/include/gpxe/efi/PiDxe.h25
-rw-r--r--gpxe/src/include/gpxe/efi/ProcessorBind.h14
-rw-r--r--gpxe/src/include/gpxe/efi/Protocol/ComponentName2.h174
-rw-r--r--gpxe/src/include/gpxe/efi/Protocol/Cpu.h291
-rw-r--r--gpxe/src/include/gpxe/efi/Protocol/CpuIo.h128
-rw-r--r--gpxe/src/include/gpxe/efi/Protocol/DebugSupport.h634
-rw-r--r--gpxe/src/include/gpxe/efi/Protocol/DevicePath.h535
-rw-r--r--gpxe/src/include/gpxe/efi/Protocol/DriverBinding.h153
-rw-r--r--gpxe/src/include/gpxe/efi/Protocol/NetworkInterfaceIdentifier.h74
-rw-r--r--gpxe/src/include/gpxe/efi/Protocol/PciIo.h519
-rw-r--r--gpxe/src/include/gpxe/efi/Protocol/PciRootBridgeIo.h393
-rw-r--r--gpxe/src/include/gpxe/efi/Protocol/SimpleNetwork.h593
-rw-r--r--gpxe/src/include/gpxe/efi/Protocol/SimpleTextIn.h136
-rw-r--r--gpxe/src/include/gpxe/efi/Protocol/SimpleTextOut.h404
-rw-r--r--gpxe/src/include/gpxe/efi/Uefi.h27
-rw-r--r--gpxe/src/include/gpxe/efi/Uefi/UefiBaseType.h200
-rw-r--r--gpxe/src/include/gpxe/efi/Uefi/UefiGpt.h62
-rw-r--r--gpxe/src/include/gpxe/efi/Uefi/UefiInternalFormRepresentation.h1590
-rw-r--r--gpxe/src/include/gpxe/efi/Uefi/UefiMultiPhase.h210
-rw-r--r--gpxe/src/include/gpxe/efi/Uefi/UefiPxe.h1756
-rw-r--r--gpxe/src/include/gpxe/efi/Uefi/UefiSpec.h1916
-rw-r--r--gpxe/src/include/gpxe/efi/X64/ProcessorBind.h247
-rw-r--r--gpxe/src/include/gpxe/efi/efi.h131
-rw-r--r--gpxe/src/include/gpxe/efi/efi_io.h178
-rw-r--r--gpxe/src/include/gpxe/efi/efi_pci.h146
-rw-r--r--gpxe/src/include/gpxe/efi/efi_smbios.h16
-rw-r--r--gpxe/src/include/gpxe/efi/efi_timer.h16
-rw-r--r--gpxe/src/include/gpxe/efi/efi_uaccess.h88
-rw-r--r--gpxe/src/include/gpxe/efi/efi_umalloc.h16
-rwxr-xr-xgpxe/src/include/gpxe/efi/import.pl75
-rw-r--r--gpxe/src/include/gpxe/embedded.h9
-rw-r--r--gpxe/src/include/gpxe/errfile.h16
-rw-r--r--gpxe/src/include/gpxe/ethernet.h2
-rw-r--r--gpxe/src/include/gpxe/fakedhcp.h4
-rw-r--r--gpxe/src/include/gpxe/features.h24
-rw-r--r--gpxe/src/include/gpxe/i2c.h68
-rw-r--r--gpxe/src/include/gpxe/ib_mad.h364
-rw-r--r--gpxe/src/include/gpxe/ib_packet.h147
-rw-r--r--gpxe/src/include/gpxe/ib_sma.h63
-rw-r--r--gpxe/src/include/gpxe/ib_smc.h18
-rw-r--r--gpxe/src/include/gpxe/icmp.h23
-rw-r--r--gpxe/src/include/gpxe/image.h19
-rw-r--r--gpxe/src/include/gpxe/in.h4
-rw-r--r--gpxe/src/include/gpxe/infiniband.h540
-rw-r--r--gpxe/src/include/gpxe/init.h1
-rw-r--r--gpxe/src/include/gpxe/io.h504
-rw-r--r--gpxe/src/include/gpxe/iobuf.h38
-rw-r--r--gpxe/src/include/gpxe/ipoib.h47
-rw-r--r--gpxe/src/include/gpxe/keys.h29
-rw-r--r--gpxe/src/include/gpxe/login_ui.h12
-rw-r--r--gpxe/src/include/gpxe/nap.h54
-rw-r--r--gpxe/src/include/gpxe/netdevice.h83
-rw-r--r--gpxe/src/include/gpxe/null_nap.h21
-rw-r--r--gpxe/src/include/gpxe/open.h2
-rw-r--r--gpxe/src/include/gpxe/pci.h2
-rw-r--r--gpxe/src/include/gpxe/pci_io.h122
-rw-r--r--gpxe/src/include/gpxe/resolv.h2
-rw-r--r--gpxe/src/include/gpxe/retry.h9
-rw-r--r--gpxe/src/include/gpxe/rotate.h27
-rw-r--r--gpxe/src/include/gpxe/sanboot.h14
-rw-r--r--gpxe/src/include/gpxe/settings.h33
-rw-r--r--gpxe/src/include/gpxe/smbios.h140
-rw-r--r--gpxe/src/include/gpxe/socket.h14
-rw-r--r--gpxe/src/include/gpxe/tcpip.h7
-rw-r--r--gpxe/src/include/gpxe/timer.h95
-rw-r--r--gpxe/src/include/gpxe/tls.h26
-rw-r--r--gpxe/src/include/gpxe/uaccess.h317
-rw-r--r--gpxe/src/include/gpxe/udp.h1
-rw-r--r--gpxe/src/include/gpxe/umalloc.h55
-rw-r--r--gpxe/src/include/gpxe/uri.h1
-rw-r--r--gpxe/src/include/gpxe/virtio-pci.h (renamed from gpxe/src/drivers/net/virtio-pci.h)39
-rw-r--r--gpxe/src/include/gpxe/virtio-ring.h (renamed from gpxe/src/drivers/net/virtio-ring.h)59
-rw-r--r--gpxe/src/include/gpxe/x509.h39
-rw-r--r--gpxe/src/include/gpxe/xfer.h4
-rw-r--r--gpxe/src/include/nic.h1
-rw-r--r--gpxe/src/include/stddef.h6
-rw-r--r--gpxe/src/include/stdlib.h1
-rw-r--r--gpxe/src/include/unistd.h18
-rw-r--r--gpxe/src/include/usr/aoeboot.h6
-rw-r--r--gpxe/src/include/usr/autoboot.h6
-rw-r--r--gpxe/src/include/usr/dhcpmgmt.h3
-rw-r--r--gpxe/src/include/usr/iscsiboot.h6
-rw-r--r--gpxe/src/interface/efi/efi_console.c274
-rw-r--r--gpxe/src/interface/efi/efi_init.c122
-rw-r--r--gpxe/src/interface/efi/efi_io.c203
-rw-r--r--gpxe/src/interface/efi/efi_pci.c81
-rw-r--r--gpxe/src/interface/efi/efi_smbios.c62
-rw-r--r--gpxe/src/interface/efi/efi_snp.c1145
-rw-r--r--gpxe/src/interface/efi/efi_strerror.c43
-rw-r--r--gpxe/src/interface/efi/efi_timer.c116
-rw-r--r--gpxe/src/interface/efi/efi_uaccess.c37
-rw-r--r--gpxe/src/interface/efi/efi_umalloc.c96
-rw-r--r--gpxe/src/interface/smbios/smbios.c (renamed from gpxe/src/arch/i386/firmware/pcbios/smbios.c)120
-rw-r--r--gpxe/src/interface/smbios/smbios_settings.c (renamed from gpxe/src/arch/i386/firmware/pcbios/smbios_settings.c)25
-rw-r--r--gpxe/src/libgcc/__divdi3.c2
-rw-r--r--gpxe/src/libgcc/__moddi3.c2
-rw-r--r--gpxe/src/libgcc/__udivdi3.c2
-rw-r--r--gpxe/src/libgcc/__udivmoddi4.c2
-rw-r--r--gpxe/src/libgcc/__umoddi3.c2
-rw-r--r--gpxe/src/libgcc/libgcc.h24
-rw-r--r--gpxe/src/net/aoe.c209
-rw-r--r--gpxe/src/net/arp.c4
-rw-r--r--gpxe/src/net/dhcppkt.c78
-rw-r--r--gpxe/src/net/ethernet.c61
-rw-r--r--gpxe/src/net/fakedhcp.c43
-rw-r--r--gpxe/src/net/icmp.c101
-rw-r--r--gpxe/src/net/icmpv6.c2
-rw-r--r--gpxe/src/net/infiniband.c351
-rw-r--r--gpxe/src/net/ipv4.c27
-rw-r--r--gpxe/src/net/ipv6.c1
-rw-r--r--gpxe/src/net/netdevice.c88
-rw-r--r--gpxe/src/net/retry.c12
-rw-r--r--gpxe/src/net/tcp.c23
-rw-r--r--gpxe/src/net/tcp/ftp.c63
-rw-r--r--gpxe/src/net/tcp/http.c45
-rw-r--r--gpxe/src/net/tcp/iscsi.c2
-rw-r--r--gpxe/src/net/tcpip.c9
-rw-r--r--gpxe/src/net/tls.c214
-rw-r--r--gpxe/src/net/udp.c38
-rw-r--r--gpxe/src/net/udp/dhcp.c1431
-rw-r--r--gpxe/src/net/udp/dns.c76
-rw-r--r--gpxe/src/net/udp/slam.c4
-rw-r--r--gpxe/src/net/udp/tftp.c67
-rw-r--r--gpxe/src/netboot.gpxe4
-rw-r--r--gpxe/src/tests/gdbstub_test.S4
-rwxr-xr-x[-rw-r--r--]gpxe/src/tests/gdbstub_test.gdb0
-rw-r--r--gpxe/src/usr/autoboot.c72
-rw-r--r--gpxe/src/usr/dhcpmgmt.c11
-rw-r--r--gpxe/src/usr/ifmgmt.c34
-rw-r--r--gpxe/src/usr/imgmgmt.c13
-rw-r--r--gpxe/src/usr/pxemenu.c381
-rw-r--r--gpxe/src/util/.gitignore3
-rwxr-xr-xgpxe/src/util/disrom.pl47
-rw-r--r--gpxe/src/util/efirom.c280
-rw-r--r--gpxe/src/util/elf2efi.c803
-rwxr-xr-xgpxe/src/util/geniso2
-rwxr-xr-x[-rw-r--r--]gpxe/src/util/mergerom.pl0
-rwxr-xr-xgpxe/src/util/mkconfig.pl205
-rwxr-xr-xgpxe/src/util/sortobjdump.pl2
-rw-r--r--gpxe/src/util/zbin.c27
430 files changed, 45138 insertions, 13535 deletions
diff --git a/gpxe/.gitignore b/gpxe/.gitignore
new file mode 100644
index 00000000..0517ab74
--- /dev/null
+++ b/gpxe/.gitignore
@@ -0,0 +1 @@
+/contrib
diff --git a/gpxe/Makefile b/gpxe/Makefile
index c846e939..7a34f8a7 100644
--- a/gpxe/Makefile
+++ b/gpxe/Makefile
@@ -1,6 +1,6 @@
## -----------------------------------------------------------------------
##
-## Copyright 2008 H. Peter Anvin - All Rights Reserved
+## Copyright 2008-2009 H. Peter Anvin - All Rights Reserved
##
## 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
@@ -32,8 +32,9 @@ spotless: clean dist
installer:
-src/bin/undionly.kpxe: ../core/pxelinux.0
- $(MAKE) -C src EMBEDDED_IMAGE=../$< NO_WERROR=1 bin/undionly.kpxe
+src/bin/undionly.kkpxe: pxelinux.gpxe ../core/pxelinux.0
+ $(MAKE) -C src bin/undionly.kkpxe NO_WERROR=1 \
+ EMBEDDED_IMAGE=../pxelinux.gpxe,../../core/pxelinux.0
-gpxelinux.0: src/bin/undionly.kpxe
+gpxelinux.0: src/bin/undionly.kkpxe
cp -f $< $@
diff --git a/gpxe/VERSION b/gpxe/VERSION
index 010605b1..69b51101 100644
--- a/gpxe/VERSION
+++ b/gpxe/VERSION
@@ -1 +1 @@
-0.9.5 2008-10-01
+0.9.6+ 2008-11-23
diff --git a/gpxe/pxelinux.gpxe b/gpxe/pxelinux.gpxe
new file mode 100644
index 00000000..51fe222e
--- /dev/null
+++ b/gpxe/pxelinux.gpxe
@@ -0,0 +1,4 @@
+#!gpxe
+dhcp net0
+imgload pxelinux.0
+boot pxelinux.0
diff --git a/gpxe/src/Makefile b/gpxe/src/Makefile
index 6c42da6a..147f6997 100644
--- a/gpxe/src/Makefile
+++ b/gpxe/src/Makefile
@@ -1,19 +1,17 @@
-# Location to place generated files
+###############################################################################
#
-BIN := bin
-
-# Initialise variables that get added to throughout the various Makefiles
+# Initialise various variables
#
-MAKEDEPS := Makefile .toolcheck .echocheck
-SRCDIRS :=
-SRCS :=
-NON_AUTO_SRCS :=
-DRIVERS :=
-ROMS :=
-MEDIA :=
-NON_AUTO_MEDIA :=
-# Locations of utilities
+CLEANUP :=
+CFLAGS :=
+ASFLAGS :=
+LDFLAGS :=
+MAKEDEPS := Makefile
+
+###############################################################################
+#
+# Locations of tools
#
HOST_CC := gcc
RM := rm -f
@@ -35,109 +33,20 @@ NM := $(CROSS_COMPILE)nm
OBJDUMP := $(CROSS_COMPILE)objdump
PARSEROM := $(PERL) ./util/parserom.pl
MAKEROM := $(PERL) ./util/makerom.pl
-MKCONFIG := $(PERL) ./util/mkconfig.pl
SYMCHECK := $(PERL) ./util/symcheck.pl
SORTOBJDUMP := $(PERL) ./util/sortobjdump.pl
NRV2B := ./util/nrv2b
ZBIN := ./util/zbin
+ELF2EFI32 := ./util/elf2efi32
+ELF2EFI64 := ./util/elf2efi64
+EFIROM := ./util/efirom
DOXYGEN := doxygen
-# If invoked with no build target, print out a helpfully suggestive
-# message.
-#
-noargs : blib $(BIN)/NIC $(BIN)/gpxe.dsk $(BIN)/gpxe.iso $(BIN)/gpxe.usb $(BIN)/undionly.kpxe
- @$(ECHO) '==========================================================='
- @$(ECHO)
- @$(ECHO) 'To create a bootable floppy, type'
- @$(ECHO) ' cat $(BIN)/gpxe.dsk > /dev/fd0'
- @$(ECHO) 'where /dev/fd0 is your floppy drive. This will erase any'
- @$(ECHO) 'data already on the disk.'
- @$(ECHO)
- @$(ECHO) 'To create a bootable USB key, type'
- @$(ECHO) ' cat $(BIN)/gpxe.usb > /dev/sdX'
- @$(ECHO) 'where /dev/sdX is your USB key, and is *not* a real hard'
- @$(ECHO) 'disk on your system. This will erase any data already on'
- @$(ECHO) 'the USB key.'
- @$(ECHO)
- @$(ECHO) 'To create a bootable CD-ROM, burn the ISO image '
- @$(ECHO) '$(BIN)/gpxe.iso to a blank CD-ROM.'
- @$(ECHO)
- @$(ECHO) 'These images contain drivers for all supported cards. You'
- @$(ECHO) 'can build more customised images, and ROM images, using'
- @$(ECHO) ' make bin/<rom-name>.<output-format>'
- @$(ECHO)
- @$(ECHO) '==========================================================='
-
-# If no architecture is specified in Config or on the command-line,
-# use that of the build machine.
-#
-ARCH := $(shell uname -m | sed -e 's,i[3456789]86,i386,')
-
-# handle x86_64 like i386, but set -m32 option for 32bit code only
-ifeq ($(ARCH),x86_64)
-ARCH := i386
-CFLAGS += -m32
-ASFLAGS += --32
-LDFLAGS += -m elf_i386
-endif
-
-# Drag in architecture-specific Config
-#
-MAKEDEPS += arch/$(ARCH)/Config
-include arch/$(ARCH)/Config
-
-# Common flags
-#
-CFLAGS += -I include -I arch/$(ARCH)/include -I . -DARCH=$(ARCH)
-CFLAGS += -Os -ffreestanding
-CFLAGS += -Wall -W
-CFLAGS += -g
-CFLAGS += $(EXTRA_CFLAGS)
-ASFLAGS += $(EXTRA_ASFLAGS)
-LDFLAGS += $(EXTRA_LDFLAGS)
-
-# Embedded image, if present
+###############################################################################
#
-EMBEDDED_IMAGE = /dev/null
-
-ifneq ($(NO_WERROR),1)
-CFLAGS += -Werror
-endif
-
-# CFLAGS for specific object types
-#
-CFLAGS_c +=
-CFLAGS_S += -DASSEMBLY
-
-# Base object name of the current target
-#
-OBJECT = $(firstword $(subst ., ,$(@F)))
-
-# CFLAGS for specific object files. You can define
-# e.g. CFLAGS_rtl8139, and have those flags automatically used when
-# compiling bin/rtl8139.o.
-#
-OBJ_CFLAGS = $(CFLAGS_$(OBJECT)) -DOBJECT=$(subst -,_,$(OBJECT))
-$(BIN)/%.flags :
- @$(ECHO) $(OBJ_CFLAGS)
-
-# 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_to_c = $(Q)$(COMPILE_c) -E -c $< > $@
-RULE_c_to_s = $(Q)$(COMPILE_c) -S -g0 -c $< -o $@
-
-PREPROCESS_S = $(CPP) $(CFLAGS) $(CFLAGS_S) $(OBJ_CFLAGS)
-ASSEMBLE_S = $(AS) $(ASFLAGS)
-RULE_S = $(Q)$(PREPROCESS_S) $< | $(ASSEMBLE_S) -o $@
-RULE_S_to_s = $(Q)$(PREPROCESS_S) $< > $@
-
-DEBUG_TARGETS += dbg%.o c s
-
# SRCDIRS lists all directories containing source files.
#
+SRCDIRS :=
SRCDIRS += libgcc
SRCDIRS += core
SRCDIRS += proto
@@ -151,7 +60,7 @@ SRCDIRS += drivers/block
SRCDIRS += drivers/nvs
SRCDIRS += drivers/bitbash
SRCDIRS += drivers/infiniband
-SRCDIRS += interface/pxe
+SRCDIRS += interface/pxe interface/efi interface/smbios
SRCDIRS += tests
SRCDIRS += crypto crypto/axtls crypto/matrixssl
SRCDIRS += hci hci/commands hci/tui
@@ -161,25 +70,69 @@ SRCDIRS += usr
# NON_AUTO_SRCS lists files that are excluded from the normal
# automatic build system.
#
-NON_AUTO_SRCS += core/elf_loader.c
+NON_AUTO_SRCS :=
NON_AUTO_SRCS += drivers/net/prism2.c
-# Rules for finalising files. TGT_MAKEROM_FLAGS is defined as part of
-# the automatic build system and varies by target; it includes the
-# "-p 0x1234,0x5678" string to set the PCI IDs.
+###############################################################################
+#
+# Default build target: build the most common targets and print out a
+# helpfully suggestive message
#
-FINALISE_rom = $(MAKEROM) $(MAKEROM_FLAGS) $(TGT_MAKEROM_FLAGS) \
- -i$(IDENT) -s 0 $@
+all : bin/blib.a bin/gpxe.dsk bin/gpxe.iso bin/gpxe.usb bin/undionly.kpxe
+ @$(ECHO) '==========================================================='
+ @$(ECHO)
+ @$(ECHO) 'To create a bootable floppy, type'
+ @$(ECHO) ' cat bin/gpxe.dsk > /dev/fd0'
+ @$(ECHO) 'where /dev/fd0 is your floppy drive. This will erase any'
+ @$(ECHO) 'data already on the disk.'
+ @$(ECHO)
+ @$(ECHO) 'To create a bootable USB key, type'
+ @$(ECHO) ' cat bin/gpxe.usb > /dev/sdX'
+ @$(ECHO) 'where /dev/sdX is your USB key, and is *not* a real hard'
+ @$(ECHO) 'disk on your system. This will erase any data already on'
+ @$(ECHO) 'the USB key.'
+ @$(ECHO)
+ @$(ECHO) 'To create a bootable CD-ROM, burn the ISO image '
+ @$(ECHO) 'bin/gpxe.iso to a blank CD-ROM.'
+ @$(ECHO)
+ @$(ECHO) 'These images contain drivers for all supported cards. You'
+ @$(ECHO) 'can build more customised images, and ROM images, using'
+ @$(ECHO) ' make bin/<rom-name>.<output-format>'
+ @$(ECHO)
+ @$(ECHO) '==========================================================='
+
+###############################################################################
+#
+# Build targets that do nothing but might be tried by users
+#
+configure :
+ @$(ECHO) "No configuration needed."
+
+install :
+ @$(ECHO) "No installation required."
-# Some ROMs require specific flags to be passed to makerom.pl
+###############################################################################
#
-MAKEROM_FLAGS_3c503 = -3
+# Version number calculations
+#
+VERSION_MAJOR = 0
+VERSION_MINOR = 9
+VERSION_PATCH = 6
+EXTRAVERSION = +
+MM_VERSION = $(VERSION_MAJOR).$(VERSION_MINOR)
+VERSION = $(MM_VERSION).$(VERSION_PATCH)$(EXTRAVERSION)
+CFLAGS += -DVERSION_MAJOR=$(VERSION_MAJOR) \
+ -DVERSION_MINOR=$(VERSION_MINOR) \
+ -DVERSION_PATCH=$(VERSION_PATCH) \
+ -DVERSION=\"$(VERSION)\"
+IDENT = '$(@F) $(VERSION) (GPL) etherboot.org'
+version :
+ @$(ECHO) $(VERSION)
-# Drag in architecture-specific Makefile
+###############################################################################
+#
+# Drag in the bulk of the build system
#
-MAKEDEPS += arch/$(ARCH)/Makefile
-include arch/$(ARCH)/Makefile
-# Drag in the automatic build system and other housekeeping functions
MAKEDEPS += Makefile.housekeeping
include Makefile.housekeeping
diff --git a/gpxe/src/Makefile.housekeeping b/gpxe/src/Makefile.housekeeping
index 9e11ceb4..2146d9cb 100644
--- a/gpxe/src/Makefile.housekeeping
+++ b/gpxe/src/Makefile.housekeeping
@@ -1,50 +1,10 @@
# -*- makefile -*- : Force emacs to use Makefile mode
-
+#
# This file contains various boring housekeeping functions that would
# otherwise seriously clutter up the main Makefile.
-# Objects to be removed by "make clean"
-#
-CLEANUP := $(BIN)/*.* # *.* to avoid catching the "CVS" directory
-
-# Version number calculations
-#
-VERSION_MAJOR = 0
-VERSION_MINOR = 9
-VERSION_PATCH = 5
-EXTRAVERSION =
-MM_VERSION = $(VERSION_MAJOR).$(VERSION_MINOR)
-VERSION = $(MM_VERSION).$(VERSION_PATCH)$(EXTRAVERSION)
-CFLAGS += -DVERSION_MAJOR=$(VERSION_MAJOR) \
- -DVERSION_MINOR=$(VERSION_MINOR) \
- -DVERSION=\"$(VERSION)\"
-IDENT = '$(@F) $(VERSION) (GPL) etherboot.org'
-version :
- @$(ECHO) $(VERSION)
-
-configure :
- @$(ECHO) "No configuration needed."
-
-install :
- @$(ECHO) "No installation required. Generated images will be placed in the" $(BIN) "directory."
-
-# Check for tools that can cause failed builds
+###############################################################################
#
-.toolcheck : Makefile
- @if $(CC) -v 2>&1 | grep -is 'gcc version 2\.96' > /dev/null; then \
- $(ECHO) 'gcc 2.96 is unsuitable for compiling Etherboot'; \
- $(ECHO) 'Use gcc 2.95 or gcc 3.x instead'; \
- exit 1; \
- fi
- @if [ `perl -e 'use bytes; print chr(255)' | wc -c` = 2 ]; then \
- $(ECHO) 'Your Perl version has a Unicode handling bug'; \
- $(ECHO) 'Execute this command before compiling Etherboot:'; \
- $(ECHO) 'export LANG=$${LANG%.UTF-8}'; \
- exit 1; \
- fi
- @$(TOUCH) $@
-VERYCLEANUP += .toolcheck
-
# Find a usable "echo -e" substitute.
#
TAB := $(shell $(PRINTF) '\t')
@@ -86,20 +46,51 @@ else
@$(ECHO) "No usable \"echo -e\" substitute found"
@exit 1
endif
+MAKEDEPS += .echocheck
VERYCLEANUP += .echocheck
echo :
@$(ECHO) "Using \"$(ECHO_E)\" for \"echo -e\""
-# Build verbosity
+###############################################################################
+#
+# Determine host OS
+#
+HOST_OS := $(shell uname -s)
+hostos :
+ @$(ECHO) $(HOST_OS)
+
+###############################################################################
+#
+# Check for tools that can cause failed builds
+#
+.toolcheck :
+ @if $(CC) -v 2>&1 | grep -is 'gcc version 2\.96' > /dev/null; then \
+ $(ECHO) 'gcc 2.96 is unsuitable for compiling Etherboot'; \
+ $(ECHO) 'Use gcc 2.95 or gcc 3.x instead'; \
+ exit 1; \
+ fi
+ @if [ `perl -e 'use bytes; print chr(255)' | wc -c` = 2 ]; then \
+ $(ECHO) 'Your Perl version has a Unicode handling bug'; \
+ $(ECHO) 'Execute this command before compiling Etherboot:'; \
+ $(ECHO) 'export LANG=$${LANG%.UTF-8}'; \
+ exit 1; \
+ fi
+ @$(TOUCH) $@
+MAKEDEPS += .toolcheck
+VERYCLEANUP += .toolcheck
+
+###############################################################################
+#
+# Check for various tool workarounds
#
-ifeq ($(V),1)
-Q =
-QM = @\#
-else
-Q = @
-QM = @
-endif
+
+# Make syntax does not allow use of comma or space in certain places.
+# This ugly workaround is suggested in the manual.
+#
+COMMA := ,
+EMPTY :=
+SPACE := $(EMPTY) $(EMPTY)
# Check for an old version of gas (binutils 2.9.1)
#
@@ -112,18 +103,154 @@ oldgas :
# default, even when -ffreestanding is specified. We therefore need
# to disable -fstack-protector if the compiler supports it.
#
-SP_TEST = $(CC) -fno-stack-protector -x c -E - < /dev/null >/dev/null 2>&1
+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)
-# compiler.h is needed for our linking and debugging system
+###############################################################################
+#
+# Build verbosity
+#
+ifeq ($(V),1)
+Q :=
+QM := @\#
+else
+Q := @
+QM := @
+endif
+
+###############################################################################
+#
+# Set BIN according to whatever was specified on the command line as
+# the build target.
+#
+
+# Determine how many different BIN directories are mentioned in the
+# make goals.
+#
+BIN_GOALS := $(filter bin/% bin-%,$(MAKECMDGOALS))
+BIN_GOAL_BINS := $(foreach BG,$(BIN_GOALS),$(firstword $(subst /, ,$(BG))))
+NUM_BINS := $(words $(sort $(BIN_GOAL_BINS)))
+
+ifeq ($(NUM_BINS),0)
+
+# No BIN directory was specified. Set BIN to "bin" as a sensible
+# default.
+
+BIN := bin
+
+else # NUM_BINS == 0
+
+ifeq ($(NUM_BINS),1)
+
+# If exactly one BIN directory was specified, set BIN to match this
+# directory.
+#
+BIN := $(firstword $(BIN_GOAL_BINS))
+
+else # NUM_BINS == 1
+
+# More than one BIN directory was specified. We cannot handle the
+# latter case within a single make invocation, so set up recursive
+# targets for each BIN directory.
+#
+# Leave $(BIN) undefined. This has implications for any target that
+# depends on $(BIN); such targets should be made conditional upon the
+# existence of $(BIN).
#
-CFLAGS += -include compiler.h
+$(BIN_GOALS) : % : BIN_RECURSE
+ $(Q)$(MAKE) --no-print-directory BIN=$(firstword $(subst /, ,$@)) $@
+.PHONY : BIN_RECURSE
+
+endif # NUM_BINS == 1
+endif # NUM_BINS == 0
+
+ifdef BIN
+
+# Create $(BIN) directory if it doesn't exist yet
+#
+ifeq ($(wildcard $(BIN)),)
+$(shell $(MKDIR) -p $(BIN))
+endif
+
+# Target to allow e.g. "make bin-efi arch"
+#
+$(BIN) :
+ @# Do nothing, silently
+.PHONY : $(BIN)
+
+# Remove everything in $(BIN) for a "make clean"
+#
+CLEANUP += $(BIN)/*.* # Avoid picking up directories
+
+endif # defined(BIN)
+
+# Determine whether or not we need to include the dependency files
+#
+NO_DEP_TARGETS := $(BIN) clean veryclean
+ifeq ($(MAKECMDGOALS),)
+NEED_DEPS := 1
+endif
+ifneq ($(strip $(filter-out $(NO_DEP_TARGETS),$(MAKECMDGOALS))),)
+NEED_DEPS := 1
+endif
+
+###############################################################################
+#
+# Select build architecture and platform based on $(BIN)
+#
+# BIN has the form bin[-[arch-]platform]
+
+ARCHS := $(patsubst arch/%,%,$(wildcard arch/*))
+PLATFORMS := $(patsubst config/defaults/%.h,%,\
+ $(wildcard config/defaults/*.h))
+archs :
+ @$(ECHO) $(ARCHS)
+
+platforms :
+ @$(ECHO) $(PLATFORMS)
+
+ifdef BIN
+
+# Determine architecture portion of $(BIN), if present
+BIN_ARCH := $(strip $(foreach A,$(ARCHS),\
+ $(patsubst bin-$(A)-%,$(A),\
+ $(filter bin-$(A)-%,$(BIN)))))
-# config/%.h files are generated from config.h using mkconfig.pl
-config/%.h : config*.h
- $(MKCONFIG) config.h
-CLEANUP += config/*.h
+# Determine platform portion of $(BIN), if present
+ifeq ($(BIN_ARCH),)
+BIN_PLATFORM := $(patsubst bin-%,%,$(filter bin-%,$(BIN)))
+else
+BIN_PLATFORM := $(patsubst bin-$(BIN_ARCH)-%,%,$(BIN))
+endif
+
+# Determine build architecture
+DEFAULT_ARCH := i386
+ARCH := $(firstword $(BIN_ARCH) $(DEFAULT_ARCH))
+CFLAGS += -DARCH=$(ARCH)
+arch :
+ @$(ECHO) $(ARCH)
+.PHONY : arch
+
+# Determine build platform
+DEFAULT_PLATFORM := pcbios
+PLATFORM := $(firstword $(BIN_PLATFORM) $(DEFAULT_PLATFORM))
+CFLAGS += -DPLATFORM=$(PLATFORM)
+platform :
+ @$(ECHO) $(PLATFORM)
+
+endif # defined(BIN)
+
+# Include architecture-specific Makefile
+ifdef ARCH
+MAKEDEPS += arch/$(ARCH)/Makefile
+include arch/$(ARCH)/Makefile
+endif
+
+###############################################################################
+#
+# Source file handling
# SRCDIRS lists all directories containing source files.
srcdirs :
@@ -144,6 +271,68 @@ AUTO_SRCS = $(filter-out $(NON_AUTO_SRCS),$(SRCS))
autosrcs :
@$(ECHO) $(AUTO_SRCS)
+# Just about everything else in this section depends upon having
+# $(BIN) set
+
+ifdef BIN
+
+# Common flags
+#
+CFLAGS += -I include -I arch/$(ARCH)/include -I .
+CFLAGS += -Os -ffreestanding
+CFLAGS += -Wall -W -Wformat-nonliteral
+CFLAGS += -g
+CFLAGS += $(EXTRA_CFLAGS)
+ASFLAGS += $(EXTRA_ASFLAGS)
+LDFLAGS += $(EXTRA_LDFLAGS)
+
+# Embedded image(s), or default if not set
+#
+EMBEDDED_IMAGE = image/default.gpxe
+
+# Inhibit -Werror if NO_WERROR is specified on make command line
+#
+ifneq ($(NO_WERROR),1)
+CFLAGS += -Werror
+ASFLAGS += --fatal-warnings
+endif
+
+# compiler.h is needed for our linking and debugging system
+#
+CFLAGS += -include compiler.h
+
+# CFLAGS for specific object types
+#
+CFLAGS_c +=
+CFLAGS_S += -DASSEMBLY
+
+# Base object name of the current target
+#
+OBJECT = $(firstword $(subst ., ,$(@F)))
+
+# CFLAGS for specific object files. You can define
+# e.g. CFLAGS_rtl8139, and have those flags automatically used when
+# compiling bin/rtl8139.o.
+#
+OBJ_CFLAGS = $(CFLAGS_$(OBJECT)) -DOBJECT=$(subst -,_,$(OBJECT))
+$(BIN)/%.flags :
+ @$(ECHO) $(OBJ_CFLAGS)
+
+# 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_to_c = $(Q)$(COMPILE_c) -E -c $< > $@
+RULE_c_to_s = $(Q)$(COMPILE_c) -S -g0 -c $< -o $@
+
+PREPROCESS_S = $(CPP) $(CFLAGS) $(CFLAGS_S) $(OBJ_CFLAGS)
+ASSEMBLE_S = $(AS) $(ASFLAGS)
+RULE_S = $(Q)$(PREPROCESS_S) $< | $(ASSEMBLE_S) -o $@
+RULE_S_to_s = $(Q)$(PREPROCESS_S) $< > $@
+
+DEBUG_TARGETS += dbg%.o c s
+
# We automatically generate rules for any file mentioned in AUTO_SRCS
# using the following set of templates. It would be cleaner to use
# $(eval ...), but this function exists only in GNU make >= 3.80.
@@ -157,7 +346,7 @@ autosrcs :
#
define src_template
- @$(ECHO) "Generating Makefile rules for $(1)"
+ @$(ECHO) " [DEPS] $(1)"
@$(MKDIR) -p $(dir $(2))
@$(RM) $(2)
@$(TOUCH) $(2)
@@ -182,13 +371,13 @@ define obj_template
-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)' \
- '\n\t$$(QM)$(ECHO) " [BUILD] $$@"\n' \
+ '\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\t$$(QM)$(ECHO) " [BUILD] $$@"\n' \
+ '\n\t$$(QM)$(ECHO) " [BUILD] $$@"' \
'\n\t$$(RULE_$(3)_to_$(TGT))\n' \
'\n$(TGT)_OBJS += $$(BIN)/$(4).$(TGT)\n' ) ) \
'\n$(2) : $$($(4)_DEPS)\n' \
@@ -205,7 +394,11 @@ $(BIN)/deps/%.d : % $(MAKEDEPS) $(PARSEROM)
# Calculate and include the list of Makefile rules files
#
AUTO_DEPS = $(patsubst %,$(BIN)/deps/%.d,$(AUTO_SRCS))
+ifdef NEED_DEPS
+ifneq ($(AUTO_DEPS),)
-include $(AUTO_DEPS)
+endif
+endif
autodeps :
@$(ECHO) $(AUTO_DEPS)
VERYCLEANUP += $(BIN)/deps
@@ -220,13 +413,31 @@ drivers :
roms :
@$(ECHO) $(ROMS)
-# Embedded binary
-$(BIN)/embedimg.bin: $(EMBEDDED_IMAGE)
- $(QM)$(ECHO) " [COPY] $@"
- $(Q)$(CP) -f $(EMBEDDED_IMAGE) $@
+# List of embedded images included in the last build of embedded.o.
+# This is needed in order to correctly rebuild embedded.o whenever the
+# list of objects changes.
+#
+EMBEDDED_LIST := $(BIN)/.embedded.list
+ifeq ($(wildcard $(EMBEDDED_LIST)),)
+EMBEDDED_LIST_IMAGE :=
+else
+EMBEDDED_LIST_IMAGE := $(shell cat $(EMBEDDED_LIST))
+endif
+ifneq ($(EMBEDDED_LIST_IMAGE),$(EMBEDDED_IMAGE))
+$(shell $(ECHO) "$(EMBEDDED_IMAGE)" > $(EMBEDDED_LIST))
+endif
+
+$(EMBEDDED_LIST) :
+
+VERYCLEANUP += $(EMBEDDED_LIST)
-$(BIN)/embed.o: $(BIN)/embedimg.bin
-CFLAGS_embed = -DEMBEDIMG=\"$(BIN)/embedimg.bin\"
+EMBEDDED_FILES := $(subst $(COMMA), ,$(EMBEDDED_IMAGE))
+EMBED_ALL := $(foreach i,$(shell seq 1 $(words $(EMBEDDED_FILES))),\
+ EMBED ( $(i), \"$(word $(i), $(EMBEDDED_FILES))\",\
+ \"$(notdir $(word $(i),$(EMBEDDED_FILES)))\" ))
+
+$(BIN)/embedded.o : $(EMBEDDED_FILES) $(EMBEDDED_LIST)
+CFLAGS_embedded = -DEMBED_ALL="$(EMBED_ALL)"
# Generate the NIC file from the parsed source files. The NIC file is
# only for rom-o-matic.
@@ -237,7 +448,7 @@ $(BIN)/NIC : $(AUTO_DEPS)
'it is only for rom-o-matic' >> $@
@$(ECHO) >> $@
@perl -ne 'chomp; print "$$1\n" if /\# NIC\t(.*)$$/' $^ >> $@
-CLEANUP += $(BIN)/NIC
+CLEANUP += $(BIN)/NIC # Doesn't match the $(BIN)/*.* pattern
# Analyse a target name (e.g. "bin/dfe538--prism2_pci.zrom.tmp") and
# derive the variables:
@@ -305,7 +516,6 @@ TGT_MAKEROM_FLAGS = $(strip $(MAKEROM_FLAGS_$(TGT_ROM_NAME)) \
# Calculate list of debugging versions of objects to be included in
# the target.
#
-COMMA := ,
DEBUG_LIST = $(subst $(COMMA), ,$(DEBUG))
DEBUG_OBJ_LEVEL = $(firstword $(word 2,$(subst :, ,$(1))) 1)
DEBUG_OBJ_BASE = $(word 1,$(subst :, ,$(1))).dbg$(call DEBUG_OBJ_LEVEL,$(1))
@@ -342,8 +552,13 @@ $(BIN)/%.info :
# in order to correctly rebuild blib whenever the list of objects
# changes.
#
-BLIB_LIST = $(BIN)/.blib.list
-ifneq ($(shell cat $(BLIB_LIST)),$(BLIB_OBJS))
+BLIB_LIST := $(BIN)/.blib.list
+ifeq ($(wildcard $(BLIB_LIST)),)
+BLIB_LIST_OBJS :=
+else
+BLIB_LIST_OBJS := $(shell cat $(BLIB_LIST))
+endif
+ifneq ($(BLIB_LIST_OBJS),$(BLIB_OBJS))
$(shell $(ECHO) "$(BLIB_OBJS)" > $(BLIB_LIST))
endif
@@ -396,10 +611,6 @@ $(BIN)/%.zbin : $(BIN)/%.bin $(BIN)/%.zinfo $(ZBIN)
$(QM)$(ECHO) " [ZBIN] $@"
$(Q)$(ZBIN) $(BIN)/$*.bin $(BIN)/$*.zinfo > $@
-# Build bochs symbol table
-$(BIN)/%.bxs : $(BIN)/%.tmp
- $(NM) $< | cut -d" " -f1,3 > $@
-
# Rules for each media format. These are generated and placed in an
# external Makefile fragment. We could do this via $(eval ...), but
# that would require make >= 3.80.
@@ -435,7 +646,7 @@ automedia :
#
define media_template
- @$(ECHO) "Generating Makefile rules for $(1) media"
+ @$(ECHO) " [MEDIADEPS] $(1)"
@$(MKDIR) -p $(dir $(2))
@$(RM) $(2)
@$(TOUCH) $(2)
@@ -459,7 +670,20 @@ $(BIN)/deps/%.media.d : $(MAKEDEPS)
MEDIA_DEPS = $(patsubst %,$(BIN)/deps/%.media.d,$(AUTO_MEDIA))
mediadeps :
@$(ECHO) $(MEDIA_DEPS)
+ifdef NEED_DEPS
+ifneq ($(MEDIA_DEPS),)
-include $(MEDIA_DEPS)
+endif
+endif
+
+# Wrap up binary blobs (for embedded images)
+#
+$(BIN)/%.o : payload/%.img
+ $(QM)echo " [WRAP] $@"
+ $(Q)$(LD) -b binary -r -o $@ $< --undefined obj_payload \
+ --defsym obj_$*=0
+
+BOBJS += $(patsubst payload/%.img,$(BIN)/%.o,$(wildcard payload/*.img))
# The "allXXXs" targets for each suffix
#
@@ -472,15 +696,23 @@ allpxes allisos alldsks : all%s : $(foreach DRIVER,$(DRIVERS),$(BIN)/$(DRIVER).%
$(BIN)/etherboot.% : $(BIN)/gpxe.%
ln -sf $(notdir $<) $@
-# Wrap up binary blobs
+endif # defined(BIN)
+
+###############################################################################
#
-$(BIN)/%.o : payload/%.img
- $(QM)echo " [WRAP] $@"
- $(Q)$(LD) -b binary -r -o $@ $< --undefined obj_payload \
- --defsym obj_$*=0
+# Rules for finalising files. TGT_MAKEROM_FLAGS is defined as part of
+# the automatic build system and varies by target; it includes the
+# "-p 0x1234,0x5678" string to set the PCI IDs.
+#
+FINALISE_rom = $(MAKEROM) $(MAKEROM_FLAGS) $(TGT_MAKEROM_FLAGS) \
+ -i$(IDENT) -s 0 $@
-BOBJS += $(patsubst payload/%.img,$(BIN)/%.o,$(wildcard payload/*.img))
+# Some ROMs require specific flags to be passed to makerom.pl
+#
+MAKEROM_FLAGS_3c503 = -3
+###############################################################################
+#
# The compression utilities
#
$(NRV2B) : util/nrv2b.c $(MAKEDEPS)
@@ -494,6 +726,29 @@ $(ZBIN) : util/zbin.c util/nrv2b.c $(MAKEDEPS)
$(Q)$(HOST_CC) -O2 -o $@ $<
CLEANUP += $(ZBIN)
+###############################################################################
+#
+# The EFI image converter
+#
+$(ELF2EFI32) : util/elf2efi.c $(MAKEDEPS)
+ $(QM)$(ECHO) " [HOSTCC] $@"
+ $(Q)$(HOST_CC) -DMDE_CPU_IA32 -idirafter include -O2 \
+ -o $@ $< -lbfd -liberty
+CLEANUP += $(ELF2EFI32)
+
+$(ELF2EFI64) : util/elf2efi.c $(MAKEDEPS)
+ $(QM)$(ECHO) " [HOSTCC] $@"
+ $(Q)$(HOST_CC) -DMDE_CPU_X64 -idirafter include -O2 \
+ -o $@ $< -lbfd -liberty
+CLEANUP += $(ELF2EFI64)
+
+$(EFIROM) : util/efirom.c $(MAKEDEPS)
+ $(QM)$(ECHO) " [HOSTCC] $@"
+ $(Q)$(HOST_CC) -idirafter include -O2 -o $@ $<
+CLEANUP += $(EFIROM)
+
+###############################################################################
+#
# 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.
@@ -517,27 +772,30 @@ bs : $(BUILDSERIAL_NOW)
@$(ECHO) $$(( $(shell cat $<) + 1 )) > $(BUILDSERIAL_NEXT)
@$(ECHO) "Build serial number is $(shell cat $<)"
-# List of available architectures
+###############################################################################
#
-ARCHS = $(filter-out CVS,$(patsubst arch/%,%,$(wildcard arch/*)))
-archs :
- @$(ECHO) $(ARCHS)
+# Build the TAGS file(s) for emacs
+#
+TAGS :
+ ctags -e -R -f $@ --exclude=bin
-OTHER_ARCHS = $(filter-out $(ARCH),$(ARCHS))
-otherarchs :
- @$(ECHO) $(OTHER_ARCHS)
+CLEANUP += TAGS
-# Build the TAGS file for emacs
+###############################################################################
#
-TAGS : TAGS.$(ARCH)
-
-TAGS.$(ARCH) :
- ctags -e -R -f $@ --exclude=bin \
- $(foreach ARCH,$(OTHER_ARCHS),--exclude=arch/$(ARCH))
-CLEANUP += TAGS*
+# Force rebuild for any given target
+#
+%.rebuild :
+ rm -f $*
+ $(Q)$(MAKE) $*
+###############################################################################
+#
# Symbol table checks
#
+
+ifdef BIN
+
SYMTAB = $(BIN)/symtab
$(SYMTAB) : $(BLIB)
$(OBJDUMP) -w -t $< > $@
@@ -547,14 +805,27 @@ CLEANUP += $(BIN)/symtab
symcheck : $(SYMTAB)
$(SYMCHECK) $<
-# Force rebuild for any given target
+endif # defined(BIN)
+
+###############################################################################
+#
+# Build bochs symbol table
#
-$(BIN)/%.rebuild :
- rm -f $(BIN)/$*
- $(MAKE) $(MAKEFLAGS) $(BIN)/$*
+ifdef BIN
+
+$(BIN)/%.bxs : $(BIN)/%.tmp
+ $(NM) $< | cut -d" " -f1,3 > $@
+
+endif # defined(BIN)
+
+###############################################################################
+#
# Documentation
#
+
+ifdef BIN
+
$(BIN)/doxygen.cfg : doxygen.cfg $(MAKEDEPS)
$(PERL) -pe 's{\@SRCDIRS\@}{$(SRCDIRS)}; ' \
-e 's{\@BIN\@}{$(BIN)}; ' \
@@ -578,6 +849,10 @@ docview :
$(ECHO) "Documentation index in $(BIN)/doc/html/index.html" ; \
fi
+endif # defined(BIN)
+
+###############################################################################
+#
# Clean-up
#
clean :
@@ -585,19 +860,3 @@ clean :
veryclean : clean
$(RM) -r $(VERYCLEANUP)
-
-# Make clean tarballs for release
-
-tarball : ../VERSION
- ($(ECHO) -n $(VERSION) ''; date -u +'%Y-%m-%d') > ../VERSION
- $(RM) -r /tmp/$(USER)/gpxe-$(VERSION)
- mkdir -p /tmp/$(USER)/gpxe-$(VERSION)
- cp -rP .. /tmp/$(USER)/gpxe-$(VERSION)
- ( cd /tmp/$(USER)/gpxe-$(VERSION)/src ; $(MAKE) veryclean ; $(RM) -r bin/deps )
- ( cd /tmp/$(USER); tar cf /tmp/$(USER)/gpxe-$(VERSION).tar --exclude ".git*" --exclude "#*" \
- --exclude "*~" gpxe-$(VERSION) )
- bzip2 -9 < /tmp/$(USER)/gpxe-$(VERSION).tar > /tmp/$(USER)/gpxe-$(VERSION).tar.bz2
- gzip -9 < /tmp/$(USER)/gpxe-$(VERSION).tar > /tmp/$(USER)/gpxe-$(VERSION).tar.gz
- $(RM) -r /tmp/$(USER)/gpxe-$(VERSION)
- $(RM) /tmp/$(USER)/gpxe-$(VERSION).tar
- ( cd /tmp/$(USER) ; tar -zxf /tmp/$(USER)/gpxe-$(VERSION).tar.gz )
diff --git a/gpxe/src/arch/i386/Config b/gpxe/src/arch/i386/Config
deleted file mode 100644
index 1c086ecc..00000000
--- a/gpxe/src/arch/i386/Config
+++ /dev/null
@@ -1,148 +0,0 @@
-# -*- makefile -*-
-
-##############################################################################
-##############################################################################
-#
-# IMPORTANT!
-#
-# The use of this file to set options that affect only single object
-# files is deprecated, because changing anything in this file results
-# in a complete rebuild, which is slow. All options are gradually
-# being migrated to config.h, which does not suffer from this problem.
-#
-# Only options that affect the entire build (e.g. overriding the $(CC)
-# Makefile variable) should be placed in here.
-#
-##############################################################################
-##############################################################################
-
-
-# Config for i386 Etherboot
-#
-# Do not delete the tag OptionDescription and /OptionDescription
-# It is used to automatically generate the documentation.
-#
-# @OptionDescrition@
-#
-# BIOS interface options:
-#
-# -DPCBIOS
-# Compile in support for the normal pcbios
-# -DLINUXBIOS
-# Compile in support for LinuxBIOS
-# -DBBS_BUT_NOT_PNP_COMPLIANT
-# Some BIOSes claim to be PNP but they don't conform
-# to the BBS spec which specifies that ES:DI must
-# point to the string $PnP on entry. This option
-# works around those. This option must be added to
-# LCONFIG.
-# -DNO_DELAYED_INT
-# Take control as soon as BIOS detects the ROM.
-# Normally hooks onto INT18H or INT19H. Use only if you
-# have a very non-conformant BIOS as it bypasses
-# BIOS initialisation of devices. This only works for
-# legacy ROMs, i.e. PCI_PNP_HEADER not defined.
-# This option was formerly called NOINT19H.
-# -DBOOT_INT18H
-# Etherboot normally hooks onto INT19H for legacy ROMs.
-# You can choose to hook onto INT18H (BASIC interpreter
-# entry point) instead. This entry point is used when
-# all boot devices have been exhausted. This option must
-# be added to LCONFIG.
-# -DCONFIG_PCI_DIRECT
-# Define this for PCI BIOSes that do not implement
-# BIOS32 or not correctly. Normally not needed.
-# Only works for BIOSes of a certain era.
-# -DCONFIG_TSC_CURRTICKS
-# Uses the processor time stamp counter instead of reading
-# the BIOS time counter. This allows Etherboot to work
-# even without a BIOS. This only works on late model
-# 486s and above.
-# -DCONFIG_NO_TIMER2
-# Some systems do not have timer2 implemented.
-# If you have a RTC this will allow you to roughly calibrate
-# it using outb instructions.
-#
-# Extended cpu options
-
-# -DCONFIG_X86_64
-# Compile in support for booting x86_64 64bit binaries.
-#
-# PXE loader options:
-#
-# -DPXELOADER_KEEP_ALL
-# Prevent PXE loader (prefix) from unloading the
-# PXE stack. You will want to use this if, for
-# example, you are booting via PXE-on-floppy.
-# You may want to use it under certain
-# circumstances when using the Etherboot UNDI
-# driver; these are complex and best practice is
-# not yet established.
-#
-# Obscure options you probably don't need to touch:
-#
-# -DIGNORE_E820_MAP
-# Ignore the memory map returned by the E820 BIOS
-# call. May be necessary on some buggy BIOSes.
-# -DT503_AUI
-# Use AUI by default on 3c503 cards.
-# -DFLATTEN_REAL_MODE
-# Use 4GB segment limits when calling out to or
-# returning to real-mode code. This is necessary to
-# work around some buggy code (e.g. OpenBSD's pxeboot)
-# that uses flat real-mode without being sufficiently
-# paranoid about the volatility of its segment limits.
-
-#
-# @/OptionDescription@
-
-# BIOS select don't change unless you know what you are doing
-# CFLAGS+= -DPCBIOS
-
-# Compile in k8/hammer support
-# CFLAGS+= -DCONFIG_X86_64
-
-# Options to make a version of Etherboot that will work under linuxBIOS.
-# CFLAGS+= -DLINUXBIOS -DCONFIG_TSC_CURRTICKS -DCONSOLE_SERIAL -DCOMCONSOLE=0x3f8 -DCOMPRESERVE -DCONFIG_PCI_DIRECT -DELF_IMAGE
-
-# These options affect the loader that is prepended to the Etherboot image
-# LCONFIG+= -DBBS_BUT_NOT_PNP_COMPLIANT
-# LCONFIG+= -DBOOT_INT18H
-
-# Produce code that will work with OpenBSD's pxeboot
-# CFLAGS+= -DFLATTEN_REAL_MODE
-
-CFLAGS+= -fstrength-reduce -fomit-frame-pointer -march=i386
-# Squeeze the code in as little space as possible.
-# gcc3 needs a different syntax to gcc2 if you want to avoid spurious warnings.
-GCC_VERSION = $(subst ., ,$(shell $(CC) -dumpversion))
-GCC_MAJORVERSION = $(firstword $(GCC_VERSION))
-ifeq ($(GCC_MAJORVERSION),2)
-CFLAGS+= -malign-jumps=1 -malign-loops=1 -malign-functions=1
-else
-CFLAGS+= -falign-jumps=1 -falign-loops=1 -falign-functions=1
-endif
-
-# this is almost always a win. the kernel uses it, too.
-CFLAGS+= -mpreferred-stack-boundary=2
-
-# use regparm for all functions - C functions called from assembly (or
-# vice versa) need __cdecl now
-CFLAGS+= -mregparm=3
-
-# use -mrtd (same __cdecl requirements as above)
-CFLAGS+= -mrtd
-
-# this is the logical complement to -mregparm=3.
-# it doesn't currently buy us anything, but if anything ever tries
-# to return small structures, let's be prepared
-CFLAGS+= -freg-struct-return
-
-LDFLAGS+= -N --no-check-sections
-
-ifeq "$(shell uname -s)" "FreeBSD"
-CFLAGS+= -DIMAGE_FREEBSD -DELF_IMAGE -DAOUT_IMAGE
-endif
-
-# An alternate location for isolinux.bin can be set here
-# ISOLINUX_BIN=/path/to/isolinux.bin
diff --git a/gpxe/src/arch/i386/Makefile b/gpxe/src/arch/i386/Makefile
index 97ca0774..1392bbac 100644
--- a/gpxe/src/arch/i386/Makefile
+++ b/gpxe/src/arch/i386/Makefile
@@ -1,3 +1,59 @@
+# Force i386-only instructions
+#
+CFLAGS += -march=i386
+
+# Code size reduction.
+#
+CFLAGS += -fstrength-reduce -fomit-frame-pointer
+
+# Code size reduction. gcc3 needs a different syntax to gcc2 if you
+# want to avoid spurious warnings.
+#
+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
+
+# Code size reduction. This is almost always a win. The kernel uses it, too.
+#
+CFLAGS += -mpreferred-stack-boundary=2
+
+# Code size reduction. Use regparm for all functions - C functions
+# called from assembly (or vice versa) need __asmcall now
+#
+CFLAGS += -mregparm=3
+
+# Code size reduction. Use -mrtd (same __asmcall requirements as above)
+CFLAGS += -mrtd
+
+# Code size reduction. This is the logical complement to -mregparm=3.
+# It doesn't currently buy us anything, but if anything ever tries to
+# return small structures, let's be prepared
+#
+CFLAGS += -freg-struct-return
+
+# Force 32-bit code even on an x86-64 machine
+#
+CFLAGS += -m32
+ASFLAGS += --32
+ifeq ($(HOST_OS),FreeBSD)
+LDFLAGS += -m elf_i386_fbsd
+else
+LDFLAGS += -m elf_i386
+endif
+
+# EFI requires -fshort-wchar, and nothing else currently uses wchar_t
+#
+CFLAGS += -fshort-wchar
+
+# We need to undefine the default macro "i386" when compiling .S
+# files, otherwise ".arch i386" translates to ".arch 1"...
+#
+CFLAGS += -Ui386
+
# Locations of utilities
#
ISOLINUX_BIN = /usr/lib/syslinux/isolinux.bin
@@ -22,85 +78,37 @@ 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
+OBJS_unnrv2b = unnrv2b unnrv2b16
+CFLAGS_unnrv2b16 = -DCODE16
-# We need to undefine the default macro "i386" when compiling .S
-# files, otherwise ".arch i386" translates to ".arch 1"...
+# Include common x86 Makefile
+#
+MAKEDEPS += arch/x86/Makefile
+include arch/x86/Makefile
+
+# Include platform-specific Makefile
#
-CFLAGS_S += -Ui386
-
-# The i386 linker script
-#
-LDSCRIPT = arch/i386/scripts/i386.lds
-
-# Media types.
-#
-MEDIA += rom
-MEDIA += pxe
-MEDIA += kpxe
-MEDIA += elf
-MEDIA += elfd
-MEDIA += lmelf
-MEDIA += lmelfd
-MEDIA += lkrn
-MEDIA += bImage
-MEDIA += dsk
-MEDIA += nbi
-MEDIA += hd
-MEDIA += raw
-MEDIA += com
-MEDIA += exe
-
-# Special target for building Master Boot Record binary
-$(BIN)/mbr.bin : $(BIN)/mbr.o
- $(OBJCOPY) -O binary $< $@
+MAKEDEPS += arch/i386/Makefile.$(PLATFORM)
+include arch/i386/Makefile.$(PLATFORM)
# Some suffixes (e.g. %.fd0) are generated directly from other
# finished files (e.g. %.dsk), rather than having their own prefix.
# rule to write disk images to /dev/fd0
-NON_AUTO_MEDIA += fd0
+NON_AUTO_MEDIA += fd0
%fd0 : %dsk
- dd if=$< bs=512 conv=sync of=/dev/fd0
- sync
+ $(QM)$(ECHO) " [DD] $@"
+ $(Q)dd if=$< bs=512 conv=sync of=/dev/fd0
+ $(Q)sync
# rule to create padded disk images
-NON_AUTO_MEDIA += pdsk
+NON_AUTO_MEDIA += pdsk
%pdsk : %dsk
- cp $< $@
- $(PERL) ./util/dskpad.pl $@
-
-# rule to make a non-emulation ISO boot image
-NON_AUTO_MEDIA += iso
-%iso: %lkrn util/geniso
- ISOLINUX_BIN=$(ISOLINUX_BIN) bash util/geniso $@ $<
-
-# rule to make a floppy emulation ISO boot image
-NON_AUTO_MEDIA += liso
-%liso: %lkrn util/genliso
- bash util/genliso $@ $<
-
-# rule to make a USB disk image
-$(BIN)/usbdisk.bin : $(BIN)/usbdisk.o
- $(OBJCOPY) -O binary $< $@
-
-NON_AUTO_MEDIA += usb
-%usb: $(BIN)/usbdisk.bin %hd
- cat $^ > $@
+ $(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"
#
MEDIA += $(NON_AUTO_MEDIA)
-
-# Shortcut to allow typing just
-# make bin-kir/%
-# rather than
-# make -f arch/i386/kir-Makefile bin-kir/%
-# for building a KEEP_IT_REAL flavour.
-#
-$(BIN)-kir/% : kir-target
- $(MAKE) -f arch/i386/kir-Makefile $(MAKECMDGOALS)
-
-.PHONY : kir-target
diff --git a/gpxe/src/arch/i386/Makefile.efi b/gpxe/src/arch/i386/Makefile.efi
new file mode 100644
index 00000000..8d651b04
--- /dev/null
+++ b/gpxe/src/arch/i386/Makefile.efi
@@ -0,0 +1,10 @@
+# -*- makefile -*- : Force emacs to use Makefile mode
+
+# Specify EFI image builder
+#
+ELF2EFI = $(ELF2EFI32)
+
+# Include generic EFI Makefile
+#
+MAKEDEPS += arch/x86/Makefile.efi
+include arch/x86/Makefile.efi
diff --git a/gpxe/src/arch/i386/Makefile.pcbios b/gpxe/src/arch/i386/Makefile.pcbios
new file mode 100644
index 00000000..64b3dac2
--- /dev/null
+++ b/gpxe/src/arch/i386/Makefile.pcbios
@@ -0,0 +1,55 @@
+# -*- makefile -*- : Force emacs to use Makefile mode
+
+# The i386 linker script
+#
+LDSCRIPT = arch/i386/scripts/i386.lds
+
+# Stop ld from complaining about our customised linker script
+#
+LDFLAGS += -N --no-check-sections
+
+# Media types.
+#
+MEDIA += rom
+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
+
+# rule to make a non-emulation ISO boot image
+NON_AUTO_MEDIA += iso
+%iso: %lkrn util/geniso
+ $(QM)$(ECHO) " [GENISO] $@"
+ $(Q)ISOLINUX_BIN=$(ISOLINUX_BIN) bash util/geniso $@ $<
+
+# rule to make a floppy emulation ISO boot image
+NON_AUTO_MEDIA += liso
+%liso: %lkrn util/genliso
+ $(QM)$(ECHO) " [GENLISO] $@"
+ $(Q)bash util/genliso $@ $<
+
+# Special target for building Master Boot Record binary
+$(BIN)/mbr.bin : $(BIN)/mbr.o
+ $(QM)$(ECHO) " [OBJCOPY] $@"
+ $(Q)$(OBJCOPY) -O binary $< $@
+
+# rule to make a USB disk image
+$(BIN)/usbdisk.bin : $(BIN)/usbdisk.o
+ $(QM)$(ECHO) " [OBJCOPY] $@"
+ $(Q)$(OBJCOPY) -O binary $< $@
+
+NON_AUTO_MEDIA += usb
+%usb: $(BIN)/usbdisk.bin %hd
+ $(QM)$(ECHO) " [FINISH] $@"
+ $(Q)cat $^ > $@
diff --git a/gpxe/src/arch/i386/core/dumpregs.c b/gpxe/src/arch/i386/core/dumpregs.c
index 89426d58..82dc2184 100644
--- a/gpxe/src/arch/i386/core/dumpregs.c
+++ b/gpxe/src/arch/i386/core/dumpregs.c
@@ -1,7 +1,7 @@
#include <stdio.h>
#include <realmode.h>
-void __cdecl _dump_regs ( struct i386_all_regs *ix86 ) {
+void __asmcall _dump_regs ( struct i386_all_regs *ix86 ) {
__asm__ __volatile__ (
TEXT16_CODE ( ".globl dump_regs\n\t"
@@ -12,8 +12,8 @@ void __cdecl _dump_regs ( struct i386_all_regs *ix86 ) {
"addr32 leal 4(%%esp), %%esp\n\t"
"ret\n\t" ) : : );
- printf ( "EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
- "ESI=%08lx EDI=%08lx EBP=%08lx ESP=%08lx\n"
+ printf ( "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
+ "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
"CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
ix86->regs.eax, ix86->regs.ebx, ix86->regs.ecx,
ix86->regs.edx, ix86->regs.esi, ix86->regs.edi,
diff --git a/gpxe/src/arch/i386/core/gdbidt.S b/gpxe/src/arch/i386/core/gdbidt.S
index 860f7b01..cd8b38a9 100644
--- a/gpxe/src/arch/i386/core/gdbidt.S
+++ b/gpxe/src/arch/i386/core/gdbidt.S
@@ -2,7 +2,7 @@
* Interrupt Descriptor Table (IDT) setup and interrupt handlers for GDB stub.
*/
-#include <virtaddr.h>
+#include <librm.h>
#define SIZEOF_I386_REGS 32
#define SIZEOF_I386_FLAGS 4
@@ -11,7 +11,7 @@
* Interrupt Descriptor Table
****************************************************************************
*/
- .section ".data16"
+ .section ".data16", "aw", @progbits
.globl idtr
idtr:
idt_limit:
@@ -68,7 +68,7 @@ idt_fixed:
* Destroys %ax, %bx, and %di.
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
.code16
.globl idt_init
idt_init:
@@ -100,7 +100,7 @@ idt_init:
* Interrupt handlers
****************************************************************************
*/
- .section ".text"
+ .section ".text", "ax", @progbits
.code32
/* POSIX signal numbers for reporting traps to GDB */
diff --git a/gpxe/src/arch/i386/core/gdbmach.c b/gpxe/src/arch/i386/core/gdbmach.c
index 5e72e4d0..97827ecb 100644
--- a/gpxe/src/arch/i386/core/gdbmach.c
+++ b/gpxe/src/arch/i386/core/gdbmach.c
@@ -19,7 +19,7 @@
#include <stddef.h>
#include <stdio.h>
#include <assert.h>
-#include <virtaddr.h>
+#include <gpxe/uaccess.h>
#include <gpxe/gdbstub.h>
#include <gdbmach.h>
@@ -142,7 +142,7 @@ static void gdbmach_enable_hwbps ( void ) {
__asm__ __volatile__ ( "movl %0, %%dr7\n" : : "r" ( dr7 ) );
}
-__cdecl void gdbmach_handler ( int signo, gdbreg_t *regs ) {
+__asmcall void gdbmach_handler ( int signo, gdbreg_t *regs ) {
gdbmach_disable_hwbps();
gdbstub_handler ( signo, regs );
gdbmach_enable_hwbps();
diff --git a/gpxe/src/arch/i386/core/nap.c b/gpxe/src/arch/i386/core/nap.c
deleted file mode 100644
index 12bb5699..00000000
--- a/gpxe/src/arch/i386/core/nap.c
+++ /dev/null
@@ -1,12 +0,0 @@
-
-#include <realmode.h>
-#include <bios.h>
-
-/**************************************************************************
- * Save power by halting the CPU until the next interrupt
- **************************************************************************/
-void cpu_nap ( void ) {
- __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
- "hlt\n\t"
- "cli\n\t" ) : : );
-}
diff --git a/gpxe/src/arch/i386/core/pic8259.c b/gpxe/src/arch/i386/core/pic8259.c
index defe2e7d..8a0433dd 100644
--- a/gpxe/src/arch/i386/core/pic8259.c
+++ b/gpxe/src/arch/i386/core/pic8259.c
@@ -16,6 +16,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <gpxe/io.h>
#include <pic8259.h>
/** @file
diff --git a/gpxe/src/arch/i386/core/rdtsc_timer.c b/gpxe/src/arch/i386/core/rdtsc_timer.c
new file mode 100644
index 00000000..443c8ada
--- /dev/null
+++ b/gpxe/src/arch/i386/core/rdtsc_timer.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2008 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
+ *
+ * RDTSC timer
+ *
+ */
+
+#include <assert.h>
+#include <gpxe/timer.h>
+#include <gpxe/timer2.h>
+
+/**
+ * Number of TSC ticks per microsecond
+ *
+ * This is calibrated on the first use of the timer.
+ */
+static unsigned long rdtsc_ticks_per_usec;
+
+/**
+ * Delay for a fixed number of microseconds
+ *
+ * @v usecs Number of microseconds for which to delay
+ */
+static void rdtsc_udelay ( unsigned long usecs ) {
+ unsigned long start;
+ unsigned long elapsed;
+
+ /* Sanity guard, since we may divide by this */
+ if ( ! usecs )
+ usecs = 1;
+
+ start = currticks();
+ if ( rdtsc_ticks_per_usec ) {
+ /* Already calibrated; busy-wait until done */
+ do {
+ elapsed = ( currticks() - start );
+ } while ( elapsed < ( usecs * rdtsc_ticks_per_usec ) );
+ } else {
+ /* Not yet calibrated; use timer2 and calibrate
+ * based on result.
+ */
+ timer2_udelay ( usecs );
+ elapsed = ( currticks() - start );
+ rdtsc_ticks_per_usec = ( elapsed / usecs );
+ DBG ( "RDTSC timer calibrated: %ld ticks in %ld usecs "
+ "(%ld MHz)\n", elapsed, usecs,
+ ( rdtsc_ticks_per_usec << TSC_SHIFT ) );
+ }
+}
+
+/**
+ * Get number of ticks per second
+ *
+ * @ret ticks_per_sec Number of ticks per second
+ */
+static unsigned long rdtsc_ticks_per_sec ( void ) {
+
+ /* Calibrate timer, if not already done */
+ if ( ! rdtsc_ticks_per_usec )
+ udelay ( 1 );
+
+ /* Sanity check */
+ assert ( rdtsc_ticks_per_usec != 0 );
+
+ return ( rdtsc_ticks_per_usec * 1000 * 1000 );
+}
+
+PROVIDE_TIMER ( rdtsc, udelay, rdtsc_udelay );
+PROVIDE_TIMER_INLINE ( rdtsc, currticks );
+PROVIDE_TIMER ( rdtsc, ticks_per_sec, rdtsc_ticks_per_sec );
diff --git a/gpxe/src/arch/i386/core/relocate.c b/gpxe/src/arch/i386/core/relocate.c
index aa58ad65..bdc8498e 100644
--- a/gpxe/src/arch/i386/core/relocate.c
+++ b/gpxe/src/arch/i386/core/relocate.c
@@ -1,4 +1,4 @@
-#include <io.h>
+#include <gpxe/io.h>
#include <registers.h>
#include <gpxe/memmap.h>
@@ -18,8 +18,8 @@ extern char _max_align[];
#define max_align ( ( unsigned int ) _max_align )
/* Linker symbols */
-extern char _text[];
-extern char _end[];
+extern char _textdata[];
+extern char _etextdata[];
/* within 1MB of 4GB is too close.
* MAX_ADDR is the maximum address we can easily do DMA to.
@@ -39,7 +39,7 @@ extern char _end[];
* address space, and returns the physical address of the new location
* to the prefix in %edi.
*/
-__cdecl void relocate ( struct i386_all_regs *ix86 ) {
+__asmcall void relocate ( struct i386_all_regs *ix86 ) {
struct memory_map memmap;
unsigned long start, end, size, padded_size;
unsigned long new_start, new_end;
@@ -47,8 +47,8 @@ __cdecl void relocate ( struct i386_all_regs *ix86 ) {
/* Get memory map and current location */
get_memmap ( &memmap );
- start = virt_to_phys ( _text );
- end = virt_to_phys ( _end );
+ start = virt_to_phys ( _textdata );
+ end = virt_to_phys ( _etextdata );
size = ( end - start );
padded_size = ( size + max_align - 1 );
diff --git a/gpxe/src/arch/i386/core/stack.S b/gpxe/src/arch/i386/core/stack.S
index c2d138aa..da66d239 100644
--- a/gpxe/src/arch/i386/core/stack.S
+++ b/gpxe/src/arch/i386/core/stack.S
@@ -4,7 +4,7 @@
* Internal stack
****************************************************************************
*/
- .section ".stack"
+ .section ".stack", "aw", @nobits
.align 8
.globl _stack
_stack:
diff --git a/gpxe/src/arch/i386/core/stack16.S b/gpxe/src/arch/i386/core/stack16.S
index 3380a083..d1251f06 100644
--- a/gpxe/src/arch/i386/core/stack16.S
+++ b/gpxe/src/arch/i386/core/stack16.S
@@ -4,7 +4,7 @@
* Internal stack
****************************************************************************
*/
- .section ".stack16"
+ .section ".stack16", "aw", @nobits
.align 8
.globl _stack16
_stack16:
diff --git a/gpxe/src/arch/i386/core/start32.S b/gpxe/src/arch/i386/core/start32.S
deleted file mode 100644
index 37ef5eb9..00000000
--- a/gpxe/src/arch/i386/core/start32.S
+++ /dev/null
@@ -1,325 +0,0 @@
-#include "virtaddr.h"
-
- .equ MSR_K6_EFER, 0xC0000080
- .equ EFER_LME, 0x00000100
- .equ X86_CR4_PAE, 0x00000020
- .equ CR0_PG, 0x80000000
-
-#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
-
-/*
- * NOTE: if you write a subroutine that is called from C code (gcc/egcs),
- * then you only have to take care of %ebx, %esi, %edi and %ebp. These
- * registers must not be altered under any circumstance. All other registers
- * may be clobbered without any negative side effects. If you don't follow
- * this rule then you'll run into strange effects that only occur on some
- * gcc versions (because the register allocator may use different registers).
- *
- * All the data32 prefixes for the ljmp instructions are necessary, because
- * the assembler emits code with a relocation address of 0. This means that
- * all destinations are initially negative, which the assembler doesn't grok,
- * because for some reason negative numbers don't fit into 16 bits. The addr32
- * prefixes are there for the same reasons, because otherwise the memory
- * references are only 16 bit wide. Theoretically they are all superfluous.
- * One last note about prefixes: the data32 prefixes on all call _real_to_prot
- * instructions could be removed if the _real_to_prot function is changed to
- * deal correctly with 16 bit return addresses. I tried it, but failed.
- */
-
- .text
- .arch i386
- .code32
-
- /* This is a struct os_entry_regs */
- .globl os_regs
-os_regs: .space 56
-
-/**************************************************************************
-XSTART32 - Transfer control to the kernel just loaded
-**************************************************************************/
- .globl xstart32
-xstart32:
- /* Save the callee save registers */
- movl %ebp, os_regs + 32
- movl %esi, os_regs + 36
- movl %edi, os_regs + 40
- movl %ebx, os_regs + 44
-
- /* save the return address */
- popl %eax
- movl %eax, os_regs + 48
-
- /* save the stack pointer */
- movl %esp, os_regs + 52
-
- /* Get the new destination address */
- popl %ecx
-
- /* Store the physical address of xend on the stack */
- movl $xend32, %ebx
- addl virt_offset, %ebx
- pushl %ebx
-
- /* Store the destination address on the stack */
- pushl $PHYSICAL_CS
- pushl %ecx
-
- /* Cache virt_offset */
- movl virt_offset, %ebp
-
- /* Switch to using physical addresses */
- call _virt_to_phys
-
- /* Save the target stack pointer */
- movl %esp, os_regs + 12(%ebp)
- leal os_regs(%ebp), %esp
-
- /* Store the pointer to os_regs */
- movl %esp, os_regs_ptr(%ebp)
-
- /* Load my new registers */
- popal
- movl (-32 + 12)(%esp), %esp
-
- /* Jump to the new kernel
- * The lret switches to a flat code segment
- */
- lret
-
- .balign 4
- .globl xend32
-xend32:
- /* Fixup %eflags */
- nop
- cli
- cld
-
- /* Load %esp with &os_regs + virt_offset */
- .byte 0xbc /* movl $0, %esp */
-os_regs_ptr:
- .long 0
-
- /* Save the result registers */
- addl $32, %esp
- pushal
-
- /* Compute virt_offset */
- movl %esp, %ebp
- subl $os_regs, %ebp
-
- /* Load the stack pointer and convert it to physical address */
- movl 52(%esp), %esp
- addl %ebp, %esp
-
- /* Enable the virtual addresses */
- leal _phys_to_virt(%ebp), %eax
- call *%eax
-
- /* Restore the callee save registers */
- movl os_regs + 32, %ebp
- movl os_regs + 36, %esi
- movl os_regs + 40, %edi
- movl os_regs + 44, %ebx
- movl os_regs + 48, %edx
- movl os_regs + 52, %esp
-
- /* Get the C return value */
- movl os_regs + 28, %eax
-
- jmpl *%edx
-
-#ifdef CONFIG_X86_64
- .arch sledgehammer
-/**************************************************************************
-XSTART_lm - Transfer control to the kernel just loaded in long mode
-**************************************************************************/
- .globl xstart_lm
-xstart_lm:
- /* Save the callee save registers */
- pushl %ebp
- pushl %esi
- pushl %edi
- pushl %ebx
-
- /* Cache virt_offset && (virt_offset & 0xfffff000) */
- movl virt_offset, %ebp
- movl %ebp, %ebx
- andl $0xfffff000, %ebx
-
- /* Switch to using physical addresses */
- call _virt_to_phys
-
- /* Initialize the page tables */
- /* Level 4 */
- leal 0x23 + pgt_level3(%ebx), %eax
- leal pgt_level4(%ebx), %edi
- movl %eax, (%edi)
-
- /* Level 3 */
- leal 0x23 + pgt_level2(%ebx), %eax
- leal pgt_level3(%ebx), %edi
- movl %eax, 0x00(%edi)
- addl $4096, %eax
- movl %eax, 0x08(%edi)
- addl $4096, %eax
- movl %eax, 0x10(%edi)
- addl $4096, %eax
- movl %eax, 0x18(%edi)
-
- /* Level 2 */
- movl $0xe3, %eax
- leal pgt_level2(%ebx), %edi
- leal 16384(%edi), %esi
-pgt_level2_loop:
- movl %eax, (%edi)
- addl $8, %edi
- addl $0x200000, %eax
- cmp %esi, %edi
- jne pgt_level2_loop
-
- /* Point at the x86_64 page tables */
- leal pgt_level4(%ebx), %edi
- movl %edi, %cr3
-
-
- /* Setup for the return from 64bit mode */
- /* 64bit align the stack */
- movl %esp, %ebx /* original stack pointer + 16 */
- andl $0xfffffff8, %esp
-
- /* Save original stack pointer + 16 */
- pushl %ebx
-
- /* Save virt_offset */
- pushl %ebp
-
- /* Setup for the jmp to 64bit long mode */
- leal start_lm(%ebp), %eax
- movl %eax, 0x00 + start_lm_addr(%ebp)
- movl $LM_CODE_SEG, %eax
- movl %eax, 0x04 + start_lm_addr(%ebp)
-
- /* Setup for the jump out of 64bit long mode */
- leal end_lm(%ebp), %eax
- movl %eax, 0x00 + end_lm_addr(%ebp)
- movl $FLAT_CODE_SEG, %eax
- movl %eax, 0x04 + end_lm_addr(%ebp)
-
- /* Enable PAE mode */
- movl %cr4, %eax
- orl $X86_CR4_PAE, %eax
- movl %eax, %cr4
-
- /* Enable long mode */
- movl $MSR_K6_EFER, %ecx
- rdmsr
- orl $EFER_LME, %eax
- wrmsr
-
- /* Start paging, entering 32bit compatiblity mode */
- movl %cr0, %eax
- orl $CR0_PG, %eax
- movl %eax, %cr0
-
- /* Enter 64bit long mode */
- ljmp *start_lm_addr(%ebp)
- .code64
-start_lm:
- /* Load 64bit data segments */
- movl $LM_DATA_SEG, %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %ss
-
- andq $0xffffffff, %rbx
- /* Get the address to jump to */
- movl 20(%rbx), %edx
- andq $0xffffffff, %rdx
-
- /* Get the argument pointer */
- movl 24(%rbx), %ebx
- andq $0xffffffff, %rbx
-
- /* Jump to the 64bit code */
- call *%rdx
-
- /* Preserve the result */
- movl %eax, %edx
-
- /* Fixup %eflags */
- cli
- cld
-
- /* Switch to 32bit compatibility mode */
- ljmp *end_lm_addr(%rip)
-
- .code32
-end_lm:
- /* 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
-
- /* Compute virt_offset */
- popl %ebp
-
- /* Compute the original stack pointer + 16 */
- popl %ebx
- movl %ebx, %esp
-
- /* Enable the virtual addresses */
- leal _phys_to_virt(%ebp), %eax
- call *%eax
-
- /* Restore the callee save registers */
- popl %ebx
- popl %esi
- popl %edi
- popl %ebp
-
- /* Get the C return value */
- movl %edx, %eax
-
- /* Return */
- ret
-
- .arch i386
-#endif /* CONFIG_X86_64 */
-
-#ifdef CONFIG_X86_64
- .section ".bss"
- .p2align 12
- /* Include a dummy space in case we are loaded badly aligned */
- .space 4096
- /* Reserve enough space for a page table convering 4GB with 2MB pages */
-pgt_level4:
- .space 4096
-pgt_level3:
- .space 4096
-pgt_level2:
- .space 16384
-start_lm_addr:
- .space 8
-end_lm_addr:
- .space 8
-#endif
diff --git a/gpxe/src/arch/i386/core/i386_timer.c b/gpxe/src/arch/i386/core/timer2.c
index 8f90ae05..bb589ecc 100644
--- a/gpxe/src/arch/i386/core/i386_timer.c
+++ b/gpxe/src/arch/i386/core/timer2.c
@@ -12,12 +12,11 @@
*/
#include <stddef.h>
-#include <bits/timer2.h>
-#include <gpxe/timer.h>
-#include <io.h>
+#include <gpxe/timer2.h>
+#include <gpxe/io.h>
/* Timers tick over at this rate */
-#define TIMER2_TICK_RATE 1193180U
+#define TIMER2_TICKS_PER_SEC 1193180U
/* Parallel Peripheral Controller Port B */
#define PPC_PORTB 0x61
@@ -52,8 +51,7 @@
#define BINARY_COUNT 0x00
#define BCD_COUNT 0x01
-static void load_timer2(unsigned int ticks)
-{
+static void load_timer2 ( unsigned int ticks ) {
/*
* Now let's take care of PPC channel 2
*
@@ -75,15 +73,13 @@ static void load_timer2(unsigned int ticks)
outb(ticks >> 8, TIMER2_PORT);
}
-static int timer2_running(void)
-{
+static int timer2_running ( void ) {
return ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
}
-void i386_timer2_udelay(unsigned int usecs)
-{
- load_timer2((usecs * TIMER2_TICK_RATE)/USECS_IN_SEC);
- while (timer2_running())
- ;
+void timer2_udelay ( unsigned long usecs ) {
+ load_timer2 ( ( usecs * TIMER2_TICKS_PER_SEC ) / ( 1000 * 1000 ) );
+ while (timer2_running()) {
+ /* Do nothing */
+ }
}
-
diff --git a/gpxe/src/arch/i386/core/video_subr.c b/gpxe/src/arch/i386/core/video_subr.c
index bf82cc61..c821cd02 100644
--- a/gpxe/src/arch/i386/core/video_subr.c
+++ b/gpxe/src/arch/i386/core/video_subr.c
@@ -7,7 +7,7 @@
#include "stddef.h"
#include "string.h"
-#include "io.h"
+#include <gpxe/io.h>
#include "console.h"
#include <gpxe/init.h>
#include "vga.h"
diff --git a/gpxe/src/arch/i386/core/virtaddr.S b/gpxe/src/arch/i386/core/virtaddr.S
index 5d762375..cf6da4f6 100644
--- a/gpxe/src/arch/i386/core/virtaddr.S
+++ b/gpxe/src/arch/i386/core/virtaddr.S
@@ -4,7 +4,7 @@
*
*/
-#include "virtaddr.h"
+#include "librm.h"
.arch i386
.text
diff --git a/gpxe/src/arch/i386/core/x86_io.c b/gpxe/src/arch/i386/core/x86_io.c
new file mode 100644
index 00000000..424a96cc
--- /dev/null
+++ b/gpxe/src/arch/i386/core/x86_io.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include <gpxe/io.h>
+#include <gpxe/x86_io.h>
+
+/** @file
+ *
+ * gPXE I/O API for x86
+ *
+ */
+
+/**
+ * Read 64-bit qword from memory-mapped device
+ *
+ * @v io_addr I/O address
+ * @ret data Value read
+ *
+ * This routine uses MMX instructions.
+ */
+static uint64_t x86_readq ( volatile uint64_t *io_addr ) {
+ uint64_t data;
+ __asm__ __volatile__ ( "pushl %%edx\n\t"
+ "pushl %%eax\n\t"
+ "movq (%1), %%mm0\n\t"
+ "movq %%mm0, (%%esp)\n\t"
+ "popl %%eax\n\t"
+ "popl %%edx\n\t"
+ "emms\n\t"
+ : "=A" ( data ) : "r" ( io_addr ) );
+ return data;
+}
+
+/**
+ * Write 64-bit qword to memory-mapped device
+ *
+ * @v data Value to write
+ * @v io_addr I/O address
+ *
+ * This routine uses MMX instructions.
+ */
+static void x86_writeq ( uint64_t data, volatile uint64_t *io_addr ) {
+ __asm__ __volatile__ ( "pushl %%edx\n\t"
+ "pushl %%eax\n\t"
+ "movq (%%esp), %%mm0\n\t"
+ "movq %%mm0, (%1)\n\t"
+ "popl %%eax\n\t"
+ "popl %%edx\n\t"
+ "emms\n\t"
+ : : "A" ( data ), "r" ( io_addr ) );
+}
+
+PROVIDE_IOAPI_INLINE ( x86, phys_to_bus );
+PROVIDE_IOAPI_INLINE ( x86, bus_to_phys );
+PROVIDE_IOAPI_INLINE ( x86, ioremap );
+PROVIDE_IOAPI_INLINE ( x86, iounmap );
+PROVIDE_IOAPI_INLINE ( x86, io_to_bus );
+PROVIDE_IOAPI_INLINE ( x86, readb );
+PROVIDE_IOAPI_INLINE ( x86, readw );
+PROVIDE_IOAPI_INLINE ( x86, readl );
+PROVIDE_IOAPI ( x86, readq, x86_readq );
+PROVIDE_IOAPI_INLINE ( x86, writeb );
+PROVIDE_IOAPI_INLINE ( x86, writew );
+PROVIDE_IOAPI_INLINE ( x86, writel );
+PROVIDE_IOAPI ( x86, writeq, x86_writeq );
+PROVIDE_IOAPI_INLINE ( x86, inb );
+PROVIDE_IOAPI_INLINE ( x86, inw );
+PROVIDE_IOAPI_INLINE ( x86, inl );
+PROVIDE_IOAPI_INLINE ( x86, outb );
+PROVIDE_IOAPI_INLINE ( x86, outw );
+PROVIDE_IOAPI_INLINE ( x86, outl );
+PROVIDE_IOAPI_INLINE ( x86, insb );
+PROVIDE_IOAPI_INLINE ( x86, insw );
+PROVIDE_IOAPI_INLINE ( x86, insl );
+PROVIDE_IOAPI_INLINE ( x86, outsb );
+PROVIDE_IOAPI_INLINE ( x86, outsw );
+PROVIDE_IOAPI_INLINE ( x86, outsl );
+PROVIDE_IOAPI_INLINE ( x86, iodelay );
+PROVIDE_IOAPI_INLINE ( x86, mb );
diff --git a/gpxe/src/arch/i386/drivers/net/undiisr.S b/gpxe/src/arch/i386/drivers/net/undiisr.S
index a6c6c381..2b31b414 100644
--- a/gpxe/src/arch/i386/drivers/net/undiisr.S
+++ b/gpxe/src/arch/i386/drivers/net/undiisr.S
@@ -10,11 +10,9 @@
.text
.arch i386
- .section ".text16", "ax", @progbits
- .section ".data16", "aw", @progbits
.code16
- .section ".text16"
+ .section ".text16", "ax", @progbits
.globl undiisr
undiisr:
@@ -75,7 +73,7 @@ exit: /* Restore registers and return */
popw %ds
iret
- .section ".data16"
+ .section ".data16", "aw", @progbits
undinet_params:
status: .word 0
funcflag: .word 0
diff --git a/gpxe/src/arch/i386/drivers/net/undinet.c b/gpxe/src/arch/i386/drivers/net/undinet.c
index 9576ad60..d6db6f7c 100644
--- a/gpxe/src/arch/i386/drivers/net/undinet.c
+++ b/gpxe/src/arch/i386/drivers/net/undinet.c
@@ -23,6 +23,7 @@
#include <biosint.h>
#include <pnpbios.h>
#include <basemem_packet.h>
+#include <gpxe/io.h>
#include <gpxe/iobuf.h>
#include <gpxe/netdevice.h>
#include <gpxe/if_ether.h>
@@ -481,8 +482,7 @@ static void undinet_poll ( struct net_device *netdev ) {
undi_isr.Frame.offset, frag_len );
if ( iob_len ( iobuf ) == len ) {
/* Whole packet received; deliver it */
- netdev_rx ( netdev, iobuf );
- iobuf = NULL;
+ netdev_rx ( netdev, iob_disown ( iobuf ) );
/* Etherboot 5.4 fails to return all packets
* under mild load; pretend it retriggered.
*/
@@ -554,7 +554,7 @@ static int undinet_open ( struct net_device *netdev ) {
DBGC ( undinic, "UNDINIC %p opened\n", undinic );
return 0;
-err:
+ err:
undinet_close ( netdev );
return rc;
}
@@ -595,10 +595,6 @@ static void undinet_close ( struct net_device *netdev ) {
/* Disable interrupt and unhook ISR */
disable_irq ( undinic->irq );
undinet_unhook_isr ( undinic->irq );
-#if 0
- enable_irq ( undinic->irq );
- send_eoi ( undinic->irq );
-#endif
DBGC ( undinic, "UNDINIC %p closed\n", undinic );
}
@@ -642,9 +638,7 @@ int undinet_probe ( struct undi_device *undi ) {
struct s_PXENV_UNDI_GET_IFACE_INFO undi_iface;
struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
struct s_PXENV_UNDI_CLEANUP undi_cleanup;
-#if 0
struct s_PXENV_STOP_UNDI stop_undi;
-#endif
int rc;
/* Allocate net device */
@@ -671,20 +665,23 @@ int undinet_probe ( struct undi_device *undi ) {
&start_undi,
sizeof ( start_undi ) ) ) != 0 )
goto err_start_undi;
- /* Bring up UNDI stack */
+ }
+ undi->flags |= UNDI_FL_STARTED;
+
+ /* 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 )
- goto err_undi_startup;
-
+ 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 )
- goto err_undi_initialize;
+ sizeof ( undi_initialize ))) != 0 )
+ goto err_undi_initialize;
}
- undi->flags |= UNDI_FL_STARTED;
+ undi->flags |= UNDI_FL_INITIALIZED;
/* Get device information */
memset ( &undi_info, 0, sizeof ( undi_info ) );
@@ -707,7 +704,7 @@ int undinet_probe ( struct undi_device *undi ) {
&undi_iface,
sizeof ( undi_iface ) ) ) != 0 )
goto err_undi_get_iface_info;
- DBGC ( undinic, "UNDINIC %p has type %s and link speed %ld\n",
+ DBGC ( undinic, "UNDINIC %p has type %s and link speed %d\n",
undinic, undi_iface.IfaceType, undi_iface.LinkSpeed );
if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
sizeof ( undi_iface.IfaceType ) ) == 0 ) {
@@ -731,7 +728,6 @@ int undinet_probe ( struct undi_device *undi ) {
err_bad_irq:
err_undi_get_information:
err_undi_initialize:
-
/* Shut down UNDI stack */
memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
undinet_call ( undinic, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
@@ -739,13 +735,13 @@ int undinet_probe ( struct undi_device *undi ) {
memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
sizeof ( undi_cleanup ) );
+ undi->flags &= ~UNDI_FL_INITIALIZED;
err_undi_startup:
-#if 0
/* Unhook UNDI stack */
memset ( &stop_undi, 0, sizeof ( stop_undi ) );
undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
sizeof ( stop_undi ) );
-#endif
+ undi->flags &= ~UNDI_FL_STARTED;
err_start_undi:
netdev_nullify ( netdev );
netdev_put ( netdev );
@@ -761,30 +757,33 @@ int undinet_probe ( struct undi_device *undi ) {
void undinet_remove ( struct undi_device *undi ) {
struct net_device *netdev = undi_get_drvdata ( undi );
struct undi_nic *undinic = netdev->priv;
-#if 0
struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
struct s_PXENV_UNDI_CLEANUP undi_cleanup;
struct s_PXENV_STOP_UNDI stop_undi;
-#endif
/* Unregister net device */
unregister_netdev ( netdev );
- /* Shut down UNDI stack */
-#if 0
- memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
- undinet_call ( undinic, 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 ) );
-
- /* Unhook UNDI stack */
- memset ( &stop_undi, 0, sizeof ( stop_undi ) );
- undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
- sizeof ( stop_undi ) );
- undi->flags &= ~UNDI_FL_STARTED;
-#endif
+ /* If we are preparing for an OS boot, or if we cannot exit
+ * via the PXE stack, then shut down the PXE stack.
+ */
+ if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) {
+
+ /* Shut down UNDI stack */
+ memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
+ undinet_call ( undinic, 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 ) );
+ 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 ) );
+ undi->flags &= ~UNDI_FL_STARTED;
+ }
/* Clear entry point */
memset ( &undinet_entry_point, 0, sizeof ( undinet_entry_point ) );
diff --git a/gpxe/src/arch/i386/drivers/net/undionly.c b/gpxe/src/arch/i386/drivers/net/undionly.c
index ee361493..4cdce677 100644
--- a/gpxe/src/arch/i386/drivers/net/undionly.c
+++ b/gpxe/src/arch/i386/drivers/net/undionly.c
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <string.h>
#include <gpxe/device.h>
+#include <gpxe/init.h>
#include <undi.h>
#include <undinet.h>
#include <undipreload.h>
@@ -107,3 +108,20 @@ struct root_device undi_root_device __root_device = {
.dev = { .name = "UNDI" },
.driver = &undi_root_driver,
};
+
+/**
+ * Prepare for exit
+ *
+ * @v flags Shutdown flags
+ */
+static void undionly_shutdown ( int flags ) {
+ /* If we are shutting down to boot an OS, clear the "keep PXE
+ * stack" flag.
+ */
+ if ( flags & SHUTDOWN_BOOT )
+ preloaded_undi.flags &= ~UNDI_FL_KEEP_ALL;
+}
+
+struct startup_fn startup_undionly __startup_fn ( STARTUP_LATE ) = {
+ .shutdown = undionly_shutdown,
+};
diff --git a/gpxe/src/arch/i386/drivers/net/undirom.c b/gpxe/src/arch/i386/drivers/net/undirom.c
index d40fcd35..e5782781 100644
--- a/gpxe/src/arch/i386/drivers/net/undirom.c
+++ b/gpxe/src/arch/i386/drivers/net/undirom.c
@@ -52,7 +52,7 @@ static int undirom_parse_pxeromid ( struct undi_rom *undirom,
sizeof ( undi_rom_id ) );
if ( undi_rom_id.Signature != UNDI_ROM_ID_SIGNATURE ) {
DBGC ( undirom, "UNDIROM %p has bad PXE ROM ID signature "
- "%08lx\n", undirom, undi_rom_id.Signature );
+ "%08x\n", undirom, undi_rom_id.Signature );
return -EINVAL;
}
@@ -94,7 +94,7 @@ static int undirom_parse_pcirheader ( struct undi_rom *undirom,
sizeof ( pcir_header ) );
if ( pcir_header.signature != PCIR_SIGNATURE ) {
DBGC ( undirom, "UNDIROM %p has bad PCI expansion header "
- "signature %08lx\n", undirom, pcir_header.signature );
+ "signature %08x\n", undirom, pcir_header.signature );
return -EINVAL;
}
diff --git a/gpxe/src/arch/i386/drivers/timer_bios.c b/gpxe/src/arch/i386/drivers/timer_bios.c
deleted file mode 100644
index f9caf8d9..00000000
--- a/gpxe/src/arch/i386/drivers/timer_bios.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Etherboot routines for PCBIOS firmware.
- *
- * Body of routines taken from old pcbios.S
- */
-
-#include <gpxe/init.h>
-#include <gpxe/timer.h>
-#include <stdio.h>
-#include <realmode.h>
-#include <bios.h>
-#include <bits/timer2.h>
-
-/* A bit faster actually, but we don't care. */
-#define TIMER2_TICKS_PER_SEC 18
-
-/*
- * Use direct memory access to BIOS variables, longword 0040:006C (ticks
- * today) and byte 0040:0070 (midnight crossover flag) instead of calling
- * timeofday BIOS interrupt.
- */
-
-static tick_t bios_currticks ( void ) {
- static int days = 0;
- uint32_t ticks;
- uint8_t midnight;
-
- /* Re-enable interrupts so that the timer interrupt can occur */
- __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
- "nop\n\t"
- "nop\n\t"
- "cli\n\t" ) : : );
-
- get_real ( ticks, BDA_SEG, 0x006c );
- get_real ( midnight, BDA_SEG, 0x0070 );
-
- if ( midnight ) {
- midnight = 0;
- put_real ( midnight, BDA_SEG, 0x0070 );
- days += 0x1800b0;
- }
-
- return ( (days + ticks) * (USECS_IN_SEC / TIMER2_TICKS_PER_SEC) );
-}
-
-static int bios_ts_init(void)
-{
- DBG("BIOS timer installed\n");
- return 0;
-}
-
-struct timer bios_ts __timer ( 02 ) = {
- .init = bios_ts_init,
- .udelay = i386_timer2_udelay,
- .currticks = bios_currticks,
-};
-
diff --git a/gpxe/src/arch/i386/drivers/timer_rdtsc.c b/gpxe/src/arch/i386/drivers/timer_rdtsc.c
deleted file mode 100644
index 09b7df2f..00000000
--- a/gpxe/src/arch/i386/drivers/timer_rdtsc.c
+++ /dev/null
@@ -1,69 +0,0 @@
-
-#include <gpxe/init.h>
-#include <gpxe/timer.h>
-#include <errno.h>
-#include <stdio.h>
-#include <bits/cpu.h>
-#include <bits/timer2.h>
-#include <io.h>
-
-
-#define rdtsc(low,high) \
- __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
-
-#define rdtscll(val) \
- __asm__ __volatile__ ("rdtsc" : "=A" (val))
-
-
-/* Measure how many clocks we get in one microsecond */
-static inline uint64_t calibrate_tsc(void)
-{
-
- uint64_t rdtsc_start;
- uint64_t rdtsc_end;
-
- rdtscll(rdtsc_start);
- i386_timer2_udelay(USECS_IN_MSEC);
- rdtscll(rdtsc_end);
-
- return (rdtsc_end - rdtsc_start) / USECS_IN_MSEC;
-}
-
-static uint32_t clocks_per_usec = 0;
-
-/* We measure time in microseconds. */
-static tick_t rdtsc_currticks(void)
-{
- uint64_t clocks;
-
- /* Read the Time Stamp Counter */
- rdtscll(clocks);
-
- return clocks / clocks_per_usec;
-}
-
-static int rdtsc_ts_init(void)
-{
-
- struct cpuinfo_x86 cpu_info;
-
- get_cpuinfo(&cpu_info);
- if (cpu_info.features & X86_FEATURE_TSC) {
- clocks_per_usec= calibrate_tsc();
- if (clocks_per_usec) {
- DBG("RDTSC ticksource installed. CPU running at %ld Mhz\n",
- clocks_per_usec);
- return 0;
- }
- }
-
- DBG("RDTSC ticksource not available on this machine.\n");
- return -ENODEV;
-}
-
-struct timer rdtsc_ts __timer (01) = {
- .init = rdtsc_ts_init,
- .udelay = generic_currticks_udelay,
- .currticks = rdtsc_currticks,
-};
-
diff --git a/gpxe/src/arch/i386/firmware/pcbios/bios_console.c b/gpxe/src/arch/i386/firmware/pcbios/bios_console.c
index dcb0462a..91363772 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/bios_console.c
+++ b/gpxe/src/arch/i386/firmware/pcbios/bios_console.c
@@ -193,13 +193,14 @@ static const char *ansi_input = "";
* dense range, so subtracting a constant and treating them as offsets
* into an array works efficiently.
*/
-#define BIOS_KEY_MIN 0x47
+#define BIOS_KEY_MIN 0x42
/** Offset into list of interesting BIOS scancodes */
#define BIOS_KEY(scancode) ( (scancode) - BIOS_KEY_MIN )
/** Mapping from BIOS scan codes to ANSI escape sequences */
static const char *ansi_sequences[] = {
+ [ BIOS_KEY ( 0x42 ) ] = "[19~", /* F8 (required for PXE) */
[ BIOS_KEY ( 0x47 ) ] = "[H", /* Home */
[ BIOS_KEY ( 0x48 ) ] = "[A", /* Up arrow */
[ BIOS_KEY ( 0x4b ) ] = "[D", /* Left arrow */
@@ -222,6 +223,7 @@ static const char * scancode_to_ansi_seq ( unsigned int scancode ) {
sizeof ( ansi_sequences[0] ) ) ) {
return ansi_sequences[bios_key];
}
+ DBG ( "Unrecognised BIOS scancode %02x\n", scancode );
return NULL;
}
diff --git a/gpxe/src/arch/i386/firmware/pcbios/e820mangler.S b/gpxe/src/arch/i386/firmware/pcbios/e820mangler.S
index 4fbd6563..4ba3fb14 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/e820mangler.S
+++ b/gpxe/src/arch/i386/firmware/pcbios/e820mangler.S
@@ -18,9 +18,6 @@
.text
.arch i386
- .section ".text16", "ax", @progbits
- .section ".data16", "aw", @progbits
- .section ".text16.data", "aw", @progbits
.code16
#define SMAP 0x534d4150
@@ -62,11 +59,11 @@
*
****************************************************************************
*/
- .section ".data16"
+ .section ".data16", "aw", @progbits
.align 16
.globl hidemem_base
.globl hidemem_umalloc
- .globl hidemem_text
+ .globl hidemem_textdata
memory_windows:
base_memory_window: .long 0x00000000, 0x00000000 /* Start of memory */
@@ -76,7 +73,7 @@ ext_memory_window: .long 0x000a0000, 0x00000000 /* 640kB mark */
hidemem_umalloc: .long 0xffffffff, 0xffffffff /* Changes at runtime */
.long 0xffffffff, 0xffffffff /* Changes at runtime */
-hidemem_text: .long 0xffffffff, 0xffffffff /* Changes at runtime */
+hidemem_textdata: .long 0xffffffff, 0xffffffff /* Changes at runtime */
.long 0xffffffff, 0xffffffff /* Changes at runtime */
.long 0xffffffff, 0xffffffff /* End of memory */
@@ -94,7 +91,7 @@ memory_windows_end:
* %ecx:%ebx Length of windowed region
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
window_region:
/* Convert (start,len) to (start, end) */
addl %eax, %ebx
@@ -132,7 +129,7 @@ window_region:
* %ax Modified memory above 1M in 1kB blocks
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
patch_1m:
pushal
/* Convert to (start,len) format and call truncate */
@@ -162,7 +159,7 @@ patch_1m:
* %bx Modified memory above 16M in 64kB blocks
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
patch_16m:
pushal
/* Convert to (start,len) format and call truncate */
@@ -193,7 +190,7 @@ patch_16m:
* %bx Modified memory above 16MB, in 64kB blocks
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
patch_1m_16m:
call patch_1m
call patch_16m
@@ -219,7 +216,7 @@ patch_1m_16m:
*
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
get_underlying_e820:
/* If the requested region is in the cache, return it */
@@ -268,8 +265,10 @@ get_underlying_e820:
pushl %ebx
pushl %ecx
pushl %edx
+ pushl %esi /* Some implementations corrupt %esi, so we */
+ pushl %edi /* preserve %esi, %edi and %ebp to be paranoid */
+ pushl %ebp
pushw %es
- pushw %di
pushw %ds
popw %es
movw $underlying_e820_cache, %di
@@ -280,8 +279,10 @@ get_underlying_e820:
stc
pushfw
lcall *%cs:int15_vector
- popw %di
popw %es
+ popl %ebp
+ popl %edi
+ popl %esi
/* Check for error return from underlying e820 call */
jc 2f /* CF set: error */
cmpl $SMAP, %eax
@@ -304,22 +305,22 @@ get_underlying_e820:
jmp get_underlying_e820
.size get_underlying_e820, . - get_underlying_e820
- .section ".data16"
+ .section ".data16", "aw", @progbits
underlying_e820_index:
.word 0xffff /* Initialise to an invalid value */
.size underlying_e820_index, . - underlying_e820_index
- .section ".bss16"
+ .section ".bss16", "aw", @nobits
underlying_e820_ebx:
.long 0
.size underlying_e820_ebx, . - underlying_e820_ebx
- .section ".bss16"
+ .section ".bss16", "aw", @nobits
underlying_e820_cache:
.space E820MAXSIZE
.size underlying_e820_cache, . - underlying_e820_cache
- .section ".bss16"
+ .section ".bss16", "aw", @nobits
underlying_e820_cache_size:
.long 0
.size underlying_e820_cache_size, . - underlying_e820_cache_size
@@ -338,7 +339,7 @@ underlying_e820_cache_size:
*
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
get_windowed_e820:
/* Preserve registers */
@@ -413,7 +414,7 @@ get_windowed_e820:
*
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
get_nonempty_e820:
/* Record entry parameters */
@@ -458,7 +459,7 @@ get_nonempty_e820:
*
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
get_mangled_e820:
/* Get a nonempty region */
@@ -492,7 +493,7 @@ get_mangled_e820:
* INT 15,e820 handler
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
int15_e820:
pushw %ds
pushw %cs:rm_ds
@@ -506,7 +507,7 @@ int15_e820:
* INT 15,e801 handler
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
int15_e801:
/* Call previous handler */
pushfw
@@ -532,7 +533,7 @@ int15_e801:
* INT 15,88 handler
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
int15_88:
/* Call previous handler */
pushfw
@@ -553,7 +554,7 @@ int15_88:
* INT 15 handler
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
.globl int15
int15:
/* See if we want to intercept this call */
@@ -576,7 +577,7 @@ int15:
ljmp *%cs:int15_vector
.size int15, . - int15
- .section ".text16.data"
+ .section ".text16.data", "aw", @progbits
.globl int15_vector
int15_vector:
.long 0
diff --git a/gpxe/src/arch/i386/firmware/pcbios/gateA20.c b/gpxe/src/arch/i386/firmware/pcbios/gateA20.c
index a14e3416..34e3ac52 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/gateA20.c
+++ b/gpxe/src/arch/i386/firmware/pcbios/gateA20.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <realmode.h>
#include <bios.h>
+#include <gpxe/io.h>
#include <gpxe/timer.h>
#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
@@ -48,9 +49,9 @@ static void empty_8042 ( void ) {
time = currticks() + TICKS_PER_SEC; /* max wait of 1 second */
while ( ( inb ( K_CMD ) & ( K_IBUF_FUL | K_OBUF_FUL ) ) &&
currticks() < time ) {
- SLOW_DOWN_IO;
- ( void ) inb ( K_RDWR );
- SLOW_DOWN_IO;
+ iodelay();
+ ( void ) inb_p ( K_RDWR );
+ iodelay();
}
}
@@ -77,7 +78,7 @@ static int gateA20_is_set ( int retries ) {
/* Avoid false negatives */
test_pattern++;
- SLOW_DOWN_IO;
+ iodelay();
/* Always retry at least once, to avoid false negatives */
} while ( retries-- >= 0 );
@@ -145,9 +146,9 @@ void gateA20_set ( void ) {
scp_a = inb ( SCP_A );
scp_a &= ~0x01; /* Avoid triggering a reset */
scp_a |= 0x02; /* Enable A20 */
- SLOW_DOWN_IO;
+ iodelay();
outb ( scp_a, SCP_A );
- SLOW_DOWN_IO;
+ iodelay();
if ( gateA20_is_set ( A20_SCPA_RETRIES ) ) {
DBG ( "Enabled gate A20 using "
"Fast Gate A20\n" );
diff --git a/gpxe/src/arch/i386/firmware/pcbios/hidemem.c b/gpxe/src/arch/i386/firmware/pcbios/hidemem.c
index c9df7bd0..620b62e0 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/hidemem.c
+++ b/gpxe/src/arch/i386/firmware/pcbios/hidemem.c
@@ -55,8 +55,8 @@ extern struct hidden_region __data16 ( hidemem_umalloc );
#define hidemem_umalloc __use_data16 ( hidemem_umalloc )
/** Hidden text memory */
-extern struct hidden_region __data16 ( hidemem_text );
-#define hidemem_text __use_data16 ( hidemem_text )
+extern struct hidden_region __data16 ( hidemem_textdata );
+#define hidemem_textdata __use_data16 ( hidemem_textdata )
/** Assembly routine in e820mangler.S */
extern void int15();
@@ -66,12 +66,12 @@ extern struct segoff __text16 ( int15_vector );
#define int15_vector __use_text16 ( int15_vector )
/* The linker defines these symbols for us */
-extern char _text[];
-extern char _end[];
-extern char _text16_size[];
-#define _text16_size ( ( unsigned int ) _text16_size )
-extern char _data16_size[];
-#define _data16_size ( ( unsigned int ) _data16_size )
+extern char _textdata[];
+extern char _etextdata[];
+extern char _text16_memsz[];
+#define _text16_memsz ( ( unsigned int ) _text16_memsz )
+extern char _data16_memsz[];
+#define _data16_memsz ( ( unsigned int ) _data16_memsz )
/**
* Hide region of memory from system memory map
@@ -110,7 +110,7 @@ void hide_basemem ( void ) {
*
*/
void hide_umalloc ( physaddr_t start, physaddr_t end ) {
- assert ( end <= virt_to_phys ( _text ) );
+ assert ( end <= virt_to_phys ( _textdata ) );
hide_region ( &hidemem_umalloc, start, end );
}
@@ -118,9 +118,9 @@ void hide_umalloc ( physaddr_t start, physaddr_t end ) {
* Hide .text and .data
*
*/
-void hide_text ( void ) {
- hide_region ( &hidemem_text, virt_to_phys ( _text ),
- virt_to_phys ( _end ) );
+void hide_textdata ( void ) {
+ hide_region ( &hidemem_textdata, virt_to_phys ( _textdata ),
+ virt_to_phys ( _etextdata ) );
}
/**
@@ -148,8 +148,8 @@ static void hide_etherboot ( void ) {
/* Initialise the hidden regions */
hide_basemem();
- hide_umalloc ( virt_to_phys ( _text ), virt_to_phys ( _text ) );
- hide_text();
+ hide_umalloc ( virt_to_phys ( _textdata ), virt_to_phys ( _textdata ) );
+ hide_textdata();
/* Some really moronic BIOSes bring up the PXE stack via the
* UNDI loader entry point and then don't bother to unload it
@@ -161,8 +161,8 @@ static void hide_etherboot ( void ) {
* We use a heuristic to guess whether or not we are being
* loaded sensibly.
*/
- rm_cs_top = ( ( ( rm_cs << 4 ) + _text16_size + 1024 - 1 ) >> 10 );
- rm_ds_top = ( ( ( rm_ds << 4 ) + _data16_size + 1024 - 1 ) >> 10 );
+ rm_cs_top = ( ( ( rm_cs << 4 ) + _text16_memsz + 1024 - 1 ) >> 10 );
+ rm_ds_top = ( ( ( rm_ds << 4 ) + _data16_memsz + 1024 - 1 ) >> 10 );
fbms = get_fbms();
if ( ( rm_cs_top < fbms ) && ( rm_ds_top < fbms ) ) {
DBG ( "Detected potentially unsafe UNDI load at CS=%04x "
diff --git a/gpxe/src/arch/i386/firmware/pcbios/memmap.c b/gpxe/src/arch/i386/firmware/pcbios/memmap.c
index 9de10a7a..ff387d93 100644
--- a/gpxe/src/arch/i386/firmware/pcbios/memmap.c
+++ b/gpxe/src/arch/i386/firmware/pcbios/memmap.c
@@ -158,7 +158,7 @@ static int meme820 ( struct memory_map *memmap ) {
uint32_t smap;
size_t size;
unsigned int flags;
- unsigned int discard_d, discard_D;
+ unsigned int discard_D;
/* Clear the E820 buffer. Do this once before starting,
* rather than on each call; some BIOSes rely on the contents
@@ -167,18 +167,24 @@ static int meme820 ( struct memory_map *memmap ) {
memset ( &e820buf, 0, sizeof ( e820buf ) );
do {
- __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
+ /* Some BIOSes corrupt %esi for fun. Guard against
+ * this by telling gcc that all non-output registers
+ * may be corrupted.
+ */
+ __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t"
+ "stc\n\t"
"int $0x15\n\t"
"pushfw\n\t"
- "popw %w0\n\t" )
- : "=r" ( flags ), "=a" ( smap ),
- "=b" ( next ), "=D" ( discard_D ),
- "=c" ( size ), "=d" ( discard_d )
+ "popw %%dx\n\t"
+ "popl %%ebp\n\t" )
+ : "=a" ( smap ), "=b" ( next ),
+ "=c" ( size ), "=d" ( flags ),
+ "=D" ( discard_D )
: "a" ( 0xe820 ), "b" ( next ),
"D" ( __from_data16 ( &e820buf ) ),
"c" ( sizeof ( e820buf ) ),
"d" ( SMAP )
- : "memory" );
+ : "esi", "memory" );
if ( smap != SMAP ) {
DBG ( "INT 15,e820 failed SMAP signature check\n" );
@@ -195,6 +201,13 @@ static int meme820 ( struct memory_map *memmap ) {
break;
}
+ /* If first region is not RAM, assume map is invalid */
+ if ( ( memmap->count == 0 ) &&
+ ( e820buf.type != E820_TYPE_RAM ) ) {
+ DBG ( "INT 15,e820 failed, first entry not RAM\n" );
+ return -EINVAL;
+ }
+
DBG ( "INT 15,e820 region [%llx,%llx) type %d",
e820buf.start, ( e820buf.start + e820buf.len ),
( int ) e820buf.type );
@@ -204,7 +217,7 @@ static int meme820 ( struct memory_map *memmap ) {
if ( e820buf.attrs & E820_ATTR_NONVOLATILE )
DBG ( ", non-volatile" );
if ( e820buf.attrs & E820_ATTR_UNKNOWN )
- DBG ( ", other [%08lx]", e820buf.attrs );
+ DBG ( ", other [%08x]", e820buf.attrs );
DBG ( ")" );
}
DBG ( "\n" );
diff --git a/gpxe/src/arch/i386/image/bzimage.c b/gpxe/src/arch/i386/image/bzimage.c
index e6fd854f..47d46ca4 100644
--- a/gpxe/src/arch/i386/image/bzimage.c
+++ b/gpxe/src/arch/i386/image/bzimage.c
@@ -400,7 +400,7 @@ static int bzimage_load_header ( struct image *image,
copy_from_user ( bzhdr, image->data, BZI_HDR_OFFSET,
sizeof ( *bzhdr ) );
if ( bzhdr->header != BZI_SIGNATURE ) {
- DBGC ( image, "bzImage %p bad signature %08lx\n",
+ DBGC ( image, "bzImage %p bad signature %08x\n",
image, bzhdr->header );
return -ENOEXEC;
}
diff --git a/gpxe/src/arch/i386/image/com32.c b/gpxe/src/arch/i386/image/com32.c
index da604625..d1b9a59f 100644
--- a/gpxe/src/arch/i386/image/com32.c
+++ b/gpxe/src/arch/i386/image/com32.c
@@ -52,7 +52,7 @@ static int com32_exec ( struct image *image ) {
int state;
uint32_t avail_mem_top;
- state = setjmp ( comboot_return );
+ state = rmsetjmp ( comboot_return );
switch ( state ) {
case 0: /* First time through; invoke COM32 program */
@@ -70,20 +70,20 @@ static int com32_exec ( struct image *image ) {
}
DBGC ( image, "COM32 %p: available memory top = 0x%x\n",
- image, (int)avail_mem_top );
+ image, avail_mem_top );
assert ( avail_mem_top != 0 );
com32_external_esp = phys_to_virt ( avail_mem_top );
/* Hook COMBOOT API interrupts */
- hook_comboot_interrupts( );
+ hook_comboot_interrupts();
- /* Temporarily de-register image, so that a "boot" command
- * doesn't throw us into an execution loop. Hold a reference
- * to avoid the image's being freed.
+ /* Unregister image, so that a "boot" command doesn't
+ * throw us into an execution loop. We never
+ * reregister ourselves; COMBOOT images expect to be
+ * removed on exit.
*/
- image_get ( image );
unregister_image ( image );
__asm__ __volatile__ (
@@ -111,25 +111,33 @@ static int com32_exec ( struct image *image ) {
/* %6 */ "r" ( COM32_START_PHYS )
:
"memory" );
+ DBGC ( image, "COM32 %p: returned\n", image );
break;
- case COMBOOT_RETURN_RUN_KERNEL:
- DBGC ( image, "COM32 %p: returned to run kernel...\n", image );
- comboot_run_kernel ( );
+ case COMBOOT_EXIT:
+ DBGC ( image, "COM32 %p: exited\n", image );
break;
- case COMBOOT_RETURN_EXIT:
+ case COMBOOT_EXIT_RUN_KERNEL:
+ DBGC ( image, "COM32 %p: exited to run kernel %p\n",
+ image, comboot_replacement_image );
+ image->replacement = comboot_replacement_image;
+ comboot_replacement_image = NULL;
+ image_autoload ( image->replacement );
break;
- }
-
- comboot_force_text_mode ( );
+ case COMBOOT_EXIT_COMMAND:
+ DBGC ( image, "COM32 %p: exited after executing command\n",
+ image );
+ break;
- DBGC ( image, "COM32 %p returned\n", image );
+ default:
+ assert ( 0 );
+ break;
+ }
- /* Re-register image and return */
- register_image ( image );
- image_put ( image );
+ unhook_comboot_interrupts();
+ comboot_force_text_mode();
return 0;
}
diff --git a/gpxe/src/arch/i386/image/comboot.c b/gpxe/src/arch/i386/image/comboot.c
index 63d02c0f..40e32185 100644
--- a/gpxe/src/arch/i386/image/comboot.c
+++ b/gpxe/src/arch/i386/image/comboot.c
@@ -133,7 +133,7 @@ static int comboot_exec ( struct image *image ) {
userptr_t seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 );
int state;
- state = setjmp ( comboot_return );
+ state = rmsetjmp ( comboot_return );
switch ( state ) {
case 0: /* First time through; invoke COMBOOT program */
@@ -142,16 +142,16 @@ static int comboot_exec ( struct image *image ) {
comboot_init_psp ( image, seg_userptr );
/* Hook COMBOOT API interrupts */
- hook_comboot_interrupts ( );
+ hook_comboot_interrupts();
DBGC ( image, "executing 16-bit COMBOOT image at %4x:0100\n",
- COMBOOT_PSP_SEG );
+ COMBOOT_PSP_SEG );
- /* Temporarily de-register image, so that a "boot" command
- * doesn't throw us into an execution loop. Hold a reference
- * to avoid the image's being freed.
+ /* Unregister image, so that a "boot" command doesn't
+ * throw us into an execution loop. We never
+ * reregister ourselves; COMBOOT images expect to be
+ * removed on exit.
*/
- image_get ( image );
unregister_image ( image );
/* Store stack segment at 0x38 and stack pointer at 0x3A
@@ -180,26 +180,34 @@ static int comboot_exec ( struct image *image ) {
"xorw %%bp, %%bp\n\t"
"lret\n\t" )
: : "r" ( COMBOOT_PSP_SEG ) : "eax" );
+ DBGC ( image, "COMBOOT %p: returned\n", image );
break;
- case COMBOOT_RETURN_RUN_KERNEL:
- DBGC ( image, "COMBOOT %p: returned to run kernel...\n", image );
- comboot_run_kernel ( );
+ case COMBOOT_EXIT:
+ DBGC ( image, "COMBOOT %p: exited\n", image );
break;
- case COMBOOT_RETURN_EXIT:
+ case COMBOOT_EXIT_RUN_KERNEL:
+ DBGC ( image, "COMBOOT %p: exited to run kernel %p\n",
+ image, comboot_replacement_image );
+ image->replacement = comboot_replacement_image;
+ comboot_replacement_image = NULL;
+ image_autoload ( image->replacement );
break;
- }
+ case COMBOOT_EXIT_COMMAND:
+ DBGC ( image, "COMBOOT %p: exited after executing command\n",
+ image );
+ break;
- comboot_force_text_mode ( );
+ default:
+ assert ( 0 );
+ break;
+ }
- DBGC ( image, "COMBOOT %p returned\n", image );
+ unhook_comboot_interrupts();
+ comboot_force_text_mode();
- /* Re-register image and return */
- register_image ( image );
- image_put ( image );
-
return 0;
}
diff --git a/gpxe/src/arch/i386/image/multiboot.c b/gpxe/src/arch/i386/image/multiboot.c
index a4a340fd..52bb10f6 100644
--- a/gpxe/src/arch/i386/image/multiboot.c
+++ b/gpxe/src/arch/i386/image/multiboot.c
@@ -220,7 +220,7 @@ multiboot_build_module_list ( struct image *image,
/* Dump module configuration */
for ( i = 0 ; i < count ; i++ ) {
- DBGC ( image, "MULTIBOOT %p module %d is [%lx,%lx)\n",
+ DBGC ( image, "MULTIBOOT %p module %d is [%x,%x)\n",
image, i, modules[i].mod_start,
modules[i].mod_end );
}
@@ -282,11 +282,13 @@ static int multiboot_exec ( struct image *image ) {
/* Jump to OS with flat physical addressing */
DBGC ( image, "MULTIBOOT %p starting execution at %lx\n",
image, entry );
- __asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" )
+ __asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t"
+ "call *%%edi\n\t"
+ "popl %%ebp\n\t" )
: : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
"b" ( virt_to_phys ( &mbinfo ) ),
"D" ( entry )
- : "ecx", "edx", "esi", "ebp", "memory" );
+ : "ecx", "edx", "esi", "memory" );
DBGC ( image, "MULTIBOOT %p returned\n", image );
@@ -416,7 +418,7 @@ static int multiboot_load ( struct image *image ) {
image );
return rc;
}
- DBGC ( image, "MULTIBOOT %p found header with flags %08lx\n",
+ DBGC ( image, "MULTIBOOT %p found header with flags %08x\n",
image, hdr.mb.flags );
/* This is a multiboot image, valid or otherwise */
@@ -425,7 +427,7 @@ static int multiboot_load ( struct image *image ) {
/* Abort if we detect flags that we cannot support */
if ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) {
- DBGC ( image, "MULTIBOOT %p flags %08lx not supported\n",
+ DBGC ( image, "MULTIBOOT %p flags %08x not supported\n",
image, ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) );
return -ENOTSUP;
}
diff --git a/gpxe/src/arch/i386/image/nbi.c b/gpxe/src/arch/i386/image/nbi.c
index e6a0ab0f..a4ee4420 100644
--- a/gpxe/src/arch/i386/image/nbi.c
+++ b/gpxe/src/arch/i386/image/nbi.c
@@ -367,22 +367,6 @@ static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) {
}
/**
- * Guess boot network device
- *
- * @ret netdev Boot network device
- */
-static struct net_device * guess_boot_netdev ( void ) {
- struct net_device *boot_netdev;
-
- /* Just use the first network device */
- for_each_netdev ( boot_netdev ) {
- return boot_netdev;
- }
-
- return NULL;
-}
-
-/**
* Prepare DHCP parameter block for NBI image
*
* @v image NBI image
@@ -392,7 +376,7 @@ static int nbi_prepare_dhcp ( struct image *image ) {
struct net_device *boot_netdev;
int rc;
- boot_netdev = guess_boot_netdev();
+ boot_netdev = last_opened_netdev();
if ( ! boot_netdev ) {
DBGC ( image, "NBI %p could not identify a network device\n",
image );
diff --git a/gpxe/src/arch/i386/image/pxe_image.c b/gpxe/src/arch/i386/image/pxe_image.c
index 77fa0469..90550d83 100644
--- a/gpxe/src/arch/i386/image/pxe_image.c
+++ b/gpxe/src/arch/i386/image/pxe_image.c
@@ -42,18 +42,14 @@ 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 first open network device to use for PXE */
- for_each_netdev ( netdev ) {
- pxe_set_netdev ( netdev );
- break;
- }
+ /* 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 ) {
@@ -92,6 +88,12 @@ int pxe_load ( struct image *image ) {
if ( filesz > ( 0xa0000 - 0x7c00 ) )
return -ENOEXEC;
+ /* Rejecting zero-length images is also useful, since these
+ * end up looking to the user like bugs in gPXE.
+ */
+ if ( ! filesz )
+ return -ENOEXEC;
+
/* There are no signature checks for PXE; we will accept anything */
if ( ! image->type )
image->type = &pxe_image_type;
diff --git a/gpxe/src/arch/i386/include/bios.h b/gpxe/src/arch/i386/include/bios.h
index 630a898b..979a092c 100644
--- a/gpxe/src/arch/i386/include/bios.h
+++ b/gpxe/src/arch/i386/include/bios.h
@@ -5,7 +5,4 @@
#define BDA_FBMS 0x0013
#define BDA_NUM_DRIVES 0x0075
-extern unsigned long currticks ( void );
-extern void cpu_nap ( void );
-
#endif /* BIOS_H */
diff --git a/gpxe/src/arch/i386/include/biosint.h b/gpxe/src/arch/i386/include/biosint.h
index d4e34963..d365cf01 100644
--- a/gpxe/src/arch/i386/include/biosint.h
+++ b/gpxe/src/arch/i386/include/biosint.h
@@ -6,9 +6,22 @@
*
*/
+#include <realmode.h>
+
struct segoff;
-extern int hooked_bios_interrupts;
+/**
+ * Hooked interrupt count
+ *
+ * At exit, after unhooking all possible interrupts, this counter
+ * should be examined. If it is non-zero, it means that we failed to
+ * unhook at least one interrupt vector, and so must not free up the
+ * memory we are using. (Note that this also implies that we should
+ * re-hook INT 15 in order to hide ourselves from the memory map).
+ */
+extern uint16_t __text16 ( hooked_bios_interrupts );
+#define hooked_bios_interrupts __use_text16 ( hooked_bios_interrupts )
+
extern void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
struct segoff *chain_vector );
extern int unhook_bios_interrupt ( unsigned int interrupt,
diff --git a/gpxe/src/arch/i386/include/bits/byteswap.h b/gpxe/src/arch/i386/include/bits/byteswap.h
index 54b93ab9..98418c29 100644
--- a/gpxe/src/arch/i386/include/bits/byteswap.h
+++ b/gpxe/src/arch/i386/include/bits/byteswap.h
@@ -2,7 +2,7 @@
#define ETHERBOOT_BITS_BYTESWAP_H
static inline __attribute__ ((always_inline, const)) uint16_t
-__i386_bswap_16(uint16_t x)
+__bswap_variable_16(uint16_t x)
{
__asm__("xchgb %b0,%h0\n\t"
: "=q" (x)
@@ -11,7 +11,7 @@ __i386_bswap_16(uint16_t x)
}
static inline __attribute__ ((always_inline, const)) uint32_t
-__i386_bswap_32(uint32_t x)
+__bswap_variable_32(uint32_t x)
{
__asm__("xchgb %b0,%h0\n\t"
"rorl $16,%0\n\t"
@@ -22,7 +22,7 @@ __i386_bswap_32(uint32_t x)
}
static inline __attribute__ ((always_inline, const)) uint64_t
-__i386_bswap_64(uint64_t x)
+__bswap_variable_64(uint64_t x)
{
union {
uint64_t qword;
@@ -30,47 +30,12 @@ __i386_bswap_64(uint64_t x)
} u;
u.qword = x;
- u.dword[0] = __i386_bswap_32(u.dword[0]);
- u.dword[1] = __i386_bswap_32(u.dword[1]);
+ u.dword[0] = __bswap_variable_32(u.dword[0]);
+ u.dword[1] = __bswap_variable_32(u.dword[1]);
__asm__("xchgl %0,%1"
: "=r" ( u.dword[0] ), "=r" ( u.dword[1] )
: "0" ( u.dword[0] ), "1" ( u.dword[1] ) );
return u.qword;
}
-#define __bswap_constant_16(x) \
- ((uint16_t)((((uint16_t)(x) & 0x00ff) << 8) | \
- (((uint16_t)(x) & 0xff00) >> 8)))
-
-#define __bswap_constant_32(x) \
- ((uint32_t)((((uint32_t)(x) & 0x000000ffU) << 24) | \
- (((uint32_t)(x) & 0x0000ff00U) << 8) | \
- (((uint32_t)(x) & 0x00ff0000U) >> 8) | \
- (((uint32_t)(x) & 0xff000000U) >> 24)))
-
-#define __bswap_constant_64(x) \
- ((uint64_t)((((uint64_t)(x) & 0x00000000000000ffULL) << 56) | \
- (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
- (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
- (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
- (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
- (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
- (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
- (((uint64_t)(x) & 0xff00000000000000ULL) >> 56)))
-
-#define __bswap_16(x) \
- ((uint16_t)(__builtin_constant_p(x) ? \
- __bswap_constant_16(x) : \
- __i386_bswap_16(x)))
-
-#define __bswap_32(x) \
- ((uint32_t)(__builtin_constant_p(x) ? \
- __bswap_constant_32(x) : \
- __i386_bswap_32(x)))
-
-#define __bswap_64(x) \
- ((uint64_t)(__builtin_constant_p(x) ? \
- __bswap_constant_64(x) : \
- __i386_bswap_64(x)))
-
#endif /* ETHERBOOT_BITS_BYTESWAP_H */
diff --git a/gpxe/src/arch/i386/include/bits/compiler.h b/gpxe/src/arch/i386/include/bits/compiler.h
new file mode 100644
index 00000000..119a9a21
--- /dev/null
+++ b/gpxe/src/arch/i386/include/bits/compiler.h
@@ -0,0 +1,25 @@
+#ifndef _BITS_COMPILER_H
+#define _BITS_COMPILER_H
+
+#ifndef ASSEMBLY
+
+/** Declare a function with standard calling conventions */
+#define __asmcall __attribute__ (( cdecl, regparm(0) ))
+
+/**
+ * Declare a function with libgcc implicit linkage
+ *
+ * It seems as though gcc expects its implicit arithmetic functions to
+ * be cdecl, even if -mrtd is specified. This is somewhat
+ * inconsistent; for example, if -mregparm=3 is used then the implicit
+ * functions do become regparm(3).
+ *
+ * The implicit calls to memcpy() and memset() which gcc can generate
+ * do not seem to have this inconsistency; -mregparm and -mrtd affect
+ * them in the same way as any other function.
+ */
+#define __libgcc __attribute__ (( cdecl ))
+
+#endif /* ASSEMBLY */
+
+#endif /* _BITS_COMPILER_H */
diff --git a/gpxe/src/arch/i386/include/bits/elf.h b/gpxe/src/arch/i386/include/bits/elf.h
deleted file mode 100644
index dad9c7b8..00000000
--- a/gpxe/src/arch/i386/include/bits/elf.h
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifndef I386_BITS_ELF_H
-#define I386_BITS_ELF_H
-
-#include "cpu.h"
-
-#ifdef CONFIG_X86_64
-/* ELF Defines for the 64bit version of the current architecture */
-#define EM_CURRENT_64 EM_X86_64
-#define EM_CURRENT_64_PRESENT ( \
- CPU_FEATURE_P(cpu_info.x86_capability, LM) && \
- CPU_FEATURE_P(cpu_info.x86_capability, PAE) && \
- CPU_FEATURE_P(cpu_info.x86_capability, PSE))
-
-#define ELF_CHECK_X86_64_ARCH(x) \
- (EM_CURRENT_64_PRESENT && ((x).e_machine == EM_X86_64))
-#define __unused_i386
-#else
-#define ELF_CHECK_X86_64_ARCH(x) 0
-#define __unused_i386 __unused
-#endif
-
-
-/* ELF Defines for the current architecture */
-#define EM_CURRENT EM_386
-#define ELFDATA_CURRENT ELFDATA2LSB
-
-#define ELF_CHECK_I386_ARCH(x) \
- (((x).e_machine == EM_386) || ((x).e_machine == EM_486))
-
-#define ELF_CHECK_ARCH(x) \
- ((ELF_CHECK_I386_ARCH(x) || ELF_CHECK_X86_64_ARCH(x)) && \
- ((x).e_entry <= 0xffffffffUL))
-
-#ifdef IMAGE_FREEBSD
-/*
- * FreeBSD has this rather strange "feature" of its design.
- * At some point in its evolution, FreeBSD started to rely
- * externally on private/static/debug internal symbol information.
- * That is, some of the interfaces that software uses to access
- * and work with the FreeBSD kernel are made available not
- * via the shared library symbol information (the .DYNAMIC section)
- * but rather the debug symbols. This means that any symbol, not
- * just publicly defined symbols can be (and are) used by system
- * tools to make the system work. (such as top, swapinfo, swapon,
- * etc)
- *
- * Even worse, however, is the fact that standard ELF loaders do
- * not know how to load the symbols since they are not within
- * an ELF PT_LOAD section. The kernel needs these symbols to
- * operate so the following changes/additions to the boot
- * loading of EtherBoot have been made to get the kernel to load.
- * All of the changes are within IMAGE_FREEBSD such that the
- * extra/changed code only compiles when FREEBSD support is
- * enabled.
- */
-
-/*
- * Section header for FreeBSD (debug symbol kludge!) support
- */
-typedef struct {
- Elf32_Word sh_name; /* Section name (index into the
- section header string table). */
- Elf32_Word sh_type; /* Section type. */
- Elf32_Word sh_flags; /* Section flags. */
- Elf32_Addr sh_addr; /* Address in memory image. */
- Elf32_Off sh_offset; /* Offset in file. */
- Elf32_Size sh_size; /* Size in bytes. */
- Elf32_Word sh_link; /* Index of a related section. */
- Elf32_Word sh_info; /* Depends on section type. */
- Elf32_Size sh_addralign; /* Alignment in bytes. */
- Elf32_Size sh_entsize; /* Size of each entry in section. */
-} Elf32_Shdr;
-
-/* sh_type */
-#define SHT_SYMTAB 2 /* symbol table section */
-#define SHT_STRTAB 3 /* string table section */
-
-/*
- * Module information subtypes (for the metadata that we need to build)
- */
-#define MODINFO_END 0x0000 /* End of list */
-#define MODINFO_NAME 0x0001 /* Name of module (string) */
-#define MODINFO_TYPE 0x0002 /* Type of module (string) */
-#define MODINFO_METADATA 0x8000 /* Module-specfic */
-
-#define MODINFOMD_SSYM 0x0003 /* start of symbols */
-#define MODINFOMD_ESYM 0x0004 /* end of symbols */
-
-#endif /* IMAGE_FREEBSD */
-
-#endif /* I386_BITS_ELF_H */
diff --git a/gpxe/src/arch/i386/include/bits/elf_x.h b/gpxe/src/arch/i386/include/bits/elf_x.h
deleted file mode 100644
index 86c67250..00000000
--- a/gpxe/src/arch/i386/include/bits/elf_x.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#define ARCH_ELF_CLASS ELFCLASS32
-#define ARCH_ELF_DATA ELFDATA2LSB
-#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_386 || (x)==EM_486)
-typedef Elf32_Ehdr Elf_ehdr;
-typedef Elf32_Phdr Elf_phdr;
diff --git a/gpxe/src/arch/i386/include/bits/errfile.h b/gpxe/src/arch/i386/include/bits/errfile.h
index 99927c28..5ea8a318 100644
--- a/gpxe/src/arch/i386/include/bits/errfile.h
+++ b/gpxe/src/arch/i386/include/bits/errfile.h
@@ -6,13 +6,12 @@
* @{
*/
-#define ERRFILE_umalloc ( ERRFILE_ARCH | ERRFILE_CORE | 0x00000000 )
+#define ERRFILE_memtop_umalloc ( ERRFILE_ARCH | ERRFILE_CORE | 0x00000000 )
#define ERRFILE_memmap ( ERRFILE_ARCH | ERRFILE_CORE | 0x00010000 )
#define ERRFILE_pnpbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00020000 )
-#define ERRFILE_smbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00030000 )
+#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_smbios_settings ( ERRFILE_ARCH | ERRFILE_CORE | 0x00060000 )
#define ERRFILE_bootsector ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
#define ERRFILE_bzimage ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )
@@ -24,6 +23,7 @@
#define ERRFILE_comboot ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00070000 )
#define ERRFILE_com32 ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00080000 )
#define ERRFILE_comboot_resolv ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00090000 )
+#define ERRFILE_comboot_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000a0000 )
#define ERRFILE_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 )
#define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 )
diff --git a/gpxe/src/arch/i386/include/bits/io.h b/gpxe/src/arch/i386/include/bits/io.h
new file mode 100644
index 00000000..dd0ee444
--- /dev/null
+++ b/gpxe/src/arch/i386/include/bits/io.h
@@ -0,0 +1,12 @@
+#ifndef _BITS_IO_H
+#define _BITS_IO_H
+
+/** @file
+ *
+ * i386-specific I/O API implementations
+ *
+ */
+
+#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
new file mode 100644
index 00000000..f8ba7a7c
--- /dev/null
+++ b/gpxe/src/arch/i386/include/bits/nap.h
@@ -0,0 +1,13 @@
+#ifndef _BITS_NAP_H
+#define _BITS_NAP_H
+
+/** @file
+ *
+ * i386-specific CPU sleeping API implementations
+ *
+ */
+
+#include <gpxe/bios_nap.h>
+#include <gpxe/efi/efix86_nap.h>
+
+#endif /* _BITS_MAP_H */
diff --git a/gpxe/src/arch/i386/include/bits/smbios.h b/gpxe/src/arch/i386/include/bits/smbios.h
new file mode 100644
index 00000000..647ea19e
--- /dev/null
+++ b/gpxe/src/arch/i386/include/bits/smbios.h
@@ -0,0 +1,12 @@
+#ifndef _BITS_SMBIOS_H
+#define _BITS_SMBIOS_H
+
+/** @file
+ *
+ * i386-specific SMBIOS API implementations
+ *
+ */
+
+#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 a2947cda..6ccf0971 100644
--- a/gpxe/src/arch/i386/include/bits/stdint.h
+++ b/gpxe/src/arch/i386/include/bits/stdint.h
@@ -1,18 +1,18 @@
#ifndef _BITS_STDINT_H
#define _BITS_STDINT_H
-typedef typeof(sizeof(int)) size_t;
-typedef signed long ssize_t;
+typedef unsigned int size_t;
+typedef signed int ssize_t;
typedef signed long off_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
-typedef unsigned long uint32_t;
+typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef signed char int8_t;
typedef signed short int16_t;
-typedef signed long int32_t;
+typedef signed int int32_t;
typedef signed long long int64_t;
typedef unsigned long physaddr_t;
diff --git a/gpxe/src/arch/i386/include/bits/timer.h b/gpxe/src/arch/i386/include/bits/timer.h
new file mode 100644
index 00000000..99666d84
--- /dev/null
+++ b/gpxe/src/arch/i386/include/bits/timer.h
@@ -0,0 +1,13 @@
+#ifndef _BITS_TIMER_H
+#define _BITS_TIMER_H
+
+/** @file
+ *
+ * i386-specific timer API implementations
+ *
+ */
+
+#include <gpxe/bios_timer.h>
+#include <gpxe/rdtsc_timer.h>
+
+#endif /* _BITS_TIMER_H */
diff --git a/gpxe/src/arch/i386/include/bits/timer2.h b/gpxe/src/arch/i386/include/bits/timer2.h
deleted file mode 100644
index 83923b29..00000000
--- a/gpxe/src/arch/i386/include/bits/timer2.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef BITS_TIMER2_H
-#define BITS_TIMER2_H
-
-#include <stddef.h>
-
-void i386_timer2_udelay(unsigned int usecs);
-
-#endif
diff --git a/gpxe/src/arch/i386/include/bits/uaccess.h b/gpxe/src/arch/i386/include/bits/uaccess.h
index 9c6d0c21..0ecc5028 100644
--- a/gpxe/src/arch/i386/include/bits/uaccess.h
+++ b/gpxe/src/arch/i386/include/bits/uaccess.h
@@ -1,6 +1,12 @@
#ifndef _BITS_UACCESS_H
#define _BITS_UACCESS_H
-#include <realmode.h>
+/** @file
+ *
+ * i386-specific user access API implementations
+ *
+ */
+
+#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
new file mode 100644
index 00000000..dcbd0a6b
--- /dev/null
+++ b/gpxe/src/arch/i386/include/bits/umalloc.h
@@ -0,0 +1,12 @@
+#ifndef _BITS_UMALLOC_H
+#define _BITS_UMALLOC_H
+
+/** @file
+ *
+ * i386-specific user memory allocation API implementations
+ *
+ */
+
+#include <gpxe/memtop_umalloc.h>
+
+#endif /* _BITS_UMALLOC_H */
diff --git a/gpxe/src/arch/i386/include/comboot.h b/gpxe/src/arch/i386/include/comboot.h
index 1fc3b718..56661a80 100644
--- a/gpxe/src/arch/i386/include/comboot.h
+++ b/gpxe/src/arch/i386/include/comboot.h
@@ -58,12 +58,47 @@ typedef struct {
} com32sys_t;
typedef struct {
+ uint32_t eax; /* Offset 0 */
+ uint32_t ecx; /* Offset 4 */
+ uint32_t edx; /* Offset 8 */
+ uint32_t ebx; /* Offset 12 */
+ uint32_t esp; /* Offset 16 */
+ uint32_t ebp; /* Offset 20 */
+ uint32_t esi; /* Offset 24 */
+ uint32_t edi; /* Offset 28 */
+
+ uint32_t eip; /* Offset 32 */
+} syslinux_pm_regs;
+
+typedef struct {
+ uint16_t es; /* Offset 0 */
+ uint16_t _unused_cs; /* Offset 2 */
+ uint16_t ds; /* Offset 4 */
+ uint16_t ss; /* Offset 6 */
+ uint16_t fs; /* Offset 8 */
+ uint16_t gs; /* Offset 10 */
+
+ uint32_t eax; /* Offset 12 */
+ uint32_t ecx; /* Offset 16 */
+ uint32_t edx; /* Offset 20 */
+ uint32_t ebx; /* Offset 24 */
+ uint32_t esp; /* Offset 28 */
+ uint32_t ebp; /* Offset 32 */
+ uint32_t esi; /* Offset 36 */
+ uint32_t edi; /* Offset 40 */
+
+ uint16_t ip; /* Offset 44 */
+ uint16_t cs; /* Offset 46 */
+} syslinux_rm_regs;
+
+typedef struct {
uint32_t dest;
uint32_t src;
uint32_t len;
} comboot_shuffle_descriptor;
extern void hook_comboot_interrupts ( );
+extern void unhook_comboot_interrupts ( );
/* These are not the correct prototypes, but it doens't matter,
* as we only ever get the address of these functions;
@@ -77,20 +112,16 @@ extern void com32_cfarcall_wrapper ( );
extern int comboot_resolv ( const char *name, struct in_addr *address );
/* setjmp/longjmp context buffer used to return after loading an image */
-extern jmp_buf comboot_return;
-
-/* Command line to execute when returning via comboot_return
- * with COMBOOT_RETURN_RUN_KERNEL
- */
-extern char *comboot_kernel_cmdline;
+extern rmjmp_buf comboot_return;
-/* Execute comboot_image_cmdline */
-extern void comboot_run_kernel ( );
+/* Replacement image when exiting with COMBOOT_EXIT_RUN_KERNEL */
+extern struct image *comboot_replacement_image;
extern void *com32_external_esp;
-#define COMBOOT_RETURN_EXIT 1
-#define COMBOOT_RETURN_RUN_KERNEL 2
+#define COMBOOT_EXIT 1
+#define COMBOOT_EXIT_RUN_KERNEL 2
+#define COMBOOT_EXIT_COMMAND 3
extern void comboot_force_text_mode ( void );
diff --git a/gpxe/src/arch/i386/include/gdbmach.h b/gpxe/src/arch/i386/include/gdbmach.h
index 1a38ccd1..794dab19 100644
--- a/gpxe/src/arch/i386/include/gdbmach.h
+++ b/gpxe/src/arch/i386/include/gdbmach.h
@@ -12,7 +12,7 @@
#include <stdint.h>
-typedef uint32_t gdbreg_t;
+typedef unsigned long gdbreg_t;
/* The register snapshot, this must be in sync with interrupt handler and the
* GDB protocol. */
diff --git a/gpxe/src/include/gpxe/abft.h b/gpxe/src/arch/i386/include/gpxe/abft.h
index 1c651ef1..1c651ef1 100644
--- a/gpxe/src/include/gpxe/abft.h
+++ b/gpxe/src/arch/i386/include/gpxe/abft.h
diff --git a/gpxe/src/arch/i386/include/gpxe/bios_nap.h b/gpxe/src/arch/i386/include/gpxe/bios_nap.h
new file mode 100644
index 00000000..f1c721e9
--- /dev/null
+++ b/gpxe/src/arch/i386/include/gpxe/bios_nap.h
@@ -0,0 +1,16 @@
+#ifndef _GPXE_BIOS_NAP_H
+#define _GPXE_BIOS_NAP_H
+
+/** @file
+ *
+ * BIOS CPU sleeping
+ *
+ */
+
+#ifdef NAP_PCBIOS
+#define NAP_PREFIX_pcbios
+#else
+#define NAP_PREFIX_pcbios __pcbios_
+#endif
+
+#endif /* _GPXE_BIOS_NAP_H */
diff --git a/gpxe/src/arch/i386/include/gpxe/bios_smbios.h b/gpxe/src/arch/i386/include/gpxe/bios_smbios.h
new file mode 100644
index 00000000..0a6f277a
--- /dev/null
+++ b/gpxe/src/arch/i386/include/gpxe/bios_smbios.h
@@ -0,0 +1,16 @@
+#ifndef _GPXE_BIOS_SMBIOS_H
+#define _GPXE_BIOS_SMBIOS_H
+
+/** @file
+ *
+ * Standard PC-BIOS SMBIOS interface
+ *
+ */
+
+#ifdef SMBIOS_PCBIOS
+#define SMBIOS_PREFIX_pcbios
+#else
+#define SMBIOS_PREFIX_pcbios __pcbios_
+#endif
+
+#endif /* _GPXE_BIOS_SMBIOS_H */
diff --git a/gpxe/src/arch/i386/include/gpxe/bios_timer.h b/gpxe/src/arch/i386/include/gpxe/bios_timer.h
new file mode 100644
index 00000000..7e3caa3c
--- /dev/null
+++ b/gpxe/src/arch/i386/include/gpxe/bios_timer.h
@@ -0,0 +1,42 @@
+#ifndef _GPXE_BIOS_TIMER_H
+#define _GPXE_BIOS_TIMER_H
+
+/** @file
+ *
+ * BIOS timer
+ *
+ */
+
+#ifdef TIMER_PCBIOS
+#define TIMER_PREFIX_pcbios
+#else
+#define TIMER_PREFIX_pcbios __pcbios_
+#endif
+
+#include <gpxe/timer2.h>
+
+/**
+ * Delay for a fixed number of microseconds
+ *
+ * @v usecs Number of microseconds for which to delay
+ */
+static inline __always_inline void
+TIMER_INLINE ( pcbios, udelay ) ( unsigned long usecs ) {
+ /* BIOS timer is not high-resolution enough for udelay(), so
+ * we use timer2
+ */
+ timer2_udelay ( usecs );
+}
+
+/**
+ * Get number of ticks per second
+ *
+ * @ret ticks_per_sec Number of ticks per second
+ */
+static inline __always_inline unsigned long
+TIMER_INLINE ( pcbios, ticks_per_sec ) ( void ) {
+ /* BIOS timer ticks over at 18.2 ticks per second */
+ return 18;
+}
+
+#endif /* _GPXE_BIOS_TIMER_H */
diff --git a/gpxe/src/include/gpxe/ibft.h b/gpxe/src/arch/i386/include/gpxe/ibft.h
index 5eef547b..5eef547b 100644
--- a/gpxe/src/include/gpxe/ibft.h
+++ b/gpxe/src/arch/i386/include/gpxe/ibft.h
diff --git a/gpxe/src/arch/i386/include/gpxe/memtop_umalloc.h b/gpxe/src/arch/i386/include/gpxe/memtop_umalloc.h
new file mode 100644
index 00000000..a3cd2c01
--- /dev/null
+++ b/gpxe/src/arch/i386/include/gpxe/memtop_umalloc.h
@@ -0,0 +1,16 @@
+#ifndef _GPXE_MEMTOP_UMALLOC_H
+#define _GPXE_MEMTOP_UMALLOC_H
+
+/** @file
+ *
+ * External memory allocation
+ *
+ */
+
+#ifdef UMALLOC_MEMTOP
+#define UMALLOC_PREFIX_memtop
+#else
+#define UMALLOC_PREFIX_memtop __memtop_
+#endif
+
+#endif /* _GPXE_MEMTOP_UMALLOC_H */
diff --git a/gpxe/src/arch/i386/include/gpxe/rdtsc_timer.h b/gpxe/src/arch/i386/include/gpxe/rdtsc_timer.h
new file mode 100644
index 00000000..0e03d707
--- /dev/null
+++ b/gpxe/src/arch/i386/include/gpxe/rdtsc_timer.h
@@ -0,0 +1,37 @@
+#ifndef _GPXE_RDTSC_TIMER_H
+#define _GPXE_RDTSC_TIMER_H
+
+/** @file
+ *
+ * RDTSC timer
+ *
+ */
+
+#ifdef TIMER_RDTSC
+#define TIMER_PREFIX_rdtsc
+#else
+#define TIMER_PREFIX_rdtsc __rdtsc_
+#endif
+
+/**
+ * RDTSC values can easily overflow an unsigned long. We discard the
+ * low-order bits in order to obtain sensibly-scaled values.
+ */
+#define TSC_SHIFT 8
+
+/**
+ * Get current system time in ticks
+ *
+ * @ret ticks Current time, in ticks
+ */
+static inline __always_inline unsigned long
+TIMER_INLINE ( rdtsc, currticks ) ( void ) {
+ unsigned long ticks;
+
+ __asm__ __volatile__ ( "rdtsc\n\t"
+ "shrdl %1, %%edx, %%eax\n\t"
+ : "=a" ( ticks ) : "i" ( TSC_SHIFT ) : "edx" );
+ return ticks;
+}
+
+#endif /* _GPXE_RDTSC_TIMER_H */
diff --git a/gpxe/src/arch/i386/include/gpxe/timer2.h b/gpxe/src/arch/i386/include/gpxe/timer2.h
new file mode 100644
index 00000000..59705fa2
--- /dev/null
+++ b/gpxe/src/arch/i386/include/gpxe/timer2.h
@@ -0,0 +1,12 @@
+#ifndef _GPXE_TIMER2_H
+#define _GPXE_TIMER2_H
+
+/** @file
+ *
+ * Timer chip control
+ *
+ */
+
+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
new file mode 100644
index 00000000..b1ae3bac
--- /dev/null
+++ b/gpxe/src/arch/i386/include/gpxe/x86_io.h
@@ -0,0 +1,151 @@
+#ifndef _GPXE_X86_IO_H
+#define _GPXE_X86_IO_H
+
+/** @file
+ *
+ * gPXE I/O API for x86
+ *
+ * i386 uses direct pointer dereferences for accesses to memory-mapped
+ * I/O space, and the inX/outX instructions for accesses to
+ * port-mapped I/O space.
+ *
+ * 64-bit atomic accesses (readq() and writeq()) use MMX instructions,
+ * and will crash original Pentium and earlier CPUs. Fortunately, no
+ * hardware that requires atomic 64-bit accesses will physically fit
+ * into a machine with such an old CPU anyway.
+ */
+
+#ifdef IOAPI_X86
+#define IOAPI_PREFIX_x86
+#else
+#define IOAPI_PREFIX_x86 __x86_
+#endif
+
+/*
+ * Memory space mappings
+ *
+ */
+
+/*
+ * Physical<->Bus and Bus<->I/O address mappings
+ *
+ */
+
+static inline __always_inline unsigned long
+IOAPI_INLINE ( x86, phys_to_bus ) ( unsigned long phys_addr ) {
+ return phys_addr;
+}
+
+static inline __always_inline unsigned long
+IOAPI_INLINE ( x86, bus_to_phys ) ( unsigned long bus_addr ) {
+ return bus_addr;
+}
+
+static inline __always_inline void *
+IOAPI_INLINE ( x86, ioremap ) ( unsigned long bus_addr, size_t len __unused ) {
+ return phys_to_virt ( bus_addr );
+}
+
+static inline __always_inline void
+IOAPI_INLINE ( x86, iounmap ) ( volatile const void *io_addr __unused ) {
+ /* Nothing to do */
+}
+
+static inline __always_inline unsigned long
+IOAPI_INLINE ( x86, io_to_bus ) ( volatile const void *io_addr ) {
+ return virt_to_phys ( io_addr );
+}
+
+/*
+ * MMIO reads and writes up to 32 bits
+ *
+ */
+
+#define X86_READX( _api_func, _type ) \
+static inline __always_inline _type \
+IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) { \
+ return *io_addr; \
+}
+X86_READX ( readb, uint8_t );
+X86_READX ( readw, uint16_t );
+X86_READX ( readl, uint32_t );
+
+#define X86_WRITEX( _api_func, _type ) \
+static inline __always_inline void \
+IOAPI_INLINE ( x86, _api_func ) ( _type data, \
+ volatile _type *io_addr ) { \
+ *io_addr = data; \
+}
+X86_WRITEX ( writeb, uint8_t );
+X86_WRITEX ( writew, uint16_t );
+X86_WRITEX ( writel, uint32_t );
+
+/*
+ * PIO reads and writes up to 32 bits
+ *
+ */
+
+#define X86_INX( _insn_suffix, _type, _reg_prefix ) \
+static inline __always_inline _type \
+IOAPI_INLINE ( x86, in ## _insn_suffix ) ( volatile _type *io_addr ) { \
+ _type data; \
+ __asm__ __volatile__ ( "in" #_insn_suffix " %w1, %" _reg_prefix "0" \
+ : "=a" ( data ) : "Nd" ( io_addr ) ); \
+ return data; \
+} \
+static inline __always_inline void \
+IOAPI_INLINE ( x86, ins ## _insn_suffix ) ( volatile _type *io_addr, \
+ _type *data, \
+ unsigned int count ) { \
+ unsigned int discard_D; \
+ __asm__ __volatile__ ( "rep ins" #_insn_suffix \
+ : "=D" ( discard_D ) \
+ : "d" ( io_addr ), "c" ( count ), \
+ "0" ( data ) ); \
+}
+X86_INX ( b, uint8_t, "b" );
+X86_INX ( w, uint16_t, "w" );
+X86_INX ( l, uint32_t, "k" );
+
+#define X86_OUTX( _insn_suffix, _type, _reg_prefix ) \
+static inline __always_inline void \
+IOAPI_INLINE ( x86, out ## _insn_suffix ) ( _type data, \
+ volatile _type *io_addr ) { \
+ __asm__ __volatile__ ( "out" #_insn_suffix " %" _reg_prefix "0, %w1" \
+ : : "a" ( data ), "Nd" ( io_addr ) ); \
+} \
+static inline __always_inline void \
+IOAPI_INLINE ( x86, outs ## _insn_suffix ) ( volatile _type *io_addr, \
+ const _type *data, \
+ unsigned int count ) { \
+ unsigned int discard_S; \
+ __asm__ __volatile__ ( "rep outs" #_insn_suffix \
+ : "=S" ( discard_S ) \
+ : "d" ( io_addr ), "c" ( count ), \
+ "0" ( data ) ); \
+}
+X86_OUTX ( b, uint8_t, "b" );
+X86_OUTX ( w, uint16_t, "w" );
+X86_OUTX ( l, uint32_t, "k" );
+
+/*
+ * Slow down I/O
+ *
+ */
+
+static inline __always_inline void
+IOAPI_INLINE ( x86, iodelay ) ( void ) {
+ __asm__ __volatile__ ( "outb %al, $0x80" );
+}
+
+/*
+ * Memory barrier
+ *
+ */
+
+static inline __always_inline void
+IOAPI_INLINE ( x86, mb ) ( void ) {
+ __asm__ __volatile__ ( "lock; addl $0, 0(%%esp)" : : : "memory" );
+}
+
+#endif /* _GPXE_X86_IO_H */
diff --git a/gpxe/src/arch/i386/include/int13.h b/gpxe/src/arch/i386/include/int13.h
index 72ca97d7..bf6d0318 100644
--- a/gpxe/src/arch/i386/include/int13.h
+++ b/gpxe/src/arch/i386/include/int13.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <gpxe/list.h>
+#include <realmode.h>
struct block_device;
diff --git a/gpxe/src/arch/i386/include/io.h b/gpxe/src/arch/i386/include/io.h
deleted file mode 100644
index c26fdf7e..00000000
--- a/gpxe/src/arch/i386/include/io.h
+++ /dev/null
@@ -1,265 +0,0 @@
-#ifndef ETHERBOOT_IO_H
-#define ETHERBOOT_IO_H
-
-#include <stdint.h>
-#include "virtaddr.h"
-
-/* virt_to_bus converts an addresss inside of etherboot [_start, _end]
- * into a memory access cards can use.
- */
-#define virt_to_bus virt_to_phys
-
-
-/* bus_to_virt reverses virt_to_bus, the address must be output
- * from virt_to_bus to be valid. This function does not work on
- * all bus addresses.
- */
-#define bus_to_virt phys_to_virt
-
-/* ioremap converts a random 32bit bus address into something
- * etherboot can access.
- */
-static inline void *ioremap(unsigned long bus_addr, unsigned long length __unused)
-{
- return bus_to_virt(bus_addr);
-}
-
-/* iounmap cleans up anything ioremap had to setup */
-static inline void iounmap(void *virt_addr __unused)
-{
- return;
-}
-
-/*
- * This file contains the definitions for the x86 IO instructions
- * inb/inw/inl/outb/outw/outl and the "string versions" of the same
- * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
- * versions of the single-IO instructions (inb_p/inw_p/..).
- *
- * This file is not meant to be obfuscating: it's just complicated
- * to (a) handle it all in a way that makes gcc able to optimize it
- * as well as possible and (b) trying to avoid writing the same thing
- * over and over again with slight variations and possibly making a
- * mistake somewhere.
- */
-
-/*
- * Thanks to James van Artsdalen for a better timing-fix than
- * the two short jumps: using outb's to a nonexistent port seems
- * to guarantee better timings even on fast machines.
- *
- * On the other hand, I'd like to be sure of a non-existent port:
- * I feel a bit unsafe about using 0x80 (should be safe, though)
- *
- * Linus
- */
-
-#ifdef SLOW_IO_BY_JUMPING
-#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
-#else
-#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
-#endif
-
-#ifdef REALLY_SLOW_IO
-#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
-#else
-#define SLOW_DOWN_IO __SLOW_DOWN_IO
-#endif
-
-/*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the x86 architecture, we just read/write the
- * memory location directly.
- */
-static inline __attribute__ (( always_inline )) unsigned long
-_readb ( volatile uint8_t *addr ) {
- unsigned long data = *addr;
- DBGIO ( "[%08lx] => %02lx\n", virt_to_phys ( addr ), data );
- return data;
-}
-static inline __attribute__ (( always_inline )) unsigned long
-_readw ( volatile uint16_t *addr ) {
- unsigned long data = *addr;
- DBGIO ( "[%08lx] => %04lx\n", virt_to_phys ( addr ), data );
- return data;
-}
-static inline __attribute__ (( always_inline )) unsigned long
-_readl ( volatile uint32_t *addr ) {
- unsigned long data = *addr;
- DBGIO ( "[%08lx] => %08lx\n", virt_to_phys ( addr ), data );
- return data;
-}
-#define readb( addr ) _readb ( ( volatile uint8_t * ) (addr) )
-#define readw( addr ) _readw ( ( volatile uint16_t * ) (addr) )
-#define readl( addr ) _readl ( ( volatile uint32_t * ) (addr) )
-
-static inline __attribute__ (( always_inline )) void
-_writeb ( unsigned long data, volatile uint8_t *addr ) {
- DBGIO ( "[%08lx] <= %02lx\n", virt_to_phys ( addr ), data );
- *addr = data;
-}
-static inline __attribute__ (( always_inline )) void
-_writew ( unsigned long data, volatile uint16_t *addr ) {
- DBGIO ( "[%08lx] <= %04lx\n", virt_to_phys ( addr ), data );
- *addr = data;
-}
-static inline __attribute__ (( always_inline )) void
-_writel ( unsigned long data, volatile uint32_t *addr ) {
- DBGIO ( "[%08lx] <= %08lx\n", virt_to_phys ( addr ), data );
- *addr = data;
-}
-#define writeb( b, addr ) _writeb ( (b), ( volatile uint8_t * ) (addr) )
-#define writew( b, addr ) _writew ( (b), ( volatile uint16_t * ) (addr) )
-#define writel( b, addr ) _writel ( (b), ( volatile uint32_t * ) (addr) )
-
-#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- *
- * For now, "wmb()" doesn't actually do anything, as all
- * Intel CPU's follow what Intel calls a *Processor Order*,
- * in which all writes are seen in the program order even
- * outside the CPU.
- *
- * I expect future Intel CPU's to have a weaker ordering,
- * but I'd also expect them to finally get their act together
- * and add some real memory barriers if so.
- *
- * Some non intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-
-#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
-#define rmb() mb()
-#define wmb() mb();
-
-
-/*
- * Talk about misusing macros..
- */
-
-#define __OUT1(s,x) \
-extern void __out##s(unsigned x value, unsigned short port); \
-extern inline void __out##s(unsigned x value, unsigned short port) {
-
-#define __OUT2(s,s1,s2) \
-__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
-
-#define __OUT(s,s1,x) \
-__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \
-__OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); } \
-__OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \
-__OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; }
-
-#define __IN1(s,x) \
-extern unsigned x __in##s(unsigned short port); \
-extern inline unsigned x __in##s(unsigned short port) { unsigned x _v;
-
-#define __IN2(s,s1,s2) \
-__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
-
-#define __IN(s,s1,x,i...) \
-__IN1(s,x) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \
-__IN1(s##c,x) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); return _v; } \
-__IN1(s##_p,x) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \
-__IN1(s##c_p,x) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; }
-
-#define __INS(s) \
-extern void ins##s(unsigned short port, void * addr, unsigned long count); \
-extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \
-{ __asm__ __volatile__ ("cld ; rep ; ins" #s \
-: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
-
-#define __OUTS(s) \
-extern void outs##s(unsigned short port, const void * addr, unsigned long count); \
-extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
-{ __asm__ __volatile__ ("cld ; rep ; outs" #s \
-: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
-
-__IN(b,"", char)
-__IN(w,"",short)
-__IN(l,"", long)
-
-__OUT(b,"b",char)
-__OUT(w,"w",short)
-__OUT(l,,int)
-
-__INS(b)
-__INS(w)
-__INS(l)
-
-__OUTS(b)
-__OUTS(w)
-__OUTS(l)
-
-/*
- * Note that due to the way __builtin_constant_p() works, you
- * - can't use it inside a inline function (it will never be true)
- * - you don't have to worry about side effects within the __builtin..
- */
-#define outb(val,port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __outbc((val),(port)) : \
- __outb((val),(port)))
-
-#define inb(port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __inbc(port) : \
- __inb(port))
-
-#define outb_p(val,port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __outbc_p((val),(port)) : \
- __outb_p((val),(port)))
-
-#define inb_p(port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __inbc_p(port) : \
- __inb_p(port))
-
-#define outw(val,port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __outwc((val),(port)) : \
- __outw((val),(port)))
-
-#define inw(port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __inwc(port) : \
- __inw(port))
-
-#define outw_p(val,port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __outwc_p((val),(port)) : \
- __outw_p((val),(port)))
-
-#define inw_p(port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __inwc_p(port) : \
- __inw_p(port))
-
-#define outl(val,port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __outlc((val),(port)) : \
- __outl((val),(port)))
-
-#define inl(port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __inlc(port) : \
- __inl(port))
-
-#define outl_p(val,port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __outlc_p((val),(port)) : \
- __outl_p((val),(port)))
-
-#define inl_p(port) \
-((__builtin_constant_p((port)) && (port) < 256) ? \
- __inlc_p(port) : \
- __inl_p(port))
-
-#endif /* ETHERBOOT_IO_H */
diff --git a/gpxe/src/arch/i386/include/librm.h b/gpxe/src/arch/i386/include/librm.h
index 07a85c59..9eb2767a 100644..100755
--- a/gpxe/src/arch/i386/include/librm.h
+++ b/gpxe/src/arch/i386/include/librm.h
@@ -1,21 +1,109 @@
#ifndef LIBRM_H
#define LIBRM_H
-/* Drag in protected-mode segment selector values */
-#include "virtaddr.h"
-#include "realmode.h"
+/* Segment selectors as used in our protected-mode GDTs.
+ *
+ * Don't change these unless you really know what you're doing.
+ */
+
+#define VIRTUAL_CS 0x08
+#define VIRTUAL_DS 0x10
+#define PHYSICAL_CS 0x18
+#define PHYSICAL_DS 0x20
+#define REAL_CS 0x28
+#define REAL_DS 0x30
+#if 0
+#define LONG_CS 0x38
+#define LONG_DS 0x40
+#endif
#ifndef ASSEMBLY
-#include "stddef.h"
-#include "string.h"
+#ifdef UACCESS_LIBRM
+#define UACCESS_PREFIX_librm
+#else
+#define UACCESS_PREFIX_librm __librm_
+#endif
+
+/* Variables in librm.S */
+extern unsigned long virt_offset;
+
+/**
+ * Convert physical address to user pointer
+ *
+ * @v phys_addr Physical address
+ * @ret userptr User pointer
+ */
+static inline __always_inline userptr_t
+UACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
+ return ( phys_addr - virt_offset );
+}
-/*
- * Data structures and type definitions
+/**
+ * Convert user buffer to physical address
+ *
+ * @v userptr User pointer
+ * @v offset Offset from user pointer
+ * @ret phys_addr Physical address
+ */
+static inline __always_inline unsigned long
+UACCESS_INLINE ( librm, user_to_phys ) ( userptr_t userptr, off_t offset ) {
+ return ( userptr + offset + virt_offset );
+}
+
+static inline __always_inline userptr_t
+UACCESS_INLINE ( librm, virt_to_user ) ( volatile const void *addr ) {
+ return trivial_virt_to_user ( addr );
+}
+
+static inline __always_inline void *
+UACCESS_INLINE ( librm, user_to_virt ) ( userptr_t userptr, off_t offset ) {
+ return trivial_user_to_virt ( userptr, offset );
+}
+
+static inline __always_inline userptr_t
+UACCESS_INLINE ( librm, userptr_add ) ( userptr_t userptr, off_t offset ) {
+ return trivial_userptr_add ( userptr, offset );
+}
+
+static inline __always_inline void
+UACCESS_INLINE ( librm, memcpy_user ) ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off,
+ size_t len ) {
+ trivial_memcpy_user ( dest, dest_off, src, src_off, len );
+}
+
+static inline __always_inline void
+UACCESS_INLINE ( librm, memmove_user ) ( userptr_t dest, off_t dest_off,
+ userptr_t src, off_t src_off,
+ size_t len ) {
+ trivial_memmove_user ( dest, dest_off, src, src_off, len );
+}
+
+static inline __always_inline void
+UACCESS_INLINE ( librm, memset_user ) ( userptr_t buffer, off_t offset,
+ int c, size_t len ) {
+ trivial_memset_user ( buffer, offset, c, len );
+}
+
+static inline __always_inline size_t
+UACCESS_INLINE ( librm, strlen_user ) ( userptr_t buffer, off_t offset ) {
+ return trivial_strlen_user ( buffer, offset );
+}
+
+static inline __always_inline off_t
+UACCESS_INLINE ( librm, memchr_user ) ( userptr_t buffer, off_t offset,
+ int c, size_t len ) {
+ return trivial_memchr_user ( buffer, offset, c, len );
+}
+
+
+/******************************************************************************
+ *
+ * Access to variables in .data16 and .text16
*
*/
-/* Access to variables in .data16 and .text16 */
extern char *data16;
extern char *text16;
@@ -72,178 +160,6 @@ extern uint16_t __text16 ( rm_ds );
*/
extern void gateA20_set ( void );
-/*
- * librm_mgmt: functions for manipulating base memory and executing
- * real-mode code.
- *
- * Full API documentation for these functions is in realmode.h.
- *
- */
-
-/* Macro for obtaining a physical address from a segment:offset pair. */
-#define VIRTUAL(x,y) ( phys_to_virt ( ( ( x ) << 4 ) + ( y ) ) )
-
-/* Copy to/from base memory */
-static inline __attribute__ (( always_inline )) void
-copy_to_real_librm ( unsigned int dest_seg, unsigned int dest_off,
- void *src, size_t n ) {
- memcpy ( VIRTUAL ( dest_seg, dest_off ), src, n );
-}
-static inline __attribute__ (( always_inline )) void
-copy_from_real_librm ( void *dest, unsigned int src_seg,
- unsigned int src_off, size_t n ) {
- memcpy ( dest, VIRTUAL ( src_seg, src_off ), n );
-}
-#define put_real_librm( var, dest_seg, dest_off ) \
- do { \
- * ( ( typeof(var) * ) VIRTUAL ( dest_seg, dest_off ) ) = var; \
- } while ( 0 )
-#define get_real_librm( var, src_seg, src_off ) \
- do { \
- var = * ( ( typeof(var) * ) VIRTUAL ( src_seg, src_off ) ); \
- } while ( 0 )
-#define copy_to_real copy_to_real_librm
-#define copy_from_real copy_from_real_librm
-#define put_real put_real_librm
-#define get_real get_real_librm
-
-/**
- * A pointer to a user buffer
- *
- * Even though we could just use a void *, we use an intptr_t so that
- * attempts to use normal pointers show up as compiler warnings. Such
- * code is actually valid for librm, but not for libkir (i.e. under
- * KEEP_IT_REAL), so it's good to have the warnings even under librm.
- */
-typedef intptr_t userptr_t;
-
-/**
- * Add offset to user pointer
- *
- * @v ptr User pointer
- * @v offset Offset
- * @ret new_ptr New pointer value
- */
-static inline __attribute__ (( always_inline )) userptr_t
-userptr_add ( userptr_t ptr, off_t offset ) {
- return ( ptr + offset );
-}
-
-/**
- * Copy data to user buffer
- *
- * @v buffer User buffer
- * @v offset Offset within user buffer
- * @v src Source
- * @v len Length
- */
-static inline __attribute__ (( always_inline )) void
-copy_to_user ( userptr_t buffer, off_t offset, const void *src, size_t len ) {
- memcpy ( ( ( void * ) buffer + offset ), src, len );
-}
-
-/**
- * Copy data from user buffer
- *
- * @v dest Destination
- * @v buffer User buffer
- * @v offset Offset within user buffer
- * @v len Length
- */
-static inline __attribute__ (( always_inline )) void
-copy_from_user ( void *dest, userptr_t buffer, off_t offset, size_t len ) {
- memcpy ( dest, ( ( void * ) buffer + offset ), len );
-}
-
-/**
- * Copy data between user buffers
- *
- * @v dest Destination user buffer
- * @v dest_off Offset within destination buffer
- * @v src Source user buffer
- * @v src_off Offset within source buffer
- * @v len Length
- */
-static inline __attribute__ (( always_inline )) void
-memcpy_user ( userptr_t dest, off_t dest_off, userptr_t src, off_t src_off,
- size_t len ) {
- memcpy ( ( ( void * ) dest + dest_off ), ( ( void * ) src + src_off ),
- len );
-}
-
-/**
- * Copy data between user buffers, allowing for overlap
- *
- * @v dest Destination user buffer
- * @v dest_off Offset within destination buffer
- * @v src Source user buffer
- * @v src_off Offset within source buffer
- * @v len Length
- */
-static inline __attribute__ (( always_inline )) void
-memmove_user ( userptr_t dest, off_t dest_off, userptr_t src, off_t src_off,
- size_t len ) {
- memmove ( ( ( void * ) dest + dest_off ), ( ( void * ) src + src_off ),
- len );
-}
-
-/**
- * Fill user buffer with a constant byte
- *
- * @v buffer User buffer
- * @v offset Offset within buffer
- * @v c Constant byte with which to fill
- * @v len Length
- */
-static inline __attribute__ (( always_inline )) void
-memset_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
- memset ( ( ( void * ) buffer + offset ), c, len );
-}
-
-/**
- * Find length of NUL-terminated string in user buffer
- *
- * @v buffer User buffer
- * @v offset Offset within buffer
- * @ret len Length of string (excluding NUL)
- */
-static inline __attribute__ (( always_inline )) size_t
-strlen_user ( userptr_t buffer, off_t offset ) {
- return strlen ( ( void * ) buffer + offset );
-}
-
-/**
- * Find character in user buffer
- *
- * @v buffer User buffer
- * @v offset Starting offset within buffer
- * @v c Character to search for
- * @v len Length of user buffer
- * @ret offset Offset of character, or <0 if not found
- */
-static inline __attribute__ (( always_inline )) off_t
-memchr_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
- void *found;
-
- found = memchr ( ( ( void * ) buffer + offset ), c, len );
- return ( found ? ( found - ( void * ) buffer ) : -1 );
-}
-
-/**
- * Convert virtual address to user buffer
- *
- * @v virtual Virtual address
- * @ret buffer User buffer
- *
- * This constructs a user buffer from an ordinary pointer. Use it
- * when you need to pass a pointer to an internal buffer to a function
- * that expects a @c userptr_t.
- */
-static inline __attribute__ (( always_inline )) userptr_t
-virt_to_user ( void * virtual ) {
- return ( ( intptr_t ) virtual );
-}
-
/**
* Convert segment:offset address to user buffer
*
@@ -251,32 +167,9 @@ virt_to_user ( void * virtual ) {
* @v offset Real-mode offset
* @ret buffer User buffer
*/
-static inline __attribute__ (( always_inline )) userptr_t
+static inline __always_inline userptr_t
real_to_user ( unsigned int segment, unsigned int offset ) {
- return virt_to_user ( VIRTUAL ( segment, offset ) );
-}
-
-/**
- * Convert physical address to user buffer
- *
- * @v physical Physical address
- * @ret buffer User buffer
- */
-static inline __attribute__ (( always_inline )) userptr_t
-phys_to_user ( physaddr_t physical ) {
- return virt_to_user ( phys_to_virt ( physical ) );
-}
-
-/**
- * Convert user buffer to physical address
- *
- * @v buffer User buffer
- * @v offset Offset within user buffer
- * @ret physical Physical address
- */
-static inline __attribute__ (( always_inline )) physaddr_t
-user_to_phys ( userptr_t buffer, off_t offset ) {
- return virt_to_phys ( ( void * ) buffer + offset );
+ return ( phys_to_user ( ( segment << 4 ) + offset ) );
}
extern uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size );
diff --git a/gpxe/src/arch/i386/include/pci_io.h b/gpxe/src/arch/i386/include/pci_io.h
deleted file mode 100644
index 4888d557..00000000
--- a/gpxe/src/arch/i386/include/pci_io.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _PCI_IO_H
-#define _PCI_IO_H
-
-#include <pcibios.h>
-#include <pcidirect.h>
-
-/** @file
- *
- * i386 PCI configuration space access
- *
- * We have two methods of PCI configuration space access: the PCI BIOS
- * and direct Type 1 accesses. Selecting between them is via the
- * compile-time switch -DCONFIG_PCI_DIRECT.
- *
- */
-
-#if CONFIG_PCI_DIRECT
-#define pci_max_bus pcidirect_max_bus
-#define pci_read_config_byte pcidirect_read_config_byte
-#define pci_read_config_word pcidirect_read_config_word
-#define pci_read_config_dword pcidirect_read_config_dword
-#define pci_write_config_byte pcidirect_write_config_byte
-#define pci_write_config_word pcidirect_write_config_word
-#define pci_write_config_dword pcidirect_write_config_dword
-#else /* CONFIG_PCI_DIRECT */
-#define pci_max_bus pcibios_max_bus
-#define pci_read_config_byte pcibios_read_config_byte
-#define pci_read_config_word pcibios_read_config_word
-#define pci_read_config_dword pcibios_read_config_dword
-#define pci_write_config_byte pcibios_write_config_byte
-#define pci_write_config_word pcibios_write_config_word
-#define pci_write_config_dword pcibios_write_config_dword
-#endif /* CONFIG_PCI_DIRECT */
-
-#endif /* _PCI_IO_H */
diff --git a/gpxe/src/include/pxe.h b/gpxe/src/arch/i386/include/pxe.h
index 6d332ac7..6d332ac7 100644
--- a/gpxe/src/include/pxe.h
+++ b/gpxe/src/arch/i386/include/pxe.h
diff --git a/gpxe/src/arch/i386/include/pxe_addr.h b/gpxe/src/arch/i386/include/pxe_addr.h
deleted file mode 100644
index 954551e8..00000000
--- a/gpxe/src/arch/i386/include/pxe_addr.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Architecture-specific portion of pxe.h for Etherboot
- *
- * This file has to define the types SEGOFF16_t, SEGDESC_t and
- * SEGSEL_t for use in other PXE structures. See pxe.h for details.
- */
-
-#ifndef PXE_ADDR_H
-#define PXE_ADDR_H
-
-#define IS_NULL_SEGOFF16(x) ( ( (x).segment == 0 ) && ( (x).offset == 0 ) )
-#define SEGOFF16_TO_PTR(x) ( VIRTUAL( (x).segment, (x).offset ) )
-#define PTR_TO_SEGOFF16(ptr,segoff16) \
- (segoff16).segment = SEGMENT(ptr); \
- (segoff16).offset = OFFSET(ptr);
-
-#endif /* PXE_ADDR_H */
diff --git a/gpxe/src/include/pxe_api.h b/gpxe/src/arch/i386/include/pxe_api.h
index b3d4bca8..b3d4bca8 100644
--- a/gpxe/src/include/pxe_api.h
+++ b/gpxe/src/arch/i386/include/pxe_api.h
diff --git a/gpxe/src/arch/i386/include/pxe_call.h b/gpxe/src/arch/i386/include/pxe_call.h
index 7a38d314..2f3ea15a 100644
--- a/gpxe/src/arch/i386/include/pxe_call.h
+++ b/gpxe/src/arch/i386/include/pxe_call.h
@@ -30,6 +30,6 @@ extern void pxe_hook_int1a ( void );
extern int pxe_unhook_int1a ( void );
extern void pxe_init_structures ( void );
extern int pxe_start_nbp ( void );
-extern __cdecl void pxe_api_call ( struct i386_all_regs *ix86 );
+extern __asmcall void pxe_api_call ( struct i386_all_regs *ix86 );
#endif /* _PXE_CALL_H */
diff --git a/gpxe/src/include/pxe_types.h b/gpxe/src/arch/i386/include/pxe_types.h
index e31af062..dd9092ef 100644
--- a/gpxe/src/include/pxe_types.h
+++ b/gpxe/src/arch/i386/include/pxe_types.h
@@ -7,9 +7,8 @@
*
*/
-#include "stdint.h"
-#include "pxe_addr.h" /* Architecture-specific PXE definitions */
-#include "errno.h" /* PXE status codes */
+#include <stdint.h>
+#include <errno.h> /* PXE status codes */
/** @addtogroup pxe Preboot eXecution Environment (PXE) API
* @{
diff --git a/gpxe/src/arch/i386/include/realmode.h b/gpxe/src/arch/i386/include/realmode.h
index 5d3ddf50..26e6dd77 100644
--- a/gpxe/src/arch/i386/include/realmode.h
+++ b/gpxe/src/arch/i386/include/realmode.h
@@ -1,45 +1,15 @@
#ifndef REALMODE_H
#define REALMODE_H
-#ifndef ASSEMBLY
-
-#include "stdint.h"
-#include "registers.h"
-#include "io.h"
+#include <stdint.h>
+#include <registers.h>
+#include <gpxe/uaccess.h>
/*
* Data structures and type definitions
*
*/
-/* Segment:offset structure. Note that the order within the structure
- * is offset:segment.
- */
-struct segoff {
- uint16_t offset;
- uint16_t segment;
-} __attribute__ (( packed ));
-
-typedef struct segoff segoff_t;
-
-/* Macro hackery needed to stringify bits of inline assembly */
-#define RM_XSTR(x) #x
-#define RM_STR(x) RM_XSTR(x)
-
-/* Drag in the selected real-mode transition library header */
-#ifdef KEEP_IT_REAL
-#include "libkir.h"
-#else
-#include "librm.h"
-#endif
-
-/*
- * The API to some functions is identical between librm and libkir, so
- * they are documented here, even though the prototypes are in librm.h
- * and libkir.h.
- *
- */
-
/*
* Declaration of variables in .data16
*
@@ -92,24 +62,53 @@ typedef struct segoff segoff_t;
* assembler output to make sure that it's doing the right thing.
*/
-/*
- * void copy_to_real ( uint16_t dest_seg, uint16_t dest_off,
- * void *src, size_t n )
- * void copy_from_real ( void *dest, uint16_t src_seg, uint16_t src_off,
- * size_t n )
+/**
+ * Copy data to base memory
*
- * These functions can be used to copy data to and from arbitrary
- * locations in base memory.
+ * @v dest_seg Destination segment
+ * @v dest_off Destination offset
+ * @v src Source
+ * @v len Length
*/
+static inline __always_inline void
+copy_to_real ( unsigned int dest_seg, unsigned int dest_off,
+ void *src, size_t n ) {
+ copy_to_user ( real_to_user ( dest_seg, dest_off ), 0, src, n );
+}
-/*
- * put_real ( variable, uint16_t dest_seg, uint16_t dest_off )
- * get_real ( variable, uint16_t src_seg, uint16_t src_off )
+/**
+ * Copy data to base memory
+ *
+ * @v dest Destination
+ * @v src_seg Source segment
+ * @v src_off Source offset
+ * @v len Length
+ */
+static inline __always_inline void
+copy_from_real ( void *dest, unsigned int src_seg,
+ unsigned int src_off, size_t n ) {
+ copy_from_user ( dest, real_to_user ( src_seg, src_off ), 0, n );
+}
+
+/**
+ * Write a single variable to base memory
*
- * These macros can be used to read or write single variables to and
- * from arbitrary locations in base memory. "variable" must be a
- * variable of either 1, 2 or 4 bytes in length.
+ * @v var Variable to write
+ * @v dest_seg Destination segment
+ * @v dest_off Destination offset
*/
+#define put_real( var, dest_seg, dest_off ) \
+ copy_to_real ( (dest_seg), (dest_off), &(var), sizeof (var) )
+
+/**
+ * Read a single variable from base memory
+ *
+ * @v var Variable to read
+ * @v src_seg Source segment
+ * @v src_off Source offset
+ */
+#define get_real( var, src_seg, src_off ) \
+ copy_from_real ( &(var), (src_seg), (src_off), sizeof (var) )
/*
* REAL_CODE ( asm_code_str )
@@ -123,6 +122,4 @@ typedef struct segoff segoff_t;
*
*/
-#endif /* ASSEMBLY */
-
#endif /* REALMODE_H */
diff --git a/gpxe/src/arch/i386/include/registers.h b/gpxe/src/arch/i386/include/registers.h
index 2b9b2b43..e68fa85a 100644
--- a/gpxe/src/arch/i386/include/registers.h
+++ b/gpxe/src/arch/i386/include/registers.h
@@ -10,8 +10,7 @@
*
*/
-#include "compiler.h" /* for doxygen */
-#include "stdint.h"
+#include <stdint.h>
/**
* A 16-bit general register.
@@ -184,4 +183,14 @@ struct i386_all_regs {
#define SF ( 1 << 7 )
#define OF ( 1 << 11 )
+/* Segment:offset structure. Note that the order within the structure
+ * is offset:segment.
+ */
+struct segoff {
+ uint16_t offset;
+ uint16_t segment;
+} PACKED;
+
+typedef struct segoff segoff_t;
+
#endif /* REGISTERS_H */
diff --git a/gpxe/src/arch/i386/include/setjmp.h b/gpxe/src/arch/i386/include/setjmp.h
index bb0a100d..c18d03e1 100644
--- a/gpxe/src/arch/i386/include/setjmp.h
+++ b/gpxe/src/arch/i386/include/setjmp.h
@@ -1,12 +1,38 @@
#ifndef ETHERBOOT_SETJMP_H
#define ETHERBOOT_SETJMP_H
+#include <stdint.h>
+#include <realmode.h>
-/* Define a type for use by setjmp and longjmp */
-#define JBLEN 6
-typedef unsigned long jmp_buf[JBLEN];
+/** A jump buffer */
+typedef struct {
+ uint32_t retaddr;
+ uint32_t ebx;
+ uint32_t esp;
+ uint32_t ebp;
+ uint32_t esi;
+ uint32_t edi;
+} jmp_buf[1];
-extern int __cdecl setjmp (jmp_buf env);
-extern void __cdecl longjmp (jmp_buf env, int val);
+/** A real-mode-extended jump buffer */
+typedef struct {
+ jmp_buf env;
+ uint16_t rm_ss;
+ uint16_t rm_sp;
+} rmjmp_buf[1];
+
+extern int __asmcall setjmp ( jmp_buf env );
+extern void __asmcall longjmp ( jmp_buf env, int val );
+
+#define rmsetjmp( _env ) ( { \
+ (_env)->rm_ss = rm_ss; \
+ (_env)->rm_sp = rm_sp; \
+ setjmp ( (_env)->env ); } ) \
+
+#define rmlongjmp( _env, _val ) do { \
+ rm_ss = (_env)->rm_ss; \
+ rm_sp = (_env)->rm_sp; \
+ longjmp ( (_env)->env, (_val) ); \
+ } while ( 0 )
#endif /* ETHERBOOT_SETJMP_H */
diff --git a/gpxe/src/arch/i386/include/smbios.h b/gpxe/src/arch/i386/include/smbios.h
deleted file mode 100644
index f2736dc3..00000000
--- a/gpxe/src/arch/i386/include/smbios.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef _SMBIOS_H
-#define _SMBIOS_H
-
-/** @file
- *
- * System Management BIOS
- */
-
-#include <stdint.h>
-
-/** An SMBIOS structure header */
-struct smbios_header {
- /** Type */
- uint8_t type;
- /** Length */
- uint8_t len;
- /** Handle */
- uint16_t handle;
-} __attribute__ (( packed ));
-
-/** SMBIOS structure descriptor */
-struct smbios_structure {
- /** Copy of SMBIOS structure header */
- struct smbios_header header;
- /** Offset of structure within SMBIOS */
- size_t offset;
- /** Length of strings section */
- size_t strings_len;
-};
-
-/** SMBIOS system information structure */
-struct smbios_system_information {
- /** SMBIOS structure header */
- struct smbios_header header;
- /** Manufacturer string */
- uint8_t manufacturer;
- /** Product string */
- uint8_t product;
- /** Version string */
- uint8_t version;
- /** Serial number string */
- uint8_t serial;
- /** UUID */
- uint8_t uuid[16];
- /** Wake-up type */
- uint8_t wakeup;
-} __attribute__ (( packed ));
-
-/** SMBIOS system information structure type */
-#define SMBIOS_TYPE_SYSTEM_INFORMATION 1
-
-extern int find_smbios_structure ( unsigned int type,
- struct smbios_structure *structure );
-extern int read_smbios_structure ( struct smbios_structure *structure,
- void *data, size_t len );
-extern int read_smbios_string ( struct smbios_structure *structure,
- unsigned int index,
- void *data, size_t len );
-
-#endif /* _SMBIOS_H */
diff --git a/gpxe/src/arch/i386/include/undi.h b/gpxe/src/arch/i386/include/undi.h
index 9936e17f..c6253d0a 100644
--- a/gpxe/src/arch/i386/include/undi.h
+++ b/gpxe/src/arch/i386/include/undi.h
@@ -24,10 +24,6 @@ struct undi_device {
SEGOFF16_t ppxe;
/** Entry point */
SEGOFF16_t entry;
- /** Return stack */
- UINT16_t return_stack[3];
- /** Return type */
- UINT16_t return_type;
/** Free base memory after load */
UINT16_t fbms;
/** Free base memory prior to load */
@@ -99,4 +95,10 @@ static inline void * undi_get_drvdata ( struct undi_device *undi ) {
/** UNDI flag: START_UNDI has been called */
#define UNDI_FL_STARTED 0x0001
+/** UNDI flag: UNDI_STARTUP and UNDI_INITIALIZE have been called */
+#define UNDI_FL_INITIALIZED 0x0002
+
+/** UNDI flag: keep stack resident */
+#define UNDI_FL_KEEP_ALL 0x0004
+
#endif /* _UNDI_H */
diff --git a/gpxe/src/arch/i386/include/virtaddr.h b/gpxe/src/arch/i386/include/virtaddr.h
deleted file mode 100644
index f2ffa2a1..00000000
--- a/gpxe/src/arch/i386/include/virtaddr.h
+++ /dev/null
@@ -1,105 +0,0 @@
-#ifndef VIRTADDR_H
-#define VIRTADDR_H
-
-/* Segment selectors as used in our protected-mode GDTs.
- *
- * Don't change these unless you really know what you're doing.
- */
-
-#define VIRTUAL_CS 0x08
-#define VIRTUAL_DS 0x10
-#define PHYSICAL_CS 0x18
-#define PHYSICAL_DS 0x20
-#define REAL_CS 0x28
-#define REAL_DS 0x30
-#if 0
-#define LONG_CS 0x38
-#define LONG_DS 0x40
-#endif
-
-#ifndef ASSEMBLY
-
-#include "stdint.h"
-#include "string.h"
-
-#ifndef KEEP_IT_REAL
-
-/*
- * Without -DKEEP_IT_REAL, we are in 32-bit protected mode with a
- * fixed link address but an unknown physical start address. Our GDT
- * sets up code and data segments with an offset of virt_offset, so
- * that link-time addresses can still work.
- *
- */
-
-/* C-callable function prototypes */
-
-extern void relocate_to ( uint32_t new_phys_addr );
-
-/* Variables in virtaddr.S */
-extern unsigned long virt_offset;
-
-/*
- * Convert between virtual and physical addresses
- *
- */
-static inline unsigned long virt_to_phys ( volatile const void *virt_addr ) {
- return ( ( unsigned long ) virt_addr ) + virt_offset;
-}
-
-static inline void * phys_to_virt ( unsigned long phys_addr ) {
- return ( void * ) ( phys_addr - virt_offset );
-}
-
-static inline void copy_to_phys ( physaddr_t dest, const void *src,
- size_t len ) {
- memcpy ( phys_to_virt ( dest ), src, len );
-}
-
-static inline void copy_from_phys ( void *dest, physaddr_t src, size_t len ) {
- memcpy ( dest, phys_to_virt ( src ), len );
-}
-
-static inline void copy_phys_to_phys ( physaddr_t dest, physaddr_t src,
- size_t len ) {
- memcpy ( phys_to_virt ( dest ), phys_to_virt ( src ), len );
-}
-
-#else /* KEEP_IT_REAL */
-
-/*
- * With -DKEEP_IT_REAL, we are in 16-bit real mode with fixed link
- * addresses and a segmented memory model. We have separate code and
- * data segments.
- *
- * Because we may be called in 16-bit protected mode (damn PXE spec),
- * we cannot simply assume that physical = segment * 16 + offset.
- * Instead, we have to look up the physical start address of the
- * segment in the !PXE structure. We have to assume that
- * virt_to_phys() is called only on pointers within the data segment,
- * because nothing passes segment information to us.
- *
- * We don't implement phys_to_virt at all, because there will be many
- * addresses that simply cannot be reached via a virtual address when
- * the virtual address space is limited to 64kB!
- */
-
-static inline unsigned long virt_to_phys ( volatile const void *virt_addr ) {
- /* Cheat: just for now, do the segment*16+offset calculation */
- uint16_t ds;
-
- __asm__ ( "movw %%ds, %%ax" : "=a" ( ds ) : );
- return ( 16 * ds + ( ( unsigned long ) virt_addr ) );
-}
-
-/* Define it as a deprecated function so that we get compile-time
- * warnings, rather than just the link-time errors.
- */
-extern void * phys_to_virt ( unsigned long phys_addr )
- __attribute__ ((deprecated));
-
-#endif /* KEEP_IT_REAL */
-
-#endif /* ASSEMBLY */
-
-#endif /* VIRTADDR_H */
diff --git a/gpxe/src/core/abft.c b/gpxe/src/arch/i386/interface/pcbios/abft.c
index af28bbcf..af28bbcf 100644
--- a/gpxe/src/core/abft.c
+++ b/gpxe/src/arch/i386/interface/pcbios/abft.c
diff --git a/gpxe/src/usr/aoeboot.c b/gpxe/src/arch/i386/interface/pcbios/aoeboot.c
index f0e481bd..6e1e51cb 100644
--- a/gpxe/src/usr/aoeboot.c
+++ b/gpxe/src/arch/i386/interface/pcbios/aoeboot.c
@@ -6,27 +6,11 @@
#include <gpxe/ata.h>
#include <gpxe/netdevice.h>
#include <gpxe/settings.h>
+#include <gpxe/sanboot.h>
#include <gpxe/abft.h>
#include <int13.h>
-#include <usr/aoeboot.h>
-/**
- * Guess boot network device
- *
- * @ret netdev Boot network device
- */
-static struct net_device * guess_boot_netdev ( void ) {
- struct net_device *boot_netdev;
-
- /* Just use the first network device */
- for_each_netdev ( boot_netdev ) {
- return boot_netdev;
- }
-
- return NULL;
-}
-
-int aoeboot ( const char *root_path ) {
+static int aoeboot ( const char *root_path ) {
struct ata_device ata;
struct int13_drive drive;
int rc;
@@ -37,7 +21,7 @@ int aoeboot ( const char *root_path ) {
printf ( "AoE booting from %s\n", root_path );
/* FIXME: ugly, ugly hack */
- struct net_device *netdev = guess_boot_netdev();
+ struct net_device *netdev = last_opened_netdev();
if ( ( rc = aoe_attach ( &ata, netdev, root_path ) ) != 0 ) {
printf ( "Could not attach AoE device: %s\n",
@@ -71,3 +55,8 @@ int aoeboot ( const char *root_path ) {
error_attach:
return rc;
}
+
+struct sanboot_protocol aoe_sanboot_protocol __sanboot_protocol = {
+ .prefix = "aoe:",
+ .boot = aoeboot,
+};
diff --git a/gpxe/src/arch/i386/interface/pcbios/bios_nap.c b/gpxe/src/arch/i386/interface/pcbios/bios_nap.c
new file mode 100644
index 00000000..2f4a0513
--- /dev/null
+++ b/gpxe/src/arch/i386/interface/pcbios/bios_nap.c
@@ -0,0 +1,14 @@
+#include <gpxe/nap.h>
+#include <realmode.h>
+
+/**
+ * Save power by halting the CPU until the next interrupt
+ *
+ */
+static void bios_cpu_nap ( void ) {
+ __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
+ "hlt\n\t"
+ "cli\n\t" ) : : );
+}
+
+PROVIDE_NAP ( pcbios, cpu_nap, bios_cpu_nap );
diff --git a/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c b/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c
new file mode 100644
index 00000000..efaaef0d
--- /dev/null
+++ b/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <gpxe/uaccess.h>
+#include <gpxe/smbios.h>
+#include <realmode.h>
+#include <pnpbios.h>
+
+/** @file
+ *
+ * System Management BIOS
+ *
+ */
+
+/**
+ * Find SMBIOS
+ *
+ * @v smbios SMBIOS entry point descriptor structure to fill in
+ * @ret rc Return status code
+ */
+static int bios_find_smbios ( struct smbios *smbios ) {
+ union {
+ struct smbios_entry entry;
+ uint8_t bytes[256]; /* 256 is maximum length possible */
+ } u;
+ static unsigned int offset = 0;
+ size_t len;
+ unsigned int i;
+ uint8_t sum;
+
+ /* Try to find SMBIOS */
+ for ( ; offset < 0x10000 ; offset += 0x10 ) {
+
+ /* Read start of header and verify signature */
+ copy_from_real ( &u.entry, BIOS_SEG, offset,
+ sizeof ( u.entry ));
+ if ( u.entry.signature != SMBIOS_SIGNATURE )
+ continue;
+
+ /* Read whole header and verify checksum */
+ len = u.entry.len;
+ copy_from_real ( &u.bytes, BIOS_SEG, offset, len );
+ for ( i = 0 , sum = 0 ; i < len ; i++ ) {
+ sum += u.bytes[i];
+ }
+ if ( sum != 0 ) {
+ DBG ( "SMBIOS at %04x:%04x has bad checksum %02x\n",
+ BIOS_SEG, offset, sum );
+ continue;
+ }
+
+ /* Fill result structure */
+ DBG ( "Found SMBIOS v%d.%d entry point at %04x:%04x\n",
+ u.entry.major, u.entry.minor, BIOS_SEG, offset );
+ smbios->address = phys_to_user ( u.entry.smbios_address );
+ smbios->len = u.entry.smbios_len;
+ smbios->count = u.entry.smbios_count;
+ return 0;
+ }
+
+ DBG ( "No SMBIOS found\n" );
+ return -ENODEV;
+}
+
+PROVIDE_SMBIOS ( pcbios, find_smbios, bios_find_smbios );
diff --git a/gpxe/src/arch/i386/interface/pcbios/bios_timer.c b/gpxe/src/arch/i386/interface/pcbios/bios_timer.c
new file mode 100644
index 00000000..0b475ea3
--- /dev/null
+++ b/gpxe/src/arch/i386/interface/pcbios/bios_timer.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008 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
+ *
+ * BIOS timer
+ *
+ */
+
+#include <gpxe/timer.h>
+#include <realmode.h>
+#include <bios.h>
+
+/**
+ * Get current system time in ticks
+ *
+ * @ret ticks Current time, in ticks
+ *
+ * Use direct memory access to BIOS variables, longword 0040:006C
+ * (ticks today) and byte 0040:0070 (midnight crossover flag) instead
+ * of calling timeofday BIOS interrupt.
+ */
+static unsigned long bios_currticks ( void ) {
+ static int days = 0;
+ uint32_t ticks;
+ uint8_t midnight;
+
+ /* Re-enable interrupts so that the timer interrupt can occur */
+ __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "cli\n\t" ) : : );
+
+ get_real ( ticks, BDA_SEG, 0x006c );
+ get_real ( midnight, BDA_SEG, 0x0070 );
+
+ if ( midnight ) {
+ midnight = 0;
+ put_real ( midnight, BDA_SEG, 0x0070 );
+ days += 0x1800b0;
+ }
+
+ return ( days + ticks );
+}
+
+PROVIDE_TIMER_INLINE ( pcbios, udelay );
+PROVIDE_TIMER ( pcbios, currticks, bios_currticks );
+PROVIDE_TIMER_INLINE ( pcbios, ticks_per_sec );
diff --git a/gpxe/src/arch/i386/interface/pcbios/biosint.c b/gpxe/src/arch/i386/interface/pcbios/biosint.c
index 8ef2d7ab..1306f918 100644
--- a/gpxe/src/arch/i386/interface/pcbios/biosint.c
+++ b/gpxe/src/arch/i386/interface/pcbios/biosint.c
@@ -8,17 +8,6 @@
*/
/**
- * Hooked interrupt count
- *
- * At exit, after unhooking all possible interrupts, this counter
- * should be examined. If it is non-zero, it means that we failed to
- * unhook at least one interrupt vector, and so must not free up the
- * memory we are using. (Note that this also implies that we should
- * re-hook INT 15 in order to hide ourselves from the memory map).
- */
-int hooked_bios_interrupts = 0;
-
-/**
* Hook INT vector
*
* @v interrupt INT number
diff --git a/gpxe/src/core/ibft.c b/gpxe/src/arch/i386/interface/pcbios/ibft.c
index ffa65964..ffa65964 100644
--- a/gpxe/src/core/ibft.c
+++ b/gpxe/src/arch/i386/interface/pcbios/ibft.c
diff --git a/gpxe/src/arch/i386/interface/pcbios/int13.c b/gpxe/src/arch/i386/interface/pcbios/int13.c
index 6f61e4a1..2e9de5cb 100644
--- a/gpxe/src/arch/i386/interface/pcbios/int13.c
+++ b/gpxe/src/arch/i386/interface/pcbios/int13.c
@@ -144,7 +144,7 @@ static int int13_rw_sectors ( struct int13_drive *drive,
static int int13_read_sectors ( struct int13_drive *drive,
struct i386_all_regs *ix86 ) {
DBG ( "Read: " );
- return int13_rw_sectors ( drive, ix86, drive->blockdev->read );
+ return int13_rw_sectors ( drive, ix86, drive->blockdev->op->read );
}
/**
@@ -163,7 +163,7 @@ static int int13_read_sectors ( struct int13_drive *drive,
static int int13_write_sectors ( struct int13_drive *drive,
struct i386_all_regs *ix86 ) {
DBG ( "Write: " );
- return int13_rw_sectors ( drive, ix86, drive->blockdev->write );
+ return int13_rw_sectors ( drive, ix86, drive->blockdev->op->write );
}
/**
@@ -275,7 +275,7 @@ static int int13_extended_rw ( struct int13_drive *drive,
static int int13_extended_read ( struct int13_drive *drive,
struct i386_all_regs *ix86 ) {
DBG ( "Extended read: " );
- return int13_extended_rw ( drive, ix86, drive->blockdev->read );
+ return int13_extended_rw ( drive, ix86, drive->blockdev->op->read );
}
/**
@@ -288,7 +288,7 @@ static int int13_extended_read ( struct int13_drive *drive,
static int int13_extended_write ( struct int13_drive *drive,
struct i386_all_regs *ix86 ) {
DBG ( "Extended write: " );
- return int13_extended_rw ( drive, ix86, drive->blockdev->write );
+ return int13_extended_rw ( drive, ix86, drive->blockdev->op->write );
}
/**
@@ -322,7 +322,7 @@ static int int13_get_extended_parameters ( struct int13_drive *drive,
* INT 13 handler
*
*/
-static __cdecl void int13 ( struct i386_all_regs *ix86 ) {
+static __asmcall void int13 ( struct i386_all_regs *ix86 ) {
int command = ix86->regs.ah;
unsigned int bios_drive = ix86->regs.dl;
struct int13_drive *drive;
@@ -488,8 +488,8 @@ static void guess_int13_geometry ( struct int13_drive *drive ) {
/* Scan through partition table and modify guesses for heads
* and sectors_per_track if we find any used partitions.
*/
- if ( drive->blockdev->read ( drive->blockdev, 0, 1,
- virt_to_user ( &mbr ) ) == 0 ) {
+ if ( drive->blockdev->op->read ( drive->blockdev, 0, 1,
+ virt_to_user ( &mbr ) ) == 0 ) {
for ( i = 0 ; i < 4 ; i++ ) {
partition = &mbr.partitions[i];
if ( ! partition->type )
diff --git a/gpxe/src/usr/iscsiboot.c b/gpxe/src/arch/i386/interface/pcbios/iscsiboot.c
index 84d77c45..02aec4ba 100644
--- a/gpxe/src/usr/iscsiboot.c
+++ b/gpxe/src/arch/i386/interface/pcbios/iscsiboot.c
@@ -9,9 +9,9 @@
#include <gpxe/netdevice.h>
#include <gpxe/ibft.h>
#include <gpxe/init.h>
+#include <gpxe/sanboot.h>
#include <int13.h>
#include <usr/autoboot.h>
-#include <usr/iscsiboot.h>
struct setting keep_san_setting __setting = {
.name = "keep-san",
@@ -20,23 +20,7 @@ struct setting keep_san_setting __setting = {
.type = &setting_type_int8,
};
-/**
- * Guess boot network device
- *
- * @ret netdev Boot network device
- */
-static struct net_device * guess_boot_netdev ( void ) {
- struct net_device *boot_netdev;
-
- /* Just use the first network device */
- for_each_netdev ( boot_netdev ) {
- return boot_netdev;
- }
-
- return NULL;
-}
-
-int iscsiboot ( const char *root_path ) {
+static int iscsiboot ( const char *root_path ) {
struct scsi_device *scsi;
struct int13_drive *drive;
int keep_san;
@@ -69,7 +53,7 @@ int iscsiboot ( const char *root_path ) {
drive->blockdev = &scsi->blockdev;
/* FIXME: ugly, ugly hack */
- struct net_device *netdev = guess_boot_netdev();
+ struct net_device *netdev = last_opened_netdev();
struct iscsi_session *iscsi =
container_of ( scsi->backend, struct iscsi_session, refcnt );
ibft_fill_data ( netdev, iscsi );
@@ -100,3 +84,8 @@ int iscsiboot ( const char *root_path ) {
err_alloc_scsi:
return rc;
}
+
+struct sanboot_protocol iscsi_sanboot_protocol __sanboot_protocol = {
+ .prefix = "iscsi:",
+ .boot = iscsiboot,
+};
diff --git a/gpxe/src/arch/i386/core/umalloc.c b/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
index 3990488c..744d8e30 100644
--- a/gpxe/src/arch/i386/core/umalloc.c
+++ b/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
@@ -36,9 +36,6 @@
/** Equivalent of NOWHERE for user pointers */
#define UNOWHERE ( ~UNULL )
-/** Start of Etherboot text, as defined by the linker */
-extern char _text[];
-
/** An external memory block */
struct external_memory {
/** Size of this memory block (excluding this header) */
@@ -95,7 +92,7 @@ static int init_eheap ( void ) {
}
}
- if ( ! top ) {
+ if ( ! heap_size ) {
DBG ( "No external heap available\n" );
return -ENOMEM;
}
@@ -135,16 +132,16 @@ static void ecollect_free ( void ) {
* Calling realloc() with a new size of zero is a valid way to free a
* memory block.
*/
-userptr_t urealloc ( userptr_t ptr, size_t new_size ) {
+static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
struct external_memory extmem;
userptr_t new = ptr;
size_t align;
int rc;
/* Initialise external memory allocator if necessary */
- if ( ! top ) {
+ if ( bottom == top ) {
if ( ( rc = init_eheap() ) != 0 )
- return rc;
+ return UNULL;
}
/* Get block properties into extmem */
@@ -200,25 +197,4 @@ userptr_t urealloc ( userptr_t ptr, size_t new_size ) {
return ( new_size ? new : UNOWHERE );
}
-/**
- * Allocate external memory
- *
- * @v size Requested size
- * @ret ptr Memory, or UNULL
- *
- * Memory is guaranteed to be aligned to a page boundary.
- */
-userptr_t umalloc ( size_t size ) {
- return urealloc ( UNULL, size );
-}
-
-/**
- * Free external memory
- *
- * @v ptr Memory allocated by umalloc(), or UNULL
- *
- * If @c ptr is UNULL, no action is taken.
- */
-void ufree ( userptr_t ptr ) {
- urealloc ( ptr, 0 );
-}
+PROVIDE_UMALLOC ( memtop, urealloc, memtop_urealloc );
diff --git a/gpxe/src/arch/i386/core/pcibios.c b/gpxe/src/arch/i386/interface/pcbios/pcibios.c
index 1c93e4be..81b4fd3c 100644
--- a/gpxe/src/arch/i386/core/pcibios.c
+++ b/gpxe/src/arch/i386/interface/pcbios/pcibios.c
@@ -18,7 +18,6 @@
#include <stdint.h>
#include <gpxe/pci.h>
-#include <pcibios.h>
#include <realmode.h>
/** @file
@@ -32,7 +31,7 @@
*
* @ret max_bus Maximum bus number
*/
-int pcibios_max_bus ( void ) {
+static int pcibios_max_bus ( void ) {
int discard_a, discard_D;
uint8_t max_bus;
@@ -104,3 +103,11 @@ int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
return ( ( status >> 8 ) & 0xff );
}
+
+PROVIDE_PCIAPI ( pcbios, pci_max_bus, pcibios_max_bus );
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_byte );
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_word );
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_dword );
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_byte );
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_word );
+PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_dword );
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_call.c b/gpxe/src/arch/i386/interface/pxe/pxe_call.c
index 7122c4eb..04aaf3b2 100644
--- a/gpxe/src/arch/i386/interface/pxe/pxe_call.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_call.c
@@ -119,7 +119,7 @@ static PXENV_EXIT_t pxenv_unknown ( struct s_PXENV_UNKNOWN *pxenv_unknown ) {
* @v es:di Address of PXE parameter block
* @ret ax PXE exit code
*/
-__cdecl void pxe_api_call ( struct i386_all_regs *ix86 ) {
+__asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) {
int opcode = ix86->regs.bx;
userptr_t parameters = real_to_user ( ix86->segs.es, ix86->regs.di );
size_t param_len;
@@ -339,7 +339,7 @@ __cdecl void pxe_api_call ( struct i386_all_regs *ix86 ) {
* @v es:di Address of PXE parameter block
* @ret ax PXE exit code
*/
-__cdecl void pxe_loader_call ( struct i386_all_regs *ix86 ) {
+__asmcall void pxe_loader_call ( struct i386_all_regs *ix86 ) {
userptr_t uparams = real_to_user ( ix86->segs.es, ix86->regs.di );
struct s_UNDI_LOADER params;
PXENV_EXIT_t ret;
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_entry.S b/gpxe/src/arch/i386/interface/pxe/pxe_entry.S
index e5d327a5..68b7374f 100644
--- a/gpxe/src/arch/i386/interface/pxe/pxe_entry.S
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_entry.S
@@ -18,15 +18,12 @@
*/
.arch i386
- .section ".text16", "awx", @progbits
- .section ".text16.data", "aw", @progbits
- .section ".data16", "aw", @progbits
/****************************************************************************
* !PXE structure
****************************************************************************
*/
- .section ".text16.data"
+ .section ".text16.data", "aw", @progbits
.globl ppxe
.align 16
ppxe:
@@ -44,10 +41,10 @@ ppxe:
.byte SegDescCnt /* SegDescCnt */
.word 0 /* FirstSelector */
pxe_segments:
- .word 0, 0, 0, _data16_size /* Stack */
- .word 0, 0, 0, _data16_size /* UNDIData */
- .word 0, 0, 0, _text16_size /* UNDICode */
- .word 0, 0, 0, _text16_size /* UNDICodeWrite */
+ .word 0, 0, 0, _data16_memsz /* Stack */
+ .word 0, 0, 0, _data16_memsz /* UNDIData */
+ .word 0, 0, 0, _text16_memsz /* UNDICode */
+ .word 0, 0, 0, _text16_memsz /* UNDICodeWrite */
.word 0, 0, 0, 0 /* BC_Data */
.word 0, 0, 0, 0 /* BC_Code */
.word 0, 0, 0, 0 /* BC_CodeWrite */
@@ -56,7 +53,7 @@ pxe_segments:
.size ppxe, . - ppxe
/* Define undiheader=0 as a weak symbol for non-ROM builds */
- .section ".weak"
+ .section ".weak", "a", @nobits
.weak undiheader
undiheader:
@@ -64,7 +61,7 @@ undiheader:
* PXENV+ structure
****************************************************************************
*/
- .section ".text16.data"
+ .section ".text16.data", "aw", @progbits
.globl pxenv
.align 16
pxenv:
@@ -76,15 +73,15 @@ pxenv:
.long 0 /* PMEntry */
.word 0 /* PMSelector */
.word 0 /* StackSeg */
- .word _data16_size /* StackSize */
+ .word _data16_memsz /* StackSize */
.word 0 /* BC_CodeSeg */
.word 0 /* BC_CodeSize */
.word 0 /* BC_DataSeg */
.word 0 /* BC_DataSize */
.word 0 /* UNDIDataSeg */
- .word _data16_size /* UNDIDataSize */
+ .word _data16_memsz /* UNDIDataSize */
.word 0 /* UNDICodeSeg */
- .word _text16_size /* UNDICodeSize */
+ .word _text16_memsz /* UNDICodeSize */
.word ppxe, 0 /* PXEPtr */
.equ pxenv_length, . - pxenv
.size pxenv, . - pxenv
@@ -108,12 +105,12 @@ pxenv:
* somebody at Wyse has difficulty distinguishing between the
* words "may" and "must"...
*/
- .section ".text16.null"
+ .section ".text16.null", "ax", @progbits
.code16
pxenv_null_entry:
jmp pxenv_entry
- .section ".text16"
+ .section ".text16", "ax", @progbits
.code16
pxenv_entry:
pushl $pxe_api_call
@@ -137,7 +134,7 @@ pxenv_entry:
* none
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
.code16
pxe_entry:
pxe_entry_sp:
@@ -186,7 +183,7 @@ pxe_entry_common:
* none
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
.code16
.globl pxe_int_1a
pxe_int_1a:
@@ -205,6 +202,6 @@ pxe_int_1a:
popfw
ljmp *%cs:pxe_int_1a_vector
- .section ".text16.data"
+ .section ".text16.data", "aw", @progbits
.globl pxe_int_1a_vector
pxe_int_1a_vector: .long 0
diff --git a/gpxe/src/interface/pxe/pxe_errors.c b/gpxe/src/arch/i386/interface/pxe/pxe_errors.c
index f884ef8a..f884ef8a 100644
--- a/gpxe/src/interface/pxe/pxe_errors.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_errors.c
diff --git a/gpxe/src/interface/pxe/pxe_file.c b/gpxe/src/arch/i386/interface/pxe/pxe_file.c
index 41674588..41674588 100644
--- a/gpxe/src/interface/pxe/pxe_file.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_file.c
diff --git a/gpxe/src/interface/pxe/pxe_loader.c b/gpxe/src/arch/i386/interface/pxe/pxe_loader.c
index d228a36d..d228a36d 100644
--- a/gpxe/src/interface/pxe/pxe_loader.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_loader.c
diff --git a/gpxe/src/interface/pxe/pxe_preboot.c b/gpxe/src/arch/i386/interface/pxe/pxe_preboot.c
index 8220d1f2..193abc3d 100644
--- a/gpxe/src/interface/pxe/pxe_preboot.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_preboot.c
@@ -82,7 +82,7 @@ struct pxe_dhcp_packet_creator {
static struct pxe_dhcp_packet_creator pxe_dhcp_packet_creators[] = {
[CACHED_INFO_DHCPDISCOVER] = { create_fakedhcpdiscover },
[CACHED_INFO_DHCPACK] = { create_fakedhcpack },
- [CACHED_INFO_BINL] = { create_fakeproxydhcpack },
+ [CACHED_INFO_BINL] = { create_fakepxebsack },
};
/* The case in which the caller doesn't supply a buffer is really
diff --git a/gpxe/src/interface/pxe/pxe_tftp.c b/gpxe/src/arch/i386/interface/pxe/pxe_tftp.c
index f5e76206..715a0b61 100644
--- a/gpxe/src/interface/pxe/pxe_tftp.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_tftp.c
@@ -113,12 +113,6 @@ static int pxe_tftp_xfer_deliver_iob ( struct xfer_interface *xfer __unused,
/* Calculate new buffer position */
pxe_tftp.offset += len;
- /* Mildly ugly hack; assume that the first non-zero seek
- * indicates the block size.
- */
- if ( pxe_tftp.blksize == 0 )
- pxe_tftp.blksize = pxe_tftp.offset;
-
/* Record maximum offset as the file size */
if ( pxe_tftp.max_offset < pxe_tftp.offset )
pxe_tftp.max_offset = pxe_tftp.offset;
@@ -265,10 +259,12 @@ PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) {
/* Wait for OACK to arrive so that we have the block size */
while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) &&
- ( pxe_tftp.blksize == 0 ) ) {
+ ( pxe_tftp.max_offset == 0 ) ) {
step();
}
+ pxe_tftp.blksize = xfer_window ( &pxe_tftp.xfer );
tftp_open->PacketSize = pxe_tftp.blksize;
+ DBG ( " blksize=%d", tftp_open->PacketSize );
/* EINPROGRESS is normal; we don't wait for the whole transfer */
if ( rc == -EINPROGRESS )
@@ -485,7 +481,7 @@ PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
*tftp_read_file ) {
int rc;
- DBG ( "PXENV_TFTP_READ_FILE to %08lx+%lx", tftp_read_file->Buffer,
+ DBG ( "PXENV_TFTP_READ_FILE to %08x+%x", tftp_read_file->Buffer,
tftp_read_file->BufferSize );
/* Open TFTP file */
@@ -571,6 +567,7 @@ PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE
step();
}
tftp_get_fsize->FileSize = pxe_tftp.max_offset;
+ DBG ( " fsize=%d", tftp_get_fsize->FileSize );
/* EINPROGRESS is normal; we don't wait for the whole transfer */
if ( rc == -EINPROGRESS )
diff --git a/gpxe/src/interface/pxe/pxe_udp.c b/gpxe/src/arch/i386/interface/pxe/pxe_udp.c
index 033b1ad9..033b1ad9 100644
--- a/gpxe/src/interface/pxe/pxe_udp.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_udp.c
diff --git a/gpxe/src/interface/pxe/pxe_undi.c b/gpxe/src/arch/i386/interface/pxe/pxe_undi.c
index 5d06f2d8..4e4a3da0 100644
--- a/gpxe/src/interface/pxe/pxe_undi.c
+++ b/gpxe/src/arch/i386/interface/pxe/pxe_undi.c
@@ -199,9 +199,10 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
struct DataBlk *datablk;
struct io_buffer *iobuf;
struct net_protocol *net_protocol;
+ struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
char destaddr[MAX_LL_ADDR_LEN];
const void *ll_dest;
- size_t ll_hlen = pxe_netdev->ll_protocol->ll_header_len;
+ size_t ll_hlen = ll_protocol->ll_header_len;
size_t len;
unsigned int i;
int rc;
@@ -259,17 +260,17 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT
copy_from_real ( destaddr,
undi_transmit->DestAddr.segment,
undi_transmit->DestAddr.offset,
- pxe_netdev->ll_protocol->ll_addr_len );
+ ll_protocol->ll_addr_len );
ll_dest = destaddr;
} else {
DBG ( " BCAST" );
- ll_dest = pxe_netdev->ll_protocol->ll_broadcast;
+ ll_dest = ll_protocol->ll_broadcast;
}
/* Add link-layer header */
- if ( ( rc = pxe_netdev->ll_protocol->push ( iobuf, pxe_netdev,
- net_protocol,
- ll_dest )) != 0 ){
+ if ( ( rc = ll_protocol->push ( iobuf, ll_dest,
+ pxe_netdev->ll_addr,
+ net_protocol->net_proto ))!=0){
free_iob ( iobuf );
undi_transmit->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE;
@@ -391,10 +392,10 @@ PXENV_EXIT_t pxenv_undi_get_statistics ( struct s_PXENV_UNDI_GET_STATISTICS
*undi_get_statistics ) {
DBG ( "PXENV_UNDI_GET_STATISTICS" );
- undi_get_statistics->XmtGoodFrames = pxe_netdev->stats.tx_ok;
- undi_get_statistics->RcvGoodFrames = pxe_netdev->stats.rx_ok;
- undi_get_statistics->RcvCRCErrors = pxe_netdev->stats.rx_err;
- undi_get_statistics->RcvResourceErrors = pxe_netdev->stats.rx_err;
+ undi_get_statistics->XmtGoodFrames = pxe_netdev->tx_stats.good;
+ undi_get_statistics->RcvGoodFrames = pxe_netdev->rx_stats.good;
+ undi_get_statistics->RcvCRCErrors = pxe_netdev->rx_stats.bad;
+ undi_get_statistics->RcvResourceErrors = pxe_netdev->rx_stats.bad;
undi_get_statistics->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
@@ -408,7 +409,8 @@ PXENV_EXIT_t pxenv_undi_clear_statistics ( struct s_PXENV_UNDI_CLEAR_STATISTICS
*undi_clear_statistics ) {
DBG ( "PXENV_UNDI_CLEAR_STATISTICS" );
- memset ( &pxe_netdev->stats, 0, sizeof ( pxe_netdev->stats ) );
+ memset ( &pxe_netdev->tx_stats, 0, sizeof ( pxe_netdev->tx_stats ) );
+ memset ( &pxe_netdev->rx_stats, 0, sizeof ( pxe_netdev->rx_stats ) );
undi_clear_statistics->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
@@ -545,6 +547,7 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
struct io_buffer *iobuf;
size_t len;
struct ll_protocol *ll_protocol;
+ const void *ll_dest;
const void *ll_source;
uint16_t net_proto;
size_t ll_hlen;
@@ -625,9 +628,8 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
/* Strip link-layer header */
ll_protocol = pxe_netdev->ll_protocol;
- if ( ( rc = ll_protocol->pull ( iobuf, pxe_netdev,
- &net_proto,
- &ll_source ) ) != 0 ) {
+ if ( ( rc = ll_protocol->pull ( iobuf, &ll_dest, &ll_source,
+ &net_proto ) ) != 0 ) {
/* Assume unknown net_proto and no ll_source */
net_proto = 0;
ll_source = NULL;
diff --git a/gpxe/src/arch/i386/interface/syslinux/com32_call.c b/gpxe/src/arch/i386/interface/syslinux/com32_call.c
index 586730cf..4a782dce 100644
--- a/gpxe/src/arch/i386/interface/syslinux/com32_call.c
+++ b/gpxe/src/arch/i386/interface/syslinux/com32_call.c
@@ -41,7 +41,7 @@ uint16_t __bss16 ( com32_saved_sp );
/**
* Interrupt call helper
*/
-void __cdecl com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
+void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
memcpy_user ( virt_to_user( &com32_regs ), 0,
phys_to_user ( inregs_phys ), 0,
@@ -111,7 +111,7 @@ void __cdecl com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physaddr
/**
* Farcall helper
*/
-void __cdecl com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
+void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
memcpy_user ( virt_to_user( &com32_regs ), 0,
phys_to_user ( inregs_phys ), 0,
@@ -170,7 +170,7 @@ void __cdecl com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t o
/**
* CDECL farcall helper
*/
-int __cdecl com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz ) {
+int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz ) {
int32_t eax;
copy_user_to_rm_stack ( phys_to_user ( stack ), stacksz );
diff --git a/gpxe/src/arch/i386/interface/syslinux/comboot_call.c b/gpxe/src/arch/i386/interface/syslinux/comboot_call.c
index 5a400ede..bf6c4c66 100644
--- a/gpxe/src/arch/i386/interface/syslinux/comboot_call.c
+++ b/gpxe/src/arch/i386/interface/syslinux/comboot_call.c
@@ -35,6 +35,8 @@
#include <gpxe/process.h>
#include <gpxe/serial.h>
#include <gpxe/init.h>
+#include <gpxe/image.h>
+#include <usr/imgmgmt.h>
/** The "SYSLINUX" version string */
static char __data16_array ( syslinux_version, [] ) = "gPXE " VERSION;
@@ -51,6 +53,14 @@ static char __data16_array ( syslinux_configuration_file, [] ) = "";
static uint8_t __data16 ( comboot_feature_flags ) = COMBOOT_FEATURE_IDLE_LOOP;
#define comboot_feature_flags __use_data16 ( comboot_feature_flags )
+typedef union {
+ syslinux_pm_regs pm; syslinux_rm_regs rm;
+} syslinux_regs;
+
+/** Initial register values for INT 22h AX=1Ah and 1Bh */
+static syslinux_regs __text16 ( comboot_initial_regs );
+#define comboot_initial_regs __use_text16 ( comboot_initial_regs )
+
static struct segoff __text16 ( int20_vector );
#define int20_vector __use_text16 ( int20_vector )
@@ -65,12 +75,10 @@ extern void int21_wrapper ( void );
extern void int22_wrapper ( void );
/* setjmp/longjmp context buffer used to return after loading an image */
-jmp_buf comboot_return;
+rmjmp_buf comboot_return;
-/* Command line to execute when returning via comboot_return
- * with COMBOOT_RETURN_RUN_KERNEL
- */
-char *comboot_kernel_cmdline;
+/* Replacement image when exiting with COMBOOT_EXIT_RUN_KERNEL */
+struct image *comboot_replacement_image;
/* Mode flags set by INT 22h AX=0017h */
static uint16_t comboot_graphics_mode = 0;
@@ -154,79 +162,101 @@ void comboot_force_text_mode ( void ) {
/**
- * Run the kernel specified in comboot_kernel_cmdline
+ * Fetch kernel and optional initrd
*/
-void comboot_run_kernel ( )
-{
- char *initrd;
-
- comboot_force_text_mode ( );
-
- DBG ( "COMBOOT: executing image '%s'\n", comboot_kernel_cmdline );
+static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) {
+ struct image *kernel = NULL;
+ struct image *initrd = NULL;
+ char *initrd_file;
+ int rc;
/* Find initrd= parameter, if any */
- if ( ( initrd = strstr ( comboot_kernel_cmdline, "initrd=" ) ) ) {
- char old_char = '\0';
- char *initrd_end = strchr( initrd, ' ' );
-
- /* Replace space after end of parameter
- * with a nul terminator if this is not
- * the last parameter
- */
- if ( initrd_end ) {
- old_char = *initrd_end;
- *initrd_end = '\0';
- }
+ if ( ( initrd_file = strstr ( cmdline, "initrd=" ) ) != NULL ) {
+ char *initrd_end;
- /* Replace = with space to get 'initrd filename'
- * command suitable for system()
- */
- initrd[6] = ' ';
+ /* skip "initrd=" */
+ initrd_file += 7;
- DBG( "COMBOOT: loading initrd '%s'\n", initrd );
+ /* Find terminating space, if any, and replace with NUL */
+ initrd_end = strchr ( initrd_file, ' ' );
+ if ( initrd_end )
+ *initrd_end = '\0';
- system ( initrd );
+ DBG ( "COMBOOT: fetching initrd '%s'\n", initrd_file );
- /* Restore space after parameter */
- if ( initrd_end ) {
- *initrd_end = old_char;
+ /* Allocate and fetch initrd */
+ initrd = alloc_image();
+ if ( ! initrd ) {
+ DBG ( "COMBOOT: could not allocate initrd\n" );
+ rc = -ENOMEM;
+ goto out;
+ }
+ if ( ( rc = imgfetch ( initrd, initrd_file,
+ register_image ) ) != 0 ) {
+ DBG ( "COMBOOT: could not fetch initrd: %s\n",
+ strerror ( rc ) );
+ goto out;
}
- /* Restore = */
- initrd[6] = '=';
+ /* Restore space after initrd name, if applicable */
+ if ( initrd_end )
+ *initrd_end = ' ';
}
- /* Load kernel */
- DBG ( "COMBOOT: loading kernel '%s'\n", comboot_kernel_cmdline );
- system ( comboot_kernel_cmdline );
-
- free ( comboot_kernel_cmdline );
+ DBG ( "COMBOOT: fetching kernel '%s'\n", kernel_file );
- /* Boot */
- system ( "boot" );
+ /* Allocate and fetch kernel */
+ kernel = alloc_image();
+ if ( ! kernel ) {
+ DBG ( "COMBOOT: could not allocate kernel\n" );
+ rc = -ENOMEM;
+ goto out;
+ }
+ if ( ( rc = imgfetch ( kernel, kernel_file,
+ register_image ) ) != 0 ) {
+ DBG ( "COMBOOT: could not fetch kernel: %s\n",
+ strerror ( rc ) );
+ goto out;
+ }
+ if ( ( rc = image_set_cmdline ( kernel, cmdline ) ) != 0 ) {
+ DBG ( "COMBOOT: could not set kernel command line: %s\n",
+ strerror ( rc ) );
+ goto out;
+ }
- DBG ( "COMBOOT: back from executing command\n" );
+ /* Store kernel as replacement image */
+ assert ( comboot_replacement_image == NULL );
+ comboot_replacement_image = image_get ( kernel );
+
+ out:
+ /* Drop image references unconditionally; either we want to
+ * discard them, or they have been registered and we should
+ * drop out local reference.
+ */
+ image_put ( kernel );
+ image_put ( initrd );
+ return rc;
}
/**
* Terminate program interrupt handler
*/
-static __cdecl void int20 ( struct i386_all_regs *ix86 __unused ) {
- longjmp ( comboot_return, COMBOOT_RETURN_EXIT );
+static __asmcall void int20 ( struct i386_all_regs *ix86 __unused ) {
+ rmlongjmp ( comboot_return, COMBOOT_EXIT );
}
/**
* DOS-compatible API
*/
-static __cdecl void int21 ( struct i386_all_regs *ix86 ) {
+static __asmcall void int21 ( struct i386_all_regs *ix86 ) {
ix86->flags |= CF;
switch ( ix86->regs.ah ) {
case 0x00:
case 0x4C: /* Terminate program */
- longjmp ( comboot_return, COMBOOT_RETURN_EXIT );
+ rmlongjmp ( comboot_return, COMBOOT_EXIT );
break;
case 0x01: /* Get Key with Echo */
@@ -287,14 +317,14 @@ static __cdecl void int21 ( struct i386_all_regs *ix86 ) {
/**
* SYSLINUX API
*/
-static __cdecl void int22 ( struct i386_all_regs *ix86 ) {
+static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
ix86->flags |= CF;
switch ( ix86->regs.ax ) {
case 0x0001: /* Get Version */
/* Number of INT 22h API functions available */
- ix86->regs.ax = 0x0018;
+ ix86->regs.ax = 0x001B;
/* SYSLINUX version number */
ix86->regs.ch = 0; /* major */
@@ -323,17 +353,15 @@ static __cdecl void int22 ( struct i386_all_regs *ix86 ) {
char cmd[len + 1];
copy_from_user ( cmd, cmd_u, 0, len + 1 );
DBG ( "COMBOOT: executing command '%s'\n", cmd );
-
- comboot_kernel_cmdline = strdup ( cmd );
-
- DBG ( "COMBOOT: returning to run image...\n" );
- longjmp ( comboot_return, COMBOOT_RETURN_RUN_KERNEL );
+ system ( cmd );
+ DBG ( "COMBOOT: exiting after executing command...\n" );
+ rmlongjmp ( comboot_return, COMBOOT_EXIT_COMMAND );
}
break;
case 0x0004: /* Run default command */
/* FIXME: just exit for now */
- longjmp ( comboot_return, COMBOOT_RETURN_EXIT );
+ rmlongjmp ( comboot_return, COMBOOT_EXIT_COMMAND );
break;
case 0x0005: /* Force text mode */
@@ -518,21 +546,21 @@ static __cdecl void int22 ( struct i386_all_regs *ix86 ) {
userptr_t cmd_u = real_to_user ( ix86->segs.es, ix86->regs.bx );
int file_len = strlen_user ( file_u, 0 );
int cmd_len = strlen_user ( cmd_u, 0 );
- char file[file_len + 1 + cmd_len + 7 + 1];
+ char file[file_len + 1];
char cmd[cmd_len + 1];
- memcpy( file, "kernel ", 7 );
- copy_from_user ( file + 7, file_u, 0, file_len + 1 );
+ copy_from_user ( file, file_u, 0, file_len + 1 );
copy_from_user ( cmd, cmd_u, 0, cmd_len + 1 );
- strcat ( file, " " );
- strcat ( file, cmd );
-
- DBG ( "COMBOOT: run kernel image '%s'\n", file );
- comboot_kernel_cmdline = strdup ( file );
-
- DBG ( "COMBOOT: returning to run image...\n" );
- longjmp ( comboot_return, COMBOOT_RETURN_RUN_KERNEL );
+ DBG ( "COMBOOT: run kernel %s %s\n", file, cmd );
+ comboot_fetch_kernel ( file, cmd );
+ /* Technically, we should return if we
+ * couldn't load the kernel, but it's not safe
+ * to do that since we have just overwritten
+ * part of the COMBOOT program's memory space.
+ */
+ DBG ( "COMBOOT: exiting to run kernel...\n" );
+ rmlongjmp ( comboot_return, COMBOOT_EXIT_RUN_KERNEL );
}
break;
@@ -549,6 +577,58 @@ static __cdecl void int22 ( struct i386_all_regs *ix86 ) {
ix86->flags &= ~CF;
break;
+ case 0x001B: /* Cleanup, shuffle and boot to real mode */
+ if ( ix86->regs.cx > COMBOOT_MAX_SHUFFLE_DESCRIPTORS )
+ break;
+
+ /* Perform final cleanup */
+ shutdown ( SHUTDOWN_BOOT );
+
+ /* Perform sequence of copies */
+ shuffle ( ix86->segs.es, ix86->regs.di, ix86->regs.cx );
+
+ /* Copy initial register values to .text16 */
+ memcpy_user ( real_to_user ( rm_cs, (unsigned) __from_text16 ( &comboot_initial_regs ) ), 0,
+ real_to_user ( ix86->segs.ds, ix86->regs.si ), 0,
+ sizeof(syslinux_rm_regs) );
+
+ /* Load initial register values */
+ __asm__ __volatile__ (
+ REAL_CODE (
+ /* Point SS:SP at the register value structure */
+ "pushw %%cs\n\t"
+ "popw %%ss\n\t"
+ "movw $comboot_initial_regs, %%sp\n\t"
+
+ /* Segment registers */
+ "popw %%es\n\t"
+ "popw %%ax\n\t" /* Skip CS */
+ "popw %%ds\n\t"
+ "popw %%ax\n\t" /* Skip SS for now */
+ "popw %%fs\n\t"
+ "popw %%gs\n\t"
+
+ /* GP registers */
+ "popl %%eax\n\t"
+ "popl %%ecx\n\t"
+ "popl %%edx\n\t"
+ "popl %%ebx\n\t"
+ "popl %%ebp\n\t" /* Skip ESP for now */
+ "popl %%ebp\n\t"
+ "popl %%esi\n\t"
+ "popl %%edi\n\t"
+
+ /* Load correct SS:ESP */
+ "movw $(comboot_initial_regs + 6), %%sp\n\t"
+ "popw %%ss\n\t"
+ "movl %%cs:(comboot_initial_regs + 28), %%esp\n\t"
+
+ "ljmp *%%cs:(comboot_initial_regs + 44)\n\t"
+ )
+ : : );
+
+ break;
+
default:
DBG ( "COMBOOT unknown int22 function %04x\n", ix86->regs.ax );
break;
@@ -596,3 +676,18 @@ void hook_comboot_interrupts ( ) {
hook_bios_interrupt ( 0x22, ( unsigned int ) int22_wrapper,
&int22_vector );
}
+
+/**
+ * Unhook BIOS interrupts related to COMBOOT API (INT 20h, 21h, 22h)
+ */
+void unhook_comboot_interrupts ( ) {
+
+ unhook_bios_interrupt ( 0x20, ( unsigned int ) int20_wrapper,
+ &int20_vector );
+
+ unhook_bios_interrupt ( 0x21, ( unsigned int ) int21_wrapper,
+ &int21_vector );
+
+ unhook_bios_interrupt ( 0x22, ( unsigned int ) int22_wrapper,
+ &int22_vector );
+}
diff --git a/gpxe/src/arch/i386/prefix/boot1a.S b/gpxe/src/arch/i386/prefix/boot1a.S
new file mode 100644
index 00000000..557462f1
--- /dev/null
+++ b/gpxe/src/arch/i386/prefix/boot1a.S
@@ -0,0 +1,410 @@
+# This code is no longer used in Etherboot. It is not maintained and
+# may not work.
+
+
+#
+# Copyright (c) 1998 Robert Nordier
+# All rights reserved.
+# Very small bootrom changes by Luigi Rizzo
+# <comment author="Luigi Rizzo">
+# I recently had the problem of downloading the etherboot code
+# from a hard disk partition instead of a floppy, and noticed that
+# floppyload.S does not do the job. With a bit of hacking to
+# the FreeBSD's boot1.s code, I managed to obtain a boot sector
+# which works both for floppies and hard disks -- basically you
+# do something like
+#
+# cat boot1a bin32/<yourcard>.lzrom > /dev/ad0s4
+#
+# (or whatever is the HD partition you are using, I am using slice
+# 4 on FreeBSD) and you are up and running.
+# Then with "fdisk" you have to mark your partition as having type "1"
+# (which is listed as DOS-- but basically it must be something matching
+# the variable PRT_BSD in the assembly source below).
+# </comment>
+#
+# Redistribution and use in source and binary forms are freely
+# permitted provided that the above copyright notice and this
+# paragraph and the following disclaimer are duplicated in all
+# such forms.
+#
+# This software is provided "AS IS" and without any express or
+# implied warranties, including, without limitation, the implied
+# warranties of merchantability and fitness for a particular
+# purpose.
+#
+# Makefile:
+#boot1a: boot1a.out
+# objcopy -S -O binary boot1a.out boot1a
+#
+#boot1a.out: boot1a.o
+# ld -nostdlib -static -N -e start -Ttext 0x7c00 -o boot1a.out boot1a.o
+#
+#boot1a.o: boot1a.s
+# as --defsym FLAGS=0x80 boot1a.s -o boot1a.o
+#
+#
+
+# $FreeBSD: src/sys/boot/i386/boot2/boot1.s,v 1.10.2.2 2000/07/07 21:12:32 jhb Exp $
+
+# Memory Locations
+ .set MEM_REL,0x700 # Relocation address
+ .set MEM_ARG,0x900 # Arguments
+ .set MEM_ORG,0x7c00 # Origin
+ .set MEM_BUF,0x8c00 # Load area
+ .set MEM_BTX,0x9000 # BTX start
+ .set MEM_JMP,0x9010 # BTX entry point
+ .set MEM_USR,0xa000 # Client start
+ .set BDA_BOOT,0x472 # Boot howto flag
+
+# Partition Constants
+ .set PRT_OFF,0x1be # Partition offset
+ .set PRT_NUM,0x4 # Partitions
+ .set PRT_BSD,0x1 # Partition type
+
+# Flag Bits
+ .set FL_PACKET,0x80 # Packet mode
+
+# Misc. Constants
+ .set SIZ_PAG,0x1000 # Page size
+ .set SIZ_SEC,0x200 # Sector size
+
+ .globl start
+ .globl xread
+ .code16
+
+start: jmp main # Start recognizably
+
+ .org 0x4,0x90
+#
+# Trampoline used by boot2 to call read to read data from the disk via
+# the BIOS. Call with:
+#
+# %cx:%ax - long - LBA to read in
+# %es:(%bx) - caddr_t - buffer to read data into
+# %dl - byte - drive to read from
+# %dh - byte - num sectors to read
+#
+
+xread: push %ss # Address
+ pop %ds # data
+#
+# Setup an EDD disk packet and pass it to read
+#
+xread.1: # Starting
+ pushl $0x0 # absolute
+ push %cx # block
+ push %ax # number
+ push %es # Address of
+ push %bx # transfer buffer
+ xor %ax,%ax # Number of
+ movb %dh,%al # blocks to
+ push %ax # transfer
+ push $0x10 # Size of packet
+ mov %sp,%bp # Packet pointer
+ callw read # Read from disk
+ lea 0x10(%bp),%sp # Clear stack
+ lret # To far caller
+#
+# Load the rest of boot2 and BTX up, copy the parts to the right locations,
+# and start it all up.
+#
+
+#
+# Setup the segment registers to flat addressing (segment 0) and setup the
+# stack to end just below the start of our code.
+#
+main: cld # String ops inc
+ xor %cx,%cx # Zero
+ mov %cx,%es # Address
+ mov %cx,%ds # data
+ mov %cx,%ss # Set up
+ mov $start,%sp # stack
+#
+# Relocate ourself to MEM_REL. Since %cx == 0, the inc %ch sets
+# %cx == 0x100.
+#
+ mov %sp,%si # Source
+ mov $MEM_REL,%di # Destination
+ incb %ch # Word count
+ rep # Copy
+ movsw # code
+#
+# If we are on a hard drive, then load the MBR and look for the first
+# FreeBSD slice. We use the fake partition entry below that points to
+# the MBR when we call nread. The first pass looks for the first active
+# FreeBSD slice. The second pass looks for the first non-active FreeBSD
+# slice if the first one fails.
+#
+ mov $part4,%si # Partition
+ cmpb $0x80,%dl # Hard drive?
+ jb main.4 # No
+ movb $0x1,%dh # Block count
+ callw nread # Read MBR
+ mov $0x1,%cx # Two passes
+main.1: mov $MEM_BUF+PRT_OFF,%si # Partition table
+ movb $0x1,%dh # Partition
+main.2: cmpb $PRT_BSD,0x4(%si) # Our partition type?
+ jne main.3 # No
+ jcxz main.5 # If second pass
+ testb $0x80,(%si) # Active?
+ jnz main.5 # Yes
+main.3: add $0x10,%si # Next entry
+ incb %dh # Partition
+ cmpb $0x1+PRT_NUM,%dh # In table?
+ jb main.2 # Yes
+ dec %cx # Do two
+ jcxz main.1 # passes
+#
+# If we get here, we didn't find any FreeBSD slices at all, so print an
+# error message and die.
+#
+booterror: mov $msg_part,%si # Message
+ jmp error # Error
+#
+# Floppies use partition 0 of drive 0.
+#
+main.4: xor %dx,%dx # Partition:drive
+#
+# Ok, we have a slice and drive in %dx now, so use that to locate and load
+# boot2. %si references the start of the slice we are looking for, so go
+# ahead and load up the first 16 sectors (boot1 + boot2) from that. When
+# we read it in, we conveniently use 0x8c00 as our transfer buffer. Thus,
+# boot1 ends up at 0x8c00, and boot2 starts at 0x8c00 + 0x200 = 0x8e00.
+# The first part of boot2 is the disklabel, which is 0x200 bytes long.
+# The second part is BTX, which is thus loaded into 0x9000, which is where
+# it also runs from. The boot2.bin binary starts right after the end of
+# BTX, so we have to figure out where the start of it is and then move the
+# binary to 0xb000. Normally, BTX clients start at MEM_USR, or 0xa000, but
+# when we use btxld create boot2, we use an entry point of 0x1000. That
+# entry point is relative to MEM_USR; thus boot2.bin starts at 0xb000.
+#
+main.5: mov %dx,MEM_ARG # Save args
+ movb $0x2,%dh # Sector count
+ mov $0x7e00, %bx
+ callw nreadbx # Read disk
+ movb $0x40,%dh # Sector count
+ movb %dh, %al
+ callw puthex
+ mov $0x7e00, %bx
+ callw nreadbx # Read disk
+ push %si
+ mov $msg_r1,%si
+ callw putstr
+ pop %si
+ lcall $0x800,$0 # enter the rom code
+ int $0x19
+
+msg_r1: .asciz " done\r\n"
+
+.if 0
+ mov $MEM_BTX,%bx # BTX
+ mov 0xa(%bx),%si # Get BTX length and set
+ add %bx,%si # %si to start of boot2.bin
+ mov $MEM_USR+SIZ_PAG,%di # Client page 1
+ mov $MEM_BTX+0xe*SIZ_SEC,%cx # Byte
+ sub %si,%cx # count
+ rep # Relocate
+ movsb # client
+ sub %di,%cx # Byte count
+ xorb %al,%al # Zero assumed bss from
+ rep # the end of boot2.bin
+ stosb # up to 0x10000
+ callw seta20 # Enable A20
+ jmp start+MEM_JMP-MEM_ORG # Start BTX
+#
+# Enable A20 so we can access memory above 1 meg.
+#
+seta20: cli # Disable interrupts
+seta20.1: inb $0x64,%al # Get status
+ testb $0x2,%al # Busy?
+ jnz seta20.1 # Yes
+ movb $0xd1,%al # Command: Write
+ outb %al,$0x64 # output port
+seta20.2: inb $0x64,%al # Get status
+ testb $0x2,%al # Busy?
+ jnz seta20.2 # Yes
+ movb $0xdf,%al # Enable
+ outb %al,$0x60 # A20
+ sti # Enable interrupts
+ retw # To caller
+.endif
+#
+# Trampoline used to call read from within boot1.
+#
+nread: mov $MEM_BUF,%bx # Transfer buffer
+nreadbx: # same but address is in bx
+ mov 0x8(%si),%ax # Get
+ mov 0xa(%si),%cx # LBA
+ push %bx
+ push %ax
+ callw putword
+ pop %ax
+ pop %bx
+ push %cs # Read from
+ callw xread.1 # disk
+ jnc return # If success, return
+ mov $msg_read,%si # Otherwise, set the error
+ # message and fall through to
+ # the error routine
+#
+# Print out the error message pointed to by %ds:(%si) followed
+# by a prompt, wait for a keypress, and then reboot the machine.
+#
+error: callw putstr # Display message
+ mov $prompt,%si # Display
+ callw putstr # prompt
+ xorb %ah,%ah # BIOS: Get
+ int $0x16 # keypress
+ movw $0x1234, BDA_BOOT # Do a warm boot
+ ljmp $0xffff,$0x0 # reboot the machine
+#
+# Display a null-terminated string using the BIOS output.
+#
+putstr.0: call putchar
+putstr: lodsb # Get char
+ testb %al,%al # End of string?
+ jne putstr.0 # No
+ retw
+
+putword: push %ax
+ movb $'.', %al
+ callw putchar
+ movb %ah, %al
+ callw puthex
+ pop %ax
+puthex: push %ax
+ shr $4, %al
+ callw putdigit
+ pop %ax
+putdigit:
+ andb $0xf, %al
+ addb $0x30, %al
+ cmpb $0x39, %al
+ jbe putchar
+ addb $7, %al
+putchar: push %ax
+ mov $0x7,%bx
+ movb $0xe,%ah
+ int $0x10
+ pop %ax
+ retw
+
+#
+# Overused return code. ereturn is used to return an error from the
+# read function. Since we assume putstr succeeds, we (ab)use the
+# same code when we return from putstr.
+#
+ereturn: movb $0x1,%ah # Invalid
+ stc # argument
+return: retw # To caller
+#
+# Reads sectors from the disk. If EDD is enabled, then check if it is
+# installed and use it if it is. If it is not installed or not enabled, then
+# fall back to using CHS. Since we use a LBA, if we are using CHS, we have to
+# fetch the drive parameters from the BIOS and divide it out ourselves.
+# Call with:
+#
+# %dl - byte - drive number
+# stack - 10 bytes - EDD Packet
+#
+read: push %dx # Save
+ movb $0x8,%ah # BIOS: Get drive
+ int $0x13 # parameters
+ movb %dh,%ch # Max head number
+ pop %dx # Restore
+ jc return # If error
+ andb $0x3f,%cl # Sectors per track
+ jz ereturn # If zero
+ cli # Disable interrupts
+ mov 0x8(%bp),%eax # Get LBA
+ push %dx # Save
+ movzbl %cl,%ebx # Divide by
+ xor %edx,%edx # sectors
+ div %ebx # per track
+ movb %ch,%bl # Max head number
+ movb %dl,%ch # Sector number
+ inc %bx # Divide by
+ xorb %dl,%dl # number
+ div %ebx # of heads
+ movb %dl,%bh # Head number
+ pop %dx # Restore
+ cmpl $0x3ff,%eax # Cylinder number supportable?
+ sti # Enable interrupts
+ ja read.7 # No, try EDD
+ xchgb %al,%ah # Set up cylinder
+ rorb $0x2,%al # number
+ orb %ch,%al # Merge
+ inc %ax # sector
+ xchg %ax,%cx # number
+ movb %bh,%dh # Head number
+ subb %ah,%al # Sectors this track
+ mov 0x2(%bp),%ah # Blocks to read
+ cmpb %ah,%al # To read
+ jb read.2 # this
+ movb %ah,%al # track
+read.2: mov $0x5,%di # Try count
+read.3: les 0x4(%bp),%bx # Transfer buffer
+ push %ax # Save
+ movb $0x2,%ah # BIOS: Read
+ int $0x13 # from disk
+ pop %bx # Restore
+ jnc read.4 # If success
+ dec %di # Retry?
+ jz read.6 # No
+ xorb %ah,%ah # BIOS: Reset
+ int $0x13 # disk system
+ xchg %bx,%ax # Block count
+ jmp read.3 # Continue
+read.4: movzbw %bl,%ax # Sectors read
+ add %ax,0x8(%bp) # Adjust
+ jnc read.5 # LBA,
+ incw 0xa(%bp) # transfer
+read.5: shlb %bl # buffer
+ add %bl,0x5(%bp) # pointer,
+ sub %al,0x2(%bp) # block count
+ ja read # If not done
+read.6: retw # To caller
+read.7: testb $FL_PACKET,%cs:MEM_REL+flags-start # LBA support enabled?
+ jz ereturn # No, so return an error
+ mov $0x55aa,%bx # Magic
+ push %dx # Save
+ movb $0x41,%ah # BIOS: Check
+ int $0x13 # extensions present
+ pop %dx # Restore
+ jc return # If error, return an error
+ cmp $0xaa55,%bx # Magic?
+ jne ereturn # No, so return an error
+ testb $0x1,%cl # Packet interface?
+ jz ereturn # No, so return an error
+ mov %bp,%si # Disk packet
+ movb $0x42,%ah # BIOS: Extended
+ int $0x13 # read
+ retw # To caller
+
+# Messages
+
+msg_read: .asciz "Rd"
+msg_part: .asciz "Boot"
+
+prompt: .asciz " err\r\n"
+
+flags: .byte FLAGS # Flags
+
+ .org PRT_OFF,0x90
+
+# Partition table
+
+ .fill 0x30,0x1,0x0
+part4: .byte 0x80
+ .byte 0x00 # start head
+ .byte 0x01 # start sector (6 bits) + start cyl (2 bit)
+ .byte 0x00 # start cyl (low 8 bits)
+ .byte 0x1 # part.type
+ .byte 0xff # end head
+ .byte 0xff # end sect (6) + end_cyl(2)
+ .byte 0xff # end cyl
+ .byte 0x00, 0x00, 0x00, 0x00 # explicit start
+ .byte 0x50, 0xc3, 0x00, 0x00 # 50000 sectors long, bleh
+
+ .word 0xaa55 # Magic number
diff --git a/gpxe/src/arch/i386/prefix/dskprefix.S b/gpxe/src/arch/i386/prefix/dskprefix.S
index cdc43b37..0156812a 100644
--- a/gpxe/src/arch/i386/prefix/dskprefix.S
+++ b/gpxe/src/arch/i386/prefix/dskprefix.S
@@ -144,8 +144,8 @@ got_sectors:
/* Jump to loaded copy */
ljmp $SYSSEG, $start_runtime
-endseg: .word SYSSEG + _load_size_pgh
- .section ".zinfo.fixup", "a" /* Compressor fixup information */
+endseg: .word SYSSEG + _filesz_pgh
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii "SUBW"
.long endseg
.long 16
@@ -353,6 +353,7 @@ msg1end:
.word 0xAA55
start_runtime:
+ /* Install gPXE */
call install
/* Set up real-mode stack */
@@ -368,7 +369,10 @@ start_runtime:
pushl $main
pushw %cs
call prot_call
- popl %eax /* discard */
+ popl %ecx /* discard */
+
+ /* Uninstall gPXE */
+ call uninstall
/* Boot next device */
int $0x18
diff --git a/gpxe/src/arch/i386/prefix/hdprefix.S b/gpxe/src/arch/i386/prefix/hdprefix.S
index 56fcb36d..086d7f45 100644
--- a/gpxe/src/arch/i386/prefix/hdprefix.S
+++ b/gpxe/src/arch/i386/prefix/hdprefix.S
@@ -63,9 +63,9 @@ max_sector:
max_head:
.byte 0
load_length:
- .long _load_size_sect
+ .long _filesz_sect
- .section ".zinfo.fixup", "a" /* Compressor fixup information */
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii "SUBL"
.long load_length
.long 512
@@ -82,6 +82,7 @@ load_failed:
.byte 0x55, 0xaa
start_image:
+ /* Install gPXE */
call install
/* Set up real-mode stack */
@@ -97,7 +98,10 @@ start_image:
pushl $main
pushw %cs
call prot_call
- popl %eax /* discard */
+ popl %ecx /* discard */
+
+ /* Uninstall gPXE */
+ call uninstall
/* Boot next device */
int $0x18
diff --git a/gpxe/src/arch/i386/prefix/kkpxeprefix.S b/gpxe/src/arch/i386/prefix/kkpxeprefix.S
new file mode 100644
index 00000000..e0bea0cd
--- /dev/null
+++ b/gpxe/src/arch/i386/prefix/kkpxeprefix.S
@@ -0,0 +1,8 @@
+/*****************************************************************************
+ * PXE prefix that keeps the whole PXE stack present
+ *****************************************************************************
+ */
+
+#define PXELOADER_KEEP_UNDI
+#define PXELOADER_KEEP_PXE
+#include "pxeprefix.S"
diff --git a/gpxe/src/arch/i386/prefix/libprefix.S b/gpxe/src/arch/i386/prefix/libprefix.S
index ae2a491f..42189135 100644
--- a/gpxe/src/arch/i386/prefix/libprefix.S
+++ b/gpxe/src/arch/i386/prefix/libprefix.S
@@ -18,8 +18,6 @@
*/
.arch i386
- .section ".prefix.lib", "awx", @progbits
- .section ".data16", "aw", @progbits
/**
* High memory temporary load address
@@ -53,7 +51,7 @@
* %ds:di : next character in output buffer (if applicable)
*****************************************************************************
*/
- .section ".prefix.lib"
+ .section ".prefix.lib", "awx", @progbits
.code16
.globl print_character
print_character:
@@ -93,7 +91,7 @@ print_character:
* %ds:di : next character in output buffer (if applicable)
*****************************************************************************
*/
- .section ".prefix.lib"
+ .section ".prefix.lib", "awx", @progbits
.code16
.globl print_message
print_message:
@@ -123,7 +121,7 @@ print_message:
* %ds:di : next character in output buffer (if applicable)
*****************************************************************************
*/
- .section ".prefix.lib"
+ .section ".prefix.lib", "awx", @progbits
.code16
.globl print_hex_dword
print_hex_dword:
@@ -171,7 +169,7 @@ print_hex_nibble:
* %ds:di : next character in output buffer (if applicable)
*****************************************************************************
*/
- .section ".prefix.lib"
+ .section ".prefix.lib", "awx", @progbits
.code16
.globl print_pci_busdevfn
print_pci_busdevfn:
@@ -181,14 +179,14 @@ print_pci_busdevfn:
xchgb %al, %ah
call print_hex_byte
/* Print ":" */
- movb $':', %al
+ movb $( ':' ), %al
call print_character
/* Print device */
movb %ah, %al
shrb $3, %al
call print_hex_byte
/* Print "." */
- movb $'.', %al
+ movb $( '.' ), %al
call print_character
/* Print function */
movb %ah, %al
@@ -199,6 +197,39 @@ print_pci_busdevfn:
ret
.size print_pci_busdevfn, . - print_pci_busdevfn
+/*****************************************************************************
+ * Utility function: clear current line
+ *
+ * Parameters:
+ * %ds:di : output buffer (or %di=0 to print to console)
+ * Returns:
+ * %ds:di : next character in output buffer (if applicable)
+ *****************************************************************************
+ */
+ .section ".prefix.lib", "awx", @progbits
+ .code16
+ .globl print_kill_line
+print_kill_line:
+ /* Preserve registers */
+ pushw %ax
+ pushw %cx
+ /* Print CR */
+ movb $( '\r' ), %al
+ call print_character
+ /* Print 79 spaces */
+ movb $( ' ' ), %al
+ movw $79, %cx
+1: call print_character
+ loop 1b
+ /* Print CR */
+ movb $( '\r' ), %al
+ call print_character
+ /* Restore registers and return */
+ popw %cx
+ popw %ax
+ ret
+ .size print_kill_line, . - print_kill_line
+
/****************************************************************************
* pm_call (real-mode near call)
*
@@ -223,7 +254,7 @@ print_pci_busdevfn:
#ifndef KEEP_IT_REAL
/* GDT for protected-mode calls */
- .section ".prefix.lib"
+ .section ".prefix.lib", "awx", @progbits
.align 16
pm_call_vars:
gdt:
@@ -246,7 +277,7 @@ gdt_end:
.equ gdt_length, . - gdt
.size gdt, . - gdt
- .section ".prefix.lib"
+ .section ".prefix.lib", "awx", @progbits
.align 16
pm_saved_gdt:
.long 0, 0
@@ -255,7 +286,7 @@ pm_saved_gdt:
.equ pm_call_vars_size, . - pm_call_vars
#define PM_CALL_VAR(x) ( -pm_call_vars_size + ( (x) - pm_call_vars ) )
- .section ".prefix.lib"
+ .section ".prefix.lib", "awx", @progbits
.code16
pm_call:
/* Preserve registers, flags, and RM return point */
@@ -308,7 +339,7 @@ pm_call:
/* Switch CPU to protected mode and load up segment registers */
pushl %eax
cli
- lgdt PM_CALL_VAR(gdt)(%bp)
+ data32 lgdt PM_CALL_VAR(gdt)(%bp)
movl %cr0, %eax
orb $CR0_PE, %al
movl %eax, %cr0
@@ -344,7 +375,7 @@ pm_call:
popw %es
popw %fs
popw %gs
- lgdt PM_CALL_VAR(pm_saved_gdt)(%bp)
+ data32 lgdt PM_CALL_VAR(pm_saved_gdt)(%bp)
popfl
movw %bp, %sp
popw %bp
@@ -378,7 +409,7 @@ set_seg_base:
* None
****************************************************************************
*/
- .section ".prefix.lib"
+ .section ".prefix.lib", "awx", @progbits
.code16
copy_bytes:
pushl %ecx
@@ -403,7 +434,7 @@ copy_bytes:
* none
****************************************************************************
*/
- .section ".prefix.lib"
+ .section ".prefix.lib", "awx", @progbits
.code16
install_block:
@@ -500,35 +531,93 @@ install_block:
* none
****************************************************************************
*/
- .section ".prefix.lib"
+ .section ".prefix.lib", "awx", @progbits
.code16
.globl alloc_basemem
alloc_basemem:
+ /* Preserve registers */
+ pushw %fs
+
/* FBMS => %ax as segment address */
- movw $0x40, %ax
- movw %ax, %fs
+ pushw $0x40
+ popw %fs
movw %fs:0x13, %ax
shlw $6, %ax
- /* .data16 segment address */
- subw $_data16_size_pgh, %ax
+ /* Calculate .data16 segment address */
+ subw $_data16_memsz_pgh, %ax
pushw %ax
- /* .text16 segment address */
- subw $_text16_size_pgh, %ax
+ /* Calculate .text16 segment address */
+ subw $_text16_memsz_pgh, %ax
pushw %ax
/* Update FBMS */
shrw $6, %ax
movw %ax, %fs:0x13
- /* Return */
+ /* Retrieve .text16 and .data16 segment addresses */
popw %ax
popw %bx
+
+ /* Restore registers and return */
+ popw %fs
ret
.size alloc_basemem, . - alloc_basemem
/****************************************************************************
+ * free_basemem (real-mode near call)
+ *
+ * Free space allocated with alloc_basemem.
+ *
+ * Parameters:
+ * %ax : .text16 segment address
+ * %bx : .data16 segment address
+ * Returns:
+ * %ax : 0 if successfully freed
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+ .code16
+ .globl free_basemem
+free_basemem:
+ /* Preserve registers */
+ pushw %fs
+
+ /* Check FBMS counter */
+ pushw %ax
+ shrw $6, %ax
+ pushw $0x40
+ popw %fs
+ cmpw %ax, %fs:0x13
+ popw %ax
+ jne 1f
+
+ /* Check hooked interrupt count */
+ cmpw $0, %cs:hooked_bios_interrupts
+ jne 1f
+
+ /* OK to free memory */
+ addw $_text16_memsz_pgh, %ax
+ addw $_data16_memsz_pgh, %ax
+ shrw $6, %ax
+ movw %ax, %fs:0x13
+ xorw %ax, %ax
+
+1: /* Restore registers and return */
+ popw %fs
+ ret
+ .size free_basemem, . - free_basemem
+
+ .section ".text16.data", "aw", @progbits
+ .globl hooked_bios_interrupts
+hooked_bios_interrupts:
+ .word 0
+ .size hooked_bios_interrupts, . - hooked_bios_interrupts
+
+/****************************************************************************
* install (real-mode near call)
*
* Install all text and data segments.
@@ -542,7 +631,7 @@ alloc_basemem:
* none
****************************************************************************
*/
- .section ".prefix.lib"
+ .section ".prefix.lib", "awx", @progbits
.code16
.globl install
install:
@@ -577,7 +666,7 @@ install:
* none
****************************************************************************
*/
- .section ".prefix.lib"
+ .section ".prefix.lib", "awx", @progbits
.code16
.globl install_prealloc
install_prealloc:
@@ -594,19 +683,19 @@ install_prealloc:
jnz 1f
movw %cs, %si
shll $4, %esi
-1: addl $_payload_offset, %esi
+1: addl $_payload_lma, %esi
/* Install .text16 and .data16 */
pushl %edi
movzwl %ax, %edi
shll $4, %edi
- movl $_text16_size, %ecx
+ movl $_text16_memsz, %ecx
movl %ecx, %edx
call install_block /* .text16 */
movzwl %bx, %edi
shll $4, %edi
- movl $_data16_progbits_size, %ecx
- movl $_data16_size, %edx
+ movl $_data16_filesz, %ecx
+ movl $_data16_memsz, %edx
call install_block /* .data16 */
popl %edi
@@ -622,8 +711,8 @@ install_prealloc:
* prior to reading the E820 memory map and relocating
* properly.
*/
- movl $_textdata_progbits_size, %ecx
- movl $_textdata_size, %edx
+ movl $_textdata_filesz, %ecx
+ movl $_textdata_memsz, %edx
call install_block
/* Initialise librm at current location */
@@ -659,7 +748,7 @@ install_prealloc:
.size install_prealloc, . - install_prealloc
/* Vectors for far calls to .text16 functions */
- .section ".data16"
+ .section ".data16", "aw", @progbits
#ifdef KEEP_IT_REAL
init_libkir_vector:
.word init_libkir
@@ -676,30 +765,53 @@ prot_call_vector:
.size prot_call_vector, . - prot_call_vector
#endif
+/****************************************************************************
+ * uninstall (real-mode near call)
+ *
+ * Uninstall all text and data segments.
+ *
+ * Parameters:
+ * %ax : .text16 segment address
+ * %bx : .data16 segment address
+ * Returns:
+ * none
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".text16", "ax", @progbits
+ .code16
+ .globl uninstall
+uninstall:
+ call free_basemem
+ ret
+ .size uninstall, . - uninstall
+
+
/* File split information for the compressor */
#if COMPRESS
- .section ".zinfo", "a"
+ .section ".zinfo", "a", @progbits
.ascii "COPY"
- .long _prefix_load_offset
- .long _prefix_progbits_size
+ .long _prefix_lma
+ .long _prefix_filesz
.long _max_align
.ascii "PACK"
- .long _text16_load_offset
- .long _text16_progbits_size
+ .long _text16_lma
+ .long _text16_filesz
.long _max_align
.ascii "PACK"
- .long _data16_load_offset
- .long _data16_progbits_size
+ .long _data16_lma
+ .long _data16_filesz
.long _max_align
.ascii "PACK"
- .long _textdata_load_offset
- .long _textdata_progbits_size
+ .long _textdata_lma
+ .long _textdata_filesz
.long _max_align
#else /* COMPRESS */
- .section ".zinfo", "a"
+ .section ".zinfo", "a", @progbits
.ascii "COPY"
- .long _prefix_load_offset
- .long _load_size
+ .long _prefix_lma
+ .long _filesz
.long _max_align
#endif /* COMPRESS */
diff --git a/gpxe/src/arch/i386/prefix/lkrnprefix.S b/gpxe/src/arch/i386/prefix/lkrnprefix.S
index c1e92f57..094263d2 100644
--- a/gpxe/src/arch/i386/prefix/lkrnprefix.S
+++ b/gpxe/src/arch/i386/prefix/lkrnprefix.S
@@ -92,9 +92,9 @@ setup_sects:
root_flags:
.word 0
syssize:
- .long _load_size_pgh - PREFIXPGH
+ .long _filesz_pgh - PREFIXPGH
- .section ".zinfo.fixup", "a" /* Compressor fixup information */
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii "SUBL"
.long syssize
.long 16
@@ -189,6 +189,7 @@ run_gpxe:
movw %ax, %ss
movw $0x7c00, %sp
+ /* Install gPXE */
call install
/* Set up real-mode stack */
@@ -204,7 +205,10 @@ run_gpxe:
pushl $main
pushw %cs
call prot_call
- popl %eax /* discard */
+ popl %ecx /* discard */
+
+ /* Uninstall gPXE */
+ call uninstall
/* Boot next device */
int $0x18
diff --git a/gpxe/src/arch/i386/prefix/nbiprefix.S b/gpxe/src/arch/i386/prefix/nbiprefix.S
index d4904b73..4fb4acb1 100644
--- a/gpxe/src/arch/i386/prefix/nbiprefix.S
+++ b/gpxe/src/arch/i386/prefix/nbiprefix.S
@@ -1,9 +1,7 @@
.text
.arch i386
- .section ".prefix", "ax", @progbits
- .section ".prefix.data", "aw", @progbits
.code16
- .section ".prefix"
+ .section ".prefix", "ax", @progbits
.org 0
nbi_header:
@@ -32,11 +30,11 @@ segment_header:
.byte 0
.byte 0x04 /* Last segment */
.long 0x00007e00
-imglen: .long _load_size - 512
-memlen: .long _load_size - 512
+imglen: .long _filesz - 512
+memlen: .long _filesz - 512
.size segment_header, . - segment_header
- .section ".zinfo.fixup", "a" /* Compressor fixup information */
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii "SUBL"
.long imglen
.long 1
@@ -52,7 +50,7 @@ memlen: .long _load_size - 512
*****************************************************************************
*/
entry:
- /* Install low and high memory regions */
+ /* Install gPXE */
call install
/* Jump to .text16 segment */
@@ -64,7 +62,10 @@ entry:
pushl $main
pushw %cs
call prot_call
- popl %eax /* discard */
+ popl %ecx /* discard */
+
+ /* Uninstall gPXE */
+ call uninstall
/* Reboot system */
int $0x19
diff --git a/gpxe/src/arch/i386/prefix/pxeprefix.S b/gpxe/src/arch/i386/prefix/pxeprefix.S
index 302f8e5d..ee0f4d94 100644
--- a/gpxe/src/arch/i386/prefix/pxeprefix.S
+++ b/gpxe/src/arch/i386/prefix/pxeprefix.S
@@ -2,57 +2,60 @@
#define PXENV_UNDI_GET_NIC_TYPE 0x0012
#define PXENV_STOP_UNDI 0x0015
#define PXENV_UNLOAD_STACK 0x0070
-
+
.text
.arch i386
.org 0
- .section ".prefix", "ax", @progbits
- .section ".prefix.data", "aw", @progbits
.code16
#include <undi.h>
+#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
+
/*****************************************************************************
* Entry point: set operating context, print welcome message
*****************************************************************************
*/
- .section ".prefix"
- /* Set up our non-stack segment registers */
+ .section ".prefix", "ax", @progbits
jmp $0x7c0, $1f
-1: pushfl
- /* %ax here is the default return type... */
- movw $5, %ax /* Keep PXE+UNDI */
+1:
+ /* Preserve registers for possible return to PXE */
+ pushfl
pushal
- pushw %ds
- pushw %es
- pushw %fs
pushw %gs
+ pushw %fs
+ pushw %es
+ pushw %ds
+
+ /* Store magic word on PXE stack and remember PXE %ss:esp */
+ pushl $STACK_MAGIC
+ movw %ss, %cs:pxe_ss
+ movl %esp, %cs:pxe_esp
+ movw %sp, %bp
+ movl (10*4+4*2+4)(%bp),%ebp /* !PXE address */
+
+ /* Set up %ds */
movw %cs, %ax
movw %ax, %ds
-
- movw $0x40, %ax /* BIOS data segment access */
- movw %ax, %fs
-
- pushw %fs:0x13
/* Record PXENV+ and !PXE nominal addresses */
- movw %es, pxenv_segment
+ movw %es, pxenv_segment /* PXENV+ address */
movw %bx, pxenv_offset
- movw %sp, %bp
- movw %ss, return_stack_segment
- movl %esp, return_stack_offset
- movl 50(%bp), %eax
- movl %eax, ppxe_segoff /* !PXE address */
+ movl %ebp, ppxe_segoff /* !PXE address */
+ /* Set up %es and %fs */
+ movw %ax, %es
+ movw $0x40, %ax /* BIOS data segment access */
+ movw %ax, %fs
/* Set up stack just below 0x7c00 */
xorw %ax, %ax
movw %ax, %ss
- movw $0x7c00, %sp
+ movl $0x7c00, %esp
/* Clear direction flag, for the sake of sanity */
cld
/* Print welcome message */
movw $10f, %si
xorw %di, %di
call print_message
- .section ".prefix.data"
+ .section ".prefix.data", "aw", @progbits
10: .asciz "PXE->EB:"
.previous
@@ -80,10 +83,10 @@ detect_pxenv:
movw $10f, %si
call print_message
call print_segoff
- movb $',', %al
+ movb $( ',' ), %al
call print_character
jmp 99f
- .section ".prefix.data"
+ .section ".prefix.data", "aw", @progbits
10: .asciz " PXENV+ at "
.previous
@@ -118,10 +121,10 @@ detect_ppxe:
movw $10f, %si
call print_message
call print_segoff
- movb $',', %al
+ movb $( ',' ), %al
call print_character
jmp 99f
- .section ".prefix.data"
+ .section ".prefix.data", "aw", @progbits
10: .asciz " !PXE at "
.previous
@@ -144,7 +147,7 @@ check_have_stack:
movw $10f, %si
call print_message
jmp finished
- .section ".prefix.data"
+ .section ".prefix.data", "aw", @progbits
10: .asciz " No PXE stack found!\n"
.previous
99:
@@ -182,7 +185,7 @@ print_structure_information:
call print_message
les entry_segoff, %bx
call print_segoff
- .section ".prefix.data"
+ .section ".prefix.data", "aw", @progbits
10: .asciz " entry point at "
.previous
/* Print UNDI code segment */
@@ -190,7 +193,7 @@ print_structure_information:
call print_message
les undi_code_segoff, %bx
call print_segoff
- .section ".prefix.data"
+ .section ".prefix.data", "aw", @progbits
10: .asciz "\n UNDI code segment "
.previous
/* Print UNDI data segment */
@@ -198,7 +201,7 @@ print_structure_information:
call print_message
les undi_data_segoff, %bx
call print_segoff
- .section ".prefix.data"
+ .section ".prefix.data", "aw", @progbits
10: .asciz ", data segment "
.previous
/* Print UNDI memory usage */
@@ -206,13 +209,13 @@ print_structure_information:
call print_message
movw undi_fbms_start, %ax
call print_word
- movb $'-', %al
+ movb $( '-' ), %al
call print_character
movw undi_fbms_end, %ax
call print_word
movw $20f, %si
call print_message
- .section ".prefix.data"
+ .section ".prefix.data", "aw", @progbits
10: .asciz " ("
20: .asciz "kB)\n"
.previous
@@ -246,7 +249,7 @@ pci_physical_device:
movb $0x0a, %al
call print_character
jmp 99f
- .section ".prefix.data"
+ .section ".prefix.data", "aw", @progbits
10: .asciz " UNDI device is PCI "
.previous
@@ -254,7 +257,7 @@ no_physical_device:
/* No device found, or device type not understood */
movw $10f, %si
call print_message
- .section ".prefix.data"
+ .section ".prefix.data", "aw", @progbits
10: .asciz " Unable to determine UNDI physical device\n"
.previous
@@ -264,7 +267,7 @@ no_physical_device:
* Leave NIC in a safe state
*****************************************************************************
*/
-#ifndef PXELOADER_KEEP_UNDI
+#ifndef PXELOADER_KEEP_PXE
shutdown_nic:
/* Issue PXENV_UNDI_SHUTDOWN */
movw $PXENV_UNDI_SHUTDOWN, %bx
@@ -272,11 +275,6 @@ shutdown_nic:
jnc 1f
call print_pxe_error
1:
-
-/*****************************************************************************
- * Unload PXE base code
- *****************************************************************************
- */
unload_base_code:
/* Issue PXENV_UNLOAD_STACK */
movw $PXENV_UNLOAD_STACK, %bx
@@ -289,12 +287,14 @@ unload_base_code:
movw %fs:(0x13), %bx
call free_basemem
99:
+ andw $~( UNDI_FL_INITIALIZED | UNDI_FL_KEEP_ALL ), flags
+#endif /* PXELOADER_KEEP_PXE */
/*****************************************************************************
* Unload UNDI driver
*****************************************************************************
*/
-
+#ifndef PXELOADER_KEEP_UNDI
unload_undi:
/* Issue PXENV_STOP_UNDI */
movw $PXENV_STOP_UNDI, %bx
@@ -309,6 +309,7 @@ unload_undi:
/* Clear UNDI_FL_STARTED */
andw $~UNDI_FL_STARTED, flags
99:
+#endif /* PXELOADER_KEEP_UNDI */
/*****************************************************************************
* Print remaining free base memory
@@ -321,19 +322,18 @@ print_free_basemem:
call print_word
movw $20f, %si
call print_message
- .section ".prefix.data"
+ .section ".prefix.data", "aw", @progbits
10: .asciz " "
20: .asciz "kB free base memory after PXE unload\n"
.previous
-#endif /* PXELOADER_KEEP_UNDI */
/*****************************************************************************
* Exit point
*****************************************************************************
*/
finished:
- jmp run_etherboot
-
+ jmp run_gpxe
+
/*****************************************************************************
* Subroutine: print segment:offset address
*
@@ -350,7 +350,7 @@ print_segoff:
/* Print "<segment>:offset" */
movw %es, %ax
call print_hex_word
- movb $':', %al
+ movb $( ':' ), %al
call print_character
movw %bx, %ax
call print_hex_word
@@ -517,7 +517,7 @@ print_pxe_error:
call print_message
popw %si
ret
- .section ".prefix.data"
+ .section ".prefix.data", "aw", @progbits
10: .asciz " UNDI API call "
20: .asciz " failed: status code "
30: .asciz "\n"
@@ -527,6 +527,10 @@ print_pxe_error:
* PXE data structures
*****************************************************************************
*/
+ .section ".prefix.data"
+
+pxe_ss: .word 0
+pxe_esp: .long 0
pxe_parameter_structure: .fill 20
@@ -554,12 +558,6 @@ entry_segoff:
entry_offset: .word 0
entry_segment: .word 0
-return_stack_segoff:
-return_stack_offset: .long 0
-return_stack_segment: .word 0
-
-return_type: .word 0 /* Default: unload PXE and boot next */
-
undi_fbms_start: .word 0
undi_fbms_end: .word 0
@@ -569,16 +567,18 @@ isapnp_read_port: .word UNDI_NO_ISAPNP_READ_PORT
pci_vendor: .word 0
pci_device: .word 0
-flags: .word UNDI_FL_STARTED
+flags:
+ .word ( UNDI_FL_INITIALIZED | UNDI_FL_STARTED | UNDI_FL_KEEP_ALL )
.equ undi_device_size, ( . - undi_device )
/*****************************************************************************
- * Run Etherboot main code
+ * Run gPXE main code
*****************************************************************************
- */
-run_etherboot:
- /* Install Etherboot */
+ */
+ .section ".prefix"
+run_gpxe:
+ /* Install gPXE */
call install
/* Set up real-mode stack */
@@ -594,6 +594,10 @@ run_etherboot:
rep movsb
#endif
+ /* Retrieve PXE %ss:esp */
+ movw pxe_ss, %di
+ movl pxe_esp, %ebp
+
/* Jump to .text16 segment with %ds pointing to .data16 */
movw %bx, %ds
pushw %ax
@@ -605,29 +609,30 @@ run_etherboot:
pushl $main
pushw %cs
call prot_call
- popl %eax /* discard */
+ popl %ecx /* discard */
-#ifdef PXELOADER_KEEP_UNDI
- /* Boot next device */
- movw $0x40, %ax
- movw %ax, %fs
- movw $preloaded_undi,%bx
-
- cli
- movw %ss:return_type-undi_device(%bx),%ax
- lssl %ss:return_stack_segoff-undi_device(%bx), %esp
- movw %sp,%bp
- movw %ax,38(%bp) /* Overwrite return AX value */
- popw %fs:0x13 /* 0 */
- popw %gs /* 2 */
- popw %fs /* 4 */
- popw %es /* 6 */
- popw %ds /* 8 */
- popal /* 10, 14, 18, 22, 26, 30, 34, 38 */
- popfl /* 42 */
- lret /* 46 */
-#else
- int $0x18
-#endif
+ /* Uninstall gPXE */
+ call uninstall
+
+ /* Restore PXE stack */
+ movw %di, %ss
+ movl %ebp, %esp
+
+ /* Check PXE stack magic */
+ popl %eax
+ cmpl $STACK_MAGIC, %eax
+ jne 1f
+ /* PXE stack OK: return to caller */
+ popw %ds
+ popw %es
+ popw %fs
+ popw %gs
+ popal
+ popfl
+ xorw %ax, %ax /* Return success */
+ lret
+
+1: /* PXE stack corrupt or removed: use INT 18 */
+ int $0x18
.previous
diff --git a/gpxe/src/arch/i386/prefix/romprefix.S b/gpxe/src/arch/i386/prefix/romprefix.S
index 92a931cd..7d532375 100644
--- a/gpxe/src/arch/i386/prefix/romprefix.S
+++ b/gpxe/src/arch/i386/prefix/romprefix.S
@@ -14,6 +14,7 @@
#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
#define PNP_GET_BBS_VERSION 0x60
#define PMM_ALLOCATE 0x0000
+#define PMM_DEALLOCATE 0x0002
/* ROM banner timeout. Based on the configurable BANNER_TIMEOUT in
* config.h, but converted to a number of (18Hz) timer ticks, and
@@ -30,7 +31,7 @@
.org 0x00
romheader:
.word 0xAA55 /* BIOS extension signature */
-romheader_size: .byte _load_size_sect /* Size in 512-byte blocks */
+romheader_size: .byte _filesz_sect /* Size in 512-byte blocks */
jmp init /* Initialisation vector */
checksum:
.byte 0
@@ -42,7 +43,7 @@ checksum:
.word pnpheader
.size romheader, . - romheader
- .section ".zinfo.fixup", "a" /* Compressor fixup information */
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii "SUBB"
.long romheader_size
.long 512
@@ -58,18 +59,18 @@ pciheader:
.byte 0x03 /* PCI data structure revision */
.byte 0x02, 0x00, 0x00 /* Class code */
pciheader_image_length:
- .word _load_size_sect /* Image length */
+ .word _filesz_sect /* Image length */
.word 0x0001 /* Revision level */
.byte 0x00 /* Code type */
.byte 0x80 /* Last image indicator */
pciheader_runtime_length:
- .word _load_size_sect /* Maximum run-time image length */
+ .word _filesz_sect /* Maximum run-time image length */
.word 0x0000 /* Configuration utility code header */
.word 0x0000 /* DMTF CLP entry point */
.equ pciheader_len, . - pciheader
.size pciheader, . - pciheader
- .section ".zinfo.fixup", "a" /* Compressor fixup information */
+ .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii "SUBW"
.long pciheader_image_length
.long 512
@@ -109,12 +110,12 @@ mfgstr:
/* Product string
*
- * Defaults to "gPXE". If the ROM image is writable at initialisation
- * time, it will be filled in to include the PCI bus:dev.fn number of
- * the card as well.
+ * Defaults to PRODUCT_SHORT_NAME. If the ROM image is writable at
+ * initialisation time, it will be filled in to include the PCI
+ * bus:dev.fn number of the card as well.
*/
prodstr:
- .ascii "gPXE"
+ .ascii PRODUCT_SHORT_NAME
prodstr_separator:
.byte 0
.ascii "(PCI "
@@ -130,9 +131,9 @@ undiheader:
.byte 0 /* Structure revision */
.byte 0,1,2 /* PXE version: 2.1.0 */
.word undiloader /* Offset to loader routine */
- .word _data16_size /* Stack segment size */
- .word _data16_size /* Data segment size */
- .word _text16_size /* Code segment size */
+ .word _data16_memsz /* Stack segment size */
+ .word _data16_memsz /* Data segment size */
+ .word _text16_memsz /* Code segment size */
.ascii "PCIR" /* Bus type */
.equ undiheader_len, . - undiheader
.size undiheader, . - undiheader
@@ -174,10 +175,10 @@ init:
/* Fill in product name string, if possible */
movw $prodstr_pci_id, %di
call print_pci_busdevfn
- movb $' ', prodstr_separator
+ movb $( ' ' ), prodstr_separator
/* Print segment address */
- movb $' ', %al
+ movb $( ' ' ), %al
xorw %di, %di
call print_character
movw %cs, %ax
@@ -190,26 +191,48 @@ init:
stc
movw $0xb101, %ax
int $0x1a
- jc 1f
+ jc no_pci3
cmpl $PCI_SIGNATURE, %edx
- jne 1f
+ jne no_pci3
testb %ah, %ah
- jnz 1f
+ jnz no_pci3
movw $init_message_pci, %si
xorw %di, %di
call print_message
movb %bh, %al
call print_hex_nibble
- movb $'.', %al
+ movb $( '.' ), %al
call print_character
movb %bl, %al
call print_hex_byte
cmpb $3, %bh
- jae 2f
-1: /* PCI <3.0: set %gs (runtime segment) = %cs (init-time segment) */
+ jb no_pci3
+ /* PCI >=3.0: leave %gs as-is if sane */
+ movw %gs, %ax
+ cmpw $0xa000, %ax /* Insane if %gs < 0xa000 */
+ jb pci3_insane
+ movw %cs, %bx /* Sane if %cs == %gs */
+ cmpw %bx, %ax
+ je 1f
+ movzbw romheader_size, %cx /* Sane if %cs+len <= %gs */
+ shlw $5, %cx
+ addw %cx, %bx
+ cmpw %bx, %ax
+ jae 1f
+ movw %cs, %bx /* Sane if %gs+len <= %cs */
+ addw %cx, %ax
+ cmpw %bx, %ax
+ jbe 1f
+pci3_insane: /* PCI 3.0 with insane %gs value: print error and ignore %gs */
+ movb $( '!' ), %al
+ call print_character
+ movw %gs, %ax
+ call print_hex_word
+no_pci3:
+ /* PCI <3.0: set %gs (runtime segment) = %cs (init-time segment) */
pushw %cs
popw %gs
-2: popl %edi
+1: popl %edi
popl %edx
popl %ebx
@@ -268,21 +291,52 @@ pmm_scan:
movw $init_message_pmm, %si
xorw %di, %di
call print_message
- /* Try to allocate 2MB block via PMM */
+ /* We have PMM and so a 1kB stack: preserve upper register halves */
+ pushal
+ /* Calculate required allocation size in %esi */
+ movzbl romheader_size, %eax
+ shll $9, %eax
+ addl $_textdata_memsz, %eax
+ orw $0xffff, %ax /* Ensure allocation size is at least 64kB */
+ bsrl %eax, %ecx
+ subw $15, %cx /* Round up and convert to 64kB count */
+ movw $1, %si
+ shlw %cl, %si
+pmm_loop:
+ /* Try to allocate block via PMM */
pushw $0x0006 /* Aligned, extended memory */
pushl $0xffffffff /* No handle */
- pushl $( 0x00200000 / 16 ) /* 2MB in paragraphs */
+ movzwl %si, %eax
+ shll $12, %eax
+ pushl %eax /* Allocation size in paragraphs */
pushw $PMM_ALLOCATE
lcall *%es:7
addw $12, %sp
+ /* Abort if allocation fails */
+ testw %dx, %dx /* %ax==0 even on success, since align>=64kB */
+ jz pmm_fail
+ /* If block has A20==1, free block and try again with twice
+ * the allocation size (and hence alignment).
+ */
+ testw $0x0010, %dx
+ jz got_pmm
+ pushw %dx
+ pushw $0
+ pushw $PMM_DEALLOCATE
+ lcall *%es:7
+ addw $6, %sp
+ addw %si, %si
+ jmp pmm_loop
+got_pmm: /* PMM allocation succeeded */
+ movw %dx, ( image_source + 2 )
movw %dx, %ax
xorw %di, %di
call print_hex_word
- movw %dx, ( image_source + 2 )
- testw %dx, %dx /* %ax==0 even on success, since align=2MB */
- jz no_pmm
- /* PMM allocation succeeded: copy ROM to PMM block */
- pushal /* PMM presence implies 1kB stack */
+ movb $( '@' ), %al
+ call print_character
+ movw %si, %ax
+ call print_hex_byte
+ /* Copy ROM to PMM block */
xorw %ax, %ax
movw %ax, %es
movl image_source, %edi
@@ -291,24 +345,28 @@ pmm_scan:
shll $9, %ecx
addr32 rep movsb /* PMM presence implies flat real mode */
movl %edi, decompress_to
- /* Shrink ROM and update checksum */
+ /* Shrink ROM */
+ movb $_prefix_memsz_sect, romheader_size
+pmm_fail:
+ /* Restore upper register halves */
+ popal
+no_pmm:
+
+ /* Update checksum */
xorw %bx, %bx
xorw %si, %si
- movw $_prefix_size_sect, %cx
- movb %cl, romheader_size
+ movzbw romheader_size, %cx
shlw $9, %cx
1: lodsb
addb %al, %bl
loop 1b
subb %bl, checksum
- popal
-no_pmm:
/* Copy self to option ROM space. Required for PCI3.0, which
* loads us to a temporary location in low memory. Will be a
* no-op for lower PCI versions.
*/
- movb $' ', %al
+ movb $( ' ' ), %al
xorw %di, %di
call print_character
movw %gs, %ax
@@ -324,23 +382,28 @@ no_pmm:
movw $init_message_prompt, %si
xorw %di, %di
call print_message
+ movw $prodstr, %si
+ call print_message
+ movw $init_message_dots, %si
+ call print_message
/* Wait for Ctrl-B */
movw $0xff02, %bx
call wait_for_key
/* Clear prompt */
pushf
- movw $clear_message, %si
xorw %di, %di
+ call print_kill_line
+ movw $init_message_done, %si
call print_message
popf
- jnz 1f
+ jnz 2f
/* 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
-1:
+2:
/* Restore registers */
popw %gs
popw %fs
@@ -353,7 +416,26 @@ no_pmm:
lret
.size init, . - init
+/*
+ * Note to hardware vendors:
+ *
+ * If you wish to brand this boot ROM, please do so by defining the
+ * strings PRODUCT_NAME and PRODUCT_SHORT_NAME in config/general.h.
+ *
+ * While nothing in the GPL prevents you from removing all references
+ * to gPXE or http://etherboot.org, we prefer you not to do so.
+ *
+ * If you have an OEM-mandated branding requirement that cannot be
+ * satisfied simply by defining PRODUCT_NAME and PRODUCT_SHORT_NAME,
+ * please contact us.
+ *
+ * [ Including an ASCII NUL in PRODUCT_NAME is considered to be
+ * bypassing the spirit of this request! ]
+ */
init_message:
+ .ascii "\n"
+ .ascii PRODUCT_NAME
+ .ascii "\n"
.asciz "gPXE (http://etherboot.org) - "
.size init_message, . - init_message
init_message_pci:
@@ -372,11 +454,14 @@ init_message_int19:
.asciz " INT19"
.size init_message_int19, . - init_message_int19
init_message_prompt:
- .asciz "\nPress Ctrl-B to configure gPXE..."
+ .asciz "\nPress Ctrl-B to configure "
.size init_message_prompt, . - init_message_prompt
-clear_message:
- .asciz "\r \n\n"
- .size clear_message, . - clear_message
+init_message_dots:
+ .asciz "..."
+ .size init_message_dots, . - init_message_dots
+init_message_done:
+ .asciz "\n\n"
+ .size init_message_done, . - init_message_done
/* ROM image location
*
@@ -429,14 +514,15 @@ int19_entry:
call print_message
movw $int19_message_dots, %si
call print_message
- movw $0xdf42, %bx
+ movw $0xdf4e, %bx
call wait_for_key
pushf
- movw $clear_message, %si
xorw %di, %di
+ call print_kill_line
+ movw $int19_message_done, %si
call print_message
popf
- jnz 1f
+ jz 1f
/* Leave keypress in buffer and start gPXE. The keypress will
* cause the usual initial Ctrl-B prompt to be skipped.
*/
@@ -455,11 +541,14 @@ orig_int19:
.size orig_int19, . - orig_int19
int19_message_prompt:
- .asciz "Press B to boot from "
+ .asciz "Press N to skip booting from "
.size int19_message_prompt, . - int19_message_prompt
int19_message_dots:
.asciz "..."
.size int19_message_dots, . - int19_message_dots
+int19_message_done:
+ .asciz "\n\n"
+ .size int19_message_done, . - int19_message_done
/* Execute as a boot device
*
@@ -504,8 +593,11 @@ exec: /* Set %ds = %cs */
pushl $main
pushw %cs
call prot_call
- /* No need to clean up stack; we are about to reload %ss:sp */
-
+ popl %ecx /* discard */
+
+ /* Uninstall gPXE */
+ call uninstall
+
/* Restore BIOS stack */
movw %dx, %ss
movw %bp, %sp
diff --git a/gpxe/src/arch/i386/scripts/i386.lds b/gpxe/src/arch/i386/scripts/i386.lds
index 729ad30a..8a0c6733 100644
--- a/gpxe/src/arch/i386/scripts/i386.lds
+++ b/gpxe/src/arch/i386/scripts/i386.lds
@@ -5,15 +5,9 @@
*
*/
-OUTPUT_FORMAT ( "elf32-i386", "elf32-i386", "elf32-i386" )
-OUTPUT_ARCH ( i386 )
-ENTRY ( _entry )
-
SECTIONS {
- /* All sections in the resulting file have consecutive load
- * addresses, but may have individual link addresses depending on
- * the memory model being used.
+ /* Each section starts at a virtual address of zero.
*
* We guarantee alignment of virtual addresses to any alignment
* specified by the constituent object files (e.g. via
@@ -31,254 +25,185 @@ SECTIONS {
*/
/*
- * Weak symbols that need zero values if not otherwise defined
- */
-
- . = 0;
- .weak : AT ( 0 ) {
- *(.weak)
- }
- _assert = ASSERT ( ( . == 0 ), ".weak is non-zero length" );
-
- /*
* The prefix
+ *
*/
- _prefix_link_addr = 0;
- . = _prefix_link_addr;
- _prefix = .;
-
- .prefix : AT ( _prefix_load_offset + __prefix ) {
- __prefix = .;
- _entry = .;
+ .prefix 0x0 : AT ( _prefix_lma ) {
+ _prefix = .;
*(.prefix)
*(.prefix.*)
- _eprefix_progbits = .;
+ _mprefix = .;
+ } .bss.prefix (NOLOAD) : AT ( _end_lma ) {
+ _eprefix = .;
}
-
- _eprefix = .;
+ _prefix_filesz = ABSOLUTE ( _mprefix - _prefix );
+ _prefix_memsz = ABSOLUTE ( _eprefix - _prefix );
/*
- * The 16-bit sections, if present
+ * The 16-bit (real-mode) code section
+ *
*/
- _text16_link_addr = 0;
- . = _text16_link_addr;
- _text16 = .;
-
- /* We need to allow code at the NULL address in .text16 */
-
- .text16 : AT ( _text16_load_offset + __text16 ) {
- __text16 = .;
+ .text16 0x0 : AT ( _text16_lma ) {
+ _text16 = .;
*(.text16.null)
- . += 1; /* Prevent NULL being valid */
+ . += 1; /* Prevent NULL being valid */
*(.text16)
*(.text16.*)
- _etext16_progbits = .;
- } = 0x9090
-
- _etext16 = .;
-
- _data16_link_addr = 0;
- . = _data16_link_addr;
- _data16 = .;
+ _mtext16 = .;
+ } .bss.text16 (NOLOAD) : AT ( _end_lma ) {
+ _etext16 = .;
+ }
+ _text16_filesz = ABSOLUTE ( _mtext16 - _text16 );
+ _text16_memsz = ABSOLUTE ( _etext16 - _text16 );
- . += 1; /* Prevent NULL being valid */
+ /*
+ * The 16-bit (real-mode) data section
+ *
+ */
- .rodata16 : AT ( _data16_load_offset + __rodata16 ) {
- __rodata16 = .;
+ .data16 0x0 : AT ( _data16_lma ) {
+ _data16 = .;
+ . += 1; /* Prevent NULL being valid */
*(.rodata16)
*(.rodata16.*)
- }
- .data16 : AT ( _data16_load_offset + __data16 ) {
- __data16 = .;
*(.data16)
*(.data16.*)
- _edata16_progbits = .;
- }
- .bss16 : AT ( _data16_load_offset + __bss16 ) {
- __bss16 = .;
- _bss16 = .;
+ _mdata16 = .;
+ } .bss.data16 (NOLOAD) : AT ( _end_lma ) {
*(.bss16)
*(.bss16.*)
- _ebss16 = .;
- }
- .stack16 : AT ( _data16_load_offset + __stack16 ) {
- __stack16 = .;
*(.stack16)
*(.stack16.*)
+ _edata16 = .;
}
-
- _edata16 = .;
+ _data16_filesz = ABSOLUTE ( _mdata16 - _data16 );
+ _data16_memsz = ABSOLUTE ( _edata16 - _data16 );
/*
* The 32-bit sections
+ *
*/
- _textdata_link_addr = 0;
- . = _textdata_link_addr;
- _textdata = .;
-
- _text = .;
-
- . += 1; /* Prevent NULL being valid */
-
- .text : AT ( _textdata_load_offset + __text ) {
- __text = .;
+ .textdata 0x0 : AT ( _textdata_lma ) {
+ _textdata = .;
*(.text.null_trap)
+ . += 1; /* Prevent NULL being valid */
*(.text)
*(.text.*)
- } = 0x9090
-
- _etext = .;
-
- _data = .;
-
- .rodata : AT ( _textdata_load_offset + __rodata ) {
- __rodata = .;
*(.rodata)
*(.rodata.*)
- }
- .data : AT ( _textdata_load_offset + __data ) {
- __data = .;
*(.data)
*(.data.*)
*(SORT(.tbl.*)) /* Various tables. See include/tables.h */
- _etextdata_progbits = .;
- }
- .bss : AT ( _textdata_load_offset + __bss ) {
- __bss = .;
- _bss = .;
+ _mtextdata = .;
+ } .bss.textdata (NOLOAD) : AT ( _end_lma ) {
*(.bss)
*(.bss.*)
*(COMMON)
- _ebss = .;
- }
- .stack : AT ( _textdata_load_offset + __stack ) {
- __stack = .;
*(.stack)
*(.stack.*)
+ _etextdata = .;
}
-
- _edata = .;
-
- _etextdata = .;
-
- _end = .;
+ _textdata_filesz = ABSOLUTE ( _mtextdata - _textdata );
+ _textdata_memsz = ABSOLUTE ( _etextdata - _textdata );
/*
* Compressor information block
+ *
*/
- _zinfo_link_addr = 0;
- . = _zinfo_link_addr;
- _zinfo = .;
-
- .zinfo : AT ( _zinfo_load_offset + __zinfo ) {
- __zinfo = .;
- _entry = .;
+ .zinfo 0x0 : AT ( _zinfo_lma ) {
+ _zinfo = .;
*(.zinfo)
*(.zinfo.*)
- _ezinfo_progbits = .;
+ _mzinfo = .;
+ } .bss.zinfo (NOLOAD) : AT ( _end_lma ) {
+ _ezinfo = .;
}
-
- _ezinfo = .;
+ _zinfo_filesz = ABSOLUTE ( _mzinfo - _zinfo );
+ _zinfo_memsz = ABSOLUTE ( _ezinfo - _zinfo );
+
+ /*
+ * Weak symbols that need zero values if not otherwise defined
+ *
+ */
+
+ .weak 0x0 : AT ( _end_lma ) {
+ _weak = .;
+ *(.weak)
+ _eweak = .;
+ }
+ _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
/*
* Dispose of the comment and note sections to make the link map
* easier to read
+ *
*/
/DISCARD/ : {
*(.comment)
+ *(.comment.*)
*(.note)
+ *(.note.*)
+ *(.eh_frame)
+ *(.eh_frame.*)
+ *(.rel)
+ *(.rel.*)
}
/*
- * Load address calculations. The slightly obscure nature of the
- * calculations is because ALIGN(x) can only operate on the
- * location counter.
+ * Load address calculations. In older versions of ld, ALIGN()
+ * can operate only on the location counter, so we use that.
+ *
*/
- _max_align = 16;
- _load_addr = 0;
-
- . = _load_addr;
-
- . -= _prefix_link_addr;
- _prefix_load_offset = ALIGN ( _max_align );
- _prefix_load_addr = _prefix_link_addr + _prefix_load_offset;
- _prefix_size = _eprefix - _prefix;
- _prefix_progbits_size = _eprefix_progbits - _prefix;
- . = _prefix_load_addr + _prefix_progbits_size;
-
- . -= _text16_link_addr;
- _text16_load_offset = ALIGN ( _max_align );
- _text16_load_addr = _text16_link_addr + _text16_load_offset;
- _text16_size = _etext16 - _text16;
- _text16_progbits_size = _etext16_progbits - _text16;
- . = _text16_load_addr + _text16_progbits_size;
+ PROVIDE ( _max_align = 16 );
+ . = 0;
- . -= _data16_link_addr;
- _data16_load_offset = ALIGN ( _max_align );
- _data16_load_addr = _data16_link_addr + _data16_load_offset;
- _data16_size = _edata16 - _data16;
- _data16_progbits_size = _edata16_progbits - _data16;
- . = _data16_load_addr + _data16_progbits_size;
+ . = ALIGN ( _max_align );
+ _prefix_lma = .;
+ . += _prefix_filesz;
- . -= _textdata_link_addr;
- _textdata_load_offset = ALIGN ( _max_align );
- _textdata_load_addr = _textdata_link_addr + _textdata_load_offset;
- _textdata_size = _etextdata - _textdata;
- _textdata_progbits_size = _etextdata_progbits - _textdata;
- . = _textdata_load_addr + _textdata_progbits_size;
+ . = ALIGN ( _max_align );
+ _payload_lma = .;
+ _text16_lma = .;
+ . += _text16_filesz;
- _load_size = . - _load_addr;
+ . = ALIGN ( _max_align );
+ _data16_lma = .;
+ . += _data16_filesz;
- . -= _zinfo_link_addr;
- _zinfo_load_offset = ALIGN ( _max_align );
- _zinfo_load_addr = _zinfo_link_addr + _zinfo_load_offset;
- _zinfo_size = _ezinfo - _zinfo;
- _zinfo_progbits_size = _ezinfo_progbits - _zinfo;
- . = _zinfo_load_addr + _zinfo_progbits_size;
+ . = ALIGN ( _max_align );
+ _textdata_lma = .;
+ . += _textdata_filesz;
- _payload_offset = _text16_load_offset;
+ _filesz = .; /* Do not include zinfo block in file size */
- /*
- * Alignment checks. ALIGN() can only operate on the location
- * counter, so we set the location counter to each value we want
- * to check.
- */
-
- . = _prefix_load_addr - _prefix_link_addr;
- _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
- "_prefix is badly aligned" );
-
- . = _text16_load_addr - _text16_link_addr;
- _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
- "_text16 is badly aligned" );
+ . = ALIGN ( _max_align );
+ _zinfo_lma = .;
+ . += _zinfo_filesz;
- . = _data16_load_addr - _data16_link_addr;
- _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
- "_data16 is badly aligned" );
-
- . = _textdata_load_addr - _textdata_link_addr;
- _assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
- "_text is badly aligned" );
+ . = ALIGN ( _max_align );
+ _end_lma = .;
/*
* Values calculated to save code from doing it
+ *
*/
- _prefix_size_pgh = ( ( _prefix_size + 15 ) / 16 );
- _prefix_size_sect = ( ( _prefix_size + 511 ) / 512 );
- _text16_size_pgh = ( ( _text16_size + 15 ) / 16 );
- _data16_size_pgh = ( ( _data16_size + 15 ) / 16 );
+ _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 );
/*
- * Load sizes in paragraphs and sectors. Note that wherever the
- * _load_size variables are used, there must be a corresponding
+ * File size in paragraphs and sectors. Note that wherever the
+ * _filesz variables are used, there must be a corresponding
* .zinfo.fixup section.
+ *
*/
- _load_size_pgh = ( ( _load_size + 15 ) / 16 );
- _load_size_sect = ( ( _load_size + 511 ) / 512 );
+ _filesz_pgh = ( ( _filesz + 15 ) / 16 );
+ _filesz_sect = ( ( _filesz + 511 ) / 512 );
}
diff --git a/gpxe/src/arch/i386/transitions/librm.S b/gpxe/src/arch/i386/transitions/librm.S
index ff4b1d97..8cf1f7f5 100644..100755
--- a/gpxe/src/arch/i386/transitions/librm.S
+++ b/gpxe/src/arch/i386/transitions/librm.S
@@ -19,9 +19,6 @@
#define SIZEOF_I386_ALL_REGS ( SIZEOF_REAL_MODE_REGS + SIZEOF_I386_FLAGS )
.arch i386
- .section ".text16", "ax", @progbits
- .section ".text16.data", "aw", @progbits
- .section ".data16", "aw", @progbits
/****************************************************************************
* Global descriptor table
@@ -47,7 +44,7 @@
#else
#define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x00
#endif
- .section ".data16"
+ .section ".data16", "aw", @progbits
.align 16
gdt:
gdtr: /* The first GDT entry is unused, the GDTR can fit here. */
@@ -99,7 +96,7 @@ gdt_end:
* %edi : Physical base of protected-mode code (virt_offset)
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
.code16
.globl init_librm
init_librm:
@@ -149,7 +146,7 @@ init_librm:
popl %eax
lret
- .section ".text16"
+ .section ".text16", "ax", @progbits
.code16
.weak idt_init
set_seg_base:
@@ -177,7 +174,7 @@ idt_init: /* Reuse the return opcode here */
*
****************************************************************************
*/
- .section ".text16"
+ .section ".text16", "ax", @progbits
.code16
real_to_prot:
/* Make sure we have our data segment available */
@@ -203,13 +200,13 @@ real_to_prot:
/* Switch to protected mode */
cli
- data32 lgdt gdtr
- data32 lidt idtr
+ data32 lgdt gdtr
+ data32 lidt idtr
movl %cr0, %eax
orb $CR0_PE, %al
movl %eax, %cr0
data32 ljmp $VIRTUAL_CS, $1f
- .section ".text"
+ .section ".text", "ax", @progbits
.code32
1:
/* Set up protected-mode data segments and stack pointer */
@@ -240,7 +237,7 @@ real_to_prot:
ret
/* Default IDTR with no interrupts */
- .section ".data16"
+ .section ".data16", "aw", @progbits
.weak idtr
idtr:
rm_idtr:
@@ -266,7 +263,7 @@ rm_idtr:
*
****************************************************************************
*/
- .section ".text"
+ .section ".text", "ax", @progbits
.code32
prot_to_real:
/* Add return address to data to be moved to RM stack */
@@ -296,7 +293,7 @@ prot_to_real:
movw %ax, %gs
movw %ax, %ss
ljmp $REAL_CS, $1f
- .section ".text16"
+ .section ".text16", "ax", @progbits
.code16
1:
/* Switch to real mode */
@@ -316,7 +313,7 @@ p2r_jump_target:
movl %edx, %esp
/* Reset IDTR to the real-mode defaults */
- lidt rm_idtr
+ data32 lidt rm_idtr
/* Return to real-mode address */
data32 ret
@@ -328,13 +325,13 @@ p2r_jump_target:
* rather than .data16 because code needs to be able to locate
* the data segment.
*/
- .section ".data16"
+ .section ".data16", "aw", @progbits
p2r_jump_vector:
.word p2r_jump_target
.globl rm_cs
rm_cs: .word 0
.globl rm_ds
- .section ".text16.data"
+ .section ".text16.data", "aw", @progbits
rm_ds: .word 0
/****************************************************************************
@@ -378,7 +375,7 @@ rm_ds: .word 0
#define PC_OFFSET_FUNCTION ( PC_OFFSET_RETADDR + 4 )
#define PC_OFFSET_END ( PC_OFFSET_FUNCTION + 4 )
- .section ".text16"
+ .section ".text16", "ax", @progbits
.code16
.globl prot_call
prot_call:
@@ -403,7 +400,7 @@ prot_call:
movl $PC_OFFSET_END, %ecx
pushl $1f
jmp real_to_prot
- .section ".text"
+ .section ".text", "ax", @progbits
.code32
1:
/* Set up environment expected by C code */
@@ -419,13 +416,13 @@ prot_call:
movl $PC_OFFSET_END, %ecx
pushl $1f
jmp prot_to_real
- .section ".text16"
+ .section ".text16", "ax", @progbits
.code16
1:
/* Reload GDT and IDT, restore registers and flags and return */
movw %sp, %bp
- lgdt (%bp)
- lidt 8(%bp)
+ data32 lgdt (%bp)
+ data32 lidt 8(%bp)
addw $20, %sp /* also skip %cs and %ss */
popw %ds
popw %es
@@ -475,7 +472,7 @@ prot_call:
#define RC_OFFSET_FUNCTION ( RC_OFFSET_RETADDR + 4 )
#define RC_OFFSET_END ( RC_OFFSET_FUNCTION + 4 )
- .section ".text"
+ .section ".text", "ax", @progbits
.code32
.globl real_call
real_call:
@@ -487,7 +484,7 @@ real_call:
movl $( RC_OFFSET_RETADDR + 4 /* function pointer copy */ ), %ecx
pushl $1f
jmp prot_to_real
- .section ".text16"
+ .section ".text16", "ax", @progbits
.code16
1:
/* Call real-mode function */
@@ -503,7 +500,7 @@ real_call:
movl $RC_OFFSET_RETADDR, %ecx
pushl $1f
jmp real_to_prot
- .section ".text"
+ .section ".text", "ax", @progbits
.code32
1:
/* Restore registers and return */
@@ -514,7 +511,7 @@ real_call:
/* Function vector, used because "call xx(%sp)" is not a valid
* 16-bit expression.
*/
- .section ".data16"
+ .section ".data16", "aw", @progbits
rc_function: .word 0, 0
/****************************************************************************
@@ -551,7 +548,7 @@ rc_function: .word 0, 0
* to us.
****************************************************************************
*/
- .section ".data"
+ .section ".data", "aw", @progbits
.globl rm_sp
rm_sp: .word 0
.globl rm_ss
@@ -567,13 +564,13 @@ pm_esp: .long _estack
****************************************************************************
*/
/* Internal copies, created by init_librm (which runs in real mode) */
- .section ".data16"
+ .section ".data16", "aw", @progbits
_virt_offset: .long 0
_text16: .long 0
_data16: .long 0
/* Externally-visible copies, created by real_to_prot */
- .section ".data"
+ .section ".data", "aw", @progbits
.globl virt_offset
virt_offset: .long 0
.globl text16
diff --git a/gpxe/src/arch/i386/transitions/librm_mgmt.c b/gpxe/src/arch/i386/transitions/librm_mgmt.c
index 59b2eabc..50569f8e 100644..100755
--- a/gpxe/src/arch/i386/transitions/librm_mgmt.c
+++ b/gpxe/src/arch/i386/transitions/librm_mgmt.c
@@ -1,45 +1,56 @@
-/*
- * librm: a library for interfacing to real-mode code
- *
- * Michael Brown <mbrown@fensystems.co.uk>
- *
- */
-
-#include <stdint.h>
-#include <librm.h>
-
-/*
- * This file provides functions for managing librm.
- *
- */
-
-/**
- * Allocate space on the real-mode stack and copy data there from a
- * user buffer
- *
- * @v data User buffer
- * @v size Size of stack data
- * @ret sp New value of real-mode stack pointer
- */
-uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size ) {
- userptr_t rm_stack;
- rm_sp -= size;
- rm_stack = real_to_user ( rm_ss, rm_sp );
- memcpy_user ( rm_stack, 0, data, 0, size );
- return rm_sp;
-};
-
-/**
- * Deallocate space on the real-mode stack, optionally copying back
- * data to a user buffer.
- *
- * @v data User buffer
- * @v size Size of stack data
- */
-void remove_user_from_rm_stack ( userptr_t data, size_t size ) {
- if ( data ) {
- userptr_t rm_stack = real_to_user ( rm_ss, rm_sp );
- memcpy_user ( rm_stack, 0, data, 0, size );
- }
- rm_sp += size;
-};
+/*
+ * librm: a library for interfacing to real-mode code
+ *
+ * Michael Brown <mbrown@fensystems.co.uk>
+ *
+ */
+
+#include <stdint.h>
+#include <realmode.h>
+
+/*
+ * This file provides functions for managing librm.
+ *
+ */
+
+/**
+ * Allocate space on the real-mode stack and copy data there from a
+ * user buffer
+ *
+ * @v data User buffer
+ * @v size Size of stack data
+ * @ret sp New value of real-mode stack pointer
+ */
+uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size ) {
+ userptr_t rm_stack;
+ rm_sp -= size;
+ rm_stack = real_to_user ( rm_ss, rm_sp );
+ memcpy_user ( rm_stack, 0, data, 0, size );
+ return rm_sp;
+};
+
+/**
+ * Deallocate space on the real-mode stack, optionally copying back
+ * data to a user buffer.
+ *
+ * @v data User buffer
+ * @v size Size of stack data
+ */
+void remove_user_from_rm_stack ( userptr_t data, size_t size ) {
+ if ( data ) {
+ userptr_t rm_stack = real_to_user ( rm_ss, rm_sp );
+ memcpy_user ( rm_stack, 0, data, 0, size );
+ }
+ rm_sp += size;
+};
+
+PROVIDE_UACCESS_INLINE ( librm, phys_to_user );
+PROVIDE_UACCESS_INLINE ( librm, user_to_phys );
+PROVIDE_UACCESS_INLINE ( librm, virt_to_user );
+PROVIDE_UACCESS_INLINE ( librm, user_to_virt );
+PROVIDE_UACCESS_INLINE ( librm, userptr_add );
+PROVIDE_UACCESS_INLINE ( librm, memcpy_user );
+PROVIDE_UACCESS_INLINE ( librm, memmove_user );
+PROVIDE_UACCESS_INLINE ( librm, memset_user );
+PROVIDE_UACCESS_INLINE ( librm, strlen_user );
+PROVIDE_UACCESS_INLINE ( librm, memchr_user );
diff --git a/gpxe/src/arch/x86/Makefile b/gpxe/src/arch/x86/Makefile
new file mode 100644
index 00000000..a7c4bc0e
--- /dev/null
+++ b/gpxe/src/arch/x86/Makefile
@@ -0,0 +1,9 @@
+# Include common x86 headers
+#
+CFLAGS += -Iarch/x86/include
+
+# x86-specific directories containing source files
+#
+SRCDIRS += arch/x86/core
+SRCDIRS += arch/x86/interface/efi
+SRCDIRS += arch/x86/prefix
diff --git a/gpxe/src/arch/x86/Makefile.efi b/gpxe/src/arch/x86/Makefile.efi
new file mode 100644
index 00000000..bef8d59d
--- /dev/null
+++ b/gpxe/src/arch/x86/Makefile.efi
@@ -0,0 +1,28 @@
+# -*- makefile -*- : Force emacs to use Makefile mode
+
+# The EFI linker script
+#
+LDSCRIPT = arch/x86/scripts/efi.lds
+
+# Retain relocation information for elf2efi
+#
+LDFLAGS += -q -S
+
+# Media types.
+#
+NON_AUTO_MEDIA += efi
+NON_AUTO_MEDIA += efidrv
+
+# Rules for building EFI files
+#
+$(BIN)/%.efi : $(BIN)/%.efi.tmp $(ELF2EFI)
+ $(QM)$(ECHO) " [FINISH] $@"
+ $(Q)$(ELF2EFI) --subsystem=10 $< $@
+
+$(BIN)/%.efidrv : $(BIN)/%.efidrv.tmp $(ELF2EFI)
+ $(QM)$(ECHO) " [FINISH] $@"
+ $(Q)$(ELF2EFI) --subsystem=11 $< $@
+
+$(BIN)/%.efirom : $(BIN)/%.efidrv $(EFIROM)
+ $(QM)$(ECHO) " [FINISH] $@"
+ $(Q)$(EFIROM) -v $(TGT_PCI_VENDOR) -d $(TGT_PCI_DEVICE) $< $@
diff --git a/gpxe/src/arch/i386/core/pcidirect.c b/gpxe/src/arch/x86/core/pcidirect.c
index 2ed8c2ad..db17215e 100644
--- a/gpxe/src/arch/i386/core/pcidirect.c
+++ b/gpxe/src/arch/x86/core/pcidirect.c
@@ -16,8 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <gpxe/io.h>
#include <gpxe/pci.h>
-#include <pcidirect.h>
/** @file
*
@@ -36,3 +36,10 @@ void pcidirect_prepare ( struct pci_device *pci, int where ) {
( where & ~3 ) ), PCIDIRECT_CONFIG_ADDRESS );
}
+PROVIDE_PCIAPI_INLINE ( direct, pci_max_bus );
+PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_byte );
+PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_word );
+PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_dword );
+PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_byte );
+PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_word );
+PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_dword );
diff --git a/gpxe/src/arch/i386/core/i386_string.c b/gpxe/src/arch/x86/core/x86_string.c
index 9917363a..c0224c7a 100644
--- a/gpxe/src/arch/i386/core/i386_string.c
+++ b/gpxe/src/arch/x86/core/x86_string.c
@@ -32,9 +32,7 @@
* @v len Length
* @ret dest Destination address
*/
-__attribute__ (( regparm ( 3 ) )) void * __memcpy ( void *dest,
- const void *src,
- size_t len ) {
+void * __memcpy ( void *dest, const void *src, size_t len ) {
void *edi = dest;
const void *esi = src;
int discard_ecx;
diff --git a/gpxe/src/arch/x86/include/bits/pci_io.h b/gpxe/src/arch/x86/include/bits/pci_io.h
new file mode 100644
index 00000000..0fbb439d
--- /dev/null
+++ b/gpxe/src/arch/x86/include/bits/pci_io.h
@@ -0,0 +1,13 @@
+#ifndef _BITS_PCI_IO_H
+#define _BITS_PCI_IO_H
+
+/** @file
+ *
+ * i386-specific PCI I/O API implementations
+ *
+ */
+
+#include <gpxe/pcibios.h>
+#include <gpxe/pcidirect.h>
+
+#endif /* _BITS_PCI_IO_H */
diff --git a/gpxe/src/arch/i386/include/bits/string.h b/gpxe/src/arch/x86/include/bits/string.h
index c05a7df8..42ddeddf 100644
--- a/gpxe/src/arch/i386/include/bits/string.h
+++ b/gpxe/src/arch/x86/include/bits/string.h
@@ -23,9 +23,7 @@
#define __HAVE_ARCH_MEMCPY
-extern __attribute__ (( regparm ( 3 ) )) void * __memcpy ( void *dest,
- const void *src,
- size_t len );
+extern void * __memcpy ( void *dest, const void *src, size_t len );
#if 0
static inline __attribute__ (( always_inline )) void *
diff --git a/gpxe/src/arch/x86/include/gpxe/efi/efix86_nap.h b/gpxe/src/arch/x86/include/gpxe/efi/efix86_nap.h
new file mode 100644
index 00000000..91424c54
--- /dev/null
+++ b/gpxe/src/arch/x86/include/gpxe/efi/efix86_nap.h
@@ -0,0 +1,16 @@
+#ifndef _GPXE_EFIX86_NAP_H
+#define _GPXE_EFIX86_NAP_H
+
+/** @file
+ *
+ * EFI CPU sleeping
+ *
+ */
+
+#ifdef NAP_EFIX86
+#define NAP_PREFIX_efix86
+#else
+#define NAP_PREFIX_efix86 __efix86_
+#endif
+
+#endif /* _GPXE_EFIX86_NAP_H */
diff --git a/gpxe/src/arch/i386/include/pcibios.h b/gpxe/src/arch/x86/include/gpxe/pcibios.h
index 3d08d135..b86f5abd 100644
--- a/gpxe/src/arch/i386/include/pcibios.h
+++ b/gpxe/src/arch/x86/include/gpxe/pcibios.h
@@ -1,5 +1,5 @@
-#ifndef _PCIBIOS_H
-#define _PCIBIOS_H
+#ifndef _GPXE_PCIBIOS_H
+#define _GPXE_PCIBIOS_H
#include <stdint.h>
@@ -9,6 +9,12 @@
*
*/
+#ifdef PCIAPI_PCBIOS
+#define PCIAPI_PREFIX_pcbios
+#else
+#define PCIAPI_PREFIX_pcbios __pcbios_
+#endif
+
struct pci_device;
#define PCIBIOS_INSTALLATION_CHECK 0xb1010000
@@ -19,7 +25,6 @@ struct pci_device;
#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c0000
#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d0000
-extern int pcibios_max_bus ( void );
extern int pcibios_read ( struct pci_device *pci, uint32_t command,
uint32_t *value );
extern int pcibios_write ( struct pci_device *pci, uint32_t command,
@@ -33,9 +38,10 @@ extern int pcibios_write ( struct pci_device *pci, uint32_t command,
* @v value Value read
* @ret rc Return status code
*/
-static inline __attribute__ (( always_inline )) int
-pcibios_read_config_byte ( struct pci_device *pci, unsigned int where,
- uint8_t *value ) {
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_read_config_byte ) ( struct pci_device *pci,
+ unsigned int where,
+ uint8_t *value ) {
uint32_t tmp;
int rc;
@@ -52,9 +58,10 @@ pcibios_read_config_byte ( struct pci_device *pci, unsigned int where,
* @v value Value read
* @ret rc Return status code
*/
-static inline __attribute__ (( always_inline )) int
-pcibios_read_config_word ( struct pci_device *pci, unsigned int where,
- uint16_t *value ) {
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_read_config_word ) ( struct pci_device *pci,
+ unsigned int where,
+ uint16_t *value ) {
uint32_t tmp;
int rc;
@@ -71,9 +78,10 @@ pcibios_read_config_word ( struct pci_device *pci, unsigned int where,
* @v value Value read
* @ret rc Return status code
*/
-static inline __attribute__ (( always_inline )) int
-pcibios_read_config_dword ( struct pci_device *pci, unsigned int where,
- uint32_t *value ) {
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_read_config_dword ) ( struct pci_device *pci,
+ unsigned int where,
+ uint32_t *value ) {
return pcibios_read ( pci, PCIBIOS_READ_CONFIG_DWORD | where, value );
}
@@ -85,9 +93,10 @@ pcibios_read_config_dword ( struct pci_device *pci, unsigned int where,
* @v value Value to be written
* @ret rc Return status code
*/
-static inline __attribute__ (( always_inline )) int
-pcibios_write_config_byte ( struct pci_device *pci, unsigned int where,
- uint8_t value ) {
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_write_config_byte ) ( struct pci_device *pci,
+ unsigned int where,
+ uint8_t value ) {
return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_BYTE | where, value );
}
@@ -99,9 +108,10 @@ pcibios_write_config_byte ( struct pci_device *pci, unsigned int where,
* @v value Value to be written
* @ret rc Return status code
*/
-static inline __attribute__ (( always_inline )) int
-pcibios_write_config_word ( struct pci_device *pci, unsigned int where,
- uint16_t value ) {
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_write_config_word ) ( struct pci_device *pci,
+ unsigned int where,
+ uint16_t value ) {
return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_WORD | where, value );
}
@@ -113,10 +123,11 @@ pcibios_write_config_word ( struct pci_device *pci, unsigned int where,
* @v value Value to be written
* @ret rc Return status code
*/
-static inline __attribute__ (( always_inline )) int
-pcibios_write_config_dword ( struct pci_device *pci, unsigned int where,
- uint32_t value ) {
+static inline __always_inline int
+PCIAPI_INLINE ( pcbios, pci_write_config_dword ) ( struct pci_device *pci,
+ unsigned int where,
+ uint32_t value ) {
return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_DWORD | where, value);
}
-#endif /* _PCIBIOS_H */
+#endif /* _GPXE_PCIBIOS_H */
diff --git a/gpxe/src/arch/i386/include/pcidirect.h b/gpxe/src/arch/x86/include/gpxe/pcidirect.h
index 4e2e9d12..fe433c6f 100644
--- a/gpxe/src/arch/i386/include/pcidirect.h
+++ b/gpxe/src/arch/x86/include/gpxe/pcidirect.h
@@ -2,7 +2,13 @@
#define _PCIDIRECT_H
#include <stdint.h>
-#include <io.h>
+#include <gpxe/io.h>
+
+#ifdef PCIAPI_DIRECT
+#define PCIAPI_PREFIX_direct
+#else
+#define PCIAPI_PREFIX_direct __direct_
+#endif
/** @file
*
@@ -22,7 +28,8 @@ extern void pcidirect_prepare ( struct pci_device *pci, int where );
*
* @ret max_bus Maximum bus number
*/
-static inline int pcidirect_max_bus ( void ) {
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_max_bus ) ( void ) {
/* No way to work this out via Type 1 accesses */
return 0xff;
}
@@ -35,9 +42,10 @@ static inline int pcidirect_max_bus ( void ) {
* @v value Value read
* @ret rc Return status code
*/
-static inline __attribute__ (( always_inline )) int
-pcidirect_read_config_byte ( struct pci_device *pci, unsigned int where,
- uint8_t *value ) {
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_read_config_byte ) ( struct pci_device *pci,
+ unsigned int where,
+ uint8_t *value ) {
pcidirect_prepare ( pci, where );
*value = inb ( PCIDIRECT_CONFIG_DATA + ( where & 3 ) );
return 0;
@@ -51,9 +59,10 @@ pcidirect_read_config_byte ( struct pci_device *pci, unsigned int where,
* @v value Value read
* @ret rc Return status code
*/
-static inline __attribute__ (( always_inline )) int
-pcidirect_read_config_word ( struct pci_device *pci, unsigned int where,
- uint16_t *value ) {
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_read_config_word ) ( struct pci_device *pci,
+ unsigned int where,
+ uint16_t *value ) {
pcidirect_prepare ( pci, where );
*value = inw ( PCIDIRECT_CONFIG_DATA + ( where & 2 ) );
return 0;
@@ -67,9 +76,10 @@ pcidirect_read_config_word ( struct pci_device *pci, unsigned int where,
* @v value Value read
* @ret rc Return status code
*/
-static inline __attribute__ (( always_inline )) int
-pcidirect_read_config_dword ( struct pci_device *pci, unsigned int where,
- uint32_t *value ) {
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_read_config_dword ) ( struct pci_device *pci,
+ unsigned int where,
+ uint32_t *value ) {
pcidirect_prepare ( pci, where );
*value = inl ( PCIDIRECT_CONFIG_DATA );
return 0;
@@ -83,9 +93,10 @@ pcidirect_read_config_dword ( struct pci_device *pci, unsigned int where,
* @v value Value to be written
* @ret rc Return status code
*/
-static inline __attribute__ (( always_inline )) int
-pcidirect_write_config_byte ( struct pci_device *pci, unsigned int where,
- uint8_t value ) {
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_write_config_byte ) ( struct pci_device *pci,
+ unsigned int where,
+ uint8_t value ) {
pcidirect_prepare ( pci, where );
outb ( value, PCIDIRECT_CONFIG_DATA + ( where & 3 ) );
return 0;
@@ -99,9 +110,10 @@ pcidirect_write_config_byte ( struct pci_device *pci, unsigned int where,
* @v value Value to be written
* @ret rc Return status code
*/
-static inline __attribute__ (( always_inline )) int
-pcidirect_write_config_word ( struct pci_device *pci, unsigned int where,
- uint16_t value ) {
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_write_config_word ) ( struct pci_device *pci,
+ unsigned int where,
+ uint16_t value ) {
pcidirect_prepare ( pci, where );
outw ( value, PCIDIRECT_CONFIG_DATA + ( where & 2 ) );
return 0;
@@ -115,9 +127,10 @@ pcidirect_write_config_word ( struct pci_device *pci, unsigned int where,
* @v value Value to be written
* @ret rc Return status code
*/
-static inline __attribute__ (( always_inline )) int
-pcidirect_write_config_dword ( struct pci_device *pci, unsigned int where,
- uint32_t value ) {
+static inline __always_inline int
+PCIAPI_INLINE ( direct, pci_write_config_dword ) ( struct pci_device *pci,
+ unsigned int where,
+ uint32_t value ) {
pcidirect_prepare ( pci, where );
outl ( value, PCIDIRECT_CONFIG_DATA );
return 0;
diff --git a/gpxe/src/arch/x86/interface/efi/efix86_nap.c b/gpxe/src/arch/x86/interface/efi/efix86_nap.c
new file mode 100644
index 00000000..45e99a68
--- /dev/null
+++ b/gpxe/src/arch/x86/interface/efi/efix86_nap.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include <gpxe/nap.h>
+#include <gpxe/efi/efi.h>
+
+/** @file
+ *
+ * gPXE CPU sleeping API for EFI
+ *
+ */
+
+/**
+ * Sleep until next interrupt
+ *
+ */
+static void efix86_cpu_nap ( void ) {
+ /*
+ * I can't find any EFI API that allows us to put the CPU to
+ * sleep. The CpuSleep() function is defined in CpuLib.h, but
+ * isn't part of any exposed protocol so we have no way to
+ * call it.
+ *
+ * The EFI shell doesn't seem to bother sleeping the CPU; it
+ * just sits there idly burning power.
+ *
+ */
+ __asm__ __volatile__ ( "hlt" );
+}
+
+PROVIDE_NAP ( efix86, cpu_nap, efix86_cpu_nap );
diff --git a/gpxe/src/arch/x86/prefix/efidrvprefix.c b/gpxe/src/arch/x86/prefix/efidrvprefix.c
new file mode 100644
index 00000000..5f631588
--- /dev/null
+++ b/gpxe/src/arch/x86/prefix/efidrvprefix.c
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <gpxe/init.h>
+#include <gpxe/efi/efi.h>
+
+/**
+ * EFI entry point
+ *
+ * @v image_handle Image handle
+ * @v systab System table
+ * @ret efirc EFI return status code
+ */
+EFI_STATUS EFIAPI _start ( EFI_HANDLE image_handle,
+ EFI_SYSTEM_TABLE *systab ) {
+ EFI_STATUS efirc;
+
+ /* Initialise EFI environment */
+ if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 )
+ return efirc;
+
+ /* Initialise gPXE environment */
+ initialise();
+ startup();
+
+ /* Install SNP driver and return */
+ return RC_TO_EFIRC ( efi_snp_install () );
+}
diff --git a/gpxe/src/arch/x86/prefix/efiprefix.c b/gpxe/src/arch/x86/prefix/efiprefix.c
new file mode 100644
index 00000000..b05b744d
--- /dev/null
+++ b/gpxe/src/arch/x86/prefix/efiprefix.c
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <gpxe/efi/efi.h>
+
+/**
+ * EFI entry point
+ *
+ * @v image_handle Image handle
+ * @v systab System table
+ * @ret efirc EFI return status code
+ */
+EFI_STATUS EFIAPI _start ( EFI_HANDLE image_handle,
+ EFI_SYSTEM_TABLE *systab ) {
+ EFI_STATUS efirc;
+
+ /* Initialise EFI environment */
+ if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 )
+ return efirc;
+
+ /* Call to main() */
+ return RC_TO_EFIRC ( main () );
+}
diff --git a/gpxe/src/arch/x86/scripts/efi.lds b/gpxe/src/arch/x86/scripts/efi.lds
new file mode 100644
index 00000000..aac31056
--- /dev/null
+++ b/gpxe/src/arch/x86/scripts/efi.lds
@@ -0,0 +1,105 @@
+/* -*- sh -*- */
+
+/*
+ * Linker script for EFI images
+ *
+ */
+
+ENTRY ( _start )
+
+SECTIONS {
+
+ /* The file starts at a virtual address of zero, and sections are
+ * contiguous. Each section is aligned to at least _max_align,
+ * which defaults to 32. Load addresses are equal to virtual
+ * addresses.
+ */
+
+ _max_align = 32;
+
+ /* Allow plenty of space for file headers */
+ . = 0x1000;
+
+ /*
+ * The text section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .text : {
+ _text = .;
+ *(.text)
+ *(.text.*)
+ _etext = .;
+ }
+
+ /*
+ * The rodata section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .rodata : {
+ _rodata = .;
+ *(.rodata)
+ *(.rodata.*)
+ _erodata = .;
+ }
+
+ /*
+ * The data section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .data : {
+ _data = .;
+ *(.data)
+ *(.data.*)
+ *(SORT(.tbl.*)) /* Various tables. See include/tables.h */
+ _edata = .;
+ }
+
+ /*
+ * The bss section
+ *
+ */
+
+ . = ALIGN ( _max_align );
+ .bss : {
+ _bss = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ _ebss = .;
+ }
+
+ /*
+ * Weak symbols that need zero values if not otherwise defined
+ *
+ */
+
+ .weak 0x0 : {
+ _weak = .;
+ *(.weak)
+ _eweak = .;
+ }
+ _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
+
+ /*
+ * Dispose of the comment and note sections to make the link map
+ * easier to read
+ *
+ */
+
+ /DISCARD/ : {
+ *(.comment)
+ *(.comment.*)
+ *(.note)
+ *(.note.*)
+ *(.eh_frame)
+ *(.eh_frame.*)
+ *(.rel)
+ *(.rel.*)
+ }
+}
diff --git a/gpxe/src/arch/x86_64/Makefile b/gpxe/src/arch/x86_64/Makefile
new file mode 100644
index 00000000..d2c2ff53
--- /dev/null
+++ b/gpxe/src/arch/x86_64/Makefile
@@ -0,0 +1,41 @@
+# Code size reduction.
+#
+CFLAGS += -fstrength-reduce -fomit-frame-pointer
+
+# Code size reduction. gcc3 needs a different syntax to gcc2 if you
+# want to avoid spurious warnings.
+#
+CFLAGS += -falign-jumps=1 -falign-loops=1 -falign-functions=1
+
+# Use %rip-relative addressing wherever possible.
+#
+CFLAGS += -fpie
+
+# Force 64-bit code
+#
+CFLAGS += -m64
+ASFLAGS += --64
+LDFLAGS += -m elf_x86_64
+
+# EFI requires -fshort-wchar, and nothing else currently uses wchar_t
+#
+CFLAGS += -fshort-wchar
+
+# We need to undefine the default macro "i386" when compiling .S
+# files, otherwise ".arch i386" translates to ".arch 1"...
+#
+CFLAGS += -Ui386
+
+# x86_64-specific directories containing source files
+#
+SRCDIRS += arch/x86_64/prefix
+
+# Include common x86 Makefile
+#
+MAKEDEPS += arch/x86/Makefile
+include arch/x86/Makefile
+
+# Include platform-specific Makefile
+#
+MAKEDEPS += arch/x86_64/Makefile.$(PLATFORM)
+include arch/x86_64/Makefile.$(PLATFORM)
diff --git a/gpxe/src/arch/x86_64/Makefile.efi b/gpxe/src/arch/x86_64/Makefile.efi
new file mode 100644
index 00000000..26b71278
--- /dev/null
+++ b/gpxe/src/arch/x86_64/Makefile.efi
@@ -0,0 +1,14 @@
+# -*- makefile -*- : Force emacs to use Makefile mode
+
+# EFI probably doesn't guarantee us a red zone, so let's not rely on it.
+#
+CFLAGS += -mno-red-zone
+
+# Specify EFI image builder
+#
+ELF2EFI = $(ELF2EFI64)
+
+# Include generic EFI Makefile
+#
+MAKEDEPS += arch/x86/Makefile.efi
+include arch/x86/Makefile.efi
diff --git a/gpxe/src/arch/x86_64/include/bits/byteswap.h b/gpxe/src/arch/x86_64/include/bits/byteswap.h
new file mode 100644
index 00000000..9ed85e8f
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/bits/byteswap.h
@@ -0,0 +1,22 @@
+#ifndef _BITS_BYTESWAP_H
+#define _BITS_BYTESWAP_H
+
+static inline __attribute__ (( always_inline, const )) uint16_t
+__bswap_variable_16 ( uint16_t x ) {
+ __asm__ ( "xchgb %b0,%h0" : "=Q" ( x ) : "0" ( x ) );
+ return x;
+}
+
+static inline __attribute__ (( always_inline, const )) uint32_t
+__bswap_variable_32 ( uint32_t x ) {
+ __asm__ ( "bswapl %k0" : "=r" ( x ) : "0" ( x ) );
+ return x;
+}
+
+static inline __attribute__ (( always_inline, const )) uint64_t
+__bswap_variable_64 ( uint64_t x ) {
+ __asm__ ( "bswapq %q0" : "=r" ( x ) : "0" ( x ) );
+ return x;
+}
+
+#endif /* _BITS_BYTESWAP_H */
diff --git a/gpxe/src/arch/x86_64/include/bits/compiler.h b/gpxe/src/arch/x86_64/include/bits/compiler.h
new file mode 100644
index 00000000..51a7eaae
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/bits/compiler.h
@@ -0,0 +1,14 @@
+#ifndef _BITS_COMPILER_H
+#define _BITS_COMPILER_H
+
+#ifndef ASSEMBLY
+
+/** Declare a function with standard calling conventions */
+#define __asmcall __attribute__ (( regparm(0) ))
+
+/** Declare a function with libgcc implicit linkage */
+#define __libgcc
+
+#endif /* ASSEMBLY */
+
+#endif /* _BITS_COMPILER_H */
diff --git a/gpxe/src/arch/x86_64/include/bits/endian.h b/gpxe/src/arch/x86_64/include/bits/endian.h
new file mode 100644
index 00000000..413e702d
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/bits/endian.h
@@ -0,0 +1,6 @@
+#ifndef ETHERBOOT_BITS_ENDIAN_H
+#define ETHERBOOT_BITS_ENDIAN_H
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#endif /* ETHERBOOT_BITS_ENDIAN_H */
diff --git a/gpxe/src/arch/x86_64/include/bits/errfile.h b/gpxe/src/arch/x86_64/include/bits/errfile.h
new file mode 100644
index 00000000..dcda26ba
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/bits/errfile.h
@@ -0,0 +1,11 @@
+#ifndef _BITS_ERRFILE_H
+#define _BITS_ERRFILE_H
+
+/**
+ * @addtogroup errfile Error file identifiers
+ * @{
+ */
+
+/** @} */
+
+#endif /* _BITS_ERRFILE_H */
diff --git a/gpxe/src/arch/x86_64/include/bits/io.h b/gpxe/src/arch/x86_64/include/bits/io.h
new file mode 100644
index 00000000..921fdcc0
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/bits/io.h
@@ -0,0 +1,10 @@
+#ifndef _BITS_IO_H
+#define _BITS_IO_H
+
+/** @file
+ *
+ * x86_64-specific I/O API implementations
+ *
+ */
+
+#endif /* _BITS_IO_H */
diff --git a/gpxe/src/arch/x86_64/include/bits/nap.h b/gpxe/src/arch/x86_64/include/bits/nap.h
new file mode 100644
index 00000000..0a0c8a24
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/bits/nap.h
@@ -0,0 +1,12 @@
+#ifndef _BITS_NAP_H
+#define _BITS_NAP_H
+
+/** @file
+ *
+ * x86_64-specific CPU sleeping API implementations
+ *
+ */
+
+#include <gpxe/efi/efix86_nap.h>
+
+#endif /* _BITS_MAP_H */
diff --git a/gpxe/src/arch/x86_64/include/bits/smbios.h b/gpxe/src/arch/x86_64/include/bits/smbios.h
new file mode 100644
index 00000000..2f0118d0
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/bits/smbios.h
@@ -0,0 +1,10 @@
+#ifndef _BITS_SMBIOS_H
+#define _BITS_SMBIOS_H
+
+/** @file
+ *
+ * i386-specific SMBIOS API implementations
+ *
+ */
+
+#endif /* _BITS_SMBIOS_H */
diff --git a/gpxe/src/arch/x86_64/include/bits/stdint.h b/gpxe/src/arch/x86_64/include/bits/stdint.h
new file mode 100644
index 00000000..23bae9c4
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/bits/stdint.h
@@ -0,0 +1,21 @@
+#ifndef _BITS_STDINT_H
+#define _BITS_STDINT_H
+
+typedef unsigned long size_t;
+typedef signed long ssize_t;
+typedef signed long off_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+typedef unsigned long physaddr_t;
+typedef unsigned long intptr_t;
+
+#endif /* _BITS_STDINT_H */
diff --git a/gpxe/src/arch/x86_64/include/bits/timer.h b/gpxe/src/arch/x86_64/include/bits/timer.h
new file mode 100644
index 00000000..dfa6c270
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/bits/timer.h
@@ -0,0 +1,10 @@
+#ifndef _BITS_TIMER_H
+#define _BITS_TIMER_H
+
+/** @file
+ *
+ * x86_64-specific timer API implementations
+ *
+ */
+
+#endif /* _BITS_TIMER_H */
diff --git a/gpxe/src/arch/x86_64/include/bits/uaccess.h b/gpxe/src/arch/x86_64/include/bits/uaccess.h
new file mode 100644
index 00000000..45582924
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/bits/uaccess.h
@@ -0,0 +1,10 @@
+#ifndef _BITS_UACCESS_H
+#define _BITS_UACCESS_H
+
+/** @file
+ *
+ * x86_64-specific user access API implementations
+ *
+ */
+
+#endif /* _BITS_UACCESS_H */
diff --git a/gpxe/src/arch/x86_64/include/bits/umalloc.h b/gpxe/src/arch/x86_64/include/bits/umalloc.h
new file mode 100644
index 00000000..12bf949d
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/bits/umalloc.h
@@ -0,0 +1,10 @@
+#ifndef _BITS_UMALLOC_H
+#define _BITS_UMALLOC_H
+
+/** @file
+ *
+ * x86_64-specific user memory allocation API implementations
+ *
+ */
+
+#endif /* _BITS_UMALLOC_H */
diff --git a/gpxe/src/arch/x86_64/include/gdbmach.h b/gpxe/src/arch/x86_64/include/gdbmach.h
new file mode 100644
index 00000000..fcf8e94e
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/gdbmach.h
@@ -0,0 +1,51 @@
+#ifndef GDBMACH_H
+#define GDBMACH_H
+
+/** @file
+ *
+ * GDB architecture specifics
+ *
+ * This file declares functions for manipulating the machine state and
+ * debugging context.
+ *
+ */
+
+#include <stdint.h>
+
+typedef unsigned long gdbreg_t;
+
+/* The register snapshot, this must be in sync with interrupt handler and the
+ * GDB protocol. */
+enum {
+ // STUB: don't expect this to work!
+ GDBMACH_EIP,
+ GDBMACH_EFLAGS,
+ GDBMACH_NREGS,
+ GDBMACH_SIZEOF_REGS = GDBMACH_NREGS * sizeof ( gdbreg_t )
+};
+
+/* Breakpoint types */
+enum {
+ GDBMACH_BPMEM,
+ GDBMACH_BPHW,
+ GDBMACH_WATCH,
+ GDBMACH_RWATCH,
+ GDBMACH_AWATCH,
+};
+
+static inline void gdbmach_set_pc ( gdbreg_t *regs, gdbreg_t pc ) {
+ regs [ GDBMACH_EIP ] = pc;
+}
+
+static inline void gdbmach_set_single_step ( gdbreg_t *regs, int step ) {
+ regs [ GDBMACH_EFLAGS ] &= ~( 1 << 8 ); /* Trace Flag (TF) */
+ regs [ GDBMACH_EFLAGS ] |= ( step << 8 );
+}
+
+static inline void gdbmach_breakpoint ( void ) {
+ __asm__ __volatile__ ( "int $3\n" );
+}
+
+extern int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len, int enable );
+
+#endif /* GDBMACH_H */
diff --git a/gpxe/src/arch/x86_64/include/limits.h b/gpxe/src/arch/x86_64/include/limits.h
new file mode 100644
index 00000000..8cf87b47
--- /dev/null
+++ b/gpxe/src/arch/x86_64/include/limits.h
@@ -0,0 +1,59 @@
+#ifndef LIMITS_H
+#define LIMITS_H 1
+
+/* Number of bits in a `char' */
+#define CHAR_BIT 8
+
+/* Minimum and maximum values a `signed char' can hold */
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
+#define UCHAR_MAX 255
+
+/* Minimum and maximum values a `char' can hold */
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+
+/* Minimum and maximum values a `signed short int' can hold */
+#define SHRT_MIN (-32768)
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */
+#define USHRT_MAX 65535
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MAX 2147483647
+#define INT_MIN (-INT_MAX - 1)
+
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+
+/* Minimum and maximum values a `signed long' can hold */
+#define LONG_MAX 9223372036854775807L
+#define LONG_MIN (-LONG_MAX - 1L)
+
+/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */
+#define ULONG_MAX 18446744073709551615UL
+
+/* Minimum and maximum values a `signed long long' can hold */
+#define LLONG_MAX 9223372036854775807LL
+#define LLONG_MIN (-LONG_MAX - 1LL)
+
+
+/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */
+#define ULLONG_MAX 18446744073709551615ULL
+
+
+#endif /* LIMITS_H */
diff --git a/gpxe/src/config.h b/gpxe/src/config.h
deleted file mode 100644
index 603604ab..00000000
--- a/gpxe/src/config.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * This file defines the configuration for Etherboot.
- *
- * The build system splits this file into several individual header
- * files of the form config/%.h, so that changing one option doesn't
- * necessitate a rebuild of every single object. For this reason, it
- * is important to maintain the strict formatting in this file.
- *
- */
-
-/* @BEGIN general.h
- *
- * Console configuration
- *
- * These options specify the console types that Etherboot will use for
- * interaction with the user.
- *
- */
-
-#define CONSOLE_FIRMWARE /* Default BIOS console */
-#undef CONSOLE_SERIAL /* Serial port */
-#undef CONSOLE_DIRECT_VGA /* Direct access to VGA card */
-#undef CONSOLE_BTEXT /* Who knows what this does? */
-#undef CONSOLE_PC_KBD /* Direct access to PC keyboard */
-
-/* @END general.h */
-
-/* @BEGIN serial.h
- *
- * Serial port configuration
- *
- * These options affect the operation of the serial console. They
- * take effect only if the serial console is included using the
- * CONSOLE_SERIAL option.
- *
- */
-
-#define COMCONSOLE 0x3f8 /* 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.
- */
-#undef COMPRESERVE
-
-#ifndef COMPRESERVE
-#define COMSPEED 115200 /* Baud rate */
-#define COMDATA 8 /* Data bits */
-#define COMPARITY 0 /* Parity: 0=None, 1=Odd, 2=Even */
-#define COMSTOP 1 /* Stop bits */
-#endif
-
-/* @END serial.h */
-
-/* @BEGIN general.h
- *
- * Timer configuration
- *
- */
-#define TIMER_BIOS /* 18Hz BIOS timer */
-#define TIMER_RDTSC /* CPU TimeStamp Counter timer */
-#define BANNER_TIMEOUT 20 /* Tenths of a second for which the shell
- banner should appear */
-
-/* @END general.h */
-
-/* @BEGIN isa.h
- *
- * ISA probe address configuration
- *
- * You can override the list of addresses that will be probed by any
- * ISA drivers.
- *
- */
-#undef ISA_PROBE_ADDRS /* e.g. 0x200, 0x300 */
-#undef ISA_PROBE_ONLY /* Do not probe any other addresses */
-
-/* @END isa.h */
-
-/* @BEGIN general.h
- *
- * Network protocols
- *
- */
-
-#define NET_PROTO_IPV4 /* IPv4 protocol */
-
-/* @END general.h */
-
-/* @BEGIN general.h
- *
- * 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? */
-
-/* @END general.h */
-
-/* @BEGIN general.h
- *
- * Name resolution modules
- *
- */
-
-#define DNS_RESOLVER /* DNS resolver */
-#undef NMB_RESOLVER /* NMB resolver */
-
-/* @END general.h */
-
-/* @BEGIN general.h
- *
- * Image types
- *
- * Etherboot supports various image formats. Select whichever ones
- * you want to use.
- *
- */
-#undef IMAGE_NBI /* NBI image support */
-#define IMAGE_ELF /* ELF image support */
-#undef IMAGE_FREEBSD /* FreeBSD kernel image support */
-#define IMAGE_MULTIBOOT /* MultiBoot image support */
-#undef IMAGE_AOUT /* a.out image support */
-#undef IMAGE_WINCE /* WinCE image support */
-#define IMAGE_PXE /* PXE image support */
-#define IMAGE_SCRIPT /* gPXE script image support */
-#define IMAGE_BZIMAGE /* Linux bzImage image support */
-#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */
-
-/* @END general.h */
-
-/* @BEGIN general.h
- *
- * Command-line commands to include
- *
- */
-#define AUTOBOOT_CMD /* Automatic booting */
-#define NVO_CMD /* Non-volatile option storage commands */
-#define CONFIG_CMD /* Option configuration console */
-#define IFMGMT_CMD /* 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 */
-
-/* @END general.h */
-
-/* @BEGIN general.h
- *
- * Obscure configuration options
- *
- * You probably don't need to touch these.
- *
- */
-
-#undef BUILD_SERIAL /* Include an automatic build serial
- * number. Add "bs" to the list of
- * make targets. For example:
- * "make bin/rtl8139.dsk bs" */
-#undef BUILD_ID /* Include a custom build ID string,
- * e.g "test-foo" */
-#undef NULL_TRAP /* Attempt to catch NULL function calls */
-#undef GDBSERIAL /* Remote GDB debugging over serial */
-#undef GDBUDP /* Remote GDB debugging over UDP
- * (both may be set) */
-
-/* @END general.h */
-
-/* @TRYSOURCE config-local.h */
diff --git a/gpxe/src/config/.gitignore b/gpxe/src/config/.gitignore
index 499ae122..8e94f32f 100644
--- a/gpxe/src/config/.gitignore
+++ b/gpxe/src/config/.gitignore
@@ -1,2 +1 @@
-*.h
.buildserial.*
diff --git a/gpxe/src/config/console.h b/gpxe/src/config/console.h
new file mode 100644
index 00000000..b4ea1dda
--- /dev/null
+++ b/gpxe/src/config/console.h
@@ -0,0 +1,21 @@
+#ifndef CONFIG_CONSOLE_H
+#define CONFIG_CONSOLE_H
+
+/** @file
+ *
+ * Console configuration
+ *
+ * These options specify the console types that Etherboot will use for
+ * interaction with the user.
+ *
+ */
+
+#include <config/defaults.h>
+
+//#define CONSOLE_PCBIOS /* Default BIOS console */
+//#define CONSOLE_SERIAL /* Serial port */
+//#define CONSOLE_DIRECT_VGA /* Direct access to VGA card */
+//#define CONSOLE_BTEXT /* Who knows what this does? */
+//#define CONSOLE_PC_KBD /* Direct access to PC keyboard */
+
+#endif /* CONFIG_CONSOLE_H */
diff --git a/gpxe/src/config/defaults.h b/gpxe/src/config/defaults.h
new file mode 100644
index 00000000..1f55ef3c
--- /dev/null
+++ b/gpxe/src/config/defaults.h
@@ -0,0 +1,8 @@
+#ifndef CONFIG_DEFAULTS_H
+#define CONFIG_DEFAULTS_H
+
+#define CONFIG_DEFAULTS(_platform) <config/defaults/_platform.h>
+
+#include CONFIG_DEFAULTS(PLATFORM)
+
+#endif /* CONFIG_DEFAULTS_H */
diff --git a/gpxe/src/config/defaults/efi.h b/gpxe/src/config/defaults/efi.h
new file mode 100644
index 00000000..fe38fd03
--- /dev/null
+++ b/gpxe/src/config/defaults/efi.h
@@ -0,0 +1,21 @@
+#ifndef CONFIG_DEFAULTS_EFI_H
+#define CONFIG_DEFAULTS_EFI_H
+
+/** @file
+ *
+ * Configuration defaults for EFI
+ *
+ */
+
+#define UACCESS_EFI
+#define IOAPI_EFI
+#define PCIAPI_EFI
+#define CONSOLE_EFI
+#define TIMER_EFI
+#define NAP_EFIX86
+#define UMALLOC_EFI
+#define SMBIOS_EFI
+
+#define IMAGE_EFI /* EFI image support */
+
+#endif /* CONFIG_DEFAULTS_EFI_H */
diff --git a/gpxe/src/config/defaults/pcbios.h b/gpxe/src/config/defaults/pcbios.h
new file mode 100644
index 00000000..4359e1a4
--- /dev/null
+++ b/gpxe/src/config/defaults/pcbios.h
@@ -0,0 +1,29 @@
+#ifndef CONFIG_DEFAULTS_PCBIOS_H
+#define CONFIG_DEFAULTS_PCBIOS_H
+
+/** @file
+ *
+ * Configuration defaults for PCBIOS
+ *
+ */
+
+#define UACCESS_LIBRM
+#define IOAPI_X86
+#define PCIAPI_PCBIOS
+#define TIMER_PCBIOS
+#define CONSOLE_PCBIOS
+#define NAP_PCBIOS
+#define UMALLOC_MEMTOP
+#define SMBIOS_PCBIOS
+
+#define IMAGE_ELF /* ELF image support */
+#define IMAGE_MULTIBOOT /* MultiBoot image support */
+#define IMAGE_PXE /* PXE image support */
+#define IMAGE_SCRIPT /* gPXE script image support */
+#define IMAGE_BZIMAGE /* Linux bzImage image support */
+#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */
+
+#define SANBOOT_PROTO_ISCSI /* iSCSI protocol */
+#define SANBOOT_PROTO_AOE /* AoE protocol */
+
+#endif /* CONFIG_DEFAULTS_PCBIOS_H */
diff --git a/gpxe/src/config/general.h b/gpxe/src/config/general.h
new file mode 100644
index 00000000..a3d563c2
--- /dev/null
+++ b/gpxe/src/config/general.h
@@ -0,0 +1,123 @@
+#ifndef CONFIG_GENERAL_H
+#define CONFIG_GENERAL_H
+
+/** @file
+ *
+ * General configuration
+ *
+ */
+
+#include <config/defaults.h>
+
+/*
+ * Branding
+ *
+ * Vendors may use these strings to add their own branding to gPXE.
+ * PRODUCT_NAME is displayed prior to any gPXE branding in startup
+ * messages, and PRODUCT_SHORT_NAME is used where a brief product
+ * label is required (e.g. in BIOS boot selection menus).
+ *
+ * To minimise end-user confusion, it's probably a good idea to either
+ * make PRODUCT_SHORT_NAME a substring of PRODUCT_NAME or leave it as
+ * "gPXE".
+ *
+ */
+#define PRODUCT_NAME ""
+#define PRODUCT_SHORT_NAME "gPXE"
+
+/*
+ * Timer configuration
+ *
+ */
+#define BANNER_TIMEOUT 20 /* Tenths of a second for which the shell
+ banner should appear */
+
+/*
+ * Network protocols
+ *
+ */
+
+#define NET_PROTO_IPV4 /* IPv4 protocol */
+
+/*
+ * 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
+ *
+ */
+
+//#undef SANBOOT_PROTO_ISCSI /* iSCSI protocol */
+//#undef SANBOOT_PROTO_AOE /* AoE protocol */
+
+/*
+ * Name resolution modules
+ *
+ */
+
+#define DNS_RESOLVER /* DNS resolver */
+#undef NMB_RESOLVER /* NMB resolver */
+
+/*
+ * Image types
+ *
+ * Etherboot supports various image formats. Select whichever ones
+ * you want to use.
+ *
+ */
+//#define IMAGE_NBI /* NBI image support */
+//#define IMAGE_ELF /* ELF image support */
+//#define IMAGE_FREEBSD /* FreeBSD kernel image support */
+//#define IMAGE_MULTIBOOT /* MultiBoot image support */
+//#define IMAGE_AOUT /* a.out image support */
+//#define IMAGE_WINCE /* WinCE image support */
+//#define IMAGE_PXE /* PXE image support */
+//#define IMAGE_SCRIPT /* gPXE script image support */
+//#define IMAGE_BZIMAGE /* Linux bzImage image support */
+//#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */
+//#define IMAGE_EFI /* EFI image support */
+
+/*
+ * Command-line commands to include
+ *
+ */
+#define AUTOBOOT_CMD /* Automatic booting */
+#define NVO_CMD /* Non-volatile option storage commands */
+#define CONFIG_CMD /* Option configuration console */
+#define IFMGMT_CMD /* 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 */
+
+/*
+ * Obscure configuration options
+ *
+ * You probably don't need to touch these.
+ *
+ */
+
+#undef BUILD_SERIAL /* Include an automatic build serial
+ * number. Add "bs" to the list of
+ * make targets. For example:
+ * "make bin/rtl8139.dsk bs" */
+#undef BUILD_ID /* Include a custom build ID string,
+ * e.g "test-foo" */
+#undef NULL_TRAP /* Attempt to catch NULL function calls */
+#undef GDBSERIAL /* Remote GDB debugging over serial */
+#undef GDBUDP /* Remote GDB debugging over UDP
+ * (both may be set) */
+
+#endif /* CONFIG_GENERAL_H */
diff --git a/gpxe/src/config/ioapi.h b/gpxe/src/config/ioapi.h
new file mode 100644
index 00000000..7726a0f0
--- /dev/null
+++ b/gpxe/src/config/ioapi.h
@@ -0,0 +1,15 @@
+#ifndef CONFIG_IOAPI_H
+#define CONFIG_IOAPI_H
+
+/** @file
+ *
+ * I/O API configuration
+ *
+ */
+
+#include <config/defaults.h>
+
+//#undef PCIAPI_PCBIOS /* Access via PCI BIOS */
+//#define PCIAPI_DIRECT /* Direct access via Type 1 accesses */
+
+#endif /* CONFIG_IOAPI_H */
diff --git a/gpxe/src/config/isa.h b/gpxe/src/config/isa.h
new file mode 100644
index 00000000..523be1c0
--- /dev/null
+++ b/gpxe/src/config/isa.h
@@ -0,0 +1,15 @@
+#ifndef CONFIG_ISA_H
+#define CONFIG_ISA_H
+
+/** @file
+ *
+ * ISA probe address configuration
+ *
+ * You can override the list of addresses that will be probed by any
+ * ISA drivers.
+ *
+ */
+#undef ISA_PROBE_ADDRS /* e.g. 0x200, 0x300 */
+#undef ISA_PROBE_ONLY /* Do not probe any other addresses */
+
+#endif /* CONFIG_ISA_H */
diff --git a/gpxe/src/config/nap.h b/gpxe/src/config/nap.h
new file mode 100644
index 00000000..8648d925
--- /dev/null
+++ b/gpxe/src/config/nap.h
@@ -0,0 +1,15 @@
+#ifndef CONFIG_NAP_H
+#define CONFIG_NAP_H
+
+/** @file
+ *
+ * CPU sleeping
+ *
+ */
+
+#include <config/defaults.h>
+
+//#undef NAP_PCBIOS
+//#define NAP_NULL
+
+#endif /* CONFIG_NAP_H */
diff --git a/gpxe/src/config/serial.h b/gpxe/src/config/serial.h
new file mode 100644
index 00000000..984a7a9c
--- /dev/null
+++ b/gpxe/src/config/serial.h
@@ -0,0 +1,28 @@
+#ifndef CONFIG_SERIAL_H
+#define CONFIG_SERIAL_H
+
+/** @file
+ *
+ * Serial port configuration
+ *
+ * These options affect the operation of the serial console. They
+ * take effect only if the serial console is included using the
+ * CONSOLE_SERIAL option.
+ *
+ */
+
+#define COMCONSOLE 0x3f8 /* 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.
+ */
+#undef COMPRESERVE
+
+#ifndef COMPRESERVE
+#define COMSPEED 115200 /* Baud rate */
+#define COMDATA 8 /* Data bits */
+#define COMPARITY 0 /* Parity: 0=None, 1=Odd, 2=Even */
+#define COMSTOP 1 /* Stop bits */
+#endif
+
+#endif /* CONFIG_SERIAL_H */
diff --git a/gpxe/src/config/timer.h b/gpxe/src/config/timer.h
new file mode 100644
index 00000000..7c3f3521
--- /dev/null
+++ b/gpxe/src/config/timer.h
@@ -0,0 +1,15 @@
+#ifndef CONFIG_TIMER_H
+#define CONFIG_TIMER_H
+
+/** @file
+ *
+ * Timer configuration.
+ *
+ */
+
+#include <config/defaults.h>
+
+//#undef TIMER_PCBIOS
+//#define TIMER_RDTSC
+
+#endif /* CONFIG_TIMER_H */
diff --git a/gpxe/src/config/umalloc.h b/gpxe/src/config/umalloc.h
new file mode 100644
index 00000000..de4019e5
--- /dev/null
+++ b/gpxe/src/config/umalloc.h
@@ -0,0 +1,12 @@
+#ifndef CONFIG_UMALLOC_H
+#define CONFIG_UMALLOC_H
+
+/** @file
+ *
+ * User memory allocation API configuration
+ *
+ */
+
+#include <config/defaults.h>
+
+#endif /* CONFIG_UMALLOC_H */
diff --git a/gpxe/src/core/base64.c b/gpxe/src/core/base64.c
new file mode 100644
index 00000000..e54821e3
--- /dev/null
+++ b/gpxe/src/core/base64.c
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <gpxe/base64.h>
+
+/** @file
+ *
+ * Base64 encoding
+ *
+ */
+
+static const char base64[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * Base64-encode a string
+ *
+ * @v raw Raw string
+ * @v encoded Buffer for encoded string
+ *
+ * The buffer must be the correct length for the encoded string. Use
+ * something like
+ *
+ * char buf[ base64_encoded_len ( strlen ( raw ) ) + 1 ];
+ *
+ * (the +1 is for the terminating NUL) to provide a buffer of the
+ * correct size.
+ */
+void base64_encode ( const char *raw, char *encoded ) {
+ const uint8_t *raw_bytes = ( ( const uint8_t * ) raw );
+ uint8_t *encoded_bytes = ( ( uint8_t * ) encoded );
+ size_t raw_bit_len = ( 8 * strlen ( raw ) );
+ unsigned int bit;
+ unsigned int tmp;
+
+ for ( bit = 0 ; bit < raw_bit_len ; bit += 6 ) {
+ tmp = ( ( raw_bytes[ bit / 8 ] << ( bit % 8 ) ) |
+ ( raw_bytes[ bit / 8 + 1 ] >> ( 8 - ( bit % 8 ) ) ) );
+ tmp = ( ( tmp >> 2 ) & 0x3f );
+ *(encoded_bytes++) = base64[tmp];
+ }
+ for ( ; ( bit % 8 ) != 0 ; bit += 6 )
+ *(encoded_bytes++) = '=';
+ *(encoded_bytes++) = '\0';
+
+ DBG ( "Base64-encoded \"%s\" as \"%s\"\n", raw, encoded );
+ assert ( strlen ( encoded ) == base64_encoded_len ( strlen ( raw ) ) );
+}
diff --git a/gpxe/src/core/config.c b/gpxe/src/core/config.c
index b5624fae..bd0d66ec 100644
--- a/gpxe/src/core/config.c
+++ b/gpxe/src/core/config.c
@@ -5,7 +5,8 @@
* your option) any later version.
*/
-#include "config/general.h"
+#include <config/general.h>
+#include <config/console.h>
/*
* Build ID string calculations
@@ -38,19 +39,9 @@
/*
* Drag in all requested console types
*
- * CONSOLE_DUAL sets both CONSOLE_FIRMWARE and CONSOLE_SERIAL for
- * legacy compatibility.
- *
*/
-#ifdef CONSOLE_DUAL
-#undef CONSOLE_FIRMWARE
-#define CONSOLE_FIRMWARE 1
-#undef CONSOLE_SERIAL
-#define CONSOLE_SERIAL 1
-#endif
-
-#ifdef CONSOLE_FIRMWARE
+#ifdef CONSOLE_PCBIOS
REQUIRE_OBJECT ( bios_console );
#endif
#ifdef CONSOLE_SERIAL
@@ -68,15 +59,8 @@ REQUIRE_OBJECT ( pc_kbd );
#ifdef CONSOLE_SYSLOG
REQUIRE_OBJECT ( syslog );
#endif
-
-/*
- * Drag in all requested timers
- */
-#ifdef TIMER_BIOS
-REQUIRE_OBJECT ( timer_bios );
-#endif
-#ifdef TIMER_RDTSC
-REQUIRE_OBJECT ( timer_rdtsc );
+#ifdef CONSOLE_EFI
+REQUIRE_OBJECT ( efi_console );
#endif
/*
@@ -114,6 +98,17 @@ REQUIRE_OBJECT ( slam );
#endif
/*
+ * Drag in all requested SAN boot protocols
+ *
+ */
+#ifdef SANBOOT_PROTO_ISCSI
+REQUIRE_OBJECT ( iscsiboot );
+#endif
+#ifdef SANBOOT_PROTO_AOE
+REQUIRE_OBJECT ( aoeboot );
+#endif
+
+/*
* Drag in all requested resolvers
*
*/
@@ -166,6 +161,9 @@ REQUIRE_OBJECT ( com32_call );
REQUIRE_OBJECT ( com32_wrapper );
REQUIRE_OBJECT ( comboot_resolv );
#endif
+#ifdef IMAGE_EFI
+REQUIRE_OBJECT ( efi_image );
+#endif
/*
* Drag in all requested commands
@@ -195,6 +193,9 @@ REQUIRE_OBJECT ( dhcp_cmd );
#ifdef SANBOOT_CMD
REQUIRE_OBJECT ( sanboot_cmd );
#endif
+#ifdef LOGIN_CMD
+REQUIRE_OBJECT ( login_cmd );
+#endif
/*
* Drag in miscellaneous objects
@@ -220,3 +221,4 @@ REQUIRE_OBJECT ( gdbstub_cmd );
*
*/
REQUIRE_OBJECT ( device );
+REQUIRE_OBJECT ( embedded );
diff --git a/gpxe/src/core/console.c b/gpxe/src/core/console.c
index 653f689d..c9773f71 100644
--- a/gpxe/src/core/console.c
+++ b/gpxe/src/core/console.c
@@ -1,11 +1,10 @@
#include "stddef.h"
#include "console.h"
#include <gpxe/process.h>
+#include <gpxe/nap.h>
/** @file */
-#include "bios.h"
-
static struct console_driver console_drivers[0]
__table_start ( struct console_driver, console );
static struct console_driver console_drivers_end[0]
@@ -82,9 +81,6 @@ static struct console_driver * has_input ( void ) {
*
* The character read will not be echoed back to any console.
*
- * @bug We need a cleaner way to pick up cpu_nap(). It makes a
- * real-mode call, and so we don't want to use it with LinuxBIOS.
- *
*/
int getchar ( void ) {
struct console_driver *console;
diff --git a/gpxe/src/core/cwuri.c b/gpxe/src/core/cwuri.c
index c7f01386..81fd900e 100644
--- a/gpxe/src/core/cwuri.c
+++ b/gpxe/src/core/cwuri.c
@@ -36,6 +36,9 @@ struct uri *cwuri = NULL;
* @v uri New working URI, or NULL
*/
void churi ( struct uri *uri ) {
+ struct uri *new_uri;
+
+ new_uri = resolve_uri ( cwuri, uri );
uri_put ( cwuri );
- cwuri = uri_get ( uri );
+ cwuri = new_uri;
}
diff --git a/gpxe/src/core/debug.c b/gpxe/src/core/debug.c
index 09830420..500a7ac0 100644
--- a/gpxe/src/core/debug.c
+++ b/gpxe/src/core/debug.c
@@ -1,7 +1,7 @@
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
-#include <io.h>
+#include <gpxe/io.h>
#include <console.h>
void pause ( void ) {
@@ -106,12 +106,12 @@ int check_region ( void *region, size_t len ) {
virt_to_phys ( region + len ) );
}
in_corruption = 1;
- printf ( "--- offset %#lx ", offset );
+ printf ( "--- offset %#x ", offset );
} else if ( ( in_corruption != 0 ) &&
( test == GUARD_SYMBOL ) ) {
/* End of corruption */
in_corruption = 0;
- printf ( "to offset %#lx", offset );
+ printf ( "to offset %#x", offset );
}
}
diff --git a/gpxe/src/core/gdbudp.c b/gpxe/src/core/gdbudp.c
index c49a1bca..26feb38a 100644
--- a/gpxe/src/core/gdbudp.c
+++ b/gpxe/src/core/gdbudp.c
@@ -19,7 +19,6 @@
#include <stdio.h>
#include <string.h>
#include <byteswap.h>
-#include <bios.h>
#include <gpxe/iobuf.h>
#include <gpxe/in.h>
#include <gpxe/if_arp.h>
@@ -27,6 +26,7 @@
#include <gpxe/ip.h>
#include <gpxe/udp.h>
#include <gpxe/netdevice.h>
+#include <gpxe/nap.h>
#include <gpxe/gdbstub.h>
#include <gpxe/gdbudp.h>
diff --git a/gpxe/src/core/getkey.c b/gpxe/src/core/getkey.c
index 1551cf37..787c9027 100644
--- a/gpxe/src/core/getkey.c
+++ b/gpxe/src/core/getkey.c
@@ -16,6 +16,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <ctype.h>
#include <console.h>
#include <gpxe/process.h>
#include <gpxe/keys.h>
@@ -59,21 +60,22 @@ static int getchar_timeout ( unsigned long timeout ) {
*/
int getkey ( void ) {
int character;
- int key;
+ unsigned int n = 0;
character = getchar();
if ( character != ESC )
return character;
- key = 0;
while ( ( character = getchar_timeout ( GETKEY_TIMEOUT ) ) >= 0 ) {
if ( character == '[' )
continue;
- if ( ! key )
- key = KEY_ANSI ( character );
+ if ( isdigit ( character ) ) {
+ n = ( ( n * 10 ) + ( character - '0' ) );
+ continue;
+ }
if ( character >= 0x40 )
- break;
+ return KEY_ANSI ( n, character );
}
- return ( key ? key : ESC );
+ return ESC;
}
diff --git a/gpxe/src/core/image.c b/gpxe/src/core/image.c
index 440a68c9..277d09a9 100644
--- a/gpxe/src/core/image.c
+++ b/gpxe/src/core/image.c
@@ -53,6 +53,7 @@ static void free_image ( struct refcnt *refcnt ) {
uri_put ( image->uri );
ufree ( image->data );
+ image_put ( image->replacement );
free ( image );
DBGC ( image, "IMAGE %p freed\n", image );
}
@@ -142,9 +143,9 @@ int register_image ( struct image *image ) {
* @v image Executable/loadable image
*/
void unregister_image ( struct image *image ) {
+ DBGC ( image, "IMAGE %p unregistered\n", image );
list_del ( &image->list );
image_put ( image );
- DBGC ( image, "IMAGE %p unregistered\n", image );
}
/**
@@ -237,6 +238,7 @@ int image_autoload ( struct image *image ) {
* @ret rc Return status code
*/
int image_exec ( struct image *image ) {
+ struct image *replacement;
struct uri *old_cwuri;
int rc;
@@ -257,18 +259,39 @@ int image_exec ( struct image *image ) {
old_cwuri = uri_get ( cwuri );
churi ( image->uri );
+ /* Take out a temporary reference to the image. This allows
+ * the image to unregister itself if necessary, without
+ * automatically freeing itself.
+ */
+ image_get ( image );
+
/* Try executing the image */
if ( ( rc = image->type->exec ( image ) ) != 0 ) {
DBGC ( image, "IMAGE %p could not execute: %s\n",
image, strerror ( rc ) );
- goto done;
+ /* Do not return yet; we still have clean-up to do */
}
- done:
+ /* Pick up replacement image before we drop the original
+ * image's temporary reference.
+ */
+ replacement = image->replacement;
+
+ /* Drop temporary reference to the original image */
+ image_put ( image );
+
/* Reset current working directory */
churi ( old_cwuri );
uri_put ( old_cwuri );
+ /* Tail-recurse into replacement image, if one exists */
+ if ( replacement ) {
+ DBGC ( image, "IMAGE %p replacing self with IMAGE %p\n",
+ image, replacement );
+ if ( ( rc = image_exec ( replacement ) ) != 0 )
+ return rc;
+ }
+
return rc;
}
diff --git a/gpxe/src/core/main.c b/gpxe/src/core/main.c
index d5892261..8d360c42 100644
--- a/gpxe/src/core/main.c
+++ b/gpxe/src/core/main.c
@@ -19,7 +19,9 @@ Literature dealing with the network protocols:
#include <gpxe/features.h>
#include <gpxe/shell.h>
#include <gpxe/shell_banner.h>
+#include <gpxe/image.h>
#include <usr/autoboot.h>
+#include <config/general.h>
#define NORMAL "\033[0m"
#define BOLD "\033[1m"
@@ -33,14 +35,29 @@ static struct feature features_end[0] __table_end ( struct feature, features );
*
* @ret rc Return status code
*/
-__cdecl int main ( void ) {
+__asmcall int main ( void ) {
struct feature *feature;
+ struct image *image;
+
+ /* Some devices take an unreasonably long time to initialise */
+ printf ( PRODUCT_SHORT_NAME " initialising devices...\n" );
initialise();
startup();
- /* Print welcome banner */
- printf ( NORMAL "\n\n\n" BOLD "gPXE " VERSION
+ /*
+ * Print welcome banner
+ *
+ *
+ * If you wish to brand this build of gPXE, please do so by
+ * defining the string PRODUCT_NAME in config/general.h.
+ *
+ * While nothing in the GPL prevents you from removing all
+ * references to gPXE or http://etherboot.org, we prefer you
+ * not to do so.
+ *
+ */
+ printf ( NORMAL "\n\n" PRODUCT_NAME "\n" BOLD "gPXE " VERSION
NORMAL " -- Open Source Boot Firmware -- "
CYAN "http://etherboot.org" NORMAL "\n"
"Features:" );
@@ -53,11 +70,16 @@ __cdecl int main ( void ) {
/* User wants shell; just give them a shell */
shell();
} else {
- /* User doesn't want shell; try booting. If booting
- * fails, offer a second chance to enter the shell for
- * diagnostics.
+ /* User doesn't want shell; load and execute the first
+ * image. If booting fails (i.e. if the image
+ * returns, or fails to execute), offer a second
+ * chance to enter the shell for diagnostics.
*/
- autoboot();
+ for_each_image ( image ) {
+ image_exec ( image );
+ break;
+ }
+
if ( shell_banner() )
shell();
}
diff --git a/gpxe/src/core/malloc.c b/gpxe/src/core/malloc.c
index 2d892f42..db7f1bed 100644
--- a/gpxe/src/core/malloc.c
+++ b/gpxe/src/core/malloc.c
@@ -20,7 +20,7 @@
#include <stdint.h>
#include <string.h>
#include <strings.h>
-#include <io.h>
+#include <gpxe/io.h>
#include <gpxe/list.h>
#include <gpxe/init.h>
#include <gpxe/malloc.h>
diff --git a/gpxe/src/core/monojob.c b/gpxe/src/core/monojob.c
index 2c91e132..657bfd7a 100644
--- a/gpxe/src/core/monojob.c
+++ b/gpxe/src/core/monojob.c
@@ -63,7 +63,8 @@ struct job_interface monojob = {
int monojob_wait ( const char *string ) {
int key;
int rc;
- tick_t last_progress_dot;
+ unsigned long last_progress_dot;
+ unsigned long elapsed;
printf ( "%s.", string );
monojob_rc = -EINPROGRESS;
@@ -81,7 +82,8 @@ int monojob_wait ( const char *string ) {
break;
}
}
- if ( ( currticks() - last_progress_dot ) > TICKS_PER_SEC ) {
+ elapsed = ( currticks() - last_progress_dot );
+ if ( elapsed >= TICKS_PER_SEC ) {
printf ( "." );
last_progress_dot = currticks();
}
@@ -89,6 +91,7 @@ int monojob_wait ( const char *string ) {
rc = monojob_rc;
done:
+ job_done ( &monojob, rc );
if ( rc ) {
printf ( " %s\n", strerror ( rc ) );
} else {
diff --git a/gpxe/src/core/null_nap.c b/gpxe/src/core/null_nap.c
new file mode 100644
index 00000000..a3b01eb1
--- /dev/null
+++ b/gpxe/src/core/null_nap.c
@@ -0,0 +1,3 @@
+#include <gpxe/nap.h>
+
+PROVIDE_NAP_INLINE ( null, cpu_nap );
diff --git a/gpxe/src/core/nvo.c b/gpxe/src/core/nvo.c
index 13078022..e5c07d98 100644
--- a/gpxe/src/core/nvo.c
+++ b/gpxe/src/core/nvo.c
@@ -203,7 +203,7 @@ void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs,
nvo->nvs = nvs;
nvo->fragments = fragments;
settings_init ( &nvo->settings, &nvo_settings_operations, refcnt,
- "nvo" );
+ "nvo", 0 );
}
/**
diff --git a/gpxe/src/core/pc_kbd.c b/gpxe/src/core/pc_kbd.c
index d43357fe..799c8beb 100644
--- a/gpxe/src/core/pc_kbd.c
+++ b/gpxe/src/core/pc_kbd.c
@@ -10,7 +10,7 @@
* yhlu@tyan.com
*/
-#include "io.h"
+#include <gpxe/io.h>
#include "console.h"
static char key_map[][128] = {
diff --git a/gpxe/src/core/process.c b/gpxe/src/core/process.c
index cf931acf..6a687140 100644
--- a/gpxe/src/core/process.c
+++ b/gpxe/src/core/process.c
@@ -79,7 +79,9 @@ void step ( void ) {
list_for_each_entry ( process, &run_queue, list ) {
list_del ( &process->list );
list_add_tail ( &process->list, &run_queue );
+ DBGC2 ( process, "PROCESS %p executing\n", process );
process->step ( process );
+ DBGC2 ( process, "PROCESS %p finished executing\n", process );
break;
}
}
diff --git a/gpxe/src/core/serial.c b/gpxe/src/core/serial.c
index 97640f93..5b3be39c 100644
--- a/gpxe/src/core/serial.c
+++ b/gpxe/src/core/serial.c
@@ -13,7 +13,7 @@
#include "stddef.h"
#include <gpxe/init.h>
-#include "io.h"
+#include <gpxe/io.h>
#include <unistd.h>
#include <gpxe/serial.h>
#include "config/serial.h"
diff --git a/gpxe/src/core/settings.c b/gpxe/src/core/settings.c
index 3e9eb18a..f34eb664 100644
--- a/gpxe/src/core/settings.c
+++ b/gpxe/src/core/settings.c
@@ -183,12 +183,17 @@ static void reprioritise_settings ( struct settings *settings ) {
* @ret rc Return status code
*/
int register_settings ( struct settings *settings, struct settings *parent ) {
+ struct settings *old_settings;
/* NULL parent => add to settings root */
assert ( settings != NULL );
if ( parent == NULL )
parent = &settings_root;
+ /* Remove any existing settings with the same name */
+ if ( ( old_settings = find_child_settings ( parent, settings->name ) ))
+ unregister_settings ( old_settings );
+
/* Add to list of settings */
ref_get ( settings->refcnt );
ref_get ( parent->refcnt );
@@ -279,7 +284,7 @@ struct settings * find_settings ( const char *name ) {
/**
* Store value of setting
*
- * @v settings Settings block
+ * @v settings Settings block, or NULL
* @v setting Setting to store
* @v data Setting data, or NULL to clear setting
* @v len Length of setting data
@@ -289,9 +294,9 @@ int store_setting ( struct settings *settings, struct setting *setting,
const void *data, size_t len ) {
int rc;
- /* Sanity check */
+ /* NULL settings implies storing into the global settings root */
if ( ! settings )
- return -ENODEV;
+ settings = &settings_root;
/* Store setting */
if ( ( rc = settings->op->store ( settings, setting,
@@ -333,6 +338,9 @@ int fetch_setting ( struct settings *settings, struct setting *setting,
struct settings *child;
int ret;
+ /* Avoid returning uninitialised data on error */
+ memset ( data, 0, len );
+
/* NULL settings implies starting at the global settings root */
if ( ! settings )
settings = &settings_root;
@@ -387,6 +395,38 @@ int fetch_string_setting ( struct settings *settings, struct setting *setting,
}
/**
+ * Fetch value of string setting
+ *
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v data Buffer to allocate and fill with setting string data
+ * @ret len Length of string setting, or negative error
+ *
+ * The resulting string is guaranteed to be correctly NUL-terminated.
+ * The returned length will be the length of the underlying setting
+ * data. The caller is responsible for eventually freeing the
+ * allocated buffer.
+ */
+int fetch_string_setting_copy ( struct settings *settings,
+ struct setting *setting,
+ char **data ) {
+ int len;
+ int check_len;
+
+ len = fetch_setting_len ( settings, setting );
+ if ( len < 0 )
+ return len;
+
+ *data = malloc ( len + 1 );
+ if ( ! *data )
+ return -ENOMEM;
+
+ fetch_string_setting ( settings, setting, *data, ( len + 1 ) );
+ assert ( check_len == len );
+ return len;
+}
+
+/**
* Fetch value of IPv4 address setting
*
* @v settings Settings block, or NULL to search all blocks
@@ -417,20 +457,23 @@ int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
int fetch_int_setting ( struct settings *settings, struct setting *setting,
long *value ) {
union {
- long value;
uint8_t u8[ sizeof ( long ) ];
int8_t s8[ sizeof ( long ) ];
} buf;
int len;
int i;
- buf.value = 0;
+ /* Avoid returning uninitialised data on error */
+ *value = 0;
+
+ /* Fetch raw (network-ordered, variable-length) setting */
len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
if ( len < 0 )
return len;
if ( len > ( int ) sizeof ( buf ) )
return -ERANGE;
+ /* Convert to host-ordered signed long */
*value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
for ( i = 0 ; i < len ; i++ ) {
*value = ( ( *value << 8 ) | buf.u8[i] );
@@ -452,10 +495,15 @@ int fetch_uint_setting ( struct settings *settings, struct setting *setting,
long svalue;
int len;
+ /* Avoid returning uninitialised data on error */
+ *value = 0;
+
+ /* Fetch as a signed long */
len = fetch_int_setting ( settings, setting, &svalue );
if ( len < 0 )
return len;
+ /* Mask off sign-extended bits */
*value = ( svalue & ( -1UL >> ( sizeof ( long ) - len ) ) );
return len;
@@ -469,7 +517,7 @@ int fetch_uint_setting ( struct settings *settings, struct setting *setting,
* @ret value Setting value, or zero
*/
long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
- long value = 0;
+ long value;
fetch_int_setting ( settings, setting, &value );
return value;
@@ -484,7 +532,7 @@ long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
*/
unsigned long fetch_uintz_setting ( struct settings *settings,
struct setting *setting ) {
- unsigned long value = 0;
+ unsigned long value;
fetch_uint_setting ( settings, setting, &value );
return value;
@@ -655,6 +703,7 @@ static int parse_setting_name ( const char *name, struct settings **settings,
}
tmp++;
}
+ setting->tag |= (*settings)->tag_magic;
}
/* Identify setting type, if specified */
@@ -776,12 +825,15 @@ static int storef_uristring ( struct settings *settings,
static int fetchf_uristring ( struct settings *settings,
struct setting *setting,
char *buf, size_t len ) {
- size_t raw_len;
+ ssize_t raw_len;
/* We need to always retrieve the full raw string to know the
* length of the encoded string.
*/
raw_len = fetch_setting ( settings, setting, NULL, 0 );
+ if ( raw_len < 0 )
+ return raw_len;
+
{
char raw_buf[ raw_len + 1 ];
diff --git a/gpxe/src/core/timer.c b/gpxe/src/core/timer.c
index 4e047ea7..d71e3da1 100644
--- a/gpxe/src/core/timer.c
+++ b/gpxe/src/core/timer.c
@@ -1,7 +1,5 @@
/*
- * core/timer.c
- *
- * Copyright (C) 2007 Alexey Zaytsev <alexey.zaytsev@gmail.com>
+ * Copyright (C) 2008 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
@@ -18,96 +16,25 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <stddef.h>
-#include <assert.h>
-#include <gpxe/timer.h>
-
-static struct timer ts_table[0]
- __table_start ( struct timer, timers );
-static struct timer ts_table_end[0]
- __table_end ( struct timer, timers );
-
-/*
- * This function may be used in custom timer driver.
- *
- * This udelay implementation works well if you've got a
- * fast currticks().
- */
-void generic_currticks_udelay ( unsigned int usecs ) {
- tick_t start;
- tick_t elapsed;
-
- start = currticks();
- do {
- /* xxx: Relax the cpu some way. */
- elapsed = ( currticks() - start );
- } while ( elapsed < usecs );
-}
-
-/**
- * Identify timer source
- *
- * @ret timer Timer source
- */
-static struct timer * timer ( void ) {
- static struct timer *ts = NULL;
-
- /* If we have a timer, use it */
- if ( ts )
- return ts;
-
- /* Scan for a usable timer */
- for ( ts = ts_table ; ts < ts_table_end ; ts++ ) {
- if ( ts->init() == 0 )
- return ts;
- }
-
- /* No timer found; we cannot continue */
- assert ( 0 );
- while ( 1 ) {};
-}
-
-/**
- * Read current time
- *
- * @ret ticks Current time, in ticks
- */
-tick_t currticks ( void ) {
- tick_t ct;
-
- ct = timer()->currticks();
- DBG ( "currticks: %ld.%06ld seconds\n",
- ct / USECS_IN_SEC, ct % USECS_IN_SEC );
-
- return ct;
-}
-
-/**
- * Delay
- *
- * @v usecs Time to delay, in microseconds
- */
-void udelay ( unsigned int usecs ) {
- timer()->udelay ( usecs );
-}
+#include <unistd.h>
/**
- * Delay
+ * Delay for a fixed number of milliseconds
*
- * @v msecs Time to delay, in milliseconds
+ * @v msecs Number of milliseconds for which to delay
*/
-void mdelay ( unsigned int msecs ) {
+void mdelay ( unsigned long msecs ) {
while ( msecs-- )
- udelay ( USECS_IN_MSEC );
+ udelay ( 1000 );
}
/**
- * Delay
+ * Delay for a fixed number of seconds
*
- * @v secs Time to delay, in seconds
+ * @v secs Number of seconds for which to delay
*/
unsigned int sleep ( unsigned int secs ) {
while ( secs-- )
- mdelay ( MSECS_IN_SEC );
+ mdelay ( 1000 );
return 0;
}
diff --git a/gpxe/src/core/uri.c b/gpxe/src/core/uri.c
index cf2b071d..7bb46da0 100644
--- a/gpxe/src/core/uri.c
+++ b/gpxe/src/core/uri.c
@@ -92,8 +92,12 @@ struct uri * parse_uri ( const char *uri_string ) {
uri->fragment = tmp;
}
- /* Identify absolute/relative URI */
- if ( ( tmp = strchr ( raw, ':' ) ) ) {
+ /* Identify absolute/relative URI. We ignore schemes that are
+ * apparently only a single character long, since otherwise we
+ * misinterpret a DOS-style path name ("C:\path\to\file") as a
+ * URI with scheme="C",opaque="\path\to\file".
+ */
+ if ( ( tmp = strchr ( raw, ':' ) ) && ( tmp > ( raw + 1 ) ) ) {
/* Absolute URI: identify hierarchical/opaque */
uri->scheme = raw;
*(tmp++) = '\0';
diff --git a/gpxe/src/core/uuid.c b/gpxe/src/core/uuid.c
index c6e7f5d5..a3a82c68 100644
--- a/gpxe/src/core/uuid.c
+++ b/gpxe/src/core/uuid.c
@@ -36,7 +36,7 @@
char * uuid_ntoa ( union uuid *uuid ) {
static char buf[37]; /* "00000000-0000-0000-0000-000000000000" */
- sprintf ( buf, "%08lx-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ sprintf ( buf, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
be32_to_cpu ( uuid->canonical.a ),
be16_to_cpu ( uuid->canonical.b ),
be16_to_cpu ( uuid->canonical.c ),
diff --git a/gpxe/src/core/xfer.c b/gpxe/src/core/xfer.c
index 14c77d64..9ed19da2 100644
--- a/gpxe/src/core/xfer.c
+++ b/gpxe/src/core/xfer.c
@@ -28,6 +28,14 @@
*/
/**
+ * Dummy transfer metadata
+ *
+ * This gets passed to xfer_interface::deliver_iob() and equivalents
+ * when no metadata is available.
+ */
+static struct xfer_metadata dummy_metadata;
+
+/**
* Close data transfer interface
*
* @v xfer Data transfer interface
@@ -159,7 +167,6 @@ int xfer_deliver_iob_meta ( struct xfer_interface *xfer,
*/
int xfer_deliver_iob ( struct xfer_interface *xfer,
struct io_buffer *iobuf ) {
- static struct xfer_metadata dummy_metadata;
return xfer_deliver_iob_meta ( xfer, iobuf, &dummy_metadata );
}
@@ -366,7 +373,7 @@ int xfer_deliver_as_iob ( struct xfer_interface *xfer,
return -ENOMEM;
memcpy ( iob_put ( iobuf, len ), data, len );
- return xfer->op->deliver_iob ( xfer, iobuf, NULL );
+ return xfer->op->deliver_iob ( xfer, iobuf, &dummy_metadata );
}
/**
diff --git a/gpxe/src/crypto/asn1.c b/gpxe/src/crypto/asn1.c
index 0a69162a..25e7495b 100644
--- a/gpxe/src/crypto/asn1.c
+++ b/gpxe/src/crypto/asn1.c
@@ -32,7 +32,7 @@
*
* @v cursor ASN.1 object cursor
* @v type Expected type
- * @ret len Length of object body, or -1 on error
+ * @ret len Length of object body, or negative error
*
* The object cursor will be updated to point to the start of the
* object body (i.e. the first byte following the length byte(s)), and
@@ -44,29 +44,32 @@
* the cursor will be invalidated and a negative value will be
* returned.
*/
-static int asn1_start_object ( struct asn1_cursor *cursor,
+static int asn1_start ( struct asn1_cursor *cursor,
unsigned int type ) {
unsigned int len_len;
unsigned int len;
+ int rc;
/* Sanity check */
if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
if ( cursor->len )
DBGC ( cursor, "ASN1 %p too short\n", cursor );
+ rc = -EINVAL;
goto notfound;
}
/* Check the tag byte */
- if ( cursor->data[0] != type ) {
+ if ( *( ( uint8_t * ) cursor->data ) != type ) {
DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
- cursor, type, cursor->data[0] );
+ cursor, type, *( ( uint8_t * ) cursor->data ) );
+ rc = -ENXIO;
goto notfound;
}
cursor->data++;
cursor->len--;
/* Extract length of the length field and sanity check */
- len_len = cursor->data[0];
+ len_len = *( ( uint8_t * ) cursor->data );
if ( len_len & 0x80 ) {
len_len = ( len_len & 0x7f );
cursor->data++;
@@ -77,19 +80,21 @@ static int asn1_start_object ( struct asn1_cursor *cursor,
if ( cursor->len < len_len ) {
DBGC ( cursor, "ASN1 %p bad length field length %d (max "
"%zd)\n", cursor, len_len, cursor->len );
+ rc = -EINVAL;
goto notfound;
}
/* Extract the length and sanity check */
for ( len = 0 ; len_len ; len_len-- ) {
len <<= 8;
- len |= cursor->data[0];
+ len |= *( ( uint8_t * ) cursor->data );
cursor->data++;
cursor->len--;
}
if ( cursor->len < len ) {
DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
cursor, len, cursor->len );
+ rc = -EINVAL;
goto notfound;
}
@@ -98,7 +103,7 @@ static int asn1_start_object ( struct asn1_cursor *cursor,
notfound:
cursor->data = NULL;
cursor->len = 0;
- return -1;
+ return rc;
}
/**
@@ -112,12 +117,12 @@ static int asn1_start_object ( struct asn1_cursor *cursor,
* current ASN.1 object. If any error occurs, the object cursor will
* be invalidated.
*/
-int asn1_enter_object ( struct asn1_cursor *cursor, unsigned int type ) {
+int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
int len;
- len = asn1_start_object ( cursor, type );
+ len = asn1_start ( cursor, type );
if ( len < 0 )
- return -ENOENT;
+ return len;
cursor->len = len;
DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
@@ -137,12 +142,12 @@ int asn1_enter_object ( struct asn1_cursor *cursor, unsigned int type ) {
* object. If any error occurs, the object cursor will be
* invalidated.
*/
-int asn1_skip_object ( struct asn1_cursor *cursor, unsigned int type ) {
+int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
int len;
- len = asn1_start_object ( cursor, type );
+ len = asn1_start ( cursor, type );
if ( len < 0 )
- return -ENOENT;
+ return len;
cursor->data += len;
cursor->len -= len;
diff --git a/gpxe/src/crypto/axtls/axtls_asn1.c b/gpxe/src/crypto/axtls/axtls_asn1.c
deleted file mode 100644
index 74411c70..00000000
--- a/gpxe/src/crypto/axtls/axtls_asn1.c
+++ /dev/null
@@ -1,867 +0,0 @@
-/*
- * Copyright(C) 2006 Cameron Rich
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/**
- * @file asn1.c
- *
- * Some primitive asn methods for extraction rsa modulus information. It also
- * is used for retrieving information from X.509 certificates.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "crypto.h"
-
-#define SIG_OID_PREFIX_SIZE 8
-
-#define SIG_TYPE_MD2 0x02
-#define SIG_TYPE_MD5 0x04
-#define SIG_TYPE_SHA1 0x05
-
-/* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
-static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] =
-{
- 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01
-};
-
-/* CN, O, OU */
-static const uint8_t g_dn_types[] = { 3, 10, 11 };
-
-static int get_asn1_length(const uint8_t *buf, int *offset)
-{
- int len, i;
-
- if (!(buf[*offset] & 0x80)) /* short form */
- {
- len = buf[(*offset)++];
- }
- else /* long form */
- {
- int length_bytes = buf[(*offset)++]&0x7f;
- len = 0;
- for (i = 0; i < length_bytes; i++)
- {
- len <<= 8;
- len += buf[(*offset)++];
- }
- }
-
- return len;
-}
-
-/**
- * Skip the ASN1.1 object type and its length. Get ready to read the object's
- * data.
- */
-int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type)
-{
- if (buf[*offset] != obj_type)
- return X509_NOT_OK;
- (*offset)++;
- return get_asn1_length(buf, offset);
-}
-
-/**
- * Skip over an ASN.1 object type completely. Get ready to read the next
- * object.
- */
-int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
-{
- int len;
-
- if (buf[*offset] != obj_type)
- return X509_NOT_OK;
- (*offset)++;
- len = get_asn1_length(buf, offset);
- *offset += len;
- return 0;
-}
-
-/**
- * Read an integer value for ASN.1 data
- * Note: This function allocates memory which must be freed by the user.
- */
-int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object)
-{
- int len;
-
- if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
- goto end_int_array;
-
- *object = (uint8_t *)malloc(len);
- memcpy(*object, &buf[*offset], len);
- *offset += len;
-
-end_int_array:
- return len;
-}
-
-#if 0
-
-/**
- * Get all the RSA private key specifics from an ASN.1 encoded file
- */
-int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx)
-{
- int offset = 7;
- uint8_t *modulus, *priv_exp, *pub_exp;
- int mod_len, priv_len, pub_len;
-#ifdef CONFIG_BIGINT_CRT
- uint8_t *p, *q, *dP, *dQ, *qInv;
- int p_len, q_len, dP_len, dQ_len, qInv_len;
-#endif
-
- /* not in der format */
- if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("Error: This is not a valid ASN.1 file\n");
-#endif
- return X509_INVALID_PRIV_KEY;
- }
-
- /* initialise the RNG */
- RNG_initialize(buf, len);
-
- mod_len = asn1_get_int(buf, &offset, &modulus);
- pub_len = asn1_get_int(buf, &offset, &pub_exp);
- priv_len = asn1_get_int(buf, &offset, &priv_exp);
-
- if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
- return X509_INVALID_PRIV_KEY;
-
-#ifdef CONFIG_BIGINT_CRT
- p_len = asn1_get_int(buf, &offset, &p);
- q_len = asn1_get_int(buf, &offset, &q);
- dP_len = asn1_get_int(buf, &offset, &dP);
- dQ_len = asn1_get_int(buf, &offset, &dQ);
- qInv_len = asn1_get_int(buf, &offset, &qInv);
-
- if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
- return X509_INVALID_PRIV_KEY;
-
- RSA_priv_key_new(rsa_ctx,
- modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len,
- p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len);
-
- free(p);
- free(q);
- free(dP);
- free(dQ);
- free(qInv);
-#else
- RSA_priv_key_new(rsa_ctx,
- modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len);
-#endif
-
- free(modulus);
- free(priv_exp);
- free(pub_exp);
- return X509_OK;
-}
-
-/**
- * Get the time of a certificate. Ignore hours/minutes/seconds.
- */
-static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
-{
- int ret = X509_NOT_OK, len, t_offset;
- struct tm tm;
-
- if (buf[(*offset)++] != ASN1_UTC_TIME)
- goto end_utc_time;
- len = get_asn1_length(buf, offset);
- t_offset = *offset;
-
- memset(&tm, 0, sizeof(struct tm));
- tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
-
- if (tm.tm_year <= 50) /* 1951-2050 thing */
- {
- tm.tm_year += 100;
- }
-
- tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
- tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
- *t = mktime(&tm);
- *offset += len;
- ret = X509_OK;
-
-end_utc_time:
- return ret;
-}
-
-/**
- * Get the version type of a certificate (which we don't actually care about)
- */
-static int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
-{
- int ret = X509_NOT_OK;
-
- (*offset) += 2; /* get past explicit tag */
- if (asn1_skip_obj(cert, offset, ASN1_INTEGER))
- goto end_version;
-
- ret = X509_OK;
-end_version:
- return ret;
-}
-
-/**
- * Retrieve the notbefore and notafter certificate times.
- */
-static int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
-{
- return (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
- asn1_get_utc_time(cert, offset, &x509_ctx->not_before) ||
- asn1_get_utc_time(cert, offset, &x509_ctx->not_after));
-}
-
-/**
- * Get the components of a distinguished name
- */
-static int asn1_get_oid_x520(const uint8_t *buf, int *offset)
-{
- int dn_type = 0;
- int len;
-
- if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
- goto end_oid;
-
- /* expect a sequence of 2.5.4.[x] where x is a one of distinguished name
- components we are interested in. */
- if (len == 3 && buf[(*offset)++] == 0x55 && buf[(*offset)++] == 0x04)
- dn_type = buf[(*offset)++];
- else
- {
- *offset += len; /* skip over it */
- }
-
-end_oid:
- return dn_type;
-}
-
-/**
- * Obtain an ASN.1 printable string type.
- */
-static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
-{
- int len = X509_NOT_OK;
-
- /* some certs have this awful crud in them for some reason */
- if (buf[*offset] != ASN1_PRINTABLE_STR &&
- buf[*offset] != ASN1_TELETEX_STR && buf[*offset] != ASN1_IA5_STR)
- goto end_pnt_str;
-
- (*offset)++;
- len = get_asn1_length(buf, offset);
- *str = (char *)malloc(len+1); /* allow for null */
- memcpy(*str, &buf[*offset], len);
- (*str)[len] = 0; /* null terminate */
- *offset += len;
-end_pnt_str:
- return len;
-}
-
-/**
- * Get the subject name (or the issuer) of a certificate.
- */
-static int asn1_name(const uint8_t *cert, int *offset, char *dn[])
-{
- int ret = X509_NOT_OK;
- int dn_type;
- char *tmp = NULL;
-
- if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
- goto end_name;
-
- while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
- {
- int i, found = 0;
-
- if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
- (dn_type = asn1_get_oid_x520(cert, offset)) < 0)
- goto end_name;
-
- if (asn1_get_printable_str(cert, offset, &tmp) < 0)
- {
- free(tmp);
- goto end_name;
- }
-
- /* find the distinguished named type */
- for (i = 0; i < X509_NUM_DN_TYPES; i++)
- {
- if (dn_type == g_dn_types[i])
- {
- if (dn[i] == NULL)
- {
- dn[i] = tmp;
- found = 1;
- break;
- }
- }
- }
-
- if (found == 0) /* not found so get rid of it */
- {
- free(tmp);
- }
- }
-
- ret = X509_OK;
-end_name:
- return ret;
-}
-
-/**
- * Read the modulus and public exponent of a certificate.
- */
-static int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
-{
- int ret = X509_NOT_OK, mod_len, pub_len;
- uint8_t *modulus, *pub_exp;
-
- if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(cert, offset, ASN1_SEQUENCE) ||
- asn1_next_obj(cert, offset, ASN1_BIT_STRING) < 0)
- goto end_pub_key;
-
- (*offset)++;
-
- if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
- goto end_pub_key;
-
- mod_len = asn1_get_int(cert, offset, &modulus);
- pub_len = asn1_get_int(cert, offset, &pub_exp);
-
- RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
-
- free(modulus);
- free(pub_exp);
- ret = X509_OK;
-
-end_pub_key:
- return ret;
-}
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-/**
- * Read the signature of the certificate.
- */
-static int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
-{
- int ret = X509_NOT_OK;
-
- if (cert[(*offset)++] != ASN1_BIT_STRING)
- goto end_sig;
-
- x509_ctx->sig_len = get_asn1_length(cert, offset);
- x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
- memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
- *offset += x509_ctx->sig_len;
- ret = X509_OK;
-
-end_sig:
- return ret;
-}
-
-/*
- * Compare 2 distinguished name components for equality
- * @return 0 if a match
- */
-static int asn1_compare_dn_comp(const char *dn1, const char *dn2)
-{
- int ret = 1;
-
- if ((dn1 && dn2 == NULL) || (dn1 == NULL && dn2)) goto err_no_match;
-
- ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 0;
-
-err_no_match:
- return ret;
-}
-
-/**
- * Clean up all of the CA certificates.
- */
-void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx)
-{
- int i = 0;
-
- while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
- {
- x509_free(ca_cert_ctx->cert[i]);
- ca_cert_ctx->cert[i++] = NULL;
- }
-
- free(ca_cert_ctx);
-}
-
-/*
- * Compare 2 distinguished names for equality
- * @return 0 if a match
- */
-static int asn1_compare_dn(char * const dn1[], char * const dn2[])
-{
- int i;
-
- for (i = 0; i < X509_NUM_DN_TYPES; i++)
- {
- if (asn1_compare_dn_comp(dn1[i], dn2[i]))
- {
- return 1;
- }
- }
-
- return 0; /* all good */
-}
-
-/**
- * Retrieve the signature from a certificate.
- */
-const uint8_t *x509_get_signature(const uint8_t *asn1_sig, int *len)
-{
- int offset = 0;
- const uint8_t *ptr = NULL;
-
- if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
- goto end_get_sig;
-
- if (asn1_sig[offset++] != ASN1_OCTET_STRING)
- goto end_get_sig;
- *len = get_asn1_length(asn1_sig, &offset);
- ptr = &asn1_sig[offset]; /* all ok */
-
-end_get_sig:
- return ptr;
-}
-
-#endif
-
-/**
- * Read the signature type of the certificate. We only support RSA-MD5 and
- * RSA-SHA1 signature types.
- */
-static int asn1_signature_type(const uint8_t *cert,
- int *offset, X509_CTX *x509_ctx)
-{
- int ret = X509_NOT_OK, len;
-
- if (cert[(*offset)++] != ASN1_OID)
- goto end_check_sig;
-
- len = get_asn1_length(cert, offset);
-
- if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
- goto end_check_sig; /* unrecognised cert type */
-
- x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
-
- *offset += len;
- if (asn1_skip_obj(cert, offset, ASN1_NULL))
- goto end_check_sig;
- ret = X509_OK;
-
-end_check_sig:
- return ret;
-}
-
-/**
- * Construct a new x509 object.
- * @return 0 if ok. < 0 if there was a problem.
- */
-int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
-{
- int begin_tbs, end_tbs;
- int ret = X509_NOT_OK, offset = 0, cert_size = 0;
- X509_CTX *x509_ctx;
- BI_CTX *bi_ctx;
-
- *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
- x509_ctx = *ctx;
-
- /* get the certificate size */
- asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE);
-
- if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
- goto end_cert;
-
- begin_tbs = offset; /* start of the tbs */
- end_tbs = begin_tbs; /* work out the end of the tbs */
- asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE);
-
- if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
- goto end_cert;
-
- if (cert[offset] == ASN1_EXPLICIT_TAG) /* optional version */
- {
- if (asn1_version(cert, &offset, x509_ctx))
- goto end_cert;
- }
-
- if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */
- asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
- goto end_cert;
-
- /* make sure the signature is ok */
- if (asn1_signature_type(cert, &offset, x509_ctx))
- {
- ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
- goto end_cert;
- }
-
- if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) ||
- asn1_validity(cert, &offset, x509_ctx) ||
- asn1_name(cert, &offset, x509_ctx->cert_dn) ||
- asn1_public_key(cert, &offset, x509_ctx))
- goto end_cert;
-
- bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
- /* use the appropriate signature algorithm (either SHA1 or MD5) */
- if (x509_ctx->sig_type == SIG_TYPE_MD5)
- {
- MD5_CTX md5_ctx;
- uint8_t md5_dgst[MD5_SIZE];
- MD5Init(&md5_ctx);
- MD5Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
- MD5Final(&md5_ctx, md5_dgst);
- x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
- }
- else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
- {
- SHA1_CTX sha_ctx;
- uint8_t sha_dgst[SHA1_SIZE];
- SHA1Init(&sha_ctx);
- SHA1Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
- SHA1Final(&sha_ctx, sha_dgst);
- x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
- }
-
- offset = end_tbs; /* skip the v3 data */
- if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) ||
- asn1_signature(cert, &offset, x509_ctx))
- goto end_cert;
-#endif
-
- if (len)
- {
- *len = cert_size;
- }
-
- ret = X509_OK;
-end_cert:
-
-#ifdef CONFIG_SSL_FULL_MODE
- if (ret)
- {
- printf("Error: Invalid X509 ASN.1 file\n");
- }
-#endif
-
- return ret;
-}
-
-/**
- * Free an X.509 object's resources.
- */
-void x509_free(X509_CTX *x509_ctx)
-{
- X509_CTX *next;
- int i;
-
- if (x509_ctx == NULL) /* if already null, then don't bother */
- return;
-
- for (i = 0; i < X509_NUM_DN_TYPES; i++)
- {
- free(x509_ctx->ca_cert_dn[i]);
- free(x509_ctx->cert_dn[i]);
- }
-
- free(x509_ctx->signature);
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- if (x509_ctx->digest)
- {
- bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
- }
-#endif
-
- RSA_free(x509_ctx->rsa_ctx);
-
- next = x509_ctx->next;
- free(x509_ctx);
- x509_free(next); /* clear the chain */
-}
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-/**
- * Do some basic checks on the certificate chain.
- *
- * Certificate verification consists of a number of checks:
- * - A root certificate exists in the certificate store.
- * - The date of the certificate is after the start date.
- * - The date of the certificate is before the finish date.
- * - The certificate chain is valid.
- * - That the certificate(s) are not self-signed.
- * - The signature of the certificate is valid.
- */
-int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
-{
- int ret = X509_OK, i = 0;
- bigint *cert_sig;
- X509_CTX *next_cert = NULL;
- BI_CTX *ctx;
- bigint *mod, *expn;
- struct timeval tv;
- int match_ca_cert = 0;
-
- if (cert == NULL || ca_cert_ctx == NULL)
- {
- ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
- goto end_verify;
- }
-
- /* last cert in the chain - look for a trusted cert */
- if (cert->next == NULL)
- {
- while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
- {
- if (asn1_compare_dn(cert->ca_cert_dn,
- ca_cert_ctx->cert[i]->cert_dn) == 0)
- {
- match_ca_cert = 1;
- break;
- }
-
- i++;
- }
-
- if (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
- {
- next_cert = ca_cert_ctx->cert[i];
- }
- else /* trusted cert not found */
- {
- ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
- goto end_verify;
- }
- }
- else
- {
- next_cert = cert->next;
- }
-
- gettimeofday(&tv, NULL);
-
- /* check the not before date */
- if (tv.tv_sec < cert->not_before)
- {
- ret = X509_VFY_ERROR_NOT_YET_VALID;
- goto end_verify;
- }
-
- /* check the not after date */
- if (tv.tv_sec > cert->not_after)
- {
- ret = X509_VFY_ERROR_EXPIRED;
- goto end_verify;
- }
-
- /* check the chain integrity */
- if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn))
- {
- ret = X509_VFY_ERROR_INVALID_CHAIN;
- goto end_verify;
- }
-
- /* check for self-signing */
- if (!match_ca_cert && asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
- {
- ret = X509_VFY_ERROR_SELF_SIGNED;
- goto end_verify;
- }
-
- /* check the signature */
- ctx = cert->rsa_ctx->bi_ctx;
- mod = next_cert->rsa_ctx->m;
- expn = next_cert->rsa_ctx->e;
- cert_sig = RSA_sign_verify(ctx, cert->signature, cert->sig_len,
- bi_clone(ctx, mod), bi_clone(ctx, expn));
-
- if (cert_sig)
- {
- ret = cert->digest ? /* check the signature */
- bi_compare(cert_sig, cert->digest) :
- X509_VFY_ERROR_UNSUPPORTED_DIGEST;
- bi_free(ctx, cert_sig);
-
- if (ret)
- goto end_verify;
- }
- else
- {
- ret = X509_VFY_ERROR_BAD_SIGNATURE;
- goto end_verify;
- }
-
- /* go down the certificate chain using recursion. */
- if (ret == 0 && cert->next)
- {
- ret = x509_verify(ca_cert_ctx, next_cert);
- }
-
-end_verify:
- return ret;
-}
-#endif
-
-#if defined (CONFIG_SSL_FULL_MODE)
-/**
- * Used for diagnostics.
- */
-void x509_print(CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
-{
- if (cert == NULL)
- return;
-
- printf("---------------- CERT DEBUG ----------------\n");
- printf("* CA Cert Distinguished Name\n");
- if (cert->ca_cert_dn[X509_COMMON_NAME])
- {
- printf("Common Name (CN):\t%s\n", cert->ca_cert_dn[X509_COMMON_NAME]);
- }
-
- if (cert->ca_cert_dn[X509_ORGANIZATION])
- {
- printf("Organization (O):\t%s\n", cert->ca_cert_dn[X509_ORGANIZATION]);
- }
-
- if (cert->ca_cert_dn[X509_ORGANIZATIONAL_TYPE])
- {
- printf("Organizational Unit (OU): %s\n",
- cert->ca_cert_dn[X509_ORGANIZATIONAL_TYPE]);
- }
-
- printf("* Cert Distinguished Name\n");
- if (cert->cert_dn[X509_COMMON_NAME])
- {
- printf("Common Name (CN):\t%s\n", cert->cert_dn[X509_COMMON_NAME]);
- }
-
- if (cert->cert_dn[X509_ORGANIZATION])
- {
- printf("Organization (O):\t%s\n", cert->cert_dn[X509_ORGANIZATION]);
- }
-
- if (cert->cert_dn[X509_ORGANIZATIONAL_TYPE])
- {
- printf("Organizational Unit (OU): %s\n",
- cert->cert_dn[X509_ORGANIZATIONAL_TYPE]);
- }
-
- printf("Not Before:\t\t%s", ctime(&cert->not_before));
- printf("Not After:\t\t%s", ctime(&cert->not_after));
- printf("RSA bitsize:\t\t%d\n", cert->rsa_ctx->num_octets*8);
- printf("Sig Type:\t\t");
- switch (cert->sig_type)
- {
- case SIG_TYPE_MD5:
- printf("MD5\n");
- break;
- case SIG_TYPE_SHA1:
- printf("SHA1\n");
- break;
- case SIG_TYPE_MD2:
- printf("MD2\n");
- break;
- default:
- printf("Unrecognized: %d\n", cert->sig_type);
- break;
- }
-
- printf("Verify:\t\t\t");
-
- if (ca_cert_ctx)
- {
- x509_display_error(x509_verify(ca_cert_ctx, cert));
- }
-
- printf("\n");
-#if 0
- print_blob("Signature", cert->signature, cert->sig_len);
- bi_print("Modulus", cert->rsa_ctx->m);
- bi_print("Pub Exp", cert->rsa_ctx->e);
-#endif
-
- if (ca_cert_ctx)
- {
- x509_print(ca_cert_ctx, cert->next);
- }
-}
-
-void x509_display_error(int error)
-{
- switch (error)
- {
- case X509_NOT_OK:
- printf("X509 not ok");
- break;
-
- case X509_VFY_ERROR_NO_TRUSTED_CERT:
- printf("No trusted cert is available");
- break;
-
- case X509_VFY_ERROR_BAD_SIGNATURE:
- printf("Bad signature");
- break;
-
- case X509_VFY_ERROR_NOT_YET_VALID:
- printf("Cert is not yet valid");
- break;
-
- case X509_VFY_ERROR_EXPIRED:
- printf("Cert has expired");
- break;
-
- case X509_VFY_ERROR_SELF_SIGNED:
- printf("Cert is self-signed");
- break;
-
- case X509_VFY_ERROR_INVALID_CHAIN:
- printf("Chain is invalid (check order of certs)");
- break;
-
- case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
- printf("Unsupported digest");
- break;
-
- case X509_INVALID_PRIV_KEY:
- printf("Invalid private key");
- break;
- }
-}
-#endif /* CONFIG_SSL_FULL_MODE */
-
-#endif
diff --git a/gpxe/src/crypto/cryptoLayer.h b/gpxe/src/crypto/cryptoLayer.h
deleted file mode 100644
index 28ce97bc..00000000
--- a/gpxe/src/crypto/cryptoLayer.h
+++ /dev/null
@@ -1,120 +0,0 @@
-#ifndef _MATRIXSSL_CRYPTOLAYER_H
-#define _MATRIXSSL_CRYPTOLAYER_H
-
-/** @file
- *
- * Compatibility layer for MatrixSSL
- *
- */
-
-#include <stdint.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <byteswap.h>
-#include <gpxe/bitops.h>
-#include <gpxe/crypto.h>
-
-/* Drag in pscrypto.h */
-typedef uint64_t ulong64;
-typedef void psPool_t;
-#define SMALL_CODE
-#define USE_INT64
-#define USE_RSA
-#define USE_RSA_PUBLIC_ENCRYPT
-#define CRYPT
-#include "matrixssl/pscrypto.h"
-#define SMALL_CODE
-#undef CLEAN_STACK
-
-#define sslAssert( ... ) assert ( __VA_ARGS__ )
-
-static inline __attribute__ (( always_inline )) void * __malloc
-psMalloc ( psPool_t *pool __unused, size_t len ) {
- return malloc ( len );
-}
-
-static inline __attribute__ (( always_inline )) void *
-psRealloc ( void *ptr, size_t len ) {
- return realloc ( ptr, len );
-}
-
-static inline __attribute__ (( always_inline )) void psFree ( void *ptr ) {
- free ( ptr );
-}
-
-#define matrixStrDebugMsg( ... ) DBG ( __VA_ARGS__ )
-#define matrixIntDebugMsg( ... ) DBG ( __VA_ARGS__ )
-
-/* Use our standard cpu_to_leXX etc. macros */
-
-#undef LOAD32L
-#define LOAD32L( cpu32, ptr ) do { \
- uint32_t *le32 = ( ( uint32_t * ) ptr ); \
- cpu32 = le32_to_cpu ( *le32 ); \
- } while ( 0 )
-
-#undef LOAD32H
-#define LOAD32H( cpu32, ptr ) do { \
- uint32_t *be32 = ( ( uint32_t * ) ptr ); \
- cpu32 = be32_to_cpu ( *be32 ); \
- } while ( 0 )
-
-#undef LOAD64L
-#define LOAD64L( cpu64, ptr ) do { \
- uint64_t *le64 = ( ( uint64_t * ) ptr ); \
- cpu64 = le64_to_cpu ( *le64 ); \
- } while ( 0 )
-
-#undef LOAD64H
-#define LOAD64H( cpu64, ptr ) do { \
- uint64_t *be64 = ( ( uint64_t * ) ptr ); \
- cpu64 = be64_to_cpu ( *be64 ); \
- } while ( 0 )
-
-#undef STORE32L
-#define STORE32L( cpu32, ptr ) do { \
- uint32_t *le32 = ( ( uint32_t * ) ptr ); \
- *le32 = cpu_to_le32 ( cpu32 ); \
- } while ( 0 )
-
-#undef STORE32H
-#define STORE32H( cpu32, ptr ) do { \
- uint32_t *be32 = ( ( uint32_t * ) ptr ); \
- *be32 = cpu_to_be32 ( cpu32 ); \
- } while ( 0 )
-
-#undef STORE64L
-#define STORE64L( cpu64, ptr ) do { \
- uint64_t *le64 = ( ( uint64_t * ) ptr ); \
- *le64 = cpu_to_le64 ( cpu64 ); \
- } while ( 0 )
-
-#undef STORE64H
-#define STORE64H( cpu64, ptr ) do { \
- uint64_t *be64 = ( ( uint64_t * ) ptr ); \
- *be64 = cpu_to_be64 ( cpu64 ); \
- } while ( 0 )
-
-/* Use rolXX etc. from bitops.h */
-
-#undef ROL
-#define ROL( data, rotation ) rol32 ( (data), (rotation) )
-#undef ROLc
-#define ROLc( data, rotation ) rol32 ( (data), (rotation) )
-#undef ROR
-#define ROR( data, rotation ) ror32 ( (data), (rotation) )
-#undef RORc
-#define RORc( data, rotation ) ror32 ( (data), (rotation) )
-#undef ROL64
-#define ROL64( data, rotation ) rol64 ( (data), (rotation) )
-#undef ROL64c
-#define ROL64c( data, rotation ) rol64 ( (data), (rotation) )
-#undef ROR64
-#define ROR64( data, rotation ) ror64 ( (data), (rotation) )
-#undef ROR64c
-#define ROR64c( data, rotation ) ror64 ( (data), (rotation) )
-
-#endif /* _MATRIXSSL_CRYPTOLAYER_H */
diff --git a/gpxe/src/crypto/framework.c b/gpxe/src/crypto/framework.c
deleted file mode 100644
index 0da2cbe3..00000000
--- a/gpxe/src/crypto/framework.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* mcb - this file breaks the build process; temporarily deactivating */
-#if 0
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include "ssl.h"
-
-int main(int argc, char *argv[])
-{
- SSL_t ssl;
- int sockfd, portno, rc;
- struct sockaddr_in serv_addr;
- struct hostent *server;
-
- portno = 443;
- sockfd = socket(AF_INET,SOCK_STREAM,0);
- if(sockfd<0){
- fprintf(stderr,"Error creating socket\n");
- exit(sockfd);
- }
-
- server = gethostbyname(argv[1]);
- if(server==NULL){
- fprintf(stderr,"Error looking up host %s\n",argv[1]);
- exit(1);
- }
-
- /**
- *matrixSslOpen()
- *matrixSslReadKeys()
- **/
- printf("Calling CreateSSLHello()\n");
- rc = CreateSSLHello(&ssl);
- printf("Finished calling CreateSSLHello()\n");
-
- bzero((char *) &serv_addr, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length);
- serv_addr.sin_port = htons(portno);
- if(connect(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
- fprintf(stderr,"ERROR connecting to server\n");
- exit(1);
- }
-
- PrintSSLPacket(&ssl);
-
- printf("Write ssl.buffer\n");
- write(sockfd,ssl.buffer,ssl.length);
- printf("Finished writing\n");
- ssl.length = read(sockfd,ssl.buffer,ssl.max_size);
- ReadSSLHello(&ssl);
-
- /**
- *matrixSslNewSession()
- *matrixSslSetCetValidator()
- *encodeSslHandshake()
-
- *write handshake buffer
-
- *readSslResponse() <-+
- |
- *read return code |-- similar/same function??
- |
- *sslEncode() |
- *sslDecode() <-------+
-
- *encodeSslCloseAlert()
-
- *write close alert buffer
- **/
- close(sockfd);
-
- /**
- *sslClose()
- * -free connection
- * -free keys
- * -close pki interface
- **/
-
- return 0;
-}
-
-#endif
diff --git a/gpxe/src/crypto/matrixssl/mpi.h b/gpxe/src/crypto/matrixssl/mpi.h
deleted file mode 100644
index bb2c9c57..00000000
--- a/gpxe/src/crypto/matrixssl/mpi.h
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * mpi.h
- * Release $Name$
- *
- * multiple-precision integer library
- */
-/*
- * Copyright (c) PeerSec Networks, 2002-2006. All Rights Reserved.
- * The latest version of this code is available at http://www.matrixssl.org
- *
- * This software is open source; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This General Public License does NOT permit incorporating this software
- * into proprietary programs. If you are unable to comply with the GPL, a
- * commercial license for this software may be purchased from PeerSec Networks
- * at http://www.peersec.com
- *
- * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * http://www.gnu.org/copyleft/gpl.html
- */
-/******************************************************************************/
-
-#ifndef _h_MPI
-#define _h_MPI
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <limits.h>
-
-#undef MIN
-#define MIN(x,y) ((x)<(y)?(x):(y))
-#undef MAX
-#define MAX(x,y) ((x)>(y)?(x):(y))
-
-#ifdef __cplusplus
-extern "C" {
-
-
-/*
- C++ compilers don't like assigning void * to mp_digit *
- */
-#define OPT_CAST(x) (x *)
-
-#else
-
-/*
- C on the other hand doesn't care
- */
-#define OPT_CAST(x)
-
-#endif /* __cplusplus */
-
-/******************************************************************************/
-/*
- some default configurations.
-
- A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
- A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
-
- At the very least a mp_digit must be able to hold 7 bits
- [any size beyond that is ok provided it doesn't overflow the data type]
- */
-#ifdef MP_8BIT
- typedef unsigned char mp_digit;
- typedef unsigned short mp_word;
-#elif defined(MP_16BIT)
- typedef unsigned short mp_digit;
- typedef unsigned long mp_word;
-#elif defined(MP_64BIT)
-/*
- for GCC only on supported platforms
- */
- #ifndef CRYPT
- typedef unsigned long long ulong64;
- typedef signed long long long64;
- #endif /* CRYPT */
-
- typedef ulong64 mp_digit;
- typedef unsigned long mp_word __attribute__ ((mode(TI)));
-
- #define DIGIT_BIT 60
-#else /* MP_8BIT */
-/*
- this is the default case, 28-bit digits
- */
- #ifndef CRYPT
- #if defined(_MSC_VER) || defined(__BORLANDC__)
- typedef unsigned __int64 ulong64;
- typedef signed __int64 long64;
- #else
- typedef unsigned long long ulong64;
- typedef signed long long long64;
- #endif
- #endif /* CRYPT */
-
- typedef unsigned long mp_digit;
- typedef ulong64 mp_word;
-
- #ifdef MP_31BIT
-/*
- this is an extension that uses 31-bit digits
- */
- #define DIGIT_BIT 31
- #else /* MP_31BIT */
-/*
- default case is 28-bit digits, defines MP_28BIT as a handy macro to test
- */
- #define DIGIT_BIT 28
- #define MP_28BIT
- #endif /* MP_31BIT */
-#endif /* MP_8BIT */
-
-/*
- otherwise the bits per digit is calculated automatically from the size of
- a mp_digit
- */
-#ifndef DIGIT_BIT
- #define DIGIT_BIT ((int32)((CHAR_BIT * sizeof(mp_digit) - 1))) /* bits per digit */
-#endif /* DIGIT_BIT */
-
-#define MP_DIGIT_BIT DIGIT_BIT
-#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
-#define MP_DIGIT_MAX MP_MASK
-
-/******************************************************************************/
-/*
- equalities
- */
-#define MP_LT -1 /* less than */
-#define MP_EQ 0 /* equal to */
-#define MP_GT 1 /* greater than */
-
-#define MP_ZPOS 0 /* positive integer */
-#define MP_NEG 1 /* negative */
-
-#define MP_OKAY 0 /* ok result */
-#define MP_MEM -2 /* out of mem */
-#define MP_VAL -3 /* invalid input */
-#define MP_RANGE MP_VAL
-
-#define MP_YES 1 /* yes response */
-#define MP_NO 0 /* no response */
-
-typedef int32 mp_err;
-
-/******************************************************************************/
-/*
- various build options
- */
-#define MP_PREC 64 /* default digits of precision */
-
-/*
- define this to use lower memory usage routines (exptmods mostly)
- */
-#define MP_LOW_MEM
-
-/*
- size of comba arrays, should be at least
- 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2)
- */
-#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
-
-typedef struct {
- int32 used, alloc, sign;
- mp_digit *dp;
-} mp_int;
-
-#define USED(m) ((m)->used)
-#define DIGIT(m,k) ((m)->dp[(k)])
-#define SIGN(m) ((m)->sign)
-
-/******************************************************************************/
-/*
- init and deinit bignum functions
- */
-
-/*
- init a bignum
- */
-extern int32 mp_init(psPool_t *pool, mp_int *a);
-
-/*
- free a bignum
- */
-extern void mp_clear(mp_int *a);
-
-/*
- init a series of arguments
- */
-extern int32 _mp_init_multi(psPool_t *pool, mp_int *mp0, mp_int *mp1, mp_int *mp2,
- mp_int *mp3, mp_int *mp4, mp_int *mp5, mp_int *mp6,
- mp_int *mp7);
-
-/*
- clear a series of arguments
- */
-extern void _mp_clear_multi(mp_int *mp0, mp_int *mp1, mp_int *mp2, mp_int *mp3,
- mp_int *mp4, mp_int *mp5, mp_int *mp6, mp_int *mp7);
-
-/*
- exchange two ints
- */
-extern void mp_exch(mp_int *a, mp_int *b);
-
-/*
- shrink ram required for a bignum
- */
-extern int32 mp_shrink(mp_int *a);
-
-/*
- grow an int32 to a given size
- */
-extern int32 mp_grow(mp_int *a, int32 size);
-
-/*
- init to a given number of digits
- */
-extern int32 mp_init_size(psPool_t *pool, mp_int *a, int32 size);
-
-/******************************************************************************/
-/*
- Basic Manipulations
- */
-#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
-#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
-#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
-
-extern int32 mp_add_d (mp_int * a, mp_digit b, mp_int * c);
-extern int32 mp_sub_d (mp_int * a, mp_digit b, mp_int * c);
-/*
- set to zero
- */
-extern void mp_zero(mp_int *a);
-
-/*
- set to a digit
- */
-extern void mp_set(mp_int *a, mp_digit b);
-
-/*
- copy, b = a
- */
-extern int32 mp_copy(mp_int *a, mp_int *b);
-
-/*
- inits and copies, a = b
- */
-extern int32 mp_init_copy(psPool_t *pool, mp_int *a, mp_int *b);
-
-/*
- trim unused digits
- */
-extern void mp_clamp(mp_int *a);
-
-/******************************************************************************/
-/*
- digit manipulation
-*/
-
-/*
- right shift by "b" digits
- */
-extern void mp_rshd(mp_int *a, int32 b);
-
-/*
- left shift by "b" digits
- */
-extern int32 mp_lshd(mp_int *a, int32 b);
-
-/*
- c = a / 2**b
- */
-extern int32 mp_div_2d(psPool_t *pool, mp_int *a, int32 b, mp_int *c, mp_int *d);
-
-/*
- b = a/2
- */
-extern int32 mp_div_2(mp_int *a, mp_int *b);
-
-/*
- c = a * 2**b
- */
-extern int32 mp_mul_2d(mp_int *a, int32 b, mp_int *c);
-
-/*
- c = a mod 2**d
- */
-extern int32 mp_mod_2d(mp_int *a, int32 b, mp_int *c);
-
-/*
- computes a = 2**b
- */
-extern int32 mp_2expt(mp_int *a, int32 b);
-
-/******************************************************************************/
-/*
- Basic arithmetic
- */
-
-/*
- b = |a|
- */
-extern int32 mp_abs(mp_int *a, mp_int *b);
-
-/*
- compare a to b
- */
-extern int32 mp_cmp(mp_int *a, mp_int *b);
-
-/*
- compare |a| to |b|
- */
-extern int32 mp_cmp_mag(mp_int *a, mp_int *b);
-
-/*
- c = a + b
- */
-extern int32 mp_add(mp_int *a, mp_int *b, mp_int *c);
-
-/*
- c = a - b
- */
-extern int32 mp_sub(mp_int *a, mp_int *b, mp_int *c);
-
-/*
- c = a * b
- b = a*a
- */
-/* STEVE - moved mp_mul out of SLOW case */
-extern int32 mp_mul(psPool_t *pool, mp_int *a, mp_int *b, mp_int *c);
-#ifdef USE_SMALL_WORD
-extern int32 mp_sqr(psPool_t *pool, mp_int *a, mp_int *b);
-#endif
-
-/*
- a/b => cb + d == a
- */
-extern int32 mp_div(psPool_t *pool, mp_int *a, mp_int *b, mp_int *c, mp_int *d);
-
-/*
- c = a mod b, 0 <= c < b
- */
-extern int32 mp_mod(psPool_t *pool, mp_int *a, mp_int *b, mp_int *c);
-
-/******************************************************************************/
-/*
- single digit functions
- */
-
-/*
- compare against a single digit
- */
-extern int32 mp_cmp_d(mp_int *a, mp_digit b);
-
-/*
- c = a * b
- */
-extern int32 mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
-
-/******************************************************************************/
-/*
- number theory
- */
-
-/*
- d = a + b (mod c)
- */
-extern int32 mp_addmod(psPool_t *pool, mp_int *a, mp_int *b, mp_int *c, mp_int *d);
-
-/*
- d = a * b (mod c)
- */
-extern int32 mp_mulmod(psPool_t *pool, mp_int *a, mp_int *b, mp_int *c, mp_int *d);
-
-/*
- c = 1/a (mod b)
- */
-#ifdef USE_SMALL_WORD
-extern int32 mp_invmod(psPool_t *pool, mp_int *a, mp_int *b, mp_int *c);
-#endif
-
-/*
- setups the montgomery reduction
- */
-extern int32 mp_montgomery_setup(mp_int *a, mp_digit *mp);
-
-/*
- computes a = B**n mod b without division or multiplication useful for
- normalizing numbers in a Montgomery system.
- */
-extern int32 mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
-
-/*
- computes x/R == x (mod N) via Montgomery Reduction
- */
-#ifdef USE_SMALL_WORD
-extern int32 mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
-#endif
-
-/*
- d = a**b (mod c)
- */
-/* TODO - we never define this */
-extern int32 mp_exptmod(psPool_t *pool, mp_int *a, mp_int *b, mp_int *c, mp_int *d);
-
-/******************************************************************************/
-/*
- If we're using 1024 or 2048 bit keys and 28 bit digits, we only need the
- fast_ versions of these functions, removing the others to save space.
- Otherwise, we include the slow versions as well and which version to use
- is done at runtime.
-*/
-#ifdef USE_SMALL_WORD
-extern int32 s_mp_mul_digs(psPool_t *pool, mp_int *a, mp_int *b, mp_int *c,
- int32 digs);
-extern int32 s_mp_sqr(psPool_t *pool, mp_int *a, mp_int *b);
-#else
-#define mp_montgomery_reduce fast_mp_montgomery_reduce
-#define mp_sqr fast_s_mp_sqr
-#if STEVE
-#define mp_mul(P, A, B, C) fast_s_mp_mul_digs(P, A, B, C, (A)->used + (B)->used + 1)
-#endif
-#define s_mp_mul_digs fast_s_mp_mul_digs
-#define mp_invmod fast_mp_invmod
-#endif
-
-/******************************************************************************/
-/*
- radix conversion
- */
-extern int32 mp_count_bits(mp_int *a);
-
-extern int32 mp_unsigned_bin_size(mp_int *a);
-extern int32 mp_read_unsigned_bin(mp_int *a, unsigned char *b, int32 c);
-extern int32 mp_to_unsigned_bin(psPool_t *pool, mp_int *a, unsigned char *b);
-
-extern int32 mp_signed_bin_size(mp_int *a);
-
-/*
- lowlevel functions, do not call!
- */
-#if STEVE
-#ifdef USE_SMALL_WORD
-#define s_mp_mul(P, A, B, C) s_mp_mul_digs(P, A, B, C, (A)->used + (B)->used + 1)
-#else
-#define s_mp_mul(P, A, B, C) sslAssert();
-#endif
-#endif /* STEVE */
-/* define this in all cases for now STEVE */
-#define s_mp_mul(P, A, B, C) s_mp_mul_digs(P, A, B, C, (A)->used + (B)->used + 1)
-
-
-/*
- b = a*2
- */
-extern int32 mp_mul_2(mp_int *a, mp_int *b);
-
-extern int32 s_mp_add(mp_int *a, mp_int *b, mp_int *c);
-extern int32 s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
-
-extern int32 fast_s_mp_mul_digs(psPool_t *pool, mp_int *a, mp_int *b, mp_int *c,
- int32 digs);
-extern int32 fast_s_mp_sqr(psPool_t *pool, mp_int *a, mp_int *b);
-
-extern int32 fast_mp_invmod(psPool_t *pool, mp_int *a, mp_int *b, mp_int *c);
-extern int32 fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
-
-extern void bn_reverse(unsigned char *s, int32 len);
-
-
-#ifdef __cplusplus
- }
-#endif /* __cplusplus */
-
-#endif /* _h_MPI */
-
diff --git a/gpxe/src/crypto/matrixssl/pscrypto.h b/gpxe/src/crypto/matrixssl/pscrypto.h
deleted file mode 100644
index 4d684327..00000000
--- a/gpxe/src/crypto/matrixssl/pscrypto.h
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- * pscrypto.h
- * Release $Name$
- *
- * Internal definitions for PeerSec Networks MatrixSSL cryptography provider
- */
-/*
- * Copyright (c) PeerSec Networks, 2002-2006. All Rights Reserved.
- * The latest version of this code is available at http://www.matrixssl.org
- *
- * This software is open source; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This General Public License does NOT permit incorporating this software
- * into proprietary programs. If you are unable to comply with the GPL, a
- * commercial license for this software may be purchased from PeerSec Networks
- * at http://www.peersec.com
- *
- * This program is distributed in 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * http://www.gnu.org/copyleft/gpl.html
- */
-/******************************************************************************/
-
-#ifndef _h_PSCRYPTO
-#define _h_PSCRYPTO
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- PeerSec crypto-specific defines.
- */
-#define SMALL_CODE
-#define CLEAN_STACK
-/*
- If Native 64 bit integers are not supported, we must set the 16 bit flag
- to produce 32 bit mp_words in mpi.h
- We must also include the slow MPI functions because the fast ones only
- work with larger (28 bit) digit sizes.
-*/
-#ifndef USE_INT64
-#define MP_16BIT
-#define USE_SMALL_WORD
-#endif /* USE_INT64 */
-
-/******************************************************************************/
-
-#ifdef USE_RSA
-
-#include "mpi.h"
-
-#if LINUX
- #define _stat stat
-#endif
-
-/* this is the "32-bit at least" data type
- * Re-define it to suit your platform but it must be at least 32-bits
- */
-typedef unsigned long ulong32;
-
-/*
- Primary RSA Key struct. Define here for crypto
-*/
-typedef struct {
- mp_int e, d, N, qP, dP, dQ, p, q;
- int32 size; /* Size of the key in bytes */
- int32 optimized; /* 1 for optimized */
-} sslRsaKey_t;
-
-#endif /* USE_RSA */
-
-
-/*
- * Private
- */
-extern int32 ps_base64_decode(const unsigned char *in, uint32 len,
- unsigned char *out, uint32 *outlen);
-
-/*
- * Memory routines
- */
-extern void psZeromem(void *dst, size_t len);
-extern void psBurnStack(unsigned long len);
-
-
-/* max size of either a cipher/hash block or symmetric key [largest of the two] */
-#define MAXBLOCKSIZE 24
-
-/* ch1-01-1 */
-/* error codes [will be expanded in future releases] */
-enum {
- CRYPT_OK=0, /* Result OK */
- CRYPT_ERROR, /* Generic Error */
- CRYPT_NOP, /* Not a failure but no operation was performed */
-
- CRYPT_INVALID_KEYSIZE, /* Invalid key size given */
- CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */
- CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */
-
- CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */
- CRYPT_INVALID_PACKET, /* Invalid input packet given */
-
- CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
- CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */
-
- CRYPT_INVALID_CIPHER, /* Invalid cipher specified */
- CRYPT_INVALID_HASH, /* Invalid hash specified */
- CRYPT_INVALID_PRNG, /* Invalid PRNG specified */
-
- CRYPT_MEM, /* Out of memory */
-
- CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
- CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */
-
- CRYPT_INVALID_ARG, /* Generic invalid argument */
- CRYPT_FILE_NOTFOUND, /* File Not Found */
-
- CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */
- CRYPT_PK_INVALID_SYSTEM, /* Invalid PK system specified */
- CRYPT_PK_DUP, /* Duplicate key already in key ring */
- CRYPT_PK_NOT_FOUND, /* Key not found in keyring */
- CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */
-
- CRYPT_INVALID_PRIME_SIZE /* Invalid size of prime requested */
-};
-
-/******************************************************************************/
-/*
- hash defines
- */
-struct sha1_state {
-#ifdef USE_INT64
- ulong64 length;
-#else
- ulong32 lengthHi;
- ulong32 lengthLo;
-#endif /* USE_INT64 */
- ulong32 state[5], curlen;
- unsigned char buf[64];
-};
-
-struct md5_state {
-#ifdef USE_INT64
- ulong64 length;
-#else
- ulong32 lengthHi;
- ulong32 lengthLo;
-#endif /* USE_INT64 */
- ulong32 state[4], curlen;
- unsigned char buf[64];
-};
-
-#ifdef USE_MD2
-struct md2_state {
- unsigned char chksum[16], X[48], buf[16];
- unsigned long curlen;
-};
-#endif /* USE_MD2 */
-
-#ifdef USE_SHA256
-struct sha256_state {
- ulong64 length;
- ulong32 state[8], curlen;
- unsigned char buf[64];
-};
-#endif /* USE_SHA256 */
-
-typedef union {
- struct sha1_state sha1;
- struct md5_state md5;
-#ifdef USE_MD2
- struct md2_state md2;
-#endif /* USE_MD2 */
-#ifdef USE_SHA256
- struct sha256_state sha256;
-#endif
-} hash_state;
-
-typedef hash_state sslSha1Context_t;
-typedef hash_state sslMd5Context_t;
-#ifdef USE_MD2
-typedef hash_state sslMd2Context_t;
-#endif /* USE_MD2 */
-#ifdef USE_SHA256
-typedef hash_state sslSha256Context_t;
-#endif /* USE_SHA256 */
-
-typedef struct {
- unsigned char pad[64];
- union {
- sslMd5Context_t md5;
- sslSha1Context_t sha1;
- } u;
-} sslHmacContext_t;
-
-/******************************************************************************/
-/*
- RC4
- */
-#ifdef USE_ARC4
-typedef struct {
- unsigned char state[256];
- uint32 byteCount;
- unsigned char x;
- unsigned char y;
-} rc4_key;
-#endif /* USE_ARC4 */
-
-#define SSL_DES3_KEY_LEN 24
-#define SSL_DES3_IV_LEN 8
-#ifdef USE_3DES
-
-typedef struct {
- ulong32 ek[3][32], dk[3][32];
-} des3_key;
-
-/*
- A block cipher CBC structure
- */
-typedef struct {
- int32 blocklen;
- unsigned char IV[8];
- des3_key key;
- int32 explicitIV; /* 1 if yes */
-} des3_CBC;
-
-extern int32 des3_setup(const unsigned char *key, int32 keylen, int32 num_rounds,
- des3_CBC *skey);
-extern void des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
- des3_CBC *key);
-extern void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
- des3_CBC *key);
-extern int32 des3_keysize(int32 *desired_keysize);
-
-extern int32 des_setup(const unsigned char *key, int32 keylen, int32 num_rounds,
- des3_CBC *skey);
-extern void des_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
- des3_CBC *key);
-extern void des_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
- des3_CBC *key);
-
-#endif /* USE_3DES */
-
-
-typedef union {
-#ifdef USE_ARC4
- rc4_key arc4;
-#endif
-#ifdef USE_3DES
- des3_CBC des3;
-#endif
-} sslCipherContext_t;
-
-
-/*
- Controls endianess and size of registers. Leave uncommented to get
- platform neutral [slower] code detect x86-32 machines somewhat
- */
-#if (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__)))
- #define ENDIAN_LITTLE
- #define ENDIAN_32BITWORD
-#endif
-
-
-/* #define ENDIAN_LITTLE */
-/* #define ENDIAN_BIG */
-
-/* #define ENDIAN_32BITWORD */
-/* #define ENDIAN_64BITWORD */
-
-#if (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD))
- #error You must specify a word size as well as endianess
-#endif
-
-#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE))
- #define ENDIAN_NEUTRAL
-#endif
-
-/*
- helper macros
- */
-#if defined (ENDIAN_NEUTRAL)
-
-#define STORE32L(x, y) \
- { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
- (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
-
-#define LOAD32L(x, y) \
- { x = ((unsigned long)((y)[3] & 255)<<24) | \
- ((unsigned long)((y)[2] & 255)<<16) | \
- ((unsigned long)((y)[1] & 255)<<8) | \
- ((unsigned long)((y)[0] & 255)); }
-
-#define STORE64L(x, y) \
- { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
- (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
- (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
- (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
-
-#define LOAD64L(x, y) \
- { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
- (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
- (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
- (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
-
-#define STORE32H(x, y) \
- { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
- (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
-
-#define LOAD32H(x, y) \
- { x = ((unsigned long)((y)[0] & 255)<<24) | \
- ((unsigned long)((y)[1] & 255)<<16) | \
- ((unsigned long)((y)[2] & 255)<<8) | \
- ((unsigned long)((y)[3] & 255)); }
-
-#define STORE64H(x, y) \
- { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
- (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
- (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
- (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
-
-#define LOAD64H(x, y) \
- { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
- (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
- (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
- (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
-
-#endif /* ENDIAN_NEUTRAL */
-
-#ifdef ENDIAN_LITTLE
-
-#define STORE32H(x, y) \
- { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
- (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
-
-#define LOAD32H(x, y) \
- { x = ((unsigned long)((y)[0] & 255)<<24) | \
- ((unsigned long)((y)[1] & 255)<<16) | \
- ((unsigned long)((y)[2] & 255)<<8) | \
- ((unsigned long)((y)[3] & 255)); }
-
-#define STORE64H(x, y) \
- { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
- (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
- (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
- (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
-
-#define LOAD64H(x, y) \
- { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
- (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
- (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
- (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
-
-#ifdef ENDIAN_32BITWORD
-
-#define STORE32L(x, y) \
- { unsigned long __t = (x); memcpy(y, &__t, 4); }
-
-#define LOAD32L(x, y) \
- memcpy(&(x), y, 4);
-
-#define STORE64L(x, y) \
- { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
- (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
- (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
- (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
-
-#define LOAD64L(x, y) \
- { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
- (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
- (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
- (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
-
-#else /* 64-bit words then */
-
-#define STORE32L(x, y) \
- { unsigned long __t = (x); memcpy(y, &__t, 4); }
-
-#define LOAD32L(x, y) \
- { memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
-
-#define STORE64L(x, y) \
- { ulong64 __t = (x); memcpy(y, &__t, 8); }
-
-#define LOAD64L(x, y) \
- { memcpy(&(x), y, 8); }
-
-#endif /* ENDIAN_64BITWORD */
-#endif /* ENDIAN_LITTLE */
-
-#ifdef ENDIAN_BIG
-#define STORE32L(x, y) \
- { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
- (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
-
-#define LOAD32L(x, y) \
- { x = ((unsigned long)((y)[3] & 255)<<24) | \
- ((unsigned long)((y)[2] & 255)<<16) | \
- ((unsigned long)((y)[1] & 255)<<8) | \
- ((unsigned long)((y)[0] & 255)); }
-
-#define STORE64L(x, y) \
- { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
- (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
- (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
- (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
-
-#define LOAD64L(x, y) \
- { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \
- (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \
- (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \
- (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
-
-#ifdef ENDIAN_32BITWORD
-
-#define STORE32H(x, y) \
- { unsigned long __t = (x); memcpy(y, &__t, 4); }
-
-#define LOAD32H(x, y) \
- memcpy(&(x), y, 4);
-
-#define STORE64H(x, y) \
- { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
- (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
- (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
- (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
-
-#define LOAD64H(x, y) \
- { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \
- (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \
- (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \
- (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); }
-
-#else /* 64-bit words then */
-
-#define STORE32H(x, y) \
- { unsigned long __t = (x); memcpy(y, &__t, 4); }
-
-#define LOAD32H(x, y) \
- { memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
-
-#define STORE64H(x, y) \
- { ulong64 __t = (x); memcpy(y, &__t, 8); }
-
-#define LOAD64H(x, y) \
- { memcpy(&(x), y, 8); }
-
-#endif /* ENDIAN_64BITWORD */
-#endif /* ENDIAN_BIG */
-
-/*
- packet code */
-#if defined(USE_RSA) || defined(MDH) || defined(MECC)
- #define PACKET
-
-/*
- size of a packet header in bytes */
- #define PACKET_SIZE 4
-
-/*
- Section tags
- */
- #define PACKET_SECT_RSA 0
- #define PACKET_SECT_DH 1
- #define PACKET_SECT_ECC 2
- #define PACKET_SECT_DSA 3
-
-/*
- Subsection Tags for the first three sections
- */
- #define PACKET_SUB_KEY 0
- #define PACKET_SUB_ENCRYPTED 1
- #define PACKET_SUB_SIGNED 2
- #define PACKET_SUB_ENC_KEY 3
-#endif
-
-/*
- fix for MSVC ...evil!
- */
-#ifdef WIN32
-#ifdef _MSC_VER
- #define CONST64(n) n ## ui64
- typedef unsigned __int64 ulong64;
-#else
- #define CONST64(n) n ## ULL
- typedef unsigned long long ulong64;
-#endif
-#endif /* WIN32 */
-
-
-#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \
- ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) )
-
-#ifdef _MSC_VER
-
-/*
- instrinsic rotate
- */
-#include <stdlib.h>
-#pragma intrinsic(_lrotr,_lrotl)
-#define ROR(x,n) _lrotr(x,n)
-#define ROL(x,n) _lrotl(x,n)
-#define RORc(x,n) _lrotr(x,n)
-#define ROLc(x,n) _lrotl(x,n)
-
-/*
-#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(PS_NO_ASM)
-
-static inline unsigned ROL(unsigned word, int32 i)
-{
- asm ("roll %%cl,%0"
- :"0" (word),"c" (i));
- return word;
-}
-
-static inline unsigned ROR(unsigned word, int32 i)
-{
- asm ("rorl %%cl,%0"
- :"=r" (word)
- :"0" (word),"c" (i));
- return word;
-}
-*/
-/*
-#ifndef PS_NO_ROLC
-
-static inline unsigned ROLc(unsigned word, const int32 i)
-{
- asm ("roll %2,%0"
- :"=r" (word)
- :"0" (word),"I" (i));
- return word;
-}
-
-static inline unsigned RORc(unsigned word, const int32 i)
-{
- asm ("rorl %2,%0"
- :"=r" (word)
- :"0" (word),"I" (i));
- return word;
-}
-
-#else
-
-#define ROLc ROL
-#define RORc ROR
-
-#endif
-*/
-
-#else /* _MSC_VER */
-
-/*
- rotates the hard way
- */
-#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
-#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
-#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
-#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
-
-#endif /* _MSC_VER */
-
-/* 64-bit Rotates */
-#if 0
-
-#if defined(__GNUC__) && defined(__x86_64__) && !defined(PS_NO_ASM)
-
-static inline unsigned long ROL64(unsigned long word, int32 i)
-{
- asm("rolq %%cl,%0"
- :"=r" (word)
- :"0" (word),"c" (i));
- return word;
-}
-
-static inline unsigned long ROR64(unsigned long word, int32 i)
-{
- asm("rorq %%cl,%0"
- :"=r" (word)
- :"0" (word),"c" (i));
- return word;
-}
-
-#ifndef PS_NO_ROLC
-
-static inline unsigned long ROL64c(unsigned long word, const int32 i)
-{
- asm("rolq %2,%0"
- :"=r" (word)
- :"0" (word),"J" (i));
- return word;
-}
-
-static inline unsigned long ROR64c(unsigned long word, const int32 i)
-{
- asm("rorq %2,%0"
- :"=r" (word)
- :"0" (word),"J" (i));
- return word;
-}
-
-#else /* PS_NO_ROLC */
-
-#define ROL64c ROL
-#define ROR64c ROR
-
-#endif /* PS_NO_ROLC */
-#endif
-#endif /* commented out */
-
-#define ROL64(x, y) \
- ( (((x)<<((ulong64)(y)&63)) | \
- (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
-
-#define ROR64(x, y) \
- ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
- ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
-
-#define ROL64c(x, y) \
- ( (((x)<<((ulong64)(y)&63)) | \
- (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
-
-#define ROR64c(x, y) \
- ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
- ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
-
-#undef MAX
-#undef MIN
-#define MAX(x, y) ( ((x)>(y))?(x):(y) )
-#define MIN(x, y) ( ((x)<(y))?(x):(y) )
-
-/*
- extract a byte portably This MSC code causes runtime errors in VS.NET,
- always use the other
- */
-/*
-#ifdef _MSC_VER
- #define byte(x, n) ((unsigned char)((x) >> (8 * (n))))
-#else
-*/
- #define byte(x, n) (((x) >> (8 * (n))) & 255)
-/*
-#endif
-*/
-#ifdef __cplusplus
- }
-#endif /* __cplusplus */
-
-#endif /* _h_PSCRYPTO */
-
-/******************************************************************************/
-
diff --git a/gpxe/src/crypto/ssl.c b/gpxe/src/crypto/ssl.c
deleted file mode 100644
index 8abd7af8..00000000
--- a/gpxe/src/crypto/ssl.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#if 0
-
-#include "ssl.h"
-#include "ssl_constructs.h"
-#include <string.h> // for bcopy()
-#include <time.h> // for time()
-#include <stdlib.h> // for rand(), htons?, htonl?
-// note net byte order is big-endian
-// Need to set error codes
-
-int CreateSSLHello(SSL_t *ssl)
-{
- printf("In CreateSSLHello()\n",ssl);
-
- // Initalize the structure
- bzero(ssl,sizeof(SSL_t));
- //ssl->max_size = sizeof(ssl->buffer);
- ssl->max_size = 18456;
-
- // Declare variables
- int i; void *ptr;
-
- // Set pointers into buffer
- SSLPlaintext *record = (SSLPlaintext *)ssl->buffer;
- Handshake *handshake = (Handshake *)record->fragment;
- // the body starts right after the handshake
- printf("sizeof(Handshake) = %d\n",sizeof(Handshake));
- ClientHello *hello = (ClientHello *)(handshake + 1);
-
- printf("record->%#x, handshake->%#x, hello->%#x\n",record,handshake,hello);
-
- // Construct ClientHello Message
- hello->client_version = version;
- i = htonl(time(NULL));
- bcopy(&i,hello->random.gmt_unix_time,4);
- for(i=0;i<28;i++){ hello->random.random_bytes[i] = (uint8)rand(); }
- hello->session_id_length = 0;
- hello->session_id = &hello->session_id_length;
- hello->session_id_end = hello->session_id;
- hello->cipher_suites_length = (CipherSuiteLength *)(hello->session_id_end + 1);
- hello->cipher_suites = (hello->cipher_suites_length + 1);
- hello->cipher_suites_end = hello->cipher_suites;
- i = htons(2*5); // 2 bytes per Suite * 5 Suites
- bcopy(&i,hello->cipher_suites_length,2);
- bcopy(SSL_NULL_WITH_NULL_NULL,hello->cipher_suites_end,sizeof(CipherSuite));
- *hello->cipher_suites_end++;
- bcopy(SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,hello->cipher_suites_end,sizeof(CipherSuite));
- *hello->cipher_suites_end++;
- bcopy(SSL_DH_DSS_WITH_DES_CBC_SHA,hello->cipher_suites_end,sizeof(CipherSuite));
- *hello->cipher_suites_end++;
- bcopy(SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,hello->cipher_suites_end,sizeof(CipherSuite));
- *hello->cipher_suites_end++;
- bcopy(SSL_DH_anon_WITH_RC4_128_MD5,hello->cipher_suites_end,sizeof(CipherSuite));
- hello->compression_methods_length = (CompressionMethodLength *)(hello->cipher_suites_end + 1);
- hello->compression_methods = (hello->compression_methods_length + 1);
- hello->compression_methods_end = hello->compression_methods;
- *hello->compression_methods_length = 1;
- *hello->compression_methods_end = compression_method_null;
-
- // Construct Handshake Message
- handshake->msg_type = handshake_type_client_hello;
- i = (void *)(hello->compression_methods_end + 1) - (void *)hello;
- printf("Handshake.length = %d\n", i);
- handshake->length[0] = (char)*(&i+8);
- handshake->length[1] = (char)*(&i+8);
- handshake->length[2] = (char)i;
- //bcopy((&i+1),handshake->length,3); // +1 so we copy 3 bytes
-
- // Construct SSL Record
- printf("sizeof(ContentType)=%d\n",sizeof(ContentType));
- printf("sizeof(uint8)=%d\n",sizeof(uint8));
- record->type = content_type_handshake;
- record->version = version;
- i += sizeof(Handshake);
- printf("SSLPlaintext.length = %d\n",i);
- record->length[0] = (char)*(&i+8);
- record->length[1] = (char)i;
- //bcopy(&i,record->length,4); // length of handshake
-
- // Set total size of message
- i += sizeof(ContentType) + sizeof(ProtocolVersion) + sizeof(uint16);
- ssl->length = i;
- printf("End of CreateSSLHello\n");
- return 0;
-}
-
-void PrintSSLPacket(SSL_t *ssl)
-{
- printf("Printing packet with length:%d\n", ssl->length);
- char *ptr = ssl->buffer;
- char *begin = ptr;
- char *tmp;
- char *end = ssl->buffer + ssl->length;
- printf("Record Layer:\n");
- printf("\tContentType: %2hhX\n",(char)*ptr++);
- printf("\tVersion: %2hhX %2hhX\n", (char)*ptr++, (char)*ptr++);
- printf("\tLength: %2hhX %2hhX\n", (char)*ptr++, (char)*ptr++);
-
- printf("Handshake:\n");
- printf("\tType: %2hhX\n", (char)*ptr++);
- printf("\tLength: %2hhX %2hhX %2hhX\n", (char)*ptr++, (char)*ptr++, (char)*ptr++);
- printf("\tVersion: %2hhX %2hhX\n", (char)*ptr++, (char)*ptr++);
- printf("\tgmt_unix_time: %2hhX %2hhX %2hhX %2hhX\n", (char)*ptr++, (char)*ptr++, (char)*ptr++, (char)*ptr++);
- printf("\trandom: ");
- tmp = ptr + 28;
- for(;ptr<tmp;ptr++){printf("%2hhX ", (char)*ptr);}
-
- printf("\n\nHexDump:\n");
-
- int ctr = 0;
- for(;begin<end;begin++){printf("%2hhX ",(char)*begin);if(++ctr%10==0){printf("\n");}}
- printf("\n\n");
-}
-
-int ReadSSLHello(SSL_t *ssl)
-{
- SSLCiphertext *ct = (SSLCiphertext *)ssl->buffer;
-
- if(ct->type == content_type_alert){
- // assuming text is still plaintext
- Alert *a = (Alert *)&ct->fragment;
- if(a->level == alert_level_fatal){
- printf("Fatal Alert %d, connection terminated\n",a->description);
- return (1);
- }else if(a->level == alert_level_warning){
- printf("Warning Alert %d\n", a->description);
- }else{
- printf("Unknown alert level %d\n", a->level);
- }
- }else{
- printf("SSL type %d\n",ct->type);
- }
- return (0);
-}
-
-#endif
diff --git a/gpxe/src/crypto/ssl.h b/gpxe/src/crypto/ssl.h
deleted file mode 100644
index 06d43008..00000000
--- a/gpxe/src/crypto/ssl.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// At the moment I have hard coded one buffer. The size
-// is the max size of SSLCiphertext.length (so, actually it should
-// be increased to include the other information in the struct)
-// I might need to make a new, or split the current, buffer because
-// I have to have space to read in and write out, as well as keep
-// any data that has not been translated.
-// It works for now.
-typedef struct _ssl_t{
- char buffer[18456];
- int length;
- int max_size; // can't define const here
- // Current CipherSuite
- // Client random / Server random ???
- // pointers to different crypto functions
-} SSL_t;
-
-int CreateSSLHello(SSL_t *ssl);
-int ReadSSLHello(SSL_t *ssl);
-void PrintSSLPacket(SSL_t *ssl);
diff --git a/gpxe/src/crypto/ssl_constructs.h b/gpxe/src/crypto/ssl_constructs.h
deleted file mode 100644
index ab3aa703..00000000
--- a/gpxe/src/crypto/ssl_constructs.h
+++ /dev/null
@@ -1,342 +0,0 @@
-// Note: This file still needs some work.
-// Note: I had to redefine the enums to a set of const values,
-// so that the size of the variable would be correct.
-
-// Typedefs
-// (As defined by the SSL v3.0 RFC Draft)
-// URL: http://wp.netscape.com/eng/ssl3/draft302.txt
-typedef unsigned char uint8;
-typedef uint8 uint16[2];
-typedef uint8 uint24[3];
-typedef uint8 uint32[4];
-typedef uint8 uint64[8];
-
-// Record layers
-typedef struct _ProtocolVersion{
- uint8 major, minor;
-} ProtocolVersion;
-
-const ProtocolVersion version = { 3, 0 };
-
-typedef uint8 ContentType;
-const ContentType content_type_change_cipher_spec_type = 20;
-const ContentType content_type_alert = 21;
-const ContentType content_type_handshake = 22;
-const ContentType content_type_application_data = 23;
-
-typedef struct _SSLPlaintext{
- ContentType type;
- ProtocolVersion version;
- uint16 length; // can not exceed 2^14 bytes
- uint8 fragment[16384]; // 2^14 = 16,384 bytes
-} SSLPlaintext;
-
-typedef struct _SSLCompressed{
- ContentType type;
- ProtocolVersion version;
- uint16 length; // can not exceed 2^14 + 1024
- uint8 fragment[17408]; // SSLCompressed.length
-} SSLCompressed;
-
-typedef struct _SSLCiphertext{
- ContentType type;
- ProtocolVersion version;
- uint16 length;
- uint8 fragment; // so we have a pointer to the data, and don't have to do math
- // fragment; type GenericStreamCipher or GenericBlockCipher
-} SSLCiphertext; // recast to get fragment
-
-typedef struct _GenericStreamCipher{
- uint8 content[17408]; // SSLCompressed.length
- uint8 MAC[]; // CipherSpec.hash_size
-} GenericStreamCipher;
-
-typedef struct _SSLStreamCiphertext{
- ContentType type;
- ProtocolVersion version;
- uint16 length; // can not exceed 2^14 + 2048 = 18,456
- GenericStreamCipher fragment;
-} SSLStreamCiphertext;
-
-typedef struct _GenericBlockCipher{
- uint8 content[17408]; // SSLConpressed.length
- uint8 MAC[0]; // CipherSpec.hash_size
- // padding is used to bring the plaintext to
- // a multiple of the block cipher's block length.
- uint8 padding[0]; // GenericBlockCipher.padding_length
- uint8 padding_length;
-} GenericBlockCipher;
-
-typedef struct _SSLBlockCiphertext{
- ContentType type;
- ProtocolVersion version;
- uint16 length; // can not exceed 2^14 + 2048 = 18,456
- GenericBlockCipher fragment;
-} SSLBlockCiphertext;
-
-// Change cipher specs message
-typedef struct _ChangeCipherSpec{
- enum { type_change_cipher_spec=1, type_size=255 } type;
-} ChangeCipherSpec;
-
-// Alert messages
-typedef uint8 AlertLevel;
-const AlertLevel alert_level_warning = 1;
-const AlertLevel alert_level_fatal=2;
-
-typedef uint8 AlertDescription;
-const AlertDescription alert_description_close_notify = 0;
-const AlertDescription alert_description_unexpected_message = 10;
-const AlertDescription alert_description_bad_record_mac = 20;
-const AlertDescription alert_description_decompression_failure = 30;
-const AlertDescription alert_description_handshake_failure = 40;
-const AlertDescription alert_description_no_certificate = 41;
-const AlertDescription alert_description_bad_certificate = 42;
-const AlertDescription alert_description_unsupported_certificate = 43;
-const AlertDescription alert_description_certificate_revoked = 44;
-const AlertDescription alert_description_certificate_expired = 45;
-const AlertDescription alert_description_certificate_unknown = 46;
-const AlertDescription alert_description_illegal_parameter = 47;
-
-typedef struct _Alert{
- AlertLevel level;
- AlertDescription description;
-} Alert;
-
-// Handshake protocol
-// What is the best way to have a generic pointer to the body struct??
-typedef uint8 HandshakeType;
-const HandshakeType handshake_type_hello_request = 0;
-const HandshakeType handshake_type_client_hello = 1;
-const HandshakeType handshake_type_server_hello = 2;
-const HandshakeType handshake_type_certificate = 11;
-const HandshakeType handshake_type_server_key_exchange = 12;
-const HandshakeType handshake_type_certificate_request = 13;
-const HandshakeType handshake_type_server_done = 14;
-const HandshakeType handshake_type_certificate_verify = 15;
-const HandshakeType handshake_type_client_key_exchange = 16;
-const HandshakeType handshake_type_finished = 20;
-
-typedef struct _Handshake{
- HandshakeType msg_type;
- uint24 length;
- // body; // one of HandshakeType structs
-} Handshake; // generic Handshake, need to recast to get body
-
-// Hello messages
-typedef struct _HelloRequest{} HelloRequest;
-
-typedef struct _HelloRequestHandshake{
- HandshakeType msg_type;
- uint24 length;
- HelloRequest body;
-} HelloRequestHandshake;
-
-typedef struct _Random{
- uint32 gmt_unix_time;
- uint8 random_bytes[28];
-} Random;
-
-//typedef uint8 SessionID[32]; // <0..32>
-typedef uint8 SessionIDLength;
-typedef uint8 SessionID;
-
-typedef uint16 CipherSuiteLength;
-typedef uint8 CipherSuite[2];
-
-typedef uint8 CompressionMethodLength;
-typedef uint8 CompressionMethod;
-const CompressionMethod compression_method_null = 0;
-
-
-typedef struct _ClientHello{
- ProtocolVersion client_version;
- Random random;
- SessionIDLength session_id_length;
- SessionID *session_id;
- SessionID *session_id_end;
- CipherSuiteLength *cipher_suites_length;
- CipherSuite *cipher_suites; // min size is one entry
- CipherSuite *cipher_suites_end;
- //CipherSuite cipher_suites[32768]; // <2..2^16-1> = 65,536 bytes and CipherSuite is 2 bytes
- CompressionMethodLength *compression_methods_length;
- CompressionMethod *compression_methods;
- CompressionMethod *compression_methods_end;
- //CompressionMethod *compression_methods; // min size is zero
- //CompressionMethod compression_methods[256]; // <0..2^8-1> = 256 bytes and CompressionMethod is 1 byte
-} ClientHello;
-
-typedef struct _ClientHelloHandshake{
- //HandshakeType msg_type;
- uint8 msg_type;
- uint24 length;
- ClientHello body;
-} ClientHelloHandshake;
-
-typedef struct _ServerHello{
- ProtocolVersion server_version;
- Random random;
- SessionID session_id;
- CipherSuite cipher_suite;
- CompressionMethod compression_method;
-} ServerHello;
-
-typedef struct _ServerHelloHandshake{
- HandshakeType msg_type;
- uint24 length;
- ServerHello body;
-} ServerHelloHandshake;
-
-// Server authentication and key exchange messages
-typedef uint8 ASN1Cert[16777216]; // <1..2^24-1> = 16,777,216 bytes
-
-typedef struct _Certificate{
- ASN1Cert certificate_list[1]; // <1..2^24-1> / ANS1Cert = 1
- // for some reason the size of certificate_list and ASN1Cert is the same, so only one certificate in the list
-} Certificate;
-
-typedef uint8 KeyExchangeAlgorithm;
-const KeyExchangeAlgorithm key_exchange_algorithm_rsa = 0;
-const KeyExchangeAlgorithm key_exchange_algorithm_diffie_hellman = 1;
-const KeyExchangeAlgorithm key_exchange_algorithm_fortezza_kea = 2;
-
-typedef struct _AnonSignature{
- struct {};
-} AnonSignature;
-
-typedef struct _RSASignature{
- uint8 md5_hash[16];
- uint8 sha_hash[20];
-} RSASignature;
-
-typedef struct _DSASignature{
- uint8 sha_hash[20];
-} DSASignature;
-
-// use union??, make a mess to reference, but easy to make Signature type.
-typedef union _Signature{ AnonSignature anon; RSASignature rsa; DSASignature dsa; } Signature;
-
-typedef struct _ServerRSAParams{
- uint8 RSA_modulus[65536]; // <1..2^16-1> = 65,536
- uint8 RSA_exponent[65536]; // <1..2^16-1> = 65,536
-} ServerRSAParams;
-
-typedef struct _ServerDHParams{
- uint8 DH_p[65536]; // <1..2^16-1>
- uint8 DH_g[65536]; // <1..2^16-1>
- uint8 DH_Ys[65536]; // <1..2^16-1>
-} ServerDHParams;
-
-typedef struct _ServerDHKeyExchange{
- ServerDHParams params;
- Signature signed_params;
-} ServerDHKeyExchange;
-
-typedef struct _ServerRSAKeyExchange{
- ServerRSAParams params;
- Signature signed_params;
-} ServerRSAKeyExchange;
-
-typedef uint8 SignatureAlgorithm;
-const SignatureAlgorithm signature_algorithm_anonymous = 0;
-const SignatureAlgorithm signature_algorithm_rsa = 1;
-const SignatureAlgorithm signature_algorithm_dsa = 2;
-
-typedef uint8 CertificateType;
-const CertificateType certificate_type_RSA_sign = 1;
-const CertificateType certificate_type_DSS_sign = 2;
-const CertificateType certificate_type_RSA_fixed_DH = 3;
-const CertificateType certificate_type_DSS_fixed_DH = 4;
-const CertificateType certificate_type_RSA_ephemeral_DH = 5;
-const CertificateType certificate_type_DSS_ephemeral_DH = 6;
-const CertificateType certificate_type_FORTEZZA_MISSI = 20;
-
-typedef uint8 DistinguishedName[65536]; // <1..2^16-1> = 65,536
-
-typedef struct _CertificateRequest{
- CertificateType certificate_types[256]; // <1..2^8-1>
- DistinguishedName certificate_authorities[1]; // <3...2^16-1> / DistinguishedName
- // this is another one that is odd with a list size of 1
-} CertificateRequest;
-
-typedef struct _ServerHelloDone{} ServerHelloDone;
-
-// Client authentication and key exchange messages
-typedef struct _PreMasterSecret{
- ProtocolVersion client_version;
- uint8 random[46];
-} PreMasterSecret;
-
-typedef struct _EncryptedPreMasterSecret{
- PreMasterSecret pre_master_secret;
-} EncryptedPreMasterSecret;
-
-typedef struct _RSAClientKeyExchange{
- EncryptedPreMasterSecret exchange_keys;
-} RSAClientKeyExchange;
-
-typedef uint8 PublicValueEncoding;
-const PublicValueEncoding public_value_encoding_implicit = 0;
-const PublicValueEncoding public_value_encoding_explicit = 1;
-
-typedef struct _ClientDiffieHellmanPublic{
- // This is a select on PublicValueEncoding, and I chose the larger size
- uint8 dh_public[65536]; // DH_Yc<1..2^16-1>, the dh public value
-} ClientDiffieHellmanPublic;
-
-typedef struct _DHClientKeyExhange{
- ClientDiffieHellmanPublic exchange_keys;
-} DHClientKeyExchange;
-
-typedef struct _CertificateVerify{
- Signature signature;
-} CertificateVerify;
-
-// Handshake finalization message
-typedef struct _Finished{
- uint8 md5_hash[16];
- uint8 sha_hash[20];
-} Finished;
-
-// The CipherSuite
-CipherSuite SSL_NULL_WITH_NULL_NULL = { 0x00, 0x13 };
-CipherSuite SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x0B };
-CipherSuite SSL_DH_DSS_WITH_DES_CBC_SHA = { 0x00, 0x0C };
-CipherSuite SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x11 };
-CipherSuite SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = { 0x00, 0x17 };
-CipherSuite SSL_DH_anon_WITH_RC4_128_MD5 = { 0x00, 0x18 };
-
-// The CipherSpec
-typedef uint8 CipherType;
-const CipherType cipher_type_stream = 0;
-const CipherType cipher_type_block = 1;
-
-typedef uint8 IsExportable;
-const IsExportable is_exportable_true = 0;
-const IsExportable is_exportable_false = 1;
-
-typedef uint8 BulkCipherAlgorithm;
-const BulkCipherAlgorithm bulk_cipher_algorithm_null = 0;
-const BulkCipherAlgorithm bulk_cipher_algorithm_rc4 = 1;
-const BulkCipherAlgorithm bulk_cipher_algorithm_rc2 = 2;
-const BulkCipherAlgorithm bulk_cipher_algorithm_des = 3;
-const BulkCipherAlgorithm bulk_cipher_algorithm_3des = 4;
-const BulkCipherAlgorithm bulk_cipher_algorithm_des40 = 5;
-const BulkCipherAlgorithm bulk_cipher_algorithm_fortezza = 6;
-
-typedef uint8 MACAlgorithm;
-const MACAlgorithm mac_algorithm_null = 0;
-const MACAlgorithm mac_algorithm_md5 = 1;
-const MACAlgorithm mac_algorithm_sha = 2;
-
-typedef struct _CipherSpec{
- BulkCipherAlgorithm bulk_cipher_algorithm;
- MACAlgorithm mac_algorithm;
- CipherType cipher_type;
- IsExportable is_exportable;
- uint8 hash_size;
- uint8 key_material;
- uint8 IV_size;
-} CipherSpec;
-
-
diff --git a/gpxe/src/crypto/x509.c b/gpxe/src/crypto/x509.c
new file mode 100644
index 00000000..35adfa38
--- /dev/null
+++ b/gpxe/src/crypto/x509.c
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <gpxe/asn1.h>
+#include <gpxe/x509.h>
+
+/** @file
+ *
+ * X.509 certificates
+ *
+ * The structure of X.509v3 certificates is concisely documented in
+ * RFC5280 section 4.1. The structure of RSA public keys is
+ * documented in RFC2313.
+ */
+
+/** Object Identifier for "rsaEncryption" (1.2.840.113549.1.1.1) */
+static const uint8_t oid_rsa_encryption[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01 };
+
+/**
+ * Identify X.509 certificate public key
+ *
+ * @v certificate Certificate
+ * @v algorithm Public key algorithm to fill in
+ * @v pubkey Public key value to fill in
+ * @ret rc Return status code
+ */
+static int x509_public_key ( const struct asn1_cursor *certificate,
+ struct asn1_cursor *algorithm,
+ struct asn1_cursor *pubkey ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Locate subjectPublicKeyInfo */
+ memcpy ( &cursor, certificate, sizeof ( cursor ) );
+ rc = ( asn1_enter ( &cursor, ASN1_SEQUENCE ), /* Certificate */
+ asn1_enter ( &cursor, ASN1_SEQUENCE ), /* tbsCertificate */
+ asn1_skip ( &cursor, ASN1_EXPLICIT_TAG ), /* version */
+ asn1_skip ( &cursor, ASN1_INTEGER ), /* serialNumber */
+ asn1_skip ( &cursor, ASN1_SEQUENCE ), /* signature */
+ asn1_skip ( &cursor, ASN1_SEQUENCE ), /* issuer */
+ asn1_skip ( &cursor, ASN1_SEQUENCE ), /* validity */
+ asn1_skip ( &cursor, ASN1_SEQUENCE ), /* name */
+ asn1_enter ( &cursor, ASN1_SEQUENCE )/* subjectPublicKeyInfo*/);
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate subjectPublicKeyInfo in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return rc;
+ }
+
+ /* Locate algorithm */
+ memcpy ( algorithm, &cursor, sizeof ( *algorithm ) );
+ rc = ( asn1_enter ( algorithm, ASN1_SEQUENCE ) /* algorithm */ );
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate algorithm in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return rc;
+ }
+
+ /* Locate subjectPublicKey */
+ memcpy ( pubkey, &cursor, sizeof ( *pubkey ) );
+ rc = ( asn1_skip ( pubkey, ASN1_SEQUENCE ), /* algorithm */
+ asn1_enter ( pubkey, ASN1_BIT_STRING ) /* subjectPublicKey*/ );
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate subjectPublicKey in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Identify X.509 certificate RSA modulus and public exponent
+ *
+ * @v certificate Certificate
+ * @v rsa RSA public key to fill in
+ * @ret rc Return status code
+ *
+ * The caller is responsible for eventually calling
+ * x509_free_rsa_public_key() to free the storage allocated to hold
+ * the RSA modulus and exponent.
+ */
+int x509_rsa_public_key ( const struct asn1_cursor *certificate,
+ struct x509_rsa_public_key *rsa_pubkey ) {
+ struct asn1_cursor algorithm;
+ struct asn1_cursor pubkey;
+ struct asn1_cursor modulus;
+ struct asn1_cursor exponent;
+ int rc;
+
+ /* First, extract the public key algorithm and key data */
+ if ( ( rc = x509_public_key ( certificate, &algorithm,
+ &pubkey ) ) != 0 )
+ return rc;
+
+ /* Check that algorithm is RSA */
+ rc = ( asn1_enter ( &algorithm, ASN1_OID ) /* algorithm */ );
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate algorithm:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return rc;
+ }
+ if ( ( algorithm.len != sizeof ( oid_rsa_encryption ) ) ||
+ ( memcmp ( algorithm.data, &oid_rsa_encryption,
+ sizeof ( oid_rsa_encryption ) ) != 0 ) ) {
+ DBG ( "algorithm is not rsaEncryption in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return -ENOTSUP;
+ }
+
+ /* Check that public key is a byte string, i.e. that the
+ * "unused bits" byte contains zero.
+ */
+ if ( ( pubkey.len < 1 ) ||
+ ( ( *( uint8_t * ) pubkey.data ) != 0 ) ) {
+ DBG ( "subjectPublicKey is not a byte string in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return -ENOTSUP;
+ }
+ pubkey.data++;
+ pubkey.len--;
+
+ /* Pick out the modulus and exponent */
+ rc = ( asn1_enter ( &pubkey, ASN1_SEQUENCE ) /* RSAPublicKey */ );
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate RSAPublicKey in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return -ENOTSUP;
+ }
+ memcpy ( &modulus, &pubkey, sizeof ( modulus ) );
+ rc = ( asn1_enter ( &modulus, ASN1_INTEGER ) /* modulus */ );
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate modulus in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return -ENOTSUP;
+ }
+ memcpy ( &exponent, &pubkey, sizeof ( exponent ) );
+ rc = ( asn1_skip ( &exponent, ASN1_INTEGER ), /* modulus */
+ asn1_enter ( &exponent, ASN1_INTEGER ) /* publicExponent */ );
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate publicExponent in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return -ENOTSUP;
+ }
+
+ /* Allocate space and copy out modulus and exponent */
+ rsa_pubkey->modulus = malloc ( modulus.len + exponent.len );
+ if ( ! rsa_pubkey->modulus )
+ return -ENOMEM;
+ rsa_pubkey->exponent = ( rsa_pubkey->modulus + modulus.len );
+ memcpy ( rsa_pubkey->modulus, modulus.data, modulus.len );
+ rsa_pubkey->modulus_len = modulus.len;
+ memcpy ( rsa_pubkey->exponent, exponent.data, exponent.len );
+ rsa_pubkey->exponent_len = exponent.len;
+
+ DBG2 ( "RSA modulus:\n" );
+ DBG2_HDA ( 0, rsa_pubkey->modulus, rsa_pubkey->modulus_len );
+ DBG2 ( "RSA exponent:\n" );
+ DBG2_HDA ( 0, rsa_pubkey->exponent, rsa_pubkey->exponent_len );
+
+ return 0;
+}
diff --git a/gpxe/src/dl360.gpxe b/gpxe/src/dl360.gpxe
new file mode 100644
index 00000000..237555b7
--- /dev/null
+++ b/gpxe/src/dl360.gpxe
@@ -0,0 +1,4 @@
+#!gpxe
+kernel http://www.zytor.com/dl360/pxelinux.0
+set filename http://www.zytor.com/dl360/pxelinux.0
+boot
diff --git a/gpxe/src/drivers/bitbash/i2c_bit.c b/gpxe/src/drivers/bitbash/i2c_bit.c
index a3af610b..b85057af 100644
--- a/gpxe/src/drivers/bitbash/i2c_bit.c
+++ b/gpxe/src/drivers/bitbash/i2c_bit.c
@@ -19,6 +19,7 @@
#include <stddef.h>
#include <stdint.h>
#include <errno.h>
+#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <gpxe/bitbash.h>
@@ -49,6 +50,7 @@ static void i2c_delay ( void ) {
* @v state New state of SCL
*/
static void setscl ( struct bit_basher *basher, int state ) {
+ DBG2 ( "%c", ( state ? '/' : '\\' ) );
write_bit ( basher, I2C_BIT_SCL, state );
i2c_delay();
}
@@ -60,6 +62,7 @@ static void setscl ( struct bit_basher *basher, int state ) {
* @v state New state of SDA
*/
static void setsda ( struct bit_basher *basher, int state ) {
+ DBG2 ( "%c", ( state ? '1' : '0' ) );
write_bit ( basher, I2C_BIT_SDA, state );
i2c_delay();
}
@@ -71,7 +74,10 @@ static void setsda ( struct bit_basher *basher, int state ) {
* @ret state State of SDA
*/
static int getsda ( struct bit_basher *basher ) {
- return read_bit ( basher, I2C_BIT_SDA );
+ int state;
+ state = read_bit ( basher, I2C_BIT_SDA );
+ DBG2 ( "%c", ( state ? '+' : '-' ) );
+ return state;
}
/**
@@ -137,15 +143,20 @@ static void i2c_stop ( struct bit_basher *basher ) {
*/
static int i2c_send_byte ( struct bit_basher *basher, uint8_t byte ) {
int i;
-
+ int ack;
+
/* Send byte */
+ DBG2 ( "[send %02x]", byte );
for ( i = 8 ; i ; i-- ) {
i2c_send_bit ( basher, byte & 0x80 );
byte <<= 1;
}
/* Check for acknowledgement from slave */
- return ( i2c_recv_bit ( basher ) == 0 ? 0 : -EIO );
+ ack = ( i2c_recv_bit ( basher ) == 0 );
+ DBG2 ( "%s", ( ack ? "[acked]" : "[not acked]" ) );
+
+ return ( ack ? 0 : -EIO );
}
/**
@@ -157,19 +168,20 @@ static int i2c_send_byte ( struct bit_basher *basher, uint8_t byte ) {
* Receives a byte via the I2C bus and sends NACK to the slave device.
*/
static uint8_t i2c_recv_byte ( struct bit_basher *basher ) {
- uint8_t value = 0;
+ uint8_t byte = 0;
int i;
/* Receive byte */
for ( i = 8 ; i ; i-- ) {
- value <<= 1;
- value |= ( i2c_recv_bit ( basher ) & 0x1 );
+ byte <<= 1;
+ byte |= ( i2c_recv_bit ( basher ) & 0x1 );
}
/* Send NACK */
i2c_send_bit ( basher, 1 );
- return value;
+ DBG2 ( "[rcvd %02x]", byte );
+ return byte;
}
/**
@@ -177,30 +189,29 @@ static uint8_t i2c_recv_byte ( struct bit_basher *basher ) {
*
* @v basher Bit-bashing interface
* @v i2cdev I2C device
+ * @v offset Starting offset within the device
* @v direction I2C_READ or I2C_WRITE
* @ret rc Return status code
*/
static int i2c_select ( struct bit_basher *basher, struct i2c_device *i2cdev,
- unsigned int direction ) {
+ unsigned int offset, unsigned int direction ) {
unsigned int address;
+ int shift;
+ unsigned int byte;
int rc;
i2c_start ( basher );
- /* First byte of the address */
- address = i2cdev->address;
- if ( i2cdev->tenbit ) {
- address |= I2C_TENBIT_ADDRESS;
- address >>= 8;
- }
- if ( ( rc = i2c_send_byte ( basher,
- ( ( address << 1 ) | direction ) ) ) != 0 )
- return rc;
+ /* Calculate address to appear on bus */
+ address = ( ( ( i2cdev->dev_addr |
+ ( offset >> ( 8 * i2cdev->word_addr_len ) ) ) << 1 )
+ | direction );
- /* Second byte of the address (10-bit addresses only) */
- if ( i2cdev->tenbit ) {
- if ( ( rc = i2c_send_byte ( basher,
- ( i2cdev->address & 0xff ) ) ) !=0)
+ /* Send address a byte at a time */
+ for ( shift = ( 8 * ( i2cdev->dev_addr_len - 1 ) ) ;
+ shift >= 0 ; shift -= 8 ) {
+ byte = ( ( address >> shift ) & 0xff );
+ if ( ( rc = i2c_send_byte ( basher, byte ) ) != 0 )
return rc;
}
@@ -208,6 +219,46 @@ static int i2c_select ( struct bit_basher *basher, struct i2c_device *i2cdev,
}
/**
+ * Reset I2C bus
+ *
+ * @v basher Bit-bashing interface
+ * @ret rc Return status code
+ *
+ * i2c devices often don't have a reset line, so even a reboot or
+ * system power cycle is sometimes not enough to bring them back to a
+ * known state.
+ */
+static int i2c_reset ( struct bit_basher *basher ) {
+ unsigned int i;
+ int sda;
+
+ /* Clock through several cycles, waiting for an opportunity to
+ * pull SDA low while SCL is high (which creates a start
+ * condition).
+ */
+ setscl ( basher, 0 );
+ setsda ( basher, 1 );
+ for ( i = 0 ; i < I2C_RESET_MAX_CYCLES ; i++ ) {
+ setscl ( basher, 1 );
+ sda = getsda ( basher );
+ if ( sda ) {
+ /* Now that the device will see a start, issue it */
+ i2c_start ( basher );
+ /* Stop the bus to leave it in a known good state */
+ i2c_stop ( basher );
+ DBGC ( basher, "I2CBIT %p reset after %d attempts\n",
+ basher, ( i + 1 ) );
+ return 0;
+ }
+ setscl ( basher, 0 );
+ }
+
+ DBGC ( basher, "I2CBIT %p could not reset after %d attempts\n",
+ basher, i );
+ return -ETIMEDOUT;
+}
+
+/**
* Read data from I2C device via bit-bashing interface
*
* @v i2c I2C interface
@@ -228,12 +279,14 @@ static int i2c_bit_read ( struct i2c_interface *i2c,
struct bit_basher *basher = &i2cbit->basher;
int rc = 0;
- DBG ( "Reading from I2C device %x: ", i2cdev->address );
+ DBGC ( basher, "I2CBIT %p reading from device %x: ",
+ basher, i2cdev->dev_addr );
- while ( 1 ) {
+ for ( ; ; data++, offset++ ) {
/* Select device for writing */
- if ( ( rc = i2c_select ( basher, i2cdev, I2C_WRITE ) ) != 0 )
+ if ( ( rc = i2c_select ( basher, i2cdev, offset,
+ I2C_WRITE ) ) != 0 )
break;
/* Abort at end of data */
@@ -241,19 +294,20 @@ static int i2c_bit_read ( struct i2c_interface *i2c,
break;
/* Select offset */
- if ( ( rc = i2c_send_byte ( basher, offset++ ) ) != 0 )
+ if ( ( rc = i2c_send_byte ( basher, offset ) ) != 0 )
break;
/* Select device for reading */
- if ( ( rc = i2c_select ( basher, i2cdev, I2C_READ ) ) != 0 )
+ if ( ( rc = i2c_select ( basher, i2cdev, offset,
+ I2C_READ ) ) != 0 )
break;
/* Read byte */
- *data++ = i2c_recv_byte ( basher );
- DBG ( "%02x ", *(data - 1) );
+ *data = i2c_recv_byte ( basher );
+ DBGC ( basher, "%02x ", *data );
}
- DBG ( "%s\n", ( rc ? "failed" : "" ) );
+ DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) );
i2c_stop ( basher );
return rc;
}
@@ -279,12 +333,14 @@ static int i2c_bit_write ( struct i2c_interface *i2c,
struct bit_basher *basher = &i2cbit->basher;
int rc = 0;
- DBG ( "Writing to I2C device %x: ", i2cdev->address );
+ DBGC ( basher, "I2CBIT %p writing to device %x: ",
+ basher, i2cdev->dev_addr );
- while ( 1 ) {
+ for ( ; ; data++, offset++ ) {
/* Select device for writing */
- if ( ( rc = i2c_select ( basher, i2cdev, I2C_WRITE ) ) != 0 )
+ if ( ( rc = i2c_select ( basher, i2cdev, offset,
+ I2C_WRITE ) ) != 0 )
break;
/* Abort at end of data */
@@ -292,16 +348,16 @@ static int i2c_bit_write ( struct i2c_interface *i2c,
break;
/* Select offset */
- if ( ( rc = i2c_send_byte ( basher, offset++ ) ) != 0 )
+ if ( ( rc = i2c_send_byte ( basher, offset ) ) != 0 )
break;
/* Write data to device */
- DBG ( "%02x ", *data );
- if ( ( rc = i2c_send_byte ( basher, *data++ ) ) != 0 )
+ DBGC ( basher, "%02x ", *data );
+ if ( ( rc = i2c_send_byte ( basher, *data ) ) != 0 )
break;
}
- DBG ( "%s\n", ( rc ? "failed" : "" ) );
+ DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) );
i2c_stop ( basher );
return rc;
}
@@ -310,13 +366,26 @@ static int i2c_bit_write ( struct i2c_interface *i2c,
* Initialise I2C bit-bashing interface
*
* @v i2cbit I2C bit-bashing interface
+ * @v bash_op Bit-basher operations
*/
-void init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit ) {
+int init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit,
+ struct bit_basher_operations *bash_op ) {
struct bit_basher *basher = &i2cbit->basher;
-
+ int rc;
+
+ /* Initialise data structures */
+ basher->op = bash_op;
assert ( basher->op->read != NULL );
assert ( basher->op->write != NULL );
i2cbit->i2c.read = i2c_bit_read;
i2cbit->i2c.write = i2c_bit_write;
- i2c_stop ( basher );
+
+ /* Reset I2C bus */
+ if ( ( rc = i2c_reset ( basher ) ) != 0 ) {
+ DBGC ( basher, "I2CBIT %p could not reset I2C bus: %s\n",
+ basher, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
}
diff --git a/gpxe/src/drivers/block/ata.c b/gpxe/src/drivers/block/ata.c
index 555a5f6e..c21d2f65 100644
--- a/gpxe/src/drivers/block/ata.c
+++ b/gpxe/src/drivers/block/ata.c
@@ -139,6 +139,11 @@ static int ata_identify ( struct block_device *blockdev ) {
return 0;
}
+static struct block_device_operations ata_operations = {
+ .read = ata_read,
+ .write = ata_write
+};
+
/**
* Initialise ATA device
*
@@ -153,7 +158,6 @@ static int ata_identify ( struct block_device *blockdev ) {
*/
int init_atadev ( struct ata_device *ata ) {
/** Fill in read and write methods, and get device capacity */
- ata->blockdev.read = ata_read;
- ata->blockdev.write = ata_write;
+ ata->blockdev.op = &ata_operations;
return ata_identify ( &ata->blockdev );
}
diff --git a/gpxe/src/drivers/block/ramdisk.c b/gpxe/src/drivers/block/ramdisk.c
index b5324bf1..50911994 100644
--- a/gpxe/src/drivers/block/ramdisk.c
+++ b/gpxe/src/drivers/block/ramdisk.c
@@ -75,6 +75,11 @@ static int ramdisk_write ( struct block_device *blockdev, uint64_t block,
return 0;
}
+static struct block_device_operations ramdisk_operations = {
+ .read = ramdisk_read,
+ .write = ramdisk_write
+};
+
int init_ramdisk ( struct ramdisk *ramdisk, userptr_t data, size_t len,
unsigned int blksize ) {
@@ -82,8 +87,7 @@ int init_ramdisk ( struct ramdisk *ramdisk, userptr_t data, size_t len,
blksize = 512;
ramdisk->data = data;
- ramdisk->blockdev.read = ramdisk_read;
- ramdisk->blockdev.write = ramdisk_write;
+ ramdisk->blockdev.op = &ramdisk_operations;
ramdisk->blockdev.blksize = blksize;
ramdisk->blockdev.blocks = ( len / blksize );
diff --git a/gpxe/src/drivers/block/scsi.c b/gpxe/src/drivers/block/scsi.c
index 9651583a..71d22040 100644
--- a/gpxe/src/drivers/block/scsi.c
+++ b/gpxe/src/drivers/block/scsi.c
@@ -29,6 +29,13 @@
*
*/
+/** Maximum number of dummy "read capacity (10)" operations
+ *
+ * These are issued at connection setup to draw out various useless
+ * power-on messages.
+ */
+#define SCSI_MAX_DUMMY_READ_CAP 10
+
static inline __attribute__ (( always_inline )) struct scsi_device *
block_to_scsi ( struct block_device *blockdev ) {
return container_of ( blockdev, struct scsi_device, blockdev );
@@ -228,6 +235,16 @@ static int scsi_read_capacity_16 ( struct block_device *blockdev ) {
return 0;
}
+static struct block_device_operations scsi_operations_16 = {
+ .read = scsi_read_16,
+ .write = scsi_write_16,
+};
+
+static struct block_device_operations scsi_operations_10 = {
+ .read = scsi_read_10,
+ .write = scsi_write_10,
+};
+
/**
* Initialise SCSI device
*
@@ -240,18 +257,24 @@ static int scsi_read_capacity_16 ( struct block_device *blockdev ) {
* CAPACITY call to determine the block size and total device size.
*/
int init_scsidev ( struct scsi_device *scsi ) {
+ unsigned int i;
int rc;
- /* Issue a theoretically extraneous READ CAPACITY (10)
- * command, solely in order to draw out the "CHECK CONDITION
- * (power-on occurred)" that some dumb targets insist on
- * sending as an error at start of day.
+ /* Issue some theoretically extraneous READ CAPACITY (10)
+ * commands, solely in order to draw out the "CHECK CONDITION
+ * (power-on occurred)", "CHECK CONDITION (reported LUNs data
+ * has changed)" etc. that some dumb targets insist on sending
+ * as an error at start of day. The precise command that we
+ * use is unimportant; we just need to provide the target with
+ * an opportunity to send its responses.
*/
- scsi_read_capacity_10 ( &scsi->blockdev );
+ for ( i = 0 ; i < SCSI_MAX_DUMMY_READ_CAP ; i++ ) {
+ if ( ( rc = scsi_read_capacity_10 ( &scsi->blockdev ) ) == 0 )
+ break;
+ }
/* Try READ CAPACITY (10), which is a mandatory command, first. */
- scsi->blockdev.read = scsi_read_10;
- scsi->blockdev.write = scsi_write_10;
+ scsi->blockdev.op = &scsi_operations_10;
if ( ( rc = scsi_read_capacity_10 ( &scsi->blockdev ) ) != 0 )
return rc;
@@ -261,8 +284,7 @@ int init_scsidev ( struct scsi_device *scsi ) {
* mandatory, so we can't just use it straight off.
*/
if ( scsi->blockdev.blocks == 0 ) {
- scsi->blockdev.read = scsi_read_16;
- scsi->blockdev.write = scsi_write_16;
+ scsi->blockdev.op = &scsi_operations_16;
if ( ( rc = scsi_read_capacity_16 ( &scsi->blockdev ) ) != 0 )
return rc;
}
diff --git a/gpxe/src/drivers/bus/eisa.c b/gpxe/src/drivers/bus/eisa.c
index ee03df3a..d9e42359 100644
--- a/gpxe/src/drivers/bus/eisa.c
+++ b/gpxe/src/drivers/bus/eisa.c
@@ -3,7 +3,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
-#include <io.h>
+#include <gpxe/io.h>
#include <unistd.h>
#include <gpxe/eisa.h>
diff --git a/gpxe/src/drivers/bus/isa.c b/gpxe/src/drivers/bus/isa.c
index a4105fd0..fa5def54 100644
--- a/gpxe/src/drivers/bus/isa.c
+++ b/gpxe/src/drivers/bus/isa.c
@@ -3,7 +3,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
-#include <io.h>
+#include <gpxe/io.h>
#include <gpxe/isa.h>
/*
@@ -49,9 +49,9 @@ static isa_probe_addr_t isa_extra_probe_addrs[] = {
(driver)->probe_addrs[(ioidx)] )
static struct isa_driver isa_drivers[0]
- __table_start ( struct isa_driver, isa_driver );
+ __table_start ( struct isa_driver, isa_drivers );
static struct isa_driver isa_drivers_end[0]
- __table_end ( struct isa_driver, isa_driver );
+ __table_end ( struct isa_driver, isa_drivers );
static void isabus_remove ( struct root_device *rootdev );
diff --git a/gpxe/src/drivers/bus/isapnp.c b/gpxe/src/drivers/bus/isapnp.c
index f4968eb1..8f812df8 100644
--- a/gpxe/src/drivers/bus/isapnp.c
+++ b/gpxe/src/drivers/bus/isapnp.c
@@ -60,7 +60,7 @@
#include <string.h>
#include <stdio.h>
#include <errno.h>
-#include <io.h>
+#include <gpxe/io.h>
#include <unistd.h>
#include <gpxe/isapnp.h>
@@ -84,7 +84,7 @@ static void isapnpbus_remove ( struct root_device *rootdev );
*
*/
-#define ISAPNP_CARD_ID_FMT "ID %04x:%04x (\"%s\") serial %lx"
+#define ISAPNP_CARD_ID_FMT "ID %04x:%04x (\"%s\") serial %x"
#define ISAPNP_CARD_ID_DATA(identifier) \
(identifier)->vendor_id, (identifier)->prod_id, \
isa_id_string ( (identifier)->vendor_id, (identifier)->prod_id ), \
diff --git a/gpxe/src/drivers/bus/mca.c b/gpxe/src/drivers/bus/mca.c
index eb7b7e39..e9233813 100644
--- a/gpxe/src/drivers/bus/mca.c
+++ b/gpxe/src/drivers/bus/mca.c
@@ -10,7 +10,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
-#include <io.h>
+#include <gpxe/io.h>
#include <gpxe/mca.h>
static struct mca_driver mca_drivers[0]
diff --git a/gpxe/src/drivers/bus/pci.c b/gpxe/src/drivers/bus/pci.c
index 967441ac..2dc9d43a 100644
--- a/gpxe/src/drivers/bus/pci.c
+++ b/gpxe/src/drivers/bus/pci.c
@@ -67,7 +67,7 @@ static unsigned long pci_bar ( struct pci_device *pci, unsigned int reg ) {
if ( sizeof ( unsigned long ) > sizeof ( uint32_t ) ) {
return ( ( ( uint64_t ) high << 32 ) | low );
} else {
- DBG ( "Unhandled 64-bit BAR %08lx%08lx\n",
+ DBG ( "Unhandled 64-bit BAR %08x%08x\n",
high, low );
return PCI_BASE_ADDRESS_MEM_TYPE_64;
}
@@ -148,7 +148,8 @@ void adjust_pci_device ( struct pci_device *pci ) {
unsigned char pci_latency;
pci_read_config_word ( pci, PCI_COMMAND, &pci_command );
- new_command = pci_command | PCI_COMMAND_MASTER | PCI_COMMAND_IO;
+ new_command = ( pci_command | PCI_COMMAND_MASTER |
+ PCI_COMMAND_MEM | PCI_COMMAND_IO );
if ( pci_command != new_command ) {
DBG ( "PCI BIOS has not enabled device %02x:%02x.%x! "
"Updating PCI command %04x->%04x\n", pci->bus,
diff --git a/gpxe/src/drivers/bus/virtio-pci.c b/gpxe/src/drivers/bus/virtio-pci.c
new file mode 100644
index 00000000..34acce2d
--- /dev/null
+++ b/gpxe/src/drivers/bus/virtio-pci.c
@@ -0,0 +1,64 @@
+/* virtio-pci.c - pci interface for virtio interface
+ *
+ * (c) Copyright 2008 Bull S.A.S.
+ *
+ * Author: Laurent Vivier <Laurent.Vivier@bull.net>
+ *
+ * some parts from Linux Virtio PCI driver
+ *
+ * Copyright IBM Corp. 2007
+ * Authors: Anthony Liguori <aliguori@us.ibm.com>
+ *
+ */
+
+#include "etherboot.h"
+#include "gpxe/io.h"
+#include "gpxe/virtio-ring.h"
+#include "gpxe/virtio-pci.h"
+
+int vp_find_vq(unsigned int ioaddr, int queue_index,
+ struct vring_virtqueue *vq)
+{
+ struct vring * vr = &vq->vring;
+ u16 num;
+
+ /* select the queue */
+
+ outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
+
+ /* check if the queue is available */
+
+ num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM);
+ if (!num) {
+ printf("ERROR: queue size is 0\n");
+ return -1;
+ }
+
+ if (num > MAX_QUEUE_NUM) {
+ printf("ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM);
+ return -1;
+ }
+
+ /* check if the queue is already active */
+
+ if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
+ printf("ERROR: queue already active\n");
+ return -1;
+ }
+
+ vq->queue_index = queue_index;
+
+ /* initialize the queue */
+
+ vring_init(vr, num, (unsigned char*)&vq->queue);
+
+ /* activate the queue
+ *
+ * NOTE: vr->desc is initialized by vring_init()
+ */
+
+ outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT,
+ ioaddr + VIRTIO_PCI_QUEUE_PFN);
+
+ return num;
+}
diff --git a/gpxe/src/drivers/bus/virtio-ring.c b/gpxe/src/drivers/bus/virtio-ring.c
new file mode 100644
index 00000000..6415f626
--- /dev/null
+++ b/gpxe/src/drivers/bus/virtio-ring.c
@@ -0,0 +1,134 @@
+/* virtio-pci.c - virtio ring management
+ *
+ * (c) Copyright 2008 Bull S.A.S.
+ *
+ * Author: Laurent Vivier <Laurent.Vivier@bull.net>
+ *
+ * some parts from Linux Virtio Ring
+ *
+ * Copyright Rusty Russell IBM Corporation 2007
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ *
+ */
+
+#include "etherboot.h"
+#include "gpxe/io.h"
+#include "gpxe/virtio-ring.h"
+#include "gpxe/virtio-pci.h"
+
+#define BUG() do { \
+ printf("BUG: failure at %s:%d/%s()!\n", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ while(1); \
+} while (0)
+#define BUG_ON(condition) do { if (condition) BUG(); } while (0)
+
+/*
+ * vring_free
+ *
+ * put at the begin of the free list the current desc[head]
+ */
+
+void vring_detach(struct vring_virtqueue *vq, unsigned int head)
+{
+ struct vring *vr = &vq->vring;
+ unsigned int i;
+
+ /* find end of given descriptor */
+
+ i = head;
+ while (vr->desc[i].flags & VRING_DESC_F_NEXT)
+ i = vr->desc[i].next;
+
+ /* link it with free list and point to it */
+
+ vr->desc[i].next = vq->free_head;
+ wmb();
+ vq->free_head = head;
+}
+
+/*
+ * vring_get_buf
+ *
+ * get a buffer from the used list
+ *
+ */
+
+int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
+{
+ struct vring *vr = &vq->vring;
+ struct vring_used_elem *elem;
+ u32 id;
+ int ret;
+
+ BUG_ON(!vring_more_used(vq));
+
+ elem = &vr->used->ring[vq->last_used_idx % vr->num];
+ wmb();
+ id = elem->id;
+ if (len != NULL)
+ *len = elem->len;
+
+ ret = vq->vdata[id];
+
+ vring_detach(vq, id);
+
+ vq->last_used_idx++;
+
+ return ret;
+}
+
+void vring_add_buf(struct vring_virtqueue *vq,
+ struct vring_list list[],
+ unsigned int out, unsigned int in,
+ int index, int num_added)
+{
+ struct vring *vr = &vq->vring;
+ int i, avail, head, prev;
+
+ BUG_ON(out + in == 0);
+
+ prev = 0;
+ head = vq->free_head;
+ for (i = head; out; i = vr->desc[i].next, out--) {
+
+ vr->desc[i].flags = VRING_DESC_F_NEXT;
+ vr->desc[i].addr = (u64)virt_to_phys(list->addr);
+ vr->desc[i].len = list->length;
+ prev = i;
+ list++;
+ }
+ for ( ; in; i = vr->desc[i].next, in--) {
+
+ vr->desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
+ vr->desc[i].addr = (u64)virt_to_phys(list->addr);
+ vr->desc[i].len = list->length;
+ prev = i;
+ list++;
+ }
+ vr->desc[prev].flags &= ~VRING_DESC_F_NEXT;
+
+ vq->free_head = i;
+
+ vq->vdata[head] = index;
+
+ avail = (vr->avail->idx + num_added) % vr->num;
+ vr->avail->ring[avail] = head;
+ wmb();
+}
+
+void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
+{
+ struct vring *vr = &vq->vring;
+
+ wmb();
+ vr->avail->idx += num_added;
+
+ mb();
+ if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY))
+ vp_notify(ioaddr, vq->queue_index);
+}
+
diff --git a/gpxe/src/drivers/infiniband/arbel.c b/gpxe/src/drivers/infiniband/arbel.c
index 1b55131b..1756a6e2 100644
--- a/gpxe/src/drivers/infiniband/arbel.c
+++ b/gpxe/src/drivers/infiniband/arbel.c
@@ -27,12 +27,14 @@
#include <unistd.h>
#include <errno.h>
#include <byteswap.h>
+#include <gpxe/io.h>
#include <gpxe/pci.h>
#include <gpxe/malloc.h>
#include <gpxe/umalloc.h>
#include <gpxe/iobuf.h>
#include <gpxe/netdevice.h>
#include <gpxe/infiniband.h>
+#include <gpxe/ib_smc.h>
#include "arbel.h"
/**
@@ -484,6 +486,50 @@ arbel_cmd_map_fa ( struct arbel *arbel,
/***************************************************************************
*
+ * MAD operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Issue management datagram
+ *
+ * @v ibdev Infiniband device
+ * @v mad Management datagram
+ * @ret rc Return status code
+ */
+static int arbel_mad ( struct ib_device *ibdev, union ib_mad *mad ) {
+ struct arbel *arbel = ib_get_drvdata ( ibdev );
+ union arbelprm_mad mad_ifc;
+ int rc;
+
+ linker_assert ( sizeof ( *mad ) == sizeof ( mad_ifc.mad ),
+ mad_size_mismatch );
+
+ /* Copy in request packet */
+ memcpy ( &mad_ifc.mad, mad, sizeof ( mad_ifc.mad ) );
+
+ /* Issue MAD */
+ if ( ( rc = arbel_cmd_mad_ifc ( arbel, ibdev->port,
+ &mad_ifc ) ) != 0 ) {
+ DBGC ( arbel, "Arbel %p could not issue MAD IFC: %s\n",
+ arbel, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Copy out reply packet */
+ memcpy ( mad, &mad_ifc.mad, sizeof ( *mad ) );
+
+ if ( mad->hdr.status != 0 ) {
+ DBGC ( arbel, "Arbel %p MAD IFC status %04x\n",
+ arbel, ntohs ( mad->hdr.status ) );
+ return -EIO;
+ }
+ return 0;
+}
+
+/***************************************************************************
+ *
* Completion queue operations
*
***************************************************************************
@@ -947,7 +993,7 @@ static void arbel_ring_doorbell ( struct arbel *arbel,
union arbelprm_doorbell_register *db_reg,
unsigned int offset ) {
- DBGC2 ( arbel, "Arbel %p ringing doorbell %08lx:%08lx at %lx\n",
+ DBGC2 ( arbel, "Arbel %p ringing doorbell %08x:%08x at %lx\n",
arbel, db_reg->dword[0], db_reg->dword[1],
virt_to_phys ( arbel->uar + offset ) );
@@ -1006,7 +1052,7 @@ static int arbel_post_send ( struct ib_device *ibdev,
ud_address_vector.pd, ARBEL_GLOBAL_PD,
ud_address_vector.port_number, ibdev->port );
MLX_FILL_2 ( &wqe->ud, 1,
- ud_address_vector.rlid, av->dlid,
+ ud_address_vector.rlid, av->lid,
ud_address_vector.g, av->gid_present );
MLX_FILL_2 ( &wqe->ud, 2,
ud_address_vector.max_stat_rate,
@@ -1015,7 +1061,7 @@ static int arbel_post_send ( struct ib_device *ibdev,
MLX_FILL_1 ( &wqe->ud, 3, ud_address_vector.sl, av->sl );
gid = ( av->gid_present ? &av->gid : &arbel_no_gid );
memcpy ( &wqe->ud.u.dwords[4], gid, sizeof ( *gid ) );
- MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->dest_qp );
+ MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->qpn );
MLX_FILL_1 ( &wqe->ud, 9, q_key, av->qkey );
MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_len ( iobuf ) );
MLX_FILL_1 ( &wqe->data[0], 1, l_key, arbel->reserved_lkey );
@@ -1106,17 +1152,12 @@ static int arbel_post_recv ( struct ib_device *ibdev,
* @v ibdev Infiniband device
* @v cq Completion queue
* @v cqe Hardware completion queue entry
- * @v complete_send Send completion handler
- * @v complete_recv Receive completion handler
* @ret rc Return status code
*/
static int arbel_complete ( struct ib_device *ibdev,
struct ib_completion_queue *cq,
- union arbelprm_completion_entry *cqe,
- ib_completer_t complete_send,
- ib_completer_t complete_recv ) {
+ union arbelprm_completion_entry *cqe ) {
struct arbel *arbel = ib_get_drvdata ( ibdev );
- struct ib_completion completion;
struct ib_work_queue *wq;
struct ib_queue_pair *qp;
struct arbel_queue_pair *arbel_qp;
@@ -1124,16 +1165,17 @@ static int arbel_complete ( struct ib_device *ibdev,
struct arbel_recv_work_queue *arbel_recv_wq;
struct arbelprm_recv_wqe *recv_wqe;
struct io_buffer *iobuf;
- ib_completer_t complete;
+ struct ib_address_vector av;
+ struct ib_global_route_header *grh;
unsigned int opcode;
unsigned long qpn;
int is_send;
unsigned long wqe_adr;
unsigned int wqe_idx;
+ size_t len;
int rc = 0;
/* Parse completion */
- memset ( &completion, 0, sizeof ( completion ) );
qpn = MLX_GET ( &cqe->normal, my_qpn );
is_send = MLX_GET ( &cqe->normal, s );
wqe_adr = ( MLX_GET ( &cqe->normal, wqe_adr ) << 6 );
@@ -1141,9 +1183,8 @@ static int arbel_complete ( struct ib_device *ibdev,
if ( opcode >= ARBEL_OPCODE_RECV_ERROR ) {
/* "s" field is not valid for error opcodes */
is_send = ( opcode == ARBEL_OPCODE_SEND_ERROR );
- completion.syndrome = MLX_GET ( &cqe->error, syndrome );
- DBGC ( arbel, "Arbel %p CPN %lx syndrome %x vendor %lx\n",
- arbel, cq->cqn, completion.syndrome,
+ DBGC ( arbel, "Arbel %p CPN %lx syndrome %x vendor %x\n",
+ arbel, cq->cqn, MLX_GET ( &cqe->error, syndrome ),
MLX_GET ( &cqe->error, vendor_code ) );
rc = -EIO;
/* Don't return immediately; propagate error to completer */
@@ -1181,9 +1222,12 @@ static int arbel_complete ( struct ib_device *ibdev,
}
wq->iobufs[wqe_idx] = NULL;
- /* Fill in length for received packets */
- if ( ! is_send ) {
- completion.len = MLX_GET ( &cqe->normal, byte_cnt );
+ if ( is_send ) {
+ /* Hand off to completion handler */
+ ib_complete_send ( ibdev, qp, iobuf, rc );
+ } else {
+ /* Set received length */
+ len = MLX_GET ( &cqe->normal, byte_cnt );
recv_wqe = &arbel_recv_wq->wqe[wqe_idx].recv;
assert ( MLX_GET ( &recv_wqe->data[0], local_address_l ) ==
virt_to_bus ( iobuf->data ) );
@@ -1192,18 +1236,22 @@ static int arbel_complete ( struct ib_device *ibdev,
MLX_FILL_1 ( &recv_wqe->data[0], 0, byte_count, 0 );
MLX_FILL_1 ( &recv_wqe->data[0], 1,
l_key, ARBEL_INVALID_LKEY );
- if ( completion.len > iob_tailroom ( iobuf ) ) {
- DBGC ( arbel, "Arbel %p CQN %lx QPN %lx IDX %x "
- "overlength received packet length %zd\n",
- arbel, cq->cqn, qpn, wqe_idx, completion.len );
- return -EIO;
- }
+ assert ( len <= iob_tailroom ( iobuf ) );
+ iob_put ( iobuf, len );
+ assert ( iob_len ( iobuf ) >= sizeof ( *grh ) );
+ grh = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *grh ) );
+ /* Construct address vector */
+ memset ( &av, 0, sizeof ( av ) );
+ av.qpn = MLX_GET ( &cqe->normal, rqpn );
+ av.lid = MLX_GET ( &cqe->normal, rlid );
+ av.sl = MLX_GET ( &cqe->normal, sl );
+ av.gid_present = MLX_GET ( &cqe->normal, g );
+ memcpy ( &av.gid, &grh->sgid, sizeof ( av.gid ) );
+ /* Hand off to completion handler */
+ ib_complete_recv ( ibdev, qp, &av, iobuf, rc );
}
- /* Pass off to caller's completion handler */
- complete = ( is_send ? complete_send : complete_recv );
- complete ( ibdev, qp, &completion, iobuf );
-
return rc;
}
@@ -1212,13 +1260,9 @@ static int arbel_complete ( struct ib_device *ibdev,
*
* @v ibdev Infiniband device
* @v cq Completion queue
- * @v complete_send Send completion handler
- * @v complete_recv Receive completion handler
*/
static void arbel_poll_cq ( struct ib_device *ibdev,
- struct ib_completion_queue *cq,
- ib_completer_t complete_send,
- ib_completer_t complete_recv ) {
+ struct ib_completion_queue *cq ) {
struct arbel *arbel = ib_get_drvdata ( ibdev );
struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq );
struct arbelprm_cq_ci_db_record *ci_db_rec;
@@ -1236,8 +1280,7 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
}
/* Handle completion */
- if ( ( rc = arbel_complete ( ibdev, cq, cqe, complete_send,
- complete_recv ) ) != 0 ) {
+ if ( ( rc = arbel_complete ( ibdev, cq, cqe ) ) != 0 ) {
DBGC ( arbel, "Arbel %p failed to complete: %s\n",
arbel, strerror ( rc ) );
DBGC_HD ( arbel, cqe, sizeof ( *cqe ) );
@@ -1397,6 +1440,9 @@ static void arbel_event_port_state_change ( struct arbel *arbel,
return;
}
+ /* Update MAD parameters */
+ ib_smc_update ( arbel->ibdev[port], arbel_mad );
+
/* Notify Infiniband core of link state change */
ib_link_state_changed ( arbel->ibdev[port] );
}
@@ -1447,7 +1493,7 @@ static void arbel_poll_eq ( struct ib_device *ibdev ) {
/* Ring doorbell */
MLX_FILL_1 ( &db_reg.ci, 0, ci, arbel_eq->next_idx );
- DBGCP ( arbel, "Ringing doorbell %08lx with %08lx\n",
+ DBGCP ( arbel, "Ringing doorbell %08lx with %08x\n",
virt_to_phys ( arbel_eq->doorbell ),
db_reg.dword[0] );
writel ( db_reg.dword[0], arbel_eq->doorbell );
@@ -1486,6 +1532,9 @@ static int arbel_open ( struct ib_device *ibdev ) {
return rc;
}
+ /* Update MAD parameters */
+ ib_smc_update ( ibdev, arbel_mad );
+
return 0;
}
@@ -1601,51 +1650,6 @@ static void arbel_mcast_detach ( struct ib_device *ibdev,
}
}
-/***************************************************************************
- *
- * MAD operations
- *
- ***************************************************************************
- */
-
-/**
- * Issue management datagram
- *
- * @v ibdev Infiniband device
- * @v mad Management datagram
- * @v len Length of management datagram
- * @ret rc Return status code
- */
-static int arbel_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad,
- size_t len ) {
- struct arbel *arbel = ib_get_drvdata ( ibdev );
- union arbelprm_mad mad_ifc;
- int rc;
-
- /* Copy in request packet */
- memset ( &mad_ifc, 0, sizeof ( mad_ifc ) );
- assert ( len <= sizeof ( mad_ifc.mad ) );
- memcpy ( &mad_ifc.mad, mad, len );
-
- /* Issue MAD */
- if ( ( rc = arbel_cmd_mad_ifc ( arbel, ibdev->port,
- &mad_ifc ) ) != 0 ) {
- DBGC ( arbel, "Arbel %p could not issue MAD IFC: %s\n",
- arbel, strerror ( rc ) );
- return rc;
- }
-
- /* Copy out reply packet */
- memcpy ( mad, &mad_ifc.mad, len );
-
- if ( mad->status != 0 ) {
- DBGC ( arbel, "Arbel %p MAD IFC status %04x\n",
- arbel, ntohs ( mad->status ) );
- return -EIO;
- }
- return 0;
-}
-
/** Arbel Infiniband operations */
static struct ib_device_operations arbel_ib_operations = {
.create_cq = arbel_create_cq,
@@ -1661,7 +1665,6 @@ static struct ib_device_operations arbel_ib_operations = {
.close = arbel_close,
.mcast_attach = arbel_mcast_attach,
.mcast_detach = arbel_mcast_detach,
- .mad = arbel_mad,
};
/***************************************************************************
@@ -1694,7 +1697,7 @@ static int arbel_start_firmware ( struct arbel *arbel ) {
arbel, strerror ( rc ) );
goto err_query_fw;
}
- DBGC ( arbel, "Arbel %p firmware version %ld.%ld.%ld\n", arbel,
+ DBGC ( arbel, "Arbel %p firmware version %d.%d.%d\n", arbel,
MLX_GET ( &fw, fw_rev_major ), MLX_GET ( &fw, fw_rev_minor ),
MLX_GET ( &fw, fw_rev_subminor ) );
fw_pages = MLX_GET ( &fw, fw_pages );
@@ -2172,6 +2175,10 @@ static int arbel_probe ( struct pci_device *pci,
if ( ( rc = arbel_create_eq ( arbel ) ) != 0 )
goto err_create_eq;
+ /* Update MAD parameters */
+ for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ )
+ ib_smc_update ( arbel->ibdev[i], arbel_mad );
+
/* Register Infiniband devices */
for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) {
if ( ( rc = register_ibdev ( arbel->ibdev[i] ) ) != 0 ) {
diff --git a/gpxe/src/drivers/infiniband/hermon.c b/gpxe/src/drivers/infiniband/hermon.c
index 3ca60033..40add28a 100644
--- a/gpxe/src/drivers/infiniband/hermon.c
+++ b/gpxe/src/drivers/infiniband/hermon.c
@@ -25,12 +25,14 @@
#include <unistd.h>
#include <errno.h>
#include <byteswap.h>
+#include <gpxe/io.h>
#include <gpxe/pci.h>
#include <gpxe/malloc.h>
#include <gpxe/umalloc.h>
#include <gpxe/iobuf.h>
#include <gpxe/netdevice.h>
#include <gpxe/infiniband.h>
+#include <gpxe/ib_smc.h>
#include "hermon.h"
/**
@@ -610,6 +612,50 @@ static void hermon_free_mtt ( struct hermon *hermon,
/***************************************************************************
*
+ * MAD operations
+ *
+ ***************************************************************************
+ */
+
+/**
+ * Issue management datagram
+ *
+ * @v ibdev Infiniband device
+ * @v mad Management datagram
+ * @ret rc Return status code
+ */
+static int hermon_mad ( struct ib_device *ibdev, union ib_mad *mad ) {
+ struct hermon *hermon = ib_get_drvdata ( ibdev );
+ union hermonprm_mad mad_ifc;
+ int rc;
+
+ linker_assert ( sizeof ( *mad ) == sizeof ( mad_ifc.mad ),
+ mad_size_mismatch );
+
+ /* Copy in request packet */
+ memcpy ( &mad_ifc.mad, mad, sizeof ( mad_ifc.mad ) );
+
+ /* Issue MAD */
+ if ( ( rc = hermon_cmd_mad_ifc ( hermon, ibdev->port,
+ &mad_ifc ) ) != 0 ) {
+ DBGC ( hermon, "Hermon %p could not issue MAD IFC: %s\n",
+ hermon, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Copy out reply packet */
+ memcpy ( mad, &mad_ifc.mad, sizeof ( *mad ) );
+
+ if ( mad->hdr.status != 0 ) {
+ DBGC ( hermon, "Hermon %p MAD IFC status %04x\n",
+ hermon, ntohs ( mad->hdr.status ) );
+ return -EIO;
+ }
+ return 0;
+}
+
+/***************************************************************************
+ *
* Completion queue operations
*
***************************************************************************
@@ -1015,7 +1061,7 @@ static int hermon_post_send ( struct ib_device *ibdev,
ud_address_vector.pd, HERMON_GLOBAL_PD,
ud_address_vector.port_number, ibdev->port );
MLX_FILL_2 ( &wqe->ud, 1,
- ud_address_vector.rlid, av->dlid,
+ ud_address_vector.rlid, av->lid,
ud_address_vector.g, av->gid_present );
MLX_FILL_1 ( &wqe->ud, 2,
ud_address_vector.max_stat_rate,
@@ -1024,7 +1070,7 @@ static int hermon_post_send ( struct ib_device *ibdev,
MLX_FILL_1 ( &wqe->ud, 3, ud_address_vector.sl, av->sl );
gid = ( av->gid_present ? &av->gid : &hermon_no_gid );
memcpy ( &wqe->ud.u.dwords[4], gid, sizeof ( *gid ) );
- MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->dest_qp );
+ MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->qpn );
MLX_FILL_1 ( &wqe->ud, 9, q_key, av->qkey );
MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_len ( iobuf ) );
MLX_FILL_1 ( &wqe->data[0], 1, l_key, hermon->reserved_lkey );
@@ -1041,7 +1087,7 @@ static int hermon_post_send ( struct ib_device *ibdev,
/* Ring doorbell register */
MLX_FILL_1 ( &db_reg.send, 0, qn, qp->qpn );
- DBGCP ( hermon, "Ringing doorbell %08lx with %08lx\n",
+ DBGCP ( hermon, "Ringing doorbell %08lx with %08x\n",
virt_to_phys ( hermon_send_wq->doorbell ), db_reg.dword[0] );
writel ( db_reg.dword[0], ( hermon_send_wq->doorbell ) );
@@ -1101,39 +1147,34 @@ static int hermon_post_recv ( struct ib_device *ibdev,
* @v ibdev Infiniband device
* @v cq Completion queue
* @v cqe Hardware completion queue entry
- * @v complete_send Send completion handler
- * @v complete_recv Receive completion handler
* @ret rc Return status code
*/
static int hermon_complete ( struct ib_device *ibdev,
struct ib_completion_queue *cq,
- union hermonprm_completion_entry *cqe,
- ib_completer_t complete_send,
- ib_completer_t complete_recv ) {
+ union hermonprm_completion_entry *cqe ) {
struct hermon *hermon = ib_get_drvdata ( ibdev );
- struct ib_completion completion;
struct ib_work_queue *wq;
struct ib_queue_pair *qp;
struct hermon_queue_pair *hermon_qp;
struct io_buffer *iobuf;
- ib_completer_t complete;
+ struct ib_address_vector av;
+ struct ib_global_route_header *grh;
unsigned int opcode;
unsigned long qpn;
int is_send;
unsigned int wqe_idx;
+ size_t len;
int rc = 0;
/* Parse completion */
- memset ( &completion, 0, sizeof ( completion ) );
qpn = MLX_GET ( &cqe->normal, qpn );
is_send = MLX_GET ( &cqe->normal, s_r );
opcode = MLX_GET ( &cqe->normal, opcode );
if ( opcode >= HERMON_OPCODE_RECV_ERROR ) {
/* "s" field is not valid for error opcodes */
is_send = ( opcode == HERMON_OPCODE_SEND_ERROR );
- completion.syndrome = MLX_GET ( &cqe->error, syndrome );
- DBGC ( hermon, "Hermon %p CQN %lx syndrome %x vendor %lx\n",
- hermon, cq->cqn, completion.syndrome,
+ DBGC ( hermon, "Hermon %p CQN %lx syndrome %x vendor %x\n",
+ hermon, cq->cqn, MLX_GET ( &cqe->error, syndrome ),
MLX_GET ( &cqe->error, vendor_error_syndrome ) );
rc = -EIO;
/* Don't return immediately; propagate error to completer */
@@ -1160,21 +1201,28 @@ static int hermon_complete ( struct ib_device *ibdev,
}
wq->iobufs[wqe_idx] = NULL;
- /* Fill in length for received packets */
- if ( ! is_send ) {
- completion.len = MLX_GET ( &cqe->normal, byte_cnt );
- if ( completion.len > iob_tailroom ( iobuf ) ) {
- DBGC ( hermon, "Hermon %p CQN %lx QPN %lx IDX %x "
- "overlength received packet length %zd\n",
- hermon, cq->cqn, qpn, wqe_idx, completion.len );
- return -EIO;
- }
+ if ( is_send ) {
+ /* Hand off to completion handler */
+ ib_complete_send ( ibdev, qp, iobuf, rc );
+ } else {
+ /* Set received length */
+ len = MLX_GET ( &cqe->normal, byte_cnt );
+ assert ( len <= iob_tailroom ( iobuf ) );
+ iob_put ( iobuf, len );
+ assert ( iob_len ( iobuf ) >= sizeof ( *grh ) );
+ grh = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *grh ) );
+ /* Construct address vector */
+ memset ( &av, 0, sizeof ( av ) );
+ av.qpn = MLX_GET ( &cqe->normal, srq_rqpn );
+ av.lid = MLX_GET ( &cqe->normal, slid_smac47_32 );
+ av.sl = MLX_GET ( &cqe->normal, sl );
+ av.gid_present = MLX_GET ( &cqe->normal, g );
+ memcpy ( &av.gid, &grh->sgid, sizeof ( av.gid ) );
+ /* Hand off to completion handler */
+ ib_complete_recv ( ibdev, qp, &av, iobuf, rc );
}
- /* Pass off to caller's completion handler */
- complete = ( is_send ? complete_send : complete_recv );
- complete ( ibdev, qp, &completion, iobuf );
-
return rc;
}
@@ -1183,13 +1231,9 @@ static int hermon_complete ( struct ib_device *ibdev,
*
* @v ibdev Infiniband device
* @v cq Completion queue
- * @v complete_send Send completion handler
- * @v complete_recv Receive completion handler
*/
static void hermon_poll_cq ( struct ib_device *ibdev,
- struct ib_completion_queue *cq,
- ib_completer_t complete_send,
- ib_completer_t complete_recv ) {
+ struct ib_completion_queue *cq ) {
struct hermon *hermon = ib_get_drvdata ( ibdev );
struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
union hermonprm_completion_entry *cqe;
@@ -1209,8 +1253,7 @@ static void hermon_poll_cq ( struct ib_device *ibdev,
DBGCP_HD ( hermon, cqe, sizeof ( *cqe ) );
/* Handle completion */
- if ( ( rc = hermon_complete ( ibdev, cq, cqe, complete_send,
- complete_recv ) ) != 0 ) {
+ if ( ( rc = hermon_complete ( ibdev, cq, cqe ) ) != 0 ) {
DBGC ( hermon, "Hermon %p failed to complete: %s\n",
hermon, strerror ( rc ) );
DBGC_HD ( hermon, cqe, sizeof ( *cqe ) );
@@ -1380,6 +1423,9 @@ static void hermon_event_port_state_change ( struct hermon *hermon,
return;
}
+ /* Update MAD parameters */
+ ib_smc_update ( hermon->ibdev[port], hermon_mad );
+
/* Notify Infiniband core of link state change */
ib_link_state_changed ( hermon->ibdev[port] );
}
@@ -1428,7 +1474,7 @@ static void hermon_poll_eq ( struct ib_device *ibdev ) {
/* Ring doorbell */
MLX_FILL_1 ( &db_reg.event, 0,
ci, ( hermon_eq->next_idx & 0x00ffffffUL ) );
- DBGCP ( hermon, "Ringing doorbell %08lx with %08lx\n",
+ DBGCP ( hermon, "Ringing doorbell %08lx with %08x\n",
virt_to_phys ( hermon_eq->doorbell ),
db_reg.dword[0] );
writel ( db_reg.dword[0], hermon_eq->doorbell );
@@ -1468,6 +1514,9 @@ static int hermon_open ( struct ib_device *ibdev ) {
return rc;
}
+ /* Update MAD parameters */
+ ib_smc_update ( ibdev, hermon_mad );
+
return 0;
}
@@ -1582,51 +1631,6 @@ static void hermon_mcast_detach ( struct ib_device *ibdev,
}
}
-/***************************************************************************
- *
- * MAD operations
- *
- ***************************************************************************
- */
-
-/**
- * Issue management datagram
- *
- * @v ibdev Infiniband device
- * @v mad Management datagram
- * @v len Length of management datagram
- * @ret rc Return status code
- */
-static int hermon_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad,
- size_t len ) {
- struct hermon *hermon = ib_get_drvdata ( ibdev );
- union hermonprm_mad mad_ifc;
- int rc;
-
- /* Copy in request packet */
- memset ( &mad_ifc, 0, sizeof ( mad_ifc ) );
- assert ( len <= sizeof ( mad_ifc.mad ) );
- memcpy ( &mad_ifc.mad, mad, len );
-
- /* Issue MAD */
- if ( ( rc = hermon_cmd_mad_ifc ( hermon, ibdev->port,
- &mad_ifc ) ) != 0 ) {
- DBGC ( hermon, "Hermon %p could not issue MAD IFC: %s\n",
- hermon, strerror ( rc ) );
- return rc;
- }
-
- /* Copy out reply packet */
- memcpy ( mad, &mad_ifc.mad, len );
-
- if ( mad->status != 0 ) {
- DBGC ( hermon, "Hermon %p MAD IFC status %04x\n",
- hermon, ntohs ( mad->status ) );
- return -EIO;
- }
- return 0;
-}
-
/** Hermon Infiniband operations */
static struct ib_device_operations hermon_ib_operations = {
.create_cq = hermon_create_cq,
@@ -1642,7 +1646,6 @@ static struct ib_device_operations hermon_ib_operations = {
.close = hermon_close,
.mcast_attach = hermon_mcast_attach,
.mcast_detach = hermon_mcast_detach,
- .mad = hermon_mad,
};
/***************************************************************************
@@ -1712,7 +1715,7 @@ static int hermon_start_firmware ( struct hermon *hermon ) {
hermon, strerror ( rc ) );
goto err_query_fw;
}
- DBGC ( hermon, "Hermon %p firmware version %ld.%ld.%ld\n", hermon,
+ DBGC ( hermon, "Hermon %p firmware version %d.%d.%d\n", hermon,
MLX_GET ( &fw, fw_rev_major ), MLX_GET ( &fw, fw_rev_minor ),
MLX_GET ( &fw, fw_rev_subminor ) );
fw_pages = MLX_GET ( &fw, fw_pages );
@@ -2241,6 +2244,10 @@ static int hermon_probe ( struct pci_device *pci,
if ( ( rc = hermon_create_eq ( hermon ) ) != 0 )
goto err_create_eq;
+ /* Update MAD parameters */
+ for ( i = 0 ; i < HERMON_NUM_PORTS ; i++ )
+ ib_smc_update ( hermon->ibdev[i], hermon_mad );
+
/* Register Infiniband devices */
for ( i = 0 ; i < HERMON_NUM_PORTS ; i++ ) {
if ( ( rc = register_ibdev ( hermon->ibdev[i] ) ) != 0 ) {
@@ -2306,6 +2313,7 @@ static struct pci_device_id hermon_nics[] = {
PCI_ROM ( 0x15b3, 0x6340, "mt25408", "MT25408 HCA driver" ),
PCI_ROM ( 0x15b3, 0x634a, "mt25418", "MT25418 HCA driver" ),
PCI_ROM ( 0x15b3, 0x6732, "mt26418", "MT26418 HCA driver" ),
+ PCI_ROM ( 0x15b3, 0x673c, "mt26428", "MT26428 HCA driver" ),
};
struct pci_driver hermon_driver __pci_driver = {
diff --git a/gpxe/src/drivers/infiniband/ib_packet.c b/gpxe/src/drivers/infiniband/ib_packet.c
new file mode 100644
index 00000000..0f21617f
--- /dev/null
+++ b/gpxe/src/drivers/infiniband/ib_packet.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/infiniband.h>
+#include <gpxe/ib_packet.h>
+
+/**
+ * @file
+ *
+ * Infiniband Packet Formats
+ *
+ */
+
+/**
+ * Add IB headers
+ *
+ * @v ibdev Infiniband device
+ * @v iobuf I/O buffer to contain headers
+ * @v qp Queue pair
+ * @v payload_len Payload length
+ * @v av Address vector
+ */
+int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf,
+ struct ib_queue_pair *qp, size_t payload_len,
+ const struct ib_address_vector *av ) {
+ struct ib_local_route_header *lrh;
+ struct ib_global_route_header *grh;
+ struct ib_base_transport_header *bth;
+ struct ib_datagram_extended_transport_header *deth;
+ size_t orig_iob_len = iob_len ( iobuf );
+ size_t pad_len;
+ size_t lrh_len;
+ size_t grh_len;
+ unsigned int vl;
+ unsigned int lnh;
+
+ DBGC2 ( ibdev, "IBDEV %p TX %04x:%08lx => %04x:%08lx (key %08lx)\n",
+ ibdev, ibdev->lid, qp->qpn, av->lid, av->qpn, av->qkey );
+
+ /* Calculate packet length */
+ pad_len = ( (-payload_len) & 0x3 );
+ payload_len += pad_len;
+ payload_len += 4; /* ICRC */
+
+ /* Reserve space for headers */
+ orig_iob_len = iob_len ( iobuf );
+ deth = iob_push ( iobuf, sizeof ( *deth ) );
+ bth = iob_push ( iobuf, sizeof ( *bth ) );
+ grh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len );
+ grh = ( av->gid_present ?
+ iob_push ( iobuf, sizeof ( *grh ) ) : NULL );
+ lrh = iob_push ( iobuf, sizeof ( *lrh ) );
+ lrh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len );
+
+ /* Construct LRH */
+ vl = ( ( av->qpn == IB_QPN_SMP ) ? IB_VL_SMP : IB_VL_DEFAULT );
+ lrh->vl__lver = ( vl << 4 );
+ lnh = ( grh ? IB_LNH_GRH : IB_LNH_BTH );
+ lrh->sl__lnh = ( ( av->sl << 4 ) | lnh );
+ lrh->dlid = htons ( av->lid );
+ lrh->length = htons ( lrh_len >> 2 );
+ lrh->slid = htons ( ibdev->lid );
+
+ /* Construct GRH, if required */
+ if ( grh ) {
+ grh->ipver__tclass__flowlabel =
+ htonl ( IB_GRH_IPVER_IPv6 << 28 );
+ grh->paylen = htons ( grh_len );
+ grh->nxthdr = IB_GRH_NXTHDR_IBA;
+ grh->hoplmt = 0;
+ memcpy ( &grh->sgid, &ibdev->gid, sizeof ( grh->sgid ) );
+ memcpy ( &grh->dgid, &av->gid, sizeof ( grh->dgid ) );
+ }
+
+ /* Construct BTH */
+ bth->opcode = BTH_OPCODE_UD_SEND;
+ bth->se__m__padcnt__tver = ( pad_len << 4 );
+ bth->pkey = htons ( ibdev->pkey );
+ bth->dest_qp = htonl ( av->qpn );
+ bth->ack__psn = htonl ( ( ibdev->psn++ ) & 0xffffffUL );
+
+ /* Construct DETH */
+ deth->qkey = htonl ( av->qkey );
+ deth->src_qp = htonl ( qp->qpn );
+
+ DBGCP_HDA ( ibdev, 0, iobuf->data,
+ ( iob_len ( iobuf ) - orig_iob_len ) );
+
+ return 0;
+}
+
+/**
+ * Remove IB headers
+ *
+ * @v ibdev Infiniband device
+ * @v iobuf I/O buffer containing headers
+ * @v qp Queue pair to fill in, or NULL
+ * @v payload_len Payload length to fill in, or NULL
+ * @v av Address vector to fill in
+ */
+int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf,
+ struct ib_queue_pair **qp, size_t *payload_len,
+ struct ib_address_vector *av ) {
+ struct ib_local_route_header *lrh;
+ struct ib_global_route_header *grh;
+ struct ib_base_transport_header *bth;
+ struct ib_datagram_extended_transport_header *deth;
+ size_t orig_iob_len = iob_len ( iobuf );
+ unsigned int lnh;
+ size_t pad_len;
+ unsigned long qpn;
+ unsigned int lid;
+
+ /* Clear return values */
+ if ( qp )
+ *qp = NULL;
+ if ( payload_len )
+ *payload_len = 0;
+ memset ( av, 0, sizeof ( *av ) );
+
+ /* Extract LRH */
+ if ( iob_len ( iobuf ) < sizeof ( *lrh ) ) {
+ DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for LRH\n",
+ ibdev, iob_len ( iobuf ) );
+ return -EINVAL;
+ }
+ lrh = iobuf->data;